1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-30 05:40:58 +01:00

12414: vared quotes separators when editing arrays

This commit is contained in:
Peter Stephenson 2000-07-27 17:48:47 +00:00
parent 31862868fa
commit 0aee5e1bb4
5 changed files with 92 additions and 13 deletions

View file

@ -1,3 +1,8 @@
2000-07-27 Peter Stephenson <pws@cambridgesiliconradio.com>
* 12414: Doc/Zsh/mod_zle.yo, Src/exec.c, Src/utils.c,
Src/Zle/zle_main.c: vared quotes separators when editing arrays.
2000-07-27 Sven Wischnowsky <wischnow@zsh.org>
* 12408: Test/55arguments.ztst: fix completion test (55*) because

View file

@ -161,6 +161,12 @@ an array parameter, or the tt(-A) flag to create an associative array.
If the type of an existing parameter does not match the type to be
created, the parameter is unset and recreated.
If an array or array slice is being edited, separator characters as defined
in tt($IFS) will be shown quoted with a backslash. Conversely, when the
edited text is split into an array, a backslash quotes an immediately
following separator character; no other special handling of backslashes, or
any handling of quotes, is performed.
Individual elements of existing array or associative array parameters
may be edited by using subscript syntax on var(name). New elements are
created automatically, even without tt(-c).

View file

@ -823,7 +823,46 @@ bin_vared(char *name, char **args, char *ops, int func)
zwarnnam(name, "no such variable: %s", args[0], 0);
return 1;
} else if (v) {
s = getstrvalue(v);
if (v->isarr) {
/* Array: check for separators and quote them. */
char **arr = getarrvalue(v), **aptr, **tmparr, **tptr;
tptr = tmparr = (char **)zhalloc(sizeof(char *)*(arrlen(arr)+1));
for (aptr = arr; *aptr; aptr++) {
int sepcount = 0;
/* See if this word contains a separator character */
for (t = *aptr; *t; t++) {
if (*t == Meta) {
if (isep(t[1] ^ 32))
sepcount++;
t++;
} else if (isep(*t))
sepcount++;
}
if (sepcount) {
/* Yes, so allocate enough space to quote it. */
char *newstr, *nptr;
newstr = zhalloc(strlen(*aptr)+sepcount+1);
/* Go through string quoting separators */
for (t = *aptr, nptr = newstr; *t; ) {
if (*t == Meta) {
if (isep(t[1] ^ 32))
*nptr++ = '\\';
*nptr++ = *t++;
} else if (isep(*t))
*nptr++ = '\\';
*nptr++ = *t++;
}
*nptr = '\0';
/* Stick this into the array of words to join up */
*tptr++ = newstr;
} else
*tptr++ = *aptr; /* No, keep original array element */
}
*tptr = NULL;
s = sepjoin(tmparr, NULL, 0);
} else {
s = ztrdup(getstrvalue(v));
}
pm = v->pm;
} else if (*s) {
zwarnnam(name, "invalid parameter name: %s", args[0], 0);
@ -842,7 +881,7 @@ bin_vared(char *name, char **args, char *ops, int func)
haso = 1;
}
/* edit the parameter value */
zpushnode(bufstack, ztrdup(s));
zpushnode(bufstack, s);
varedarg = *args;
ifl = isfirstln;
@ -881,7 +920,11 @@ bin_vared(char *name, char **args, char *ops, int func)
if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) {
char **a;
a = spacesplit(t, 1, 0);
/*
* Use spacesplit with fourth argument 1: identify quoted separators,
* unquote but don't split.
*/
a = spacesplit(t, 1, 0, 1);
if (PM_TYPE(pm->flags) == PM_ARRAY)
setaparam(args[0], a);
else

View file

@ -2744,7 +2744,7 @@ readoutput(int in, int qt)
}
addlinknode(ret, buf);
} else {
char **words = spacesplit(buf, 0, 1);
char **words = spacesplit(buf, 0, 1, 0);
while (*words) {
if (isset(GLOBSUBST))

View file

@ -1831,7 +1831,7 @@ skipwsep(char **s)
/**/
mod_export char **
spacesplit(char *s, int allownull, int heap)
spacesplit(char *s, int allownull, int heap, int quote)
{
char *t, **ret, **ptr;
int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
@ -1839,6 +1839,14 @@ spacesplit(char *s, int allownull, int heap)
ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zcalloc(l));
if (quote) {
/*
* we will be stripping quoted separators by hacking string,
* so make sure it's hackable.
*/
s = dupstring(s);
}
t = s;
skipwsep(&s);
if (*s && isep(*s == Meta ? s[1] ^ 32 : *s))
@ -1853,7 +1861,7 @@ spacesplit(char *s, int allownull, int heap)
skipwsep(&s);
}
t = s;
findsep(&s, NULL);
findsep(&s, NULL, quote);
if (s > t || allownull) {
*ptr = (heap ? (char *) hcalloc((s - t) + 1) :
(char *) zcalloc((s - t) + 1));
@ -1871,13 +1879,30 @@ spacesplit(char *s, int allownull, int heap)
/**/
static int
findsep(char **s, char *sep)
findsep(char **s, char *sep, int quote)
{
/*
* *s is the string we are looking along, which will be updated
* to the point we have got to.
*
* sep is a possibly multicharacter separator to look for. If NULL,
* use normal separator characters.
*
* quote is a flag that '\<sep>' should not be treated as a separator.
* in this case we need to be able to strip the backslash directly
* in the string, so the calling function must have sent us something
* modifiable. currently this only works for sep == NULL.
*/
int i;
char *t, *tt;
if (!sep) {
for (t = *s; *t; t++) {
if (quote && *t == '\\' &&
isep(t[1] == Meta ? (t[2] ^ 32) : t[1])) {
chuck(t);
continue;
}
if (*t == Meta) {
if (isep(t[1] ^ 32))
break;
@ -1928,7 +1953,7 @@ findword(char **s, char *sep)
if (sep) {
sl = strlen(sep);
r = *s;
while (! findsep(s, sep)) {
while (! findsep(s, sep, 0)) {
r = *s += sl;
}
return r;
@ -1942,7 +1967,7 @@ findword(char **s, char *sep)
break;
}
*s = t;
findsep(s, sep);
findsep(s, sep, 0);
return t;
}
@ -1955,7 +1980,7 @@ wordcount(char *s, char *sep, int mul)
if (sep) {
r = 1;
sl = strlen(sep);
for (; (c = findsep(&s, sep)) >= 0; s += sl)
for (; (c = findsep(&s, sep, 0)) >= 0; s += sl)
if ((c && *(s + sl)) || mul)
r++;
} else {
@ -1975,7 +2000,7 @@ wordcount(char *s, char *sep, int mul)
if (mul <= 0)
skipwsep(&s);
}
findsep(&s, NULL);
findsep(&s, NULL, 0);
t = s;
if (mul <= 0)
skipwsep(&s);
@ -2023,7 +2048,7 @@ sepsplit(char *s, char *sep, int allownull, int heap)
char *t, *tt, **r, **p;
if (!sep)
return spacesplit(s, allownull, heap);
return spacesplit(s, allownull, heap, 0);
sl = strlen(sep);
n = wordcount(s, sep, 1);
@ -2032,7 +2057,7 @@ sepsplit(char *s, char *sep, int allownull, int heap)
for (t = s; n--;) {
tt = t;
findsep(&t, sep);
findsep(&t, sep, 0);
*p = (heap ? (char *) hcalloc(t - tt + 1) :
(char *) zcalloc(t - tt + 1));
strncpy(*p, tt, t - tt);