diff options
Diffstat (limited to 'pcomplete.c~')
-rw-r--r-- | pcomplete.c~ | 157 |
1 files changed, 120 insertions, 37 deletions
diff --git a/pcomplete.c~ b/pcomplete.c~ index 44740e51..6bd07c35 100644 --- a/pcomplete.c~ +++ b/pcomplete.c~ @@ -66,6 +66,8 @@ #include <readline/readline.h> #include <readline/history.h> +#define PCOMP_RETRYFAIL 256 + #ifdef STRDUP # undef STRDUP #endif @@ -118,10 +120,15 @@ static STRINGLIST *gen_globpat_matches __P((COMPSPEC *, const char *)); static STRINGLIST *gen_wordlist_matches __P((COMPSPEC *, const char *)); static STRINGLIST *gen_shell_function_matches __P((COMPSPEC *, const char *, char *, int, WORD_LIST *, - int, int)); + int, int, int *)); static STRINGLIST *gen_command_matches __P((COMPSPEC *, const char *, char *, int, WORD_LIST *, int, int)); +static STRINGLIST *gen_progcomp_completions __P((const char *, const char *, + const char *, + int, int, int *, int *, + COMPSPEC **)); + static char *pcomp_filename_completion_function __P((const char *, int)); #if defined (ARRAY_VARS) @@ -653,7 +660,7 @@ gen_matches_from_itemlist (itp, text) if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) || (itp->flags & LIST_INITIALIZED) == 0) { - if (itp->flags & (LIST_DIRTY | LIST_DYNAMIC)) + if (itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) clean_itemlist (itp); if ((itp->flags & LIST_INITIALIZED) == 0) initialize_itemlist (itp); @@ -827,7 +834,7 @@ gen_wordlist_matches (cs, text) do -- there's no way to split a simple list into individual words that way, since the shell semantics say that word splitting is done only on the results of expansion. */ - l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, (int *)NULL, (int *)NULL); + l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL); if (l == 0) return ((STRINGLIST *)NULL); /* This will jump back to the top level if the expansion fails... */ @@ -992,25 +999,30 @@ build_arg_list (cmd, text, lwords, ind) variable, this does nothing if arrays are not compiled into the shell. */ static STRINGLIST * -gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw) +gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw, foundp) COMPSPEC *cs; const char *text; char *line; int ind; WORD_LIST *lwords; int nw, cw; + int *foundp; { char *funcname; STRINGLIST *sl; SHELL_VAR *f, *v; WORD_LIST *cmdlist; - int fval; + int fval, found; sh_parser_state_t ps; sh_parser_state_t * restrict pps; #if defined (ARRAY_VARS) ARRAY *a; #endif + found = 0; + if (foundp) + *foundp = found; + funcname = cs->funcname; f = find_function (funcname); if (f == 0) @@ -1043,6 +1055,12 @@ gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw) discard_unwind_frame ("gen-shell-function-matches"); restore_parser_state (pps); + found = fval != EX_NOTFOUND; + if (fval == EX_RETRYFAIL) + found |= PCOMP_RETRYFAIL; + if (foundp) + *foundp = found; + /* Now clean up and destroy everything. */ dispose_words (cmdlist); unbind_compfunc_variables (0); @@ -1057,7 +1075,7 @@ gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw) VUNSETATTR (v, att_invisible); a = array_cell (v); - if (a == 0 || array_empty (a)) + if (found == 0 || (found & PCOMP_RETRYFAIL) || a == 0 || array_empty (a)) sl = (STRINGLIST *)NULL; else { @@ -1181,25 +1199,28 @@ command_line_to_word_list (line, llen, sentinel, nwp, cwp) #else delims = rl_completer_word_break_characters; #endif - ret = split_at_delims (line, llen, delims, sentinel, nwp, cwp); + ret = split_at_delims (line, llen, delims, sentinel, SD_NOQUOTEDELIMS, nwp, cwp); return (ret); } /* Evaluate COMPSPEC *cs and return all matches for WORD. */ STRINGLIST * -gen_compspec_completions (cs, cmd, word, start, end) +gen_compspec_completions (cs, cmd, word, start, end, foundp) COMPSPEC *cs; const char *cmd; const char *word; int start, end; + int *foundp; { STRINGLIST *ret, *tmatches; char *line; - int llen, nw, cw; + int llen, nw, cw, found, foundf; WORD_LIST *lwords; COMPSPEC *tcs; + found = 1; + #ifdef DEBUG debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end); debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs); @@ -1284,7 +1305,10 @@ gen_compspec_completions (cs, cmd, word, start, end) if (cs->funcname) { - tmatches = gen_shell_function_matches (cs, word, line, rl_point - start, lwords, nw, cw); + foundf = 0; + tmatches = gen_shell_function_matches (cs, word, line, rl_point - start, lwords, nw, cw, &foundf); + if (foundf != 0) + found = foundf; if (tmatches) { #ifdef DEBUG @@ -1325,6 +1349,15 @@ gen_compspec_completions (cs, cmd, word, start, end) FREE (line); } + if (foundp) + *foundp = found; + + if (found == 0 || (found & PCOMP_RETRYFAIL)) + { + strlist_dispose (ret); + return NULL; + } + if (cs->filterpat) { tmatches = filter_stringlist (ret, cs->filterpat, word); @@ -1399,35 +1432,28 @@ pcomp_set_compspec_options (cs, flags, set_or_unset) cs->options &= ~flags; } -/* The driver function for the programmable completion code. Returns a list - of matches for WORD, which is an argument to command CMD. START and END - bound the command currently being completed in rl_line_buffer. */ -char ** -programmable_completions (cmd, word, start, end, foundp) +static STRINGLIST * +gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs) + const char *ocmd; const char *cmd; const char *word; - int start, end, *foundp; + int start, end; + int *foundp, *retryp; + COMPSPEC **lastcs; { COMPSPEC *cs, *oldcs; - STRINGLIST *ret; - char **rmatches, *t; const char *oldcmd; + STRINGLIST *ret; - /* We look at the basename of CMD if the full command does not have - an associated COMPSPEC. */ - cs = progcomp_search (cmd); - if (cs == 0) - { - t = strrchr (cmd, '/'); - if (t) - cs = progcomp_search (++t); - } - if (cs == 0) - { - if (foundp) - *foundp = 0; - return ((char **)NULL); - } + cs = progcomp_search (ocmd); + + if (cs == 0 || cs == *lastcs) + return (NULL); + + if (*lastcs) + compspec_dispose (*lastcs); + cs->refcount++; /* XXX */ + *lastcs = cs; cs = compspec_copy (cs); @@ -1437,17 +1463,68 @@ programmable_completions (cmd, word, start, end, foundp) pcomp_curcs = cs; pcomp_curcmd = cmd; - ret = gen_compspec_completions (cs, cmd, word, start, end); + ret = gen_compspec_completions (cs, cmd, word, start, end, foundp); pcomp_curcs = oldcs; pcomp_curcmd = oldcmd; - /* Signal the caller that we found a COMPSPEC for this command, and pass - back any meta-options associated with the compspec. */ + /* We need to conditionally handle setting *retryp here */ + if (retryp) + *retryp = foundp && (*foundp & PCOMP_RETRYFAIL); + if (foundp) - *foundp = 1|cs->options; + { + *foundp &= ~PCOMP_RETRYFAIL; + *foundp |= cs->options; + } compspec_dispose (cs); + return ret; +} + +/* The driver function for the programmable completion code. Returns a list + of matches for WORD, which is an argument to command CMD. START and END + bound the command currently being completed in rl_line_buffer. */ +char ** +programmable_completions (cmd, word, start, end, foundp) + const char *cmd; + const char *word; + int start, end, *foundp; +{ + COMPSPEC *cs, *lastcs; + STRINGLIST *ret; + char **rmatches, *t; + int found, retry, count; + + lastcs = 0; + found = count = 0; + + do + { + retry = 0; + + /* We look at the basename of CMD if the full command does not have + an associated COMPSPEC. */ + ret = gen_progcomp_completions (cmd, cmd, word, start, end, &found, &retry, &lastcs); + if (found == 0) + { + t = strrchr (cmd, '/'); + if (t && *(++t)) + ret = gen_progcomp_completions (t, cmd, word, start, end, &found, &retry, &lastcs); + } + + if (found == 0) + ret = gen_progcomp_completions (DEFAULTCMD, cmd, word, start, end, &found, &retry, &lastcs); + + count++; + + if (count > 32) + { + internal_warning ("programmable_completion: %s: possible retry loop", cmd); + break; + } + } + while (retry); if (ret) { @@ -1457,6 +1534,12 @@ programmable_completions (cmd, word, start, end, foundp) else rmatches = (char **)NULL; + if (foundp) + *foundp = found; + + if (lastcs) /* XXX - should be while? */ + compspec_dispose (lastcs); + return (rmatches); } |