def testUserSpec(self): comp = self._CompApi(['f'], 0, 'f') matches = list(U1.Matches(comp)) self.assertEqual([('foo.py', False), ('foo', False)], matches) predicate = completion.GlobPredicate(False, '*.py') c2 = completion.UserSpec([A1], [], [], predicate) comp = self._CompApi(['f'], 0, 'f') matches = list(c2.Matches(comp)) self.assertEqual([('foo.py', False)], matches)
def _InitDefaultCompletions(ex, complete_builtin, comp_lookup): # register builtins and words complete_builtin(['-E', '-A', 'command']) # register path completion # Add -o filenames? Or should that be automatic? complete_builtin(['-D', '-A', 'file']) # TODO: Move this into demo/slow-completion.sh if 1: # Something for fun, to show off. Also: test that you don't repeatedly hit # the file system / network / coprocess. A1 = completion.TestAction(['foo.py', 'foo', 'bar.py']) A2 = completion.TestAction(['m%d' % i for i in xrange(5)], delay=0.1) C1 = completion.UserSpec([A1, A2], [], [], lambda candidate: True) comp_lookup.RegisterName('slowc', {}, C1)
def Build(self, argv, arg, base_opts): """Given flags to complete/compgen, return a UserSpec.""" cmd_ev = self.cmd_ev actions = [] # NOTE: bash doesn't actually check the name until completion time, but # obviously it's better to check here. if arg.F: func_name = arg.F func = cmd_ev.procs.get(func_name) if func is None: raise error.Usage('Function %r not found' % func_name) actions.append( completion.ShellFuncAction(cmd_ev, func, self.comp_lookup)) # NOTE: We need completion for -A action itself!!! bash seems to have it. for name in arg.actions: if name == 'alias': a = _FixedWordsAction(self.parse_ctx.aliases) elif name == 'binding': # TODO: Where do we get this from? a = _FixedWordsAction(['vi-delete']) elif name == 'command': # compgen -A command in bash is SIX things: aliases, builtins, # functions, keywords, external commands relative to the current # directory, and external commands in $PATH. actions.append(_FixedWordsAction(consts.BUILTIN_NAMES)) actions.append(_FixedWordsAction(self.parse_ctx.aliases)) actions.append(_FixedWordsAction(cmd_ev.procs)) actions.append(_FixedWordsAction(lexer_def.OSH_KEYWORD_NAMES)) actions.append(completion.FileSystemAction(exec_only=True)) # Look on the file system. a = completion.ExternalCommandAction(cmd_ev.mem) elif name == 'directory': a = completion.FileSystemAction(dirs_only=True) elif name == 'file': a = completion.FileSystemAction() elif name == 'function': a = _FixedWordsAction(cmd_ev.procs) elif name == 'job': a = _FixedWordsAction(['jobs-not-implemented']) elif name == 'user': a = completion.UsersAction() elif name == 'variable': a = completion.VariablesAction(cmd_ev.mem) elif name == 'helptopic': # Note: it would be nice to have 'helpgroup' for help -i too a = _FixedWordsAction(help_.TOPICS) elif name == 'setopt': names = [ opt.name for opt in option_def.All() if opt.builtin == 'set' ] a = _FixedWordsAction(names) elif name == 'shopt': names = [ opt.name for opt in option_def.All() if opt.builtin == 'shopt' ] a = _FixedWordsAction(names) elif name == 'signal': a = _FixedWordsAction(['TODO:signals']) elif name == 'stopped': a = _FixedWordsAction(['jobs-not-implemented']) else: raise NotImplementedError(name) actions.append(a) # e.g. -W comes after -A directory if arg.W is not None: # could be '' # NOTES: # - Parsing is done at REGISTRATION time, but execution and splitting is # done at COMPLETION time (when the user hits tab). So parse errors # happen early. w_parser = self.parse_ctx.MakeWordParserForPlugin(arg.W) arena = self.parse_ctx.arena try: arg_word = w_parser.ReadForPlugin() except error.Parse as e: ui.PrettyPrintError(e, arena) raise # Let 'complete' or 'compgen' return 2 a = completion.DynamicWordsAction(self.word_ev, self.splitter, arg_word, arena) actions.append(a) extra_actions = [] if base_opts.get('plusdirs'): extra_actions.append(completion.FileSystemAction(dirs_only=True)) # These only happen if there were zero shown. else_actions = [] if base_opts.get('default'): else_actions.append(completion.FileSystemAction()) if base_opts.get('dirnames'): else_actions.append(completion.FileSystemAction(dirs_only=True)) if not actions and not else_actions: raise error.Usage('No actions defined in completion: %s' % argv) p = completion.DefaultPredicate if arg.X: filter_pat = arg.X if filter_pat.startswith('!'): p = completion.GlobPredicate(False, filter_pat[1:]) else: p = completion.GlobPredicate(True, filter_pat) return completion.UserSpec(actions, extra_actions, else_actions, p, prefix=arg.P or '', suffix=arg.S or '')
from core import completion # module under test from core import comp_ui from core import test_lib from core import util from core.meta import runtime_asdl, syntax_asdl from frontend import parse_lib from osh import state from testdata.completion import bash_oracle assign_op_e = syntax_asdl.assign_op_e value_e = runtime_asdl.value_e log = util.log A1 = completion.TestAction(['foo.py', 'foo', 'bar.py']) U1 = completion.UserSpec([A1], [], [], lambda candidate: True) BASE_OPTS = {} mem = state.Mem('', [], {}, None) FIRST = completion.TestAction(['grep', 'sed', 'test']) U2 = completion.UserSpec([FIRST], [], [], lambda candidate: True) def MockApi(line): """Match readline's get_begidx() / get_endidx().""" return completion.Api(line=line, begin=0, end=len(line)) def _MakeRootCompleter(parse_ctx=None, comp_lookup=None):
def Build(self, argv, arg, base_opts): """Given flags to complete/compgen, return a UserSpec.""" ex = self.ex actions = [] # NOTE: bash doesn't actually check the name until completion time, but # obviously it's better to check here. if arg.F: func_name = arg.F func = ex.funcs.get(func_name) if func is None: raise args.UsageError('Function %r not found' % func_name) actions.append( completion.ShellFuncAction(ex, func, self.comp_lookup)) # NOTE: We need completion for -A action itself!!! bash seems to have it. for name in arg.actions: if name == 'alias': a = _FixedWordsAction(ex.aliases) elif name == 'binding': # TODO: Where do we get this from? a = _FixedWordsAction(['vi-delete']) elif name == 'command': # compgen -A command in bash is SIX things: aliases, builtins, # functions, keywords, external commands relative to the current # directory, and external commands in $PATH. actions.append(_FixedWordsAction(builtin.BUILTIN_NAMES)) actions.append(_FixedWordsAction(ex.aliases)) actions.append(_FixedWordsAction(ex.funcs)) actions.append(_FixedWordsAction(lex.OSH_KEYWORD_NAMES)) actions.append(completion.FileSystemAction(exec_only=True)) # Look on the file system. a = completion.ExternalCommandAction(ex.mem) elif name == 'directory': a = completion.FileSystemAction(dirs_only=True) elif name == 'file': a = completion.FileSystemAction() elif name == 'function': a = _FixedWordsAction(ex.funcs) elif name == 'job': a = _FixedWordsAction(['jobs-not-implemented']) elif name == 'user': a = completion.UsersAction() elif name == 'variable': a = completion.VariablesAction(ex.mem) elif name == 'helptopic': a = _FixedWordsAction(osh_help.TOPIC_LOOKUP) elif name == 'setopt': a = _FixedWordsAction(state.SET_OPTION_NAMES) elif name == 'shopt': a = _FixedWordsAction(state.SHOPT_OPTION_NAMES) elif name == 'signal': a = _FixedWordsAction(['TODO:signals']) elif name == 'stopped': a = _FixedWordsAction(['jobs-not-implemented']) else: raise NotImplementedError(name) actions.append(a) # e.g. -W comes after -A directory if arg.W is not None: # could be '' # NOTES: # - Parsing is done at REGISTRATION time, but execution and splitting is # done at COMPLETION time (when the user hits tab). So parse errors # happen early. # - It's OK to reuse the same arena because this doesn't happen during # translation. TODO: But we need PushSource(). We should # create SideArena instances that track back to the current location of # the 'complete' builtin. arena = self.parse_ctx.arena w_parser = self.parse_ctx.MakeWordParserForPlugin(arg.W, arena) try: arg_word = w_parser.ReadForPlugin() except util.ParseError as e: ui.PrettyPrintError(e, self.parse_ctx.arena) raise # Let 'complete' or 'compgen' return 2 a = completion.DynamicWordsAction(self.word_ev, self.splitter, arg_word, arena) actions.append(a) extra_actions = [] if base_opts.get('plusdirs'): extra_actions.append(completion.FileSystemAction(dirs_only=True)) # These only happen if there were zero shown. else_actions = [] if base_opts.get('default'): else_actions.append(completion.FileSystemAction()) if base_opts.get('dirnames'): else_actions.append(completion.FileSystemAction(dirs_only=True)) if not actions and not else_actions: raise args.UsageError('No actions defined in completion: %s' % argv) p = completion.DefaultPredicate if arg.X: filter_pat = arg.X if filter_pat.startswith('!'): p = completion.GlobPredicate(False, filter_pat[1:]) else: p = completion.GlobPredicate(True, filter_pat) return completion.UserSpec(actions, extra_actions, else_actions, p, prefix=arg.P or '', suffix=arg.S or '')
def _BuildUserSpec(argv, arg, comp_opts, ex, respect_x=True): """Given flags to complete/compgen, built a UserSpec. Args: respect_x: Stupid special case because bash doesn't respect -X in compgen. """ actions = [] # NOTE: bash doesn't actually check the name until completion time, but # obviously it's better to check here. if arg.F: func_name = arg.F func = ex.funcs.get(func_name) if func is None: raise args.UsageError('Function %r not found' % func_name) actions.append(completion.ShellFuncAction(ex, func)) # NOTE: We need completion for -A action itself!!! bash seems to have it. for name in arg.actions: if name == 'alias': a = _SortedWordsAction(ex.aliases) elif name == 'binding': # TODO: Where do we get this from? a = _SortedWordsAction(['vi-delete']) elif name == 'command': # compgen -A command in bash is SIX things: aliases, builtins, # functions, keywords, external commands relative to the current # directory, and external commands in $PATH. actions.append(_SortedWordsAction(builtin.BUILTIN_NAMES)) actions.append(_SortedWordsAction(ex.aliases)) actions.append(_SortedWordsAction(ex.funcs)) actions.append(_SortedWordsAction(lex.OSH_KEYWORD_NAMES)) actions.append(completion.FileSystemAction(exec_only=True)) # Look on the file system. a = completion.ExternalCommandAction(ex.mem) elif name == 'directory': a = completion.FileSystemAction(dirs_only=True) elif name == 'file': a = completion.FileSystemAction() elif name == 'function': a = _SortedWordsAction(ex.funcs) elif name == 'job': a = _SortedWordsAction(['jobs-not-implemented']) elif name == 'user': a = _UsersAction() elif name == 'variable': a = completion.VariablesAction(ex.mem) elif name == 'helptopic': a = _SortedWordsAction(osh_help.TOPIC_LOOKUP) elif name == 'setopt': a = _SortedWordsAction(state.SET_OPTION_NAMES) elif name == 'shopt': a = _SortedWordsAction(state.SHOPT_OPTION_NAMES) elif name == 'signal': a = _SortedWordsAction(['TODO:signals']) elif name == 'stopped': a = _SortedWordsAction(['jobs-not-implemented']) else: raise NotImplementedError(name) actions.append(a) # e.g. -W comes after -A directory if arg.W: # TODO: Split with IFS. Is that done at registration time or completion # time? actions.append(completion.WordsAction(arg.W.split())) extra_actions = [] if comp_opts.Get('plusdirs'): extra_actions.append(completion.FileSystemAction(dirs_only=True)) # These only happen if there were zero shown. else_actions = [] if comp_opts.Get('default'): else_actions.append(completion.FileSystemAction()) if comp_opts.Get('dirnames'): else_actions.append(completion.FileSystemAction(dirs_only=True)) if not actions and not else_actions: raise args.UsageError('No actions defined in completion: %s' % argv) p = lambda candidate: True # include all if respect_x and arg.X: filter_pat = arg.X if filter_pat.startswith('!'): p = completion.GlobPredicate(False, filter_pat[1:]) else: p = completion.GlobPredicate(True, filter_pat) return completion.UserSpec(actions, extra_actions, else_actions, p, prefix=arg.P or '', suffix=arg.S or '')