]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/complete.def
Imported from ../bash-2.04.tar.gz.
[thirdparty/bash.git] / builtins / complete.def
1 This file is complete.def, from which is created complete.c.
2 It implements the builtins "complete" and "compgen" in Bash.
3
4 Copyright (C) 1999 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 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 [-abcdefjkvu] [-pr] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]
28 For each NAME, specify how arguments are to be completed.
29 If the -p option is supplied, or if no options are supplied, existing
30 completion specifications are printed in a way that allows them to be
31 reused as input. The -r option removes a completion specification for
32 each 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
47 #include "../shell.h"
48 #include "../builtins.h"
49 #include "../pcomplete.h"
50
51 #include "common.h"
52 #include "bashgetopt.h"
53
54 #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
55
56 static int remove_cmd_completions ();
57
58 static void print_all_completions ();
59 static int print_cmd_completions ();
60
61 static char *Aarg, *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
62
63 static struct _compacts {
64 char *actname;
65 int actflag;
66 int actopt;
67 } compacts[] = {
68 { "alias", CA_ALIAS, 'a' },
69 { "arrayvar", CA_ARRAYVAR, 0 },
70 { "binding", CA_BINDING, 0 },
71 { "builtin", CA_BUILTIN, 'b' },
72 { "command", CA_COMMAND, 'c' },
73 { "directory", CA_DIRECTORY, 'd' },
74 { "disabled", CA_DISABLED, 0 },
75 { "enabled", CA_ENABLED, 0 },
76 { "export", CA_EXPORT, 'e' },
77 { "file", CA_FILE, 'f' },
78 { "function", CA_FUNCTION, 0 },
79 { "helptopic", CA_BUILTIN, 0 }, /* for now */
80 { "hostname", CA_HOSTNAME, 0 },
81 { "job", CA_JOB, 'j' },
82 { "keyword", CA_KEYWORD, 'k' },
83 { "running", CA_RUNNING, 0 },
84 { "setopt", CA_SETOPT, 0 },
85 { "shopt", CA_SHOPT, 0 },
86 { "signal", CA_SIGNAL, 0 },
87 { "stopped", CA_STOPPED, 0 },
88 { "user", CA_USER, 'u' },
89 { "variable", CA_VARIABLE, 'v' },
90 { (char *)NULL, 0, 0 },
91 };
92
93 static int
94 find_compact (name)
95 char *name;
96 {
97 register int i;
98
99 for (i = 0; compacts[i].actname; i++)
100 if (STREQ (name, compacts[i].actname))
101 return i;
102 return -1;
103 }
104
105 /* Build the actions from the options specified in LIST. ACTP is a pointer
106 to an unsigned long in which to place the bitmap of actions. PP, if
107 non-null, gets 1 if -p is supplied; RP, if non-null, gets 1 if -r is
108 supplied. If either is null, the corresponding option generates an
109 error. This also sets variables corresponding to options that take
110 arguments as a side effect; the caller should ensure that those variables
111 are set to NULL before calling build_actions. Return value:
112 EX_USAGE = bad option
113 EXECUTION_SUCCESS = some options supplied
114 EXECUTION_FAILURE = no options supplied
115 */
116
117 static int
118 build_actions (list, pp, rp, actp)
119 WORD_LIST *list;
120 int *pp, *rp;
121 unsigned long *actp;
122 {
123 int opt, ind, pflag, rflag, opt_given;
124 unsigned long acts;
125
126 acts = (unsigned long)0L;
127 opt_given = 0;
128
129 reset_internal_getopt ();
130 while ((opt = internal_getopt (list, "abcdefjkpruvA:G:W:P:S:X:F:C:")) != -1)
131 {
132 opt_given = 1;
133 switch (opt)
134 {
135 case 'r':
136 if (rp)
137 {
138 *rp = 1;
139 break;
140 }
141 else
142 {
143 builtin_error ("illegal option: -r");
144 builtin_usage ();
145 return (EX_USAGE);
146 }
147
148 case 'p':
149 if (pp)
150 {
151 *pp = 1;
152 break;
153 }
154 else
155 {
156 builtin_error ("illegal option: -p");
157 builtin_usage ();
158 return (EX_USAGE);
159 }
160
161 case 'a':
162 acts |= CA_ALIAS;
163 break;
164 case 'b':
165 acts |= CA_BUILTIN;
166 break;
167 case 'c':
168 acts |= CA_COMMAND;
169 break;
170 case 'd':
171 acts |= CA_DIRECTORY;
172 break;
173 case 'e':
174 acts |= CA_EXPORT;
175 break;
176 case 'f':
177 acts |= CA_FILE;
178 break;
179 case 'j':
180 acts |= CA_JOB;
181 break;
182 case 'k':
183 acts |= CA_KEYWORD;
184 break;
185 case 'u':
186 acts |= CA_USER;
187 break;
188 case 'v':
189 acts |= CA_VARIABLE;
190 break;
191 case 'A':
192 ind = find_compact (list_optarg);
193 if (ind < 0)
194 {
195 builtin_error ("%s: invalid action name", list_optarg);
196 return (EX_USAGE);
197 }
198 acts |= compacts[ind].actflag;
199 break;
200 case 'C':
201 Carg = list_optarg;
202 break;
203 case 'F':
204 Farg = list_optarg;
205 break;
206 case 'G':
207 Garg = list_optarg;
208 break;
209 case 'P':
210 Parg = list_optarg;
211 break;
212 case 'S':
213 Sarg = list_optarg;
214 break;
215 case 'W':
216 Warg = list_optarg;
217 break;
218 case 'X':
219 Xarg = list_optarg;
220 break;
221 default:
222 builtin_usage ();
223 return (EX_USAGE);
224 }
225 }
226
227 *actp = acts;
228 return (opt_given ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
229 }
230
231 /* Add, remove, and display completion specifiers. */
232 int
233 complete_builtin (list)
234 WORD_LIST *list;
235 {
236 int opt_given, pflag, rflag, rval;
237 unsigned long acts;
238 char *cmd;
239 COMPSPEC *cs;
240
241 if (list == 0)
242 {
243 print_all_completions ();
244 return (EXECUTION_SUCCESS);
245 }
246
247 opt_given = pflag = rflag = 0;
248 acts = (unsigned long)0L;
249 Aarg = Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
250 cs = (COMPSPEC *)NULL;
251
252 /* Build the actions from the arguments. Also sets the [A-Z]arg variables
253 as a side effect if they are supplied as options. */
254 rval = build_actions (list, &pflag, &rflag, &acts);
255 if (rval == EX_USAGE)
256 return (rval);
257 opt_given = rval != EXECUTION_FAILURE;
258
259 list = loptend;
260
261 /* -p overrides everything else */
262 if (pflag || (list == 0 && opt_given == 0))
263 {
264 if (list == 0)
265 {
266 print_all_completions ();
267 return (EXECUTION_SUCCESS);
268 }
269 return (print_cmd_completions (list));
270 }
271
272 /* next, -r overrides everything else. */
273 if (rflag)
274 {
275 if (list == 0)
276 {
277 clear_progcomps ();
278 return (EXECUTION_SUCCESS);
279 }
280 return (remove_cmd_completions (list));
281 }
282
283 if (list == 0 && opt_given)
284 {
285 builtin_usage ();
286 return (EX_USAGE);
287 }
288
289 /* If we get here, we need to build a compspec and add it for each
290 remaining argument. */
291 cs = alloc_compspec ();
292 cs->actions = acts;
293
294 cs->globpat = STRDUP (Garg);
295 cs->words = STRDUP (Warg);
296 cs->prefix = STRDUP (Parg);
297 cs->suffix = STRDUP (Sarg);
298 cs->funcname = STRDUP (Farg);
299 cs->command = STRDUP (Carg);
300 cs->filterpat = STRDUP (Xarg);
301
302 for (rval = EXECUTION_SUCCESS ; list; list = list->next)
303 {
304 /* Add CS as the compspec for the specified commands. */
305 cmd = list->word->word;
306 if (add_progcomp (cmd, cs) == 0)
307 rval = EXECUTION_FAILURE;
308 }
309
310 return (rval);
311 }
312
313 static int
314 remove_cmd_completions (list)
315 WORD_LIST *list;
316 {
317 WORD_LIST *l;
318 int ret;
319
320 for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
321 {
322 if (remove_progcomp (l->word->word) == 0)
323 {
324 builtin_error ("%s: no completion specification", l->word->word);
325 ret = EXECUTION_FAILURE;
326 }
327 }
328 return ret;
329 }
330
331 #define SQPRINTARG(a, f) \
332 do { \
333 if (a) \
334 { \
335 x = single_quote (a); \
336 printf ("%s %s ", f, x); \
337 free (x); \
338 } \
339 } while (0)
340
341 #define PRINTARG(a, f) \
342 do { \
343 if (a) \
344 printf ("%s %s ", f, a); \
345 } while (0)
346
347 #define PRINTOPT(a, f) \
348 do { \
349 if (acts & a) \
350 printf ("%s ", f); \
351 } while (0)
352
353 #define PRINTACT(a, f) \
354 do { \
355 if (acts & a) \
356 printf ("-A %s ", f); \
357 } while (0)
358
359 static void
360 print_one_completion (cmd, cs)
361 char *cmd;
362 COMPSPEC *cs;
363 {
364 unsigned long acts;
365 char *x;
366
367 printf ("complete ");
368
369 acts = cs->actions;
370
371 /* simple flags first */
372 PRINTOPT (CA_ALIAS, "-a");
373 PRINTOPT (CA_BUILTIN, "-b");
374 PRINTOPT (CA_COMMAND, "-c");
375 PRINTOPT (CA_DIRECTORY, "-d");
376 PRINTOPT (CA_EXPORT, "-e");
377 PRINTOPT (CA_FILE, "-f");
378 PRINTOPT (CA_KEYWORD, "-k");
379 PRINTOPT (CA_JOB, "-j");
380 PRINTOPT (CA_USER, "-u");
381 PRINTOPT (CA_VARIABLE, "-v");
382
383 /* now the rest of the actions */
384 PRINTACT (CA_ARRAYVAR, "arrayvar");
385 PRINTACT (CA_BINDING, "binding");
386 PRINTACT (CA_DISABLED, "disabled");
387 PRINTACT (CA_ENABLED, "enabled");
388 PRINTACT (CA_FUNCTION, "function");
389 PRINTACT (CA_HELPTOPIC, "helptopic");
390 PRINTACT (CA_HOSTNAME, "hostname");
391 PRINTACT (CA_RUNNING, "running");
392 PRINTACT (CA_SETOPT, "setopt");
393 PRINTACT (CA_SHOPT, "shopt");
394 PRINTACT (CA_SIGNAL, "signal");
395 PRINTACT (CA_STOPPED, "stopped");
396
397 /* now the rest of the arguments */
398
399 /* arguments that require quoting */
400 SQPRINTARG (cs->globpat, "-G");
401 SQPRINTARG (cs->words, "-W");
402 SQPRINTARG (cs->prefix, "-P");
403 SQPRINTARG (cs->suffix, "-S");
404 SQPRINTARG (cs->filterpat, "-X");
405
406 /* simple arguments that don't require quoting */
407 PRINTARG (cs->funcname, "-F");
408 PRINTARG (cs->command, "-C");
409
410 printf ("%s\n", cmd);
411 }
412
413 static void
414 print_all_completions ()
415 {
416 print_all_compspecs (print_one_completion);
417 }
418
419 static int
420 print_cmd_completions (list)
421 WORD_LIST *list;
422 {
423 WORD_LIST *l;
424 COMPSPEC *cs;
425 int ret;
426
427 for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
428 {
429 cs = find_compspec (l->word->word);
430 if (cs)
431 print_one_completion (l->word->word, cs);
432 else
433 {
434 builtin_error ("%s: no completion specification", l->word->word);
435 ret = EXECUTION_FAILURE;
436 }
437 }
438 return (ret);
439 }
440
441 $BUILTIN compgen
442 $DEPENDS_ON PROGRAMMABLE_COMPLETION
443 $FUNCTION compgen_builtin
444 $SHORT_DOC compgen [-abcdefjkvu] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word]
445 Display the possible completions depending on the options. Intended
446 to be used from within a shell function generating possible completions.
447 If the optional WORD argument is supplied, matches against WORD are
448 generated.
449 $END
450
451 int
452 compgen_builtin (list)
453 WORD_LIST *list;
454 {
455 int rval;
456 unsigned long acts;
457 COMPSPEC *cs;
458 STRINGLIST *sl;
459 char *word;
460
461 if (list == 0)
462 return (EXECUTION_SUCCESS);
463
464 acts = (unsigned long)0L;
465 Aarg = Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
466 cs = (COMPSPEC *)NULL;
467
468 /* Build the actions from the arguments. Also sets the [A-Z]arg variables
469 as a side effect if they are supplied as options. */
470 rval = build_actions (list, (int *)NULL, (int *)NULL, &acts);
471 if (rval == EX_USAGE)
472 return (rval);
473 if (rval == EXECUTION_FAILURE)
474 return (EXECUTION_SUCCESS);
475
476 list = loptend;
477
478 word = (list && list->word) ? list->word->word : "";
479
480 if (Farg)
481 internal_warning ("compgen: -F option may not work as you expect");
482 if (Carg)
483 internal_warning ("compgen: -C option may not work as you expect");
484
485 /* If we get here, we need to build a compspec and evaluate it. */
486 cs = alloc_compspec ();
487 cs->actions = acts;
488 cs->refcount = 1;
489
490 cs->globpat = STRDUP (Garg);
491 cs->words = STRDUP (Warg);
492 cs->prefix = STRDUP (Parg);
493 cs->suffix = STRDUP (Sarg);
494 cs->funcname = STRDUP (Farg);
495 cs->command = STRDUP (Carg);
496 cs->filterpat = STRDUP (Xarg);
497
498 rval = EXECUTION_FAILURE;
499 sl = gen_compspec_completions (cs, "compgen", word, 0, 0);
500 if (sl)
501 {
502 if (sl->list)
503 {
504 rval = EXECUTION_SUCCESS;
505 print_stringlist (sl, (char *)NULL);
506 }
507 free_stringlist (sl);
508 }
509
510 free_compspec (cs);
511 return (rval);
512 }