From e75306bd43d4ed233a7fedddb060a6bdd9305fdc Mon Sep 17 00:00:00 2001 From: Grisha Levit Date: Thu, 13 Apr 2023 04:14:18 -0400 Subject: [PATCH] compgen -V option --- builtins/complete.def | 72 ++++++++++++++++++++++++++++-------- externs.h | 1 + lib/readline/doc/rluser.texi | 11 ++++-- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/builtins/complete.def b/builtins/complete.def index 881c4711..0c68aec1 100644 --- a/builtins/complete.def +++ b/builtins/complete.def @@ -87,7 +87,7 @@ struct _optflags { static int find_compact (char *); static int find_compopt (char *); -static int build_actions (WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *); +static int build_actions (WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *, char **); static int remove_cmd_completions (WORD_LIST *); @@ -177,9 +177,10 @@ find_compopt (char *name) /* Build the actions and compspec options from the options specified in LIST. ACTP is a pointer to an unsigned long in which to place the bitmap of actions. OPTP is a pointer to an unsigned long in which to place the - bitmap of compspec options (arguments to `-o'). PP, if non-null, gets 1 - if -p is supplied; RP, if non-null, gets 1 if -r is supplied. - If either is null, the corresponding option generates an error. + bitmap of compspec options (arguments to `-o'). FLAGP is a pointer to a + struct that stores non-action binary options. VNAMEP is a pointer to a + string to store the name of the output variable. + If any of the above is null, the corresponding option generates an error. This also sets variables corresponding to options that take arguments as a side effect; the caller should ensure that those variables are set to NULL before calling build_actions. Return value: @@ -189,7 +190,7 @@ find_compopt (char *name) */ static int -build_actions (WORD_LIST *list, struct _optflags *flagp, unsigned long *actp, unsigned long *optp) +build_actions (WORD_LIST *list, struct _optflags *flagp, unsigned long *actp, unsigned long *optp, char **vnamep) { int opt, ind, opt_given; unsigned long acts, copts; @@ -199,7 +200,7 @@ build_actions (WORD_LIST *list, struct _optflags *flagp, unsigned long *actp, un opt_given = 0; reset_internal_getopt (); - while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEI")) != -1) + while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:V:DEI")) != -1) { opt_given = 1; switch (opt) @@ -341,6 +342,25 @@ build_actions (WORD_LIST *list, struct _optflags *flagp, unsigned long *actp, un case 'S': Sarg = list_optarg; break; + case 'V': +#if defined (ARRAY_VARS) + if (vnamep) + { + *vnamep = list_optarg; + if (legal_identifier (*vnamep) == 0) + { + sh_invalidid (*vnamep); + return (EX_USAGE); + } + } + else +#endif + { + sh_invalidopt ("-V"); + builtin_usage (); + return (EX_USAGE); + } + break; case 'W': Warg = list_optarg; break; @@ -385,7 +405,7 @@ complete_builtin (WORD_LIST *list) /* Build the actions from the arguments. Also sets the [A-Z]arg variables as a side effect if they are supplied as options. */ - rval = build_actions (list, &oflags, &acts, &copts); + rval = build_actions (list, &oflags, &acts, &copts, (char **)NULL); if (rval == EX_USAGE) return (rval); opt_given = rval != EXECUTION_FAILURE; @@ -630,12 +650,13 @@ print_cmd_completions (WORD_LIST *list) $BUILTIN compgen $DEPENDS_ON PROGRAMMABLE_COMPLETION $FUNCTION compgen_builtin -$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word] +$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [-V var] [word] Display possible completions depending on the options. Intended to be used from within a shell function generating possible completions. If the optional WORD argument is supplied, matches against -WORD are generated. +WORD are generated. With the -V option, completions are stored in the +indexed array VAR. Exit Status: Returns success unless an invalid option is supplied or an error occurs. @@ -651,17 +672,21 @@ compgen_builtin (WORD_LIST *list) char *word, **matches; char *old_line; int old_ind, old_completion, old_quoting, old_suppress; + char *varname; + SHELL_VAR *var; + WORD_LIST *alist; if (list == 0) return (EXECUTION_SUCCESS); acts = copts = (unsigned long)0L; Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL; + varname = (char *)NULL; cs = (COMPSPEC *)NULL; /* Build the actions from the arguments. Also sets the [A-Z]arg variables as a side effect if they are supplied as options. */ - rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts); + rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts, &varname); if (rval == EX_USAGE) return (rval); if (rval == EXECUTION_FAILURE) @@ -728,15 +753,30 @@ compgen_builtin (WORD_LIST *list) rl_filename_quoting_desired = old_quoting; rl_completion_suppress_append = old_suppress; - if (sl) +#if defined (ARRAY_VARS) + if (varname) { - if (sl->list && sl->list_len) - { + var = builtin_find_indexed_array (varname, 1); + if (var && sl && sl->list && sl->list_len) + { + alist = strlist_to_word_list (sl, 0, 0); + assign_array_var_from_word_list (var, alist, 0); + free (sl); + sl = (STRINGLIST *)NULL; + dispose_words (alist); rval = EXECUTION_SUCCESS; - strlist_print (sl, (char *)NULL); - } - strlist_dispose (sl); + } } + else +#endif + if (sl && sl->list && sl->list_len) + { + strlist_print (sl, (char *)NULL); + rval = EXECUTION_SUCCESS; + } + + if (sl) + strlist_dispose (sl); compspec_dispose (cs); return (rval); diff --git a/externs.h b/externs.h index 7c70da92..49f33f20 100644 --- a/externs.h +++ b/externs.h @@ -408,6 +408,7 @@ extern STRINGLIST *strlist_prefix_suffix (STRINGLIST *, const char *, const char extern void strlist_print (STRINGLIST *, const char *); extern void strlist_walk (STRINGLIST *, sh_strlist_map_func_t *); extern void strlist_sort (STRINGLIST *); +extern WORD_LIST *strlist_to_word_list (STRINGLIST *, int, int); /* declarations for functions defined in lib/sh/stringvec.c */ diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index bb1a24f5..d9efb499 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -2106,7 +2106,7 @@ be completed, and two to modify the completion as it is happening. @item compgen @btindex compgen @example -@code{compgen [@var{option}] [@var{word}]} +@code{compgen [@var{option}] [-V @var{var}] [@var{word}]} @end example Generate possible completion matches for @var{word} according to @@ -2124,15 +2124,18 @@ with the same flags. If @var{word} is specified, only those completions matching @var{word} will be displayed. +If the @option{-V} option is supplied, completions will be stored in the +indexed array variable @var{var} instead of being written to stdout. + The return value is true unless an invalid option is supplied, or no matches were generated. @item complete @btindex complete @example -@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DEI] [-A @var{action}] [-G @var{globpat}] -[-W @var{wordlist}] [-F @var{function}] [-C @var{command}] [-X @var{filterpat}] -[-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]} +@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DEI] [-A @var{action}] + [-G @var{globpat}] [-W @var{wordlist}] [-F @var{function}] [-C @var{command}] + [-X @var{filterpat}] [-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]} @code{complete -pr [-DEI] [@var{name} @dots{}]} @end example -- 2.40.0