mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-19 09:48:03 +02:00
51816: add :S history modifier with pattern match
This commit is contained in:
parent
63400fdbc5
commit
78102120b9
5 changed files with 49 additions and 14 deletions
|
@ -1,3 +1,9 @@
|
|||
2023-06-06 Peter Stephenson <p.stephenson@samsung.com>
|
||||
|
||||
* 51816: Doc/Zsh/expn.yo, Src/hist.c, Src/subst.c,
|
||||
Test/D04parameter.ztst: add :S history modifier with pattern
|
||||
match.
|
||||
|
||||
2023-06-06 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
|
||||
|
||||
* Marlon Richert: 51779: Test/Y01completion.ztst: update
|
||||
|
|
|
@ -312,7 +312,8 @@ zero) that are neither `tt(.)' nor `tt(/)' and that continue to the end
|
|||
of the string. For example, the extension of
|
||||
`tt(foo.orig.c)' is `tt(.c)', and `tt(dir.c/foo)' has no extension.
|
||||
)
|
||||
item(tt(s/)var(l)tt(/)var(r)[tt(/)])(
|
||||
xitem(tt(s/)var(l)tt(/)var(r)[tt(/)])
|
||||
item(tt(S/)var(l)tt(/)var(r)[tt(/)])(
|
||||
Substitute var(r) for var(l) as described below.
|
||||
The substitution is done only for the
|
||||
first string that matches var(l). For arrays and for filename
|
||||
|
@ -324,13 +325,17 @@ 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.
|
||||
|
||||
The use of tt(S) instead of tt(s) is identical except that
|
||||
the source is treated as a pattern, just as if the option
|
||||
tt(HIST_SUBST_PATTERN) were set.
|
||||
|
||||
See further notes on this form of substitution below.
|
||||
)
|
||||
item(tt(&))(
|
||||
Repeat the previous tt(s) substitution. Like tt(s), may be preceded
|
||||
immediately by a tt(g). In parameter expansion the tt(&) must appear
|
||||
inside braces, and in filename generation it must be quoted with a
|
||||
backslash.
|
||||
Repeat the previous tt(s) or tt(S) substitution, whichever was most
|
||||
recent. Like tt(s) and tt(S), may be preceded immediately by a tt(g).
|
||||
In parameter expansion the tt(&) must appear inside braces, and in
|
||||
filename generation it must be quoted with a backslash.
|
||||
)
|
||||
item(tt(t) [ var(digits) ])(
|
||||
Remove all leading pathname components, leaving the final component (tail).
|
||||
|
@ -377,7 +382,8 @@ substitutions or expansions are performed once at the time the qualifier
|
|||
is parsed, even before the `tt(:s)' expression itself is divided into
|
||||
var(l) and var(r) sides.
|
||||
|
||||
If the option tt(HIST_SUBST_PATTERN) is set, var(l) is treated as
|
||||
If the option tt(HIST_SUBST_PATTERN) is set or the original substitution
|
||||
was started with a capital tt(S), var(l) is treated as
|
||||
a pattern of the usual form described in
|
||||
ifzman(the section FILENAME GENERATION below)\
|
||||
ifnzman(noderef(Filename Generation)). This can be used in
|
||||
|
|
17
Src/hist.c
17
Src/hist.c
|
@ -163,6 +163,11 @@ char *hsubl;
|
|||
/**/
|
||||
char *hsubr;
|
||||
|
||||
/* state of histsubstpattern at last substitution */
|
||||
|
||||
/**/
|
||||
int hsubpatopt;
|
||||
|
||||
/* pointer into the history line */
|
||||
|
||||
/**/
|
||||
|
@ -624,7 +629,7 @@ histsubchar(int c)
|
|||
return substfailed();
|
||||
if (!hsubl)
|
||||
return -1;
|
||||
if (subst(&sline, hsubl, hsubr, gbal))
|
||||
if (subst(&sline, hsubl, hsubr, gbal, 0))
|
||||
return substfailed();
|
||||
} else {
|
||||
/* Line doesn't begin ^foo^bar */
|
||||
|
@ -831,7 +836,7 @@ histsubchar(int c)
|
|||
if ((c = ingetc()) == 'g') {
|
||||
gbal = 1;
|
||||
c = ingetc();
|
||||
if (c != 's' && c != '&') {
|
||||
if (c != 's' && c != 'S' && c != '&') {
|
||||
zerr("'s' or '&' modifier expected after 'g'");
|
||||
return -1;
|
||||
}
|
||||
|
@ -891,11 +896,13 @@ histsubchar(int c)
|
|||
}
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
hsubpatopt = (c == 'S');
|
||||
if (getsubsargs(sline, &gbal, &cflag))
|
||||
return -1; /* fall through */
|
||||
case '&':
|
||||
if (hsubl && hsubr) {
|
||||
if (subst(&sline, hsubl, hsubr, gbal))
|
||||
if (subst(&sline, hsubl, hsubr, gbal, hsubpatopt))
|
||||
return substfailed();
|
||||
} else {
|
||||
herrflush();
|
||||
|
@ -2315,7 +2322,7 @@ casemodify(char *str, int how)
|
|||
|
||||
/**/
|
||||
int
|
||||
subst(char **strptr, char *in, char *out, int gbal)
|
||||
subst(char **strptr, char *in, char *out, int gbal, int forcepat)
|
||||
{
|
||||
char *str = *strptr, *substcut, *sptr;
|
||||
int off, inlen, outlen;
|
||||
|
@ -2323,7 +2330,7 @@ subst(char **strptr, char *in, char *out, int gbal)
|
|||
if (!*in)
|
||||
in = str, gbal = 0;
|
||||
|
||||
if (isset(HISTSUBSTPATTERN)) {
|
||||
if (isset(HISTSUBSTPATTERN) || forcepat) {
|
||||
int fl = SUB_LONG|SUB_REST|SUB_RETFAIL;
|
||||
char *oldin = in;
|
||||
if (gbal)
|
||||
|
|
12
Src/subst.c
12
Src/subst.c
|
@ -4351,6 +4351,8 @@ modify(char **str, char **ptr, int inbrace)
|
|||
break;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
hsubpatopt = (**ptr == 'S');
|
||||
c = **ptr;
|
||||
(*ptr)++;
|
||||
ptr1 = *ptr;
|
||||
|
@ -4445,7 +4447,7 @@ modify(char **str, char **ptr, int inbrace)
|
|||
break;
|
||||
|
||||
case '&':
|
||||
c = 's';
|
||||
c = hsubpatopt ? 'S' : 's';
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
|
@ -4534,8 +4536,10 @@ modify(char **str, char **ptr, int inbrace)
|
|||
copy = casemodify(tt, CASMOD_UPPER);
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
hsubpatopt = (c == 'S');
|
||||
if (hsubl && hsubr)
|
||||
subst(©, hsubl, hsubr, gbal);
|
||||
subst(©, hsubl, hsubr, gbal, hsubpatopt);
|
||||
break;
|
||||
case 'q':
|
||||
copy = quotestring(copy, QT_BACKSLASH_SHOWNULL);
|
||||
|
@ -4620,8 +4624,10 @@ modify(char **str, char **ptr, int inbrace)
|
|||
*str = casemodify(*str, CASMOD_UPPER);
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
hsubpatopt = (c == 'S');
|
||||
if (hsubl && hsubr)
|
||||
subst(str, hsubl, hsubr, gbal);
|
||||
subst(str, hsubl, hsubr, gbal, hsubpatopt);
|
||||
break;
|
||||
case 'q':
|
||||
*str = quotestring(*str, QT_BACKSLASH);
|
||||
|
|
|
@ -2754,3 +2754,13 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888
|
|||
0:(users/28784 inspired this) substituting a single-quoted backslash, part #3: control
|
||||
>xfooy
|
||||
|
||||
spacestring="string with spaces"
|
||||
print ${spacestring:gs/[[:space:]]/ /}
|
||||
print ${spacestring:g&}
|
||||
print ${spacestring:gS/[[:space:]]//}
|
||||
print ${spacestring:g&}
|
||||
0:Different behaviour of :s and :S modifiers
|
||||
>string with spaces
|
||||
>string with spaces
|
||||
>stringwithspaces
|
||||
>stringwithspaces
|
||||
|
|
Loading…
Reference in a new issue