[Bash-completion-devel] readarray and process substitution. (set -o posix)
Peter Cordes
peter at cordes.ca
Sat Dec 13 03:36:10 UTC 2014
The test suite does set -o posix for some reason. It does flag up a
few problems (esp. if you disable the &>/dev/null when sourcing dynamic
loaded completions). I think some variable names that included a -,
and a process substitution.
I see this has already come up, as
https://alioth.debian.org/tracker/?func=detail&atid=413095&aid=314720&group_id=100114
I was going to use
readarray -t COMPREPLY < <( compgen ... )
in something, but set -o posix disables <(process substitution)
(http://tiswww.case.edu/php/chet/bash/POSIX). So my code wouldn't
work with the testsuite.
So do we want to just use
x="$( compgen ... )"
readarray -t COMPREPLY <<< "$x"
as our idiom of choice, like a bunch of functions already do?
That writes to a tmpfile in /tmp, then redirects the input of
readarray from that. Redirecting from a process substitution is about
the same overhead as a pipe.
compare
strace -e trace='!rt_sigprocmask,rt_sigaction' -f bash -c 'readarray -t ARR < <(exec echo)'
strace -e trace='!rt_sigprocmask,rt_sigaction' -f bash -c 'x=$(exec echo); readarray -t ARR <<< "$x"'
<<< has to statfs('/tmp'), which seems silly, as well as a bunch of
other overhead.
readarray -u <(cmd) didn't seem to work. I guess builtin commands
don't work right with the /proc/pid/fd/number filenames that process
substitution generates? Redirecting from a process substitution
elides opening of /proc/pid/fd, and just does the usual pipe thing, so
it's actually more efficient.
Unfortunately we can't just pipe into readarray, because that would
put readarray in a subshell that didn't affect the main script's env.
(Thanks Eduardo Bustamante for reminding me about Wooledge's site,
http://mywiki.wooledge.org/BashFAQ/001 pointed me towards readarray
and process substitution.)
http://unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
points out that there is a shopt -s lastpipe to let
shopt -s lastpipe
( echo a; echo b; echo c ) | readarray arr
work. Tempting, but setting and unsetting it on enter/leave progcomp
is prob. more trouble than the readability of other ways of feeding
readarray
Also, thoughts on using readarray to replace loops in existing code?
There are a few cases of loops like
while read -r tmp; do
toks+=( "$tmp" )
done <<< "$x"
_filedir_xspec() has some REALLY ugly loops, like loop over the output
of compgen, and expose it to glob expansion for quote removal I guess?
Capturing it with toks=( $( compgen | while read ...; do printf ...;done ) )
But that's a separate issue; readarray can only replace loops that
AREN'T treating data as shell code.
I think if we want to be fully safe with filenames that include a *,
we'll need to replace every
COMPREPLY+=( $( compgen ... ) )
with a readarray (or equivalent while read loop, if we need compat
with older bash, but I'd vote that we use readarray for speed and
readability. http://wiki.bash-hackers.org/commands/builtin/mapfile
says that readarray was buggy until bash 4.1 beta, and I think we
only support bash >= 4.1.)
And to get back to where I started, IMO we don't need to support
set -o posix. Does anyone use that in interactive shells?
progcom isn't really essential, IMO, so people can get by on just
filename completion in the rare cases where they need to set -o posix
in an interactive shell.
--
#define X(x,y) x##y
Peter Cordes ; e-mail: X(peter at cor , des.ca)
"The gods confound the man who first found out how to distinguish the hours!
Confound him, too, who in this place set up a sundial, to cut and hack
my day so wretchedly into small pieces!" -- Plautus, 200 BC
More information about the Bash-completion-devel
mailing list