Skip to content

Commit

Permalink
Allow getopts to handle explicit arguments, rather than "$@".
Browse files Browse the repository at this point in the history
bash-completion uses this in _init_completion.
  • Loading branch information
Andy Chu committed Sep 24, 2018
1 parent 4d9f167 commit fd45ed1
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 14 deletions.
20 changes: 9 additions & 11 deletions core/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1245,15 +1245,13 @@ def _ParseOptSpec(spec_str):
return spec


def _GetOpts(spec, mem, optind):
def _GetOpts(spec, argv, optind):
optarg = '' # not set by default

v2 = mem.GetArgNum(optind)
if v2.tag == value_e.Undef: # No more arguments.
try:
current = argv[optind-1] # 1-based indexing
except IndexError:
return 1, '?', optarg, optind
assert v2.tag == value_e.Str

current = v2.s

if not current.startswith('-'): # The next arg doesn't look like a flag.
return 1, '?', optarg, optind
Expand All @@ -1268,14 +1266,13 @@ def _GetOpts(spec, mem, optind):

needs_arg = spec[current]
if needs_arg:
v3 = mem.GetArgNum(optind)
if v3.tag == value_e.Undef:
try:
optarg = argv[optind-1] # 1-based indexing
except IndexError:
util.error('getopts: option %r requires an argument', current)
# Hm doesn't cause status 1?
return 0, '?', optarg, optind
assert v3.tag == value_e.Str

optarg = v3.s
optind += 1

return 0, opt_char, optarg, optind
Expand Down Expand Up @@ -1318,7 +1315,8 @@ def GetOpts(argv, mem):
except ValueError:
e_die("OPTIND doesn't look like an integer, got %r", v.s)

status, opt_char, optarg, optind = _GetOpts(spec, mem, optind)
user_argv = argv[2:] or mem.GetArgv()
status, opt_char, optarg, optind = _GetOpts(spec, user_argv, optind)

state.SetGlobalString(mem, var_name, opt_char)
state.SetGlobalString(mem, 'OPTARG', optarg)
Expand Down
7 changes: 5 additions & 2 deletions spec/builtin-getopts.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,21 @@ echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
## stdout: h=0 c= optind=1 argv=x -h -c y

#### getopts with explicit args
# NOTE: Alpine doesn't appear to use this
# NOTE: Alpine doesn't appear to use this, but bash-completion does.
FLAG_h=0
FLAG_c=''
arg=''
set -- A B C
while getopts "hc:" opt -h -c foo x y z; do
case $opt in
h) FLAG_h=1 ;;
c) FLAG_c="$OPTARG" ;;
esac
done
echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
## stdout: h=1 c=foo optind=4 argv=
## STDOUT:
h=1 c=foo optind=4 argv=A B C
## END

#### OPTIND
echo $OPTIND
Expand Down
2 changes: 1 addition & 1 deletion test/spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ builtin-vars() {
}

builtin-getopts() {
sh-spec spec/builtin-getopts.test.sh --osh-failures-allowed 1 \
sh-spec spec/builtin-getopts.test.sh \
${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
}

Expand Down

0 comments on commit fd45ed1

Please sign in to comment.