Exemplo n.º 1
0
    def Matches(self, comp):
        # Have to clear the response every time.  TODO: Reuse the object?
        state.SetGlobalArray(self.ex.mem, 'COMPREPLY', [])

        # New completions should use COMP_ARGV, a construct specific to OSH>
        state.SetGlobalArray(self.ex.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.ex.mem, 'COMP_WORDS', comp_words)
        state.SetGlobalString(self.ex.mem, 'COMP_CWORD', str(comp_cword))
        state.SetGlobalString(self.ex.mem, 'COMP_LINE', comp.line)
        state.SetGlobalString(self.ex.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)

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

        # Read the response.  We set it above, so this error would only happen if
        # the user unset it.
        # NOTE: '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
Exemplo n.º 2
0
  def Matches(self, comp):
    # Have to clear the response every time.  TODO: Reuse the object?
    state.SetGlobalArray(self.ex.mem, 'COMPREPLY', [])

    # New completions should use COMP_ARGV, a construct specific to OSH>
    state.SetGlobalArray(self.ex.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.ex.mem, 'COMP_WORDS', comp_words)
    state.SetGlobalString(self.ex.mem, 'COMP_CWORD', str(comp_cword))
    state.SetGlobalString(self.ex.mem, 'COMP_LINE', comp.line)
    state.SetGlobalString(self.ex.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.ex.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.ex.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.
      ui.Stderr('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