* [PATCH] Nofork removing just one newline
@ 2024-03-15 1:59 Bart Schaefer
0 siblings, 0 replies; only message in thread
From: Bart Schaefer @ 2024-03-15 1:59 UTC (permalink / raw)
To: Zsh hackers list
[-- Attachment #1: Type: text/plain, Size: 201 bytes --]
Following on the discussion with Oliver.
This still uses the ${|var|...} alternate syntax, I haven't yet looked
closely enough at ${{var}...} as an alternative so that will have to
follow separately.
[-- Attachment #2: nofork-onenewline.txt --]
[-- Type: text/plain, Size: 5817 bytes --]
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 183ca6e03..0e121e784 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -1950,6 +1950,9 @@ the braces by whitespace, like `tt(${ )...tt( })', is replaced by its
standard output. Like `tt(${|)...tt(})' and unlike
`tt($LPAR())...tt(RPAR())', the command executes in the current shell
context with function local behaviors and does not create a subshell.
+Word splitting does not apply unless tt(SH_WORD_SPLIT) is set, but a
+single trailing newline is stripped unless the substitution is enclosed
+in double quotes.
Note that because the `tt(${|)...tt(})' and `tt(${ )...tt( })' forms
must be parsed at once as both string tokens and commands, all other
diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index 4a86050e6..4d71c8f30 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -1091,20 +1091,23 @@ sect(Comparisons of forking and non-forking command substitution)
mytt(set -- pos1 pos2 etc). Nothing that happens within mytt($(command))
affects the caller.
- mytt($(command)) removes trailing newlines from the output of mytt(command)
- when substituting, whereas mytt(${ command }) and its variants do not.
- The latter is consistent with mytt(${|...}) from mksh but differs from
- bash and ksh, so in emulation modes, newlines are stripped from command
- output (not from tt(REPLY) assignments).
-
When not enclosed in double quotes, the expansion of mytt($(command)) is
split on tt(IFS) into an array of words. In contrast, and unlike both
bash and ksh, unquoted non-forking substitutions behave like parameter
expansions with respect to the tt(SH_WORD_SPLIT) option.
- When mytt(command) is myem(not) a builtin, mytt(${ command }) does fork, and
- typically forks the same number of times as mytt($(command)), because in
- the latter case zsh usually optimizes the final fork into an exec.
+ Both of the mytt(${|...}) formats retain any trailing newlines,
+ except as handled by the tt(SH_WORD_SPLIT) option, consistent with
+ mytt(${|...}) from mksh. mytt(${ command }) removes a single final
+ newline, but mytt("${ command }") retains it. This differs from
+ bash and ksh, so in emulation modes, newlines are stripped even from
+ quoted command output. In all cases, mytt($(command)) removes all
+ trailing newlines from the output of mytt(command).
+
+ When mytt(command) is myem(not) a builtin, mytt(${ command }) does
+ fork, and typically forks the same number of times as
+ mytt($(command)), because in the latter case zsh usually optimizes
+ the final fork into an exec.
Redirecting input from files has subtle differences:
itemization(
diff --git a/Src/subst.c b/Src/subst.c
index 49f7336bb..9d20a2d0e 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1900,6 +1900,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
/* The command string to be run by ${|...;} */
char *cmdarg = NULL;
size_t slen = 0;
+ int trim = (!EMULATION(EMULATE_ZSH)) ? 2 : !qt;
inbrace = 1;
s++;
@@ -2005,10 +2006,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
int onoerrs = noerrs, rplylen;
noerrs = 2;
rplylen = zstuff(&cmdarg, rplytmp);
- if (! EMULATION(EMULATE_ZSH)) {
+ if (trim) {
/* bash and ksh strip trailing newlines here */
- while (rplylen > 0 && cmdarg[rplylen-1] == '\n')
+ while (rplylen > 0 && cmdarg[rplylen-1] == '\n') {
rplylen--;
+ if (trim == 1)
+ break;
+ }
cmdarg[rplylen] = 0;
}
noerrs = onoerrs;
diff --git a/Test/D10nofork.ztst b/Test/D10nofork.ztst
index d6a5588df..fc6b84613 100644
--- a/Test/D10nofork.ztst
+++ b/Test/D10nofork.ztst
@@ -86,9 +86,39 @@ F:setting option inside is too late for that substitution
?(eval):8: no matches found: f?*
purr ${| REPLY=$'trailing newlines remain\n\n' }
-0:newline removal should not occur
+0:newline removal should not occur, part 1
>trailing newlines remain
>
+>
+
+ purr ${ echo $'one trailing newline\nremoved\n\n\n' }
+0:newline removal in ${ ... }, zsh mode
+>one trailing newline
+>removed
+>
+>
+>
+
+ () {
+ emulate -L ksh
+ purl ${ echo $'all trailing newlines\nremoved\n\n\n' }
+ purr "${ echo $'all trailing newlines\nremoved\n\n\n' }"
+ }
+0:newline removal in ${ ... }, emulation mode, shwordsplit
+>all
+>trailing
+>newlines
+>removed
+>all trailing newlines
+>removed
+
+ purr "${ echo $'no trailing newlines\nremoved\n\n\n' }"
+0:newline removal should not occur, part 2
+>no trailing newlines
+>removed
+>
+>
+>
>
() {
@@ -159,7 +189,7 @@ F:Why not use this error in the previous case as well?
1:unbalanced braces, part 4+
?(eval):1: closing brace expected
- purr ${ purr STDOUT }
+ purr "${ purr STDOUT }"
0:capture stdout
>STDOUT
>
@@ -322,7 +352,7 @@ F:Fiddly here to get EOF past the test syntax
0:here-string behavior
>in a here string
- <<<${ purr $'stdout as a here string' }
+ <<<"${ purr $'stdout as a here string' }"
0:another capture stdout
>stdout as a here string
>
@@ -331,7 +361,7 @@ F:Fiddly here to get EOF past the test syntax
wrap=${ purr "capture in environment assignment" } typeset -p wrap
0:assignment context
>typeset -g wrap='REPLY in environment assignment'
->typeset -g wrap=$'capture in environment assignment\n'
+>typeset -g wrap='capture in environment assignment'
# Repeat return and exit tests with stdout capture
@@ -410,7 +440,7 @@ F:must do this before evaluating the next test block
0:ignored braces, part 1
>buried}
- purr ${ purr ${REPLY:-buried}}}
+ purr "${ purr ${REPLY:-buried}}}"
0:ignored braces, part 2
>buried
>}
@@ -418,7 +448,6 @@ F:must do this before evaluating the next test block
purr ${ { echo nested ;} }
0:ignored braces, part 3
>nested
->
purr ${ { echo nested } } DONE
1:ignored braces, part 4
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2024-03-15 2:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-15 1:59 [PATCH] Nofork removing just one newline 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).