diff options
author | Ron Yorston <rmy@pobox.com> | 2023-04-10 10:20:15 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-04-10 11:45:46 +0100 |
commit | 66c9b8f39acbba587eda0cababa3de37e89b8dff (patch) | |
tree | 732e6265edfd8e3a627c29f2b10410c9fa789ca6 | |
parent | 3165054d234e0f37f1a230312f1fd2ab3677bbc0 (diff) | |
download | busybox-w32-66c9b8f39acbba587eda0cababa3de37e89b8dff.tar.gz busybox-w32-66c9b8f39acbba587eda0cababa3de37e89b8dff.tar.bz2 busybox-w32-66c9b8f39acbba587eda0cababa3de37e89b8dff.zip |
ash,hush: tab completion of functions and aliases
Rework the 'get_exe_name' functions in ash and hush so functions
and aliases are considered when tab-completing a command.
function old new delta
ash_command_name - 188 +188
hush_command_name - 118 +118
complete_cmd_dir_file 876 880 +4
ash_builtin_name 17 - -17
hush_builtin_name 38 - -38
------------------------------------------------------------------------------
(add/remove: 2/2 grow/shrink: 1/0 up/down: 310/-55) Total: 255 bytes
(GitHub issue #301)
Signed-off-by: Ron Yorston <rmy@pobox.com>
-rw-r--r-- | include/libbb.h | 9 | ||||
-rw-r--r-- | libbb/lineedit.c | 8 | ||||
-rw-r--r-- | shell/ash.c | 48 | ||||
-rw-r--r-- | shell/hush.c | 34 |
4 files changed, 84 insertions, 15 deletions
diff --git a/include/libbb.h b/include/libbb.h index 6191debb1..66781da4f 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1924,7 +1924,14 @@ unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC; | |||
1924 | # else | 1924 | # else |
1925 | # define MAX_HISTORY 0 | 1925 | # define MAX_HISTORY 0 |
1926 | # endif | 1926 | # endif |
1927 | typedef const char *get_exe_name_t(int i) FAST_FUNC; | 1927 | typedef struct exe_state { |
1928 | int e_type; /* type of tab completion: builtin, alias, function */ | ||
1929 | int e_index; /* index of current table entry or hash bucket */ | ||
1930 | # if ENABLE_SHELL_ASH || (ENABLE_SHELL_HUSH && ENABLE_HUSH_FUNCTIONS) | ||
1931 | void *e_ptr; /* current position in linked list */ | ||
1932 | # endif | ||
1933 | } exe_state; | ||
1934 | typedef const char *get_exe_name_t(exe_state *e) FAST_FUNC; | ||
1928 | typedef const char *sh_get_var_t(const char *name) FAST_FUNC; | 1935 | typedef const char *sh_get_var_t(const char *name) FAST_FUNC; |
1929 | typedef struct line_input_t { | 1936 | typedef struct line_input_t { |
1930 | int flags; | 1937 | int flags; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 625884adf..5daceff16 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -875,9 +875,13 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
875 | # endif | 875 | # endif |
876 | # if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH | 876 | # if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH |
877 | if (state->get_exe_name) { | 877 | if (state->get_exe_name) { |
878 | i = 0; | 878 | # if ENABLE_SHELL_ASH || (ENABLE_SHELL_HUSH && ENABLE_HUSH_FUNCTIONS) |
879 | exe_state e = { 0, 0, NULL }; | ||
880 | # else | ||
881 | exe_state e = { 0, 0 }; | ||
882 | # endif | ||
879 | for (;;) { | 883 | for (;;) { |
880 | const char *b = state->get_exe_name(i++); | 884 | const char *b = state->get_exe_name(&e); |
881 | if (!b) | 885 | if (!b) |
882 | break; | 886 | break; |
883 | if (strncmp(basecmd, b, baselen) == 0) | 887 | if (strncmp(basecmd, b, baselen) == 0) |
diff --git a/shell/ash.c b/shell/ash.c index 26239ff09..c77ee8620 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9732,7 +9732,7 @@ evalpipe(union node *n, int flags) | |||
9732 | 9732 | ||
9733 | /* setinteractive needs this forward reference */ | 9733 | /* setinteractive needs this forward reference */ |
9734 | #if ENABLE_FEATURE_TAB_COMPLETION | 9734 | #if ENABLE_FEATURE_TAB_COMPLETION |
9735 | static const char *ash_builtin_name(int i) FAST_FUNC; | 9735 | static const char *ash_command_name(exe_state *e) FAST_FUNC; |
9736 | #endif | 9736 | #endif |
9737 | 9737 | ||
9738 | /* | 9738 | /* |
@@ -9769,7 +9769,7 @@ setinteractive(int on) | |||
9769 | if (!line_input_state) { | 9769 | if (!line_input_state) { |
9770 | line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); | 9770 | line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); |
9771 | # if ENABLE_FEATURE_TAB_COMPLETION | 9771 | # if ENABLE_FEATURE_TAB_COMPLETION |
9772 | line_input_state->get_exe_name = ash_builtin_name; | 9772 | line_input_state->get_exe_name = ash_command_name; |
9773 | # endif | 9773 | # endif |
9774 | # if EDITING_HAS_sh_get_var | 9774 | # if EDITING_HAS_sh_get_var |
9775 | line_input_state->sh_get_var = lookupvar; | 9775 | line_input_state->sh_get_var = lookupvar; |
@@ -10284,9 +10284,47 @@ find_builtin(const char *name) | |||
10284 | 10284 | ||
10285 | #if ENABLE_FEATURE_TAB_COMPLETION | 10285 | #if ENABLE_FEATURE_TAB_COMPLETION |
10286 | static const char * FAST_FUNC | 10286 | static const char * FAST_FUNC |
10287 | ash_builtin_name(int i) | 10287 | ash_command_name(struct exe_state *e) |
10288 | { | 10288 | { |
10289 | return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL; | 10289 | if (e->e_type == 0) { |
10290 | if (/*e->e_index >= 0 &&*/ e->e_index < ARRAY_SIZE(builtintab)) { | ||
10291 | return builtintab[e->e_index++].name + 1; | ||
10292 | } | ||
10293 | e->e_type++; | ||
10294 | e->e_index = 0; | ||
10295 | e->e_ptr = cmdtable[0]; | ||
10296 | } | ||
10297 | if (e->e_type == 1) { | ||
10298 | struct tblentry *cmdp = (struct tblentry *)e->e_ptr; | ||
10299 | while (e->e_index < CMDTABLESIZE) { | ||
10300 | while (cmdp) { | ||
10301 | if (cmdp->cmdtype == CMDFUNCTION) { | ||
10302 | e->e_ptr = cmdp->next; | ||
10303 | return cmdp->cmdname; | ||
10304 | } | ||
10305 | cmdp = cmdp->next; | ||
10306 | } | ||
10307 | cmdp = cmdtable[++e->e_index]; | ||
10308 | } | ||
10309 | # if ENABLE_ASH_ALIAS | ||
10310 | e->e_type++; | ||
10311 | e->e_index = 0; | ||
10312 | e->e_ptr = atab[0]; | ||
10313 | # endif | ||
10314 | } | ||
10315 | # if ENABLE_ASH_ALIAS | ||
10316 | if (e->e_type == 2) { | ||
10317 | struct alias *ap = (struct alias *)e->e_ptr; | ||
10318 | while (e->e_index < ATABSIZE) { | ||
10319 | while (ap) { | ||
10320 | e->e_ptr = ap->next; | ||
10321 | return ap->name; | ||
10322 | } | ||
10323 | ap = atab[++e->e_index]; | ||
10324 | } | ||
10325 | } | ||
10326 | # endif | ||
10327 | return NULL; | ||
10290 | } | 10328 | } |
10291 | #endif | 10329 | #endif |
10292 | 10330 | ||
diff --git a/shell/hush.c b/shell/hush.c index 330a0aa79..443bdeccf 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -8220,15 +8220,35 @@ static const struct built_in_command *find_builtin(const char *name) | |||
8220 | } | 8220 | } |
8221 | 8221 | ||
8222 | #if ENABLE_HUSH_JOB && ENABLE_FEATURE_TAB_COMPLETION | 8222 | #if ENABLE_HUSH_JOB && ENABLE_FEATURE_TAB_COMPLETION |
8223 | static const char * FAST_FUNC hush_builtin_name(int i) | 8223 | static const char * FAST_FUNC hush_command_name(exe_state *e) |
8224 | { | 8224 | { |
8225 | if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { | 8225 | if (e->e_type == 0) { |
8226 | return bltins1[i].b_cmd; | 8226 | if (/*e->e_index >= 0 && */ e->e_index < ARRAY_SIZE(bltins1)) { |
8227 | return bltins1[e->e_index++].b_cmd; | ||
8228 | } | ||
8229 | e->e_type++; | ||
8230 | e->e_index = 0; | ||
8231 | /* e->e_ptr = NULL; */ | ||
8232 | } | ||
8233 | if (e->e_type == 1) { | ||
8234 | if (e->e_index < ARRAY_SIZE(bltins2)) { | ||
8235 | return bltins2[e->e_index++].b_cmd; | ||
8236 | } | ||
8237 | # if ENABLE_HUSH_FUNCTIONS | ||
8238 | e->e_type++; | ||
8239 | /* e->e_index = 0; */ | ||
8240 | e->e_ptr = G.top_func; | ||
8241 | # endif | ||
8227 | } | 8242 | } |
8228 | i -= ARRAY_SIZE(bltins1); | 8243 | # if ENABLE_HUSH_FUNCTIONS |
8229 | if (i < ARRAY_SIZE(bltins2)) { | 8244 | if (e->e_type == 2) { |
8230 | return bltins2[i].b_cmd; | 8245 | struct function *funcp = (struct function *)e->e_ptr; |
8246 | while (funcp) { | ||
8247 | e->e_ptr = funcp->next; | ||
8248 | return funcp->name; | ||
8249 | } | ||
8231 | } | 8250 | } |
8251 | # endif | ||
8232 | return NULL; | 8252 | return NULL; |
8233 | } | 8253 | } |
8234 | #endif | 8254 | #endif |
@@ -10716,7 +10736,7 @@ int hush_main(int argc, char **argv) | |||
10716 | # if ENABLE_FEATURE_EDITING | 10736 | # if ENABLE_FEATURE_EDITING |
10717 | G.line_input_state = new_line_input_t(FOR_SHELL); | 10737 | G.line_input_state = new_line_input_t(FOR_SHELL); |
10718 | # if ENABLE_FEATURE_TAB_COMPLETION | 10738 | # if ENABLE_FEATURE_TAB_COMPLETION |
10719 | G.line_input_state->get_exe_name = hush_builtin_name; | 10739 | G.line_input_state->get_exe_name = hush_command_name; |
10720 | # endif | 10740 | # endif |
10721 | # if EDITING_HAS_sh_get_var | 10741 | # if EDITING_HAS_sh_get_var |
10722 | G.line_input_state->sh_get_var = get_local_var_value; | 10742 | G.line_input_state->sh_get_var = get_local_var_value; |