Example #1
0
def ParseLine(line):
    """Parse a gcloud command line.

  Args:
    line: a string containing one or more gcloud invocations

  Returns:
    A list of GcloudInvocations, one for each command in the line (delimited by
    terminators).
  """
    sh_tokens = lexer.GetShellTokens(line)
    if not sh_tokens:
        return []

    parsed_line = []
    current_invocation = []

    # Separate parsed line into invocations based on terminators
    while sh_tokens:
        current_token = sh_tokens.pop(0)
        if TokenIsArgument(current_token):
            current_invocation.append(current_token)
        elif TokenIsTerminator(current_token):
            parsed_line.append(GcloudInvocation(ParseArgs(current_invocation)))
            current_invocation = []
        else:
            # Ignore the rest of the current invocation if the token is not of type
            # ShellTokenType.ARG (that is, if it's of type IO, REDIRECTION, FILE or
            # TRAILING_BACKSLASH)
            while sh_tokens:
                if TokenIsTerminator(sh_tokens.pop(0)):
                    break
    # Add the last current_invocation
    parsed_line.append(GcloudInvocation(ParseArgs(current_invocation)))
    return parsed_line
Example #2
0
def ParseLine(line):
  """Parse a gcloud command line.

  Args:
    line: a string containing a gcloud command

  Returns:
    A list of ArgTokens.
  """
  sh_tokens = lexer.GetShellTokens(line)
  if not sh_tokens:
    return []

  # Cut off at first non-arg token
  i = 0
  while i < len(sh_tokens):
    if not TokenIsArgument(sh_tokens[i]):
      break
    i += 1
  sh_tokens = sh_tokens[:i]

  return ParseArgs(sh_tokens)
Example #3
0
    def get_completions(self, doc, complete_event):
        """Yields the completions for doc.

    Args:
      doc: A Document instance containing the shell command line to complete.
      complete_event: The CompleteEvent that triggered this completion.

    Yields:
      Completion instances for doc.
    """
        tokens = lexer.GetShellTokens(doc.text_before_cursor)
        if not tokens:
            return
        if tokens[0].value != 'gcloud':
            gcloud_token = lexer.ShellToken('gcloud',
                                            lex=lexer.ShellTokenType.ARG,
                                            start=0,
                                            end=0)
            tokens = ([gcloud_token] + tokens)
        node = self.root
        info = None
        last = ''
        path = []
        i = 0

        # Autocomplete commands and groups after spaces.
        if doc.text_before_cursor and doc.text_before_cursor[-1].isspace():
            for completion in CompleteCommandGroups(tokens):
                yield Completion(completion)
            return

        # If there is a terminator, do not complete.
        for token in tokens:
            if token.lex == lexer.ShellTokenType.TERMINATOR:
                return

        # Traverse the cli tree.
        while i < len(tokens):
            token = tokens[i]
            if token.lex == lexer.ShellTokenType.ARG and token.value.startswith(
                    '-'):
                if i == len(tokens) - 1:
                    last = token.value
            elif token.value in node:
                info = node[token.value]
                path.append(info)
                node = info.get('commands', {})
            else:
                break
            i += 1

        last = tokens[-1].value

        offset = -len(last)

        # Check for flags.
        if last.startswith('-') and info:
            # Collect all non-hidden flags of current command and parents into node.
            node = FilterHiddenFlags(info.get('flags', {}))
            for info in path:
                node.update(FilterHiddenFlags(info.get('flags', {})))

            value = last.find('=')
            if value > 0:
                if doc.text_before_cursor[-1].isspace():
                    return
                name = last[:value]
            else:
                name = last
            if name in node:
                info = node[name]
                if info.get('type', None) != 'bool':
                    choices = info.get('choices', None)
                    if choices:
                        # A flag with static choices.
                        prefix = last
                        if value < 0:
                            prefix += '='
                            offset -= 1
                        for choice in choices:
                            yield Completion(name + '=' + choice, offset)
                return

        def _MetaTextForChoice(choice):
            if (self.experimental_autocomplete_enabled
                    and FlagIsRequired(node[choice])):
                return 'required'

        ranked_completions = []
        if self.experimental_autocomplete_enabled:
            ranked_completions = RankedCompletions(node, doc)
        else:
            ranked_completions = sorted(node)

        for choice in ranked_completions:
            if choice.startswith(last):
                yield Completion(choice,
                                 offset,
                                 display_meta=_MetaTextForChoice(choice))
Example #4
0
    def get_completions(self, doc, complete_event):
        """Yields the completions for doc.

    Args:
      doc: A Document instance containing the shell command line to complete.
      complete_event: The CompleteEvent that triggered this completion.

    Yields:
      Completion instances for doc.
    """
        tokens = lexer.GetShellTokens(doc.text_before_cursor)
        if not tokens:
            return
        # TODO(user): rewrite without virtual "gcloud" token
        gcloud_token = lexer.ShellToken('gcloud',
                                        lex=lexer.ShellTokenType.ARG,
                                        start=0,
                                        end=0)
        tokens = ([gcloud_token] + tokens)
        node = self.root
        info = None
        last = ''
        path = []
        i = 0

        # Autocomplete commands and groups after spaces.
        if doc.text_before_cursor and doc.text_before_cursor[-1].isspace():
            for completion in CompleteCommandGroups(tokens):
                yield Completion(completion)
            return

        # Traverse the cli tree.
        while i < len(tokens):
            token = tokens[i]
            if token.lex == lexer.ShellTokenType.FLAG:
                if i == len(tokens) - 1:
                    last = token.value
            elif token.value in node:
                info = node[token.value]
                path.append(info)
                node = info.get('commands', {})
            else:
                while (i < len(tokens)
                       and tokens[i].lex != lexer.ShellTokenType.TERMINATOR):
                    i += 1
                if i >= len(tokens):
                    last = token.value
                    break
                node = self.root
                info = None
                path = []
            i += 1

        # Bail if no completions.
        if i < len(tokens) or not last:
            return

        offset = -len(last)

        # Check for flags.
        if last.startswith('-') and info:
            node = info.get('flags', {})
            for info in path:
                node.update(info.get('flags', {}))
            value = last.find('=')
            if value > 0:
                if doc.text_before_cursor[-1].isspace():
                    return
                name = last[:value]
            else:
                name = last
            if name in node:
                info = node[name]
                if info.get('type', None) != 'bool':
                    choices = info.get('choices', None)
                    if choices:
                        # A flag with static choices.
                        prefix = last
                        if value < 0:
                            prefix += '='
                            offset -= 1
                        for choice in choices:
                            yield Completion(name + '=' + choice, offset)
                return

        # Check for subcommands.
        for choice in sorted(node):
            if choice.startswith(last):
                yield Completion(choice, offset)