Skip to content

Commit

Permalink
[builtin/complete] Stub for complete -C
Browse files Browse the repository at this point in the history
So we can source testdata/completion/quoting.bash

Now we can see our extra quoting.
  • Loading branch information
Andy C committed Sep 11, 2023
1 parent 8b38f3c commit ac92e9d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
13 changes: 13 additions & 0 deletions core/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,19 @@ def Matches(self, comp):
yield path


class CommandAction(CompletionAction):

def __init__(self, cmd_ev, command_name):
# type: (CommandEvaluator, str) -> None
self.cmd_ev = cmd_ev
self.command_name = command_name

def Matches(self, comp):
# type: (Api) -> Iterator[str]
for candidate in ['TODO-complete-C']:
yield candidate


class ShellFuncAction(CompletionAction):
"""Call a user-defined function using bash's completion protocol."""

Expand Down
4 changes: 4 additions & 0 deletions frontend/flag_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ def _DefineCompletionFlags(spec):
# type: (_FlagSpecAndMore) -> None
spec.ShortFlag('-F', args.String, help='Complete with this function')
spec.ShortFlag('-W', args.String, help='Complete with these words')
spec.ShortFlag('-C', args.String,
help='Complete with stdout lines of this command')

spec.ShortFlag(
'-P',
args.String,
Expand Down Expand Up @@ -339,6 +342,7 @@ def _DefineCompletionActions(spec):
COMPLETE_SPEC.ShortFlag('-E', help='Define the compspec for an empty line')
COMPLETE_SPEC.ShortFlag(
'-D', help='Define the compspec that applies when nothing else matches')

# I would like this to be less compatible
# Field name conflicts with 'print' keyword
#COMPLETE_SPEC.LongFlag(
Expand Down
28 changes: 20 additions & 8 deletions osh/builtin_comp.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from core import vm
from data_lang import qsn
from mycpp import mylib
from mycpp.mylib import log
from mycpp.mylib import log, print_stderr
from frontend import flag_spec
from frontend import args
from frontend import consts
Expand Down Expand Up @@ -125,7 +125,11 @@ def __init__(

def Build(self, argv, attrs, base_opts):
# type: (List[str], _Attributes, Dict[str, bool]) -> UserSpec
"""Given flags to complete/compgen, return a UserSpec."""
"""Given flags to complete/compgen, return a UserSpec.
Args:
argv: only used for error message
"""
cmd_ev = self.cmd_ev

# arg_types.compgen is a subset of arg_types.complete (the two users of this
Expand All @@ -139,11 +143,18 @@ def Build(self, argv, attrs, base_opts):
func_name = arg.F
func = cmd_ev.procs.get(func_name)
if func is None:
raise error.Usage('Function %r not found' % func_name,
raise error.Usage('function %r not found' % func_name,
loc.Missing)
actions.append(
completion.ShellFuncAction(cmd_ev, func, self.comp_lookup))

if arg.C is not None:
# this can be a shell FUNCTION too, not just an external command
# Honestly seems better than -F? Does it also get COMP_CWORD?
command = arg.C
actions.append(completion.CommandAction(cmd_ev, command))
print_stderr('osh warning: complete -C not implemented')

# NOTE: We need completion for -A action itself!!! bash seems to have it.
for name in attrs.actions:
if name == 'alias':
Expand Down Expand Up @@ -359,11 +370,12 @@ def Run(self, cmd_val):
# error printed above
return 2

# NOTE: Matching bash in passing dummy values for COMP_WORDS and COMP_CWORD,
# and also showing ALL COMPREPLY reuslts, not just the ones that start with
# the word to complete.
# NOTE: Matching bash in passing dummy values for COMP_WORDS and
# COMP_CWORD, and also showing ALL COMPREPLY results, not just the ones
# that start
# with the word to complete.
matched = False
comp = completion.Api('', 0, 0)
comp = completion.Api('', 0, 0) # empty string
comp.Update('compgen', to_complete, '', -1, None)
try:
for m, _ in user_spec.Matches(comp):
Expand Down Expand Up @@ -516,7 +528,7 @@ def Run(self, cmd_val):
begin = 0 if arg.begin == -1 else arg.begin
end = len(arg.c) if arg.end == -1 else arg.end

log('%r begin %d end %d', arg.c, begin, end)
#log('%r begin %d end %d', arg.c, begin, end)

# Copied from completion.ReadlineCallback
comp = completion.Api(line=arg.c, begin=begin, end=end)
Expand Down
29 changes: 28 additions & 1 deletion spec/builtin-completion.test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

## oils_failures_allowed: 2
## oils_failures_allowed: 3
## compare_shells: bash

#### complete with no args and complete -p both print completion spec
Expand Down Expand Up @@ -455,3 +455,30 @@ compgen -A builtin g
## STDOUT:
getopts
## END

#### complete -C vs. compgen -C

f() { echo foo; echo bar; }

# Bash prints warnings: -C option may not work as you expect
# -F option may not work as you expect
#
# https://unix.stackexchange.com/questions/117987/compgen-warning-c-option-not-working-as-i-expected
#
# compexport fixes this problem, because it invokves ShellFuncAction, whcih
# sets COMP_ARGV, COMP_WORDS, etc.
#
# Should we print a warning?

compgen -C f b
echo compgen=$?

complete -C f b
echo complete=$?

## STDOUT:
foo
bar
compgen=0
complete=0
## END

0 comments on commit ac92e9d

Please sign in to comment.