Exemple #1
0
    def Matches(self, comp):
        # TODO: Delete COMPREPLY here?  It doesn't seem to be defined in bash by
        # default.
        argv, comp_words = comp.GetApiInput()

        state.SetGlobalArray(self.ex.mem, 'COMP_WORDS', comp_words)
        state.SetGlobalString(self.ex.mem, 'COMP_CWORD', str(comp.index))
        state.SetGlobalString(self.ex.mem, 'COMP_LINE', comp.line)
        state.SetGlobalString(self.ex.mem, 'COMP_POINT', str(comp.end))

        self.log('Running completion function %r with arguments %s',
                 self.func.name, argv)

        status = self.ex.RunFuncForCompletion(self.func, argv)
        if status == 124:
            self.log('Got status 124 from %r', self.func.name)
            raise _RetryCompletion()

        # Lame: COMP_REPLY would follow the naming convention!
        val = state.GetGlobal(self.ex.mem, 'COMPREPLY')
        if val.tag == value_e.Undef:
            util.error('Ran function %s but COMPREPLY was not defined',
                       self.func.name)
            return []

        if val.tag != value_e.StrArray:
            log('ERROR: COMPREPLY should be an array, got %s', val)
            return []
        self.log('COMPREPLY %s', val)

        # Return this all at once so we don't have a generator.  COMPREPLY happens
        # all at once anyway.
        return val.strs
Exemple #2
0
  def Matches(self, words, index, prefix):
    # TODO:
    # - Set COMP_CWORD etc. in ex.mem -- in the global namespace I guess
    # - Then parse the reply here

    # This is like a stack code:
    # for word in words:
    #   self.ex.PushString(word)
    # self.ex.PushString('COMP_WORDS')
    # self.ex.MakeArray()

    # self.ex.PushString(str(index))
    # self.ex.PushString('COMP_CWORD')

    # TODO: Get the name instead!
    # self.ex.PushString(self.func_name)
    # self.ex.Call()  # call wit no arguments

    # self.ex.PushString('COMP_REPLY')

    # How does this one work?
    # reply = []
    # self.ex.GetArray(reply)

    state.SetGlobalArray(self.ex.mem, 'COMP_WORDS', words)
    state.SetGlobalString(self.ex.mem, 'COMP_CWORD', str(index))

    self.ex.RunFunc(self.func, [])  # call with no arguments

    # Should be COMP_REPLY to follow naming convention!  Lame.
    val = state.GetGlobal(self.ex.mem, 'COMPREPLY')
    if val.tag == value_e.Undef:
      log('COMPREPLY not defined')
      return

    if val.tag != value_e.StrArray:
      log('ERROR: COMPREPLY should be an array, got %s', val)
      return
    reply = val.strs

    print('REPLY', reply)
    #reply = ['g1', 'g2', 'h1', 'i1']
    for name in sorted(reply):
      if name.startswith(prefix):
        yield name + ' '  # full word
Exemple #3
0
    def Matches(self, comp):
        # type: (Api) -> List[str]
        # Have to clear the response every time.  TODO: Reuse the object?
        state.SetGlobalArray(self.cmd_ev.mem, 'COMPREPLY', [])

        # New completions should use COMP_ARGV, a construct specific to OSH>
        state.SetGlobalArray(self.cmd_ev.mem, 'COMP_ARGV', comp.partial_argv)

        # Old completions may use COMP_WORDS.  It is split by : and = to emulate
        # bash's behavior.
        # More commonly, they will call _init_completion and use the 'words' output
        # of that, ignoring COMP_WORDS.
        comp_words = []
        for a in comp.partial_argv:
            AdjustArg(a, [':', '='], comp_words)
        if comp.index == -1:  # cmopgen
            comp_cword = comp.index
        else:
            comp_cword = len(comp_words) - 1  # weird invariant

        state.SetGlobalArray(self.cmd_ev.mem, 'COMP_WORDS', comp_words)
        state.SetGlobalString(self.cmd_ev.mem, 'COMP_CWORD', str(comp_cword))
        state.SetGlobalString(self.cmd_ev.mem, 'COMP_LINE', comp.line)
        state.SetGlobalString(self.cmd_ev.mem, 'COMP_POINT', str(comp.end))

        argv = [comp.first, comp.to_complete, comp.prev]
        self.log('Running completion function %r with arguments %s',
                 self.func.name, argv)

        self.comp_lookup.ClearCommandsChanged()
        status = self.cmd_ev.RunFuncForCompletion(self.func, argv)
        commands_changed = self.comp_lookup.GetCommandsChanged()

        self.log('comp.first %s, commands_changed: %s', comp.first,
                 commands_changed)

        if status == 124:
            cmd = os_path.basename(comp.first)
            if cmd in commands_changed:
                self.log('Got status 124 from %r and %s commands changed',
                         self.func.name, commands_changed)
                raise _RetryCompletion()
            else:
                # This happens with my own completion scripts.  bash doesn't show an
                # error.
                self.log(
                    "Function %r returned 124, but the completion spec for %r wasn't "
                    "changed", self.func.name, cmd)
                return []

        # Read the response.
        # NOTE: 'COMP_REPLY' would follow the naming convention!
        val = state.GetGlobal(self.cmd_ev.mem, 'COMPREPLY')
        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.
            stderr_line('osh: Ran function %r but COMPREPLY was unset',
                        self.func.name)
            return []

        if val.tag_() != value_e.MaybeStrArray:
            log('ERROR: COMPREPLY should be an array, got %s', val)
            return []
        self.log('COMPREPLY %s', val)

        # Return this all at once so we don't have a generator.  COMPREPLY happens
        # all at once anyway.
        return val.strs