Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: nested quotes
- X-seq: zsh-workers 8588
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: PATCH: nested quotes
- Date: Mon, 8 Nov 1999 11:20:31 +0100 (MET)
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
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