
Eddie Dong
I assume the edit user experience is same with what Linux has today. Right? We need a doc change patch here.
toggle quoted messageShow quoted text
-----Original Message----- From: acrn-dev@... <acrn-dev@...> On Behalf Of Minggui Cao Sent: Tuesday, July 19, 2022 11:16 PM To: acrn-dev@... Cc: Cao, Minggui <minggui.cao@...> Subject: [acrn-dev] [PATCH 1/2] hv: shell: improve console to buffer history cmds
1. buffer max to 8 history commands. 2. support up/down key to select history buffered commands
Signed-off-by: Minggui Cao <minggui.cao@...> --- hypervisor/debug/shell.c | 150 +++++++++++++++++++++++++++++----- hypervisor/debug/shell_priv.h | 9 ++ 2 files changed, 137 insertions(+), 22 deletions(-)
diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index 588e4aa0f..092b80c02 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -158,6 +158,16 @@ static struct shell_cmd shell_cmds[] = { }, };
+/* for function key: up/down key */ +enum function_key { + KEY_NONE, + + KEY_UP = 0x41, + KEY_DOWN = 0x42, +}; + +#define FUNCTION_KEY_TAG 0x5B /* function key input: esc + tag + key */ + /* The initial log level*/ uint16_t console_loglevel = CONFIG_CONSOLE_LOGLEVEL_DEFAULT; uint16_t mem_loglevel = CONFIG_MEM_LOGLEVEL_DEFAULT; @@ -271,14 +281,97 @@ static uint16_t sanitize_vmid(uint16_t vmid) return sanitized_vmid; }
+static void clear_input_line(uint32_t len) { + while (len > 0) { + len--; + shell_puts("\b"); + shell_puts(" \b"); + } +} +static void copy_chars(char *dest, char *src, uint32_t size, bool +from_head) { + uint32_t i = 0; + + if (from_head) { + for (i = 0; i < size; i++) { + *(dest + i) = *(src + i); + } + } else { + for (i = size; i > 0; i--) { + *(dest + i - 1) = *(src + i - 1); + } + } I didn't see the difference of above 2 ranches. Did I miss something? Also why not directly use memcpy? +} + +static void handle_updown_key(enum function_key key_value) { + uint32_t current_select = p_shell->selected_index; + + if (p_shell->total_buffered_cmds == 0) { + return; + } + + /* update p_shell->selected_index as up/down key */ + if (key_value == KEY_UP) { + + if ((p_shell->total_buffered_cmds < MAX_BUFFERED_CMDS) && (p_shell->selected_index > 0)) { + p_shell->selected_index--; + } else if (p_shell->total_buffered_cmds >= MAX_BUFFERED_CMDS) { + uint32_t up_select = (p_shell->selected_index + MAX_BUFFERED_CMDS - +1) % MAX_BUFFERED_CMDS; + + if (up_select != p_shell->index_to_store) { + p_shell->selected_index = up_select; + } + } + } else { /* for down-key */ + uint32_t down_select = (p_shell->selected_index + 1) % +MAX_BUFFERED_CMDS; + + if (down_select != p_shell->index_to_store) { + p_shell->selected_index = down_select; + } + } + + if (strcmp(p_shell->buffered_cmds[current_select], +p_shell->input_line[p_shell->input_line_active]) != 0) { + + clear_input_line(p_shell->input_line_len); + shell_puts(p_shell->buffered_cmds[current_select]); + + size_t len = strnlen_s(p_shell->buffered_cmds[current_select], +SHELL_CMD_MAX_LEN); + + copy_chars(p_shell->input_line[p_shell->input_line_active], + p_shell->buffered_cmds[current_select], len + 1, true); + + p_shell->input_line_len = len; + } +} + static void shell_handle_special_char(char ch) { + char key1, key2; + enum function_key key_value = KEY_NONE; + switch (ch) { - /* Escape character */ + /* function key: esc + tag + key-value, so consume the next 2 Tag what? +characters */ case 0x1b: - /* Consume the next 2 characters */ - (void) shell_getc(); - (void) shell_getc(); + key1 = shell_getc(); + key2 = shell_getc(); + The edit key must follow ESC key? + if (key1 == FUNCTION_KEY_TAG) { + key_value = key2; + } + + switch (key_value) { + case KEY_NONE: + break; + case KEY_UP: + case KEY_DOWN: + handle_updown_key(key_value); + break; + default: + break; + } + break; default: /* @@ -427,31 +520,40 @@ static int32_t shell_process(void) { int32_t status; char *p_input_line; + bool to_buffer = true;
- /* Check for the repeat command character in active input line. - */ - if (p_shell->input_line[p_shell->input_line_active][0] == '.') { - /* Repeat the last command (using inactive input line). - */ - p_input_line = - &p_shell->input_line[SHELL_INPUT_LINE_OTHER - (p_shell->input_line_active)][0]; - } else { - /* Process current command (using active input line). */ - p_input_line = - &p_shell->input_line[p_shell->input_line_active][0]; + /* Process current command (using active input line). */ + p_input_line = p_shell->input_line[p_shell->input_line_active];
- /* Switch active input line. */ - p_shell->input_line_active = - SHELL_INPUT_LINE_OTHER(p_shell-
input_line_active); - } + /* Switch active input line. */ + p_shell->input_line_active = +SHELL_INPUT_LINE_OTHER(p_shell->input_line_active);
/* Process command */ status = shell_process_cmd(p_input_line);
+ /* buffer the handled cmd */ + if (p_shell->total_buffered_cmds > 0) { + uint32_t former_index = (p_shell->index_to_store + MAX_BUFFERED_CMDS +- 1) % MAX_BUFFERED_CMDS; + + if (strcmp(p_input_line, p_shell-
buffered_cmds[former_index]) == 0) { + to_buffer = false; + } + } + + if (to_buffer && (strnlen_s(p_input_line, SHELL_CMD_MAX_LEN) > 0)) { + strncpy_s(p_shell->buffered_cmds[p_shell->index_to_store], SHELL_CMD_MAX_LEN, + p_input_line, SHELL_CMD_MAX_LEN); + + p_shell->selected_index = p_shell->index_to_store; + p_shell->index_to_store = (p_shell->index_to_store + 1) % MAX_BUFFERED_CMDS; + p_shell->total_buffered_cmds = (p_shell-
total_buffered_cmds >= MAX_BUFFERED_CMDS) ? + MAX_BUFFERED_CMDS : (p_shell-
total_buffered_cmds + 1); + } else { + p_shell->selected_index = (p_shell->index_to_store + MAX_BUFFERED_CMDS - 1) % MAX_BUFFERED_CMDS; + } + /* Now that the command is processed, zero fill the input buffer */ - (void)memset((void *) p_shell->input_line[p_shell->input_line_active], - 0, SHELL_CMD_MAX_LEN + 1U); + (void)memset((void *) p_shell->input_line[p_shell->input_line_active], +0, SHELL_CMD_MAX_LEN + 1U);
/* Process command and return result to caller */ return status; @@ -490,6 +592,10 @@ void shell_init(void) p_shell->cmds = shell_cmds; p_shell->cmd_count = ARRAY_SIZE(shell_cmds);
+ p_shell->index_to_store = 0; + p_shell->total_buffered_cmds = 0; + p_shell->selected_index = 0; + /* Zero fill the input buffer */ (void)memset((void *)p_shell->input_line[p_shell->input_line_active], 0U, SHELL_CMD_MAX_LEN + 1U); diff --git a/hypervisor/debug/shell_priv.h b/hypervisor/debug/shell_priv.h index addad6555..ce40f3cd0 100644 --- a/hypervisor/debug/shell_priv.h +++ b/hypervisor/debug/shell_priv.h @@ -26,11 +26,20 @@ struct shell_cmd {
};
+#define MAX_BUFFERED_CMDS 8 + /* Shell Control Block */ struct shell { char input_line[2][SHELL_CMD_MAX_LEN + 1U]; /* current & last */ uint32_t input_line_len; /* Length of current input line */ uint32_t input_line_active; /* Active input line index */ + + /* a ring buffer to buffer former commands */ + char buffered_cmds[MAX_BUFFERED_CMDS][SHELL_CMD_MAX_LEN + 1U]; + uint32_t total_buffered_cmds; + uint32_t index_to_store; + uint32_t selected_index; /* used for up/down key to select former cmds +*/ + struct shell_cmd *cmds; /* cmds supported */ uint32_t cmd_count; /* Count of cmds supported */ }; -- 2.25.1
|