[PATCH] ash, hush: allow builtins to be tab-completed, closes 7532

Denys Vlasenko vda.linux at googlemail.com
Wed Jan 29 14:24:09 UTC 2020


Applied, thanks

On Tue, Jan 21, 2020 at 5:02 PM Ron Yorston <rmy at pobox.com> wrote:
>
> function                                             old     new   delta
> complete_cmd_dir_file                                768     861     +93
> get_builtin_name                                       -      45     +45
> new_line_input_t                                      31      42     +11
> optschanged                                          112     117      +5
> hush_main                                           1148    1153      +5
> xc_vm_init                                           707     709      +2
> read_line_input                                     2351    2353      +2
> save_command_ps_at_cur_history                        87      86      -1
> ------------------------------------------------------------------------------
> (add/remove: 1/0 grow/shrink: 6/1 up/down: 163/-1)            Total: 162 bytes
>
> Signed-off-by: Ron Yorston <rmy at pobox.com>
> ---
>  include/libbb.h  | 10 ++++++++++
>  libbb/lineedit.c | 47 +++++++++++++++++++++++++++++++++--------------
>  miscutils/bc.c   |  2 +-
>  shell/ash.c      | 16 +++++++++++++++-
>  shell/hush.c     | 17 ++++++++++++++++-
>  5 files changed, 75 insertions(+), 17 deletions(-)
>
> diff --git a/include/libbb.h b/include/libbb.h
> index 05a560977..68aff9f5c 100644
> --- a/include/libbb.h
> +++ b/include/libbb.h
> @@ -1818,10 +1818,15 @@ unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC;
>  # else
>  #  define MAX_HISTORY 0
>  # endif
> +typedef const char *(*get_name_t)(int i);
>  typedef struct line_input_t {
>         int flags;
>         int timeout;
>         const char *path_lookup;
> +# if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
> +       /* function to fetch additional application-specific names to match */
> +       get_name_t get_name;
> +#endif
>  # if MAX_HISTORY
>         int cnt_history;
>         int cur_history;
> @@ -1847,7 +1852,12 @@ enum {
>         WITH_PATH_LOOKUP = 0x10,
>         FOR_SHELL        = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
>  };
> +# if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
> +line_input_t *new_line_input_t(int flags, get_name_t fn) FAST_FUNC;
> +# else
>  line_input_t *new_line_input_t(int flags) FAST_FUNC;
> +#define new_line_input_t(fl, fn) new_line_input_t(fl)
> +# endif
>  void free_line_input_t(line_input_t *n) FAST_FUNC;
>  /*
>   * maxsize must be >= 2.
> diff --git a/libbb/lineedit.c b/libbb/lineedit.c
> index b1ec52b88..26d26b9da 100644
> --- a/libbb/lineedit.c
> +++ b/libbb/lineedit.c
> @@ -826,6 +826,17 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
>         }
>  # endif
>
> +# if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
> +       if (type == FIND_EXE_ONLY && !dirbuf) {
> +               const char *p;
> +
> +               for (i = 0; state->get_name && (p=state->get_name(i)); i++) {
> +                       if (strncmp(pfind, p, pf_len) == 0)
> +                               add_match(xstrdup(p));
> +               }
> +       }
> +# endif
> +
>         for (i = 0; i < npaths; i++) {
>                 DIR *dir;
>                 struct dirent *next;
> @@ -1300,18 +1311,6 @@ static NOINLINE void input_tab(smallint *lastWasTab)
>  #endif  /* FEATURE_TAB_COMPLETION */
>
>
> -line_input_t* FAST_FUNC new_line_input_t(int flags)
> -{
> -       line_input_t *n = xzalloc(sizeof(*n));
> -       n->flags = flags;
> -       n->timeout = -1;
> -#if MAX_HISTORY > 0
> -       n->max_history = MAX_HISTORY;
> -#endif
> -       return n;
> -}
> -
> -
>  #if MAX_HISTORY > 0
>
>  unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp)
> @@ -1486,7 +1485,7 @@ void save_history(line_input_t *st)
>
>                 /* we may have concurrently written entries from others.
>                  * load them */
> -               st_temp = new_line_input_t(st->flags);
> +               st_temp = new_line_input_t(st->flags, NULL);
>                 st_temp->hist_file = st->hist_file;
>                 st_temp->max_history = st->max_history;
>                 load_history(st_temp);
> @@ -1535,7 +1534,7 @@ static void save_history(char *str)
>
>                 /* we may have concurrently written entries from others.
>                  * load them */
> -               st_temp = new_line_input_t(state->flags);
> +               st_temp = new_line_input_t(state->flags, NULL);
>                 st_temp->hist_file = state->hist_file;
>                 st_temp->max_history = state->max_history;
>                 load_history(st_temp);
> @@ -1607,6 +1606,26 @@ static void remember_in_history(char *str)
>  #endif /* MAX_HISTORY */
>
>
> +#if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
> +line_input_t* FAST_FUNC new_line_input_t(int flags, get_name_t fn)
> +#else
> +#undef new_line_input_t
> +line_input_t* FAST_FUNC new_line_input_t(int flags)
> +#endif
> +{
> +       line_input_t *n = xzalloc(sizeof(*n));
> +       n->flags = flags;
> +       n->timeout = -1;
> +#if MAX_HISTORY > 0
> +       n->max_history = MAX_HISTORY;
> +#endif
> +#if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
> +       n->get_name = fn;
> +#endif
> +       return n;
> +}
> +
> +
>  #if ENABLE_FEATURE_EDITING_VI
>  /*
>   * vi mode implemented 2005 by Paul Fox <pgf at foxharp.boston.ma.us>
> diff --git a/miscutils/bc.c b/miscutils/bc.c
> index c7246ea1a..9c9d28eb5 100644
> --- a/miscutils/bc.c
> +++ b/miscutils/bc.c
> @@ -7379,7 +7379,7 @@ static int xc_vm_init(const char *env_len)
>  {
>         G.prog.len = xc_vm_envLen(env_len);
>  #if ENABLE_FEATURE_EDITING
> -       G.line_input_state = new_line_input_t(DO_HISTORY);
> +       G.line_input_state = new_line_input_t(DO_HISTORY, NULL);
>  #endif
>         bc_vec_init(&G.files, sizeof(char *), NULL);
>
> diff --git a/shell/ash.c b/shell/ash.c
> index 4b5eafa7c..a6b7a7b04 100644
> --- a/shell/ash.c
> +++ b/shell/ash.c
> @@ -9523,6 +9523,11 @@ evalpipe(union node *n, int flags)
>         return status;
>  }
>
> +/* setinteractive needs this forward reference */
> +#if ENABLE_FEATURE_TAB_COMPLETION
> +static const char *get_builtin_name(int i);
> +#endif
> +
>  /*
>   * Controls whether the shell is interactive or not.
>   */
> @@ -9555,7 +9560,8 @@ setinteractive(int on)
>  #endif
>  #if ENABLE_FEATURE_EDITING
>                 if (!line_input_state)
> -                       line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
> +                       line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP,
> +                                                               get_builtin_name);
>  #endif
>         }
>  }
> @@ -10023,6 +10029,14 @@ find_builtin(const char *name)
>         return bp;
>  }
>
> +#if ENABLE_FEATURE_TAB_COMPLETION
> +static const char *
> +get_builtin_name(int i)
> +{
> +    return i >= 0 && i < ARRAY_SIZE(builtintab) ? builtintab[i].name+1 : NULL;
> +}
> +#endif
> +
>  /*
>   * Execute a simple command.
>   */
> diff --git a/shell/hush.c b/shell/hush.c
> index 97202b953..ea358cdb1 100644
> --- a/shell/hush.c
> +++ b/shell/hush.c
> @@ -7889,6 +7889,21 @@ static const struct built_in_command *find_builtin(const char *name)
>         return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
>  }
>
> +#if ENABLE_FEATURE_TAB_COMPLETION
> +static const char *
> +get_builtin_name(int i)
> +{
> +       if (i >= 0 && i < ARRAY_SIZE(bltins1)) {
> +               return bltins1[i].b_cmd;
> +       }
> +       i -= ARRAY_SIZE(bltins1);
> +       if (i >= 0 && i < ARRAY_SIZE(bltins2)) {
> +               return bltins2[i].b_cmd;
> +       }
> +       return NULL;
> +}
> +#endif
> +
>  static void remove_nested_vars(void)
>  {
>         struct variable *cur;
> @@ -10267,7 +10282,7 @@ int hush_main(int argc, char **argv)
>                 enable_restore_tty_pgrp_on_exit();
>
>  # if ENABLE_FEATURE_EDITING
> -               G.line_input_state = new_line_input_t(FOR_SHELL);
> +               G.line_input_state = new_line_input_t(FOR_SHELL, get_builtin_name);
>  # endif
>  # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
>                 {
> --
> 2.24.1
>
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list