diff options
| author | bernard.xiong <[email protected]> | 2009-09-29 13:07:29 +0000 |
|---|---|---|
| committer | bernard.xiong <[email protected]> | 2009-09-29 13:07:29 +0000 |
| commit | 3da0559f23b7cd01004c451a2ce30ecc8e9b0271 (patch) | |
| tree | b69493753063fa669b938aebbf91f0b649a10dd8 | |
| parent | bd11f44ab4660f0a42d43ed6c4e8268b2de6f99c (diff) | |
add history and auto complete feature in finsh.
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@54 bbd45198-f89e-11dd-88c7-29a3b14d5316
| -rw-r--r-- | finsh/cmd.c | 106 | ||||
| -rw-r--r-- | finsh/shell.c | 180 |
2 files changed, 274 insertions, 12 deletions
diff --git a/finsh/cmd.c b/finsh/cmd.c index ef2b02d135..f790394160 100644 --- a/finsh/cmd.c +++ b/finsh/cmd.c @@ -369,6 +369,112 @@ int list() } FINSH_FUNCTION_EXPORT(list, list all symbol in system) +int str_is_prefix(const char* prefix, const char* str) +{ + while ((*prefix) && (*prefix == *str)) + { + prefix ++; + str ++; + } + + if (*prefix == 0) return 0; + return -1; +} + +void list_prefix(char* prefix) +{ + struct finsh_syscall_item* syscall_item; + struct finsh_sysvar_item* sysvar_item;
+ rt_uint16_t func_cnt, var_cnt;
+ const char* name_ptr;
+
+ func_cnt = 0;
+ var_cnt = 0; + { + struct finsh_syscall* index; + for (index = _syscall_table_begin; index < _syscall_table_end; index ++) + { + if (str_is_prefix(prefix, index->name) == 0) + {
+ if (func_cnt == 0) + rt_kprintf("--function:\n");
+
+ func_cnt ++;
+ /* set name_ptr */
+ name_ptr = index->name;
+ +#ifdef FINSH_USING_DESCRIPTION + rt_kprintf("%-16s -- %s\n", index->name, index->desc); +#else + rt_kprintf("%s\n", index->name); +#endif + } + } + } + + /* list syscall list */ + syscall_item = global_syscall_list; + while (syscall_item != NULL) + { + if (str_is_prefix(prefix, syscall_item->syscall.name) == 0) + {
+ if (func_cnt == 0) + rt_kprintf("--function:\n"); + func_cnt ++;
+ /* set name_ptr */
+ name_ptr = syscall_item->syscall.name;
+
+ rt_kprintf("[l] %s\n", syscall_item->syscall.name); + } + syscall_item = syscall_item->next; + } + + { + struct finsh_sysvar* index; + for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++) + { + if (str_is_prefix(prefix, index->name) == 0) + {
+ if (var_cnt == 0)
+ rt_kprintf("--variable:\n");
+ + var_cnt ++;
+ /* set name ptr */
+ name_ptr = index->name;
+ +#ifdef FINSH_USING_DESCRIPTION + rt_kprintf("%-16s -- %s\n", index->name, index->desc); +#else + rt_kprintf("%s\n", index->name); +#endif + } + } + } + + sysvar_item = global_sysvar_list; + while (sysvar_item != NULL) + { + if (str_is_prefix(prefix, sysvar_item->sysvar.name) == 0) + { + if (var_cnt == 0)
+ rt_kprintf("--variable:\n");
+
+ var_cnt ++;
+ /* set name ptr */
+ name_ptr = sysvar_item->sysvar.name;
+
+ rt_kprintf("[l] %s\n", sysvar_item->sysvar.name); + } + sysvar_item = sysvar_item->next; + }
+
+ /* only one matched */
+ if ((func_cnt + var_cnt) == 1)
+ {
+ rt_strncpy(prefix, name_ptr, strlen(name_ptr));
+ } +} + #ifdef FINSH_USING_SYMTAB static int dummy = 0; FINSH_VAR_EXPORT(dummy, finsh_type_int, dummy variable for finsh) diff --git a/finsh/shell.c b/finsh/shell.c index 486959480b..295079b134 100644 --- a/finsh/shell.c +++ b/finsh/shell.c @@ -20,6 +20,8 @@ #include "finsh.h" +#define FINSH_USING_HISTORY + #if defined(__CC_ARM) /* ARMCC compiler */ #ifdef FINSH_USING_SYMTAB extern int FSymTab$$Base; @@ -41,6 +43,22 @@ struct rt_semaphore uart_sem; #ifdef RT_USING_DEVICE rt_device_t finsh_device; #endif +#ifdef FINSH_USING_HISTORY +enum input_stat +{ + WAIT_NORMAL, + WAIT_SPEC_KEY, + WAIT_FUNC_KEY, +}; +#ifndef FINSH_HISTORY_LINES +#define FINSH_HISTORY_LINES 5 +#endif +#ifndef FINSH_CMD_SIZE +#define FINSH_CMD_SIZE 80 +#endif +char finsh_cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE]; +rt_uint16_t finsh_history_count = 0; +#endif #if !defined (RT_USING_NEWLIB) && !defined (RT_USING_MINILIBC) void *memccpy(void *dst, const void *src, int c, size_t count) @@ -148,11 +166,28 @@ void finsh_notify() } #endif +void finsh_auto_complete(char* prefix) +{ + extern void list_prefix(char* prefix); + + rt_kprintf("\n"); + list_prefix(prefix); + rt_kprintf("finsh>>%s", prefix); +} + void finsh_thread_entry(void* parameter) { struct finsh_parser parser; char line[256]; int pos ; +#ifdef FINSH_USING_HISTORY + enum input_stat stat; + unsigned short current_history, use_history; +#endif + + stat = WAIT_NORMAL; + current_history = 0;
+ use_history = 0; finsh_init(&parser); @@ -170,36 +205,157 @@ void finsh_thread_entry(void* parameter) char ch; #ifndef RT_USING_DEVICE - ch = rt_serial_getc(); + ch = rt_serial_getc();
if (ch != 0) #else rt_err_t rx_result; - rx_result = rt_device_read(finsh_device, 0, &ch, 1); + rx_result = rt_device_read(finsh_device, 0, &ch, 1);
if (ch != 0 && rx_result == 1) #endif { - line[pos] = ch; +#ifdef FINSH_USING_HISTORY + /* + * handle up and down key + * up key : 0x1b 0x5b 0x41 + * down key: 0x1b 0x5b 0x42 + */ + if (ch == 0x1b) + { + stat = WAIT_SPEC_KEY; + continue; + } + + if ((stat == WAIT_SPEC_KEY) && (ch == 0x5b)) + { + if (ch == 0x5b) + { + stat = WAIT_FUNC_KEY; + continue; + } + stat = WAIT_NORMAL; + } + + if (stat == WAIT_FUNC_KEY) + { + stat = WAIT_NORMAL;
+
+ if (ch == 0x41) /* up key */ + { + /* prev history */ + if (current_history > 0)current_history --;
+ else
+ {
+ current_history = 0;
+ continue;
+ }
+ + /* copy the history command */ + memcpy(line, &finsh_cmd_history[current_history][0], + FINSH_CMD_SIZE); + pos = strlen(line);
+ use_history = 1;
+ } + else if (ch == 0x42) /* down key */ + { + /* next history */
+ if (current_history < finsh_history_count - 1) + current_history ++;
+ else
+ {
+ current_history = finsh_history_count - 1;
+ continue;
+ }
+ + memcpy(line, &finsh_cmd_history[current_history][0], + FINSH_CMD_SIZE);
+ pos = strlen(line); + use_history = 1;
+ }
+
+ if (use_history)
+ {
+ rt_kprintf("\033[2K\r");
+ rt_kprintf("finsh>>%s", line); + continue;
+ } + }
+#endif + /* + * handle tab key + */ + if (ch == '\t') + { + /* auto complete */ + finsh_auto_complete(&line[0]);
+ /* re-calculate position */
+ pos = strlen(line); + continue; + } + + /* + * handle backspace key + */ + if (ch == 0x7f) + {
+ if (pos != 0) rt_kprintf("%c", ch); + line[pos--] = 0; + if (pos < 0) pos = 0; + continue; + } + + line[pos] = ch;
rt_kprintf("%c", line[pos]); /* if it's the end of line, break */ if (line[pos] == 0xd || line[pos] == 0xa) - { + {
/* change to ';' and break */ line[pos] = ';'; break; } - else if (line[pos] == 0x7f) /* backspace */ - { - line[pos] = 0; - pos --; - if (pos < 0) pos = 0; - continue; - } + else use_history = 0; /* not "\n", it's a new command */ pos ++; } } - } + }
+ + if (pos == 0)
+ {
+ rt_kprintf("\n");
+ continue;
+ }
+ +#ifdef FINSH_USING_HISTORY
+ if (use_history == 0)
+ { + /* push history */
+ if (finsh_history_count >= FINSH_HISTORY_LINES) + { + /* move history */ + int index; + for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++) + { + memcpy(&finsh_cmd_history[index][0], + &finsh_cmd_history[index + 1][0], FINSH_CMD_SIZE); + }
+ memset(&finsh_cmd_history[index][0], 0, FINSH_CMD_SIZE); + memcpy(&finsh_cmd_history[index][0], line, pos);
+
+ /* it's the maximum history */
+ finsh_history_count = FINSH_HISTORY_LINES; + }
+ else
+ { + memset(&finsh_cmd_history[finsh_history_count][0], 0, FINSH_CMD_SIZE); + memcpy(&finsh_cmd_history[finsh_history_count][0], line, pos);
+
+ /* increase count and set current history position */
+ finsh_history_count ++;
+ } + }
+ current_history = finsh_history_count;
+#endif rt_kprintf("\n"); finsh_parser_run(&parser, (unsigned char*)&line[0]); |
