diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Doc/Zsh/expn.yo | 10 | ||||
-rw-r--r-- | Src/hist.c | 40 |
3 files changed, 48 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog index 3029a8824..cc42ba072 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-11-04 Peter Stephenson <pws@csr.com> + + * users/9618 modified as suggested in users/9621: Doc/Zsh/expn.yo, + Src/hist.c: extend history subsitution to allow trailing :G for + global. + 2005-11-02 Andrey Borzenkov <bor@zsh.org> * 21978: Src/Modules/stat.c: unmetafy file name before calling diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index c05796a94..b8aa1cfd8 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -117,6 +117,8 @@ repeats the last command, replacing the string var(foo) with var(bar). More precisely, the sequence `tt(^)var(foo)tt(^)var(bar)tt(^)' is synonymous with `tt(!!:s)tt(^)var(foo)tt(^)var(bar)tt(^)', hence other modifiers (see noderef(Modifiers)) may follow the final `tt(^)'. +In particular, `tt(^)var(foo)tt(^)var(bar)tt(:G)' performs a global +substitution. If the shell encounters the character sequence `tt(!")' in the input, the history mechanism is temporarily disabled until @@ -254,10 +256,14 @@ Convert the words to all uppercase. ) item(tt(s/)var(l)tt(/)var(r)[tt(/)])( Substitute var(r) for var(l) as described below. -Unless preceded immediately by a tt(g), with no colon between, -the substitution is done only for the +The substitution is done only for the first string that matches var(l). For arrays and for filename generation, this applies to each word of the expanded text. + +The forms `tt(gs/)var(l)tt(/)var(r)' and `tt(s/)var(l)tt(/)var(r)tt(/:G)' +perform global substitution, i.e. substitute every occurrence of var(r) +for var(l). Note that the tt(g) or tt(:G) must appear in exactly the +position shown. ) item(tt(&))( Repeat the previous tt(s) substitution. Like tt(s), may be preceded diff --git a/Src/hist.c b/Src/hist.c index 00773cd74..90e97313e 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -295,13 +295,24 @@ herrflush(void) hwaddc(ingetc()); } -/* extract :s/foo/bar/ delimiters and arguments */ +/* + * Extract :s/foo/bar/ delimiters and arguments + * + * The first character expected is the first delimiter. + * The arguments are stored in the hsubl and hsubr variables. + * + * subline is the part of the command line to be matched. + * + * If a ':' was found but was not followed by a 'G', + * *cflagp is set to 1 and the input is backed up to the + * character following the colon. + */ /**/ static int -getsubsargs(char *subline) +getsubsargs(char *subline, int *gbalp, int *cflagp) { - int del; + int del, follow; char *ptr1, *ptr2; del = ingetc(); @@ -315,6 +326,17 @@ getsubsargs(char *subline) } zsfree(hsubr); hsubr = ptr2; + follow = ingetc(); + if (follow == ':') { + follow = ingetc(); + if (follow == 'G') + *gbalp = 1; + else { + inungetc(follow); + *cflagp = 1; + } + } else + inungetc(follow); if (hsubl && !strstr(subline, hsubl)) { herrflush(); zerr("substitution failed", NULL, 0); @@ -348,14 +370,16 @@ histsubchar(int c) /* look, no goto's */ if (isfirstch && c == hatchar) { + int gbal = 0; + /* Line begins ^foo^bar */ isfirstch = 0; inungetc(hatchar); if (!(ehist = gethist(defev)) || !(sline = getargs(ehist, 0, getargc(ehist))) - || getsubsargs(sline) || !hsubl) + || getsubsargs(sline, &gbal, &cflag) || !hsubl) return -1; - subst(&sline, hsubl, hsubr, 0); + subst(&sline, hsubl, hsubr, gbal); } else { /* Line doesn't begin ^foo^bar */ if (c != ' ') @@ -543,6 +567,10 @@ histsubchar(int c) if ((c = ingetc()) == 'g') { gbal = 1; c = ingetc(); + if (c != 's' && c != '&') { + zerr("'s' or '&' modifier expected after 'g'", NULL, 0); + return -1; + } } switch (c) { case 'p': @@ -577,7 +605,7 @@ histsubchar(int c) } break; case 's': - if (getsubsargs(sline)) + if (getsubsargs(sline, &gbal, &cflag)) return -1; /* fall through */ case '&': if (hsubl && hsubr) |