zephyr/subsys/shell/shell_help.c

208 lines
4.9 KiB
C

/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ctype.h>
#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;
}