diff --git a/include/shell/shell.h b/include/shell/shell.h index 1ea820123a4..729627133b0 100644 --- a/include/shell/shell.h +++ b/include/shell/shell.h @@ -139,6 +139,22 @@ const struct device *shell_device_lookup(size_t idx, typedef int (*shell_cmd_handler)(const struct shell *shell, size_t argc, char **argv); +/** + * @brief Shell dictionary command handler prototype. + * + * @param shell Shell instance. + * @param argc Arguments count. + * @param argv Arguments. + * @param data Pointer to the user data. + * + * @retval 0 Successful command execution. + * @retval 1 Help printed and command not executed. + * @retval -EINVAL Argument validation failed. + * @retval -ENOEXEC Command not executed. + */ +typedef int (*shell_dict_cmd_handler)(const struct shell *shell, size_t argc, + char **argv, void *data); + /* * @brief Shell static command descriptor. */ @@ -396,6 +412,52 @@ struct shell_static_entry { #define SHELL_EXPR_CMD(_expr, _syntax, _subcmd, _help, _handler) \ SHELL_EXPR_CMD_ARG(_expr, _syntax, _subcmd, _help, _handler, 0, 0) +/* Internal macro used for creating handlers for dictionary commands. */ +#define SHELL_CMD_DICT_HANDLER_CREATE(_data, _handler) \ +static int UTIL_CAT(cmd_dict_, GET_ARG_N(1, __DEBRACKET _data))( \ + const struct shell *shell, size_t argc, char **argv) \ +{ \ + return _handler(shell, argc, argv, \ + (void *)GET_ARG_N(2, __DEBRACKET _data)); \ +} + +/* Internal macro used for creating dictionary commands. */ +#define SHELL_CMD_DICT_CREATE(_data) \ + SHELL_CMD_ARG(GET_ARG_N(1, __DEBRACKET _data), NULL, NULL, \ + UTIL_CAT(cmd_dict_, GET_ARG_N(1, __DEBRACKET _data)), 1, 0) + +/** + * @brief Initializes shell dictionary commands. + * + * @param[in] _name Name of the dictionary subcommand set + * @param[in] _handler Command handler common for all dictionary commands. + * @see shell_dict_cmd_handler + * @param[in] ... Dictionary pairs: (command_syntax, value). Value will be + * passed to the _handler as user data. + * + * Example usage: + * static int my_handler(const struct shell *shell, + * size_t argc, char **argv, void *data) + * { + * int val = (int)data; + + * shell_print(shell, "(syntax, value) : (%s, %d)", argv[0], val); + * return 0; + * } + + * SHELL_SUBCMD_DICT_SET_CREATE(sub_dict_cmds, my_handler, + * (value_0, 0), (value_1, 1), (value_2, 2), (value_3, 3) + * ); + * SHELL_CMD_REGISTER(dictionary, &sub_dict_cmds, NULL, NULL); + */ +#define SHELL_SUBCMD_DICT_SET_CREATE(_name, _handler, ...) \ + FOR_EACH_FIXED_ARG(SHELL_CMD_DICT_HANDLER_CREATE, (), \ + _handler, __VA_ARGS__) \ + SHELL_STATIC_SUBCMD_SET_CREATE(_name, \ + FOR_EACH(SHELL_CMD_DICT_CREATE, (,), __VA_ARGS__), \ + SHELL_SUBCMD_SET_END \ + ) + /** * @internal @brief Internal shell state in response to data received from the * terminal. @@ -898,7 +960,7 @@ void shell_help(const struct shell *shell); * Pass command line to shell to execute. * * Note: This by no means makes any of the commands a stable interface, so - * this function should only be used for debugging/diagnostic. + * this function should only be used for debugging/diagnostic. * * This function must not be called from shell command context!