shell: dictionary commands feature

Adding dictionary commands concept. It simplifies creation of multiple
commands that are handled by a one function handler.

This is a special kind of static commands. Dictionary commands can be
used every time you want to use a pair: (string <-> corresponding data)
in a command handler. The string is usually a verbal description
of a given data. The idea is to use the string as a command syntax that
can be prompted by the shell and corresponding data can be used to
process the command.

Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
Jakub Rzeszutko 2020-10-07 09:24:50 +02:00 committed by Anas Nashif
commit a8e45c4f1e

View file

@ -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!