Exemple #1
0
    def testShellFuncExecution(self):
        ex = cmd_exec_test.InitExecutor()
        func_node = ast.FuncDef()

        c1 = ast.CompoundWord()
        t1 = ast.token(Id.Lit_Chars, 'f1')
        c1.parts.append(ast.LiteralPart(t1))

        c2 = ast.CompoundWord()
        t2 = ast.token(Id.Lit_Chars, 'f2')
        c2.parts.append(ast.LiteralPart(t2))

        a = ast.ArrayLiteralPart()
        a.words = [c1, c2]
        w = ast.CompoundWord()
        w.parts.append(a)

        # Set global COMPREPLY=(f1 f2)
        pair = ast.assign_pair(ast.LhsName('COMPREPLY'), assign_op_e.Equal, w)
        pair.spids.append(0)  # dummy
        pairs = [pair]
        body_node = ast.Assignment(Id.Assign_None, [], pairs)

        func_node.name = 'myfunc'
        func_node.body = body_node

        a = completion.ShellFuncAction(ex, func_node)
        matches = list(a.Matches([], 0, 'f'))
        self.assertEqual(['f1 ', 'f2 '], matches)
Exemple #2
0
  def testShellFuncExecution(self):
    arena, c_parser = cmd_parse_test.InitCommandParser("""\
    f() {
      COMPREPLY=(f1 f2)
    }
    """)
    func_node = c_parser.ParseLogicalLine()
    print(func_node)

    ex = cmd_exec_test.InitExecutor(arena=arena)

    a = completion.ShellFuncAction(ex, func_node)
    comp = self._MakeComp(['f'], 0, 'f')
    matches = list(a.Matches(comp))
    self.assertEqual(['f1', 'f2'], matches)
Exemple #3
0
  def testShellFuncExecution(self):
    arena = test_lib.MakeArena('testShellFuncExecution')
    c_parser = test_lib.InitCommandParser("""\
    f() {
      COMPREPLY=(f1 f2)
    }
    """, arena=arena)
    node = c_parser.ParseLogicalLine()
    proc = Proc(node.name, node.spids[1], proc_sig.Open(), node.body, [], True)

    cmd_ev = test_lib.InitCommandEvaluator(arena=arena)

    comp_lookup = completion.Lookup()
    a = completion.ShellFuncAction(cmd_ev, proc, comp_lookup)
    comp = self._CompApi(['f'], 0, 'f')
    matches = list(a.Matches(comp))
    self.assertEqual(['f1', 'f2'], matches)
Exemple #4
0
    def testShellFuncExecution(self):
        arena = test_lib.MakeArena('testShellFuncExecution')
        c_parser = test_lib.InitCommandParser("""\
    f() {
      COMPREPLY=(f1 f2)
    }
    """,
                                              arena=arena)
        func_node = c_parser.ParseLogicalLine()
        print(func_node)

        ex = test_lib.InitExecutor(arena=arena)

        comp_lookup = completion.Lookup()
        a = completion.ShellFuncAction(ex, func_node, comp_lookup)
        comp = self._CompApi(['f'], 0, 'f')
        matches = list(a.Matches(comp))
        self.assertEqual(['f1', 'f2'], matches)
Exemple #5
0
    def _Complete(self, argv):
        # TODO: Parse flags?  How?
        # opts = self.builtins.Parse(EBuiltin.COMPLETE, argv)

        command = argv[1]  # e.g. 'grep'
        func_name = argv[2]

        # NOTE: bash doesn't actually check the name until completion time, but
        # obviously it's better to check here.
        func = self.funcs.get(func_name)
        if func is None:
            print('Function %r not found' % func_name)
            return 1

        chain = completion.ShellFuncAction(self, func)
        self.comp_lookup.RegisterName(command, chain)
        # TODO: Some feedback would be nice?
        return 0
    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 '')
Exemple #7
0
    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 '')
Exemple #8
0
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 '')
Exemple #9
0
def _BuildCompletionChain(argv, arg, ex):
  """Given flags to complete/compgen, built a ChainedCompleter."""
  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':
      # TODO: This needs keywords too
      actions.append(_SortedWordsAction(builtin.BUILTIN_NAMES))

      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()))

  if not actions:
    raise args.UsageError('No actions defined in completion: %s' % argv)

  chain = completion.ChainedCompleter(
      actions,
      prefix=arg.P or '',
      suffix=arg.S or '')

  return chain