From eaff11c748e005bbcd14dbd1850880e4bffee3fa Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 9 Apr 2021 21:53:41 +0200 Subject: 48378: complete compadd options for other completion functions --- Completion/Zsh/Command/_compadd | 121 ++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 37 deletions(-) (limited to 'Completion/Zsh/Command/_compadd') diff --git a/Completion/Zsh/Command/_compadd b/Completion/Zsh/Command/_compadd index 781fa2af8..9c92cda76 100644 --- a/Completion/Zsh/Command/_compadd +++ b/Completion/Zsh/Command/_compadd @@ -1,47 +1,94 @@ -#compdef compadd +#compdef compadd -P _* -local curcontext="$curcontext" state line ret=1 +local curcontext="$curcontext" ret=1 +local -a state line args typeset -A opt_args -_arguments -C -s -S -A "-*" \ - '-P+[specify prefix]:prefix' \ - '-S+[specify suffix]:suffix' \ - '-p+[specify hidden prefix]:hidden prefix' \ - '-s+[specify hidden suffix]:hidden suffix' \ - '-i+[specify ignored prefix]:ignored prefix' \ - '-I+[specify ignored suffix]:ignored suffix' \ - '(-k)-a[matches are elements of specified arrays]' \ - '(-a)-k[matches are keys of specified associative arrays]' \ - '-d+[specify display strings]:array:_parameters -g "*array*"' \ - '-l[list display strings one per line, not in columns]' \ +args=( + '-P+[specify prefix]:prefix' + '-S+[specify suffix]:suffix' + '-p+[specify hidden prefix]:hidden prefix' + '-s+[specify hidden suffix]:hidden suffix' + '-i+[specify ignored prefix]:ignored prefix' + '-I+[specify ignored suffix]:ignored suffix' '-o[specify order for matches by match string not by display string]:: : _values -s , order "match[order by match not by display string]" "nosort[matches are pre-ordered]" "numeric[order numerically]" - "reverse[order backwards]"' \ - '(-1 -E)-J+[specify match group]:group' \ - '!-V+:group' \ - '(-J -E)-1[remove only consecutive duplicates from group]' \ - '-2[preserve all duplicates]' \ - '(-x)-X[specify explanation]:explanation' \ - '(-X)-x[specify unconditional explanation]:explanation' \ - '-q[make suffix autoremovable]' \ - '-r+[specify character class for suffix autoremoval]:character class' \ - '-R+[specify function for suffix autoremoval]:function:_functions' \ - '-f[mark matches as being files]' \ - '-e[mark matches as being parameters]' \ - '-W[specify location for matches marked as files]' \ - '-F+[specify array of ignore patterns]:array:_parameters -g "*array*"' \ - '-Q[disable quoting of possible completions]' \ - '*-M[specify matching specifications]' \ - '-n[hide matches in completion listing]' \ - '-U[disable internal matching of completion candidates]' \ - '-O+[populate array with matches instead of adding them]:array:_parameters -g "*array*"' \ - '-A+[populate array with expanded matches instead of adding them]:array:_parameters -g "*array*"' \ - '-D+[delete elements from array corresponding to non-matching candidates]:array:_parameters -g "*array*"' \ - '-C[add special match that expands to all other matches]' \ - '(-1 -J)-E+[add specified number of display only matches]:number' \ - '*:candidate:->candidates' && ret=0 + "reverse[order backwards]"' + '(-1 -E)-J+[specify match group]:group' + '!-V+:group' + '(-J -E)-1[remove only consecutive duplicates from group]' + '-2[preserve all duplicates]' + '(-x)-X[specify explanation]:explanation' + '(-X)-x[specify unconditional explanation]:explanation' + '-q[make suffix autoremovable]' + '-r+[specify character class for suffix autoremoval]:character class' + '-R+[specify function for suffix autoremoval]:function:_functions' + '-F+[specify array of ignore patterns]:array:_parameters -g "*array*"' + '-Q[disable quoting of possible completions]' + '*-M[specify matching specifications]' + '-n[hide matches in completion listing]' + '-O+[populate array with matches instead of adding them]:array:_parameters -g "*array*"' + '-A+[populate array with expanded matches instead of adding them]:array:_parameters -g "*array*"' + '-D+[delete elements from array corresponding to non-matching candidates]:array:_parameters -g "*array*"' +) + +case $service in + compadd|_(path_|)files) + args+=( + '-W[specify location for matches marked as files]' + ) + ;| + compadd) + args+=( + '(-k)-a[matches are elements of specified arrays]' + '(-a)-k[matches are keys of specified associative arrays]' + '-d+[specify display strings]:array:_parameters -g "*array*"' + '-l[list display strings one per line, not in columns]' + '-f[mark matches as being files]' + '-e[mark matches as being parameters]' + '-C[add special match that expands to all other matches]' + '(-1 -J)-E+[add specified number of display only matches]:number' + '-U[disable internal matching of completion candidates]' + '*:candidate:->candidates' + ) + ;; + _dates) + args=( ${args:#([(][^)]##\)|)-[12noOAD]*} + '-f[specify format for matches]:format:_date_formats' + '-F[select a future rather than past date]' + ) + ;; + _(path_|)files) + args=( ${args:#([(][^)]##\)|)-[OAD]*} + '-g+[specify file glob pattern]:glob pattern' + '-/[complete only directories]' + ) + ;; + _parameters) + args+=( + '-g+[specify pattern to filter parameter type by]:pattern' + ) + ;; + _pids) + args+=( '-m+[pattern to filter process command line by]:pattern' ) + ;; + _process_names) + args+=( + '-a[include all processes]' + '-t[use truncated process names]' + ) + ;; + _sys_calls) + args+=( + '-a[add "all" as an additional match]' + '-n[add "none" as an additional match]' + ) + ;; +esac + +_arguments -C -s -S -A "-*" $args && ret=0 if [[ -n $state ]]; then if (( $+opt_args[-a] )); then -- cgit v1.2.3 From 632fee7cdfcd234a5c7c53f17777ca18e62d82e3 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sat, 30 Oct 2021 23:27:29 +0200 Subject: 49528: allow multiple -D options to compadd --- ChangeLog | 4 +++ Completion/X/Command/_xinput | 3 +-- Completion/Zsh/Command/_compadd | 2 +- Doc/Zsh/compwid.yo | 2 ++ Src/Zle/comp.h | 2 +- Src/Zle/compcore.c | 59 ++++++++++++++++++++++++++++------------- Src/Zle/complete.c | 21 ++++++++++++--- 7 files changed, 68 insertions(+), 25 deletions(-) (limited to 'Completion/Zsh/Command/_compadd') diff --git a/ChangeLog b/ChangeLog index 0f1886220..7721ccc8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-10-30 Oliver Kiddle + * 49528: Src/Zle/comp.h, Src/Zle/compcore.c, Src/Zle/complete.c, + Completion/X/Command/_xinput, Completion/Zsh/Command/_compadd, + Doc/Zsh/compwid.yo: allow multiple -D options to compadd + * unposted (c.f. Bart: 49531): Test/Y02compmatch.ztst: fix test 2021-10-27 Matthew Martin diff --git a/Completion/X/Command/_xinput b/Completion/X/Command/_xinput index 00a976d5d..2bbadd65a 100644 --- a/Completion/X/Command/_xinput +++ b/Completion/X/Command/_xinput @@ -106,8 +106,7 @@ case $state in if [[ $PREFIX$SUFFIX = [^-]*[^0-9]* ]]; then # match based on the names but insert IDs - compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D ids -a names - compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D disp -a names + compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D ids -D disp -a names compadd "$expl[@]" -U -ld disp -a ids && ret=0 zstyle -s ":completion:${curcontext}:input-devices" insert-ids out || out=menu diff --git a/Completion/Zsh/Command/_compadd b/Completion/Zsh/Command/_compadd index 9c92cda76..4456cf71e 100644 --- a/Completion/Zsh/Command/_compadd +++ b/Completion/Zsh/Command/_compadd @@ -31,7 +31,7 @@ args=( '-n[hide matches in completion listing]' '-O+[populate array with matches instead of adding them]:array:_parameters -g "*array*"' '-A+[populate array with expanded matches instead of adding them]:array:_parameters -g "*array*"' - '-D+[delete elements from array corresponding to non-matching candidates]:array:_parameters -g "*array*"' + '*-D+[delete elements from array corresponding to non-matching candidates]:array:_parameters -g "*array*"' ) case $service in diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index 9f67f13b7..d32a0702f 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -725,6 +725,8 @@ As with tt(-O), the var(completions) are not added to the set of matches. Instead, whenever the var(n)th var(completion) does not match, the var(n)th element of the var(array) is removed. Elements for which the corresponding var(completion) matches are retained. +This option can be used more than once to remove elements from multiple +arrays. ) item(tt(-C))( This option adds a special match which expands to all other matches diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 2e3249b52..0c5fbd4f0 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -329,7 +329,7 @@ struct cadata { char *exp; /* explanation (-X) */ char *apar; /* array to store matches in (-A) */ char *opar; /* array to store originals in (-O) */ - char *dpar; /* array to delete non-matches in (-D) */ + char **dpar; /* arrays to delete non-matches in (-D) */ char *disp; /* array with display lists (-d) */ char *mesg; /* message to show unconditionally (-x) */ int dummies; /* add that many dummy matches */ diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 63136854e..2f3d53834 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -2081,10 +2081,10 @@ addmatches(Cadata dat, char **argv) /* ms: "match string" - string to use as completion. * Overloaded at one place as a temporary. */ char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; - char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre; + char **aign = NULL, ***dparr = NULL, *oaq = autoq, *oppre = dat->ppre; char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL; char **arrays = NULL; - int lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; + int dind, lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; int ppl = 0, psl = 0, ilen = 0; int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern; int isexact, doadd, ois = instring, oib = inbackt; @@ -2092,7 +2092,7 @@ addmatches(Cadata dat, char **argv) struct cmlist mst; Cmlist oms = mstack; Patprog cp = NULL, *pign = NULL; - LinkList aparl = NULL, oparl = NULL, dparl = NULL; + LinkList aparl = NULL, oparl = NULL, *dparl = NULL; Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl; Heap oldheap; @@ -2186,11 +2186,24 @@ addmatches(Cadata dat, char **argv) if (dat->opar) oparl = newlinklist(); if (dat->dpar) { - if (*(dat->dpar) == '(') - dparr = NULL; - else if ((dparr = get_user_var(dat->dpar)) && !*dparr) - dparr = NULL; - dparl = newlinklist(); + int darr = 0, dparlen = arrlen(dat->dpar); + char **tail = dat->dpar + dparlen; + + dparr = (char ***)hcalloc((1 + dparlen) * sizeof(char **)); + dparl = (LinkList *)hcalloc((1 + dparlen) * sizeof(LinkList)); + queue_signals(); + while (darr < dparlen) { + if ((dparr[darr] = getaparam(dat->dpar[darr])) && *dparr[darr]) { + dparr[darr] = arrdup(dparr[darr]); + dparl[darr++] = newlinklist(); + } else { + /* swap in the last -D argument if we didn't get a non-empty array */ + dat->dpar[darr] = *--tail; + *tail = NULL; + --dparlen; + } + } + unqueue_signals(); } /* Store the matcher in our stack of matchers. */ if (dat->match) { @@ -2507,8 +2520,10 @@ addmatches(Cadata dat, char **argv) } if (!addit) { compignored++; - if (dparr && !*++dparr) - dparr = NULL; + for (dind = 0; dparl && dparl[dind]; dind++) { + if (dparr[dind] && !*++dparr[dind]) + dparr[dind] = NULL; + } goto next_array; } } @@ -2525,8 +2540,10 @@ addmatches(Cadata dat, char **argv) !(dat->flags & CMF_FILE) ? 1 : 2) : 0), &bpl, bcp, &bsl, bcs, &isexact))) { - if (dparr && !*++dparr) - dparr = NULL; + for (dind = 0; dparl && dparl[dind]; dind++) { + if (dparr[dind] && !*++dparr[dind]) + dparr[dind] = NULL; + } goto next_array; } if (doadd) { @@ -2553,10 +2570,14 @@ addmatches(Cadata dat, char **argv) addlinknode(aparl, ms); if (dat->opar) addlinknode(oparl, s); - if (dat->dpar && dparr) { - addlinknode(dparl, *dparr); - if (!*++dparr) - dparr = NULL; + if (dat->dpar) { + for (dind = 0; dparl[dind]; dind++) { + if (dparr[dind]) { + addlinknode(dparl[dind], *dparr[dind]); + if (!*++dparr[dind]) + dparr[dind] = NULL; + } + } } free_cline(lc); } @@ -2584,8 +2605,10 @@ addmatches(Cadata dat, char **argv) set_list_array(dat->apar, aparl); if (dat->opar) set_list_array(dat->opar, oparl); - if (dat->dpar) - set_list_array(dat->dpar, dparl); + if (dat->dpar) { + for (dind = 0; dparl[dind]; dind++) + set_list_array(dat->dpar[dind], dparl[dind]); + } if (dat->exp) addexpl(0); if (!hasallmatch && (dat->aflags & CAF_ALL)) { diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index 71d114de9..67a60963e 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -607,6 +607,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) char *oarg = NULL; /* argument of -o option */ int added; /* return value */ Cmatcher match = NULL; + size_t dparlen = 0, dparsize = 0; /* no. of -D options and array size */ if (incompfunc != 1) { zwarnnam(name, "can only be called from completion function"); @@ -614,7 +615,8 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) } dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = dat.mesg = dat.pre = dat.suf = dat.group = dat.rems = dat.remf = dat.disp = - dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL; + dat.ign = dat.exp = dat.apar = dat.opar = NULL; + dat.dpar = NULL; dat.match = NULL; dat.flags = 0; dat.aflags = CAF_MATCH; @@ -741,7 +743,12 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) e = "parameter name expected after -%c"; break; case 'D': - sp = &(dat.dpar); + if (dparsize <= dparlen + 1) { + dparsize = (dparsize + 1) * 2; + dat.dpar = (char **)zrealloc(dat.dpar, sizeof(char *) * dparsize); + } + sp = dat.dpar + dparlen++; + *sp = dat.dpar[dparlen] = NULL; e = "parameter name expected after -%c"; break; case 'd': @@ -768,11 +775,13 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) } else { zwarnnam(name, "number expected after -%c", *p); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } if (dat.dummies < 0) { zwarnnam(name, "invalid number: %d", dat.dummies); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } break; @@ -782,6 +791,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) default: zwarnnam(name, "bad option: -%c", *p); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } if (sp) { @@ -802,6 +812,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) /* Missing argument: argv[N] == "-X", argv[N+1] == NULL. */ zwarnnam(name, e, *p); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } if (m) { @@ -820,17 +831,21 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) if (mstr && (match = parse_cmatcher(name, mstr)) == pcm_err) { zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } zsfree(mstr); if (!*argv && !dat.group && !dat.mesg && - !(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON|CAF_ALL))) + !(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON|CAF_ALL))) { + zfree(dat.dpar, dparsize); return 1; + } dat.match = match = cpcmatcher(match); added = addmatches(&dat, argv); freecmatcher(match); + zfree(dat.dpar, dparsize); return added; } -- cgit v1.2.3