Implement completion
This commit is contained in:
+215
-73
@@ -7,24 +7,24 @@
|
|||||||
#include "ucore/string.h"
|
#include "ucore/string.h"
|
||||||
#include "ucore/strvec.h"
|
#include "ucore/strvec.h"
|
||||||
#include "ucore/utils.h"
|
#include "ucore/utils.h"
|
||||||
|
#include "ucore/backtrace.h"
|
||||||
//max words in a single command
|
//
|
||||||
#define UC_CMD_MAX_WORDS 32
|
|
||||||
|
|
||||||
enum UCCmdRc {
|
enum UCCmdRc {
|
||||||
/**Executed ok */
|
|
||||||
UC_CMDRC_OK,
|
UC_CMDRC_OK,
|
||||||
/**Executed with warning */
|
/**Executed with warning */
|
||||||
UC_CMDRC_WARNING,
|
UC_CMDRC_WARNING,
|
||||||
/*Not executed, incomplete command */
|
/*incomplete command */
|
||||||
UC_CMDRC_INCOMPLETE,
|
UC_CMDRC_INCOMPLETE,
|
||||||
/*Command cann't uniquely be distinguished */
|
/*Command cann't uniquely be distinguished */
|
||||||
UC_CMDRC_AMBIGUOUS,
|
UC_CMDRC_AMBIGUOUS,
|
||||||
|
/* Command doesn't exist*/
|
||||||
|
UC_CMDRC_NOT_FOUND,
|
||||||
/*Not executed, generic error */
|
/*Not executed, generic error */
|
||||||
UC_CMDRC_ERROR,
|
UC_CMDRC_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCStrv *args);
|
struct UCCmdArgs;
|
||||||
|
typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCCmdArgs *args);
|
||||||
|
|
||||||
enum UCCmdType {
|
enum UCCmdType {
|
||||||
UC_CMD_ROOT = 1,
|
UC_CMD_ROOT = 1,
|
||||||
@@ -34,6 +34,26 @@ enum UCCmdType {
|
|||||||
UC_CMD_END,
|
UC_CMD_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command are broken into words and inserted into a tree.
|
||||||
|
* the 3 commands:
|
||||||
|
* show all
|
||||||
|
* date
|
||||||
|
* show all bottles
|
||||||
|
* Results in the tree:
|
||||||
|
*
|
||||||
|
* +--------+ child +--------+ child +-------+ child +-----+
|
||||||
|
* | root |------->| show |------->| all |------>| END |
|
||||||
|
* +--------+ +--------+ +-------+ +-----+
|
||||||
|
* | next | next
|
||||||
|
* V V
|
||||||
|
* +--------+ child +-----+ +--------+ child +-----+
|
||||||
|
* | date |-----> | END | | bottles|------>| END |
|
||||||
|
* +--------+ +-----+ +--------+ +-----+
|
||||||
|
*
|
||||||
|
* END nodes are complete commands. Other child/next pointers will be nULL
|
||||||
|
*/
|
||||||
struct UCCmdNode {
|
struct UCCmdNode {
|
||||||
enum UCCmdType type;
|
enum UCCmdType type;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@@ -62,12 +82,27 @@ struct UCCmdDef {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//max words in a single command
|
||||||
|
#define UC_CMD_MAX_WORDS 32
|
||||||
|
|
||||||
struct UCCmdTokenizer {
|
struct UCCmdTokenizer {
|
||||||
char *cmd_copy;
|
char *cmd_copy;
|
||||||
char *cmd_words[UC_CMD_MAX_WORDS];
|
char *cmd_words[UC_CMD_MAX_WORDS];
|
||||||
int num_words;
|
int num_words;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UCCmdArgs {
|
||||||
|
struct UCStrv argv;
|
||||||
|
struct UCCmdDef *cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
void print_args(const struct UCStrv *args);
|
||||||
|
static int uc_cmd_type_is_variable(enum UCCmdType type)
|
||||||
|
{
|
||||||
|
return type == UC_CMD_LIST ||
|
||||||
|
type == UC_CMD_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim)
|
static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -89,21 +124,25 @@ static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const cha
|
|||||||
delim);
|
delim);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t)
|
static void
|
||||||
|
uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t)
|
||||||
|
|
||||||
{
|
{
|
||||||
free(t->cmd_copy);
|
free(t->cmd_copy);
|
||||||
t->num_words = 0;
|
t->num_words = 0;
|
||||||
t->cmd_copy = NULL;
|
t->cmd_copy = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uc_cmd_runner_init(struct UCCmdRunner *r)
|
void
|
||||||
|
uc_cmd_runner_init(struct UCCmdRunner *r)
|
||||||
{
|
{
|
||||||
memset(r, 0, sizeof *r);
|
memset(r, 0, sizeof *r);
|
||||||
r->root_node = &r->_root;
|
r->root_node = &r->_root;
|
||||||
r->_root.type = UC_CMD_KEYWORD;
|
r->_root.type = UC_CMD_KEYWORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uc_cmd_node_dealloc(struct UCCmdNode *n)
|
void
|
||||||
|
uc_cmd_node_dealloc(struct UCCmdNode *n)
|
||||||
{
|
{
|
||||||
struct UCCmdNode *next;
|
struct UCCmdNode *next;
|
||||||
while (n) {
|
while (n) {
|
||||||
@@ -122,15 +161,15 @@ void uc_cmd_node_dealloc(struct UCCmdNode *n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uc_cmd_runner_destroy(struct UCCmdRunner *r)
|
void
|
||||||
|
uc_cmd_runner_destroy(struct UCCmdRunner *r)
|
||||||
{
|
{
|
||||||
uc_cmd_node_dealloc(r->root_node->child);
|
uc_cmd_node_dealloc(r->root_node->child);
|
||||||
r->root_node->child = NULL;
|
r->root_node->child = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct UCCmdNode *
|
||||||
|
uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags)
|
||||||
struct UCCmdNode *uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags)
|
|
||||||
{
|
{
|
||||||
struct UCCmdNode *n;
|
struct UCCmdNode *n;
|
||||||
|
|
||||||
@@ -146,7 +185,8 @@ struct UCCmdNode *uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t fl
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UCCmdNode *uc_cmd_node_create(const char *word)
|
static struct UCCmdNode *
|
||||||
|
uc_cmd_node_create(const char *word)
|
||||||
{
|
{
|
||||||
struct UCCmdNode *node = NULL;
|
struct UCCmdNode *node = NULL;
|
||||||
|
|
||||||
@@ -172,14 +212,14 @@ struct UCCmdNode *uc_cmd_node_create(const char *word)
|
|||||||
node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0);
|
node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *args)
|
static int
|
||||||
|
uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *args)
|
||||||
{
|
{
|
||||||
size_t word_len;
|
size_t word_len;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
if (word == NULL || word[0] == 0) {
|
if (word == NULL || word[0] == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -190,7 +230,10 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct
|
|||||||
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_len) == 0) {
|
||||||
return 1;
|
if (args != NULL) {
|
||||||
|
uc_strv_append(args, n->data);
|
||||||
|
}
|
||||||
|
found = 1;
|
||||||
}
|
}
|
||||||
} else if (n->type == UC_CMD_LIST) {
|
} else if (n->type == UC_CMD_LIST) {
|
||||||
struct UCStrv *v = n->data;
|
struct UCStrv *v = n->data;
|
||||||
@@ -203,21 +246,22 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct
|
|||||||
if (args != NULL) {
|
if (args != NULL) {
|
||||||
uc_strv_append(args, v->strings[i]);
|
uc_strv_append(args, v->strings[i]);
|
||||||
}
|
}
|
||||||
return 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (n->type == UC_CMD_STRING) {
|
} else if (n->type == UC_CMD_STRING) {
|
||||||
if (args != NULL) {
|
if (args != NULL) {
|
||||||
uc_strv_append(args, word);
|
uc_strv_append(args, word);
|
||||||
}
|
}
|
||||||
return 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return found;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word)
|
static struct UCCmdNode *
|
||||||
|
uc_cmd_add(struct UCCmdNode *parent, const char *word)
|
||||||
{
|
{
|
||||||
struct UCCmdNode *new_node;
|
struct UCCmdNode *new_node;
|
||||||
struct UCCmdNode **iter = &parent->child;
|
struct UCCmdNode **iter = &parent->child;
|
||||||
@@ -229,11 +273,10 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while (*iter) {
|
while (*iter) {
|
||||||
struct UCCmdNode *n = *iter;
|
struct UCCmdNode *n = *iter;
|
||||||
|
|
||||||
if (new_node->type != UC_CMD_KEYWORD && n->type != UC_CMD_END) {
|
if (uc_cmd_type_is_variable(new_node->type) && n->type != UC_CMD_END) {
|
||||||
//we don't support combinations of keywords and variables
|
//we don't support combinations of keywords and variables
|
||||||
//at the same level.
|
//at the same level.
|
||||||
uc_cmd_node_dealloc(new_node);
|
uc_cmd_node_dealloc(new_node);
|
||||||
@@ -252,7 +295,8 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word)
|
|||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd)
|
int
|
||||||
|
uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd)
|
||||||
{
|
{
|
||||||
struct UCCmdNode *node = r->root_node;
|
struct UCCmdNode *node = r->root_node;
|
||||||
struct UCCmdNode *new_node;
|
struct UCCmdNode *new_node;
|
||||||
@@ -267,6 +311,7 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd)
|
|||||||
for (int i = 0; i < t.num_words; i++) {
|
for (int i = 0; i < t.num_words; i++) {
|
||||||
node = uc_cmd_add(node, t.cmd_words[i]);
|
node = uc_cmd_add(node, t.cmd_words[i]);
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
|
uc_cmd_tokenize_destroy(&t);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +320,7 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd)
|
|||||||
|
|
||||||
new_node = uc_cmd_node_alloc(UC_CMD_END, cmd, 0);
|
new_node = uc_cmd_node_alloc(UC_CMD_END, cmd, 0);
|
||||||
if (new_node == NULL) {
|
if (new_node == NULL) {
|
||||||
|
uc_cmd_tokenize_destroy(&t);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
new_node->next = node->child;
|
new_node->next = node->child;
|
||||||
@@ -286,33 +332,36 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line)
|
uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = uc_cmd_install_noassert(r, cmd);
|
||||||
|
UC_ASSERT(rc == 0);
|
||||||
|
|
||||||
struct UCCmdNode *node = r->root_node->child;
|
return rc;
|
||||||
struct UCCmdTokenizer t;
|
}
|
||||||
enum UCCmdRc rc = UC_CMDRC_ERROR;
|
|
||||||
struct UCStrv args = UC_STRV_INITIALIZER; //arguments to the callback function
|
|
||||||
|
|
||||||
|
enum UCCmdRc
|
||||||
|
uc_cmd_find(struct UCCmdNode *first,
|
||||||
|
const struct UCCmdTokenizer *t,
|
||||||
|
struct UCStrv *args,
|
||||||
|
struct UCCmdNode **result)
|
||||||
|
{
|
||||||
|
struct UCCmdNode *node = first;
|
||||||
|
enum UCCmdRc rc = UC_CMDRC_NOT_FOUND;
|
||||||
|
|
||||||
|
for (int i = 0; i < t->num_words && node; i++) {
|
||||||
//make a copy since getfields destroys the original string
|
|
||||||
uc_cmd_tokenize(&t, cmd_line, NULL);
|
|
||||||
if (t.num_words <= 0) {
|
|
||||||
uc_cmd_tokenize_destroy(&t);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
//match the commands towards the command tree
|
|
||||||
//
|
|
||||||
for (int i = 0; i < t.num_words && node; i++) {
|
|
||||||
int n_found = 0;
|
int n_found = 0;
|
||||||
struct UCCmdNode *found = NULL;
|
struct UCCmdNode *found = NULL;
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
if (uc_cmd_node_match(node, t.cmd_words[i], &args)) {
|
if (uc_cmd_node_match(node, t->cmd_words[i], args)) {
|
||||||
found = node;
|
if (n_found == 0) {
|
||||||
|
//keep the 1. matched
|
||||||
|
found = node;
|
||||||
|
}
|
||||||
n_found++;
|
n_found++;
|
||||||
}
|
}
|
||||||
node = node->next;
|
node = node->next;
|
||||||
@@ -320,31 +369,118 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line)
|
|||||||
|
|
||||||
if (n_found == 1) {
|
if (n_found == 1) {
|
||||||
node = found->child;
|
node = found->child;
|
||||||
|
rc = UC_CMDRC_OK;
|
||||||
} else if (n_found > 1) {
|
} else if (n_found > 1) {
|
||||||
uc_strv_destroy(&args);
|
node = found;
|
||||||
uc_cmd_tokenize_destroy(&t);
|
rc = UC_CMDRC_AMBIGUOUS;
|
||||||
return UC_CMDRC_AMBIGUOUS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now check the current level for any UC_CMD_END
|
|
||||||
// which indicates a complete command
|
|
||||||
while (node) {
|
|
||||||
if (node->type == UC_CMD_END) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
node = node->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node != NULL) {
|
*result = node;
|
||||||
struct UCCmdDef *cmd = node->data;
|
|
||||||
rc = cmd->callback(&args);
|
if (node == NULL) {
|
||||||
|
rc = UC_CMDRC_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum UCCmdRc
|
||||||
|
uc_cmd_parse_and_find(struct UCCmdRunner *r, const char *cmd_line,
|
||||||
|
struct UCStrv *args,
|
||||||
|
struct UCCmdNode **result)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct UCCmdNode *node = r->root_node->child;
|
||||||
|
struct UCCmdTokenizer t;
|
||||||
|
enum UCCmdRc rc = UC_CMDRC_ERROR;
|
||||||
|
|
||||||
|
//make a copy since getfields destroys the original string
|
||||||
|
uc_cmd_tokenize(&t, cmd_line, NULL);
|
||||||
|
|
||||||
|
if (t.num_words > 0) {
|
||||||
|
|
||||||
|
//match the commands towards the command tree
|
||||||
|
//
|
||||||
|
rc = uc_cmd_find(node, &t, args, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
uc_cmd_tokenize_destroy(&t);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UCCmdRc
|
||||||
|
uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct UCStrv completions = UC_STRV_INITIALIZER;
|
||||||
|
|
||||||
|
struct UCCmdNode *found = NULL;
|
||||||
|
enum UCCmdRc rc;
|
||||||
|
|
||||||
|
rc = uc_cmd_parse_and_find(r, cmd_line, NULL, &found);
|
||||||
|
if (rc != UC_CMDRC_NOT_FOUND && found != NULL) {
|
||||||
|
struct UCCmdNode *node = found;
|
||||||
|
while (node) {
|
||||||
|
if (node->type == UC_CMD_END) {
|
||||||
|
uc_strv_append(&completions, "<CR>");
|
||||||
|
} else if (node->type == UC_CMD_LIST) {
|
||||||
|
uc_strv_append_all(&completions, node->data, 1);
|
||||||
|
} else if (node->type == UC_CMD_STRING ||
|
||||||
|
node->type == UC_CMD_KEYWORD) {
|
||||||
|
uc_strv_append(&completions, node->data);
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Possible completions for '%s'\n", cmd_line);
|
||||||
|
print_args(&completions);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rc = UC_CMDRC_INCOMPLETE;
|
printf("No possible completions\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uc_strv_destroy(&completions);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum UCCmdRc
|
||||||
|
uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line)
|
||||||
|
{
|
||||||
|
struct UCCmdArgs args = {
|
||||||
|
.argv = UC_STRV_INITIALIZER,
|
||||||
|
.cmd = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UCCmdNode *found = NULL;
|
||||||
|
enum UCCmdRc rc;
|
||||||
|
|
||||||
|
rc = uc_cmd_parse_and_find(r, cmd_line, &args.argv, &found);
|
||||||
|
if (rc == UC_CMDRC_OK) {
|
||||||
|
// Now check the current level for any UC_CMD_END
|
||||||
|
// which indicates a complete command
|
||||||
|
while (found) {
|
||||||
|
if (found->type == UC_CMD_END) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
found = found->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found != NULL) {
|
||||||
|
struct UCCmdDef *cmd = found->data;
|
||||||
|
args.cmd = cmd;
|
||||||
|
rc = cmd->callback(&args);
|
||||||
|
} else {
|
||||||
|
rc = UC_CMDRC_INCOMPLETE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uc_strv_destroy(&args);
|
uc_strv_destroy(&args.argv);
|
||||||
uc_cmd_tokenize_destroy(&t);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -353,37 +489,39 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line)
|
|||||||
void print_args(const struct UCStrv *args)
|
void print_args(const struct UCStrv *args)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < args->cnt; i++) {
|
for (size_t i = 0; i < args->cnt; i++) {
|
||||||
printf("arg %zu:%s\n", i, args->strings[i]);
|
printf("arg %zu: '%s' ", i, args->strings[i]);
|
||||||
}
|
}
|
||||||
|
puts("");
|
||||||
}
|
}
|
||||||
enum UCCmdRc cmd1_cb(const struct UCStrv *args)
|
|
||||||
|
enum UCCmdRc cmd1_cb(const struct UCCmdArgs *args)
|
||||||
{
|
{
|
||||||
puts(__func__);
|
puts(__func__);
|
||||||
print_args(args);
|
print_args(&args->argv);
|
||||||
|
|
||||||
return UC_CMDRC_OK;
|
return UC_CMDRC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UCCmdRc cmd2_cb(const struct UCStrv *args)
|
enum UCCmdRc cmd2_cb(const struct UCCmdArgs *args)
|
||||||
{
|
{
|
||||||
puts(__func__);
|
puts(__func__);
|
||||||
print_args(args);
|
print_args(&args->argv);
|
||||||
|
|
||||||
return UC_CMDRC_OK;
|
return UC_CMDRC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UCCmdRc cmd3_cb(const struct UCStrv *args)
|
enum UCCmdRc cmd3_cb(const struct UCCmdArgs *args)
|
||||||
{
|
{
|
||||||
puts(__func__);
|
puts(__func__);
|
||||||
print_args(args);
|
print_args(&args->argv);
|
||||||
|
|
||||||
return UC_CMDRC_OK;
|
return UC_CMDRC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UCCmdRc cmd4_cb(const struct UCStrv *args)
|
enum UCCmdRc cmd4_cb(const struct UCCmdArgs *args)
|
||||||
{
|
{
|
||||||
puts(__func__);
|
puts(__func__);
|
||||||
print_args(args);
|
print_args(&args->argv);
|
||||||
|
|
||||||
return UC_CMDRC_OK;
|
return UC_CMDRC_OK;
|
||||||
}
|
}
|
||||||
@@ -411,7 +549,7 @@ int main(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct UCCmdDef cmd3 = {
|
struct UCCmdDef cmd3 = {
|
||||||
"show empty (bottle|glass)",
|
"show empty bottle",
|
||||||
cmd3_cb,
|
cmd3_cb,
|
||||||
0,
|
0,
|
||||||
NULL
|
NULL
|
||||||
@@ -433,7 +571,8 @@ int main(int argc, char *argv[])
|
|||||||
uc_cmd_run(&r, "delete file /tmp/a");
|
uc_cmd_run(&r, "delete file /tmp/a");
|
||||||
uc_cmd_run(&r, "show all");
|
uc_cmd_run(&r, "show all");
|
||||||
uc_cmd_run(&r, "show empty");
|
uc_cmd_run(&r, "show empty");
|
||||||
uc_cmd_run(&r, "sh emp g");
|
uc_cmd_run(&r, "sh emp b");
|
||||||
|
uc_cmd_run(&r, "");
|
||||||
/*
|
/*
|
||||||
while (fgets(line,sizeof line, stdin)) {
|
while (fgets(line,sizeof line, stdin)) {
|
||||||
enum UCCmdRc rc = uc_cmd_run(&r, line);
|
enum UCCmdRc rc = uc_cmd_run(&r, line);
|
||||||
@@ -443,6 +582,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
uc_cmd_complete(&r, "sho em");
|
||||||
|
uc_cmd_complete(&r, "show ");
|
||||||
|
uc_cmd_complete(&r, "");
|
||||||
uc_cmd_runner_destroy(&r);
|
uc_cmd_runner_destroy(&r);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user