Re: [PATCH 1/2] hv: shell: improve console to buffer history cmds


Eddie Dong
 

I assume the edit user experience is same with what Linux has today. Right?
We need a doc change patch here.

-----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




Join acrn-dev@lists.projectacrn.org to automatically receive all group messages.