summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--Completion/Builtins/_arrays6
-rw-r--r--Completion/Builtins/_zstyle2
-rw-r--r--Completion/Commands/_bash_completions4
-rw-r--r--Completion/Commands/_history_complete_word49
-rw-r--r--Completion/Core/_history33
-rw-r--r--Completion/Core/_main_complete8
-rw-r--r--Completion/Core/_parameters8
-rw-r--r--Completion/Core/_setup12
-rw-r--r--Completion/Core/_tags14
-rw-r--r--Completion/Debian/_apt2
-rw-r--r--Completion/X/_x_extension2
-rw-r--r--Doc/Zsh/compsys.yo29
-rw-r--r--Doc/Zsh/compwid.yo7
-rw-r--r--Src/Zle/compcore.c72
-rw-r--r--Src/Zle/compctl.c5
-rw-r--r--Src/Zle/complist.c2
-rw-r--r--Src/Zle/computil.c29
-rw-r--r--Src/zsh.h4
19 files changed, 209 insertions, 93 deletions
diff --git a/ChangeLog b/ChangeLog
index 3ae413e20..59cb0b23a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2000-06-22 Sven Wischnowsky <wischnow@zsh.org>
+
+ * 12029: Completion/Builtins/_arrays, Completion/Builtins/_zstyle,
+ Completion/Commands/_bash_completions,
+ Completion/Commands/_history_complete_word,
+ Completion/Core/_history, Completion/Core/_main_complete,
+ Completion/Core/_parameters, Completion/Core/_setup,
+ Completion/Core/_tags, Completion/Debian/_apt,
+ Completion/X/_x_extension, Doc/Zsh/compsys.yo, Doc/Zsh/compwid.yo,
+ Src/zsh.h, Src/Zle/compcore.c, Src/Zle/compctl.c,
+ Src/Zle/complist.c, Src/Zle/computil.c: allow subscripts for
+ compadd -[ak]; new style for history completion; better
+ list-colors handling
+
2000-06-22 Clint Adams <schizo@debian.org>
* 12027: Completion/User/_mailboxes: fix splitting problem in
diff --git a/Completion/Builtins/_arrays b/Completion/Builtins/_arrays
index cbeac7118..5ab6d41f0 100644
--- a/Completion/Builtins/_arrays
+++ b/Completion/Builtins/_arrays
@@ -1,3 +1,5 @@
-#defcomp shift
+#compdef shift
-complist -A
+local expl
+
+_wanted arrays expl array compadd -k "parameters[(R)*array*~*local*]"
diff --git a/Completion/Builtins/_zstyle b/Completion/Builtins/_zstyle
index 764afb5a1..fefa8af51 100644
--- a/Completion/Builtins/_zstyle
+++ b/Completion/Builtins/_zstyle
@@ -136,7 +136,7 @@ while [[ -n $state ]]; do
ctop=cz
fi
_wanted styles expl style \
- compadd -M 'r:|-=* r:|=*' - ${(k)styles[(R)[^:]#[$ctop][^:]#:*]}
+ compadd -M 'r:|-=* r:|=*' -k "styles[(R)[^:]#[$ctop][^:]#:*]"
;;
style-arg)
diff --git a/Completion/Commands/_bash_completions b/Completion/Commands/_bash_completions
index 50600290d..fd2222797 100644
--- a/Completion/Commands/_bash_completions
+++ b/Completion/Commands/_bash_completions
@@ -33,8 +33,8 @@ local key=$KEYS[-1] expl
case $key in
'!') _main_complete _command_names
;;
- '$') _main_complete - _wanted parameters expl 'exported parameters' \
- compadd - "${(@k)parameters[(R)*export*]}"
+ '$') _main_complete - parameters _wanted parameters expl 'exported parameters' \
+ compadd -k 'parameters[(R)*export*]'
;;
'@') _main_complete _hosts
;;
diff --git a/Completion/Commands/_history_complete_word b/Completion/Commands/_history_complete_word
index 300100f59..01cd32fce 100644
--- a/Completion/Commands/_history_complete_word
+++ b/Completion/Commands/_history_complete_word
@@ -7,20 +7,26 @@
#
# Available styles:
#
-# :history-words:list -- display lists of available matches
-# :history-words:stop -- prevent looping at beginning and end of matches
-# during menu-completion
-# :history-words:sort -- sort matches lexically (default is to sort by age)
-# :history-words:remove-all-dups --
-# remove /all/ duplicate matches rather than just
-# consecutives
-#
+# list -- display lists of available matches
+# stop -- prevent looping at beginning and end of matches during
+# menu-completion
+# sort -- sort matches lexically (default is to sort by age)
+# remove-all-dups --
+# remove /all/ duplicate matches rather than just consecutives
+# range -- range of history words to complete
_history_complete_word () {
setopt localoptions nullglob rcexpandparam extendedglob
unsetopt markdirs globsubst shwordsplit nounset ksharrays
- local expl direction stop
+ local expl direction stop curcontext="$curcontext"
+ local max slice hmax=$#historywords
+
+ if [[ -z "$curcontext" ]]; then
+ curcontext=history-words:::
+ else
+ curcontext="history-words${curcontext#*:}"
+ fi
if [[ $WIDGET = *newer ]]; then
direction=newer
@@ -32,6 +38,19 @@ _history_complete_word () {
zstyle -t ":completion:${curcontext}:history-words" list || compstate[list]=''
+ if zstyle -s ":completion:${curcontext}:history-words" range max; then
+ if [[ $max = *:* ]]; then
+ slice=${max#*:}
+ max=${max%:*}
+ else
+ slice=$max
+ fi
+ [[ max -gt hmax ]] && max=$hmax
+ else
+ max=$hmax
+ slice=$max
+ fi
+
if [[ -n "$compstate[old_list]" &&
( -n "$stop" || "$compstate[insert]" = menu ) ]] ; then
# array of matches is newest -> oldest (reverse of history order)
@@ -66,11 +85,11 @@ _history_complete_word () {
_history_complete_word_gen_matches
fi
- [[ -n "$compstate[nmatches]" ]]
+ (( $compstate[nmatches] ))
}
_history_complete_word_gen_matches () {
- local opt h_words
+ local opt beg=2
[[ -n "$_hist_stop" ]] && PREFIX="$_hist_old_prefix"
@@ -90,9 +109,11 @@ _history_complete_word_gen_matches () {
SUFFIX="$SUFFIX$ISUFFIX"
ISUFFIX=
- h_words=( "${(@)historywords[2,-1]}" )
- _wanted "$opt" history-words expl 'history word' \
- compadd -Q -a h_words
+ while [[ $compstate[nmatches] -eq 0 && beg -lt max ]]; do
+ _main_complete - history _wanted "$opt" history-words expl 'history word' \
+ compadd -Q -a 'historywords[beg,beg+slice]'
+ (( beg+=slice ))
+ done
zstyle -t ":completion:${curcontext}:history-words" list ||
compstate[list]=
diff --git a/Completion/Core/_history b/Completion/Core/_history
index 109bda91f..dafd61407 100644
--- a/Completion/Core/_history
+++ b/Completion/Core/_history
@@ -11,12 +11,12 @@
#
# Available styles:
#
-# :history-words:sort -- sort matches lexically (default is to sort by age)
-# :history-words:remove-all-dups --
-# remove /all/ duplicate matches rather than just
-# consecutives
+# sort -- sort matches lexically (default is to sort by age)
+# remove-all-dups --
+# remove /all/ duplicate matches rather than just consecutives
+# range -- range of history words to complete
-local opt expl h_words
+local opt expl max slice hmax=$#historywords beg=2
if zstyle -t ":completion:${curcontext}:" remove-all-dups; then
opt=-
@@ -30,6 +30,19 @@ else
opt="${opt}V"
fi
+if zstyle -s ":completion:${curcontext}:" range max; then
+ if [[ $max = *:* ]]; then
+ slice=${max#*:}
+ max=${max%:*}
+ else
+ slice=$max
+ fi
+ [[ max -gt hmax ]] && max=$hmax
+else
+ max=$hmax
+ slice=$max
+fi
+
PREFIX="$IPREFIX$PREFIX"
IPREFIX=
SUFFIX="$SUFFIX$ISUFFIX"
@@ -37,5 +50,11 @@ ISUFFIX=
# We skip the first element of historywords so the current word doesn't
# interfere with the completion
-h_words=( "${(@)historywords[2,-1]}" )
-_wanted "$opt" history-words expl 'history word' compadd -Q -a h_words
+
+while [[ $compstate[nmatches] -eq 0 && beg -lt max ]]; do
+ _wanted "$opt" history-words expl 'history word' \
+ compadd -Q -a 'historywords[beg,beg+slice]'
+ (( beg+=slice ))
+done
+
+(( $compstate[namtches] ))
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index b0798f67d..f238c88ac 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -34,7 +34,7 @@ local func funcs ret=1 tmp _compskip format nm call match \
_saved_insert="${compstate[insert]}" \
_saved_colors="$ZLS_COLORS"
-typeset -U _lastdescr _comp_ignore
+typeset -U _lastdescr _comp_ignore _comp_colors
[[ -z "$curcontext" ]] && curcontext=:::
@@ -263,7 +263,11 @@ fi
( "$_comp_force_list" = ?* && nm -ge _comp_force_list ) ]] &&
compstate[list]="${compstate[list]//messages} force"
-[[ "$compstate[old_list]" = keep ]] && ZLS_COLORS="$_saved_colors"
+if [[ "$compstate[old_list]" = keep ]]; then
+ ZLS_COLORS="$_saved_colors"
+else
+ ZLS_COLORS="${(j.:.)_comp_colors}"
+fi
# Now call the post-functions.
diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters
index 0e8c548f7..d3a163b49 100644
--- a/Completion/Core/_parameters
+++ b/Completion/Core/_parameters
@@ -1,8 +1,8 @@
#autoload
# This should be used to complete parameter names if you need some of the
-# extra options of compadd. It first tries to complete only non-local
-# parameters. All arguments are given to compadd.
+# extra options of compadd. It completes only non-local parameters.
-compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }" ||
- compadd "$@" - "${(@)${(@)${(@f)$(typeset)}%%\=*}##* }"
+local expl
+
+_wanted parameters expl parameter compadd "$@" -k 'parameters[(R)^*local*]'
diff --git a/Completion/Core/_setup b/Completion/Core/_setup
index 50e3dbfd8..1278fa1ba 100644
--- a/Completion/Core/_setup
+++ b/Completion/Core/_setup
@@ -7,16 +7,10 @@ local val nm="$compstate[nmatches]"
if zstyle -a ":completion:${curcontext}:$1" list-colors val; then
zmodload -i zsh/complist
if [[ "$1" = default ]]; then
- ZLS_COLORS="${(j.:.)${(@)val:gs/:/\\\:}}"
+ _comp_colors=( "$val[@]" )
else
- local simple grouped
-
- simple=( "(${2})${(@)^val:#\(*\)*}" )
- grouped=( "${(M@)val:#\(*\)*}" )
- simple="${(j.:.)simple}:"
- grouped="${(j.:.)grouped}:"
- [[ "$ZLS_COLORS" != *${simple}* ]] && ZLS_COLORS="${simple}$ZLS_COLORS"
- [[ "$ZLS_COLORS" != *${grouped}* ]] && ZLS_COLORS="${grouped}$ZLS_COLORS"
+ _comp_colors=( "$_comp_colors[@]"
+ "(${2})${(@)^val:#\(*\)*}" "${(M@)val:#\(*\)*}" )
fi
# Here is the problem mentioned in _main_complete.
diff --git a/Completion/Core/_tags b/Completion/Core/_tags
index c98990cec..5a1015356 100644
--- a/Completion/Core/_tags
+++ b/Completion/Core/_tags
@@ -30,18 +30,8 @@ if (( $# )); then
[[ "$1" = -(|-) ]] && shift
- if zstyle -a ":completion:${curcontext}:" group-order order; then
- local name
-
- for name in "$order[@]"; do
- compadd -J "$name"
- compadd -V "$name"
- compadd -J "$name" -1
- compadd -V "$name" -1
- compadd -J "$name" -2
- compadd -V "$name" -2
- done
- fi
+ zstyle -a ":completion:${curcontext}:" group-order order &&
+ compgroups "$order[@]"
# Set and remember offered tags.
diff --git a/Completion/Debian/_apt b/Completion/Debian/_apt
index 8fa056594..cfc6880df 100644
--- a/Completion/Debian/_apt
+++ b/Completion/Debian/_apt
@@ -469,7 +469,7 @@ _apt-config () {
-- \
/$'shell\0'/ \
\( \
- /$'[^\0]#\0'/ ':parameters:shell variable to assign:compadd "$expl[@]" - "${(@k)parameters}"' \
+ /$'[^\0]#\0'/ ':parameters:shell variable to assign:_parameters' \
/$'[^\0]#\0'/ ':values:configuration key:compadd "$expl[@]" - ${${(f)"$(apt-config dump 2>&1)"}% *}' \
\) \# \| \
/$'dump\0'/ \| \
diff --git a/Completion/X/_x_extension b/Completion/X/_x_extension
index 690226975..d1a299e8b 100644
--- a/Completion/X/_x_extension
+++ b/Completion/X/_x_extension
@@ -15,5 +15,5 @@ else
[[ "$1" = - ]] && shift
_wanted extensions expl 'X extensions' \
- compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' - _xe_cache
+ compadd "$@" -M 'm:{a-z}={A-Z} r:|-=* r:|=*' -a _xe_cache
fi
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 67d75bf3f..18eb388a8 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -386,6 +386,22 @@ ifnzman(noderef(The zsh/zutil Module))).
When looking up styles the completion system uses full context names,
including the tag.
+To have more control over when certain values for styles are used one
+can use the special parameters available in completion widgets (see
+ifzman(see zmanref(zshcompwid))\
+ifnzman(noderef(Completion Widgets)))\
+) and the tt(-e) option to tt(zstyle) that makes the value be
+evaluated when looked up. For example, to make the tt(completer)
+style have a different value when completion for the tt(cvs) command,
+one could use the tt(words) special array:
+
+example(zstyle -e ':completion:*' completer '
+ if [[ $words[1] = cvs ]]; then
+ reply=(_complete)
+ else
+ reply=(_complete _approximate)
+ fi')
+
Styles determine such things as how the matches are generated; some of them
correspond to shell options (for example, the use of menu completion), but
styles provide more specific control. They can have any number of strings as
@@ -1732,6 +1748,19 @@ is any, and if it is different from the word on the line.
)
enditem()
)
+kindex(range, completion style)
+item(tt(range))(
+This is used by the tt(_history) completer and the
+tt(_history_complete_word) bindable command to decide which words
+should be completed. It may be set to a number, var(N), to say that
+only the last var(N) words from the history should be completed. The
+value may also be of the form `var(max)tt(:)var(slice)'. This means
+that first the last var(slice) words will be completed. If that
+yields no matches, the var(slice) words before those will be tried and
+so on, until either at least one match is generated or var(max) words
+have been tried. The default is to complete all words from the
+history at once.
+)
kindex(remove-all-dups, completion style)
item(tt(remove-all-dups))(
The tt(_history_complete_word) bindable command and the tt(_history)
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index b63889573..8c86eef3c 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -485,11 +485,14 @@ Like tt(-i), but gives an ignored suffix.
)
item(tt(-a))(
With this flag the var(words) are taken as names of arrays and the
-possible matches are their values.
+possible matches are their values. If only some elements of the
+arrays are needed, the var(words) may also contain subscripts, as in
+`tt(foo[2,-1])'.
)
item(tt(-k))(
With this flag the var(words) are taken as names of associative arrays
-and the possible matches are their keys.
+and the possible matches are their keys. As for tt(-a), the
+var(words) may also contain subscripts, as in `tt(foo[(R)*bar*])'.
)
item(tt(-d) var(array))(
This adds per-match display strings. The var(array) should contain one
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 62d63000a..ad87fe619 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1553,14 +1553,17 @@ get_user_var(char *nam)
}
static char **
-get_user_keys(char *nam)
+get_data_arr(char *name, int keys)
{
- char **ret;
+ struct value vbuf;
+ Value v;
- if ((ret = gethkparam(nam)))
- return (incompfunc ? arrdup(ret) : ret);
+ if (!(v = fetchvalue(&vbuf, &name, 1,
+ (keys ? SCANPM_WANTKEYS : SCANPM_WANTVALS) |
+ SCANPM_MATCHMANY)))
+ return NULL;
- return NULL;
+ return getarrvalue(v);
}
/* This is used by compadd to add a couple of matches. The arguments are
@@ -1586,9 +1589,10 @@ addmatches(Cadata dat, char **argv)
Patprog cp = NULL, *pign = NULL;
LinkList aparl = NULL, oparl = NULL, dparl = NULL;
Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl;
+ Heap oldheap;
if (!*argv) {
- SWITCHHEAPS(compheap) {
+ SWITCHHEAPS(oldheap, compheap) {
/* Select the group in which to store the matches. */
gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) |
((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) |
@@ -1602,7 +1606,7 @@ addmatches(Cadata dat, char **argv)
}
if (dat->mesg)
addmesg(dat->mesg);
- } SWITCHBACKHEAPS;
+ } SWITCHBACKHEAPS(oldheap);
return 1;
}
@@ -1638,7 +1642,7 @@ addmatches(Cadata dat, char **argv)
/* Switch back to the heap that was used when the completion widget
* was invoked. */
- SWITCHHEAPS(compheap) {
+ SWITCHHEAPS(oldheap, compheap) {
if ((doadd = (!dat->apar && !dat->opar && !dat->dpar))) {
if (dat->aflags & CAF_MATCH)
hasmatched = 1;
@@ -1887,17 +1891,22 @@ addmatches(Cadata dat, char **argv)
obpl = bpl;
obsl = bsl;
if (dat->aflags & CAF_ARRAYS) {
- arrays = argv;
- argv = NULL;
- while (*arrays && (!(argv = ((dat->aflags & CAF_KEYS) ?
- get_user_keys(*arrays) :
- get_user_var(*arrays))) || !*argv))
+ Heap oldheap2;
+
+ SWITCHHEAPS(oldheap2, oldheap) {
+ arrays = argv;
+ argv = NULL;
+ while (*arrays &&
+ (!(argv = get_data_arr(*arrays,
+ (dat->aflags & CAF_KEYS))) ||
+ !*argv))
+ arrays++;
arrays++;
- arrays++;
- if (!argv) {
- ms = NULL;
- argv = &ms;
- }
+ if (!argv) {
+ ms = NULL;
+ argv = &ms;
+ }
+ } SWITCHBACKHEAPS(oldheap2);
}
if (dat->ppre)
ppl = strlen(dat->ppre);
@@ -1994,17 +2003,22 @@ addmatches(Cadata dat, char **argv)
free_cline(lc);
}
if ((dat->aflags & CAF_ARRAYS) && !argv[1]) {
- argv = NULL;
- while (*arrays && (!(argv = ((dat->aflags & CAF_KEYS) ?
- get_user_keys(*arrays) :
- get_user_var(*arrays))) || !*argv))
+ Heap oldheap2;
+
+ SWITCHHEAPS(oldheap2, oldheap) {
+ argv = NULL;
+ while (*arrays &&
+ (!(argv = get_data_arr(*arrays,
+ (dat->aflags & CAF_KEYS))) ||
+ !*argv))
+ arrays++;
arrays++;
- arrays++;
- if (!argv) {
- ms = NULL;
- argv = &ms;
- }
- argv--;
+ if (!argv) {
+ ms = NULL;
+ argv = &ms;
+ }
+ argv--;
+ } SWITCHBACKHEAPS(oldheap2);
}
}
if (dat->apar)
@@ -2015,7 +2029,7 @@ addmatches(Cadata dat, char **argv)
set_list_array(dat->dpar, dparl);
if (dat->exp)
addexpl();
- } SWITCHBACKHEAPS;
+ } SWITCHBACKHEAPS(oldheap);
/* We switched back to the current heap, now restore the stack of
* matchers. */
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index c7356b69f..052209ee3 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -2268,13 +2268,14 @@ static int cdepth = 0;
static int
makecomplistctl(int flags)
{
+ Heap oldheap;
int ret;
if (cdepth == MAX_CDEPTH)
return 0;
cdepth++;
- SWITCHHEAPS(compheap) {
+ SWITCHHEAPS(oldheap, compheap) {
int ooffs = offs, lip, lp;
char *str = comp_str(&lip, &lp, 0), *t;
char *os = cmdstr, **ow = clwords, **p, **q, qc;
@@ -2333,7 +2334,7 @@ makecomplistctl(int flags)
clwords = ow;
clwnum = on;
clwpos = op;
- } SWITCHBACKHEAPS;
+ } SWITCHBACKHEAPS(oldheap);
cdepth--;
return ret;
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 445c89bb7..75a23f0e5 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -1750,8 +1750,6 @@ domenuselect(Hookdef dummy, Chdata dat)
}
setwish = wasnext = 0;
- getk:
-
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
zbeep();
break;
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index da72a6902..a329d34d0 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -3200,7 +3200,7 @@ cfp_matcher_pats(char *matcher, char *add)
}
}
if (*add) {
- char *ret = "", buf[259], *oadd = add;
+ char *ret = "", buf[259];
for (mp = ms; *add; add++, mp++) {
if (!(m = *mp)) {
@@ -3661,6 +3661,32 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
return 1;
}
+static int
+bin_compgroups(char *nam, char **args, char *ops, int func)
+{
+ Heap oldheap;
+ char *n;
+
+ SWITCHHEAPS(oldheap, compheap) {
+ while ((n = *args++)) {
+ endcmgroup(NULL);
+ begcmgroup(n, 0);
+ endcmgroup(NULL);
+ begcmgroup(n, CGF_NOSORT);
+ endcmgroup(NULL);
+ begcmgroup(n, CGF_UNIQALL);
+ endcmgroup(NULL);
+ begcmgroup(n, CGF_NOSORT|CGF_UNIQCON);
+ endcmgroup(NULL);
+ begcmgroup(n, CGF_UNIQALL);
+ endcmgroup(NULL);
+ begcmgroup(n, CGF_NOSORT|CGF_UNIQCON);
+ }
+ } SWITCHBACKHEAPS(oldheap);
+
+ return 0;
+}
+
static struct builtin bintab[] = {
BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL),
@@ -3670,6 +3696,7 @@ static struct builtin bintab[] = {
BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL),
BUILTIN("compfmt", 0, bin_compfmt, 2, -1, 0, NULL, NULL),
BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL),
+ BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL),
};
diff --git a/Src/zsh.h b/Src/zsh.h
index 293947463..49acf129c 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1629,8 +1629,8 @@ struct heap {
# define NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do
# define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0);
-# define SWITCHHEAPS(h) do { Heap _switch_oldheaps = switch_heaps(h); do
-# define SWITCHBACKHEAPS while (0); switch_heaps(_switch_oldheaps); } while (0);
+# define SWITCHHEAPS(o, h) do { o = switch_heaps(h); do
+# define SWITCHBACKHEAPS(o) while (0); switch_heaps(o); } while (0);
/****************/
/* Debug macros */