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:
parent
31862868fa
commit
0aee5e1bb4
5 changed files with 92 additions and 13 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
43
Src/utils.c
43
Src/utils.c
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue