mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-12-29 19:12:20 +01:00
28510: add (z+c+) and (z+C+) parameter flags
This commit is contained in:
parent
72d1045da5
commit
0a5702457b
9 changed files with 159 additions and 17 deletions
|
|
@ -1,3 +1,9 @@
|
|||
2010-12-12 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* 28510: Doc/Zsh/expn.yo, Src/hist.c, Src/lex.c, Src/subst.c,
|
||||
Src/Modules/parameter.c, Src/Zle/zle_hist.c, Src/Zle/zle_misc.c,
|
||||
Test/D04parameter.ztst: add (z+c+) and (z+C+) parameter flags.
|
||||
|
||||
2010-12-07 Peter Stephenson <pws@csr.com>
|
||||
|
||||
* unposted: remove users/15622 which causes problems
|
||||
|
|
@ -13930,5 +13936,5 @@
|
|||
|
||||
*****************************************************
|
||||
* This is used by the shell to define $ZSH_PATCHLEVEL
|
||||
* $Revision: 1.5146 $
|
||||
* $Revision: 1.5147 $
|
||||
*****************************************************
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,17 @@ errors are silently ignored.
|
|||
item(tt(z))(
|
||||
Split the result of the expansion into words using shell parsing to
|
||||
find the words, i.e. taking into account any quoting in the value.
|
||||
Comments are not treated specially but as ordinary strings, similar
|
||||
to interactive shells with the tt(INTERACTIVE_COMMENTS) option unset.
|
||||
|
||||
The flag can take option letters between a following pair of
|
||||
`tt(PLUS())' characters. tt(LPAR()z+PLUS()c+PLUS()RPAR()) causes
|
||||
comments to be parsed as a string and retained; any field in the
|
||||
resulting array beginning with an unquoted comment character is a
|
||||
comment. tt(LPAR()z+PLUS()C+PLUS()RPAR()) causes comments to be parsed
|
||||
and removed. The rule for comments is standard: anything between a word
|
||||
starting with the third charcter of tt($HISTCHARS), default tt(#), up to
|
||||
the next newline is a comment.
|
||||
|
||||
Note that this is done very late, as for the `tt((s))' flag. So to
|
||||
access single words in the result, one has to use nested expansions as
|
||||
|
|
|
|||
|
|
@ -1044,7 +1044,7 @@ histwgetfn(UNUSED(Param pm))
|
|||
int i = addhistnum(curhist, -1, HIST_FOREIGN), iw;
|
||||
Histent he = gethistent(i, GETHIST_UPWARD);
|
||||
|
||||
if ((ll = bufferwords(NULL, NULL, NULL)))
|
||||
if ((ll = bufferwords(NULL, NULL, NULL, 0)))
|
||||
for (n = firstnode(ll); n; incnode(n))
|
||||
pushnode(l, getdata(n));
|
||||
|
||||
|
|
|
|||
|
|
@ -677,7 +677,7 @@ insertlastword(char **args)
|
|||
* a deleted word, because that can only have come
|
||||
* from a non-empty line. I think.
|
||||
*/
|
||||
if (!(l = bufferwords(NULL, NULL, NULL))) {
|
||||
if (!(l = bufferwords(NULL, NULL, NULL, 0))) {
|
||||
unmetafy_line();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -843,7 +843,7 @@ copyprevshellword(UNUSED(char **args))
|
|||
if (zmult <= 0)
|
||||
return 1;
|
||||
|
||||
if ((l = bufferwords(NULL, NULL, &i))) {
|
||||
if ((l = bufferwords(NULL, NULL, &i, 0))) {
|
||||
i -= (zmult-1);
|
||||
if (i < 0)
|
||||
return 1;
|
||||
|
|
|
|||
30
Src/hist.c
30
Src/hist.c
|
|
@ -2345,7 +2345,7 @@ readhistfile(char *fn, int err, int readflags)
|
|||
/*
|
||||
* Attempt to do this using the lexer.
|
||||
*/
|
||||
LinkList wordlist = bufferwords(NULL, pt, NULL);
|
||||
LinkList wordlist = bufferwords(NULL, pt, NULL, 1);
|
||||
LinkNode wordnode;
|
||||
int nwords_max;
|
||||
nwords_max = 2 * countlinknodes(wordlist);
|
||||
|
|
@ -2885,11 +2885,27 @@ histfileIsLocked(void)
|
|||
* which may not even be valid at this point.
|
||||
*
|
||||
* However, I'm so confused it could simply be baking Bakewell tarts.
|
||||
*
|
||||
* list may be an existing linked list (off the heap), in which case
|
||||
* it will be appended to; otherwise it will be created.
|
||||
*
|
||||
* If buf is set we will take input from that string, else we will
|
||||
* attempt to use ZLE directly in a way they tell you not to do on all
|
||||
* programming courses.
|
||||
*
|
||||
* If index is non-NULL, and input is from a string in ZLE, *index
|
||||
* is set to the position of the end of the current editor word.
|
||||
*
|
||||
* comments is used if buf is non-NULL (i.e. this is not a string
|
||||
* from ZLE).
|
||||
* If it is 0, comments are not parsed; they are treated as ordinary words.
|
||||
* If it is 1, comments are treated as single strings, one per line.
|
||||
* If it is 2, comments are removed.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export LinkList
|
||||
bufferwords(LinkList list, char *buf, int *index)
|
||||
bufferwords(LinkList list, char *buf, int *index, int comments)
|
||||
{
|
||||
int num = 0, cur = -1, got = 0, ne = noerrs;
|
||||
int owb = wb, owe = we, oadx = addedx, ozp = zleparse, onc = nocomments;
|
||||
|
|
@ -2906,7 +2922,6 @@ bufferwords(LinkList list, char *buf, int *index)
|
|||
* string expression, we just turn the option off for this function.
|
||||
*/
|
||||
opts[RCQUOTES] = 0;
|
||||
zleparse = 1;
|
||||
addedx = 0;
|
||||
noerrs = 1;
|
||||
lexsave();
|
||||
|
|
@ -2928,11 +2943,18 @@ bufferwords(LinkList list, char *buf, int *index)
|
|||
inpush(p, 0, NULL);
|
||||
zlemetall = strlen(p) ;
|
||||
zlemetacs = zlemetall + 1;
|
||||
nocomments = 1;
|
||||
|
||||
/*
|
||||
* If comments is non-zero we are handling comments.
|
||||
* zleparse indicates the mode to the lexer.
|
||||
*/
|
||||
zleparse = 1 + comments;
|
||||
nocomments = !comments;
|
||||
} else {
|
||||
int ll, cs;
|
||||
char *linein;
|
||||
|
||||
zleparse = 1;
|
||||
linein = zleentry(ZLE_CMD_GET_LINE, &ll, &cs);
|
||||
zlemetall = ll + 1; /* length of line plus space added below */
|
||||
zlemetacs = cs;
|
||||
|
|
|
|||
53
Src/lex.c
53
Src/lex.c
|
|
@ -116,7 +116,22 @@ mod_export int wb, we;
|
|||
/**/
|
||||
mod_export int noaliases;
|
||||
|
||||
/* we are parsing a line sent to use by the editor */
|
||||
/*
|
||||
* we are parsing a line sent to use by the editor, or some other string
|
||||
* that's not part of standard command input (e.g. eval is part of
|
||||
* normal command input).
|
||||
*
|
||||
* zleparse = 1 is the normal case.
|
||||
* zleparse = 2 is used for word splitting; the difference is we
|
||||
* preserve comments.
|
||||
* zleparse = 3 is also for word splitting, here handling comments
|
||||
* but stripping them.
|
||||
*
|
||||
* Note that although it is passed into the lexer as an input, the
|
||||
* lexer can set it to zero after finding the word it's searching for.
|
||||
* This only happens if the line being parsed actually does come from
|
||||
* ZLE.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export int zleparse;
|
||||
|
|
@ -743,26 +758,50 @@ gettok(void)
|
|||
|
||||
/* chars in initial position in word */
|
||||
|
||||
/*
|
||||
* Handle comments. There are some special cases when this
|
||||
* is not normal command input: zleparse implies we are examining
|
||||
* a line lexically without it being used for normal command input.
|
||||
* If zleparse is 1 we treat comments as normal for interactive
|
||||
* mode.
|
||||
* If zleparse is 2 (which has actually got nothing to do with zle)
|
||||
* we always handle comments and retain them.
|
||||
* If zleparse is 3 we always handle comments and discard them.
|
||||
*/
|
||||
if (c == hashchar && !nocomments &&
|
||||
(isset(INTERACTIVECOMMENTS) ||
|
||||
(!zleparse && !expanding &&
|
||||
((zleparse != 1) && !expanding &&
|
||||
(!interact || unset(SHINSTDIN) || strin)))) {
|
||||
/* History is handled here to prevent extra *
|
||||
* newlines being inserted into the history. */
|
||||
|
||||
if (zleparse == 2) {
|
||||
len = 0;
|
||||
bptr = tokstr = (char *)hcalloc(bsiz = 32);
|
||||
add(c);
|
||||
}
|
||||
while ((c = ingetc()) != '\n' && !lexstop) {
|
||||
hwaddc(c);
|
||||
addtoline(c);
|
||||
if (zleparse == 2)
|
||||
add(c);
|
||||
}
|
||||
|
||||
if (errflag)
|
||||
peek = LEXERR;
|
||||
else {
|
||||
hwend();
|
||||
hwbegin(0);
|
||||
hwaddc('\n');
|
||||
addtoline('\n');
|
||||
peek = NEWLIN;
|
||||
if (zleparse == 2) {
|
||||
*bptr = '\0';
|
||||
if (!lexstop)
|
||||
hungetc(c);
|
||||
peek = STRING;
|
||||
} else {
|
||||
hwend();
|
||||
hwbegin(0);
|
||||
hwaddc('\n');
|
||||
addtoline('\n');
|
||||
peek = NEWLIN;
|
||||
}
|
||||
}
|
||||
return peek;
|
||||
}
|
||||
|
|
|
|||
29
Src/subst.c
29
Src/subst.c
|
|
@ -1556,6 +1556,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
* The (z) flag, nothing to do with SH_WORD_SPLIT which is tied
|
||||
* spbreak, see above; fairly straighforward in use but c.f.
|
||||
* the comment for mods.
|
||||
*
|
||||
* This ultimately becomes zleparse during lexical analysis, via
|
||||
* the comments argument to bufferwords(). It's got nothing
|
||||
* to do with zle.
|
||||
*/
|
||||
int shsplit = 0;
|
||||
/*
|
||||
|
|
@ -1934,6 +1938,27 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
|
||||
case 'z':
|
||||
shsplit = 1;
|
||||
if (s[1] == '+') {
|
||||
s += 2;
|
||||
while (*s && *s != '+' && *s != ')' && *s != Outpar) {
|
||||
switch (*s++) {
|
||||
case 'c':
|
||||
/* Parse and keep comments */
|
||||
shsplit = 2;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
/* Parse and remove comments */
|
||||
shsplit = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto flagerr;
|
||||
}
|
||||
}
|
||||
if (*s != '+')
|
||||
goto flagerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
|
|
@ -3207,10 +3232,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (isarr) {
|
||||
char **ap;
|
||||
for (ap = aval; *ap; ap++)
|
||||
list = bufferwords(list, *ap, NULL);
|
||||
list = bufferwords(list, *ap, NULL, shsplit-1);
|
||||
isarr = 0;
|
||||
} else
|
||||
list = bufferwords(NULL, val, NULL);
|
||||
list = bufferwords(NULL, val, NULL, shsplit-1);
|
||||
|
||||
if (!list || !firstnode(list))
|
||||
val = dupstring("");
|
||||
|
|
|
|||
|
|
@ -417,6 +417,45 @@
|
|||
>5:i++ :
|
||||
>6:)):
|
||||
|
||||
line=$'A line with # someone\'s comment\nanother line # (1 more\nanother one'
|
||||
print "*** Normal ***"
|
||||
print -l ${(z)line}
|
||||
print "*** Kept ***"
|
||||
print -l ${(z+c+)line}
|
||||
print "*** Removed ***"
|
||||
print -l ${(z+C+)line}
|
||||
0:Comments with (z)
|
||||
>*** Normal ***
|
||||
>A
|
||||
>line
|
||||
>with
|
||||
>#
|
||||
>someone's comment
|
||||
>another line # (1 more
|
||||
>another one
|
||||
>*** Kept ***
|
||||
>A
|
||||
>line
|
||||
>with
|
||||
># someone's comment
|
||||
>;
|
||||
>another
|
||||
>line
|
||||
># (1 more
|
||||
>;
|
||||
>another
|
||||
>one
|
||||
>*** Removed ***
|
||||
>A
|
||||
>line
|
||||
>with
|
||||
>;
|
||||
>another
|
||||
>line
|
||||
>;
|
||||
>another
|
||||
>one
|
||||
|
||||
psvar=(dog)
|
||||
setopt promptsubst
|
||||
foo='It shouldn'\''t $(happen) to a %1v.'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue