zsh-workers
 help / color / mirror / code / Atom feed
* nohistsubstpattern and :s//
@ 2015-07-04 13:22 Mikael Magnusson
  2015-07-05  0:01 ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Mikael Magnusson @ 2015-07-04 13:22 UTC (permalink / raw)
  To: zsh workers

% setopt histsubstpattern; a=(aaa bab cac) b=d; echo $a:s/a/${b}/
daa bdb cdc
% setopt nohistsubstpattern; a=(aaa bab cac) b=d; echo $a:s/a/${b}/
${b}aa b${b}b cdc

(reported on irc).

I looked at the documentation of histsubstpattern and the :s/l/r/
flag, and it mostly talks about the effect of the option on the l
part. Even if this effect is somehow desired, it seems inconsistent
that the final element still gets the value of the parameter
substituted.

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-04 13:22 nohistsubstpattern and :s// Mikael Magnusson
@ 2015-07-05  0:01 ` Bart Schaefer
  2015-07-05 10:30   ` Peter Stephenson
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2015-07-05  0:01 UTC (permalink / raw)
  To: zsh workers

Peter, this is yours from way back in workers/22934 -- any memory left
from 2006?

On Jul 4,  3:22pm, Mikael Magnusson wrote:
} Subject: nohistsubstpattern and :s//
}
} % setopt histsubstpattern; a=(aaa bab cac) b=d; echo $a:s/a/${b}/
} daa bdb cdc

Hmm ... hist_subst_pattern doesn't say anything about expansions in
the replacement part of s/pat/rep/, so as far as I can tell this is
contrary to the documentation.  However, see below.

} % setopt nohistsubstpattern; a=(aaa bab cac) b=d; echo $a:s/a/${b}/
} ${b}aa b${b}b cdc

This has been like this for as long as the hist_subst_pattern option
has existed, it appears.  Random old builds I happen to have around
show behavior matching the doc in 3.0.6 and 3.0.8 --

torch% echo $ZSH_VERSION
3.0.6-pre-5
torch% a=(aaa bab cac) b=d; echo $a:s/a/${b}/
${b}aa b${b}b c${b}c

torch% echo $ZSH_VERSION
3.0.8
torch% a=(aaa bab cac) b=d; echo $a:s/a/${b}/
${b}aa b${b}b c${b}c

-- but then after hist_subst_pattern is added in 4.3.3 --

torch% echo $ZSH_VERSION                                                        
4.3.17-test-2
torch% a=(aaa bab cac) b=d; echo $a:s/a/${b}/
${b}aa b${b}b cdc

-- and (still 4.3.17-test-2) --

torch% setopt histsubstpattern
torch% a=(aaa bab cac) b=d; echo $a:s/a/${b}/
daa bdb cdc


So this undocumented behaver of the replacement has also been around
ever since the option was first implemented.  The original test case
in E01options.ztst even expects expansions in the replacement, so it
seems to have been intentional, to allow references to $match in the
event of backrefs in the pattern.

This also changed the behavior for scalars when hist_subst_pattern is
NOT set (note "g" added below):

torch% echo $ZSH_VERSION
3.0.8
torch% a="aaa bab cac" b=d; echo $a:gs/a/${b}/
${b}${b}${b} b${b}b c${b}c

torch% echo $ZSH_VERSION
4.3.17-test-2
torch% a="aaa bab cac" b=d; echo $a:gs/a/${b}/
ddd bdb cdc

So I suspect the same logic error (?) that changed this for scalars is
also somehow affecting the last element of an array.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-05  0:01 ` Bart Schaefer
@ 2015-07-05 10:30   ` Peter Stephenson
  2015-07-05 21:11     ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2015-07-05 10:30 UTC (permalink / raw)
  To: zsh workers

On Sat, 4 Jul 2015 17:01:47 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> Peter, this is yours from way back in workers/22934 -- any memory left
> from 2006?

I've forgotten the option completely, but I'd be very surprised if it
was deliberate.  I'd at least have stuck in a snotty note saying this
was for caompatibility.  It doesn't look at all useful.

pws


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-05 10:30   ` Peter Stephenson
@ 2015-07-05 21:11     ` Bart Schaefer
  2015-07-06  8:49       ` Peter Stephenson
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2015-07-05 21:11 UTC (permalink / raw)
  To: zsh workers

There's a patch near the bottom of this, which needs as many other
eyeballs on it as possible because it's changing some really old code.

On Jul 5, 11:30am, Peter Stephenson wrote:
} Subject: Re: nohistsubstpattern and :s//
}
} On Sat, 4 Jul 2015 17:01:47 -0700
} Bart Schaefer <schaefer@brasslantern.com> wrote:
} > Peter, this is yours from way back in workers/22934 -- any memory left
} > from 2006?
} 
} I've forgotten the option completely, but I'd be very surprised if it
} was deliberate.  I'd at least have stuck in a snotty note saying this
} was for caompatibility.  It doesn't look at all useful.

Not sure which "it" doesn't look useful, but here's a deeper look at a
few things -- first, the change to scalar expansion:

torch% a="aaa bab cac" b=d; echo ${a:gs/a/${b}/}

This goes into subst() in hist.c with ${b} already metafied, and comes
out again looking like

    ${b}${b}${b} b${b}b c${b}c

with all the ${b} still metafied.  I think this is exactly as expected.

#0  subst (strptr=0xbfee4ca4, in=0x82d0e00 "a", out=0x82d0e10 "\205\217b\220", 
    gbal=1) at ../../zsh-5.0/Src/hist.c:2125
#1  0x080c5a4c in modify (str=0xbfee4ca4, ptr=0xbfee4ce4)
    at ../../zsh-5.0/Src/subst.c:4210
#2  0x080c32d5 in paramsubst (l=0xb7d67758, n=0xb7d67770, str=0xbfee4d58, 
    qt=0, pf_flags=0) at ../../zsh-5.0/Src/subst.c:3237
#3  0x080bd8ae in stringsubst (list=0xb7d67758, node=0xb7d67770, pf_flags=0, 
    asssub=0) at ../../zsh-5.0/Src/subst.c:236
#4  0x080bd05e in prefork (list=0xb7d67758, flags=0)
    at ../../zsh-5.0/Src/subst.c:77

At this point stringsubst() [frame #3] keeps looping until all of the
metafied ${b} have been replaced by their expansions.

Further, if I then try a straight history substitution rather than use
a history modifier in a parameter substitution:

torch% !:0:gs/a/${b}/:p
${b}="${b}${b}${b} b${b}b c${b}c"

Here the ${b} is not metafied on the way in to subst(), because we're
doing the replacement very early in the lexing of the command line.

So the expansion of ${b} isn't really related to hist_subst_pattern at
all, it must merely be approximately coincident with it in time.  I
have no idea where to go next with this one, the hist_subst_pattern
test case relies on it behaving this way -- so maybe we should just
document it (in history section 14.1.4 under modifiers, or in Rule #7
for parameter expansion, or where)?

One more comment on this at the end of this message.


Now let's look at 

torch% a=(aaa bab cac) b=d; echo $a:gs/a/${b}/

#0  subst (strptr=0xb7d67850, in=0x82cfe28 "a", out=0x82d8e88 "\205\217b\220", 
    gbal=1) at ../../zsh-5.0/Src/hist.c:2125
#1  0x080c5a4c in modify (str=0xb7d67850, ptr=0xbfee4bb4)
    at ../../zsh-5.0/Src/subst.c:4210
#2  0x080c3354 in paramsubst (l=0xb7d67810, n=0xb7d67828, str=0xbfee4d58, 
    qt=0, pf_flags=0) at ../../zsh-5.0/Src/subst.c:3246
#3  0x080bd8ae in stringsubst (list=0xb7d67810, node=0xb7d67828, pf_flags=0, 
    asssub=0) at ../../zsh-5.0/Src/subst.c:236
#4  0x080bd05e in prefork (list=0xb7d67810, flags=0)
    at ../../zsh-5.0/Src/subst.c:77

Note modify() is being called from a different place, the loop at 3244
that applies it to each element of the array.

Passed down to stringsubst() was "node" pointing at the first element
of the array, but returning from stringsubst() to paramsubst() we have
*str pointing into the last node of the array, and assign "node" there
to that last node.  Then we continue looping until the ${b} in "c${b}c"
is expanded, but we have thus skipped over the first two elements of
the array.

This in turn all comes from the "if (isarr)" block at line 3652, where
we record "Linknode on = n" at line 3657 but conditionally restore n at
3838 based on "if (eval)".

With the patch below, removing that conditional restore, all tests still
pass and the array version of :s// works like the scalar version:

torch% a=(aaa bab cac) b=d; echo $a:gs/a/${b}/
ddd bdb cdc

The patch simply removes that conditional restore and does it always,
but restores both the node and the string pointer instead of only the
node.  There's a little more discussion after the patch.


diff --git a/Src/subst.c b/Src/subst.c
index 81d34d2..021d234 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3834,8 +3834,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
 		y = dupstring(nulstring);
 	    insertlinknode(l, n, (void *) y), incnode(n);
 	}
-	if (eval)
-	    n = on;
+	/* This used to omit restoring of *str and instead test
+	 *   if (eval)
+	 *       n = on;
+	 * but that causes strange behavior of history modifiers when
+	 * applied across all values of an array.  What is magic about
+	 * eval here that *str seemed not to need restoring?
+	 */
+	*str = getdata(n = on);
     } else {
 	/*
 	 * Scalar value.  Handle last minute transformations
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index d06a73a..0a9e253 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -1711,3 +1711,12 @@
 0:Avoid confusion after overloaded characters in braceless substitution in sh
 >13
 >0-1
+
+  a="aaa bab cac"
+  b=d
+  echo $a:gs/a/${b}/
+  a=(aaa bab cac)
+  echo $a:gs/a/${b}/
+0:History modifier works the same for scalar and array substitution
+>ddd bdb cdc
+>ddd bdb cdc



Parameter substitution also occurs in the replacement part when the
modifier is applied as a glob qualfier, in case that matters.  In this
case the replacement happens during parsing of the qualifier rather
than after the substitution:

torch% echo *a*
config.modules.local config.status Makefile stamp-h
torch% b=1
torch% print *a*(:s/a/$[b++]/) $b
config.modules.loc1l config.st1tus M1kefile st1mp-h 2
torch% a=(*a*)
torch% print ${a:s/a/$[b++]/} $b
config.modules.loc1l config.st2tus M3kefile st4mp-h 5

So we have three different behaviors of the same substitution depending
on the context.

-- 
Barton E. Schaefer


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-05 21:11     ` Bart Schaefer
@ 2015-07-06  8:49       ` Peter Stephenson
  2015-07-06 20:51         ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2015-07-06  8:49 UTC (permalink / raw)
  To: zsh workers

On Sun, 5 Jul 2015 14:11:16 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> There's a patch near the bottom of this, which needs as many other
> eyeballs on it as possible because it's changing some really old code.

I'd say use it --- I suspect you've exercised this code more than anyone
in years and if this breaks something, it's going to have to be very
obscure.

I don't think it's *that* much of a problem that the modifiers behave
differently in contexts that are themselves intrinsically rather
different.

pws


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-06  8:49       ` Peter Stephenson
@ 2015-07-06 20:51         ` Bart Schaefer
  2015-07-06 23:04           ` Mikael Magnusson
  2015-07-07 11:15           ` Peter Stephenson
  0 siblings, 2 replies; 16+ messages in thread
From: Bart Schaefer @ 2015-07-06 20:51 UTC (permalink / raw)
  To: zsh workers

On Jul 6,  9:49am, Peter Stephenson wrote:
}
} I don't think it's *that* much of a problem that the modifiers behave
} differently in contexts that are themselves intrinsically rather
} different.

Some doc below, but there's still some odd stuff going on.

$b != ${b} in parameter expansion:

torch% a=(abc dbe fbg)
torch% unset b
torch% print ${a:gs/b/$b/}  
a d f
torch% print ${a:gs/b/${b}} 
ac de fg
torch% b=/
torch% print ${a:gs/b/$b/}     
a d f
torch% print ${a:gs/b/${b}}
a/c d/e f/g

(I have no idea why the strings are being truncated in the $b case no
matter what the value of $b.)

No way to quote "/" when using in a glob qualifier:

torch% ls *a*
config.modules.local  config.status  Makefile  stamp-h
torch% b=/
torch% print *a*(:s/a/$b/)
config.modules.locl config.sttus Mkefile stmp-h
torch% b=X
torch% print *a*(:s/a/$b/)
config.modules.locXl config.stXtus MXkefile stXmp-h

(Perhaps ${(b)...} should put backslashes in front of slashes? But two
backslashes are needed:

torch% print *a*(:s/a/\//)
config.modules.locl config.sttus Mkefile stmp-h
torch% print *a*(:s/a/\\//)
config.modules.loc/l config.st/tus M/kefile st/mp-h

so maybe this just calls for using a different delimiter.)


diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 7d4e6fc..1e1fc52 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -319,6 +319,19 @@ forms of expansion.
 Note that if a `tt(&)' is used within glob qualifiers an extra backslash
 is needed as a tt(&) is a special character in this case.
 
+Also note that the order of expansions affects the interpretation of
+var(l) and var(r).  When used in a history expansion, which occurs before
+any other expansions, var(l) and var(r) are treated as literal strings
+(except as explained for tt(HIST_SUBST_PATTERN) below).  When used in
+parameter expansion, the replacement of var(r) into the parameter's value
+is done first, and then any additional process, parameter, command,
+arithmetic, or brace references are applied, which may evaluate those
+substitutions and expansions more than once if var(l) appears more than
+once in the starting value.  When used in a glob qualifier, any
+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
 a pattern of the usual form described in
 ifzman(the section FILENAME GENERATION below)\


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-06 20:51         ` Bart Schaefer
@ 2015-07-06 23:04           ` Mikael Magnusson
  2015-07-07 11:15           ` Peter Stephenson
  1 sibling, 0 replies; 16+ messages in thread
From: Mikael Magnusson @ 2015-07-06 23:04 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh workers

On Mon, Jul 6, 2015 at 10:51 PM, Bart Schaefer
<schaefer@brasslantern.com> wrote:
> On Jul 6,  9:49am, Peter Stephenson wrote:
> }
> } I don't think it's *that* much of a problem that the modifiers behave
> } differently in contexts that are themselves intrinsically rather
> } different.
[...]
> No way to quote "/" when using in a glob qualifier:
>
> torch% ls *a*
> config.modules.local  config.status  Makefile  stamp-h
> torch% b=/
> torch% print *a*(:s/a/$b/)
> config.modules.locl config.sttus Mkefile stmp-h
> torch% b=X
> torch% print *a*(:s/a/$b/)
> config.modules.locXl config.stXtus MXkefile stXmp-h
>
> (Perhaps ${(b)...} should put backslashes in front of slashes? But two
> backslashes are needed:
>
> torch% print *a*(:s/a/\//)
> config.modules.locl config.sttus Mkefile stmp-h
> torch% print *a*(:s/a/\\//)
> config.modules.loc/l config.st/tus M/kefile st/mp-h
>
> so maybe this just calls for using a different delimiter.)

You can use any character instead of a /, even a literal NUL
character, so it's not really something ${(b)...} can/should know
about, I think?

% a=f/o/o/; echo $a:gs^@/^@_^@
f_o_o_
% a=moo; echo $a:spoopypants
myants
% echo ..(:gs^@.^@hello\\^@there^@)|cat -v
hello^@therehello^@there

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-06 20:51         ` Bart Schaefer
  2015-07-06 23:04           ` Mikael Magnusson
@ 2015-07-07 11:15           ` Peter Stephenson
  2015-07-07 11:54             ` Peter Stephenson
  2015-07-07 14:48             ` Bart Schaefer
  1 sibling, 2 replies; 16+ messages in thread
From: Peter Stephenson @ 2015-07-07 11:15 UTC (permalink / raw)
  To: zsh workers

On Mon, 6 Jul 2015 13:51:07 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:

> On Jul 6,  9:49am, Peter Stephenson wrote:
> }
> } I don't think it's *that* much of a problem that the modifiers behave
> } differently in contexts that are themselves intrinsically rather
> } different.
> 
> Some doc below, but there's still some odd stuff going on.
> 
> $b != ${b} in parameter expansion:
> 
> torch% a=(abc dbe fbg)
> torch% unset b
> torch% print ${a:gs/b/$b/}  
> a d f

Perhaps the line is turning into "a$bc", "d$be", "f$bg" before the
substitution?

This is new:  the existing code gives

ac de fg

so maybe this is a clue to why the current code works the way it does.

pws


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 11:15           ` Peter Stephenson
@ 2015-07-07 11:54             ` Peter Stephenson
  2015-07-07 15:11               ` Bart Schaefer
  2015-07-07 14:48             ` Bart Schaefer
  1 sibling, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2015-07-07 11:54 UTC (permalink / raw)
  To: zsh workers

On Tue, 7 Jul 2015 12:15:35 +0100
Peter Stephenson <p.stephenson@samsung.com> wrote:
> > torch% a=(abc dbe fbg)
> > torch% unset b
> > torch% print ${a:gs/b/$b/}  
> > a d f
> 
> Perhaps the line is turning into "a$bc", "d$be", "f$bg" before the
> substitution?
> 
> This is new:  the existing code gives
> 
> ac de fg
> 
> so maybe this is a clue to why the current code works the way it does.

Hmm, it seems to have gone back to the old way after a full
recompilation --- unless there's something flaky in the memory
or pointer management.

pws


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 11:15           ` Peter Stephenson
  2015-07-07 11:54             ` Peter Stephenson
@ 2015-07-07 14:48             ` Bart Schaefer
  1 sibling, 0 replies; 16+ messages in thread
From: Bart Schaefer @ 2015-07-07 14:48 UTC (permalink / raw)
  To: zsh workers

On Jul 7, 12:15pm, Peter Stephenson wrote:
} Subject: Re: nohistsubstpattern and :s//
}
} > 
} > torch% a=(abc dbe fbg)
} > torch% unset b
} > torch% print ${a:gs/b/$b/}  
} > a d f
} 
} Perhaps the line is turning into "a$bc", "d$be", "f$bg" before the
} substitution?

Oh!  Yes, of course.

} This is new:  the existing code gives
} 
} ac de fg

?? Existing (as in, 5.0.8) code for me gives

    a$bc d$be f

which would have immediately explained the foregoing if I had thought
to compare.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 11:54             ` Peter Stephenson
@ 2015-07-07 15:11               ` Bart Schaefer
  2015-07-07 15:28                 ` Peter Stephenson
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2015-07-07 15:11 UTC (permalink / raw)
  To: zsh workers

On Jul 7, 12:54pm, Peter Stephenson wrote:
}
} Hmm, it seems to have gone back to the old way after a full
} recompilation --- unless there's something flaky in the memory
} or pointer management.

"Gone back to the old way" means what, precisely?  Sorry I lost track.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 15:11               ` Bart Schaefer
@ 2015-07-07 15:28                 ` Peter Stephenson
  2015-07-07 15:48                   ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2015-07-07 15:28 UTC (permalink / raw)
  To: zsh workers

On Tue, 7 Jul 2015 08:11:01 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Jul 7, 12:54pm, Peter Stephenson wrote:
> }
> } Hmm, it seems to have gone back to the old way after a full
> } recompilation --- unless there's something flaky in the memory
> } or pointer management.
> 
> "Gone back to the old way" means what, precisely?  Sorry I lost track.

"Old way" is misleading: I mean the expected result with b -> empty
string because b is unset.  I've been updating and recompiling without
properly keeping track of the version.

Even this afternoon(!) I'm still getting

% a=(abc dbe fbg)
% setopt histsubstpattern
% unset b
% print ${a:gs/b/$b/}
ac de fg

and I confirmed with zsh -f, too.

pws


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 15:28                 ` Peter Stephenson
@ 2015-07-07 15:48                   ` Bart Schaefer
  2015-07-07 16:10                     ` Peter Stephenson
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2015-07-07 15:48 UTC (permalink / raw)
  To: zsh workers

On Jul 7,  4:28pm, Peter Stephenson wrote:
}
} Even this afternoon(!) I'm still getting
} 
} % a=(abc dbe fbg)
} % setopt histsubstpattern
} % unset b
} % print ${a:gs/b/$b/}
} ac de fg
} 
} and I confirmed with zsh -f, too.

Ah!

torch% a=(abc dbe fbg)
torch% setopt histsubstpattern
torch% print ${a:gs/b/$b/}
ac de fg
torch% setopt nohistsubstpattern
torch% print ${a:gs/b/$b/}
a d f

So with histsubstpattern set it looks like $b is expanded before the
substitution takes place, but with nohistsubstpattern (the default,
which is why I never showed the option change in any of my previous
examples) the expansion happens after the substitution.

Demonstrable with a scalar substitution instead of an array:

torch% a=(abc dbe fbg) 
torch% b=1         
torch% print ${a:s/b/$[b++]/}
a1c d2e f3g
torch% setopt histsubstpattern
torch% print ${a:s/b/$[b++]/} 
a4c d5e f6g
torch% a="$a"				<-- scalar + histsubstpattern
torch% print ${a:gs/b/$[b++]/} 
a7c d7e f7g				<-- only one increment of b
torch% unsetopt histsubstpattern
torch% print ${a:gs/b/$[b++]/}  
a8c d9e f10g				<-- three increments of b

No memory errors found by valgrind in either case.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 15:48                   ` Bart Schaefer
@ 2015-07-07 16:10                     ` Peter Stephenson
  2015-07-07 18:10                       ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2015-07-07 16:10 UTC (permalink / raw)
  To: zsh workers

On Tue, 7 Jul 2015 08:48:51 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> So with histsubstpattern set it looks like $b is expanded before the
> substitution takes place, but with nohistsubstpattern (the default,
> which is why I never showed the option change in any of my previous
> examples) the expansion happens after the substitution.

Oh, in that case it's perfectly sensible.  The only gotcha is to
remember that because modifiers operate on raw input, which is how they
came to exist in the first place, if you don't want a $ to be active you
need to quote it.

% print ${a:gs/b/\$b/}
a$bc d$be f$bg

Not wanting this effect is probably a sign you should be using

% print ${a//b/$b}

where the rules are roughly "if it quacks like a single word, it's
expanded like a single word", so any expansion is always done (or
suppressed) within the substitution argument, and you get

% print ${a//b/$b}
ac de fg
% print ${a//b/\$b}
a$bc d$be f$bg

pws


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 16:10                     ` Peter Stephenson
@ 2015-07-07 18:10                       ` Bart Schaefer
  2015-07-08 14:37                         ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2015-07-07 18:10 UTC (permalink / raw)
  To: zsh workers

On Jul 7,  5:10pm, Peter Stephenson wrote:
} Subject: Re: nohistsubstpattern and :s//
}
} On Tue, 7 Jul 2015 08:48:51 -0700
} Bart Schaefer <schaefer@brasslantern.com> wrote:
} > So with histsubstpattern set it looks like $b is expanded before the
} > substitution takes place, but with nohistsubstpattern (the default,
} > which is why I never showed the option change in any of my previous
} > examples) the expansion happens after the substitution.
} 
} Oh, in that case it's perfectly sensible.

Except that's not QUITE what's going on ... if the expansion were simply
being done before the replacement, this wouldn't work:

torch% a=(abc dbe fbg)
torch% setopt histsubstpattern extendedglob
torch% print -R ${a:s/(#b)b(?)/${match}X/}
acX deX fgX
torch% a="$a"
torch% print -R ${a:gs/(#b)b(?)/${match}X/}
acX deX fgX

So what's actually happening (hist.c 2131-2175) is that hist_subst_pattern
causes both the left and right sides to be expanded *during* replacement
[via getmatch() -> igetmatch() in glob.c].

} The only gotcha is to remember that because modifiers operate on raw
} input, which is how they came to exist in the first place, if you
} don't want a $ to be active you need to quote it.

Not exactly the only gotcha.  The after vs. during difference is a the
least worth mentioning, particularly because of this:

torch% print *a*
config.modules.local config.status Makefile stamp-h
torch% x=':gs/(#b)(?)?/X$match/'
torch% setopt histsubstpattern extendedglob
torch% print *a*($x)          
XcXnXiX.XoXuXeX.XoXa XcXnXiX.XtXts XMXkXfXl XsXaXph

Note that I didn't even need to use $~x there, because it's expanded one
time during parsing the glob qualifier and then again during the modifier.
In fact it's actually WRONG to use $~x there:

torch% print *a*($~x)                    
zsh: bad pattern: *a*(:gs/(#b)(?)?/X$match/)

Need to think a while about the right way to document this.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: nohistsubstpattern and :s//
  2015-07-07 18:10                       ` Bart Schaefer
@ 2015-07-08 14:37                         ` Bart Schaefer
  0 siblings, 0 replies; 16+ messages in thread
From: Bart Schaefer @ 2015-07-08 14:37 UTC (permalink / raw)
  To: zsh workers

Sorry to keep coming back to this ...

On Jul 7, 11:10am, Bart Schaefer wrote:
}
} Not exactly the only gotcha.  The after vs. during difference is a the
} least worth mentioning, particularly because of this:
} 
} torch% print *a*
} config.modules.local config.status Makefile stamp-h
} torch% x=':gs/(#b)(?)?/X$match/'
} torch% setopt histsubstpattern extendedglob
} torch% print *a*($x)          
} XcXnXiX.XoXuXeX.XoXa XcXnXiX.XtXts XMXkXfXl XsXaXph

OK, this is even more confusing:

torch% setopt histsubstpattern
torch% x=1
torch% !s:gs/t/$[x++]/:p
se1op1 his1subs1pa11ern
torch% a="setopt histsubstpattern"
torch% print ${a:gs/t/$[x++]/}
se2op2 his2subs2pa22ern
torch% setopt extendedglob
torch% print ${a:gs/(#b)t(?)/$match$[x++]/}
seo3p 4hiss5ubsp6at7ern
torch% print ${a:gs/t/$[x++]/}
se8op8 his8subs8pa88ern
torch% print ${a:gs/(#b)t(?)/$[x++]/}
se9p10his11ubs12a13ern
torch% !s:gs/(#b)t(?)/$[x++]/:p
se13p14his15ubs16a17ern ex18ndedglob

Not surprising that unlike no_hist_subst_pattern, history references
expand variables in the replacement.  What IS surprising is that
when there are backreferences, $match and $[x++] are evaluated for
each replacement, even if $match is not mentioned.  When there are
no backreferences, $[x++] is evaluated only once.


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2015-07-08 14:37 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-04 13:22 nohistsubstpattern and :s// Mikael Magnusson
2015-07-05  0:01 ` Bart Schaefer
2015-07-05 10:30   ` Peter Stephenson
2015-07-05 21:11     ` Bart Schaefer
2015-07-06  8:49       ` Peter Stephenson
2015-07-06 20:51         ` Bart Schaefer
2015-07-06 23:04           ` Mikael Magnusson
2015-07-07 11:15           ` Peter Stephenson
2015-07-07 11:54             ` Peter Stephenson
2015-07-07 15:11               ` Bart Schaefer
2015-07-07 15:28                 ` Peter Stephenson
2015-07-07 15:48                   ` Bart Schaefer
2015-07-07 16:10                     ` Peter Stephenson
2015-07-07 18:10                       ` Bart Schaefer
2015-07-08 14:37                         ` Bart Schaefer
2015-07-07 14:48             ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).