Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core/completion] Support scalar COMPREPLY with compgen -F #2212

Merged
merged 2 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 25 additions & 15 deletions core/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from _devbuild.gen.runtime_asdl import (scope_e, comp_action_e, comp_action_t)
from _devbuild.gen.types_asdl import redir_arg_type_e
from _devbuild.gen.value_asdl import (value, value_e)
from core import bash_impl
from core import error
from core import pyos
from core import state
Expand All @@ -51,7 +52,7 @@
from frontend import location
from frontend import reader
from mycpp import mylib
from mycpp.mylib import print_stderr, iteritems, log
from mycpp.mylib import iteritems, log, print_stderr, tagswitch
from osh.string_ops import ShellQuoteB
from osh import word_
from pylib import os_path
Expand Down Expand Up @@ -619,25 +620,34 @@ def Matches(self, comp):
# Read the response. (The name 'COMP_REPLY' would be more consistent with others.)
val = self.cmd_ev.mem.GetValue('COMPREPLY', scope_e.GlobalOnly)

if val.tag() == value_e.Undef:
# We set it above, so this error would only happen if the user 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)
return
UP_val = val
with tagswitch(val) as case:
if case(value_e.Undef):
# We set it above, so this error would only happen if the user
# 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)
return

if val.tag() != value_e.BashArray:
print_stderr('osh error: COMPREPLY should be an array, got %s' %
ui.ValType(val))
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)

else:
print_stderr('osh error: COMPREPLY should be an array or a string, got %s' %
ui.ValType(val))
return

if 0:
self.debug('> %r' % val) # CRASHES in C++

array_val = cast(value.BashArray, val)
for s in array_val.strs:
for s in strs:
#self.debug('> %r' % s)
yield s

Expand Down
13 changes: 13 additions & 0 deletions spec/builtin-completion.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -625,3 +625,16 @@ argv.py "${words[@]}"

## N-I bash STDOUT:
## END


#### compgen -F with scalar COMPREPLY

_comp_cmd_test() {
unset -v COMPREPLY
COMPREPLY=hello
}
compgen -F _comp_cmd_test

## STDOUT:
hello
## END