/* * Copyright (c) 2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include "shell_ops.h" #include "shell_help.h" #include "shell_utils.h" /* Function prints a string on terminal screen with requested margin. * It takes care to not divide words. * shell Pointer to shell instance. * p_str Pointer to string to be printed. * terminal_offset Requested left margin. * offset_first_line Add margin to the first printed line. */ static void formatted_text_print(const struct shell *sh, const char *str, size_t terminal_offset, bool offset_first_line) { size_t offset = 0; size_t length; if (str == NULL) { return; } if (offset_first_line) { z_shell_op_cursor_horiz_move(sh, terminal_offset); } /* Skipping whitespace. */ while (isspace((int) *(str + offset)) != 0) { ++offset; } while (true) { size_t idx = 0; length = z_shell_strlen(str) - offset; if (length <= sh->ctx->vt100_ctx.cons.terminal_wid - terminal_offset) { for (idx = 0; idx < length; idx++) { if (*(str + offset + idx) == '\n') { z_transport_buffer_flush(sh); z_shell_write(sh, str + offset, idx); offset += idx + 1; z_cursor_next_line_move(sh); z_shell_op_cursor_horiz_move(sh, terminal_offset); break; } } /* String will fit in one line. */ z_shell_raw_fprintf(sh->fprintf_ctx, str + offset); break; } /* String is longer than terminal line so text needs to * divide in the way to not divide words. */ length = sh->ctx->vt100_ctx.cons.terminal_wid - terminal_offset; while (true) { /* Determining line break. */ if (isspace((int) (*(str + offset + idx))) != 0) { length = idx; if (*(str + offset + idx) == '\n') { break; } } if ((idx + terminal_offset) >= sh->ctx->vt100_ctx.cons.terminal_wid) { /* End of line reached. */ break; } ++idx; } /* Writing one line, fprintf IO buffer must be flushed * before calling shell_write. */ z_transport_buffer_flush(sh); z_shell_write(sh, str + offset, length); offset += length; /* Calculating text offset to ensure that next line will * not begin with a space. */ while (isspace((int) (*(str + offset))) != 0) { ++offset; } z_cursor_next_line_move(sh); z_shell_op_cursor_horiz_move(sh, terminal_offset); } z_cursor_next_line_move(sh); } static void help_item_print(const struct shell *sh, const char *item_name, uint16_t item_name_width, const char *item_help) { static const uint8_t tabulator[] = " "; static const char sub_cmd_sep[] = ": "; /* subcommands separator */ const uint16_t offset = 2 * strlen(tabulator) + item_name_width + strlen(sub_cmd_sep); if ((item_name == NULL) || (item_name[0] == '\0')) { return; } if (!IS_ENABLED(CONFIG_NEWLIB_LIBC) && !IS_ENABLED(CONFIG_ARCH_POSIX)) { /* print option name */ z_shell_fprintf(sh, SHELL_NORMAL, "%s%-*s", tabulator, item_name_width, item_name); } else { uint16_t tmp = item_name_width - strlen(item_name); char space = ' '; z_shell_fprintf(sh, SHELL_NORMAL, "%s%s", tabulator, item_name); if (item_help) { for (uint16_t i = 0; i < tmp; i++) { z_shell_write(sh, &space, 1); } } } if (item_help == NULL) { z_cursor_next_line_move(sh); return; } else { z_shell_fprintf(sh, SHELL_NORMAL, "%s: ", tabulator); } /* print option help */ formatted_text_print(sh, item_help, offset, false); } /* Function prints all subcommands of the parent command together with their * help string */ void z_shell_help_subcmd_print(const struct shell *sh, const struct shell_static_entry *parent, const char *description) { const struct shell_static_entry *entry = NULL; struct shell_static_entry dloc; uint16_t longest = 0U; size_t idx = 0; /* Searching for the longest subcommand to print. */ while ((entry = z_shell_cmd_get(parent, idx++, &dloc)) != NULL) { longest = Z_MAX(longest, z_shell_strlen(entry->syntax)); } /* No help to print */ if (longest == 0) { return; } if (description != NULL) { z_shell_fprintf(sh, SHELL_NORMAL, description); } /* Printing subcommands and help string (if exists). */ idx = 0; while ((entry = z_shell_cmd_get(parent, idx++, &dloc)) != NULL) { help_item_print(sh, entry->syntax, longest, entry->help); } } void z_shell_help_cmd_print(const struct shell *sh, const struct shell_static_entry *cmd) { static const char cmd_sep[] = " - "; /* commands separator */ uint16_t field_width; field_width = z_shell_strlen(cmd->syntax) + z_shell_strlen(cmd_sep); z_shell_fprintf(sh, SHELL_NORMAL, "%s%s", cmd->syntax, cmd_sep); formatted_text_print(sh, cmd->help, field_width, false); } bool z_shell_help_request(const char *str) { if (!IS_ENABLED(CONFIG_SHELL_HELP_OPT_PARSE)) { return false; } if (!strcmp(str, "-h") || !strcmp(str, "--help")) { return true; } return false; }