diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index dfd75b8..2bed370 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -24,7 +24,7 @@ enum UCCmdRc { }; struct UCCmdArgs; -typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCCmdArgs *args); +typedef enum UCCmdRc (*UCCmdHandler)(const struct UCCmdArgs *args); enum UCCmdType { UC_CMD_ROOT = 1, @@ -34,6 +34,15 @@ enum UCCmdType { 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. @@ -56,18 +65,16 @@ enum UCCmdType { */ struct UCCmdNode { enum UCCmdType type; + union { + struct UCCmdWord word; + struct UCCmdList list; + struct UCCmdDef *cmd; + } data; uint32_t flags; - void *data; struct UCCmdNode *next; //next at same level struct UCCmdNode *child; }; -//for UC_CMD_LIST, -struct UCCmdList { - char *word; - struct UCCmdList *next; -}; - struct UCCmdRunner { struct UCCmdNode *root_node; struct UCCmdNode _root; @@ -75,10 +82,9 @@ struct UCCmdRunner { struct UCCmdDef { const char *cmd; - uc_cmd_handler callback; + const char *help; + UCCmdHandler callback; uint32_t flags; - - struct UCCmdDef *next; }; @@ -149,12 +155,14 @@ uc_cmd_node_dealloc(struct UCCmdNode *n) uc_cmd_node_dealloc(n->child); next = n->next; 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) { - uc_strv_destroy(n->data); - free(n->data); + uc_strv_destroy(&n->data.list.words); + uc_strv_destroy(&n->data.list.descrs); } else if (n->type == UC_CMD_STRING) { - free(n->data); + free(n->data.word.word); + free(n->data.word.descr); } free(n); n = next; @@ -169,7 +177,7 @@ uc_cmd_runner_destroy(struct UCCmdRunner *r) } 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; @@ -179,7 +187,6 @@ uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) } n->type = type; - n->data = data; n->flags = flags; return n; @@ -195,21 +202,23 @@ uc_cmd_node_create(const char *word) uc_cmd_tokenize(&t, word, "() |\t\v"); 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++) { - 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); } 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 { - 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; @@ -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 (strncmp(word, n->data, word_len) == 0) { + if (strncmp(word, n->data.word.word, word_len) == 0) { if (args != NULL) { - uc_strv_append(args, n->data); + uc_strv_append(args, n->data.word.word); } found = 1; } } else if (n->type == UC_CMD_LIST) { - struct UCStrv *v = n->data; + const struct UCStrv *v = &n->data.list.words; assert(v); @@ -318,11 +327,12 @@ uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) //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) { uc_cmd_tokenize_destroy(&t); return -1; } + new_node->data.cmd = cmd; new_node->next = node->child; node->child = new_node; @@ -345,9 +355,9 @@ uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) enum UCCmdRc uc_cmd_find(struct UCCmdNode *first, - const struct UCCmdTokenizer *t, - struct UCStrv *args, - struct UCCmdNode **result) + const struct UCCmdTokenizer *t, + struct UCStrv *args, + struct UCCmdNode **result) { struct UCCmdNode *node = first; enum UCCmdRc rc = UC_CMDRC_NOT_FOUND; @@ -428,10 +438,10 @@ uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line) if (node->type == UC_CMD_END) { uc_strv_append(&completions, ""); } 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 || node->type == UC_CMD_KEYWORD) { - uc_strv_append(&completions, node->data); + uc_strv_append(&completions, node->data.word.word); } node = node->next; } @@ -472,7 +482,7 @@ uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) } if (found != NULL) { - struct UCCmdDef *cmd = found->data; + struct UCCmdDef *cmd = found->data.cmd; args.cmd = cmd; rc = cmd->callback(&args); } else { @@ -536,6 +546,7 @@ int main(int argc, char *argv[]) struct UCCmdRunner r; struct UCCmdDef cmd1 = { "show all", + "\n\n", cmd1_cb, 0, NULL @@ -543,6 +554,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd2 = { "show empty", + "\n\n", cmd2_cb, 0, NULL @@ -550,6 +562,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd3 = { "show empty bottle", + "\n\n\n", cmd3_cb, 0, NULL @@ -557,6 +570,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd4 = { "delete file NAME", + "\n\nName of the file\n", cmd4_cb, 0, NULL