diff --git a/builtin/completion_osh.py b/builtin/completion_osh.py index 8dc8a8e7e..65125e904 100644 --- a/builtin/completion_osh.py +++ b/builtin/completion_osh.py @@ -5,6 +5,7 @@ from _devbuild.gen.syntax_asdl import loc from _devbuild.gen.value_asdl import (value, value_e) +from core import bash_impl from core import completion from core import error from core import state @@ -454,9 +455,13 @@ def Run(self, cmd_val): # TODO: How does the user test a completion function programmatically? Set # COMP_ARGV? val = self.mem.GetValue('COMP_ARGV') - if val.tag() != value_e.BashArray: + if val.tag() == value_e.BashArray: + comp_argv = cast(value.BashArray, val).strs + elif val.tag() == value_e.SparseArray: + comp_argv = bash_impl.SparseArray_GetValues( + cast(value.SparseArray, val)) + else: raise error.Usage("COMP_ARGV should be an array", loc.Missing) - comp_argv = cast(value.BashArray, val).strs # These are the ones from COMP_WORDBREAKS that we care about. The rest occur # "outside" of words. diff --git a/core/completion.py b/core/completion.py index 4601712a6..2789c99cf 100755 --- a/core/completion.py +++ b/core/completion.py @@ -627,21 +627,23 @@ def Matches(self, comp): # unset it. Not changing it means there were no completions. # TODO: This writes over the command line; it would be better # to use an error object. - print_stderr('osh error: Ran function %r but COMPREPLY was unset' % - self.func.name) + print_stderr( + 'osh error: Ran function %r but COMPREPLY was unset' % + self.func.name) return - elif case(value_e.Str): val = cast(value.Str, UP_val) strs = [val.s] - elif case(value_e.BashArray): val = cast(value.BashArray, UP_val) strs = bash_impl.BashArray_GetValues(val) - + elif case(value_e.SparseArray): + val = cast(value.SparseArray, UP_val) + strs = bash_impl.SparseArray_GetValues(val) else: - print_stderr('osh error: COMPREPLY should be an array or a string, got %s' % - ui.ValType(val)) + print_stderr( + 'osh error: COMPREPLY should be an array or a string, got %s' + % ui.ValType(val)) return if 0: diff --git a/spec/ble-idioms.test.sh b/spec/ble-idioms.test.sh index 95bae8767..fc14f0eac 100644 --- a/spec/ble-idioms.test.sh +++ b/spec/ble-idioms.test.sh @@ -1064,6 +1064,55 @@ echo "[${a[@]: -4}][${a[*]: -4}]" ## END +#### SparseArray: compgen -F _set_COMPREPLY +case $SH in zsh|mksh|ash) exit ;; esac + +a=({0..9}) +unset -v 'a[2]' 'a[4]' 'a[6]' + +case ${SH##*/} in +osh) + eval '_set_COMPREPLY() { setglobal COMPREPLY = _a2sp(a); }' + ;; +*) + _set_COMPREPLY() { COMPREPLY=("${a[@]}"); } + ;; +esac + +compgen -F _set_COMPREPLY + +## STDOUT: +0 +1 +3 +5 +7 +8 +9 +## END + +## N-I zsh/mksh/ash STDOUT: +## END + + +#### SparseArray: compgen -F _set_COMPREPLY +case $SH in bash|zsh|mksh|ash) exit ;; esac + +a=(echo 'Hello,' 'Bash' 'world!') +var COMP_ARGV = _a2sp(a) +compadjust cur prev words cword +argv.py "$cur" "$prev" "$cword" +argv.py "${words[@]}" + +## STDOUT: +['world!', 'Bash', '3'] +['echo', 'Hello,', 'Bash', 'world!'] +## END + +## N-I bash/zsh/mksh/ash STDOUT: +## END + + #### SparseArray (YSH): $[a1 === a2] case $SH in bash|zsh|mksh|ash) exit ;; esac