diff --git a/common/complete.c b/common/complete.c index 9d749e0..d848396 100644 --- a/common/complete.c +++ b/common/complete.c @@ -20,13 +20,10 @@ #include #include #include -#include -#include #include #include #include #include -#include #include static int file_complete(struct string_list *sl, char *instr) @@ -131,7 +128,7 @@ return 0; } -static int command_complete(struct string_list *sl, char *instr) +int command_complete(struct string_list *sl, char *instr) { struct command *cmdtp; @@ -236,6 +233,32 @@ tab_pressed = 0; } +static char* cmd_complete_lookup(struct string_list *sl, char *instr) +{ + struct command *cmdtp; + int len; + int ret = 1; + char *res = NULL; + + for_each_command(cmdtp) { + len = strlen(cmdtp->name); + if (!strncmp(instr, cmdtp->name, len) && instr[len] == ' ') { + instr += len + 1; + if (cmdtp->complete) { + ret = cmdtp->complete(sl, instr); + res = instr; + } + goto end; + } + } + +end: + if (ret == COMPLETE_CONTINUE && *instr == '$') + env_param_complete(sl, instr + 1, 1); + + return res; +} + int complete(char *instr, char **outstr) { struct string_list sl, *entry, *first_entry; @@ -259,20 +282,22 @@ while (*t == ' ') t++; - instr = t; - /* get the completion possibilities */ - if ((t = strrchr(t, ' '))) { - t++; - file_complete(&sl, t); + instr = cmd_complete_lookup(&sl, t); + if (!instr) { instr = t; - } else { - command_complete(&sl, instr); - path_command_complete(&sl, instr); - env_param_complete(&sl, instr, 0); + if ((t = strrchr(t, ' '))) { + t++; + file_complete(&sl, t); + instr = t; + } else { + command_complete(&sl, instr); + path_command_complete(&sl, instr); + env_param_complete(&sl, instr, 0); + } + if (*instr == '$') + env_param_complete(&sl, instr + 1, 1); } - if (*instr == '$') - env_param_complete(&sl, instr + 1, 1); pos = strlen(instr); diff --git a/include/command.h b/include/command.h index b2e8449..80cbf56 100644 --- a/include/command.h +++ b/include/command.h @@ -40,6 +40,8 @@ #define for_each_command(cmd) list_for_each_entry(cmd, &command_list, list) +struct string_list; + /* * Monitor Command Table */ @@ -48,6 +50,7 @@ const char **aliases; /* Implementation function */ int (*cmd)(int, char *[]); + int (*complete)(struct string_list *sl, char *instr); const char *usage; /* Usage message (short) */ struct list_head list; /* List of commands */ @@ -88,6 +91,11 @@ #define BAREBOX_CMD_END \ }; +#ifdef CONFIG_AUTO_COMPLETE +#define BAREBOX_CMD_COMPLETE(_cpt) .complete = _cpt, +#else +#define BAREBOX_CMD_COMPLETE(_cpt) +#endif #define BAREBOX_CMD_HELP_START(_name) \ static const __maybe_unused char cmd_##_name##_help[] = diff --git a/include/complete.h b/include/complete.h index cc0e88d..0c8ebd6 100644 --- a/include/complete.h +++ b/include/complete.h @@ -2,9 +2,16 @@ #define __COMPLETE_ #include +#include +#include + +#define COMPLETE_END 0 +#define COMPLETE_CONTINUE 1 int complete(char *instr, char **outstr); void complete_reset(void); +int command_complete(struct string_list *sl, char *instr); + #endif /* __COMPLETE_ */