From d4d2c1e98aa3f4abb9ea2e6d294e2cad7e408b65 Mon Sep 17 00:00:00 2001 From: FreeArtMan Date: Wed, 17 Aug 2016 21:55:21 +0100 Subject: Autocomplete and history for cmd manager --- cmd.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ cmd.h | 13 +++++- 2 files changed, 149 insertions(+), 16 deletions(-) diff --git a/cmd.c b/cmd.c index 9ceab86..c20ccfc 100644 --- a/cmd.c +++ b/cmd.c @@ -269,6 +269,7 @@ int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ) { int ret = -1; int fret = 0; + int pret = 0; //pre condition return int i; cmd_arg_t *sub_arg = NULL; @@ -300,7 +301,18 @@ int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ) } sub_arg = cmd_arg_sub( arg ); - fret = tbl[i].clb( sub_arg ); + //execute callback preconditions + if (tbl[i].pre != NULL) + { + pret = tbl[i].pre( sub_arg ); + } else { + pret = 0; //no precond just pass + } + if (pret == 0) + { + //execute callback + fret = tbl[i].clb( sub_arg ); + } //if command whent wrong or not still clean mem if ( sub_arg != NULL ) @@ -308,12 +320,16 @@ int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ) cmd_arg_destroy( sub_arg ); } - //command execution whent wrong lets go out - if ( fret != 0 ) + //command execution precondtions met but wrong execution + if ( pret == 0 ) { - printf("Command broken execution\n"); - ret = -1; - break; + //command execution whent wrong lets go out + if ( fret != 0 ) + { + printf("Command broken execution\n"); + ret = -1; + break; + } } ret = 0; //succesfull execution break; @@ -489,18 +505,104 @@ void cmd_acq_free( struct cmd_acq_head_t *acq ) char* cmd_mng_history( cmd_mng_t *cmng, int index ) { + int idx; char *ret=NULL; + if (cmng == NULL) + { + return NULL; + } + if (cmng->history_size < CMD_HISTORY_SIZE) + { + if (index < cmng->history_size) + { + ret = cmng->history[index]; + } + } else + { + idx = (cmng->history_size-CMD_HISTORY_SIZE+index)%CMD_HISTORY_SIZE; + ret = cmng->history[idx]; + } return ret; } -char* cmd_mng_autocomplete( cmd_mng_t *cmng, char *cmd ) +char* cmd_mng_autocomplete( cmd_mng_t *cmng, char *cmd, size_t cmd_sz ) { char *ret=NULL; + cmd_arg_t *args; + cmd_tok_t tl, *ptr = &tl, *iter = NULL; + cmd_table_t *tab = cmng->table; + struct cmd_acq_t *iter_sugg = NULL; + int ac_sz=0,cnt_sz=0; + char *ac_str; + memset( &tl, 0, sizeof( cmd_tok_t )); + int i; + + printf("[%s]\n", cmd); + if ( parse_cmd(ptr, cmd, cmd_sz) == -1) + { + printf("Cmd problems\n"); + return NULL; + } + + iter = ptr->next; + args = cmd_arg_create( iter ); + + + for (i=0; iargc; i++) + { + printf("AC ARG:%d TYPE:%d %s\n", i, args->type[i], args->argv[i]); + } + + + //printf("Unkn command\n"); + //if command not found offer auto complete options + if (args->argc > 0) + { + //printf("asd\n"); + struct cmd_acq_head_t *ac = cmd_acq(tab,args->argv[0]); + if (ac != NULL) + { + //calculate string str + //printf("\n>"); + //printf("Did you mean "); + SLIST_FOREACH(iter_sugg,ac,next_sugg) + { + //printf("%s ", iter_sugg->suggestion); + ac_sz += strlen(iter_sugg->suggestion)+1; //1 for " " + } + ac_sz += 2; //"> " + ac_sz += 1; //"\0" + ac_str = (char *)malloc(ac_sz); + + memcpy( ac_str, "> ", 2 ); + cnt_sz = 2; + cnt_sz = 0; + SLIST_FOREACH(iter_sugg,ac,next_sugg) + { + //printf("%s ", iter_sugg->suggestion); + //double logical usage + ac_sz = strlen(iter_sugg->suggestion); + memcpy( ac_str+cnt_sz, iter_sugg->suggestion, ac_sz); + cnt_sz += ac_sz; + ac_str[cnt_sz] = ' '; + //memcpy( ac_str+cnt_sz, " ", 1); + cnt_sz += 1; + } + ac_str[cnt_sz] = '\0'; + ret = ac_str; + //printf("\n"); + } + cmd_acq_free( ac ); + } + + cmd_tok_destroy( ptr->next ); + ptr->next = NULL; + cmd_arg_destroy( args ); return ret; } @@ -522,24 +624,29 @@ int cmd_mng_exec( cmd_mng_t *cmng, const char *cmd, size_t sz_cmd ) goto error_exe; //if err memleak from parse_cmd? } - //printf("T:%d\n", ptr_tl->next); iter = ptr_tl->next; args = cmd_arg_create( iter ); cmd_tok_destroy( ptr_tl->next ); ptr_tl->next = NULL; - //int i; - //for (i=0;iargc;i++) - //{ - // printf("A:%s\n",args->argv[i]); - //} - if (cmd_exec(cmng->table, args) != 0) { ret = CMD_ECMD; goto error_cmd; } + /* if history is on then manage commands */ + if (cmng->flag_history) + { + /*replace with proper datatype in future*/ + char *p = malloc(sz_cmd); + int idx = (cmng->history_size)%CMD_HISTORY_SIZE; + memcpy(p,cmd,sz_cmd); + if (cmng->history[idx]!=NULL) free(cmng->history[idx]); + cmng->history[idx] = p; + cmng->history_size += 1; //one day there could be overflow after 2^31/2^63 cmds, good luck with this bug + } + cmd_arg_destroy( args ); return ret; @@ -551,6 +658,23 @@ error_exe: return ret; } +int cmd_mng_free( cmd_mng_t *cmng) +{ + int ret=0; + int i; + + for (i=0;ihistory[i]) + { + free(cmng->history[i]); + cmng->history[i] = NULL; + } + } + + return ret; +} + /* Clothest match function AA AB = (1) equile <100% diff --git a/cmd.h b/cmd.h index a5e349a..b2decab 100644 --- a/cmd.h +++ b/cmd.h @@ -74,6 +74,7 @@ typedef struct cmd_table_t int (*clb)(cmd_arg_t*); //callback to command int (*hlp)(cmd_arg_t*); //help command int (*pre)(cmd_arg_t*); //preconditions for execution + int (*autocpl)(cmd_arg_t*); //autocomplete according to context } cmd_table_t; /* @@ -101,6 +102,9 @@ typedef struct cmd_mng_t //not yet ready //int flag_logging; + + // flag turn on/off autocomplete + int flag_autocomplete; cmd_table_t *table; } cmd_mng_t; @@ -128,7 +132,7 @@ PARAM: cmng - cli manager index - index value in history RETURN: - [FREE] return value if there is under index + return non-NULL value if there something */ char* cmd_mng_history( cmd_mng_t *cmng, int index ); @@ -139,7 +143,7 @@ PARAM: RETURN: [FREE] return string list of autocomplete commands */ -char* cmd_mng_autocomplete( cmd_mng_t *cmng, char *cmd ); +char* cmd_mng_autocomplete( cmd_mng_t *cmng, char *cmd, size_t cmd_sz ); /* PARAM: cmng @@ -148,6 +152,11 @@ RETURN: return result of execution */ int cmd_mng_exec( cmd_mng_t *cmng, const char *cmd, size_t sz_cmd ); +/* +Free resources that where givent to cmd manager, like history +*/ +int cmd_mng_free( cmd_mng_t *cmng); + #define STR_AC_EQ(A,B) (strncmp_ac((A),(B),strlen(A))==(strlen(A)+1)) #define STR_AC_PEQ(A,B) (strncmp_ac((A),(B),strlen(A))<(strlen(A))) -- cgit v1.2.3