shell: creating new module for help functionality

1. Created new shell module: shell_help.
2. Simplified command handlers with new shell print macros.
3. Removed help functions from command handlers.

Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
Jakub Rzeszutko 2018-11-26 17:09:56 +01:00 committed by Carles Cufí
commit 3064ca4f2f
27 changed files with 686 additions and 956 deletions

View file

@ -216,8 +216,6 @@ static int cmd_test(const struct shell *shell, size_t argc, char *argv[])
return 0;
}
#define HELP_NONE "[none]"
SHELL_CREATE_STATIC_SUBCMD_SET(flash_cmds) {
SHELL_CMD(erase, NULL, "<page address> <size>", cmd_erase),
SHELL_CMD(read, NULL, "<address> <Dword count>", cmd_read),
@ -228,22 +226,9 @@ SHELL_CREATE_STATIC_SUBCMD_SET(flash_cmds) {
static int cmd_flash(const struct shell *shell, size_t argc, char **argv)
{
int err;
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
return 1;
}
err = shell_cmd_precheck(shell, argc == 2);
if (err) {
return err;
}
error(shell, "%s:%s%s", argv[0], "unknown parameter: ", argv[1]);
error(shell, "%s:unknown parameter: %s", argv[0], argv[1]);
return -EINVAL;
}
SHELL_CMD_REGISTER(flash, &flash_cmds, "Flash shell commands",
cmd_flash);
SHELL_CMD_ARG_REGISTER(flash, &flash_cmds, "Flash shell commands",
cmd_flash, 2, 0);

View file

@ -119,14 +119,14 @@ struct shell_static_entry {
*/
#define SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, \
mandatory, optional) \
static const struct shell_static_entry UTIL_CAT(shell_, syntax) = \
static const struct shell_static_entry UTIL_CAT(_shell_, syntax) = \
SHELL_CMD_ARG(syntax, subcmd, help, handler, mandatory, optional); \
static const struct shell_cmd_entry UTIL_CAT(shell_cmd_, syntax) \
__attribute__ ((section("." \
STRINGIFY(UTIL_CAT(shell_root_cmd_, syntax))))) \
__attribute__((used)) = { \
.is_dynamic = false, \
.u.entry = &UTIL_CAT(shell_, syntax) \
.u.entry = &UTIL_CAT(_shell_, syntax) \
}
/**
@ -141,14 +141,14 @@ struct shell_static_entry {
* @param[in] handler Pointer to a function handler.
*/
#define SHELL_CMD_REGISTER(syntax, subcmd, help, handler) \
static const struct shell_static_entry UTIL_CAT(shell_, syntax) = \
static const struct shell_static_entry UTIL_CAT(_shell_, syntax) = \
SHELL_CMD(syntax, subcmd, help, handler); \
static const struct shell_cmd_entry UTIL_CAT(shell_cmd_, syntax) \
__attribute__ ((section("." \
STRINGIFY(UTIL_CAT(shell_root_cmd_, syntax))))) \
__attribute__((used)) = { \
.is_dynamic = false, \
.u.entry = &UTIL_CAT(shell_, syntax) \
.u.entry = &UTIL_CAT(_shell_, syntax) \
}
/**
@ -440,6 +440,8 @@ struct shell {
k_thread_stack_t *stack;
};
extern void shell_print_stream(const void *user_ctx, const char *data,
size_t data_len);
/**
* @brief Macro for defining a shell instance.
*
@ -614,16 +616,6 @@ void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
*/
void shell_process(const struct shell *shell);
/**
* @brief Prints the current command help.
*
* Function will print a help string with the currently entered command and
* its subcommands (if exist).
*
* @param[in] shell Pointer to the shell instance.
*/
void shell_help_print(const struct shell *shell);
/**
* @brief Change displayed shell prompt.
*
@ -636,30 +628,14 @@ void shell_help_print(const struct shell *shell);
int shell_prompt_change(const struct shell *shell, char *prompt);
/**
* @brief Prints help if requested and prints error message on wrong argument
* count.
* Optionally, printing help on wrong argument count can be enabled.
* @brief Prints the current command help.
*
* Function will print a help string with: the currently entered command
* and subcommands (if they exist).
*
* @param[in] shell Pointer to the shell instance.
* @param[in] arg_cnt_ok Flag indicating valid number of arguments.
*
* @return 0 if check passed
* @return 1 if help was requested
* @return -EINVAL if wrong argument count
*/
int shell_cmd_precheck(const struct shell *shell,
bool arg_cnt_ok);
/**
* @internal @brief This function shall not be used directly, it is required by
* the fprintf module.
*
* @param[in] p_user_ctx Pointer to the context for the shell instance.
* @param[in] p_data Pointer to the data buffer.
* @param[in] data_len Data buffer size.
*/
void shell_print_stream(const void *user_ctx, const char *data,
size_t data_len);
void shell_help_print(const struct shell *shell);
/** @brief Execute command.
*

View file

@ -76,7 +76,6 @@ void shell_fprintf_fmt(const struct shell_fprintf *sh_fprintf,
*/
void shell_fprintf_buffer_flush(const struct shell_fprintf *sh_fprintf);
#ifdef __cplusplus
}
#endif

View file

@ -3,7 +3,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
@ -241,15 +240,11 @@ static int cmd_flash(const struct shell *shell, size_t argc, char **argv)
static int cmd_write_block_size(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int err = shell_cmd_precheck(shell, argc == 1);
int err = check_flash_device(shell);
if (err) {
return err;
}
err = check_flash_device(shell);
if (!err) {
PR_SHELL(shell, "%d\n",
flash_get_write_block_size(flash_device));
@ -260,19 +255,13 @@ static int cmd_write_block_size(const struct shell *shell, size_t argc,
static int cmd_read(const struct shell *shell, size_t argc, char **argv)
{
int err = shell_cmd_precheck(shell, argc == 3);
int err = check_flash_device(shell);
unsigned long int offset, len;
if (err) {
goto exit;
}
err = check_flash_device(shell);
if (err) {
goto exit;
}
if (parse_ul(argv[1], &offset) || parse_ul(argv[2], &len)) {
PR_ERROR(shell, "Invalid arguments.\n");
err = -EINVAL;
@ -287,18 +276,14 @@ exit:
static int cmd_erase(const struct shell *shell, size_t argc, char **argv)
{
int err = shell_cmd_precheck(shell, argc == 3);
unsigned long int offset, size;
int err = check_flash_device(shell);
unsigned long int offset;
unsigned long int size;
if (err) {
goto exit;
}
err = check_flash_device(shell);
if (err) {
goto exit;
}
if (parse_ul(argv[1], &offset) || parse_ul(argv[2], &size)) {
PR_ERROR(shell, "Invalid arguments.\n");
err = -EINVAL;
@ -312,15 +297,11 @@ exit:
static int cmd_write(const struct shell *shell, size_t argc, char **argv)
{
int err = shell_cmd_precheck(shell, argc > 2);
unsigned long int i, offset;
u8_t buf[ARGC_MAX];
if (err) {
goto exit;
}
int err = check_flash_device(shell);
err = check_flash_device(shell);
if (err) {
goto exit;
}
@ -365,15 +346,11 @@ exit:
static int cmd_page_count(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argv);
ARG_UNUSED(argc);
int err = shell_cmd_precheck(shell, argc == 1);
int err = check_flash_device(shell);
size_t page_count;
if (err) {
return err;
}
err = check_flash_device(shell);
if (!err) {
page_count = flash_get_page_count(flash_device);
PR_SHELL(shell, "Flash device contains %lu pages.\n",
@ -409,15 +386,11 @@ static bool page_layout_cb(const struct flash_pages_info *info, void *datav)
static int cmd_page_layout(const struct shell *shell, size_t argc, char **argv)
{
int err = shell_cmd_precheck(shell, argc <= 3);
unsigned long int start_page, end_page;
struct page_layout_data data;
if (err) {
return err;
}
int err = check_flash_device(shell);
err = check_flash_device(shell);
if (err) {
goto bail;
}
@ -463,12 +436,6 @@ static int cmd_page_read(const struct shell *shell, size_t argc, char **argv)
struct flash_pages_info info;
int ret;
ret = shell_cmd_precheck(shell, argc == 3 || argc == 4);
if (ret) {
return ret;
}
ret = check_flash_device(shell);
if (ret) {
return ret;
@ -512,11 +479,6 @@ static int cmd_page_erase(const struct shell *shell, size_t argc, char **argv)
return ret;
}
ret = shell_cmd_precheck(shell, argc == 2 || argc == 3);
if (ret) {
return ret;
}
if (parse_ul(argv[1], &page)) {
ret = -EINVAL;
goto bail;
@ -563,15 +525,11 @@ static int cmd_page_write(const struct shell *shell, size_t argc, char **argv)
return ret;
}
ret = shell_cmd_precheck(shell, argc > 2);
if (ret) {
return ret;
}
if (argc < 2 || parse_ul(argv[1], &page) || parse_ul(argv[2], &off)) {
if (parse_ul(argv[1], &page) || parse_ul(argv[2], &off)) {
ret = -EINVAL;
goto bail;
}
argc -= 3;
argv += 3;
for (i = 0; i < argc; i++) {
@ -601,12 +559,6 @@ static int cmd_set_dev(const struct shell *shell, size_t argc, char **argv)
{
struct device *dev;
const char *name;
int ret;
ret = shell_cmd_precheck(shell, argc == 2);
if (ret) {
return ret;
}
name = argv[1];
@ -642,19 +594,21 @@ void main(void)
SHELL_CREATE_STATIC_SUBCMD_SET(sub_flash)
{
/* Alphabetically sorted to ensure correct Tab autocompletion. */
SHELL_CMD(erase, NULL, ERASE_HELP, cmd_erase),
SHELL_CMD_ARG(erase, NULL, ERASE_HELP, cmd_erase, 3, 0),
#ifdef CONFIG_FLASH_PAGE_LAYOUT
SHELL_CMD(page_count, NULL, PAGE_COUNT_HELP, cmd_page_count),
SHELL_CMD(page_errase, NULL, PAGE_ERASE_HELP, cmd_page_erase),
SHELL_CMD(page_layout, NULL, PAGE_LAYOUT_HELP, cmd_page_layout),
SHELL_CMD(page_read, NULL, PAGE_READ_HELP, cmd_page_read),
SHELL_CMD(page_write, NULL, PAGE_WRITE_HELP, cmd_page_write),
SHELL_CMD_ARG(page_count, NULL, PAGE_COUNT_HELP, cmd_page_count, 1, 0),
SHELL_CMD_ARG(page_erase, NULL, PAGE_ERASE_HELP, cmd_page_erase, 2, 1),
SHELL_CMD_ARG(page_layout, NULL, PAGE_LAYOUT_HELP,
cmd_page_layout, 1, 2),
SHELL_CMD_ARG(page_read, NULL, PAGE_READ_HELP, cmd_page_read, 3, 1),
SHELL_CMD_ARG(page_write, NULL, PAGE_WRITE_HELP,
cmd_page_write, 3, 255),
#endif
SHELL_CMD(read, NULL, READ_HELP, cmd_read),
SHELL_CMD(set_device, NULL, SET_DEV_HELP, cmd_set_dev),
SHELL_CMD(write, NULL, WRITE_HELP, cmd_write),
SHELL_CMD(write_block_size, NULL, WRITE_BLOCK_SIZE_HELP,
cmd_write_block_size),
SHELL_CMD_ARG(read, NULL, READ_HELP, cmd_read, 3, 0),
SHELL_CMD_ARG(set_device, NULL, SET_DEV_HELP, cmd_set_dev, 2, 0),
SHELL_CMD_ARG(write, NULL, WRITE_HELP, cmd_write, 3, 255),
SHELL_CMD_ARG(write_block_size, NULL, WRITE_BLOCK_SIZE_HELP,
cmd_write_block_size, 1, 0),
SHELL_SUBCMD_SET_END /* Array terminated. */
};

View file

@ -134,18 +134,6 @@ static int cmd_mtest(const struct shell *shell, size_t argc, char *argv[])
{
u32_t *mem;
u32_t val;
int err;
if (argc > 3) {
PR_ERROR(shell, "mtest accepts 1 (Read) or 2 (Write)"
"parameters\n");
return -EINVAL;
}
err = shell_cmd_precheck(shell, (argc >= 2) && (argc <= 3));
if (err) {
return err;
}
val = (u32_t)strtol(argv[1], NULL, 16);
mem = (u32_t *) val;
@ -166,7 +154,7 @@ void main(void)
SHELL_CREATE_STATIC_SUBCMD_SET(sub_mpu)
{
SHELL_CMD(mtest, NULL, MTEST_CMD_HELP, cmd_mtest),
SHELL_CMD_ARG(mtest, NULL, MTEST_CMD_HELP, cmd_mtest, 2, 1),
SHELL_CMD(read, NULL, READ_CMD_HELP, cmd_read),
SHELL_CMD(run, NULL, RUN_CMD_HELP, cmd_run),
#if defined(CONFIG_SOC_FLASH_MCUX)

View file

@ -19,24 +19,6 @@ static u8_t dynamic_cmd_cnt;
typedef int cmp_t(const void *, const void *);
extern void qsort(void *a, size_t n, size_t es, cmp_t *cmp);
static int cmd_dynamic(const struct shell *shell, size_t argc, char **argv)
{
if ((argc == 1)) {
shell_help_print(shell);
return 0;
}
if (argc > 2) {
shell_fprintf(shell, SHELL_ERROR,
"%s: bad parameter count\r\n", argv[0]);
} else {
shell_fprintf(shell, SHELL_ERROR,
"%s: please specify subcommand\r\n", argv[0]);
}
return -ENOEXEC;
}
/* function required by qsort */
static int string_cmp(const void *p_a, const void *p_b)
{
@ -46,40 +28,35 @@ static int string_cmp(const void *p_a, const void *p_b)
static int cmd_dynamic_add(const struct shell *shell,
size_t argc, char **argv)
{
u8_t idx;
u16_t cmd_len;
u8_t idx;
if (argc != 2) {
shell_fprintf(shell, SHELL_ERROR,
"%s: bad parameter count\r\n", argv[0]);
return -ENOEXEC;
}
ARG_UNUSED(argc);
if (dynamic_cmd_cnt >= MAX_CMD_CNT) {
shell_fprintf(shell, SHELL_ERROR, "command limit reached\r\n");
shell_error(shell, "command limit reached");
return -ENOEXEC;
}
cmd_len = strlen(argv[1]);
if (cmd_len >= MAX_CMD_LEN) {
shell_fprintf(shell, SHELL_ERROR, "too long command\r\n");
shell_error(shell, "too long command");
return -ENOEXEC;
}
for (idx = 0U; idx < cmd_len; idx++) {
if (!isalnum((int)(argv[1][idx]))) {
shell_fprintf(shell, SHELL_ERROR,
shell_error(shell,
"bad command name - please use only"
" alphanumerical characters\r\n");
" alphanumerical characters");
return -ENOEXEC;
}
}
for (idx = 0U; idx < MAX_CMD_CNT; idx++) {
if (!strcmp(dynamic_cmd_buffer[idx], argv[1])) {
shell_fprintf(shell, SHELL_ERROR,
"duplicated command\r\n");
shell_error(shell, "duplicated command");
return -ENOEXEC;
}
}
@ -89,32 +66,7 @@ static int cmd_dynamic_add(const struct shell *shell,
qsort(dynamic_cmd_buffer, dynamic_cmd_cnt,
sizeof(dynamic_cmd_buffer[0]), string_cmp);
shell_fprintf(shell, SHELL_NORMAL, "command added successfully\r\n");
return 0;
}
static int cmd_dynamic_show(const struct shell *shell,
size_t argc, char **argv)
{
if (argc != 1) {
shell_fprintf(shell, SHELL_ERROR,
"%s: bad parameter count\r\n", argv[0]);
return -ENOEXEC;
}
if (dynamic_cmd_cnt == 0) {
shell_fprintf(shell, SHELL_WARNING,
"Please add some commands first.\r\n");
return -ENOEXEC;
}
shell_fprintf(shell, SHELL_NORMAL, "Dynamic command list:\r\n");
for (u8_t i = 0; i < dynamic_cmd_cnt; i++) {
shell_fprintf(shell, SHELL_NORMAL,
"[%3d] %s\r\n", i, dynamic_cmd_buffer[i]);
}
shell_print(shell, "command added successfully");
return 0;
}
@ -122,22 +74,17 @@ static int cmd_dynamic_show(const struct shell *shell,
static int cmd_dynamic_execute(const struct shell *shell,
size_t argc, char **argv)
{
if (argc != 2) {
shell_fprintf(shell, SHELL_ERROR,
"%s: bad parameter count\r\n", argv[0]);
return -ENOEXEC;
}
ARG_UNUSED(argc);
ARG_UNUSED(argv);
for (u8_t idx = 0; idx < dynamic_cmd_cnt; idx++) {
if (!strcmp(dynamic_cmd_buffer[idx], argv[1])) {
shell_fprintf(shell, SHELL_NORMAL,
"dynamic command: %s\r\n", argv[1]);
shell_print(shell, "dynamic command: %s", argv[1]);
return 0;
}
}
shell_fprintf(shell, SHELL_ERROR,
"%s: uknown parameter: %s\r\n", argv[0], argv[1]);
shell_error(shell, "%s: uknown parameter: %s", argv[0], argv[1]);
return -ENOEXEC;
}
@ -145,16 +92,8 @@ static int cmd_dynamic_execute(const struct shell *shell,
static int cmd_dynamic_remove(const struct shell *shell, size_t argc,
char **argv)
{
if (argc == 1) {
shell_help_print(shell);
return 0;
}
if (argc != 2) {
shell_fprintf(shell, SHELL_ERROR,
"%s: bad parameter count\r\n", argv[0]);
return -ENOEXEC;
}
ARG_UNUSED(argc);
ARG_UNUSED(argv);
for (u8_t idx = 0; idx < dynamic_cmd_cnt; idx++) {
if (!strcmp(dynamic_cmd_buffer[idx], argv[1])) {
@ -168,17 +107,35 @@ static int cmd_dynamic_remove(const struct shell *shell, size_t argc,
}
--dynamic_cmd_cnt;
shell_fprintf(shell, SHELL_NORMAL,
"command removed successfully\r\n");
shell_print(shell, "command removed successfully");
return 0;
}
}
shell_fprintf(shell, SHELL_ERROR,
"did not find command: %s\r\n", argv[1]);
shell_error(shell, "did not find command: %s", argv[1]);
return -ENOEXEC;
}
static int cmd_dynamic_show(const struct shell *shell,
size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
if (dynamic_cmd_cnt == 0) {
shell_warn(shell, "Please add some commands first.");
return -ENOEXEC;
}
shell_print(shell, "Dynamic command list:");
for (u8_t i = 0; i < dynamic_cmd_cnt; i++) {
shell_print(shell, "[%3d] %s", i, dynamic_cmd_buffer[i]);
}
return 0;
}
/* dynamic command creation */
static void dynamic_cmd_get(size_t idx, struct shell_static_entry *entry)
{
@ -201,21 +158,21 @@ static void dynamic_cmd_get(size_t idx, struct shell_static_entry *entry)
SHELL_CREATE_DYNAMIC_CMD(m_sub_dynamic_set, dynamic_cmd_get);
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_dynamic)
{
SHELL_CMD(add, NULL,
SHELL_CMD_ARG(add, NULL,
"Add a new dynamic command.\nExample usage: [ dynamic add test "
"] will add a dynamic command 'test'.\nIn this example, command"
" name length is limited to 32 chars. You can add up to 20"
" commands. Commands are automatically sorted to ensure correct"
" shell completion.",
cmd_dynamic_add),
SHELL_CMD(execute, &m_sub_dynamic_set,
"Execute a command.", cmd_dynamic_execute),
SHELL_CMD(remove, &m_sub_dynamic_set,
"Remove a command.", cmd_dynamic_remove),
SHELL_CMD(show, NULL,
"Show all added dynamic commands.", cmd_dynamic_show),
cmd_dynamic_add, 2, 0),
SHELL_CMD_ARG(execute, &m_sub_dynamic_set,
"Execute a command.", cmd_dynamic_execute, 2, 0),
SHELL_CMD_ARG(remove, &m_sub_dynamic_set,
"Remove a command.", cmd_dynamic_remove, 2, 0),
SHELL_CMD_ARG(show, NULL,
"Show all added dynamic commands.", cmd_dynamic_show, 1, 0),
SHELL_SUBCMD_SET_END
};
SHELL_CMD_REGISTER(dynamic, &m_sub_dynamic,
"Demonstrate dynamic command usage.", cmd_dynamic);
"Demonstrate dynamic command usage.", NULL);

View file

@ -31,29 +31,22 @@ static int cmd_log_test_start(const struct shell *shell, size_t argc,
{
ARG_UNUSED(argv);
int err = shell_cmd_precheck(shell, argc == 1);
if (err) {
return err;
}
k_timer_start(&log_timer, period, period);
shell_fprintf(shell, SHELL_NORMAL, "Log test started\n");
shell_print(shell, "Log test started\n");
return 0;
}
static int cmd_log_test_start_demo(const struct shell *shell, size_t argc,
char **argv)
{
cmd_log_test_start(shell, argc, argv, 200);
return 0;
return cmd_log_test_start(shell, argc, argv, 200);
}
static int cmd_log_test_start_flood(const struct shell *shell, size_t argc,
char **argv)
{
cmd_log_test_start(shell, argc, argv, 10);
return 0;
return cmd_log_test_start(shell, argc, argv, 10);
}
static int cmd_log_test_stop(const struct shell *shell, size_t argc,
@ -62,33 +55,28 @@ static int cmd_log_test_stop(const struct shell *shell, size_t argc,
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int err = shell_cmd_precheck(shell, argc == 1);
if (err) {
return err;
}
k_timer_stop(&log_timer);
shell_fprintf(shell, SHELL_NORMAL, "Log test stopped\n");
shell_print(shell, "Log test stopped");
return 0;
}
SHELL_CREATE_STATIC_SUBCMD_SET(sub_log_test_start)
{
/* Alphabetically sorted. */
SHELL_CMD(demo, NULL,
SHELL_CMD_ARG(demo, NULL,
"Start log timer which generates log message every 200ms.",
cmd_log_test_start_demo),
SHELL_CMD(flood, NULL,
cmd_log_test_start_demo, 1, 0),
SHELL_CMD_ARG(flood, NULL,
"Start log timer which generates log message every 10ms.",
cmd_log_test_start_flood),
cmd_log_test_start_flood, 1, 0),
SHELL_SUBCMD_SET_END /* Array terminated. */
};
SHELL_CREATE_STATIC_SUBCMD_SET(sub_log_test)
{
/* Alphabetically sorted. */
SHELL_CMD(start, &sub_log_test_start, "Start log test", NULL),
SHELL_CMD(stop, NULL, "Stop log test.", cmd_log_test_stop),
SHELL_CMD_ARG(start, &sub_log_test_start, "Start log test", NULL, 2, 0),
SHELL_CMD_ARG(stop, NULL, "Stop log test.", cmd_log_test_stop, 1, 0),
SHELL_SUBCMD_SET_END /* Array terminated. */
};
@ -99,20 +87,18 @@ static int cmd_demo_ping(const struct shell *shell, size_t argc, char **argv)
ARG_UNUSED(argc);
ARG_UNUSED(argv);
shell_fprintf(shell, SHELL_NORMAL, "pong\n");
shell_print(shell, "pong");
return 0;
}
static int cmd_demo_params(const struct shell *shell, size_t argc, char **argv)
{
int cnt;
shell_fprintf(shell, SHELL_NORMAL, "argc = %d\n", argc);
for (cnt = 0; cnt < argc; cnt++) {
shell_fprintf(shell, SHELL_NORMAL,
" argv[%d] = %s\n", cnt, argv[cnt]);
shell_print(shell, "argc = %d", argc);
for (size_t cnt = 0; cnt < argc; cnt++) {
shell_print(shell, " argv[%d] = %s", cnt, argv[cnt]);
}
return 0;
}
@ -121,8 +107,8 @@ static int cmd_version(const struct shell *shell, size_t argc, char **argv)
ARG_UNUSED(argc);
ARG_UNUSED(argv);
shell_fprintf(shell, SHELL_NORMAL,
"Zephyr version %s\n", KERNEL_VERSION_STRING);
shell_print(shell, "Zephyr version %s", KERNEL_VERSION_STRING);
return 0;
}
@ -135,8 +121,7 @@ SHELL_CREATE_STATIC_SUBCMD_SET(sub_demo)
};
SHELL_CMD_REGISTER(demo, &sub_demo, "Demo commands", NULL);
SHELL_CMD_REGISTER(version, NULL, "Show kernel version", cmd_version);
SHELL_CMD_ARG_REGISTER(version, NULL, "Show kernel version", cmd_version, 1, 0);
void main(void)
{

View file

@ -1574,12 +1574,6 @@ static int cmd_provision(const struct shell *shell, size_t argc, char *argv[])
int cmd_timeout(const struct shell *shell, size_t argc, char *argv[])
{
s32_t timeout;
int err;
err = shell_cmd_precheck(shell, (argc >= 1));
if (err) {
return err;
}
if (argc < 2) {
timeout = bt_mesh_cfg_cli_timeout_get();
@ -1619,11 +1613,6 @@ static int cmd_fault_get(const struct shell *shell, size_t argc, char *argv[])
u16_t cid;
int err;
err = shell_cmd_precheck(shell, (argc == 1));
if (err) {
return err;
}
cid = strtoul(argv[1], NULL, 0);
fault_count = sizeof(faults);
@ -2043,7 +2032,7 @@ static int cmd_mesh(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -552,7 +552,7 @@ static int cmd_br(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -614,7 +614,7 @@ static int cmd_scan(const struct shell *shell, size_t argc, char *argv[])
dups = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE;
} else {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
}
@ -628,7 +628,7 @@ static int cmd_scan(const struct shell *shell, size_t argc, char *argv[])
return cmd_passive_scan_on(shell, dups);
} else {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
@ -747,7 +747,7 @@ static int cmd_disconnect(const struct shell *shell, size_t argc, char *argv[])
if (argc < 3) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
@ -796,7 +796,7 @@ static int cmd_auto_conn(const struct shell *shell, size_t argc, char *argv[])
return bt_le_set_auto_conn(&addr, NULL);
} else {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
@ -823,7 +823,7 @@ static int cmd_directed_adv(const struct shell *shell,
if (strcmp(argv[3], "low")) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
@ -1015,7 +1015,7 @@ static int cmd_bondable(const struct shell *shell, size_t argc, char *argv[])
bt_set_bondable(false);
} else {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
@ -1209,7 +1209,7 @@ static int cmd_auth(const struct shell *shell, size_t argc, char *argv[])
bt_conn_auth_cb_register(NULL);
} else {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}
@ -1390,7 +1390,7 @@ static int cmd_bt(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -797,7 +797,7 @@ static int cmd_gatt(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -417,7 +417,7 @@ static int cmd_l2cap(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -245,7 +245,7 @@ static int cmd_rfcomm(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -136,7 +136,7 @@ static int cmd_ticker(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
/* shell returns 1 when help is printed */
return 1;
}

View file

@ -166,11 +166,6 @@ static int cmd_trunc(const struct shell *shell, size_t argc, char **argv)
int length;
int err;
err = shell_cmd_precheck(shell, (argc >= 2));
if (err) {
return err;
}
if (argv[1][0] == '/') {
strncpy(path, argv[1], sizeof(path) - 1);
path[MAX_PATH_LEN - 1] = '\0';
@ -212,11 +207,6 @@ static int cmd_mkdir(const struct shell *shell, size_t argc, char **argv)
int err;
char path[MAX_PATH_LEN];
err = shell_cmd_precheck(shell, (argc == 2));
if (err) {
return err;
}
create_abs_path(argv[1], path, sizeof(path));
err = fs_mkdir(path);
@ -234,11 +224,6 @@ static int cmd_rm(const struct shell *shell, size_t argc, char **argv)
int err;
char path[MAX_PATH_LEN];
err = shell_cmd_precheck(shell, (argc == 2));
if (err) {
return err;
}
create_abs_path(argv[1], path, sizeof(path));
err = fs_unlink(path);
@ -260,11 +245,6 @@ static int cmd_read(const struct shell *shell, size_t argc, char **argv)
off_t offset;
int err;
err = shell_cmd_precheck(shell, (argc >= 2));
if (err) {
return err;
}
create_abs_path(argv[1], path, sizeof(path));
if (argc > 2) {
@ -356,11 +336,6 @@ static int cmd_write(const struct shell *shell, size_t argc, char **argv)
off_t offset = -1;
int err;
err = shell_cmd_precheck(shell, (argc >= 3));
if (err) {
return err;
}
create_abs_path(argv[1], path, sizeof(path));
if (!strcmp(argv[2], "-o")) {
@ -439,11 +414,6 @@ static int cmd_mount_fat(const struct shell *shell, size_t argc, char **argv)
char *mntpt;
int res;
res = shell_cmd_precheck(shell, (argc == 2));
if (res) {
return res;
}
mntpt = mntpt_prepare(argv[1]);
if (!mntpt) {
shell_fprintf(shell, SHELL_ERROR,
@ -473,11 +443,6 @@ static int cmd_mount_nffs(const struct shell *shell, size_t argc, char **argv)
char *mntpt;
int res;
res = shell_cmd_precheck(shell, (argc == 2));
if (res) {
return res;
}
mntpt = mntpt_prepare(argv[1]);
if (!mntpt) {
shell_fprintf(shell, SHELL_ERROR,
@ -512,13 +477,15 @@ SHELL_CREATE_STATIC_SUBCMD_SET(sub_fs_mount)
{
#if defined(CONFIG_FAT_FILESYSTEM_ELM)
SHELL_CMD(fat, NULL,
"Mount fatfs. fs mount fat <mount-point>", cmd_mount_fat),
SHELL_CMD_ARG(fat, NULL,
"Mount fatfs. fs mount fat <mount-point>",
cmd_mount_fat, 2, 0),
#endif
#if defined(CONFIG_FILE_SYSTEM_NFFS)
SHELL_CMD(nffs, NULL,
"Mount nffs. fs mount nffs <mount-point>", cmd_mount_nffs),
SHELL_CMD_ARG(nffs, NULL,
"Mount nffs. fs mount nffs <mount-point>",
cmd_mount_nffs, 2, 0),
#endif
SHELL_SUBCMD_SET_END
@ -530,16 +497,16 @@ SHELL_CREATE_STATIC_SUBCMD_SET(sub_fs)
SHELL_CMD(cd, NULL,
"Change working directory", cmd_cd),
SHELL_CMD(ls, NULL, "List files in current directory", cmd_ls),
SHELL_CMD(mkdir, NULL, "Create directory", cmd_mkdir),
SHELL_CMD_ARG(mkdir, NULL, "Create directory", cmd_mkdir, 2, 0),
#if defined(CONFIG_FILE_SYSTEM_NFFS) || defined(CONFIG_FAT_FILESYSTEM_ELM)
SHELL_CMD(mount, &sub_fs_mount,
"<fs e.g: fat/nffs> <mount-point>", NULL),
#endif
SHELL_CMD(pwd, NULL, "Print current working directory", cmd_pwd),
SHELL_CMD(read, NULL, "Read from file", cmd_read),
SHELL_CMD(rm, NULL, "Remove file", cmd_rm),
SHELL_CMD(trunc, NULL, "Truncate file", cmd_trunc),
SHELL_CMD(write, NULL, "Write file", cmd_write),
SHELL_CMD_ARG(read, NULL, "Read from file", cmd_read, 2, 255),
SHELL_CMD_ARG(rm, NULL, "Remove file", cmd_rm, 2, 0),
SHELL_CMD_ARG(trunc, NULL, "Truncate file", cmd_trunc, 2, 255),
SHELL_CMD_ARG(write, NULL, "Write file", cmd_write, 3, 255),
SHELL_SUBCMD_SET_END
};

View file

@ -57,8 +57,7 @@ static bool shell_state_precheck(const struct shell *shell)
{
if (shell->log_backend->control_block->state
== SHELL_LOG_BACKEND_UNINIT) {
shell_fprintf(shell, SHELL_ERROR,
"Shell log backend not initialized.\r\n");
shell_error(shell, "Shell log backend not initialized.");
return false;
}
@ -82,8 +81,7 @@ static int shell_backend_cmd_execute(const struct shell *shell,
if (backend) {
func(shell, backend, argc, argv);
} else {
shell_fprintf(shell, SHELL_ERROR,
"Invalid backend: %s\r\n", name);
shell_error(shell, "Invalid backend: %s", name);
return -ENOEXEC;
}
return 0;
@ -101,7 +99,7 @@ static int log_status(const struct shell *shell,
if (!log_backend_is_active(backend)) {
shell_fprintf(shell, SHELL_ERROR, "Logs are halted!\r\n");
shell_warn(shell, "Logs are halted!");
}
shell_fprintf(shell, SHELL_NORMAL, "%-40s | current | built-in \r\n",
@ -168,7 +166,7 @@ static void filters_set(const struct shell *shell,
int cnt = all ? log_sources_count() : argc;
if (!backend->cb->active) {
shell_fprintf(shell, SHELL_WARNING, "Backend not active.\r\n");
shell_warn(shell, "Backend not active.");
}
for (i = 0; i < cnt; i++) {
@ -185,13 +183,11 @@ static void filters_set(const struct shell *shell,
log_source_name_get(
CONFIG_LOG_DOMAIN_ID, i) :
argv[i];
shell_fprintf(shell, SHELL_WARNING,
"%s: level set to %s.\r\n",
shell_warn(shell, "%s: level set to %s.",
name, severity_lvls[set_lvl]);
}
} else {
shell_fprintf(shell, SHELL_ERROR,
"%s: unknown source name.\r\n", argv[i]);
shell_error(shell, "%s: unknown source name.", argv[i]);
}
}
}
@ -214,17 +210,11 @@ static int log_enable(const struct shell *shell,
char **argv)
{
int severity_level;
int err = shell_cmd_precheck(shell, (argc > 1));
if (err) {
return err;
}
severity_level = severity_level_get(argv[1]);
if (severity_level < 0) {
shell_fprintf(shell, SHELL_ERROR, "Invalid severity: %s\r\n",
argv[1]);
shell_error(shell, "Invalid severity: %s", argv[1]);
return -ENOEXEC;
}
@ -254,12 +244,6 @@ static int log_disable(const struct shell *shell,
size_t argc,
char **argv)
{
int err = shell_cmd_precheck(shell, (argc > 1));
if (err) {
return err;
}
filters_set(shell, backend, argc - 1, &argv[1], LOG_LEVEL_NONE);
return 0;
}
@ -361,11 +345,6 @@ static int cmd_log_backends_list(const struct shell *shell,
size_t argc, char **argv)
{
int backend_count;
int err = shell_cmd_precheck(shell, (argc == 1));
if (err) {
return err;
}
backend_count = log_backend_count_get();
@ -387,15 +366,15 @@ static int cmd_log_backends_list(const struct shell *shell,
SHELL_CREATE_STATIC_SUBCMD_SET(sub_log_backend)
{
SHELL_CMD(disable, &dsub_module_name,
SHELL_CMD_ARG(disable, &dsub_module_name,
"'log disable <module_0> .. <module_n>' disables logs in "
"specified modules (all if no modules specified).",
cmd_log_backend_disable),
SHELL_CMD(enable, &dsub_severity_lvl,
cmd_log_backend_disable, 2, 255),
SHELL_CMD_ARG(enable, &dsub_severity_lvl,
"'log enable <level> <module_0> ... <module_n>' enables logs"
" up to given level in specified modules (all if no modules "
"specified).",
cmd_log_backend_enable),
cmd_log_backend_enable, 2, 255),
SHELL_CMD(go, NULL, "Resume logging", cmd_log_backend_go),
SHELL_CMD(halt, NULL, "Halt logging", cmd_log_backend_halt),
SHELL_CMD(status, NULL, "Logger status", cmd_log_backend_status),
@ -423,33 +402,21 @@ SHELL_CREATE_STATIC_SUBCMD_SET(sub_log_stat)
{
SHELL_CMD(backend, &dsub_backend_name_dynamic,
"Logger backends commands.", NULL),
SHELL_CMD(disable, &dsub_module_name,
SHELL_CMD_ARG(disable, &dsub_module_name,
"'log disable <module_0> .. <module_n>' disables logs in specified "
"modules (all if no modules specified).",
cmd_log_self_disable),
SHELL_CMD(enable, &dsub_severity_lvl,
cmd_log_self_disable, 2, 255),
SHELL_CMD_ARG(enable, &dsub_severity_lvl,
"'log enable <level> <module_0> ... <module_n>' enables logs up to"
" given level in specified modules (all if no modules specified).",
cmd_log_self_enable),
cmd_log_self_enable, 2, 255),
SHELL_CMD(go, NULL, "Resume logging", cmd_log_self_go),
SHELL_CMD(halt, NULL, "Halt logging", cmd_log_self_halt),
SHELL_CMD(list_backends, NULL, "Lists logger backends.",
cmd_log_backends_list),
SHELL_CMD_ARG(list_backends, NULL, "Lists logger backends.",
cmd_log_backends_list, 1, 0),
SHELL_CMD(status, NULL, "Logger status", cmd_log_self_status),
SHELL_SUBCMD_SET_END
};
static int cmd_log(const struct shell *shell, size_t argc, char **argv)
{
if (argc == 1) {
shell_help_print(shell);
return 0;
}
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\r\n",
argv[0], " unknown parameter: ", argv[1]);
return -ENOEXEC;
}
SHELL_CMD_REGISTER(log, &sub_log_stat, "Commands for controlling logger",
cmd_log);
NULL);

View file

@ -33,6 +33,11 @@ zephyr_sources_ifdef(
shell_rtt.c
)
zephyr_sources_ifdef(
CONFIG_SHELL_HELP
shell_help.c
)
zephyr_sources_ifdef(
CONFIG_SHELL_CMDS
shell_cmds.c

View file

@ -9,6 +9,7 @@
#include <stdlib.h>
#include <shell/shell.h>
#include <shell/shell_dummy.h>
#include "shell_help.h"
#include "shell_utils.h"
#include "shell_ops.h"
#include "shell_wildcard.h"
@ -42,26 +43,6 @@
static int shell_execute(const struct shell *shell);
extern const struct shell_cmd_entry __shell_root_cmds_start[0];
extern const struct shell_cmd_entry __shell_root_cmds_end[0];
static inline const struct shell_cmd_entry *shell_root_cmd_get(u32_t id)
{
return &__shell_root_cmds_start[id];
}
static inline u32_t shell_root_cmd_count(void)
{
return ((u8_t *)__shell_root_cmds_end -
(u8_t *)__shell_root_cmds_start)/
sizeof(struct shell_cmd_entry);
}
static inline void transport_buffer_flush(const struct shell *shell)
{
shell_fprintf_buffer_flush(shell->fprintf_ctx);
}
/* Function returns true if delete escape code shall be interpreted as
* backspace.
*/
@ -88,93 +69,33 @@ static void shell_cmd_buffer_clear(const struct shell *shell)
shell->ctx->cmd_buff_len = 0;
}
static void shell_pend_on_txdone(const struct shell *shell)
{
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_poll(&shell->ctx->events[SHELL_SIGNAL_TXDONE], 1, K_FOREVER);
k_poll_signal_reset(&shell->ctx->signals[SHELL_SIGNAL_TXDONE]);
} else {
/* Blocking wait in case of bare metal. */
while (!shell->ctx->internal.flags.tx_rdy) {
}
shell->ctx->internal.flags.tx_rdy = 0;
}
}
/* Function sends data stream to the shell instance. Each time before the
* shell_write function is called, it must be ensured that IO buffer of fprintf
* is flushed to avoid synchronization issues.
* For that purpose, use function transport_buffer_flush(shell)
*/
static void shell_write(const struct shell *shell, const void *data,
size_t length)
{
__ASSERT_NO_MSG(shell && data);
size_t offset = 0;
size_t tmp_cnt;
while (length) {
int err = shell->iface->api->write(shell->iface,
&((const u8_t *) data)[offset], length,
&tmp_cnt);
(void)err;
__ASSERT_NO_MSG(err == 0);
__ASSERT_NO_MSG(length >= tmp_cnt);
offset += tmp_cnt;
length -= tmp_cnt;
if (tmp_cnt == 0 &&
(shell->ctx->state != SHELL_STATE_PANIC_MODE_ACTIVE)) {
shell_pend_on_txdone(shell);
}
}
}
/* @brief Function shall be used to search commands.
/**
* @brief Prints error message on wrong argument count.
* Optionally, printing help on wrong argument count.
*
* It moves the pointer entry to command of static command structure. If the
* command cannot be found, the function will set entry to NULL.
* @param[in] shell Pointer to the shell instance.
* @param[in] arg_cnt_ok Flag indicating valid number of arguments.
*
* @param command Pointer to command which will be processed (no matter
* the root command).
* @param lvl Level of the requested command.
* @param idx Index of the requested command.
* @param entry Pointer which points to subcommand[idx] after function
* execution.
* @param st_entry Pointer to the structure where dynamic entry data can be
* stored.
* @return 0 if check passed
* @return 1 if help was requested
* @return -EINVAL if wrong argument count
*/
static void cmd_get(const struct shell_cmd_entry *command, size_t lvl,
size_t idx, const struct shell_static_entry **entry,
struct shell_static_entry *d_entry)
static int shell_cmd_precheck(const struct shell *shell,
bool arg_cnt_ok)
{
__ASSERT_NO_MSG(entry != NULL);
__ASSERT_NO_MSG(d_entry != NULL);
if (!arg_cnt_ok) {
shell_fprintf(shell, SHELL_ERROR,
"%s: wrong parameter count\n",
shell->ctx->active_cmd.syntax);
if (lvl == SHELL_CMD_ROOT_LVL) {
if (idx < shell_root_cmd_count()) {
const struct shell_cmd_entry *cmd;
cmd = shell_root_cmd_get(idx);
*entry = cmd->u.entry;
} else {
*entry = NULL;
}
return;
if (IS_ENABLED(CONFIG_SHELL_HELP_ON_WRONG_ARGUMENT_COUNT)) {
shell_help_print(shell);
}
if (command == NULL) {
*entry = NULL;
return;
return -EINVAL;
}
if (command->is_dynamic) {
command->u.dynamic_get(idx, d_entry);
*entry = (d_entry->syntax != NULL) ? d_entry : NULL;
} else {
*entry = (command->u.entry[idx].syntax != NULL) ?
&command->u.entry[idx] : NULL;
}
return 0;
}
static void vt100_color_set(const struct shell *shell,
@ -364,7 +285,7 @@ static const struct shell_static_entry *find_cmd(
size_t idx = 0;
do {
cmd_get(cmd, lvl, idx++, &entry, d_entry);
shell_cmd_get(cmd, lvl, idx++, &entry, d_entry);
if (entry && (strcmp(cmd_str, entry->syntax) == 0)) {
return entry;
}
@ -490,7 +411,7 @@ static void find_completion_candidates(const struct shell_static_entry *cmd,
*cnt = 0;
while (true) {
cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
shell_cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
idx, &candidate, &dynamic_entry);
if (!candidate) {
@ -526,7 +447,7 @@ static void autocomplete(const struct shell *shell,
/* shell->ctx->active_cmd can be safely used outside of command context
* to save stack
*/
cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
shell_cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
subcmd_idx, &match, &shell->ctx->active_cmd);
cmd_len = shell_strlen(match->syntax);
@ -589,7 +510,7 @@ static void tab_options_print(const struct shell *shell,
/* shell->ctx->active_cmd can be safely used outside of command
* context to save stack
*/
cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
shell_cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
idx, &match, &shell->ctx->active_cmd);
idx++;
@ -617,7 +538,8 @@ static u16_t common_beginning_find(const struct shell_static_entry *cmd,
u16_t common = UINT16_MAX;
size_t idx = first + 1;
cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
shell_cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
first, &match, &dynamic_entry);
*str = match->syntax;
@ -627,7 +549,7 @@ static u16_t common_beginning_find(const struct shell_static_entry *cmd,
const struct shell_static_entry *match2;
int curr_common;
cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
shell_cmd_get(cmd ? cmd->subcmd : NULL, cmd ? 1 : 0,
idx++, &match2, &dynamic_entry2);
if (match2 == NULL) {
@ -675,6 +597,7 @@ static void shell_tab_handle(const struct shell *shell)
size_t argc;
size_t cnt;
bool tab_possible = shell_tab_prepare(shell, &cmd, argv, &argc,
&arg_idx, &d_entry);
@ -949,22 +872,6 @@ static void cmd_trim(const struct shell *shell)
shell->ctx->cmd_buff_pos = shell->ctx->cmd_buff_len;
}
/* Function returning pointer to root command matching requested syntax. */
static const struct shell_cmd_entry *root_cmd_find(const char *syntax)
{
const size_t cmd_count = shell_root_cmd_count();
const struct shell_cmd_entry *cmd;
for (size_t cmd_idx = 0; cmd_idx < cmd_count; ++cmd_idx) {
cmd = shell_root_cmd_get(cmd_idx);
if (strcmp(syntax, cmd->u.entry->syntax) == 0) {
return cmd;
}
}
return NULL;
}
static int exec_cmd(const struct shell *shell, size_t argc, char **argv,
struct shell_static_entry help_entry)
{
@ -976,12 +883,14 @@ static int exec_cmd(const struct shell *shell, size_t argc, char **argv,
shell->ctx->active_cmd = help_entry;
}
shell_help_print(shell);
/* 1 is return value when shell prints help */
ret_val = 1;
} else {
shell_fprintf(shell, SHELL_ERROR,
SHELL_MSG_SPECIFY_SUBCOMMAND);
ret_val = -ENOEXEC;
}
ret_val = -ENOEXEC;
goto clear;
}
@ -1123,7 +1032,8 @@ static int shell_execute(const struct shell *shell)
}
}
cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_static_entry, &d_entry);
shell_cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_static_entry,
&d_entry);
if ((cmd_idx == 0) || (p_static_entry == NULL)) {
break;
@ -1482,13 +1392,6 @@ void shell_process(const struct shell *shell)
internal.value);
}
/* Function shall be only used by the fprintf module. */
void shell_print_stream(const void *user_ctx, const char *data,
size_t data_len)
{
shell_write((const struct shell *) user_ctx, data, data_len);
}
void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
const char *p_fmt, ...)
{
@ -1516,216 +1419,6 @@ void shell_fprintf(const struct shell *shell, enum shell_vt100_color color,
va_end(args);
}
/* 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 *shell, 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) {
shell_op_cursor_horiz_move(shell, terminal_offset);
}
/* Skipping whitespace. */
while (isspace((int) *(str + offset))) {
++offset;
}
while (true) {
size_t idx = 0;
length = shell_strlen(str) - offset;
if (length <=
shell->ctx->vt100_ctx.cons.terminal_wid - terminal_offset) {
for (idx = 0; idx < length; idx++) {
if (*(str + offset + idx) == '\n') {
transport_buffer_flush(shell);
shell_write(shell, str + offset, idx);
offset += idx + 1;
cursor_next_line_move(shell);
shell_op_cursor_horiz_move(shell,
terminal_offset);
break;
}
}
/* String will fit in one line. */
shell_raw_fprintf(shell->fprintf_ctx, str + offset);
break;
}
/* String is longer than terminal line so text needs to
* divide in the way to not divide words.
*/
length = shell->ctx->vt100_ctx.cons.terminal_wid
- terminal_offset;
while (true) {
/* Determining line break. */
if (isspace((int) (*(str + offset + idx)))) {
length = idx;
if (*(str + offset + idx) == '\n') {
break;
}
}
if ((idx + terminal_offset) >=
shell->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.
*/
transport_buffer_flush(shell);
shell_write(shell, str + offset, length);
offset += length;
/* Calculating text offset to ensure that next line will
* not begin with a space.
*/
while (isspace((int) (*(str + offset)))) {
++offset;
}
cursor_next_line_move(shell);
shell_op_cursor_horiz_move(shell, terminal_offset);
}
cursor_next_line_move(shell);
}
static void help_cmd_print(const struct shell *shell)
{
static const char cmd_sep[] = " - "; /* commands separator */
u16_t field_width = shell_strlen(shell->ctx->active_cmd.syntax) +
shell_strlen(cmd_sep);
shell_fprintf(shell, SHELL_NORMAL, "%s%s",
shell->ctx->active_cmd.syntax, cmd_sep);
formatted_text_print(shell, shell->ctx->active_cmd.help,
field_width, false);
}
static void help_item_print(const struct shell *shell, const char *item_name,
u16_t item_name_width, const char *item_help)
{
static const u8_t tabulator[] = " ";
const u16_t offset = 2 * strlen(tabulator) + item_name_width + 1;
if (item_name == NULL) {
return;
}
if (!IS_ENABLED(CONFIG_NEWLIB_LIBC) && !IS_ENABLED(CONFIG_ARCH_POSIX)) {
/* print option name */
shell_fprintf(shell, SHELL_NORMAL, "%s%-*s%s:",
tabulator,
item_name_width, item_name,
tabulator);
} else {
u16_t tmp = item_name_width - strlen(item_name);
char space = ' ';
shell_fprintf(shell, SHELL_NORMAL, "%s%s", tabulator,
item_name);
for (u16_t i = 0; i < tmp; i++) {
shell_write(shell, &space, 1);
}
shell_fprintf(shell, SHELL_NORMAL, "%s:", tabulator);
}
if (item_help == NULL) {
cursor_next_line_move(shell);
return;
}
/* print option help */
formatted_text_print(shell, item_help, offset, false);
}
/* Function is printing command help, its subcommands name and subcommands
* help string.
*/
static void help_subcmd_print(const struct shell *shell)
{
const struct shell_static_entry *entry = NULL;
struct shell_static_entry static_entry;
u16_t longest_syntax = 0U;
size_t cmd_idx = 0;
/* Checking if there are any subcommands available. */
if (!shell->ctx->active_cmd.subcmd) {
return;
}
/* Searching for the longest subcommand to print. */
do {
cmd_get(shell->ctx->active_cmd.subcmd, !SHELL_CMD_ROOT_LVL,
cmd_idx++, &entry, &static_entry);
if (!entry) {
break;
}
u16_t len = shell_strlen(entry->syntax);
longest_syntax = longest_syntax > len ? longest_syntax : len;
} while (cmd_idx != 0); /* too many commands */
if (cmd_idx == 1) {
return;
}
shell_fprintf(shell, SHELL_NORMAL, "Subcommands:\r\n");
/* Printing subcommands and help string (if exists). */
cmd_idx = 0;
while (true) {
cmd_get(shell->ctx->active_cmd.subcmd, !SHELL_CMD_ROOT_LVL,
cmd_idx++, &entry, &static_entry);
if (entry == NULL) {
break;
}
help_item_print(shell, entry->syntax, longest_syntax,
entry->help);
}
}
void shell_help_print(const struct shell *shell)
{
__ASSERT_NO_MSG(shell);
if (!IS_ENABLED(CONFIG_SHELL_HELP)) {
return;
}
help_cmd_print(shell);
help_subcmd_print(shell);
}
int shell_prompt_change(const struct shell *shell, char *prompt)
{
@ -1741,22 +1434,16 @@ int shell_prompt_change(const struct shell *shell, char *prompt)
return -1;
}
int shell_cmd_precheck(const struct shell *shell,
bool arg_cnt_ok)
void shell_help_print(const struct shell *shell)
{
if (!arg_cnt_ok) {
shell_fprintf(shell, SHELL_ERROR,
"%s: wrong parameter count\n",
shell->ctx->active_cmd.syntax);
__ASSERT_NO_MSG(shell);
if (IS_ENABLED(CONFIG_SHELL_HELP_ON_WRONG_ARGUMENT_COUNT)) {
shell_help_print(shell);
if (!IS_ENABLED(CONFIG_SHELL_HELP)) {
return;
}
return -EINVAL;
}
return 0;
shell_help_cmd_print(shell);
shell_help_subcmd_print(shell);
}
int shell_execute_cmd(const struct shell *shell, const char *cmd)

View file

@ -41,6 +41,7 @@
"Disable shell echo. Editing keys and meta-keys are not handled"
#define SHELL_HELP_SHELL "Useful, not Unix-like shell commands."
#define SHELL_HELP_HELP "Prints help message."
#define SHELL_MSG_UNKNOWN_PARAMETER " unknown parameter: "
@ -96,7 +97,7 @@ static int cursor_position_get(const struct shell *shell, u16_t *x, u16_t *y)
/* Index start position in the buffer where 'y'
* is stored.
*/
buff_idx = 2U;
buff_idx = 2;
while (shell->ctx->temp_buff[buff_idx] != ';') {
*y = *y * 10 +
@ -184,156 +185,83 @@ static int cmd_clear(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret) {
return ret;
}
SHELL_VT100_CMD(shell, SHELL_VT100_CURSORHOME);
SHELL_VT100_CMD(shell, SHELL_VT100_CLEARSCREEN);
return 0;
}
static int cmd_shell(const struct shell *shell, size_t argc, char **argv)
{
int ret = shell_cmd_precheck(shell, (argc == 2));
if (ret) {
return ret;
}
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\n", argv[0],
SHELL_MSG_UNKNOWN_PARAMETER, argv[1]);
return -EINVAL;
}
static int cmd_bacskpace_mode_backspace(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->ctx->internal.flags.mode_delete = 0;
}
return ret;
return 0;
}
static int cmd_bacskpace_mode_delete(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->ctx->internal.flags.mode_delete = 1;
}
return ret;
}
static int cmd_bacskpace_mode(const struct shell *shell, size_t argc,
char **argv)
{
int ret = shell_cmd_precheck(shell, (argc == 2));
if (ret) {
return ret;
}
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\n", argv[0],
SHELL_MSG_UNKNOWN_PARAMETER, argv[1]);
return -EINVAL;
return 0;
}
static int cmd_colors_off(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->ctx->internal.flags.use_colors = 0;
}
return ret;
return 0;
}
static int cmd_colors_on(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argv);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->ctx->internal.flags.use_colors = 1;
}
return ret;
}
static int cmd_colors(const struct shell *shell, size_t argc, char **argv)
{
int ret = shell_cmd_precheck(shell, (argc == 2));
if (ret) {
return ret;
}
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\n", argv[0],
SHELL_MSG_UNKNOWN_PARAMETER, argv[1]);
return -EINVAL;
return 0;
}
static int cmd_echo_off(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->ctx->internal.flags.echo = 0;
}
return ret;
return 0;
}
static int cmd_echo_on(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->ctx->internal.flags.echo = 1;
}
return ret;
return 0;
}
static int cmd_echo(const struct shell *shell, size_t argc, char **argv)
{
int ret = shell_cmd_precheck(shell, (argc <= 2));
if (ret) {
return ret;
}
if (argc == 2) {
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\n", argv[0],
shell_error(shell, "%s:%s%s", argv[0],
SHELL_MSG_UNKNOWN_PARAMETER, argv[1]);
return -EINVAL;
}
shell_fprintf(shell, SHELL_NORMAL, "Echo status: %s\n",
shell_print(shell, "Echo status: %s",
flag_echo_is_set(shell) ? "on" : "off");
return 0;
@ -344,41 +272,35 @@ static int cmd_help(const struct shell *shell, size_t argc, char **argv)
ARG_UNUSED(argc);
ARG_UNUSED(argv);
shell_fprintf(shell, SHELL_NORMAL,
shell_print(shell,
"Please press the <Tab> button to see all available commands.\n"
"You can also use the <Tab> button to prompt or auto-complete"
" all commands or its subcommands.\n"
"You can try to call commands with <-h> or <--help> parameter"
" for more information.\n");
" for more information.");
return 0;
}
static int cmd_history(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
size_t i = 0;
size_t len;
int ret;
if (!IS_ENABLED(CONFIG_SHELL_HISTORY)) {
shell_fprintf(shell, SHELL_ERROR, SHELL_MSG_CMD_NOT_SUPPORTED);
shell_error(shell, "Command not supported.");
return -ENOEXEC;
}
ret = shell_cmd_precheck(shell, (argc == 1));
if (ret) {
return ret;
}
while (1) {
shell_history_get(shell->history, true,
shell->ctx->temp_buff, &len);
if (len) {
shell_fprintf(shell, SHELL_NORMAL, "[%3d] %s\n",
shell_print(shell, "[%3d] %s",
i++, shell->ctx->temp_buff);
} else {
@ -394,72 +316,46 @@ static int cmd_history(const struct shell *shell, size_t argc, char **argv)
static int cmd_shell_stats_show(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
if (!IS_ENABLED(CONFIG_SHELL_STATS)) {
shell_fprintf(shell, SHELL_ERROR, SHELL_MSG_CMD_NOT_SUPPORTED);
shell_error(shell, "Command not supported.");
return -ENOEXEC;
}
int ret = shell_cmd_precheck(shell, (argc == 1));
shell_print(shell, "Lost logs: %u", shell->stats->log_lost_cnt);
if (ret == 0) {
shell_fprintf(shell, SHELL_NORMAL, "Lost logs: %u\n",
shell->stats->log_lost_cnt);
}
return ret;
return 0;
}
static int cmd_shell_stats_reset(const struct shell *shell,
size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
if (!IS_ENABLED(CONFIG_SHELL_STATS)) {
shell_fprintf(shell, SHELL_ERROR, SHELL_MSG_CMD_NOT_SUPPORTED);
shell_error(shell, "Command not supported.");
return -ENOEXEC;
}
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
shell->stats->log_lost_cnt = 0;
}
return ret;
}
static int cmd_shell_stats(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
if (argc == 1) {
shell_help_print(shell);
} else {
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\n", argv[0],
SHELL_MSG_UNKNOWN_PARAMETER, argv[1]);
}
return -EINVAL;
return 0;
}
static int cmd_resize_default(const struct shell *shell,
size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int ret = shell_cmd_precheck(shell, (argc == 1));
if (ret == 0) {
SHELL_VT100_CMD(shell, SHELL_VT100_SETCOL_80);
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.terminal_wid = SHELL_DEFAULT_TERMINAL_WIDTH;
shell->ctx->vt100_ctx.cons.terminal_hei = SHELL_DEFAULT_TERMINAL_HEIGHT;
return ret;
return 0;
}
static int cmd_resize(const struct shell *shell, size_t argc, char **argv)
@ -467,17 +363,12 @@ static int cmd_resize(const struct shell *shell, size_t argc, char **argv)
int err;
if (!IS_ENABLED(CONFIG_SHELL_CMDS_RESIZE)) {
shell_fprintf(shell, SHELL_ERROR, SHELL_MSG_CMD_NOT_SUPPORTED);
shell_error(shell, "Command not supported.");
return -ENOEXEC;
}
err = shell_cmd_precheck(shell, (argc <= 2));
if (err) {
return err;
}
if (argc != 1) {
shell_fprintf(shell, SHELL_ERROR, "%s:%s%s\n", argv[0],
shell_error(shell, "%s:%s%s", argv[0],
SHELL_MSG_UNKNOWN_PARAMETER, argv[1]);
return -EINVAL;
}
@ -488,9 +379,8 @@ static int cmd_resize(const struct shell *shell, size_t argc, char **argv)
SHELL_DEFAULT_TERMINAL_WIDTH;
shell->ctx->vt100_ctx.cons.terminal_hei =
SHELL_DEFAULT_TERMINAL_HEIGHT;
shell_fprintf(shell, SHELL_WARNING,
"No response from the terminal, assumed 80x24 "
"screen size\n");
shell_warn(shell, "No response from the terminal, assumed 80x24"
" screen size");
return -ENOEXEC;
}
@ -499,54 +389,56 @@ static int cmd_resize(const struct shell *shell, size_t argc, char **argv)
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_colors)
{
SHELL_CMD(off, NULL, SHELL_HELP_COLORS_OFF, cmd_colors_off),
SHELL_CMD(on, NULL, SHELL_HELP_COLORS_ON, cmd_colors_on),
SHELL_CMD_ARG(off, NULL, SHELL_HELP_COLORS_OFF, cmd_colors_off, 1, 0),
SHELL_CMD_ARG(on, NULL, SHELL_HELP_COLORS_ON, cmd_colors_on, 1, 0),
SHELL_SUBCMD_SET_END
};
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_echo)
{
SHELL_CMD(off, NULL, SHELL_HELP_ECHO_OFF, cmd_echo_off),
SHELL_CMD(on, NULL, SHELL_HELP_ECHO_ON, cmd_echo_on),
SHELL_CMD_ARG(off, NULL, SHELL_HELP_ECHO_OFF, cmd_echo_off, 1, 0),
SHELL_CMD_ARG(on, NULL, SHELL_HELP_ECHO_ON, cmd_echo_on, 1, 0),
SHELL_SUBCMD_SET_END
};
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_shell_stats)
{
SHELL_CMD(reset, NULL, SHELL_HELP_STATISTICS_RESET,
cmd_shell_stats_reset),
SHELL_CMD(show, NULL, SHELL_HELP_STATISTICS_SHOW, cmd_shell_stats_show),
SHELL_CMD_ARG(reset, NULL, SHELL_HELP_STATISTICS_RESET,
cmd_shell_stats_reset, 1, 0),
SHELL_CMD_ARG(show, NULL, SHELL_HELP_STATISTICS_SHOW,
cmd_shell_stats_show, 1, 0),
SHELL_SUBCMD_SET_END
};
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_backspace_mode)
{
SHELL_CMD(backspace, NULL, SHELL_HELP_BACKSPACE_MODE_BACKSPACE,
cmd_bacskpace_mode_backspace),
SHELL_CMD(delete, NULL, SHELL_HELP_BACKSPACE_MODE_DELETE,
cmd_bacskpace_mode_delete),
SHELL_CMD_ARG(backspace, NULL, SHELL_HELP_BACKSPACE_MODE_BACKSPACE,
cmd_bacskpace_mode_backspace, 1, 0),
SHELL_CMD_ARG(delete, NULL, SHELL_HELP_BACKSPACE_MODE_DELETE,
cmd_bacskpace_mode_delete, 1, 0),
SHELL_SUBCMD_SET_END
};
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_shell)
{
SHELL_CMD(backspace_mode, &m_sub_backspace_mode,
SHELL_HELP_BACKSPACE_MODE, cmd_bacskpace_mode),
SHELL_CMD(colors, &m_sub_colors, SHELL_HELP_COLORS, cmd_colors),
SHELL_CMD(echo, &m_sub_echo, SHELL_HELP_ECHO, cmd_echo),
SHELL_CMD(stats, &m_sub_shell_stats, SHELL_HELP_STATISTICS,
cmd_shell_stats),
SHELL_HELP_BACKSPACE_MODE, NULL),
SHELL_CMD(colors, &m_sub_colors, SHELL_HELP_COLORS, NULL),
SHELL_CMD_ARG(echo, &m_sub_echo, SHELL_HELP_ECHO, cmd_echo, 1, 1),
SHELL_CMD(stats, &m_sub_shell_stats, SHELL_HELP_STATISTICS, NULL),
SHELL_SUBCMD_SET_END
};
SHELL_CREATE_STATIC_SUBCMD_SET(m_sub_resize)
{
SHELL_CMD(default, NULL, SHELL_HELP_RESIZE_DEFAULT, cmd_resize_default),
SHELL_CMD_ARG(default, NULL, SHELL_HELP_RESIZE_DEFAULT,
cmd_resize_default, 1, 0),
SHELL_SUBCMD_SET_END
};
SHELL_CMD_REGISTER(clear, NULL, SHELL_HELP_CLEAR, cmd_clear);
SHELL_CMD_REGISTER(shell, &m_sub_shell, SHELL_HELP_SHELL, cmd_shell);
SHELL_CMD_REGISTER(help, NULL, NULL, cmd_help);
SHELL_CMD_REGISTER(history, NULL, SHELL_HELP_HISTORY, cmd_history);
SHELL_CMD_REGISTER(resize, &m_sub_resize, SHELL_HELP_RESIZE, cmd_resize);
SHELL_CMD_ARG_REGISTER(clear, NULL, SHELL_HELP_CLEAR, cmd_clear, 1, 0);
SHELL_CMD_REGISTER(shell, &m_sub_shell, SHELL_HELP_SHELL, NULL);
SHELL_CMD_ARG_REGISTER(help, NULL, SHELL_HELP_HELP, cmd_help, 1, 255);
SHELL_CMD_ARG_REGISTER(history, NULL, SHELL_HELP_HISTORY, cmd_history, 1, 0);
SHELL_CMD_ARG_REGISTER(resize, &m_sub_resize, SHELL_HELP_RESIZE, cmd_resize,
1, 1);

210
subsys/shell/shell_help.c Normal file
View file

@ -0,0 +1,210 @@
/*
* 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 *shell, 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) {
shell_op_cursor_horiz_move(shell, terminal_offset);
}
/* Skipping whitespace. */
while (isspace((int) *(str + offset))) {
++offset;
}
while (true) {
size_t idx = 0;
length = shell_strlen(str) - offset;
if (length <=
shell->ctx->vt100_ctx.cons.terminal_wid - terminal_offset) {
for (idx = 0; idx < length; idx++) {
if (*(str + offset + idx) == '\n') {
transport_buffer_flush(shell);
shell_write(shell, str + offset, idx);
offset += idx + 1;
cursor_next_line_move(shell);
shell_op_cursor_horiz_move(shell,
terminal_offset);
break;
}
}
/* String will fit in one line. */
shell_raw_fprintf(shell->fprintf_ctx, str + offset);
break;
}
/* String is longer than terminal line so text needs to
* divide in the way to not divide words.
*/
length = shell->ctx->vt100_ctx.cons.terminal_wid
- terminal_offset;
while (true) {
/* Determining line break. */
if (isspace((int) (*(str + offset + idx)))) {
length = idx;
if (*(str + offset + idx) == '\n') {
break;
}
}
if ((idx + terminal_offset) >=
shell->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.
*/
transport_buffer_flush(shell);
shell_write(shell, str + offset, length);
offset += length;
/* Calculating text offset to ensure that next line will
* not begin with a space.
*/
while (isspace((int) (*(str + offset)))) {
++offset;
}
cursor_next_line_move(shell);
shell_op_cursor_horiz_move(shell, terminal_offset);
}
cursor_next_line_move(shell);
}
static void help_item_print(const struct shell *shell, const char *item_name,
u16_t item_name_width, const char *item_help)
{
static const u8_t tabulator[] = " ";
const u16_t offset = 2 * strlen(tabulator) + item_name_width + 1;
if (item_name == NULL) {
return;
}
if (!IS_ENABLED(CONFIG_NEWLIB_LIBC) && !IS_ENABLED(CONFIG_ARCH_POSIX)) {
/* print option name */
shell_fprintf(shell, SHELL_NORMAL, "%s%-*s%s:",
tabulator,
item_name_width, item_name,
tabulator);
} else {
u16_t tmp = item_name_width - strlen(item_name);
char space = ' ';
shell_fprintf(shell, SHELL_NORMAL, "%s%s", tabulator,
item_name);
for (u16_t i = 0; i < tmp; i++) {
shell_write(shell, &space, 1);
}
shell_fprintf(shell, SHELL_NORMAL, "%s:", tabulator);
}
if (item_help == NULL) {
cursor_next_line_move(shell);
return;
}
/* print option help */
formatted_text_print(shell, item_help, offset, false);
}
/* Function is printing command help, its subcommands name and subcommands
* help string.
*/
void shell_help_subcmd_print(const struct shell *shell)
{
const struct shell_static_entry *entry = NULL;
struct shell_static_entry static_entry;
u16_t longest_syntax = 0;
size_t cmd_idx = 0;
/* Checking if there are any subcommands available. */
if (!shell->ctx->active_cmd.subcmd) {
return;
}
/* Searching for the longest subcommand to print. */
do {
shell_cmd_get(shell->ctx->active_cmd.subcmd,
!SHELL_CMD_ROOT_LVL,
cmd_idx++, &entry, &static_entry);
if (!entry) {
break;
}
u16_t len = shell_strlen(entry->syntax);
longest_syntax = longest_syntax > len ? longest_syntax : len;
} while (cmd_idx != 0); /* too many commands */
if (cmd_idx == 1) {
return;
}
shell_fprintf(shell, SHELL_NORMAL, "Subcommands:\r\n");
/* Printing subcommands and help string (if exists). */
cmd_idx = 0;
while (true) {
shell_cmd_get(shell->ctx->active_cmd.subcmd,
!SHELL_CMD_ROOT_LVL,
cmd_idx++, &entry, &static_entry);
if (entry == NULL) {
break;
}
help_item_print(shell, entry->syntax, longest_syntax,
entry->help);
}
}
void shell_help_cmd_print(const struct shell *shell)
{
static const char cmd_sep[] = " - "; /* commands separator */
u16_t field_width = shell_strlen(shell->ctx->active_cmd.syntax) +
shell_strlen(cmd_sep);
shell_fprintf(shell, SHELL_NORMAL, "%s%s",
shell->ctx->active_cmd.syntax, cmd_sep);
formatted_text_print(shell, shell->ctx->active_cmd.help,
field_width, false);
}

30
subsys/shell/shell_help.h Normal file
View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SHELL_HELP_H__
#define SHELL_HELP_H__
#include <shell/shell.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Function is printing command help string. */
void shell_help_cmd_print(const struct shell *shell);
/* Function is printing subcommands help string. */
void shell_help_subcmd_print(const struct shell *shell);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* SHELL_HELP__ */

View file

@ -262,3 +262,47 @@ void shell_op_completion_insert(const struct shell *shell,
{
data_insert(shell, compl, compl_len);
}
static void shell_pend_on_txdone(const struct shell *shell)
{
if (IS_ENABLED(CONFIG_MULTITHREADING)) {
k_poll(&shell->ctx->events[SHELL_SIGNAL_TXDONE], 1, K_FOREVER);
k_poll_signal_reset(&shell->ctx->signals[SHELL_SIGNAL_TXDONE]);
} else {
/* Blocking wait in case of bare metal. */
while (!shell->ctx->internal.flags.tx_rdy) {
}
shell->ctx->internal.flags.tx_rdy = 0;
}
}
void shell_write(const struct shell *shell, const void *data,
size_t length)
{
__ASSERT_NO_MSG(shell && data);
size_t offset = 0;
size_t tmp_cnt;
while (length) {
int err = shell->iface->api->write(shell->iface,
&((const u8_t *) data)[offset], length,
&tmp_cnt);
(void)err;
__ASSERT_NO_MSG(err == 0);
__ASSERT_NO_MSG(length >= tmp_cnt);
offset += tmp_cnt;
length -= tmp_cnt;
if (tmp_cnt == 0 &&
(shell->ctx->state != SHELL_STATE_PANIC_MODE_ACTIVE)) {
shell_pend_on_txdone(shell);
}
}
}
/* Function shall be only used by the fprintf module. */
void shell_print_stream(const void *user_ctx, const char *data,
size_t data_len)
{
shell_write((const struct shell *) user_ctx, data, data_len);
}

View file

@ -6,7 +6,6 @@
#ifndef SHELL_OPS_H__
#define SHELL_OPS_H__
#include <zephyr.h>
#include <shell/shell.h>
#include "shell_vt100.h"
#include "shell_utils.h"
@ -121,6 +120,29 @@ void shell_op_completion_insert(const struct shell *shell,
u16_t compl_len);
bool shell_cursor_in_empty_line(const struct shell *shell);
/* Function sends data stream to the shell instance. Each time before the
* shell_write function is called, it must be ensured that IO buffer of fprintf
* is flushed to avoid synchronization issues.
* For that purpose, use function transport_buffer_flush(shell)
*
* This function can be only used by shell module, it shall not be called
* directly.
*/
void shell_write(const struct shell *shell, const void *data,
size_t length);
/**
* @internal @brief This function shall not be used directly, it is required by
* the fprintf module.
*
* @param[in] p_user_ctx Pointer to the context for the shell instance.
* @param[in] p_data Pointer to the data buffer.
* @param[in] data_len Data buffer size.
*/
void shell_print_stream(const void *user_ctx, const char *data,
size_t data_len);
#ifdef __cplusplus
}
#endif

View file

@ -6,6 +6,14 @@
#include "shell_utils.h"
#include <ctype.h>
extern const struct shell_cmd_entry __shell_root_cmds_start[0];
extern const struct shell_cmd_entry __shell_root_cmds_end[0];
static inline const struct shell_cmd_entry *shell_root_cmd_get(u32_t id)
{
return &__shell_root_cmds_start[id];
}
/* Calculates relative line number of given position in buffer */
static u32_t line_num_with_buffer_offset_get(struct shell_multiline_cons *cons,
u16_t buffer_pos)
@ -209,6 +217,62 @@ void shell_pattern_remove(char *buff, u16_t *buff_len, const char *pattern)
memmove(pattern_addr, pattern_addr + pattern_len, shift);
}
static inline u32_t shell_root_cmd_count(void)
{
return ((u8_t *)__shell_root_cmds_end -
(u8_t *)__shell_root_cmds_start)/
sizeof(struct shell_cmd_entry);
}
/* Function returning pointer to root command matching requested syntax. */
const struct shell_cmd_entry *root_cmd_find(const char *syntax)
{
const size_t cmd_count = shell_root_cmd_count();
const struct shell_cmd_entry *cmd;
for (size_t cmd_idx = 0; cmd_idx < cmd_count; ++cmd_idx) {
cmd = shell_root_cmd_get(cmd_idx);
if (strcmp(syntax, cmd->u.entry->syntax) == 0) {
return cmd;
}
}
return NULL;
}
void shell_cmd_get(const struct shell_cmd_entry *command, size_t lvl,
size_t idx, const struct shell_static_entry **entry,
struct shell_static_entry *d_entry)
{
__ASSERT_NO_MSG(entry != NULL);
__ASSERT_NO_MSG(d_entry != NULL);
if (lvl == SHELL_CMD_ROOT_LVL) {
if (idx < shell_root_cmd_count()) {
const struct shell_cmd_entry *cmd;
cmd = shell_root_cmd_get(idx);
*entry = cmd->u.entry;
} else {
*entry = NULL;
}
return;
}
if (command == NULL) {
*entry = NULL;
return;
}
if (command->is_dynamic) {
command->u.dynamic_get(idx, d_entry);
*entry = (d_entry->syntax != NULL) ? d_entry : NULL;
} else {
*entry = (command->u.entry[idx].syntax != NULL) ?
&command->u.entry[idx] : NULL;
}
}
int shell_command_add(char *buff, u16_t *buff_len,
const char *new_cmd, const char *pattern)
{

View file

@ -8,6 +8,7 @@
#include <zephyr.h>
#include <shell/shell.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -42,9 +43,29 @@ char shell_make_argv(size_t *argc, char **argv, char *cmd, uint8_t max_argc);
*/
void shell_pattern_remove(char *buff, u16_t *buff_len, const char *pattern);
/* @brief Function shall be used to search commands.
*
* It moves the pointer entry to command of static command structure. If the
* command cannot be found, the function will set entry to NULL.
*
* @param command Pointer to command which will be processed (no matter
* the root command).
* @param lvl Level of the requested command.
* @param idx Index of the requested command.
* @param entry Pointer which points to subcommand[idx] after function
* execution.
* @param st_entry Pointer to the structure where dynamic entry data can be
* stored.
*/
void shell_cmd_get(const struct shell_cmd_entry *command, size_t lvl,
size_t idx, const struct shell_static_entry **entry,
struct shell_static_entry *d_entry);
int shell_command_add(char *buff, u16_t *buff_len,
const char *new_cmd, const char *pattern);
const struct shell_cmd_entry *root_cmd_find(const char *syntax);
void shell_spaces_trim(char *str);
/** @brief Remove white chars from beginning and end of command buffer.
@ -52,6 +73,11 @@ void shell_spaces_trim(char *str);
*/
void shell_buffer_trim(char *buff, u16_t *buff_len);
static inline void transport_buffer_flush(const struct shell *shell)
{
shell_fprintf_buffer_flush(shell->fprintf_ctx);
}
#ifdef __cplusplus
}
#endif

View file

@ -33,12 +33,6 @@ static bool hrs_simulate;
static int cmd_hrs_simulate(const struct shell *shell,
size_t argc, char *argv[])
{
int err = shell_cmd_precheck(shell, (argc == 2));
if (err) {
return err;
}
if (!strcmp(argv[1], "on")) {
static bool hrs_registered;
@ -68,34 +62,22 @@ static int cmd_hrs_simulate(const struct shell *shell,
SHELL_CREATE_STATIC_SUBCMD_SET(hrs_cmds) {
#if defined(CONFIG_BT_CONN)
SHELL_CMD(hrs-simulate, NULL,
SHELL_CMD_ARG(hrs-simulate, NULL,
"register and simulate Heart Rate Service <value: on, off>",
cmd_hrs_simulate),
cmd_hrs_simulate, 2, 0),
#endif /* CONFIG_BT_CONN */
SHELL_SUBCMD_SET_END
};
static int cmd_hrs(const struct shell *shell, size_t argc, char **argv)
{
int err = shell_cmd_precheck(shell, (argc == 2));
if (argc == 1) {
shell_help_print(shell);
/* shell_cmd_precheck returns 1 when help is printed */
return 1;
}
if (err) {
return err;
}
shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
return -ENOEXEC;
}
SHELL_CMD_REGISTER(hrs, &hrs_cmds, "Heart Rate Service shell commands",
cmd_hrs);
SHELL_CMD_ARG_REGISTER(hrs, &hrs_cmds, "Heart Rate Service shell commands",
cmd_hrs, 2, 0);
void main(void)
{

View file

@ -34,8 +34,8 @@ static void test_shell_execute_cmd(const char *cmd, int result)
static void test_cmd_help(void)
{
test_shell_execute_cmd("help", 0);
test_shell_execute_cmd("help -h", 0);
test_shell_execute_cmd("help --help", 0);
test_shell_execute_cmd("help -h", 1);
test_shell_execute_cmd("help --help", 1);
test_shell_execute_cmd("help dummy", 0);
test_shell_execute_cmd("help dummy dummy", 0);
}
@ -53,13 +53,13 @@ static void test_cmd_shell(void)
{
test_shell_execute_cmd("shell -h", 1);
test_shell_execute_cmd("shell --help", 1);
test_shell_execute_cmd("shell dummy", -EINVAL);
test_shell_execute_cmd("shell dummy dummy", -EINVAL);
test_shell_execute_cmd("shell dummy", 1);
test_shell_execute_cmd("shell dummy dummy", 1);
/* subcommand: backspace_mode */
test_shell_execute_cmd("shell backspace_mode -h", 1);
test_shell_execute_cmd("shell backspace_mode --help", 1);
test_shell_execute_cmd("shell backspace_mode dummy", -EINVAL);
test_shell_execute_cmd("shell backspace_mode dummy", 1);
test_shell_execute_cmd("shell backspace_mode backspace", 0);
test_shell_execute_cmd("shell backspace_mode backspace -h", 1);
@ -78,8 +78,8 @@ static void test_cmd_shell(void)
/* subcommand: colors */
test_shell_execute_cmd("shell colors -h", 1);
test_shell_execute_cmd("shell colors --help", 1);
test_shell_execute_cmd("shell colors dummy", -EINVAL);
test_shell_execute_cmd("shell colors dummy dummy", -EINVAL);
test_shell_execute_cmd("shell colors dummy", 1);
test_shell_execute_cmd("shell colors dummy dummy", 1);
test_shell_execute_cmd("shell colors off", 0);
test_shell_execute_cmd("shell colors off -h", 1);
@ -113,11 +113,11 @@ static void test_cmd_shell(void)
test_shell_execute_cmd("shell echo on dummy dummy", -EINVAL);
/* subcommand: stats */
test_shell_execute_cmd("shell stats", -EINVAL);
test_shell_execute_cmd("shell stats", 1);
test_shell_execute_cmd("shell stats -h", 1);
test_shell_execute_cmd("shell stats --help", 1);
test_shell_execute_cmd("shell stats dummy", -EINVAL);
test_shell_execute_cmd("shell stats dummy dummy", -EINVAL);
test_shell_execute_cmd("shell stats dummy", 1);
test_shell_execute_cmd("shell stats dummy dummy", 1);
test_shell_execute_cmd("shell stats reset", 0);
test_shell_execute_cmd("shell stats reset -h", 1);
@ -195,10 +195,11 @@ static void test_shell_wildcards_dynamic(void)
static int cmd_test_module(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argv);
ARG_UNUSED(argc);
return shell_cmd_precheck(shell, (argc == 1));
return 0;
}
SHELL_CMD_REGISTER(test_shell_cmd, NULL, NULL, cmd_test_module);
SHELL_CMD_ARG_REGISTER(test_shell_cmd, NULL, "help", cmd_test_module, 1, 0);
static int cmd_wildcard(const struct shell *shell, size_t argc, char **argv)