summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFreeArtMan <dos21h@gmail.com>2016-08-17 21:55:21 +0100
committerFreeArtMan <dos21h@gmail.com>2016-08-17 21:55:21 +0100
commitd4d2c1e98aa3f4abb9ea2e6d294e2cad7e408b65 (patch)
treebe8a9ada0b5cc3faa70376e683549792d6805440
parente6ddd00fedabeb470c7f3b132cb2289109688e73 (diff)
downloadlibcmd-d4d2c1e98aa3f4abb9ea2e6d294e2cad7e408b65.tar.gz
libcmd-d4d2c1e98aa3f4abb9ea2e6d294e2cad7e408b65.zip
Autocomplete and history for cmd manager
-rw-r--r--cmd.c152
-rw-r--r--cmd.h13
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; i<args->argc; 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;i<args->argc;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;i<CMD_HISTORY_SIZE;i++)
+ {
+ if (cmng->history[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)))