Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

RE: zsh-3.1.5-pws-5: mixing "old" and "new" completions?



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