diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 59b637847224..267481d3f875 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -98,6 +98,7 @@ PSEUDOMODULES += saul_nrf_temperature PSEUDOMODULES += scanf_float PSEUDOMODULES += sched_cb PSEUDOMODULES += semtech_loramac_rx +PSEUDOMODULES += shell_hooks PSEUDOMODULES += slipdev_stdio PSEUDOMODULES += sock PSEUDOMODULES += sock_async diff --git a/sys/include/shell.h b/sys/include/shell.h index db6d25786d73..e44c6ebb00ed 100644 --- a/sys/include/shell.h +++ b/sys/include/shell.h @@ -48,6 +48,37 @@ extern "C" { */ #define SHELL_DEFAULT_BUFSIZE (128) +/** + * @brief Optional hook after readline has triggered. + * @details User implemented function gets called after the shell + * readline is complete. + * @note Only executed with the `shell_hooks` module. + */ +void shell_post_readline_hook(void); + +/** + * @brief Optional hook before shell command is called. + * @details User implemented function gets called before a valid shell + * command will be called. + * @note Only executed with the `shell_hooks` module. + * + * @param[in] argc Number of arguments supplied to the function invocation. + * @param[in] argv The supplied argument list. + */ +void shell_pre_command_hook(int argc, char **argv); + +/** + * @brief Optional hook after shell command is called. + * @details User implemented function gets called before a valid shell + * command will be called. + * @note Only executed with the `shell_hooks` module. + * + * @param[in] ret Return value of the shell command. + * @param[in] argc Number of arguments supplied to the function invocation. + * @param[in] argv The supplied argument list. + */ +void shell_post_command_hook(int ret, int argc, char **argv); + /** * @brief Protype of a shell callback handler. * @details The functions supplied to shell_run() must use this signature. diff --git a/sys/shell/shell.c b/sys/shell/shell.c index abcb437cfafb..167cdb6ee44b 100644 --- a/sys/shell/shell.c +++ b/sys/shell/shell.c @@ -199,7 +199,9 @@ static void handle_input_line(const shell_command_t *command_list, char *line) char *writepos = readpos; uint8_t pstate = PARSE_BLANK; - + if (IS_USED(MODULE_SHELL_HOOKS)) { + shell_post_readline_hook(); + } for (; *readpos != '\0'; readpos++) { char wordbreak = SPACE; @@ -300,7 +302,14 @@ static void handle_input_line(const shell_command_t *command_list, char *line) /* then we call the appropriate handler */ shell_command_handler_t handler = find_handler(command_list, argv[0]); if (handler != NULL) { - handler(argc, argv); + if (IS_USED(MODULE_SHELL_HOOKS)) { + shell_pre_command_hook(argc, argv); + int res = handler(argc, argv); + shell_post_command_hook(res, argc, argv); + } + else { + handler(argc, argv); + } } else { if (strcmp("help", argv[0]) == 0) { @@ -312,6 +321,25 @@ static void handle_input_line(const shell_command_t *command_list, char *line) } } +__attribute__((weak)) void shell_post_readline_hook(void) +{ + +} + +__attribute__((weak)) void shell_pre_command_hook(int argc, char **argv) +{ + (void)argv; + (void)argc; +} + +__attribute__((weak)) void shell_post_command_hook(int ret, int argc, + char **argv) +{ + (void)ret; + (void)argv; + (void)argc; +} + static inline void print_prompt(void) { if (PROMPT_ON) { diff --git a/tests/shell/main.c b/tests/shell/main.c index ffdbf4a8a630..5afa5f51ec2d 100644 --- a/tests/shell/main.c +++ b/tests/shell/main.c @@ -28,6 +28,28 @@ #include "xtimer.h" #endif +#if MODULE_SHELL_HOOKS +void shell_post_readline_hook(void) +{ + puts("shell_post_readline_hook"); +} + +void shell_pre_command_hook(int argc, char **argv) +{ + (void)argc; + (void)argv; + puts("shell_pre_command_hook"); +} + +void shell_post_command_hook(int ret, int argc, char **argv) +{ + (void)ret; + (void)argc; + (void)argv; + puts("shell_post_command_hook"); +} +#endif + static int print_teststart(int argc, char **argv) { (void) argc;