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

PATCH: nested quotes



Kept me busy the whole weekend...


Here, finally, is the patch that should clean up/fix/whatever
completion in nested quotes (when splitting such strings with `compset -q').


I've done extensive testing, but, as usual with the combination of
quoting and completion, there may still be bugs. Not too many, I
think.


Apart from making some things work in the way they should be expected, 
there are a few user-visible changes:

- Most importantly, the `-Q' option now only prevents the quotes for
  the inner-most quoting level. I.e. in most cases it will work as
  before, but if you have the match `foo bar' and try completion on
  `./zsh -c foo\ f<TAB>' you'll get `foo\ bar' inserted into the line, 
  because of the (in this case implicit) outer level. I think the
  result is what one really wants in most cases (i.e. you won't have
  to worry about quoting for outer levels even then).
  However, it would be possible to add another option that says that
  no quotes should be added at all. But I can't think of any example
  where one would want to do that.
- To help functions that have to use `-Q' but still need to get the
  quoting right (currently this is only `_path_files'), the `computil' 
  module now has the `compquote' builtin which gets names of scalars
  and arrays and quotes their values as needed for the innermost
  quoting level. I.e. the combination of this and `-Q' will get things 
  right.
- A new `compstate' key: `all_quotes' gives (read-only) access to the
  stack of quotes the completion code now maintains internally. It
  contains one character per level with the characters being one of
  \', \", \\.
- Two small changes for the automatically added closing quote and
  space. In cases like `./zsh -c ls\ \"f<TAB>' you now even get the
  correctly quoted closing quote (i.e. `\"' in this example). The
  second change is that in cases like `./zsh -c ls\ <TAB>' no space is 
  added any more. This is because the completion code can't know if
  you wanted a simple space or a quoted (`\ ') one. So it just does
  nothing. If anyone wants to argue: I really think this is the best
  solution. Trying to get some magic with auto-removal working is
  impossible in some of the more complicated cases (deeper nesting,
  combinations of different quoting styles).


Ok, glad to have that removed from my list.

Bye
 Sven

diff -u -r oldsrc/Zle/comp.h Src/Zle/comp.h
--- oldsrc/Zle/comp.h	Mon Nov  8 09:28:19 1999
+++ Src/Zle/comp.h	Mon Nov  8 10:38:06 1999
@@ -95,7 +95,7 @@
     char *pre;			/* prefix string from -P */
     char *suf;			/* suffix string from -S */
     char *disp;			/* string to display (compadd -d) */
-    char autoq;			/* closing quote to add automatically */
+    char *autoq;		/* closing quote to add automatically */
     int flags;			/* see CMF_* below */
     int *brpl;			/* places where to put the brace prefixes */
     int *brsl;			/* ...and the suffixes */
@@ -115,6 +115,7 @@
 #define CMF_NOLIST    32	/* should not be listed */
 #define CMF_DISPLINE  64	/* display strings one per line */
 #define CMF_HIDE     128	/* temporarily hide this one */
+#define CMF_NOSPACE  256	/* don't add a space */
 
 /* Stuff for completion matcher control. */
 
@@ -353,9 +354,11 @@
 #define CP_ANMATCHES   (1 << CPN_ANMATCHES)
 #define CPN_LISTLINES  26
 #define CP_LISTLINES   (1 << CPN_LISTLINES)
+#define CPN_QUOTES     27
+#define CP_QUOTES      (1 << CPN_QUOTES)
 
-#define CP_KEYPARAMS   27
-#define CP_ALLKEYS     ((unsigned int) 0x7ffffff)
+#define CP_KEYPARAMS   28
+#define CP_ALLKEYS     ((unsigned int) 0xfffffff)
 
 /* Hooks. */
 
diff -u -r oldsrc/Zle/compcore.c Src/Zle/compcore.c
--- oldsrc/Zle/compcore.c	Mon Nov  8 09:28:19 1999
+++ Src/Zle/compcore.c	Mon Nov  8 10:38:07 1999
@@ -101,8 +101,7 @@
 
 /* We store the following prefixes/suffixes:                               *
  * ipre,ripre  -- the ignored prefix (quoted and unquoted)                 *
- * isuf        -- the ignored suffix                                       *
- * autoq       -- quotes to automatically insert                           */
+ * isuf        -- the ignored suffix                                       */
 
 /**/
 char *ipre, *ripre, *isuf;
@@ -246,10 +245,6 @@
 /**/
 int lastend;
 
-/* Convenience macro for calling bslashquote() (formerly quotename()). */
-
-#define quotename(s, e) bslashquote(s, e, instring)
-
 #define inststr(X) inststrlen((X),1,-1)
 
 /* Main completion entry point, called from zle. */
@@ -270,6 +265,13 @@
 	ainfo = fainfo = NULL;
 	matchers = newlinklist();
 
+	zsfree(compqstack);
+	compqstack = ztrdup("\\");
+	if (instring == 2)
+	    compqstack[0] = '"';
+	else if (instring)
+	    compqstack[0] = '\'';
+
 	hasunqu = 0;
 	useline = (lst != COMP_LIST_COMPLETE);
 	useexact = isset(RECEXACT);
@@ -603,7 +605,7 @@
 	zsfree(compprefix);
 	zsfree(compsuffix);
 	if (unset(COMPLETEINWORD)) {
-	    tmp = quotename(s, NULL);
+	    tmp = multiquote(s, 0);
 	    untokenize(tmp);
 	    compprefix = ztrdup(tmp);
 	    compsuffix = ztrdup("");
@@ -614,11 +616,11 @@
 
 	    sav = *ss;
 	    *ss = '\0';
-	    tmp = quotename(s, NULL);
+	    tmp = multiquote(s, 0);
 	    untokenize(tmp);
 	    compprefix = ztrdup(tmp);
 	    *ss = sav;
-	    ss = quotename(ss, NULL);
+	    ss = multiquote(ss, 0);
 	    untokenize(ss);
 	    compsuffix = ztrdup(ss);
 	}
@@ -917,6 +919,40 @@
     return 1;
 }
 
+/**/
+char *
+multiquote(char *s, int ign)
+{
+    char *os = s, *p = compqstack;
+
+    if (p && *p && (ign < 1 || p[ign])) {
+	if (ign > 0)
+	    p += ign;
+	while (*p) {
+	    if (ign >= 0 || p[1])
+		s = bslashquote(s, NULL,
+				(*p == '\'' ? 1 : (*p == '"' ? 2 : 0)));
+	    p++;
+	}
+    }
+    return (s == os ? dupstring(s) : s);
+}
+
+/**/
+char *
+tildequote(char *s, int ign)
+{
+    int tilde;
+
+    if ((tilde = (*s == '~')))
+	*s = 'x';
+    s = multiquote(s, ign);
+    if (tilde)
+	*s = '~';
+
+    return s;
+}
+
 /* Check if we have to complete a parameter name. */
 
 /**/
@@ -1121,20 +1157,18 @@
     return str;
 }
 
-/* This is for compset -q. */
-
 /**/
 int
 set_comp_sep(void)
 {
     int lip, lp;
-    char *s = comp_str(&lip, &lp, 0);
+    char *s = comp_str(&lip, &lp, 1);
     LinkList foo = newlinklist();
     LinkNode n;
     int owe = we, owb = wb, ocs = cs, swb, swe, scs, soffs, ne = noerrs;
-    int tl, got = 0, i = 0, cur = -1, oll = ll, sl;
+    int tl, got = 0, i = 0, cur = -1, oll = ll, sl, remq;
     int ois = instring, oib = inbackt, noffs = lip + lp;
-    char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs;
+    char *tmp, *p, *ns, *ol = (char *) line, sav, *qp, *qs, *ts, qc = '\0';
 
     if (compisuffix)
 	s = dyncat(s, compisuffix);
@@ -1154,7 +1188,8 @@
     memcpy(tmp + 1, s, noffs);
     tmp[(scs = cs = 1 + noffs)] = 'x';
     strcpy(tmp + 2 + noffs, s + noffs);
-    tmp = rembslash(tmp);
+    if ((remq = (*compqstack == '\\')))
+	tmp = rembslash(tmp);
     inpush(dupstrspace(tmp), 0, NULL);
     line = (unsigned char *) tmp;
     ll = tl - 1;
@@ -1217,21 +1252,31 @@
 		*p = '\'';
     }
     offs = owb;
+
+    untokenize(ts = dupstring(ns));
+
     if (*ns == Snull || *ns == Dnull) {
 	instring = (*ns == Snull ? 1 : 2);
 	inbackt = 0;
 	swb++;
 	if (ns[strlen(ns) - 1] == *ns && ns[1])
 	    swe--;
-	autoq = (*ns == Snull ? '\'' : '"');
+	zsfree(autoq);
+	autoq = ztrdup(compqstack[1] ? "" :
+		       multiquote(*ns == Snull ? "'" : "\"", 1));
+	qc = (*ns == Snull ? '\'' : '"');
+	ts++;
     } else {
 	instring = 0;
-	autoq = '\0';
+	zsfree(autoq);
+	autoq = NULL;
     }
     for (p = ns, i = swb; *p; p++, i++) {
 	if (INULL(*p)) {
-	    if (i < scs)
-		soffs--;
+	    if (i < scs) {
+		if (remq && *p == Bnull && p[1])
+		    swb -= 2;
+	    }
 	    if (p[1] || *p != Bnull) {
 		if (*p == Bnull) {
 		    if (scs == i + 1)
@@ -1247,17 +1292,28 @@
 	    chuck(p--);
 	}
     }
+    ns = ts;
+
+    if (instring && strchr(compqstack, '\\')) {
+	int rl = strlen(ns), ql = strlen(multiquote(ns, !!compqstack[1]));
+
+	if (ql > rl)
+	    swb -= ql - rl;
+    }
     sav = s[(i = swb - 1)];
     s[i] = '\0';
-    qp = tricat(qipre, rembslash(s), "");
+    qp = rembslash(s);
     s[i] = sav;
     if (swe < swb)
 	swe = swb;
     swe--;
     sl = strlen(s);
-    if (swe > sl)
-	swe = sl, ns[swe - swb + 1] = '\0';
-    qs = tricat(rembslash(s + swe), qisuf, "");
+    if (swe > sl) {
+	swe = sl;
+	if (strlen(ns) > swe - swb + 1)
+	    ns[swe - swb + 1] = '\0';
+    }
+    qs = rembslash(s + swe);
     sl = strlen(ns);
     if (soffs > sl)
 	soffs = sl;
@@ -1265,6 +1321,11 @@
     {
 	int set = CP_QUOTE | CP_QUOTING, unset = 0;
 
+	p = tricat((instring ? (instring == 1 ? "'" : "\"") : "\\"),
+		   compqstack, "");
+	zsfree(compqstack);
+	compqstack = p;
+
 	zsfree(compquote);
 	zsfree(compquoting);
 	if (instring == 2) {
@@ -1282,11 +1343,11 @@
 	compquoting = ztrdup(compquoting);
 	comp_setunset(0, 0, set, unset);
 
+	zsfree(compprefix);
+	zsfree(compsuffix);
 	if (unset(COMPLETEINWORD)) {
 	    untokenize(ns);
-	    zsfree(compprefix);
 	    compprefix = ztrdup(ns);
-	    zsfree(compsuffix);
 	    compsuffix = ztrdup("");
 	} else {
 	    char *ss, sav;
@@ -1305,17 +1366,12 @@
 	compiprefix = ztrdup("");
 	zsfree(compisuffix);
 	compisuffix = ztrdup("");
+	tmp = tricat(compqiprefix, "", multiquote(qp, 1));
 	zsfree(compqiprefix);
+	compqiprefix = tmp;
+	tmp = tricat(multiquote(qs, 1), "", compqisuffix);
 	zsfree(compqisuffix);
-	if (ois) {
-	    compqiprefix = qp;
-	    compqisuffix = qs;
-	} else {
-	    compqiprefix = ztrdup(quotename(qp, NULL));
-	    zsfree(qp);
-	    compqisuffix = ztrdup(quotename(qs, NULL));
-	    zsfree(qs);
-	}
+	compqisuffix = tmp;
 	freearray(compwords);
 	i = countlinknodes(foo);
 	compwords = (char **) zalloc((i + 1) * sizeof(char *));
@@ -1326,7 +1382,6 @@
 	compcurrent = cur + 1;
 	compwords[i] = NULL;
     }
-    autoq = oaq;
     instring = ois;
     inbackt = oib;
 
@@ -1422,7 +1477,7 @@
 addmatches(Cadata dat, char **argv)
 {
     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;
     int lpl, lsl, pl, sl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0;
     int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern;
@@ -1446,15 +1501,19 @@
 	if (qc == '`') {
 	    instring = 0;
 	    inbackt = 0;
-	    autoq = '\0';
+	    autoq = "";
 	} else {
+	    char buf[2];
+
 	    instring = (qc == '\'' ? 1 : 2);
 	    inbackt = 0;
-	    autoq = qc;
+	    buf[0] = qc;
+	    buf[1] = '\0';
+	    autoq = multiquote(buf, 1);
 	}
     } else {
 	instring = inbackt = 0;
-	autoq = '\0';
+	autoq = NULL;
     }
     qipre = ztrdup(compqiprefix ? compqiprefix : "");
     qisuf = ztrdup(compqisuffix ? compqisuffix : "");
@@ -1536,21 +1595,16 @@
 	    else if (lisuf)
 		dat->isuf = lisuf;
 	    if (dat->ppre) {
-		if (!(dat->aflags & CAF_QUOTE)) {
-		    dat->ppre = quotename(dat->ppre, NULL);
-		    if ((dat->flags & CMF_FILE) &&
-			dat->ppre[0] == '\\' && dat->ppre[1] == '~')
-			chuck(dat->ppre);
-		} else
-		    dat->ppre = dupstring(dat->ppre);
+		dat->ppre = ((dat->flags & CMF_FILE) ?
+			     tildequote(dat->ppre,
+					!!(dat->aflags & CAF_QUOTE)) :
+			     multiquote(dat->ppre,
+					!!(dat->aflags & CAF_QUOTE)));
 		lpl = strlen(dat->ppre);
 	    } else
 		lpl = 0;
 	    if (dat->psuf) {
-		if (!(dat->aflags & CAF_QUOTE))
-		    dat->psuf = quotename(dat->psuf, NULL);
-		else
-		    dat->psuf = dupstring(dat->psuf);
+		dat->psuf = multiquote(dat->psuf, !!(dat->aflags & CAF_QUOTE));
 		lsl = strlen(dat->psuf);
 	    } else
 		lsl = 0;
@@ -1653,6 +1707,11 @@
 		    dat->rems = NULL;
 		} else if (dat->rems)
 		    dat->rems = dupstring(dat->rems);
+
+		lpre = ((!(dat->aflags & CAF_QUOTE) &&
+			 (!dat->ppre && (dat->flags & CMF_FILE))) ?
+			tildequote(lpre, 1) : multiquote(lpre, 1));
+		lsuf = multiquote(lsuf, 1);
 	    }
 	    /* Walk through the matches given. */
 	    obpl = bpl;
@@ -1687,12 +1746,12 @@
 		    if (dat->aflags & CAF_QUOTE)
 			ms = dupstring(s);
 		    else
-			sl = strlen(ms = quotename(s, NULL));
+			sl = strlen(ms = multiquote(s, 0));
 		    lc = bld_parts(ms, sl, -1, NULL);
 		    isexact = 0;
 		} else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc,
 					     (!(dat->aflags & CAF_QUOTE) ?
-					      ((dat->ppre && dat->ppre) ||
+					      (dat->ppre ||
 					       !(dat->flags & CMF_FILE) ? 1 : 2) : 0),
 					     &bpl, bcp, &bsl, bcs,
 					     &isexact))) {
@@ -1994,6 +2053,9 @@
     cm->pre = pre;
     cm->suf = suf;
     cm->flags = flags;
+    if (*compqstack == '\\' ||
+	(autoq && *compqstack && compqstack[1] == '\\'))
+	cm->flags |= CMF_NOSPACE;
     if (nbrbeg) {
 	int *p;
 	Brinfo bp;
@@ -2016,7 +2078,7 @@
 	cm->brsl = NULL;
     cm->qipl = qipl;
     cm->qisl = qisl;
-    cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0'));
+    cm->autoq = dupstring(autoq ? autoq : (inbackt ? "`" : NULL));
     cm->rems = cm->remf = cm->disp = NULL;
 
     if ((lastprebr || lastpostbr) && !hasbrpsfx(cm, lastprebr, lastpostbr))
@@ -2348,7 +2410,7 @@
 	r->brsl = NULL;
     r->rems = ztrdup(m->rems);
     r->remf = ztrdup(m->remf);
-    r->autoq = m->autoq;
+    r->autoq = ztrdup(m->autoq);
     r->qipl = m->qipl;
     r->qisl = m->qisl;
     r->disp = dupstring(m->disp);
@@ -2489,6 +2551,7 @@
     zsfree(m->rems);
     zsfree(m->remf);
     zsfree(m->disp);
+    zsfree(m->autoq);
     zfree(m->brpl, nbeg * sizeof(int));
     zfree(m->brsl, nend * sizeof(int));
 
diff -u -r oldsrc/Zle/compctl.c Src/Zle/compctl.c
--- oldsrc/Zle/compctl.c	Mon Nov  8 09:28:19 1999
+++ Src/Zle/compctl.c	Mon Nov  8 10:38:07 1999
@@ -1811,10 +1811,12 @@
 		    isalt = 1;
 	}
 	ms = ((addwhat == CC_FILES || addwhat == -6 ||
-	       addwhat == -5 || addwhat == -8) ? 
-	      comp_match(qfpre, qfsuf, s, filecomp, &lc, (ppre && *ppre ? 1 : 2),
+	       addwhat == -5 || addwhat == -8) ?
+	      comp_match(tildequote(qfpre, 1), multiquote(qfsuf, 1),
+			 s, filecomp, &lc, (ppre && *ppre ? 1 : 2),
 			 &bpl, ppl ,&bsl, psl, &isexact) :
-	      comp_match(fpre, fsuf, s, filecomp, &lc, 0,
+	      comp_match(multiquote(fpre, 1), multiquote(fsuf, 1),
+			 s, filecomp, &lc, 0,
 			 &bpl, ppl, &bsl, psl, &isexact));
 	if (!ms)
 	    return;
@@ -1855,6 +1857,8 @@
 	    p1 = qlpre; s1 = qlsuf;
 	    p2 = lpre;  s2 = lsuf;
 	}
+	p1 = multiquote(p1, 1); s1 = multiquote(s1, 1);
+	p2 = multiquote(p2, 1); s2 = multiquote(s2, 1);
 	bpt = bpl;
 	bst = bsl;
 
@@ -2128,21 +2132,24 @@
 	    char *str = comp_str(&lip, &lp, 0), *t;
 	    char *os = cmdstr, **ow = clwords, **p, **q, qc;
 	    int on = clwnum, op = clwpos, ois =  instring, oib = inbackt;
-	    char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, oaq = autoq;
+	    char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, *oaq = autoq;
+	    char buf[2];
 
 	    if (compquote && (qc = *compquote)) {
 		if (qc == '`') {
 		    instring = 0;
 		    inbackt = 0;
-		    autoq = '\0';
+		    autoq = "";
 		} else {
+		    buf[0] = qc;
+		    buf[1] = '\0';
 		    instring = (qc == '\'' ? 1 : 2);
 		    inbackt = 0;
-		    autoq = qc;
+		    autoq = buf;
 		}
 	    } else {
 		instring = inbackt = 0;
-		autoq = '\0';
+		autoq = "";
 	    }
 	    qipre = ztrdup(compqiprefix ? compqiprefix : "");
 	    qisuf = ztrdup(compqisuffix ? compqisuffix : "");
@@ -2593,9 +2600,10 @@
     LinkList foo = newlinklist();
     LinkNode n;
     int owe = we, owb = wb, ocs = cs, swb, swe, scs, soffs, ne = noerrs;
-    int sl = strlen(ss), tl, got = 0, i = 0, cur = -1, oll = ll;
+    int sl = strlen(ss), tl, got = 0, i = 0, cur = -1, oll = ll, remq;
     int ois = instring, oib = inbackt;
-    char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs;
+    char *tmp, *p, *ns, *ol = (char *) line, sav, *oaq = autoq, *qp, *qs;
+    char *ts, qc = '\0';
 
     swb = swe = soffs = 0;
     ns = NULL;
@@ -2612,6 +2620,8 @@
     memcpy(tmp + sl + 1, s, noffs);
     tmp[(scs = cs = sl + 1 + noffs)] = 'x';
     strcpy(tmp + sl + 2 + noffs, s + noffs);
+    if ((remq = (*compqstack == '\\')))
+	tmp = rembslash(tmp);
     inpush(dupstrspace(tmp), 0, NULL);
     line = (unsigned char *) tmp;
     ll = tl - 1;
@@ -2674,21 +2684,29 @@
 		*p = '\'';
     }
     offs = owb;
+
+    untokenize(ts = dupstring(ns));
+
     if (*ns == Snull || *ns == Dnull) {
 	instring = (*ns == Snull ? 1 : 2);
 	inbackt = 0;
 	swb++;
 	if (ns[strlen(ns) - 1] == *ns && ns[1])
 	    swe--;
-	autoq = (*ns == Snull ? '\'' : '"');
+	autoq = compqstack[1] ? "" : multiquote(*ns == Snull ? "'" : "\"", 1);
+	qc = (*ns == Snull ? '\'' : '"');
+	ts++;
     } else {
 	instring = 0;
-	autoq = '\0';
+	autoq = "";
     }
     for (p = ns, i = swb; *p; p++, i++) {
 	if (INULL(*p)) {
-	    if (i < scs)
+	    if (i < scs) {
 		soffs--;
+		if (remq && *p == Bnull && p[1])
+		    swb -= 2;
+	    }
 	    if (p[1] || *p != Bnull) {
 		if (*p == Bnull) {
 		    if (scs == i + 1)
@@ -2704,27 +2722,42 @@
 	    chuck(p--);
 	}
     }
+    ns = ts;
+
+    if (instring && strchr(compqstack, '\\')) {
+	int rl = strlen(ns), ql = strlen(multiquote(ns, !!compqstack[1]));
+
+	if (ql > rl)
+	    swb -= ql - rl;
+    }
     sav = s[(i = swb - sl - 1)];
     s[i] = '\0';
-    qp = tricat(qipre, s, "");
+    qp = tricat(qipre, multiquote(s, 0), "");
     s[i] = sav;
     if (swe < swb)
 	swe = swb;
     swe -= sl + 1;
     sl = strlen(s);
-    if (swe > sl)
-	swe = sl, ns[swe - swb + 1] = '\0';
-    qs = tricat(s + swe, qisuf, "");
+    if (swe > sl) {
+	swe = sl;
+	if (strlen(ns) > swe - swb + 1)
+	    ns[swe - swb + 1] = '\0';
+    }
+    qs = tricat(multiquote(s + swe, 0), qisuf, "");
     sl = strlen(ns);
     if (soffs > sl)
 	soffs = sl;
 
     {
 	char **ow = clwords, *os = cmdstr, *oqp = qipre, *oqs = qisuf;
+	char *oqst = compqstack;
 	int olws = clwsize, olwn = clwnum, olwp = clwpos;
 	int obr = brange, oer = erange, oof = offs;
 	unsigned long occ = ccont;
 
+	compqstack = tricat((instring ? (instring == 1 ? "'" : "\"") : "\\"),
+			    compqstack, "");
+
 	clwsize = clwnum = countlinknodes(foo);
 	clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
 	for (n = firstnode(foo), i = 0; n; incnode(n), i++) {
@@ -2756,6 +2789,8 @@
 	qipre = oqp;
 	zsfree(qisuf);
 	qisuf = oqs;
+	zsfree(compqstack);
+	compqstack = oqst;
     }
     autoq = oaq;
     instring = ois;
diff -u -r oldsrc/Zle/complete.c Src/Zle/complete.c
--- oldsrc/Zle/complete.c	Mon Nov  8 09:28:19 1999
+++ Src/Zle/complete.c	Mon Nov  8 10:38:08 1999
@@ -61,6 +61,7 @@
      *compredirect,
      *compquote,
      *compquoting,
+     *compqstack,
      *comprestore,
      *complist,
      *compforcelist,
@@ -962,6 +963,7 @@
     { "vared", PM_SCALAR, VAL(compvared), NULL, NULL },
     { "alternate_nmatches", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_anmatches) },
     { "list_lines", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_listlines) },
+    { "all_quotes", PM_SCALAR | PM_READONLY, VAL(compqstack), NULL, NULL },
     { NULL, 0, NULL, NULL, NULL }
 };
 
@@ -1169,7 +1171,7 @@
 	return 1;
     else {
 	char *orest, *opre, *osuf, *oipre, *oisuf, **owords;
-	char *oqipre, *oqisuf, *oq, *oqi;
+	char *oqipre, *oqisuf, *oq, *oqi, *oqs, *oaq;
 	zlong ocur;
 	unsigned int runset = 0, kunset = 0, m, sm;
 	Param *pp;
@@ -1193,6 +1195,8 @@
 	oqisuf = dupstring(compqisuffix);
 	oq = dupstring(compquote);
 	oqi = dupstring(compquoting);
+	oqs = dupstring(compqstack);
+	oaq = dupstring(autoq);
 
 	HEAPALLOC {
 	    owords = arrdup(compwords);
@@ -1218,6 +1222,10 @@
 	    compquote = ztrdup(oq);
 	    zsfree(compquoting);
 	    compquoting = ztrdup(oqi);
+	    zsfree(compqstack);
+	    compqstack = ztrdup(oqs);
+	    zsfree(autoq);
+	    autoq = ztrdup(oaq);
 	    freearray(compwords);
 	    PERMALLOC {
 		compwords = arrdup(owords);
@@ -1354,7 +1362,7 @@
 	compquoting = comprestore = complist = compinsert =
 	compexact = compexactstr = comppatmatch = comppatinsert =
 	compforcelist = complastprompt = comptoend = 
-	compoldlist = compoldins = compvared = NULL;
+	compoldlist = compoldins = compvared = compqstack = NULL;
 
     hascompmod = 1;
 
@@ -1418,6 +1426,7 @@
     zsfree(compparameter);
     zsfree(compredirect);
     zsfree(compquote);
+    zsfree(compqstack);
     zsfree(compquoting);
     zsfree(comprestore);
     zsfree(complist);
diff -u -r oldsrc/Zle/compmatch.c Src/Zle/compmatch.c
--- oldsrc/Zle/compmatch.c	Mon Nov  8 09:28:20 1999
+++ Src/Zle/compmatch.c	Mon Nov  8 10:38:08 1999
@@ -33,10 +33,6 @@
 #undef GLOBAL_PROTOTYPES
 #include "compmatch.pro"
 
-/* Convenience macro for calling bslashquote() (formerly quotename()). */
-
-#define quotename(s, e) bslashquote(s, e, instring)
-
 /* This compares two cpattern lists and returns non-zero if they are
  * equal. */
 
@@ -853,9 +849,8 @@
 	if (!pattry(cp, r))
 	    return NULL;
     
-	r = (qu ? quotename(r, NULL) : dupstring(r));
-	if (qu == 2 && r[0] == '\\' && r[1] == '~')
-	    chuck(r);
+	r = (qu == 2 ? tildequote(r, 0) : multiquote(r, !qu));
+
 	/* We still break it into parts here, trying to build a sensible
 	 * cline list for these matches, too. */
 	w = dupstring(w);
@@ -866,10 +861,7 @@
 	Cline pli, plil;
 	int mpl, rpl, wl;
 
-	w = (qu ? quotename(w, NULL) : dupstring(w));
-	if (qu == 2 && w[0] == '\\' && w[1] == '~')
-	    chuck(w);
-
+	w = (qu == 2 ? tildequote(w, 0) : multiquote(w, !qu));
 	wl = strlen(w);
 
 	/* Always try to match the prefix. */
diff -u -r oldsrc/Zle/compresult.c Src/Zle/compresult.c
--- oldsrc/Zle/compresult.c	Mon Nov  8 09:28:20 1999
+++ Src/Zle/compresult.c	Mon Nov  8 10:38:08 1999
@@ -33,11 +33,6 @@
 #undef GLOBAL_PROTOTYPES
 #include "compresult.pro"
 
-/* Convenience macro for calling bslashquote() (formerly quotename()). *
- * This uses the instring variable above.                              */
-
-#define quotename(s, e) bslashquote(s, e, instring)
-
 #define inststr(X) inststrlen((X),1,-1)
 
 /* This cuts the cline list before the stuff that isn't worth
@@ -857,11 +852,13 @@
 	/* If we didn't add a suffix, add a space, unless we are *
 	 * doing menu completion or we are completing files and  *
 	 * the string doesn't name an existing file.             */
-	if (m->autoq && (!m->isuf || m->isuf[0] != m->autoq)) {
-	    inststrlen(&(m->autoq), 1, 1);
-	    minfo.insc++;
+	if (m->autoq && (!m->isuf || !strpfx(m->autoq, m->isuf))) {
+	    int al = strlen(m->autoq);
+	    inststrlen(m->autoq, 1, al);
+	    minfo.insc += al;
 	}
-	if (!menucmp && (usemenu != 3 || insspace)) {
+	if (!menucmp && !(m->flags & CMF_NOSPACE) &&
+	    (usemenu != 3 || insspace)) {
 	    inststrlen(" ", 1, 1);
 	    minfo.insc++;
 	    if (minfo.we)
diff -u -r oldsrc/Zle/computil.c Src/Zle/computil.c
--- oldsrc/Zle/computil.c	Mon Nov  8 09:28:20 1999
+++ Src/Zle/computil.c	Mon Nov  8 10:38:09 1999
@@ -1887,11 +1887,62 @@
 }
 
 
+static int
+bin_compquote(char *nam, char **args, char *ops, int func)
+{
+    char *name;
+    Value v;
+
+    if (!compqstack || !*compqstack)
+	return 0;
+
+    while ((name = *args++)) {
+	name = dupstring(name);
+	if ((v = getvalue(&name, 0))) {
+	    switch (PM_TYPE(v->pm->flags)) {
+	    case PM_SCALAR:
+		{
+		    char *val = getstrvalue(v);
+
+		    val = bslashquote(val, NULL,
+				      (*compqstack == '\'' ? 1 :
+				       (*compqstack == '"' ? 2 : 0)));
+
+		    setstrvalue(v, ztrdup(val));
+		}
+		break;
+	    case PM_ARRAY:
+		{
+		    char **val = v->pm->gets.afn(v->pm);
+		    char **new = (char **) zalloc((arrlen(val) + 1) *
+						  sizeof(char *));
+		    char **p = new;
+
+		    for (; *val; val++, p++)
+			*p = ztrdup(bslashquote(*val, NULL,
+						(*compqstack == '\'' ? 1 :
+						 (*compqstack == '"' ? 2 :
+						  0))));
+		    *p = NULL;
+
+		    setarrvalue(v, new);
+		}
+		break;
+	    default:
+		zwarnnam(nam, "invalid parameter type: %s", args[-1], 0);
+	    }
+	} else
+	    zwarnnam(nam, "unknown parameter: %s", args[-1], 0);
+    }
+    return 0;
+}
+
 static struct builtin bintab[] = {
     BUILTIN("compdisplay", 0, bin_compdisplay, 2, -1, 0, NULL, NULL),
     BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
     BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL),
     BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL),
+    BUILTIN("compquote", 0, bin_compquote, 1, -1, 0, NULL, NULL),
 };
 
 
diff -u -r oldsrc/Zle/computil.mdd Src/Zle/computil.mdd
--- oldsrc/Zle/computil.mdd	Mon Nov  8 09:28:20 1999
+++ Src/Zle/computil.mdd	Mon Nov  8 10:38:09 1999
@@ -2,4 +2,4 @@
 
 objects="computil.o"
 
-autobins="compdisplay compdescribe comparguments compvalues"
+autobins="compdisplay compdescribe comparguments compvalues compquote"
diff -u -r oldsrc/Zle/zle_tricky.c Src/Zle/zle_tricky.c
--- oldsrc/Zle/zle_tricky.c	Mon Nov  8 09:28:21 1999
+++ Src/Zle/zle_tricky.c	Mon Nov  8 11:00:53 1999
@@ -112,7 +112,7 @@
  * closing quote. */
 
 /**/
-char *qipre, *qisuf, autoq;
+char *qipre, *qisuf, *autoq;
 
 /* This contains the name of the function to call if this is for a new  *
  * style completion. */
@@ -547,7 +547,8 @@
     qipre = ztrdup("");
     zsfree(qisuf);
     qisuf = ztrdup("");
-    autoq = '\0';
+    zsfree(autoq);
+    autoq = NULL;
     /* Get the word to complete. */
     noerrs = 1;
     s = get_comp_string();
@@ -882,6 +883,20 @@
     return ret;
 }
 
+/* This is a bit like has_token(), but ignores nulls. */
+
+static int
+has_real_token(const char *s)
+{
+    while (*s) {
+	if (itok(*s) && !INULL(*s))
+	    return 1;
+	s++;
+    }
+    return 0;
+}
+
+
 /* Lasciate ogni speranza.                                                  *
  * This function is a nightmare.  It works, but I'm sure that nobody really *
  * understands why.  The problem is: to make it cleaner we would need       *
@@ -1264,7 +1279,7 @@
 		else if (*p == Snull)
 		    *p = '\'';
 	}
-	if ((*s == Snull || *s == Dnull) && !has_token(s + 1)) {
+	if ((*s == Snull || *s == Dnull) && !has_real_token(s + 1)) {
 	    char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, "");
 	    int sl = strlen(s);
 
@@ -1276,7 +1291,7 @@
 		zsfree(qisuf);
 		qisuf = n;
 	    }
-	    autoq = *q;
+	    autoq = ztrdup(q);
 	}
 	/* While building the quoted form, we also clean up the command line. */
 	for (p = s, tt = qword, i = wb; *p; p++, tt++, i++)
diff -u -r oldsrc/params.c Src/params.c
--- oldsrc/params.c	Mon Nov  8 09:27:58 1999
+++ Src/params.c	Mon Nov  8 10:38:09 1999
@@ -1417,7 +1417,7 @@
 }
 
 /**/
-static void
+void
 setstrvalue(Value v, char *val)
 {
     char buf[(sizeof(zlong) * 8) + 4];
@@ -1515,7 +1515,7 @@
 }
 
 /**/
-static void
+void
 setnumvalue(Value v, mnumber val)
 {
     char buf[DIGBUFSIZE], *p;
@@ -1552,7 +1552,7 @@
 }
 
 /**/
-static void
+void
 setarrvalue(Value v, char **val)
 {
     if (v->pm->flags & PM_READONLY) {
diff -u olddoc/Zsh/compwid.yo Doc/Zsh/compwid.yo
--- olddoc/Zsh/compwid.yo	Mon Nov  8 09:28:46 1999
+++ Doc/Zsh/compwid.yo	Mon Nov  8 10:38:10 1999
@@ -184,6 +184,17 @@
 (i.e. either a single quote, a double quote, or a backtick).  Otherwise it
 is unset.
 )
+item(tt(all_quotes))(
+The tt(-q) option of the tt(compset) builtin command (see below)
+allows breaking a quoted string into separate words and completing one 
+of these words. This key allows to test which types of quoted strings
+are currently broken into parts this way. Its value contains one
+character for each quoting level. The characters are a single quote or 
+a double quote for strings quoted with these characters and a
+backslash for strings not starting with a quote character. The first
+character in the value always corresponds to the innermost quoting
+level.
+)
 item(tt(nmatches))(
 The number of matches generated and accepted by the completion code so
 far, excluding those matches that are only accepted by ignoring the
diff -u olddoc/Zsh/mod_computil.yo Doc/Zsh/mod_computil.yo
--- olddoc/Zsh/mod_computil.yo	Mon Nov  8 09:28:47 1999
+++ Doc/Zsh/mod_computil.yo	Mon Nov  8 10:38:10 1999
@@ -1,16 +1,29 @@
 texinode(The computil Module)(The deltochar Module)(The complist Module)(Zsh Modules)
 sect(The computil Module)
 cindex(completion, utility)
-The tt(computil) module adds four builtin commands that are used by
+The tt(computil) module adds several builtin commands that are used by
 some of the completion functions in the shell function based
 completions system (see
 ifzman(zmanref(zshcompsys))\
 ifnzman(noderef(Completion System))
-). Except for tt(compdisplay) these builtin commands are very
+). Except for tt(compquote) and tt(compdisplay) these builtin
+commands are very
 specialised and thus not very interesting when writing your own
 completion functions. In short, these builtin commands are:
 
 startitem()
+item(tt(compquote) var(names) ...)(
+There may be reasons to write completion functions that have to add
+the matches using the tt(-Q) option to tt(compadd) and do the quoting
+themselves. Instead of interpreting the first character of the
+tt(all_quotes) key of the tt(compstate) special association and using
+the tt(q) flag for parameter expansions, one can use this builtin
+command. The arguements are the names of scalar or array parameters
+and the values of these parameters are quoted as needed for the
+innermost quoting level.
+
+The return value is non-zero in case of an error and zero otherwise.
+)
 item(tt(compdisplay) var(name) var(string) var(defs) ...)(
 The var(defs) are strings which should be of the form
 `var(str)tt(:)var(descr)' (the intended use is that the var(descr)
diff -u -r oldcompletion/Core/_path_files Completion/Core/_path_files
--- oldcompletion/Core/_path_files	Mon Nov  8 09:27:47 1999
+++ Completion/Core/_path_files	Mon Nov  8 10:38:10 1999
@@ -233,7 +233,9 @@
  	if [[ "$tmp2[1]" = */* ]]; then
 	  tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
 	  if [[ "$tmp2[1]" = */* ]]; then
-	    exppaths=( "$exppaths[@]" ${^tmp2:h:q}/${tpre}${tsuf} )
+	    tmp2=( "${(@)tmp2:h}" )
+	    compquote tmp2
+	    exppaths=( "$exppaths[@]" ${^tmp2}/${tpre}${tsuf} )
           else
 	    exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
 	  fi
@@ -329,36 +331,39 @@
 	SUFFIX="${tsuf}"
       fi
 
+tmp4="$testpath"
+compquote tmp1 tmp4
+
       if [[ -n $menu || "$compconfig[path_expand]" != *suffix* ]]; then
         [[ -n "$compconfig[path_cursor]" ]] && compstate[to_end]=''
         if [[ "$tmp3" = */* ]]; then
-	  compadd -Qf -p "$linepath${testpath:q}" -s "/${tmp3#*/}" \
+	  compadd -Qf -p "$linepath$tmp4" -s "/${tmp3#*/}" \
 	          -W "$prepath$realpath$testpath" "$ignore[@]" \
 		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                   -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
-		  - "${(@)${(@)tmp1%%/*}:q}"
+		  - "${(@)tmp1%%/*}"
 	else
-	  compadd -Qf -p "$linepath${testpath:q}" \
+	  compadd -Qf -p "$linepath$tmp4" \
 	          -W "$prepath$realpath$testpath" "$ignore[@]" \
 		   "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                    -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
-		   - "${(@)tmp1:q}"
+		   - "$tmp1[@]"
 	fi
       else
         if [[ "$tmp3" = */* ]]; then
           for i in "$tmp1[@]"; do
-	    compadd -Qf -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
+	    compadd -Qf -p "$linepath$tmp4" -s "/${i#*/}" \
 		    -W "$prepath$realpath$testpath" "$ignore[@]" \
 		    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                     -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
-		    - "${${i%%/*}:q}"
+		    - "${i%%/*}"
 	  done
         else
-	  compadd -Qf -p "$linepath${testpath:q}" \
+	  compadd -Qf -p "$linepath$tmp4" \
 		  -W "$prepath$realpath$testpath" "$ignore[@]" \
 		  "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
                   -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
-		  - "${(@)tmp1:q}"
+		  - "$tmp1[@]"
         fi
       fi
       tmp4=-
@@ -397,11 +402,13 @@
   if [[ -z "$tmp4" ]]; then
     PREFIX="${opre}${osuf}"
     SUFFIX=""
-    compadd -Qf -p "$linepath${testpath:q}" \
+    tmp4="$testpath"
+    compquote tmp4 tmp1
+    compadd -Qf -p "$linepath$tmp4" \
 	    -W "$prepath$realpath$testpath" "$ignore[@]" \
 	    "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
             -M "r:|/=* r:|=* $match" "$group[@]" "$expl[@]" \
-	    - "${(@)tmp1:q}"
+	    - "$tmp1[@]"
   fi
 done
 

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author