Prepare for handling descriptions

This commit is contained in:
Nils O. Selåsdal
2015-12-12 20:42:18 +01:00
parent e902b04996
commit f107898919
+44 -30
View File
@@ -24,7 +24,7 @@ enum UCCmdRc {
}; };
struct UCCmdArgs; struct UCCmdArgs;
typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCCmdArgs *args); typedef enum UCCmdRc (*UCCmdHandler)(const struct UCCmdArgs *args);
enum UCCmdType { enum UCCmdType {
UC_CMD_ROOT = 1, UC_CMD_ROOT = 1,
@@ -34,6 +34,15 @@ enum UCCmdType {
UC_CMD_END, UC_CMD_END,
}; };
struct UCCmdWord {
char *word;
char *descr;
};
struct UCCmdList {
struct UCStrv words;
struct UCStrv descrs;
};
/** /**
* Command are broken into words and inserted into a tree. * Command are broken into words and inserted into a tree.
@@ -56,18 +65,16 @@ enum UCCmdType {
*/ */
struct UCCmdNode { struct UCCmdNode {
enum UCCmdType type; enum UCCmdType type;
union {
struct UCCmdWord word;
struct UCCmdList list;
struct UCCmdDef *cmd;
} data;
uint32_t flags; uint32_t flags;
void *data;
struct UCCmdNode *next; //next at same level struct UCCmdNode *next; //next at same level
struct UCCmdNode *child; struct UCCmdNode *child;
}; };
//for UC_CMD_LIST,
struct UCCmdList {
char *word;
struct UCCmdList *next;
};
struct UCCmdRunner { struct UCCmdRunner {
struct UCCmdNode *root_node; struct UCCmdNode *root_node;
struct UCCmdNode _root; struct UCCmdNode _root;
@@ -75,10 +82,9 @@ struct UCCmdRunner {
struct UCCmdDef { struct UCCmdDef {
const char *cmd; const char *cmd;
uc_cmd_handler callback; const char *help;
UCCmdHandler callback;
uint32_t flags; uint32_t flags;
struct UCCmdDef *next;
}; };
@@ -149,12 +155,14 @@ uc_cmd_node_dealloc(struct UCCmdNode *n)
uc_cmd_node_dealloc(n->child); uc_cmd_node_dealloc(n->child);
next = n->next; next = n->next;
if (n->type == UC_CMD_KEYWORD) { if (n->type == UC_CMD_KEYWORD) {
free(n->data); free(n->data.word.word);
free(n->data.word.descr);
} else if (n->type == UC_CMD_LIST) { } else if (n->type == UC_CMD_LIST) {
uc_strv_destroy(n->data); uc_strv_destroy(&n->data.list.words);
free(n->data); uc_strv_destroy(&n->data.list.descrs);
} else if (n->type == UC_CMD_STRING) { } else if (n->type == UC_CMD_STRING) {
free(n->data); free(n->data.word.word);
free(n->data.word.descr);
} }
free(n); free(n);
n = next; n = next;
@@ -169,7 +177,7 @@ uc_cmd_runner_destroy(struct UCCmdRunner *r)
} }
static struct UCCmdNode * static struct UCCmdNode *
uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) uc_cmd_node_alloc(enum UCCmdType type, uint32_t flags)
{ {
struct UCCmdNode *n; struct UCCmdNode *n;
@@ -179,7 +187,6 @@ uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags)
} }
n->type = type; n->type = type;
n->data = data;
n->flags = flags; n->flags = flags;
return n; return n;
@@ -195,21 +202,23 @@ uc_cmd_node_create(const char *word)
uc_cmd_tokenize(&t, word, "() |\t\v"); uc_cmd_tokenize(&t, word, "() |\t\v");
if (t.num_words > 0) { if (t.num_words > 0) {
struct UCStrv *v = malloc(sizeof *v); node = uc_cmd_node_alloc(UC_CMD_LIST, 0);
uc_strv_init(v); uc_strv_init(&node->data.list.words);
uc_strv_init(&node->data.list.descrs);
for (int i = 0 ; i < t.num_words; i++) { for (int i = 0 ; i < t.num_words; i++) {
uc_strv_append(v, t.cmd_words[i]); uc_strv_append(&node->data.list.words, t.cmd_words[i]);
} }
node = uc_cmd_node_alloc(UC_CMD_LIST, v, 0);
} }
uc_cmd_tokenize_destroy(&t); uc_cmd_tokenize_destroy(&t);
} else if (isupper(word[0])) { } else if (isupper(word[0])) {
node = uc_cmd_node_alloc(UC_CMD_STRING, strdup(word), 0); node = uc_cmd_node_alloc(UC_CMD_STRING, 0);
node->data.word.word = strdup(word);
} else { } else {
node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); node = uc_cmd_node_alloc(UC_CMD_KEYWORD, 0);
node->data.word.word = strdup(word);
} }
return node; return node;
@@ -229,14 +238,14 @@ uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *ar
if (n->type == UC_CMD_KEYWORD) { if (n->type == UC_CMD_KEYWORD) {
if (strncmp(word, n->data, word_len) == 0) { if (strncmp(word, n->data.word.word, word_len) == 0) {
if (args != NULL) { if (args != NULL) {
uc_strv_append(args, n->data); uc_strv_append(args, n->data.word.word);
} }
found = 1; found = 1;
} }
} else if (n->type == UC_CMD_LIST) { } else if (n->type == UC_CMD_LIST) {
struct UCStrv *v = n->data; const struct UCStrv *v = &n->data.list.words;
assert(v); assert(v);
@@ -318,11 +327,12 @@ uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd)
//TODO, check for duplicate command here. //TODO, check for duplicate command here.
new_node = uc_cmd_node_alloc(UC_CMD_END, cmd, 0); new_node = uc_cmd_node_alloc(UC_CMD_END, 0);
if (new_node == NULL) { if (new_node == NULL) {
uc_cmd_tokenize_destroy(&t); uc_cmd_tokenize_destroy(&t);
return -1; return -1;
} }
new_node->data.cmd = cmd;
new_node->next = node->child; new_node->next = node->child;
node->child = new_node; node->child = new_node;
@@ -428,10 +438,10 @@ uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line)
if (node->type == UC_CMD_END) { if (node->type == UC_CMD_END) {
uc_strv_append(&completions, "<CR>"); uc_strv_append(&completions, "<CR>");
} else if (node->type == UC_CMD_LIST) { } else if (node->type == UC_CMD_LIST) {
uc_strv_append_all(&completions, node->data, 1); uc_strv_append_all(&completions, &node->data.list.words, 1);
} else if (node->type == UC_CMD_STRING || } else if (node->type == UC_CMD_STRING ||
node->type == UC_CMD_KEYWORD) { node->type == UC_CMD_KEYWORD) {
uc_strv_append(&completions, node->data); uc_strv_append(&completions, node->data.word.word);
} }
node = node->next; node = node->next;
} }
@@ -472,7 +482,7 @@ uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line)
} }
if (found != NULL) { if (found != NULL) {
struct UCCmdDef *cmd = found->data; struct UCCmdDef *cmd = found->data.cmd;
args.cmd = cmd; args.cmd = cmd;
rc = cmd->callback(&args); rc = cmd->callback(&args);
} else { } else {
@@ -536,6 +546,7 @@ int main(int argc, char *argv[])
struct UCCmdRunner r; struct UCCmdRunner r;
struct UCCmdDef cmd1 = { struct UCCmdDef cmd1 = {
"show all", "show all",
"\n\n",
cmd1_cb, cmd1_cb,
0, 0,
NULL NULL
@@ -543,6 +554,7 @@ int main(int argc, char *argv[])
struct UCCmdDef cmd2 = { struct UCCmdDef cmd2 = {
"show empty", "show empty",
"\n\n",
cmd2_cb, cmd2_cb,
0, 0,
NULL NULL
@@ -550,6 +562,7 @@ int main(int argc, char *argv[])
struct UCCmdDef cmd3 = { struct UCCmdDef cmd3 = {
"show empty bottle", "show empty bottle",
"\n\n\n",
cmd3_cb, cmd3_cb,
0, 0,
NULL NULL
@@ -557,6 +570,7 @@ int main(int argc, char *argv[])
struct UCCmdDef cmd4 = { struct UCCmdDef cmd4 = {
"delete file NAME", "delete file NAME",
"\n\nName of the file\n",
cmd4_cb, cmd4_cb,
0, 0,
NULL NULL