From e59b8cbef970b4d4f07ff52c9cb7e024d62e5316 Mon Sep 17 00:00:00 2001 From: Jakub Rzeszutko Date: Fri, 21 Sep 2018 16:41:22 +0200 Subject: [PATCH] subsys : shell : Added API changing prompt 1. Added API to change shell prompt in runtime. 2. Added prompt buffer length configuration in Kconfig. Signed-off-by: Jakub Rzeszutko --- include/shell/shell.h | 20 ++++++++++++++++---- subsys/shell/Kconfig | 6 ++++++ subsys/shell/shell.c | 31 +++++++++++++++++++++++-------- subsys/shell/shell_ops.c | 4 ++-- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/include/shell/shell.h b/include/shell/shell.h index 8c00e2cf56a..cf632575ad3 100644 --- a/include/shell/shell.h +++ b/include/shell/shell.h @@ -349,7 +349,7 @@ extern const struct log_backend_api log_backend_shell_api; * @brief Shell instance internals. */ struct shell { - const char *const name; /*!< Terminal name. */ + char *const prompt; /*!< shell prompt. */ const struct shell_transport *iface; /*!< Transport interface.*/ struct shell_ctx *ctx; /*!< Internal context.*/ @@ -375,16 +375,17 @@ struct shell { * @brief Macro for defining a shell instance. * * @param[in] _name Instance name. - * @param[in] shell_prefix Shell prefix string. + * @param[in] _prompt Shell prompt string. * @param[in] transport_iface Pointer to the transport interface. * @param[in] newline_ch New line character - only allowed values are * '\\n' or '\\r'. * @param[in] log_queue_size Logger processing queue size. */ -#define SHELL_DEFINE(_name, shell_prefix, transport_iface, \ +#define SHELL_DEFINE(_name, _prompt, transport_iface, \ newline_ch, log_queue_size) \ static const struct shell _name; \ static struct shell_ctx UTIL_CAT(_name, _ctx); \ + static char _name##prompt[CONFIG_SHELL_PROMPT_LENGTH + 1] = _prompt; \ static u8_t _name##_out_buffer[CONFIG_SHELL_PRINTF_BUFF_SIZE]; \ SHELL_LOG_BACKEND_DEFINE(_name, _name##_out_buffer, \ CONFIG_SHELL_PRINTF_BUFF_SIZE); \ @@ -397,7 +398,7 @@ struct shell { static K_THREAD_STACK_DEFINE(_name##_stack, CONFIG_SHELL_STACK_SIZE);\ static struct k_thread _name##_thread; \ static const struct shell _name = { \ - .name = shell_prefix, \ + .prompt = _name##prompt, \ .iface = transport_iface, \ .ctx = &UTIL_CAT(_name, _ctx), \ .history = SHELL_HISTORY_PTR(_name), \ @@ -528,6 +529,17 @@ static inline bool shell_help_requested(const struct shell *shell) void shell_help_print(const struct shell *shell, const struct shell_getopt_option *opt, size_t opt_len); +/* + * @brief Change displayed shell prompt. + * + * @param[in] shell Pointer to the shell instance. + * @param[in] prompt New shell prompt. + * + * @return 0 success + * @return -1 new string is too long + */ +int shell_prompt_change(const struct shell *shell, char *prompt); + /* * @brief Prints help if request and prints error message on wrong argument * count. diff --git a/subsys/shell/Kconfig b/subsys/shell/Kconfig index 44e057a09c7..195603cb97d 100644 --- a/subsys/shell/Kconfig +++ b/subsys/shell/Kconfig @@ -67,6 +67,12 @@ config SHELL_BACKSPACE_MODE_DELETE Some terminals send code: 0x08 (backspace) other 0x7F (delete). When this option is set shell will expect 0x7F for backspace key. +config SHELL_PROMPT_LENGTH + int "Maximum prompt length" + default 16 + help + Maximum length of prompt name in bytes. + config SHELL_CMD_BUFF_SIZE int "Shell command buffer size" default 256 diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index 359922af5db..e7820683b18 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -234,7 +234,7 @@ static void shell_state_set(const struct shell *shell, enum shell_state state) if (state == SHELL_STATE_ACTIVE) { shell_cmd_buffer_clear(shell); - shell_fprintf(shell, SHELL_INFO, "%s", shell->name); + shell_fprintf(shell, SHELL_INFO, "%s", shell->prompt); } } @@ -598,7 +598,7 @@ static void tab_options_print(const struct shell *shell, idx++; } - shell_fprintf(shell, SHELL_INFO, "\r\n%s", shell->name); + shell_fprintf(shell, SHELL_INFO, "\r\n%s", shell->prompt); shell_fprintf(shell, SHELL_NORMAL, "%s", shell->ctx->cmd_buff); shell_op_cursor_position_synchronize(shell); @@ -718,7 +718,7 @@ static void metakeys_handle(const struct shell *shell, char data) case SHELL_VT100_ASCII_CTRL_L: /* CTRL + L */ SHELL_VT100_CMD(shell, SHELL_VT100_CURSORHOME); SHELL_VT100_CMD(shell, SHELL_VT100_CLEARSCREEN); - shell_fprintf(shell, SHELL_INFO, "%s", shell->name); + shell_fprintf(shell, SHELL_INFO, "%s", shell->prompt); if (flag_echo_is_set(shell)) { shell_fprintf(shell, SHELL_NORMAL, "%s", shell->ctx->cmd_buff); @@ -1116,7 +1116,7 @@ static void shell_current_command_erase(const struct shell *shell) static void shell_current_command_print(const struct shell *shell) { - shell_fprintf(shell, SHELL_INFO, "%s", shell->name); + shell_fprintf(shell, SHELL_INFO, "%s", shell->prompt); if (flag_echo_is_set(shell)) { shell_fprintf(shell, SHELL_NORMAL, "%s", shell->ctx->cmd_buff); @@ -1145,7 +1145,7 @@ static int shell_instance_init(const struct shell *shell, const void *p_config, bool use_colors) { assert(shell); - assert(shell->ctx && shell->iface && shell->name); + assert(shell->ctx && shell->iface && shell->prompt); assert((shell->newline_char == '\n') || (shell->newline_char == '\r')); int err; @@ -1174,7 +1174,7 @@ static int shell_instance_init(const struct shell *shell, const void *p_config, shell->ctx->state = SHELL_STATE_INITIALIZED; shell->ctx->vt100_ctx.cons.terminal_wid = SHELL_DEFAULT_TERMINAL_WIDTH; shell->ctx->vt100_ctx.cons.terminal_hei = SHELL_DEFAULT_TERMINAL_HEIGHT; - shell->ctx->vt100_ctx.cons.name_len = shell_strlen(shell->name); + shell->ctx->vt100_ctx.cons.name_len = shell_strlen(shell->prompt); shell->ctx->internal.flags.use_colors = IS_ENABLED(CONFIG_SHELL_VT100_COLORS); @@ -1268,7 +1268,7 @@ int shell_init(const struct shell *shell, const void *transport_config, static int shell_instance_uninit(const struct shell *shell) { assert(shell); - assert(shell->ctx && shell->iface && shell->name); + assert(shell->ctx && shell->iface && shell->prompt); int err; if (flag_processing_is_set(shell)) { @@ -1307,7 +1307,7 @@ int shell_uninit(const struct shell *shell) int shell_start(const struct shell *shell) { assert(shell); - assert(shell->ctx && shell->iface && shell->name); + assert(shell->ctx && shell->iface && shell->prompt); int err; if (shell->ctx->state != SHELL_STATE_INITIALIZED) { @@ -1663,6 +1663,21 @@ void shell_help_print(const struct shell *shell, help_subcmd_print(shell); } +int shell_prompt_change(const struct shell *shell, char *prompt) +{ + + size_t len = shell_strlen(prompt); + + assert(shell); + assert(prompt); + + if (len <= CONFIG_SHELL_PROMPT_LENGTH) { + memcpy(shell->prompt, prompt, len + 1); /* +1 for '\0' */ + return 0; + } + return -1; +} + bool shell_cmd_precheck(const struct shell *shell, bool arg_cnt_ok, const struct shell_getopt_option *opt, diff --git a/subsys/shell/shell_ops.c b/subsys/shell/shell_ops.c index 561e20e8b62..12f80d2066f 100644 --- a/subsys/shell/shell_ops.c +++ b/subsys/shell/shell_ops.c @@ -29,14 +29,14 @@ void shell_op_cursor_horiz_move(const struct shell *shell, s32_t delta) */ static inline bool full_line_cmd(const struct shell *shell) { - return ((shell->ctx->cmd_buff_len + shell_strlen(shell->name)) + return ((shell->ctx->cmd_buff_len + shell_strlen(shell->prompt)) % shell->ctx->vt100_ctx.cons.terminal_wid == 0); } /* Function returns true if cursor is at beginning of an empty line. */ bool shell_cursor_in_empty_line(const struct shell *shell) { - return ((shell->ctx->cmd_buff_pos + shell_strlen(shell->name)) + return ((shell->ctx->cmd_buff_pos + shell_strlen(shell->prompt)) % shell->ctx->vt100_ctx.cons.terminal_wid == 0); }