From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 12529 invoked from network); 2 Jun 2023 10:19:02 -0000 Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368) by inbox.vuxu.org with ESMTPUTF8; 2 Jun 2023 10:19:02 -0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=zsh.org; s=rsa-20210803; t=1685701143; b=hESPymSPR1C53uSWz/lS4j/pbLU6b3vNypmAaMh77DrsMscD8ap3sekUr9QP+Txp8Zx4IC7khS SIm5gLb+LkOtO0LsaycVZ/uyDsy3AC9xn2zvio0geGUgtikRgRzwrQe+LXDwc4QQmyf3Gbdfxs H3ZXoKLXjwjOLcSvLfVjNbF0QviZHBRsw8Y3usMvU/3geFDuSHXVFgf/Sww5rQMIE5oVyvVlib eGgAe1H4c2Ymqw43q+XPvQe/bFnb0YWHXzXR/sVL3X6HUsCBvGqNAPE8vN/ieBw4wLK4CEapNE lP8wBbBrwj4aMDmzWbnt8CNFJBBee/8CUxSDSaZyrF7xXQ==; ARC-Authentication-Results: i=1; zsh.org; iprev=pass (smtpq2.tb.ukmail.iss.as9143.net) smtp.remote-ip=212.54.57.97; dkim=pass header.d=ntlworld.com header.s=meg.feb2017 header.a=rsa-sha256; dmarc=pass header.from=ntlworld.com; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=zsh.org; s=rsa-20210803; t=1685701143; bh=Rp9FHclBCZAJ+fgm7RrptGWN5T8OmoUYGnA+v2tLkLM=; h=List-Archive:List-Owner:List-Post:List-Unsubscribe:List-Subscribe:List-Help: List-Id:Sender:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject: References:In-Reply-To:Message-ID:To:From:Date:DKIM-Signature: DKIM-Signature; b=k1rnAvtGtl9Pyw7C9yM5tYIdub8LJPbfvdWFvvREbGK8aAu1lGKrRuyqPkm7QjEk0+pmja8GMX 8wbqRl7Gw931uz9ChmtvHX7ADkOrB+yqRORxTReARowW29XOi9WtyspELIKwhx4q+fLmIlmxjh l1tCCf7ErbUSgvMK2NNqtzruPM5xe/XIT1W/QenjUhJnNYcU4ZLyOVe38YVjNMPnKTDaQhi/UH nG9W/rNqSs2u9NIv4nGh8k0PAjzURIQcCbxMdS9Av1irx4gpk1lxW0SXYMeIS6Ohqi8UG9G9gx +Fnsn/NFwjTWhh9+7AAa2nlv8iETuxxBs8uJG2DFYpgqWg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20210803; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:Subject:References:In-Reply-To:Message-ID:To:From: Date:Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID; bh=yKGyPS5WSp5GKxu9w4geCBu3MkWDVRjjaf76/54xTrk=; b=PVDLAFzqmlwEC9tZx/0FozIXk5 RUlgIpy2VqM/am488MIa+3M73OpACUIiLa6ZGv+7wMKHpND/3QrNGYmubzT1h3L1oAtII64fc7IJ1 IS2BDgn3scq/j+cQzltd8CM6JxE5YUx3o65XtT1iDPLsKOszPvGOpfknmBc85g8WL3Rh9Ov0NE3n1 UQ2YdaufKN3oI2pcSHBIjUxSb6gR6juOXUl+gxhWP3c1GQQ/54QqmeiqZwkpHZNBkjMvQoU0ZNXxD rsGYK1rIpmiKil0YeDdLRQetLHiYt7hUTW3/n49V+r0qI7h5INdnPuolD0nPIy8qaNYdGKB2ciMiq vq4WEgPA==; Received: by zero.zsh.org with local id 1q51s6-000BQz-2R; Fri, 02 Jun 2023 10:19:02 +0000 Authentication-Results: zsh.org; iprev=pass (smtpq2.tb.ukmail.iss.as9143.net) smtp.remote-ip=212.54.57.97; dkim=pass header.d=ntlworld.com header.s=meg.feb2017 header.a=rsa-sha256; dmarc=pass header.from=ntlworld.com; arc=none Received: from smtpq2.tb.ukmail.iss.as9143.net ([212.54.57.97]:37884) by zero.zsh.org with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) id 1q51rj-000B79-2l; Fri, 02 Jun 2023 10:18:41 +0000 Received: from [212.54.57.82] (helo=smtp3.tb.ukmail.iss.as9143.net) by smtpq2.tb.ukmail.iss.as9143.net with esmtp (Exim 4.90_1) (envelope-from ) id 1q51ri-0002Ks-MR for zsh-workers@zsh.org; Fri, 02 Jun 2023 12:18:38 +0200 Received: from oxbe12.tb.ukmail.iss.as9143.net ([172.25.160.143]) by smtp3.tb.ukmail.iss.as9143.net with ESMTP id 51riqCucO9tPm51riqmPDi; Fri, 02 Jun 2023 12:18:38 +0200 X-Env-Mailfrom: p.w.stephenson@ntlworld.com X-Env-Rcptto: zsh-workers@zsh.org X-SourceIP: 172.25.160.143 X-CNFS-Analysis: v=2.4 cv=IPTESCjG c=1 sm=1 tr=0 ts=6479c1fe cx=a_exe a=pVlFXI3Q25jgZXAaIqG4JA==:117 a=1DWFKdCB1IcA:10 a=IkcTkHD0fZMA:10 a=NLZqzBF-AAAA:8 a=N898d1J4AAAA:8 a=npldXguGAAAA:8 a=dkbBYixBL5i4UCKbo3MA:9 a=QEXdDO2ut3YA:10 a=1Z6EAcxPEhoA:10 a=Y6yEfkeh0FwA:10 a=75Kt_H3ikK-EkTT1woid:22 a=4OhKILdWXy8MGewZJRtY:22 a=1MEZn5qd6kv58cYvHi58:22 X-Authenticated-Sender: p.w.stephenson@ntlworld.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ntlworld.com; s=meg.feb2017; t=1685701118; bh=Rp9FHclBCZAJ+fgm7RrptGWN5T8OmoUYGnA+v2tLkLM=; h=Date:From:To:In-Reply-To:References:Subject; b=gocKgsy3d0I3GGOoJs77Wzc2HDcsIOV3UOamYt1AmG4NML8NQXGf9uGPM3doQptjj KwfUrR7UxygN7PdUSlA4htanwuwfWl7sOd8wrlzRtEE6cqGOu/r4EnqPjnyr2wwvQs u5HQdwJYSZVB6P7/k9NyHaUm1ECR7WK9E1VM1+cOXsTzhSn03EFKbKvX7rYrVwdwB1 qrTaRWLLq9T2vxs8bP21RKbaYjECvMwOZgBGSsE/ZnKp5e8DYKGgQHitwPVU70jdSt tkfdXkMIvgCAqv59alyKL/xNuheJ0CCvo3mj6da+652AcA5oo5Rf8Z8pl3zP0Vm1iq 7nYuA9sUwh2tA== Date: Fri, 2 Jun 2023 11:18:38 +0100 (BST) From: Peter Stephenson To: Zsh hackers list Message-ID: <1068343689.5141130.1685701118603@mail.virginmedia.com> In-Reply-To: <1452348325.5131636.1685695219291@mail.virginmedia.com> References: <20230601183556.nl3zhv2kdxgj7x4d@chazelas.org> <1452348325.5131636.1685695219291@mail.virginmedia.com> Subject: Re: histsubstpattern in zmv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Priority: 3 Importance: Normal X-Mailer: Open-Xchange Mailer X-Originating-IP: 147.161.224.167 X-Originating-Client: open-xchange-appsuite X-CMAE-Envelope: MS4xfM2xqojQACteQWoqKnio8mUREePoD4TSCdsKUZIas73N8ESBKVN1zOeFjIHORYpBpPEcxZfo1DTlOcdRZS7yjKvUCnlQgrUPbYGfbFT2UjcUoYCSS9o7 5s8Y98hP/CPyqXysf051+1unkeWUd6ArfR9IIsGcdjd7P5WCxIs3/B1tMI3SVNJbkBALPZjCs6bfhiKQu3YE8YD5VbJzcUVsy2V/88JNIzOudAiFEfqBMguR X-Seq: 51816 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: , List-Subscribe: , List-Unsubscribe: , List-Post: List-Owner: List-Archive: > On 02/06/2023 09:40 Peter Stephenson wrote: > On 01/06/2023 19:35 Stephane Chazelas wrote: > > The csh-style ${var:s/foo/bar} is often more legible and easy > > to cumulate than the Korn-style equivalent ${var/foo/bar} > >.. > > But that needs set -o histsubstpattern and in zmv, emulate -LR > > zsh resets options. > > > > Would it be possibe to enable it in zmv along with extendedglob > > which is already enabled there, or if not allow the user to enable it, > > or maybe even better introduced some :+s/pattern/repl/ > > :-s/string/repl/ or :S/pattern/replacement/ so we can use both > > at the same time, like ${f:gs/***/3-stars/:gS/???/any-3-chars} ? > > I can't see any good reason not to enable it. Having said that, adding an :S variant isn't particularly difficult and is more widely useful. pws diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 6f86d0c54..7bc736470 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -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 diff --git a/Src/hist.c b/Src/hist.c index 7e6394406..b4dc53d90 100644 --- a/Src/hist.c +++ b/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) diff --git a/Src/subst.c b/Src/subst.c index 974d6171e..14947ae36 100644 --- a/Src/subst.c +++ b/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); diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 7990c2958..2fd2f975f 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -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