[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