shell: add select command
The "select" command has been implemented, which allows user to narrow down the command tree. This implementation differs from the "select" command available in the legacy shell. In a new implementation, if the selected command has a handler and if the user has not entered the registered subcommand, the shell will call the handler of selected command and pass the text as arguments. This may be useful, for example, if someone wants to use the shell as an interface to a modem that supports AT commands. Instead of each time you write e.g: at at+command1 at at+command2 at at+command3 user can execute following commands: select at at+command1 at+command2 at+command3 where: at - root command for passing at commands to the modem at+commandX - at command passed to the modem. Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
parent
fde86da6f5
commit
b633e431a4
8 changed files with 227 additions and 96 deletions
|
@ -3,8 +3,9 @@
|
|||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "shell_utils.h"
|
||||
#include <ctype.h>
|
||||
#include "shell_utils.h"
|
||||
#include "shell_wildcard.h"
|
||||
|
||||
extern const struct shell_cmd_entry __shell_root_cmds_start[0];
|
||||
extern const struct shell_cmd_entry __shell_root_cmds_end[0];
|
||||
|
@ -240,39 +241,127 @@ const struct shell_static_entry *shell_root_cmd_find(const char *syntax)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void shell_cmd_get(const struct shell_cmd_entry *command, size_t lvl,
|
||||
void shell_cmd_get(const struct shell *shell,
|
||||
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);
|
||||
|
||||
*entry = NULL;
|
||||
|
||||
if (lvl == SHELL_CMD_ROOT_LVL) {
|
||||
if (idx < shell_root_cmd_count()) {
|
||||
if (shell_in_select_mode(shell) &&
|
||||
IS_ENABLED(CONFIG_SHELL_CMDS_SELECT)) {
|
||||
const struct shell_static_entry *ptr =
|
||||
shell->ctx->selected_cmd;
|
||||
if (ptr->subcmd->u.entry[idx].syntax != NULL) {
|
||||
*entry = &ptr->subcmd->u.entry[idx];
|
||||
}
|
||||
} else 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;
|
||||
if (d_entry->syntax != NULL) {
|
||||
*entry = d_entry;
|
||||
}
|
||||
} else {
|
||||
*entry = (command->u.entry[idx].syntax != NULL) ?
|
||||
&command->u.entry[idx] : NULL;
|
||||
if (command->u.entry[idx].syntax != NULL) {
|
||||
*entry = &command->u.entry[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function returns pointer to a command matching given pattern.
|
||||
*
|
||||
* @param shell Shell instance.
|
||||
* @param cmd Pointer to commands array that will be searched.
|
||||
* @param lvl Root command indicator. If set to 0 shell will search
|
||||
* for pattern in root commands.
|
||||
* @param cmd_str Command pattern to be found.
|
||||
* @param d_entry Shell static command descriptor.
|
||||
*
|
||||
* @return Pointer to found command.
|
||||
*/
|
||||
static const struct shell_static_entry *find_cmd(
|
||||
const struct shell *shell,
|
||||
const struct shell_cmd_entry *cmd,
|
||||
size_t lvl,
|
||||
char *cmd_str,
|
||||
struct shell_static_entry *d_entry)
|
||||
{
|
||||
const struct shell_static_entry *entry = NULL;
|
||||
size_t idx = 0;
|
||||
|
||||
do {
|
||||
shell_cmd_get(shell, cmd, lvl, idx++, &entry, d_entry);
|
||||
if (entry && (strcmp(cmd_str, entry->syntax) == 0)) {
|
||||
return entry;
|
||||
}
|
||||
} while (entry);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct shell_static_entry *shell_get_last_command(
|
||||
const struct shell *shell,
|
||||
size_t argc,
|
||||
char *argv[],
|
||||
size_t *match_arg,
|
||||
struct shell_static_entry *d_entry,
|
||||
bool only_static)
|
||||
{
|
||||
const struct shell_static_entry *prev_entry = NULL;
|
||||
const struct shell_static_entry *entry = NULL;
|
||||
const struct shell_cmd_entry *cmd = NULL;
|
||||
|
||||
*match_arg = SHELL_CMD_ROOT_LVL;
|
||||
|
||||
while (*match_arg < argc) {
|
||||
|
||||
if (IS_ENABLED(CONFIG_SHELL_WILDCARD)) {
|
||||
/* ignore wildcard argument */
|
||||
if (shell_wildcard_character_exist(argv[*match_arg])) {
|
||||
(*match_arg)++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
entry = find_cmd(shell, cmd, *match_arg, argv[*match_arg],
|
||||
d_entry);
|
||||
if (entry) {
|
||||
cmd = entry->subcmd;
|
||||
prev_entry = entry;
|
||||
(*match_arg)++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (only_static && cmd->is_dynamic) {
|
||||
(*match_arg)--;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int shell_command_add(char *buff, u16_t *buff_len,
|
||||
const char *new_cmd, const char *pattern)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue