commit 434476f733fa46f58ccb6d5906ca557245479683
parent d949367933abd5db11bee30b14bd8a4b6be4402f
Author: Claudio Alessi <smoppy@gmail.com>
Date: Mon, 14 Mar 2016 20:02:27 +0100
Make modes dynamics.
The first viewmode is now specified in config.h through the welcome pointer.
Diffstat:
M | config.def.h | | | 17 | ++++++----------- |
M | core.c | | | 144 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
A | help.stfl | | | 27 | +++++++++++++++++++++++++++ |
3 files changed, 113 insertions(+), 75 deletions(-)
diff --git a/config.def.h b/config.def.h
@@ -7,13 +7,7 @@ static const char *dbhost = "";
static const char *dbuser = "";
static const char *dbpass = "";
-static Mode modes[] = {
- /* name function */
- { "databases", databases }, /* first entry is default */
- { "tables", tables },
- { "records", records },
- { "text", text },
-};
+static void (*welcome)(const Arg *arg) = databases;
static Key keys[] = {
/* mode modkey function argument */
@@ -23,11 +17,12 @@ static Key keys[] = {
{ NULL, L"j", itempos, {.i = +1} },
{ NULL, L"I", reload, {0} },
{ NULL, L"$", apply, {.i = 1} },
+ { NULL, L"?", help, {0} },
{ "databases", L"q", quit, {.i = 0} },
- { "databases", L"ENTER", usedb, {.v = &modes[1]} },
- { "databases", L"SPACE", usedb, {.v = &modes[1]} },
- { "tables", L"ENTER", setmode, {.v = &modes[2]} },
- { "tables", L"SPACE", setmode, {.v = &modes[2]} },
+ { "databases", L"ENTER", tables, {0} },
+ { "databases", L"SPACE", tables, {0} },
+ { "tables", L"ENTER", records, {0} },
+ { "tables", L"SPACE", records, {0} },
{ "records", L"d", flagas, {.v = "D"} },
{ "records", L"t", flagas, {.v = "*"} },
};
diff --git a/core.c b/core.c
@@ -57,8 +57,8 @@ typedef struct {
} Key;
typedef struct {
- const char *name;
- void (*func)(void);
+ char *name;
+ void (*func)(const Arg *arg);
} Mode;
typedef struct View View;
@@ -84,7 +84,7 @@ void cleanupfields(Field **fields);
void cleanupitems(Item **items);
void cleanupview(View *v);
Item *cloneitem(Item *item);
-void databases(void);
+void databases(const Arg *arg);
void detach(View *v);
void detachfieldfrom(Field *f, Field **ff);
void detachitemfrom(Item *i, Item **ii);
@@ -93,26 +93,26 @@ void *ecalloc(size_t nmemb, size_t size);
void flagas(const Arg *arg);
Item *getitem(void);
int *getmaxlengths(View *view);
+void help(const Arg *arg);
void itempos(const Arg *arg);
MYSQL_RES *mysql_exec(const char *sqlstr, ...);
int mysql_fields(MYSQL_RES *res, Field **fields);
int mysql_items(MYSQL_RES *res, Item **items);
void mysql_listview(MYSQL_RES *res, int showfds);
+View *newaview(const char *name, void (*func)(const Arg *arg));
void stfl_showfields(Field *fds, int *lens);
void stfl_showitems(Item *items, int *lens);
void quit(const Arg *arg);
-void records(void);
+void records(const Arg *arg);
void reload(const Arg *arg);
void run(void);
-void setmode(const Arg *arg);
void setup(void);
void sigint_handler(int sig);
void stfl_setf(const char *name, const char *fmtstr, ...);
void stfl_putitem(Item *item, int *lens);
int stripesc(char *src, char *dst, int len);
-void tables(void);
-void text(void);
-void usedb(const Arg *arg);
+void tables(const Arg *arg);
+void text(const Arg *arg);
void viewprev(const Arg *arg);
#include "config.h"
@@ -120,7 +120,7 @@ void viewprev(const Arg *arg);
/* variables */
static int running = 1;
static MYSQL *mysql;
-static View *views, *selview;
+static View *views, *selview = NULL;
static struct stfl_ipool *ipool;
static int fldseplen;
@@ -256,11 +256,14 @@ cloneitem(Item *item) {
}
void
-databases(void) {
+databases(const Arg *arg) {
MYSQL_RES *res;
+ int refresh = (selview && !strcmp(selview->mode->name, "databases"));
if(!(res = mysql_exec("show databases")))
- die("databases");
+ die("databases\n");
+ if(!refresh)
+ selview = newaview("databases", databases);
mysql_listview(res, 0);
mysql_free_result(res);
stfl_setf("title", "Databases in `%s`", dbhost);
@@ -316,12 +319,13 @@ flagas(const Arg *arg) {
Item *
getitem(void) {
+ const char *spos = stfl_ipool_fromwc(ipool, stfl_get(selview->form, L"pos"));
Item *item;
int pos, n;
- if(!selview)
+ if(!(selview && spos))
return NULL;
- pos = atoi(stfl_ipool_fromwc(ipool, stfl_get(selview->form, L"pos")));
+ pos = atoi(spos);
for(item = selview->items, n = 0; item; item = item->next, ++n)
if(n == pos)
@@ -353,6 +357,18 @@ getmaxlengths(View *view) {
}
void
+help(const Arg *arg) {
+ int refresh = (selview && !strcmp(selview->mode->name, "help"));
+
+ if(!refresh) {
+ selview = newaview("help", help);
+ selview->form = stfl_create(L"<help.stfl>");
+ }
+ else
+ stfl_setf("status", "Text updated.");
+}
+
+void
itempos(const Arg *arg) {
const char *spos = stfl_ipool_fromwc(ipool, stfl_get(selview->form, L"pos"));
char tmp[8];
@@ -440,13 +456,15 @@ void
mysql_listview(MYSQL_RES *res, int showfds) {
int *lens;
+ cleanupitems(&selview->items);
+ selview->nitems = mysql_items(res, &selview->items);
+
if(!selview->form) {
selview->form = stfl_create(L"<items.stfl>");
- stfl_run(selview->form, -1); /* init ncurses */
+ stfl_run(selview->form, -1); /* refresh ncurses */
curs_set(0);
}
- cleanupitems(&selview->items);
- selview->nitems = mysql_items(res, &selview->items);
+
if(showfds) {
cleanupfields(&selview->fields);
selview->nfields = mysql_fields(res, &selview->fields);
@@ -461,6 +479,19 @@ mysql_listview(MYSQL_RES *res, int showfds) {
free(lens);
}
+View *
+newaview(const char *name, void (*func)(const Arg *arg)) {
+ View *v;
+
+ v = ecalloc(1, sizeof(View));
+ v->mode = ecalloc(1, sizeof(Mode));
+ v->mode->name = ecalloc(strlen(name)+1, sizeof(char));
+ strcpy(v->mode->name, name);
+ v->mode->func = func;
+ attach(v);
+ return v;
+}
+
void
stfl_showfields(Field *fds, int *lens) {
Field *fld;
@@ -519,17 +550,23 @@ quit(const Arg *arg) {
}
void
-records(void) {
+records(const Arg *arg) {
+ int refresh = (selview && !strcmp(selview->mode->name, "records"));
+ Item *choice = (refresh ? selview->choice : cloneitem(getitem()));
MYSQL_RES *res;
char *tbl;
- tbl = calloc(selview->choice->lens[0] + 1, sizeof(char));
- memcpy(tbl, selview->choice->cols[0], selview->choice->lens[0]);
-
- if(!(selview->choice && selview->choice->ncols))
+ choice = (refresh ? selview->choice : cloneitem(getitem()));
+ if(!choice->ncols)
die("records: no choice.\n");
+ tbl = calloc(choice->lens[0] + 1, sizeof(char));
+ memcpy(tbl, choice->cols[0], choice->lens[0]);
if(!(res = mysql_exec("select * from `%s`", tbl)))
die("records: cannot select `%s`\n", tbl);
+ if(!refresh) {
+ selview = newaview("records", records);
+ selview->choice = choice;
+ }
mysql_listview(res, 1);
mysql_free_result(res);
stfl_setf("title", "Records in `%s`", tbl);
@@ -540,8 +577,11 @@ records(void) {
void
reload(const Arg *arg) {
const wchar_t *pos = stfl_get(selview->form, L"pos");
- selview->mode->func();
- stfl_set(selview->form, L"pos", pos);
+ if(!selview->mode->func)
+ return;
+ selview->mode->func(NULL);
+ if(pos)
+ stfl_set(selview->form, L"pos", pos);
}
void
@@ -565,31 +605,6 @@ run(void) {
}
void
-setmode(const Arg *arg) {
- const Mode *m = (arg ? arg->v : &modes[0]);
- View *v;
- unsigned int i;
-
- if(selview && selview->mode && !strcmp(selview->mode->name, m->name))
- return;
- for(v = views; v; v = v->next)
- if(!strcmp(v->mode->name, m->name))
- break;
- if(!v) {
- v = ecalloc(1, sizeof(View));
- for(i = 0; i < LENGTH(modes); ++i)
- if(!strcmp(modes[i].name, m->name))
- v->mode = &modes[i];
- attach(v);
- }
- if(v->choice)
- free(v->choice);
- v->choice = cloneitem(getitem());
- selview = v;
- selview->mode->func();
-}
-
-void
setup(void) {
struct sigaction sa;
@@ -599,7 +614,7 @@ setup(void) {
fldseplen = strlen(FLDSEP);
ipool = stfl_ipool_create(nl_langinfo(CODESET));
- setmode(NULL);
+ welcome(NULL);
stfl_setf("status", "Welcome to %s-%s", __FILE__, VERSION);
sa.sa_flags = 0;
@@ -675,31 +690,32 @@ stripesc(char *dst, char *src, int len) {
}
void
-tables(void) {
+usage(void) {
+ die("Usage: %s [-vhup <arg>]\n", argv0);
+}
+
+void
+tables(const Arg *arg) {
+ int refresh = (selview && !strcmp(selview->mode->name, "tables"));
+ Item *choice = (refresh ? selview->choice : cloneitem(getitem()));
MYSQL_RES *res;
+ if(!refresh) {
+ selview = newaview("tables", tables);
+ selview->choice = choice;
+ mysql_select_db(mysql, choice->cols[0]);
+ }
if(!(res = mysql_exec("show tables")))
die("tables\n");
mysql_listview(res, 0);
mysql_free_result(res);
- stfl_setf("title", "Tables in `%s`", selview->choice->cols[0]);
+ stfl_setf("title", "Tables in `%s`", choice->cols[0]);
stfl_setf("info", "%d table(s)", selview->nitems);
}
void
-text(void) {
-}
-
-void
-usage(void) {
- die("Usage: %s [-vhup <arg>]\n", argv0);
-}
-
-void
-usedb(const Arg *arg) {
- Item *item = getitem();
- mysql_select_db(mysql, item->cols[0]);
- setmode(arg);
+text(const Arg *arg) {
+ stfl_setf("status", "I don't know how to refresh the content.");
}
void
diff --git a/help.stfl b/help.stfl
@@ -0,0 +1,27 @@
+* See LICENSE file for copyright and license details.
+
+vbox[main]
+ @bind_up: @bind_down: @bind_left: @bind_right:
+ @bind_page_up: @bind_page_down: @bind_home: @bind_end:
+ @bind_delete: @bind_backspace: @bind_enter:
+
+ label
+ @style_normal:fg=black,bg=white
+ text[title]:"The mutt of MySQL - Work in progress..."
+ .expand:0
+ label
+ @style_normal:fg=blue,bg=black,attr=bold
+ text[subtle]:""
+ .display[showsubtle]:0
+ .expand:0
+ textview
+ @style_normal:fg=white,bg=black
+ listitem
+ text:"Hello!"
+ label
+ @style_normal:fg=black,bg=white
+ .expand:0
+ text[info]:""
+ label
+ .expand:0
+ text[status]:""