Skip to content

Commit

Permalink
[builtin/read] Implement read -a array.
Browse files Browse the repository at this point in the history
bash-completion uses this to parse options.  Addresses issue #208.

Also, add test for IFS character escaping in compgen/complete -W.
  • Loading branch information
Andy Chu committed Jan 21, 2019
1 parent a7a8334 commit 4871250
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 12 deletions.
25 changes: 16 additions & 9 deletions osh/builtin.py
Expand Up @@ -468,7 +468,7 @@ def _AppendParts(s, spans, max_results, join_next, parts):
join_next = True
last_span_was_black = False

if len(parts) >= max_results:
if max_results and len(parts) >= max_results:
join_next = True

start_index = end_index
Expand All @@ -488,6 +488,7 @@ def _AppendParts(s, spans, max_results, join_next, parts):
READ_SPEC = _Register('read')
READ_SPEC.ShortFlag('-r')
READ_SPEC.ShortFlag('-n', args.Int)
READ_SPEC.ShortFlag('-a', args.Str) # name of array to read into


# sys.stdin.readline() in Python has buffering! TODO: Rewrite this tight loop
Expand Down Expand Up @@ -527,7 +528,10 @@ def Read(argv, splitter, mem):
names.append('REPLY')

# leftover words assigned to the last name
max_results = len(names)
if arg.a:
max_results = 0 # no max
else:
max_results = len(names)

# We have to read more than one line if there is a line continuation (and
# it's not -r).
Expand Down Expand Up @@ -555,13 +559,16 @@ def Read(argv, splitter, mem):
if done:
break

for i in xrange(max_results):
try:
s = parts[i]
except IndexError:
s = '' # if there are too many variables
#log('read: %s = %s', names[i], s)
state.SetStringDynamic(mem, names[i], s)
if arg.a:
state.SetArrayDynamic(mem, arg.a, parts)
else:
for i in xrange(max_results):
try:
s = parts[i]
except IndexError:
s = '' # if there are too many variables
#log('read: %s = %s', names[i], s)
state.SetStringDynamic(mem, names[i], s)

return status

Expand Down
6 changes: 3 additions & 3 deletions spec/builtin-completion.test.sh
Expand Up @@ -331,13 +331,13 @@ eggs
ham cheese
## END

#### compgen -W uses IFS
#### compgen -W uses IFS, and delimiters are escaped with \
IFS=':%'
compgen -W 'spam:eggs%ham cheese'
compgen -W 'spam:eggs%ham cheese\:colon'
## STDOUT:
spam
eggs
ham cheese
ham cheese:colon
## END

#### Parse errors for compgen -W and complete -W
Expand Down
31 changes: 31 additions & 0 deletions spec/builtin-io.test.sh
Expand Up @@ -367,3 +367,34 @@ echo $head
ref: refs/heads/dev/andy
## END

#### read -a reads into array

# read -a is used in bash-completion
# none of these shells implement it
case $SH in
*mksh|*dash|*zsh|*/ash)
exit 2;
;;
esac

read -a myarray <<'EOF'
a b c\ d
EOF
argv.py "${myarray[@]}"

# arguments are ignored here
read -r -a array2 extra arguments <<'EOF'
a b c\ d
EOF
argv.py "${array2[@]}"
argv.py "${extra[@]}"
argv.py "${arguments[@]}"
## status: 0
## STDOUT:
['a', 'b', 'c d']
['a', 'b', 'c\\', 'd']
[]
[]
## END
## N-I dash/mksh/zsh/ash status: 2
## N-I dash/mksh/zsh/ash stdout-json: ""

0 comments on commit 4871250

Please sign in to comment.