ash,hush: allow builtins to be tab-completed, closes 7532
No binary (build failed)
—
(log yok)
| @@ -1818,10 +1818,19 @@ unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC; | |
| # else | |
| # define MAX_HISTORY 0 | |
| # endif | |
| + | typedef const char *get_exe_name_t(int i) FAST_FUNC; |
| typedef struct line_input_t { | |
| int flags; | |
| int timeout; | |
| const char *path_lookup; | |
| + | # if ENABLE_FEATURE_TAB_COMPLETION \ |
| + | && (ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ |
| + | || ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH \ |
| + | ) |
| + | /* function to fetch additional application-specific names to match */ |
| + | get_exe_name_t *get_exe_name; |
| + | # define EDITING_HAS_get_exe_name 1 |
| + | # endif |
| # if MAX_HISTORY | |
| int cnt_history; | |
| int cur_history; | |
| @@ -1868,6 +1877,10 @@ int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; | |
| read_line_input(prompt, command, maxsize) | |
| #endif | |
| + | #ifndef EDITING_HAS_get_exe_name |
| + | # define EDITING_HAS_get_exe_name 0 |
| + | #endif |
| + | |
| #ifndef COMM_LEN | |
| # ifdef TASK_COMM_LEN | |
| @@ -813,18 +813,29 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |
| } | |
| pf_len = strlen(pfind); | |
| - | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 |
| if (type == FIND_EXE_ONLY && !dirbuf) { | |
| + | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 |
| const char *p = applet_names; | |
| - | |
| while (*p) { | |
| if (strncmp(pfind, p, pf_len) == 0) | |
| add_match(xstrdup(p)); | |
| while (*p++ != '\0') | |
| continue; | |
| } | |
| - | } |
| # endif | |
| + | # if EDITING_HAS_get_exe_name |
| + | if (state->get_exe_name) { |
| + | i = 0; |
| + | for (;;) { |
| + | const char *b = state->get_exe_name(i++); |
| + | if (!b) |
| + | break; |
| + | if (strncmp(pfind, b, pf_len) == 0) |
| + | add_match(xstrdup(b)); |
| + | } |
| + | } |
| + | # endif |
| + | } |
| for (i = 0; i < npaths; i++) { | |
| DIR *dir; | |
| @@ -9523,6 +9523,11 @@ evalpipe(union node *n, int flags) | |
| return status; | |
| } | |
| + | /* setinteractive needs this forward reference */ |
| + | #if EDITING_HAS_get_exe_name |
| + | static const char *get_builtin_name(int i) FAST_FUNC; |
| + | #endif |
| + | |
| /* | |
| * Controls whether the shell is interactive or not. | |
| */ | |
| @@ -9554,8 +9559,12 @@ setinteractive(int on) | |
| } | |
| #endif | |
| #if ENABLE_FEATURE_EDITING | |
| - | if (!line_input_state) |
| + | if (!line_input_state) { |
| line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); | |
| + | # if EDITING_HAS_get_exe_name |
| + | line_input_state->get_exe_name = get_builtin_name; |
| + | # endif |
| + | } |
| #endif | |
| } | |
| } | |
| @@ -10023,6 +10032,14 @@ find_builtin(const char *name) | |
| return bp; | |
| } | |
| + | #if EDITING_HAS_get_exe_name |
| + | static const char * FAST_FUNC |
| + | get_builtin_name(int i) |
| + | { |
| + | return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL; |
| + | } |
| + | #endif |
| + | |
| /* | |
| * Execute a simple command. | |
| */ | |
| @@ -7889,6 +7889,20 @@ static const struct built_in_command *find_builtin(const char *name) | |
| return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); | |
| } | |
| + | #if EDITING_HAS_get_exe_name |
| + | static const char * FAST_FUNC get_builtin_name(int i) |
| + | { |
| + | if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { |
| + | return bltins1[i].b_cmd; |
| + | } |
| + | i -= ARRAY_SIZE(bltins1); |
| + | if (i < ARRAY_SIZE(bltins2)) { |
| + | return bltins2[i].b_cmd; |
| + | } |
| + | return NULL; |
| + | } |
| + | #endif |
| + | |
| static void remove_nested_vars(void) | |
| { | |
| struct variable *cur; | |
| @@ -10268,6 +10282,9 @@ int hush_main(int argc, char **argv) | |
| # if ENABLE_FEATURE_EDITING | |
| G.line_input_state = new_line_input_t(FOR_SHELL); | |
| + | # if EDITING_HAS_get_exe_name |
| + | G.line_input_state->get_exe_name = get_builtin_name; |
| + | # endif |
| # endif | |
| # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 | |
| { | |