Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
RE: zsh-3.1.5-pws-5: mixing "old" and "new" completions?
- X-seq: zsh-workers 5059
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: RE: zsh-3.1.5-pws-5: mixing "old" and "new" completions?
- Date: Wed, 27 Jan 1999 13:25:59 +0100 (MET)
- In-reply-to: "Andrej Borsenkow"'s message of Tue, 26 Jan 1999 14:52:04 +0300
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Andrej Borsenkow wrote:
> What I think about, is two interfaces: compctl->new completion and new
> completion->compctl. That is
The patch below implements this:
new->old:
The builtin `compcall' can be called from a new style completion
function and makes the `compctl's for the current settings of
COMMAND, IPREFIX, PREFIX, SUFFIX, and argv be used. Currently this
builtin accepts only to options: `T' and `D'. Without any options
the `compctl's for first completion (`-T') and for default (`-D')
completion are *not* tried. You can switch this on by using the
appropriate option.
`compcall' accepts no other option or argument, for now. It would
be easy to make it accept arguments for the command line words to
use, for the command name to use, etc. If this turns out to be
interesting to have, I'll add it.
old->new:
I'm not too sure that I like to support this way, so this is rather
hackish at the moment (meaning: even more than the rest of the new
style completion). If you give the `-K' option to `compctl' a string
that begins with one space, the named function will be called with
the variables and arguments as expected by new style completion
functions.
Ok. Even though I said that this is very experimental, I strongly
suggest to use this patch. First, it makes testing the new stuff
easier, and second, the patch contains also a minor fix (compadd now
accepts zero arguments).
The patch also changes the file `new-completion-examples' to use
`compctl's that are defined. With that you should be able to just
source this file, use the new completion stuff and still be able to
use your `compctl's. You may want to modify or delete some of the
examples in the file. You may also want to alter the way compcall is
invoked, see the comments in the file after applying this patch (or
look at the end of this patch).
[The patch looks big, but this is almost only because it contains a
lot of moving-code-around and re-indent-stuff.]
Bye
Sven
diff -u os/Zle/comp.h Src/Zle/comp.h
--- os/Zle/comp.h Tue Jan 26 14:24:21 1999
+++ Src/Zle/comp.h Wed Jan 27 11:14:43 1999
@@ -267,3 +267,8 @@
#define CLF_MISS 4
#define CLF_DIFF 8
#define CLF_SUF 16
+
+/* Flags for makecomplist*(). Things not to do. */
+
+#define CFN_FIRST 1
+#define CFN_DEFAULT 2
diff -u os/Zle/compctl.c Src/Zle/compctl.c
--- os/Zle/compctl.c Tue Jan 26 14:24:21 1999
+++ Src/Zle/compctl.c Wed Jan 27 12:07:24 1999
@@ -1677,7 +1677,7 @@
Compctl cc;
int ret = 0;
- if (!incompfunc) {
+ if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
@@ -1706,7 +1706,7 @@
char *pre = NULL, *suf = NULL, *group = NULL;
int f = 0, q = 0, m = 0, ns = 0, a = 0;
- if (!incompfunc) {
+ if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
@@ -1800,6 +1800,15 @@
return 0;
}
+/**/
+static int
+bin_compcall(char *name, char **argv, char *ops, int func)
+{
+ makecomplistctl((ops['T'] ? 0 : CFN_FIRST) |
+ (ops['D'] ? 0 : CFN_DEFAULT));
+ return 0;
+}
+
#define VAR(X) ((void *) (&(X)))
static struct compparam {
char *name;
@@ -1855,7 +1864,7 @@
static int
comp_wrapper(List list, FuncWrap w, char *name)
{
- if (!incompfunc)
+ if (incompfunc != 1)
return 1;
else {
char *octxt, *ocmd, *opre, *osuf, *oipre;
@@ -1906,7 +1915,7 @@
static int
comp_check(void)
{
- if (!incompfunc) {
+ if (incompfunc != 1) {
zerr("condition can only be used in completion function", NULL, 0);
return 0;
}
@@ -2118,7 +2127,8 @@
static struct builtin bintab[] = {
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
BUILTIN("complist", 0, bin_complist, 1, -1, 0, NULL, NULL),
- BUILTIN("compadd", 0, bin_compadd, 1, -1, 0, NULL, NULL),
+ BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL),
+ BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
};
static struct conddef cotab[] = {
diff -u os/Zle/zle_tricky.c Src/Zle/zle_tricky.c
--- os/Zle/zle_tricky.c Tue Jan 26 14:24:23 1999
+++ Src/Zle/zle_tricky.c Wed Jan 27 12:55:02 1999
@@ -3172,6 +3172,105 @@
} LASTALLOC;
}
+/* This calls the given function for new style completion. */
+
+/**/
+static void
+callcompfunc(char *s, char *fn)
+{
+ List list;
+ int lv = lastval;
+
+ if ((list = getshfunc(fn)) != &dummy_list) {
+ LinkList args = newlinklist();
+ char **p, *tmp;
+ int aadd = 0, usea = 1, icf = incompfunc;
+
+ addlinknode(args, fn);
+
+ zsfree(compcontext);
+ zsfree(compcommand);
+ compcommand = "";
+ if (inwhat == IN_MATH) {
+ if (insubscr) {
+ compcontext = "subscript";
+ compcommand = varname ? varname : "";
+ } else
+ compcontext = "math";
+ usea = 0;
+ } else if (lincmd)
+ compcontext = (insubscr ? "subscript" : "command");
+ else if (linredir) {
+ compcontext = "redirect";
+ if (rdstr)
+ compcommand = rdstr;
+ } else
+ switch (inwhat) {
+ case IN_ENV:
+ compcontext = "value";
+ compcommand = varname;
+ usea = 0;
+ break;
+ case IN_COND:
+ compcontext = "condition";
+ break;
+ default:
+ if (cmdstr) {
+ compcontext = "argument";
+ compcommand = cmdstr;
+ } else {
+ compcontext = "value";
+ if (clwords[0])
+ compcommand = clwords[0];
+ }
+ aadd = 1;
+ }
+ compcontext = ztrdup(compcontext);
+ tmp = quotename(compcommand, NULL, NULL, NULL);
+ untokenize(tmp);
+ compcommand = ztrdup(tmp);
+ if (usea && (!aadd || clwords[0]))
+ for (p = clwords + aadd; *p; p++) {
+ tmp = dupstring(*p);
+ untokenize(tmp);
+ addlinknode(args, tmp);
+ }
+ zsfree(compprefix);
+ zsfree(compsuffix);
+ if (unset(COMPLETEINWORD)) {
+ tmp = quotename(s, NULL, NULL, NULL);
+ untokenize(tmp);
+ compprefix = ztrdup(tmp);
+ compsuffix = ztrdup("");
+ } else {
+ char *ss = s + offs, sav;
+
+ tmp = quotename(s, &ss, NULL, NULL);
+ sav = *ss;
+ *ss = '\0';
+ untokenize(tmp);
+ compprefix = ztrdup(tmp);
+ *ss = sav;
+ untokenize(ss);
+ compsuffix = ztrdup(ss);
+ }
+ zsfree(compiprefix);
+ compiprefix = ztrdup("");
+ compcurrent = (usea ? (clwpos + 1 - aadd) : 1);
+ compnmatches = mnum;
+ incompfunc = 1;
+ startparamscope();
+ makecompparamsptr();
+ NEWHEAPS(compheap) {
+ doshfunc(fn, list, args, 0, 1);
+ } OLDHEAPS;
+ endparamscope();
+ lastcmd = 0;
+ incompfunc = icf;
+ }
+ lastval = lv;
+}
+
/* The beginning and end of a word range to be used by -l. */
static int brange, erange;
@@ -3224,100 +3323,10 @@
ccused = newlinklist();
ccstack = newlinklist();
- if (compfunc) {
- List list;
- int lv = lastval;
-
- if ((list = getshfunc(compfunc)) != &dummy_list) {
- LinkList args = newlinklist();
- char **p, *tmp;
- int aadd = 0, usea = 1;
-
- addlinknode(args, compfunc);
-
- zsfree(compcontext);
- zsfree(compcommand);
- compcommand = "";
- if (inwhat == IN_MATH) {
- if (insubscr) {
- compcontext = "subscript";
- compcommand = varname ? varname : "";
- } else
- compcontext = "math";
- usea = 0;
- } else if (lincmd)
- compcontext = (insubscr ? "subscript" : "command");
- else if (linredir) {
- compcontext = "redirect";
- if (rdstr)
- compcommand = rdstr;
- } else
- switch (inwhat) {
- case IN_ENV:
- compcontext = "value";
- compcommand = varname;
- usea = 0;
- break;
- case IN_COND:
- compcontext = "condition";
- break;
- default:
- if (cmdstr) {
- compcontext = "argument";
- compcommand = cmdstr;
- } else {
- compcontext = "value";
- if (clwords[0])
- compcommand = clwords[0];
- }
- aadd = 1;
- }
- compcontext = ztrdup(compcontext);
- tmp = quotename(compcommand, NULL, NULL, NULL);
- untokenize(tmp);
- compcommand = ztrdup(tmp);
- if (usea && (!aadd || clwords[0]))
- for (p = clwords + aadd; *p; p++) {
- tmp = dupstring(*p);
- untokenize(tmp);
- addlinknode(args, tmp);
- }
- zsfree(compprefix);
- zsfree(compsuffix);
- if (unset(COMPLETEINWORD)) {
- tmp = quotename(s, NULL, NULL, NULL);
- untokenize(tmp);
- compprefix = ztrdup(tmp);
- compsuffix = ztrdup("");
- } else {
- char *ss = s + offs, sav;
-
- tmp = quotename(s, &ss, NULL, NULL);
- sav = *ss;
- *ss = '\0';
- untokenize(tmp);
- compprefix = ztrdup(tmp);
- *ss = sav;
- untokenize(ss);
- compsuffix = ztrdup(ss);
- }
- zsfree(compiprefix);
- compiprefix = ztrdup("");
- compcurrent = (usea ? (clwpos + 1 - aadd) : 1);
- compnmatches = mnum;
- incompfunc = 1;
- startparamscope();
- makecompparamsptr();
- NEWHEAPS(compheap) {
- doshfunc(compfunc, list, args, 0, 1);
- } OLDHEAPS;
- endparamscope();
- lastcmd = 9;
- incompfunc = 0;
- }
- lastval = lv;
- } else
- makecomplistglobal(s, incmd, lst);
+ if (compfunc)
+ callcompfunc(s, compfunc);
+ else
+ makecomplistglobal(s, incmd, lst, 0);
endcmgroup(NULL);
@@ -3362,11 +3371,11 @@
if (*p == '\\')
bslash = 1;
else {
- if (*p == '$') {
+ if (*p == '$' || *p == '=') {
if (bslash)
p[-1] = Bnull;
else
- *p = String;
+ *p = (*p == '$' ? String : Equals);
}
bslash = 0;
}
@@ -3425,16 +3434,59 @@
} SWITCHBACKHEAPS;
}
+/**/
+void
+makecomplistctl(int flags)
+{
+ SWITCHHEAPS(compheap) {
+ HEAPALLOC {
+ int ooffs = offs, lip, lp;
+ char *str = comp_str(&lip, &lp), *t;
+ char *os = cmdstr, **ow = clwords, **p, **q;
+ int on = clwnum, op = clwpos;
+
+ clwnum = arrlen(pparams) + 1;
+ clwpos = compcurrent - 1;
+ cmdstr = ztrdup(compcommand);
+ clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
+ clwords[0] = ztrdup(cmdstr);
+ for (p = pparams, q = clwords + 1; *p; p++, q++) {
+ t = dupstring(*p);
+ ctokenize(t);
+ remnulargs(t);
+ *q = ztrdup(t);
+ }
+ *q = NULL;
+ offs = lip + lp;
+ incompfunc = 2;
+ makecomplistglobal(str,
+ (!clwpos && !strcmp(compcontext, "command")),
+ COMP_COMPLETE, flags);
+ incompfunc = 1;
+ offs = ooffs;
+ compnmatches = mnum;
+ zsfree(cmdstr);
+ freearray(clwords);
+ cmdstr = os;
+ clwords = ow;
+ clwnum = on;
+ clwpos = op;
+ } LASTALLOC;
+ } SWITCHBACKHEAPS;
+}
+
/* This function gets the compctls for the given command line and *
* adds all completions for them. */
/**/
static void
-makecomplistglobal(char *os, int incmd, int lst)
+makecomplistglobal(char *os, int incmd, int lst, int flags)
{
Compctl cc;
char *s;
+ ccont = CC_CCCONT;
+
if (lst == COMP_WIDGET) {
cc = compwidget->u.cc;
} else if (inwhat == IN_ENV)
@@ -3463,16 +3515,17 @@
cc = &cc_default;
else {
/* Otherwise get the matches for the command. */
- makecomplistcmd(os, incmd);
+ makecomplistcmd(os, incmd, flags);
cc = NULL;
}
if (cc) {
/* First, use the -T compctl. */
- makecomplistcc(&cc_first, os, incmd);
-
- if (!(ccont & CC_CCCONT))
- return;
+ if (!(flags & CFN_FIRST)) {
+ makecomplistcc(&cc_first, os, incmd);
+ if (!(ccont & CC_CCCONT))
+ return;
+ }
makecomplistcc(cc, os, incmd);
}
}
@@ -3481,18 +3534,19 @@
/**/
static void
-makecomplistcmd(char *os, int incmd)
+makecomplistcmd(char *os, int incmd, int flags)
{
Compctl cc;
Compctlp ccp;
char *s;
/* First, use the -T compctl. */
- makecomplistcc(&cc_first, os, incmd);
-
- if (!(ccont & CC_CCCONT))
- return;
+ if (!(flags & CFN_FIRST)) {
+ makecomplistcc(&cc_first, os, incmd);
+ if (!(ccont & CC_CCCONT))
+ return;
+ }
/* Then search the pattern compctls, with the command name and the *
* full pathname of the command. */
makecomplistpc(os, incmd);
@@ -3520,9 +3574,11 @@
(cc = ccp->cc)) ||
((s = dupstring(cmdstr)) && remlpaths(&s) &&
(ccp = (Compctlp) compctltab->getnode(compctltab, s)) &&
- (cc = ccp->cc)))))
+ (cc = ccp->cc))))) {
+ if (flags & CFN_DEFAULT)
+ return;
cc = &cc_default;
-
+ }
makecomplistcc(cc, os, incmd);
}
@@ -3811,12 +3867,12 @@
ccont |= (cc->mask2 & (CC_CCCONT | CC_DEFCONT | CC_PATCONT));
- if (!incompfunc && findnode(ccstack, cc))
+ if (incompfunc != 1 && findnode(ccstack, cc))
return;
addlinknode(ccstack, cc);
- if (!incompfunc && allccs) {
+ if (incompfunc != 1 && allccs) {
if (findnode(allccs, cc)) {
uremnode(ccstack, firstnode(ccstack));
return;
@@ -4424,45 +4480,50 @@
/* Add user names. */
maketildelist();
if (cc->func) {
- /* This handles the compctl -K flag. */
- List list;
- char **r;
- int lv = lastval;
-
- /* Get the function. */
- if ((list = getshfunc(cc->func)) != &dummy_list) {
- /* We have it, so build a argument list. */
- LinkList args = newlinklist();
- int osc = sfcontext;
-
- addlinknode(args, cc->func);
-
- if (delit) {
- p = dupstrpfx(os, ooffs);
- untokenize(p);
- addlinknode(args, p);
- p = dupstring(os + ooffs);
- untokenize(p);
- addlinknode(args, p);
- } else {
- addlinknode(args, lpre);
- addlinknode(args, lsuf);
+ if (cc->func[0] == ' ')
+ /* Temporary hack for access to new style completione. */
+ callcompfunc(os, cc->func + 1);
+ else {
+ /* This handles the compctl -K flag. */
+ List list;
+ char **r;
+ int lv = lastval;
+
+ /* Get the function. */
+ if ((list = getshfunc(cc->func)) != &dummy_list) {
+ /* We have it, so build a argument list. */
+ LinkList args = newlinklist();
+ int osc = sfcontext;
+
+ addlinknode(args, cc->func);
+
+ if (delit) {
+ p = dupstrpfx(os, ooffs);
+ untokenize(p);
+ addlinknode(args, p);
+ p = dupstring(os + ooffs);
+ untokenize(p);
+ addlinknode(args, p);
+ } else {
+ addlinknode(args, lpre);
+ addlinknode(args, lsuf);
+ }
+
+ /* This flag allows us to use read -l and -c. */
+ if (incompfunc != 1)
+ incompctlfunc = 1;
+ sfcontext = SFC_COMPLETE;
+ /* Call the function. */
+ doshfunc(cc->func, list, args, 0, 1);
+ sfcontext = osc;
+ incompctlfunc = 0;
+ /* And get the result from the reply parameter. */
+ if ((r = get_user_var("reply")))
+ while (*r)
+ addmatch(*r++, NULL);
}
-
- /* This flag allows us to use read -l and -c. */
- if (!incompfunc)
- incompctlfunc = 1;
- sfcontext = SFC_COMPLETE;
- /* Call the function. */
- doshfunc(cc->func, list, args, 0, 1);
- sfcontext = osc;
- incompctlfunc = 0;
- /* And get the result from the reply parameter. */
- if ((r = get_user_var("reply")))
- while (*r)
- addmatch(*r++, NULL);
+ lastval = lv;
}
- lastval = lv;
}
if (cc->mask & (CC_JOBS | CC_RUNNING | CC_STOPPED)) {
/* Get job names. */
@@ -4619,7 +4680,7 @@
}
/* No harm in allowing read -l and -c here, too */
- if (!incompfunc)
+ if (incompfunc != 1)
incompctlfunc = 1;
sfcontext = SFC_COMPLETE;
doshfunc(cc->ylist, list, args, 0, 1);
@@ -4686,7 +4747,7 @@
clwords += brange;
}
/* Produce the matches. */
- makecomplistcmd(s, incmd);
+ makecomplistcmd(s, incmd, CFN_FIRST);
/* And restore the things we changed. */
clwords = ow;
--- om/new-completion-examples Tue Jan 26 16:48:34 1999
+++ Misc/new-completion-examples Wed Jan 27 12:36:17 1999
@@ -90,11 +90,20 @@
# arguments from the command line are gives as positional parameters.
main-complete() {
- emulate -R zsh
+ # emulate -R zsh
local comp
setopt localoptions nullglob rcexpandparam globdots
unsetopt markdirs globsubst shwordsplit nounset
+
+ # We first try the `compctl's. This is without first (-T) and default (-D)
+ # completion. If you want them add `-T' and/or `-D' to this command.
+ # If this produces any matches, we don't try new style completion. If you
+ # want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
+ # below.
+
+ compcall
+ [[ -nmatches 0 ]] || return
# An entry for `--first--' is the replacement for `compctl -T'
# The `|| return 1' is used throughout: if a function producing matches
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author