1This file is complete.def, from which is created complete.c.
2It implements the builtins "complete" and "compgen" in Bash.
3
4Copyright (C) 1999-2003 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING.  If not, write to the Free Software
20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22$PRODUCES complete.c
23
24$BUILTIN complete
25$DEPENDS_ON PROGRAMMABLE_COMPLETION
26$FUNCTION complete_builtin
27$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]
28For each NAME, specify how arguments are to be completed.
29If the -p option is supplied, or if no options are supplied, existing
30completion specifications are printed in a way that allows them to be
31reused as input.  The -r option removes a completion specification for
32each NAME, or, if no NAMEs are supplied, all completion specifications.
33$END
34
35#include <config.h>
36
37#include <stdio.h>
38
39#include "../bashtypes.h"
40
41#if defined (HAVE_UNISTD_H)
42#  include <unistd.h>
43#endif
44
45#include "../bashansi.h"
46#include "../bashintl.h"
47
48#include "../shell.h"
49#include "../builtins.h"
50#include "../pcomplete.h"
51#include "../bashline.h"
52
53#include "common.h"
54#include "bashgetopt.h"
55
56#include <readline/readline.h>
57
58#define STRDUP(x)       ((x) ? savestring (x) : (char *)NULL)
59
60static int find_compact __P((char *));
61static int find_compopt __P((char *));
62
63static int build_actions __P((WORD_LIST *, int *, int *, unsigned long *, unsigned long *));
64
65static int remove_cmd_completions __P((WORD_LIST *));
66
67static int print_one_completion __P((char *, COMPSPEC *));
68static int print_compitem __P((BUCKET_CONTENTS *));
69static void print_all_completions __P((void));
70static int print_cmd_completions __P((WORD_LIST *));
71
72static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
73
74static struct _compacts {
75  char *actname;
76  int actflag;
77  int actopt;
78} compacts[] = {
79  { "alias",     CA_ALIAS,     'a' },
80  { "arrayvar",  CA_ARRAYVAR,   0 },
81  { "binding",   CA_BINDING,    0 },
82  { "builtin",   CA_BUILTIN,   'b' },
83  { "command",   CA_COMMAND,   'c' },
84  { "directory", CA_DIRECTORY, 'd' },
85  { "disabled",  CA_DISABLED,   0 },
86  { "enabled",   CA_ENABLED,    0 },
87  { "export",    CA_EXPORT,    'e' },
88  { "file",      CA_FILE,      'f' },
89  { "function",  CA_FUNCTION,   0 },
90  { "helptopic", CA_BUILTIN,  0 },	/* for now */
91  { "hostname",  CA_HOSTNAME,   0 },
92  { "group",     CA_GROUP,     'g' },
93  { "job",       CA_JOB,       'j' },
94  { "keyword",   CA_KEYWORD,   'k' },
95  { "running",   CA_RUNNING,    0 },
96  { "service",   CA_SERVICE,   's' },
97  { "setopt",    CA_SETOPT,     0 },
98  { "shopt",     CA_SHOPT,      0 },
99  { "signal",    CA_SIGNAL,     0 },
100  { "stopped",   CA_STOPPED,    0 },
101  { "user",      CA_USER,      'u' },
102  { "variable",  CA_VARIABLE,  'v' },
103  { (char *)NULL, 0, 0 },
104};
105
106/* This should be a STRING_INT_ALIST */
107static struct _compopt {
108  char *optname;
109  int optflag;
110} compopts[] = {
111  { "bashdefault", COPT_BASHDEFAULT },
112  { "default",	COPT_DEFAULT },
113  { "dirnames", COPT_DIRNAMES },
114  { "filenames",COPT_FILENAMES},
115  { "nospace",	COPT_NOSPACE },
116  { "plusdirs", COPT_PLUSDIRS },
117  { (char *)NULL, 0 },
118};
119
120static int
121find_compact (name)
122     char *name;
123{
124  register int i;
125
126  for (i = 0; compacts[i].actname; i++)
127    if (STREQ (name, compacts[i].actname))
128      return i;
129  return -1;
130}
131
132static int
133find_compopt (name)
134     char *name;
135{
136  register int i;
137
138  for (i = 0; compopts[i].optname; i++)
139    if (STREQ (name, compopts[i].optname))
140      return i;
141  return -1;
142}
143
144/* Build the actions and compspec options from the options specified in LIST.
145   ACTP is a pointer to an unsigned long in which to place the bitmap of
146   actions.  OPTP is a pointer to an unsigned long in which to place the
147   btmap of compspec options (arguments to `-o').  PP, if non-null, gets 1
148   if -p is supplied; RP, if non-null, gets 1 if -r is supplied.
149   If either is null, the corresponding option generates an error.
150   This also sets variables corresponding to options that take arguments as
151   a side effect; the caller should ensure that those variables are set to
152   NULL before calling build_actions.  Return value:
153   	EX_USAGE = bad option
154   	EXECUTION_SUCCESS = some options supplied
155   	EXECUTION_FAILURE = no options supplied
156*/
157
158static int
159build_actions (list, pp, rp, actp, optp)
160     WORD_LIST *list;
161     int *pp, *rp;
162     unsigned long *actp, *optp;
163{
164  int opt, ind, opt_given;
165  unsigned long acts, copts;
166
167  acts = copts = (unsigned long)0L;
168  opt_given = 0;
169
170  reset_internal_getopt ();
171  while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:")) != -1)
172    {
173      opt_given = 1;
174      switch (opt)
175	{
176	case 'r':
177	  if (rp)
178	    {
179	      *rp = 1;
180	      break;
181	    }
182	  else
183	    {
184	      sh_invalidopt ("-r");
185	      builtin_usage ();
186	      return (EX_USAGE);
187	    }
188
189	case 'p':
190	  if (pp)
191	    {
192	      *pp = 1;
193	      break;
194	    }
195	  else
196	    {
197	      sh_invalidopt ("-p");
198	      builtin_usage ();
199	      return (EX_USAGE);
200	    }
201
202	case 'a':
203	  acts |= CA_ALIAS;
204	  break;
205	case 'b':
206	  acts |= CA_BUILTIN;
207	  break;
208	case 'c':
209	  acts |= CA_COMMAND;
210	  break;
211	case 'd':
212	  acts |= CA_DIRECTORY;
213	  break;
214	case 'e':
215	  acts |= CA_EXPORT;
216	  break;
217	case 'f':
218	  acts |= CA_FILE;
219	  break;
220	case 'g':
221	  acts |= CA_GROUP;
222	  break;
223	case 'j':
224	  acts |= CA_JOB;
225	  break;
226	case 'k':
227	  acts |= CA_KEYWORD;
228	  break;
229	case 's':
230	  acts |= CA_SERVICE;
231	  break;
232	case 'u':
233	  acts |= CA_USER;
234	  break;
235	case 'v':
236	  acts |= CA_VARIABLE;
237	  break;
238	case 'o':
239	  ind = find_compopt (list_optarg);
240	  if (ind < 0)
241	    {
242	      sh_invalidoptname (list_optarg);
243	      return (EX_USAGE);
244	    }
245	  copts |= compopts[ind].optflag;
246	  break;
247	case 'A':
248	  ind = find_compact (list_optarg);
249	  if (ind < 0)
250	    {
251	      builtin_error (_("%s: invalid action name"), list_optarg);
252	      return (EX_USAGE);
253	    }
254	  acts |= compacts[ind].actflag;
255	  break;
256	case 'C':
257	  Carg = list_optarg;
258	  break;
259	case 'F':
260	  Farg = list_optarg;
261	  break;
262	case 'G':
263	  Garg = list_optarg;
264	  break;
265	case 'P':
266	  Parg = list_optarg;
267	  break;
268	case 'S':
269	  Sarg = list_optarg;
270	  break;
271	case 'W':
272	  Warg = list_optarg;
273	  break;
274	case 'X':
275	  Xarg = list_optarg;
276	  break;
277	default:
278	  builtin_usage ();
279	  return (EX_USAGE);
280	}
281    }
282
283  *actp = acts;
284  *optp = copts;
285
286  return (opt_given ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
287}
288
289/* Add, remove, and display completion specifiers. */
290int
291complete_builtin (list)
292     WORD_LIST *list;
293{
294  int opt_given, pflag, rflag, rval;
295  unsigned long acts, copts;
296  COMPSPEC *cs;
297
298  if (list == 0)
299    {
300      print_all_completions ();
301      return (EXECUTION_SUCCESS);
302    }
303
304  opt_given = pflag = rflag = 0;
305  acts = copts = (unsigned long)0L;
306  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
307  cs = (COMPSPEC *)NULL;
308
309  /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
310     as a side effect if they are supplied as options. */
311  rval = build_actions (list, &pflag, &rflag, &acts, &copts);
312  if (rval == EX_USAGE)
313    return (rval);
314  opt_given = rval != EXECUTION_FAILURE;
315
316  list = loptend;
317
318  /* -p overrides everything else */
319  if (pflag || (list == 0 && opt_given == 0))
320    {
321      if (list == 0)
322	{
323	  print_all_completions ();
324	  return (EXECUTION_SUCCESS);
325	}
326      return (print_cmd_completions (list));
327    }
328
329  /* next, -r overrides everything else. */
330  if (rflag)
331    {
332      if (list == 0)
333	{
334	  progcomp_flush ();
335	  return (EXECUTION_SUCCESS);
336	}
337      return (remove_cmd_completions (list));
338    }
339
340  if (list == 0 && opt_given)
341    {
342      builtin_usage ();
343      return (EX_USAGE);
344    }
345
346  /* If we get here, we need to build a compspec and add it for each
347     remaining argument. */
348  cs = compspec_create ();
349  cs->actions = acts;
350  cs->options = copts;
351
352  cs->globpat = STRDUP (Garg);
353  cs->words = STRDUP (Warg);
354  cs->prefix = STRDUP (Parg);
355  cs->suffix = STRDUP (Sarg);
356  cs->funcname = STRDUP (Farg);
357  cs->command = STRDUP (Carg);
358  cs->filterpat = STRDUP (Xarg);
359
360  for (rval = EXECUTION_SUCCESS ; list; list = list->next)
361    {
362      /* Add CS as the compspec for the specified commands. */
363      if (progcomp_insert (list->word->word, cs) == 0)
364	rval = EXECUTION_FAILURE;
365    }
366
367  return (rval);
368}
369
370static int
371remove_cmd_completions (list)
372     WORD_LIST *list;
373{
374  WORD_LIST *l;
375  int ret;
376
377  for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
378    {
379      if (progcomp_remove (l->word->word) == 0)
380	{
381	  builtin_error (_("%s: no completion specification"), l->word->word);
382	  ret = EXECUTION_FAILURE;
383	}
384    }
385  return ret;
386}
387
388#define SQPRINTARG(a, f) \
389  do { \
390    if (a) \
391      { \
392      	x = sh_single_quote (a); \
393	printf ("%s %s ", f, x); \
394	free (x); \
395      } \
396  } while (0)
397
398#define PRINTARG(a, f) \
399  do { \
400    if (a) \
401      printf ("%s %s ", f, a); \
402  } while (0)
403
404#define PRINTOPT(a, f) \
405  do { \
406    if (acts & a) \
407      printf ("%s ", f); \
408  } while (0)
409
410#define PRINTACT(a, f) \
411  do { \
412    if (acts & a) \
413      printf ("-A %s ", f); \
414  } while (0)
415
416#define PRINTCOMPOPT(a, f) \
417  do { \
418    if (copts & a) \
419      printf ("-o %s ", f); \
420  } while (0)
421
422static int
423print_one_completion (cmd, cs)
424     char *cmd;
425     COMPSPEC *cs;
426{
427  unsigned long acts, copts;
428  char *x;
429
430  printf ("complete ");
431
432  copts = cs->options;
433
434  /* First, print the -o options. */
435  PRINTCOMPOPT (COPT_BASHDEFAULT, "bashdefault");
436  PRINTCOMPOPT (COPT_DEFAULT, "default");
437  PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
438  PRINTCOMPOPT (COPT_FILENAMES, "filenames");
439  PRINTCOMPOPT (COPT_NOSPACE, "nospace");
440  PRINTCOMPOPT (COPT_PLUSDIRS, "plusdirs");
441
442  acts = cs->actions;
443
444  /* simple flags next */
445  PRINTOPT (CA_ALIAS, "-a");
446  PRINTOPT (CA_BUILTIN, "-b");
447  PRINTOPT (CA_COMMAND, "-c");
448  PRINTOPT (CA_DIRECTORY, "-d");
449  PRINTOPT (CA_EXPORT, "-e");
450  PRINTOPT (CA_FILE, "-f");
451  PRINTOPT (CA_GROUP, "-g");
452  PRINTOPT (CA_JOB, "-j");
453  PRINTOPT (CA_KEYWORD, "-k");
454  PRINTOPT (CA_SERVICE, "-s");
455  PRINTOPT (CA_USER, "-u");
456  PRINTOPT (CA_VARIABLE, "-v");
457
458  /* now the rest of the actions */
459  PRINTACT (CA_ARRAYVAR, "arrayvar");
460  PRINTACT (CA_BINDING, "binding");
461  PRINTACT (CA_DISABLED, "disabled");
462  PRINTACT (CA_ENABLED, "enabled");
463  PRINTACT (CA_FUNCTION, "function");
464  PRINTACT (CA_HELPTOPIC, "helptopic");
465  PRINTACT (CA_HOSTNAME, "hostname");
466  PRINTACT (CA_RUNNING, "running");
467  PRINTACT (CA_SETOPT, "setopt");
468  PRINTACT (CA_SHOPT, "shopt");
469  PRINTACT (CA_SIGNAL, "signal");
470  PRINTACT (CA_STOPPED, "stopped");
471
472  /* now the rest of the arguments */
473
474  /* arguments that require quoting */
475  SQPRINTARG (cs->globpat, "-G");
476  SQPRINTARG (cs->words, "-W");
477  SQPRINTARG (cs->prefix, "-P");
478  SQPRINTARG (cs->suffix, "-S");
479  SQPRINTARG (cs->filterpat, "-X");
480
481  /* simple arguments that don't require quoting */
482  PRINTARG (cs->funcname, "-F");
483  PRINTARG (cs->command, "-C");
484
485  printf ("%s\n", cmd);
486
487  return (0);
488}
489
490static int
491print_compitem (item)
492     BUCKET_CONTENTS *item;
493{
494  COMPSPEC *cs;
495  char *cmd;
496
497  cmd = item->key;
498  cs = (COMPSPEC *)item->data;
499
500  return (print_one_completion (cmd, cs));
501}
502
503static void
504print_all_completions ()
505{
506  progcomp_walk (print_compitem);
507}
508
509static int
510print_cmd_completions (list)
511     WORD_LIST *list;
512{
513  WORD_LIST *l;
514  COMPSPEC *cs;
515  int ret;
516
517  for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
518    {
519      cs = progcomp_search (l->word->word);
520      if (cs)
521	print_one_completion (l->word->word, cs);
522      else
523	{
524	  builtin_error (_("%s: no completion specification"), l->word->word);
525	  ret = EXECUTION_FAILURE;
526	}
527    }
528  return (ret);
529}
530
531$BUILTIN compgen
532$DEPENDS_ON PROGRAMMABLE_COMPLETION
533$FUNCTION compgen_builtin
534$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word]
535Display the possible completions depending on the options.  Intended
536to be used from within a shell function generating possible completions.
537If the optional WORD argument is supplied, matches against WORD are
538generated.
539$END
540
541int
542compgen_builtin (list)
543     WORD_LIST *list;
544{
545  int rval;
546  unsigned long acts, copts;
547  COMPSPEC *cs;
548  STRINGLIST *sl;
549  char *word, **matches;
550
551  if (list == 0)
552    return (EXECUTION_SUCCESS);
553
554  acts = copts = (unsigned long)0L;
555  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
556  cs = (COMPSPEC *)NULL;
557
558  /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
559     as a side effect if they are supplied as options. */
560  rval = build_actions (list, (int *)NULL, (int *)NULL, &acts, &copts);
561  if (rval == EX_USAGE)
562    return (rval);
563  if (rval == EXECUTION_FAILURE)
564    return (EXECUTION_SUCCESS);
565
566  list = loptend;
567
568  word = (list && list->word) ? list->word->word : "";
569
570  if (Farg)
571    builtin_error (_("warning: -F option may not work as you expect"));
572  if (Carg)
573    builtin_error (_("warning: -C option may not work as you expect"));
574
575  /* If we get here, we need to build a compspec and evaluate it. */
576  cs = compspec_create ();
577  cs->actions = acts;
578  cs->options = copts;
579  cs->refcount = 1;
580
581  cs->globpat = STRDUP (Garg);
582  cs->words = STRDUP (Warg);
583  cs->prefix = STRDUP (Parg);
584  cs->suffix = STRDUP (Sarg);
585  cs->funcname = STRDUP (Farg);
586  cs->command = STRDUP (Carg);
587  cs->filterpat = STRDUP (Xarg);
588
589  rval = EXECUTION_FAILURE;
590  sl = gen_compspec_completions (cs, "compgen", word, 0, 0);
591
592  /* If the compspec wants the bash default completions, temporarily
593     turn off programmable completion and call the bash completion code. */
594  if ((sl == 0 || sl->list_len == 0) && (copts & COPT_BASHDEFAULT))
595    {
596      matches = bash_default_completion (word, 0, 0, 0, 0);
597      sl = completions_to_stringlist (matches);
598      strvec_dispose (matches);
599    }
600
601  /* This isn't perfect, but it's the best we can do, given what readline
602     exports from its set of completion utility functions. */
603  if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT))
604    {
605      matches = rl_completion_matches (word, rl_filename_completion_function);
606      sl = completions_to_stringlist (matches);
607      strvec_dispose (matches);
608    }
609
610  if (sl)
611    {
612      if (sl->list && sl->list_len)
613	{
614	  rval = EXECUTION_SUCCESS;
615	  strlist_print (sl, (char *)NULL);
616	}
617      strlist_dispose (sl);
618    }
619
620  compspec_dispose (cs);
621  return (rval);
622}
623