1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <ctype.h>
7 #include "shell_ops.h"
8 #include "shell_help.h"
9 #include "shell_utils.h"
10
11
12 /* Function prints a string on terminal screen with requested margin.
13 * It takes care to not divide words.
14 * shell Pointer to shell instance.
15 * p_str Pointer to string to be printed.
16 * terminal_offset Requested left margin.
17 * offset_first_line Add margin to the first printed line.
18 */
formatted_text_print(const struct shell * sh,const char * str,size_t terminal_offset,bool offset_first_line)19 static void formatted_text_print(const struct shell *sh, const char *str,
20 size_t terminal_offset, bool offset_first_line)
21 {
22 size_t offset = 0;
23 size_t length;
24
25 if (str == NULL) {
26 return;
27 }
28
29 if (offset_first_line) {
30 z_shell_op_cursor_horiz_move(sh, terminal_offset);
31 }
32
33
34 /* Skipping whitespace. */
35 while (isspace((int) *(str + offset)) != 0) {
36 ++offset;
37 }
38
39 while (true) {
40 size_t idx = 0;
41
42 length = z_shell_strlen(str) - offset;
43
44 if (length <=
45 sh->ctx->vt100_ctx.cons.terminal_wid - terminal_offset) {
46 for (idx = 0; idx < length; idx++) {
47 if (*(str + offset + idx) == '\n') {
48 z_transport_buffer_flush(sh);
49 z_shell_write(sh, str + offset, idx);
50 offset += idx + 1;
51 z_cursor_next_line_move(sh);
52 z_shell_op_cursor_horiz_move(sh,
53 terminal_offset);
54 break;
55 }
56 }
57
58 /* String will fit in one line. */
59 z_shell_raw_fprintf(sh->fprintf_ctx, str + offset);
60
61 break;
62 }
63
64 /* String is longer than terminal line so text needs to
65 * divide in the way to not divide words.
66 */
67 length = sh->ctx->vt100_ctx.cons.terminal_wid
68 - terminal_offset;
69
70 while (true) {
71 /* Determining line break. */
72 if (isspace((int) (*(str + offset + idx))) != 0) {
73 length = idx;
74 if (*(str + offset + idx) == '\n') {
75 break;
76 }
77 }
78
79 if ((idx + terminal_offset) >=
80 sh->ctx->vt100_ctx.cons.terminal_wid) {
81 /* End of line reached. */
82 break;
83 }
84
85 ++idx;
86 }
87
88 /* Writing one line, fprintf IO buffer must be flushed
89 * before calling shell_write.
90 */
91 z_transport_buffer_flush(sh);
92 z_shell_write(sh, str + offset, length);
93 offset += length;
94
95 /* Calculating text offset to ensure that next line will
96 * not begin with a space.
97 */
98 while (isspace((int) (*(str + offset))) != 0) {
99 ++offset;
100 }
101
102 z_cursor_next_line_move(sh);
103 z_shell_op_cursor_horiz_move(sh, terminal_offset);
104
105 }
106 z_cursor_next_line_move(sh);
107 }
108
help_item_print(const struct shell * sh,const char * item_name,uint16_t item_name_width,const char * item_help)109 static void help_item_print(const struct shell *sh, const char *item_name,
110 uint16_t item_name_width, const char *item_help)
111 {
112 static const uint8_t tabulator[] = " ";
113 const uint16_t offset = 2 * strlen(tabulator) + item_name_width + 1;
114
115 if ((item_name == NULL) || (item_name[0] == '\0')) {
116 return;
117 }
118
119 if (!IS_ENABLED(CONFIG_NEWLIB_LIBC) &&
120 !IS_ENABLED(CONFIG_ARCH_POSIX)) {
121 /* print option name */
122 z_shell_fprintf(sh, SHELL_NORMAL, "%s%-*s", tabulator,
123 item_name_width, item_name);
124 } else {
125 uint16_t tmp = item_name_width - strlen(item_name);
126 char space = ' ';
127
128 z_shell_fprintf(sh, SHELL_NORMAL, "%s%s", tabulator,
129 item_name);
130
131 if (item_help) {
132 for (uint16_t i = 0; i < tmp; i++) {
133 z_shell_write(sh, &space, 1);
134 }
135 }
136 }
137
138 if (item_help == NULL) {
139 z_cursor_next_line_move(sh);
140 return;
141 } else {
142 z_shell_fprintf(sh, SHELL_NORMAL, "%s: ", tabulator);
143 }
144 /* print option help */
145 formatted_text_print(sh, item_help, offset, false);
146 }
147
148 /* Function prints all subcommands of the parent command together with their
149 * help string
150 */
z_shell_help_subcmd_print(const struct shell * sh,const struct shell_static_entry * parent,const char * description)151 void z_shell_help_subcmd_print(const struct shell *sh,
152 const struct shell_static_entry *parent,
153 const char *description)
154 {
155 const struct shell_static_entry *entry = NULL;
156 struct shell_static_entry dloc;
157 uint16_t longest = 0U;
158 size_t idx = 0;
159
160 /* Searching for the longest subcommand to print. */
161 while ((entry = z_shell_cmd_get(parent, idx++, &dloc)) != NULL) {
162 longest = Z_MAX(longest, z_shell_strlen(entry->syntax));
163 }
164
165 /* No help to print */
166 if (longest == 0) {
167 return;
168 }
169
170 if (description != NULL) {
171 z_shell_fprintf(sh, SHELL_NORMAL, description);
172 }
173
174 /* Printing subcommands and help string (if exists). */
175 idx = 0;
176
177 while ((entry = z_shell_cmd_get(parent, idx++, &dloc)) != NULL) {
178 help_item_print(sh, entry->syntax, longest, entry->help);
179 }
180 }
181
z_shell_help_cmd_print(const struct shell * sh,const struct shell_static_entry * cmd)182 void z_shell_help_cmd_print(const struct shell *sh,
183 const struct shell_static_entry *cmd)
184 {
185 static const char cmd_sep[] = " - "; /* commands separator */
186 uint16_t field_width;
187
188 field_width = z_shell_strlen(cmd->syntax) + z_shell_strlen(cmd_sep);
189
190 z_shell_fprintf(sh, SHELL_NORMAL, "%s%s", cmd->syntax, cmd_sep);
191
192 formatted_text_print(sh, cmd->help, field_width, false);
193 }
194
z_shell_help_request(const char * str)195 bool z_shell_help_request(const char *str)
196 {
197 if (!IS_ENABLED(CONFIG_SHELL_HELP_OPT_PARSE)) {
198 return false;
199 }
200
201 if (!strcmp(str, "-h") || !strcmp(str, "--help")) {
202 return true;
203 }
204
205 return false;
206 }
207