diff options
Diffstat (limited to 'builtins/complete.def')
-rw-r--r-- | builtins/complete.def | 349 |
1 files changed, 298 insertions, 51 deletions
diff --git a/builtins/complete.def b/builtins/complete.def index a859b88..2267794 100644 --- a/builtins/complete.def +++ b/builtins/complete.def @@ -1,35 +1,50 @@ This file is complete.def, from which is created complete.c. -It implements the builtins "complete" and "compgen" in Bash. +It implements the builtins "complete", "compgen", and "compopt" in Bash. -Copyright (C) 1999-2003 Free Software Foundation, Inc. +Copyright (C) 1999-2009 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. -Bash is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. +Bash is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. -Bash is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. +Bash is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. -You should have received a copy of the GNU General Public License along -with Bash; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. +You should have received a copy of the GNU General Public License +along with Bash. If not, see <http://www.gnu.org/licenses/>. $PRODUCES complete.c $BUILTIN complete $DEPENDS_ON PROGRAMMABLE_COMPLETION $FUNCTION complete_builtin -$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...] -For each NAME, specify how arguments are to be completed. -If the -p option is supplied, or if no options are supplied, existing -completion specifications are printed in a way that allows them to be -reused as input. The -r option removes a completion specification for -each NAME, or, if no NAMEs are supplied, all completion specifications. +$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...] +Specify how arguments are to be completed by Readline. + +For each NAME, specify how arguments are to be completed. If no options +are supplied, existing completion specifications are printed in a way that +allows them to be reused as input. + +Options: + -p print existing completion specifications in a reusable format + -r remove a completion specification for each NAME, or, if no + NAMEs are supplied, all completion specifications + -D apply the completions and actions as the default for commands + without any specific completion defined + -E apply the completions and actions to "empty" commands -- + completion attempted on a blank line + +When completion is attempted, the actions are applied in the order the +uppercase-letter options are listed above. The -D option takes +precedence over -E. + +Exit Status: +Returns success unless an invalid option is supplied or an error occurs. $END #include <config.h> @@ -57,22 +72,32 @@ $END #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL) +/* Structure containing all the non-action (binary) options; filled in by + build_actions(). */ +struct _optflags { + int pflag; + int rflag; + int Dflag; + int Eflag; +}; + static int find_compact __P((char *)); static int find_compopt __P((char *)); -static int build_actions __P((WORD_LIST *, int *, int *, unsigned long *, unsigned long *)); +static int build_actions __P((WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *)); static int remove_cmd_completions __P((WORD_LIST *)); static int print_one_completion __P((char *, COMPSPEC *)); static int print_compitem __P((BUCKET_CONTENTS *)); +static void print_compopts __P((const char *, COMPSPEC *, int)); static void print_all_completions __P((void)); static int print_cmd_completions __P((WORD_LIST *)); static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg; -static struct _compacts { - char *actname; +static const struct _compacts { + const char * const actname; int actflag; int actopt; } compacts[] = { @@ -104,8 +129,8 @@ static struct _compacts { }; /* This should be a STRING_INT_ALIST */ -static struct _compopt { - char *optname; +const static struct _compopt { + const char * const optname; int optflag; } compopts[] = { { "bashdefault", COPT_BASHDEFAULT }, @@ -156,9 +181,9 @@ find_compopt (name) */ static int -build_actions (list, pp, rp, actp, optp) +build_actions (list, flagp, actp, optp) WORD_LIST *list; - int *pp, *rp; + struct _optflags *flagp; unsigned long *actp, *optp; { int opt, ind, opt_given; @@ -168,15 +193,15 @@ build_actions (list, pp, rp, actp, optp) opt_given = 0; reset_internal_getopt (); - while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:")) != -1) + while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DE")) != -1) { opt_given = 1; switch (opt) { case 'r': - if (rp) + if (flagp) { - *rp = 1; + flagp->rflag = 1; break; } else @@ -187,9 +212,9 @@ build_actions (list, pp, rp, actp, optp) } case 'p': - if (pp) + if (flagp) { - *pp = 1; + flagp->pflag = 1; break; } else @@ -256,6 +281,30 @@ build_actions (list, pp, rp, actp, optp) case 'C': Carg = list_optarg; break; + case 'D': + if (flagp) + { + flagp->Dflag = 1; + break; + } + else + { + sh_invalidopt ("-D"); + builtin_usage (); + return (EX_USAGE); + } + case 'E': + if (flagp) + { + flagp->Eflag = 1; + break; + } + else + { + sh_invalidopt ("-E"); + builtin_usage (); + return (EX_USAGE); + } case 'F': Farg = list_optarg; break; @@ -291,9 +340,11 @@ int complete_builtin (list) WORD_LIST *list; { - int opt_given, pflag, rflag, rval; + int opt_given, rval; unsigned long acts, copts; COMPSPEC *cs; + struct _optflags oflags; + WORD_LIST *l, *wl; if (list == 0) { @@ -301,24 +352,34 @@ complete_builtin (list) return (EXECUTION_SUCCESS); } - opt_given = pflag = rflag = 0; + opt_given = oflags.pflag = oflags.rflag = oflags.Dflag = oflags.Eflag = 0; + acts = copts = (unsigned long)0L; Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (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, &pflag, &rflag, &acts, &copts); + rval = build_actions (list, &oflags, &acts, &copts); if (rval == EX_USAGE) return (rval); opt_given = rval != EXECUTION_FAILURE; list = loptend; + wl = oflags.Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL) + : (oflags.Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL) : 0); + /* -p overrides everything else */ - if (pflag || (list == 0 && opt_given == 0)) + if (oflags.pflag || (list == 0 && opt_given == 0)) { - if (list == 0) + if (wl) + { + rval = print_cmd_completions (wl); + dispose_words (wl); + return rval; + } + else if (list == 0) { print_all_completions (); return (EXECUTION_SUCCESS); @@ -327,9 +388,15 @@ complete_builtin (list) } /* next, -r overrides everything else. */ - if (rflag) + if (oflags.rflag) { - if (list == 0) + if (wl) + { + rval = remove_cmd_completions (wl); + dispose_words (wl); + return rval; + } + else if (list == 0) { progcomp_flush (); return (EXECUTION_SUCCESS); @@ -337,7 +404,7 @@ complete_builtin (list) return (remove_cmd_completions (list)); } - if (list == 0 && opt_given) + if (wl == 0 && list == 0 && opt_given) { builtin_usage (); return (EX_USAGE); @@ -357,13 +424,14 @@ complete_builtin (list) cs->command = STRDUP (Carg); cs->filterpat = STRDUP (Xarg); - for (rval = EXECUTION_SUCCESS ; list; list = list->next) + for (rval = EXECUTION_SUCCESS, l = wl ? wl : list ; l; l = l->next) { /* Add CS as the compspec for the specified commands. */ - if (progcomp_insert (list->word->word, cs) == 0) + if (progcomp_insert (l->word->word, cs) == 0) rval = EXECUTION_FAILURE; } + dispose_words (wl); return (rval); } @@ -419,6 +487,14 @@ remove_cmd_completions (list) printf ("-o %s ", f); \ } while (0) +#define XPRINTCOMPOPT(a, f) \ + do { \ + if (copts & a) \ + printf ("-o %s ", f); \ + else \ + printf ("+o %s ", f); \ + } while (0) + static int print_one_completion (cmd, cs) char *cmd; @@ -478,15 +554,59 @@ print_one_completion (cmd, cs) SQPRINTARG (cs->suffix, "-S"); SQPRINTARG (cs->filterpat, "-X"); + SQPRINTARG (cs->command, "-C"); + /* simple arguments that don't require quoting */ PRINTARG (cs->funcname, "-F"); - PRINTARG (cs->command, "-C"); - printf ("%s\n", cmd); + if (STREQ (cmd, EMPTYCMD)) + printf ("-E\n"); + else if (STREQ (cmd, DEFAULTCMD)) + printf ("-D\n"); + else + printf ("%s\n", cmd); return (0); } +static void +print_compopts (cmd, cs, full) + const char *cmd; + COMPSPEC *cs; + int full; +{ + int copts; + + printf ("compopt "); + copts = cs->options; + + if (full) + { + XPRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault"); + XPRINTCOMPOPT (COPT_DEFAULT, "default"); + XPRINTCOMPOPT (COPT_DIRNAMES, "dirnames"); + XPRINTCOMPOPT (COPT_FILENAMES, "filenames"); + XPRINTCOMPOPT (COPT_NOSPACE, "nospace"); + XPRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs"); + } + else + { + PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault"); + PRINTCOMPOPT (COPT_DEFAULT, "default"); + PRINTCOMPOPT (COPT_DIRNAMES, "dirnames"); + PRINTCOMPOPT (COPT_FILENAMES, "filenames"); + PRINTCOMPOPT (COPT_NOSPACE, "nospace"); + PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs"); + } + + if (STREQ (cmd, EMPTYCMD)) + printf ("-E\n"); + else if (STREQ (cmd, DEFAULTCMD)) + printf ("-D\n"); + else + printf ("%s\n", cmd); +} + static int print_compitem (item) BUCKET_CONTENTS *item; @@ -525,17 +645,22 @@ print_cmd_completions (list) ret = EXECUTION_FAILURE; } } - return (ret); + + return (sh_chkwrite (ret)); } $BUILTIN compgen $DEPENDS_ON PROGRAMMABLE_COMPLETION $FUNCTION compgen_builtin -$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word] -Display the 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. +$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [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. + +Exit Status: +Returns success unless an invalid option is supplied or an error occurs. $END int @@ -557,7 +682,7 @@ compgen_builtin (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, (int *)NULL, (int *)NULL, &acts, &copts); + rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts); if (rval == EX_USAGE) return (rval); if (rval == EXECUTION_FAILURE) @@ -587,7 +712,7 @@ compgen_builtin (list) cs->filterpat = STRDUP (Xarg); rval = EXECUTION_FAILURE; - sl = gen_compspec_completions (cs, "compgen", word, 0, 0); + sl = gen_compspec_completions (cs, "compgen", word, 0, 0, 0); /* If the compspec wants the bash default completions, temporarily turn off programmable completion and call the bash completion code. */ @@ -620,3 +745,125 @@ compgen_builtin (list) compspec_dispose (cs); return (rval); } + +$BUILTIN compopt +$DEPENDS_ON PROGRAMMABLE_COMPLETION +$FUNCTION compopt_builtin +$SHORT_DOC compopt [-o|+o option] [-DE] [name ...] +Modify or display completion options. + +Modify the completion options for each NAME, or, if no NAMEs are supplied, +the completion currently begin executed. If no OPTIONs are givenm, print +the completion options for each NAME or the current completion specification. + +Options: + -o option Set completion option OPTION for each NAME + -D Change options for the "default" command completion + -E Change options for the "empty" command completion + +Using `+o' instead of `-o' turns off the specified option. + +Arguments: + +Each NAME refers to a command for which a completion specification must +have previously been defined using the `complete' builtin. If no NAMEs +are supplied, compopt must be called by a function currently generating +completions, and the options for that currently-executing completion +generator are modified. + +Exit Status: +Returns success unless an invalid option is supplied or NAME does not +have a completion specification defined. +$END + +int +compopt_builtin (list) + WORD_LIST *list; +{ + int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag; + WORD_LIST *l, *wl; + COMPSPEC *cs; + + opts_on = opts_off = Eflag = Dflag = 0; + ret = EXECUTION_SUCCESS; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "+o:DE")) != EOF) + { + opts = (list_opttype == '-') ? &opts_on : &opts_off; + + switch (opt) + { + case 'o': + oind = find_compopt (list_optarg); + if (oind < 0) + { + sh_invalidoptname (list_optarg); + return (EX_USAGE); + } + *opts |= compopts[oind].optflag; + break; + case 'D': + Dflag = 1; + break; + case 'E': + Eflag = 1; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + wl = Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL) + : (Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL) : 0); + + if (list == 0 && wl == 0) + { + if (RL_ISSTATE (RL_STATE_COMPLETING) == 0 || pcomp_curcs == 0) + { + builtin_error (_("not currently executing completion function")); + return (EXECUTION_FAILURE); + } + cs = pcomp_curcs; + + if (opts_on == 0 && opts_off == 0) + { + print_compopts (pcomp_curcmd, cs, 1); + return (sh_chkwrite (ret)); + } + + /* Set the compspec options */ + pcomp_set_compspec_options (cs, opts_on, 1); + pcomp_set_compspec_options (cs, opts_off, 0); + + /* And change the readline variables the options control */ + pcomp_set_readline_variables (opts_on, 1); + pcomp_set_readline_variables (opts_off, 0); + + return (ret); + } + + for (l = wl ? wl : list; l; l = l->next) + { + cs = progcomp_search (l->word->word); + if (cs == 0) + { + builtin_error (_("%s: no completion specification"), l->word->word); + ret = EXECUTION_FAILURE; + continue; + } + if (opts_on == 0 && opts_off == 0) + { + print_compopts (l->word->word, cs, 1); + continue; /* XXX -- fill in later */ + } + + /* Set the compspec options */ + pcomp_set_compspec_options (cs, opts_on, 1); + pcomp_set_compspec_options (cs, opts_off, 0); + } + + return (ret); +} |