summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2024-02-03 20:10:52 -0800
committerBart Schaefer <schaefer@zsh.org>2024-02-03 20:10:52 -0800
commit2744208ab3eab1741157e01484d08095bd8ef528 (patch)
tree165e370de30f748bbb9b58afda8bd39ce2b9aaf3
parentc039a74e094bb6a4d965899f67fe34d2b84dda8d (diff)
downloadzsh-2744208ab3eab1741157e01484d08095bd8ef528.tar.gz
zsh-2744208ab3eab1741157e01484d08095bd8ef528.zip
unposted: elaboration on Roman's "slurp" implementation from zsh-users
-rw-r--r--ChangeLog3
-rw-r--r--Functions/Misc/zslurp31
2 files changed, 34 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 386ef3ab9..238c12c16 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2024-02-03 Bart Schaefer <schaefer@zsh.org>
+ * unposted: cf. Roman in users/29472: Functions/Misc/zslurp:
+ Efficient lossless read of stdin into $REPLY
+
* unposted: Src/Zle/zle_tricky.c, Src/parse.c, Src/pattern.c:
Record as comments some notes about namespace usage exceptions.
diff --git a/Functions/Misc/zslurp b/Functions/Misc/zslurp
new file mode 100644
index 000000000..84df0c948
--- /dev/null
+++ b/Functions/Misc/zslurp
@@ -0,0 +1,31 @@
+#!/bin/zsh -f
+
+# Read stdin verbatim and as efficiently as possible into $REPLY,
+# stopping without any change to $REPLY in the event of any error.
+# Benchmarked by Roman Perepelitsa in zsh-users/29472
+
+# Although this function faithfully records the input stream, later
+# references to $REPLY with the multibyte option back in effect will
+# (re-)interpret the content as multibyte characters. This may not be
+# what is desired.
+
+emulate -L zsh -o no_multibyte
+
+### Alternate formulation, faster on bigger files
+# # /dev/fd/0 is treated specially by -f so also check /dev/fd
+# if [[ -d /dev/fd && -f /dev/fd/0 ]] && zmodload zsh/mapfile
+# then
+# local +h -Ar mapfile
+# typeset -g REPLY="${mapfile[/dev/fd/0]}" && return
+# fi
+# # else fall through to read from pipe/socket
+
+zmodload zsh/system || return
+local -a content
+local -i i=0
+while true; do
+ sysread 'content[++i]' && continue
+ (( $? == 5 )) || return
+ break
+done
+typeset -g REPLY=${(j::)content}