def get_completions(self, document, complete_event):
     text_before_cursor = document.text_before_cursor
     completions = self._completer.autocomplete(text_before_cursor)
     prompt_completions = list(
         self._convert_to_prompt_completions(completions,
                                             text_before_cursor))
     if (not prompt_completions and self._completer.last_option
             and len(self._completer.cmd_path) == 3):
         # If we couldn't complete anything from the JSON model
         # completer and we're on a cli option (e.g --foo), we
         # can ask the server side completer if it knows anything
         # about this resource.
         LOG.debug("No local autocompletions found, trying "
                   "server side completion.")
         command = self._completer.cmd_path
         service = command[1]
         if service == 's3api':
             # TODO: we need a more generic way to capture renames
             # of commands.  This currently lives in the CLI
             # customization code.
             service = 's3'
         operation = command[2]
         param = self._completer.arg_metadata.get(
             self._completer.last_option, {}).get('api_name')
         if param is not None:
             LOG.debug(
                 "Trying to retrieve autcompletion for: "
                 "%s, %s, %s", service, operation, param)
             results = self._server_side_completer\
                 .retrieve_candidate_values(service, operation, param)
             LOG.debug("Results for %s, %s, %s: %s", service, operation,
                       param, results)
             word_before_cursor = text_before_cursor.strip().split()[-1]
             location = 0
             if text_before_cursor[-1] != ' ' and \
                     word_before_cursor and results:
                 # Filter the results down by fuzzy searching what
                 # the user has provided.
                 results = fuzzy.fuzzy_search(word_before_cursor, results)
                 location = -len(word_before_cursor)
             if results is not None:
                 for result in results:
                     # Insert at the end
                     yield Completion(result,
                                      location,
                                      display=result,
                                      display_meta='')
     else:
         for c in prompt_completions:
             yield c
Example #2
0
 def get_completions(self, document, complete_event):
     text_before_cursor = document.text_before_cursor
     completions = self._completer.autocomplete(text_before_cursor)
     prompt_completions = list(self._convert_to_prompt_completions(
         completions, text_before_cursor))
     if (not prompt_completions and self._completer.last_option and
             len(self._completer.cmd_path) == 3):
         # If we couldn't complete anything from the JSON model
         # completer and we're on a cli option (e.g --foo), we
         # can ask the server side completer if it knows anything
         # about this resource.
         LOG.debug("No local autocompletions found, trying "
                   "server side completion.")
         command = self._completer.cmd_path
         service = command[1]
         if service == 's3api':
             # TODO: we need a more generic way to capture renames
             # of commands.  This currently lives in the CLI
             # customization code.
             service = 's3'
         operation = command[2]
         param = self._completer.arg_metadata.get(
             self._completer.last_option, {}).get('api_name')
         if param is not None:
             LOG.debug("Trying to retrieve autcompletion for: "
                       "%s, %s, %s", service, operation, param)
             results = self._server_side_completer\
                 .retrieve_candidate_values(service, operation, param)
             LOG.debug("Results for %s, %s, %s: %s",
                       service, operation, param, results)
             word_before_cursor = text_before_cursor.strip().split()[-1]
             location = 0
             if text_before_cursor[-1] != ' ' and \
                     word_before_cursor and results:
                 # Filter the results down by fuzzy searching what
                 # the user has provided.
                 results = fuzzy.fuzzy_search(word_before_cursor, results)
                 location = -len(word_before_cursor)
             if results is not None:
                 for result in results:
                     # Insert at the end
                     yield Completion(result, location,
                                      display=result,
                                      display_meta='')
     else:
         for c in prompt_completions:
             yield c
Example #3
0
    def autocomplete(self, line):
        """Given a line, return a list of suggestions."""
        current_length = len(line)
        self._current_line = line
        if current_length == 1 and self._last_position > 1:
            # Reset state.  This is likely from a user completing
            # a previous command.
            self.reset()
        elif current_length < self._last_position:
            # The user has hit backspace.  We'll need to check
            # the current words.
            return self._handle_backspace()
        elif not line:
            return []
        elif current_length != self._last_position + 1:
            return self._complete_from_full_parse()

        # This position is important.  We only update the _last_position
        # after we've checked the special cases above where that value
        # matters.
        self._last_position = len(line)
        if line and not line.strip():
            # Special case, the user hits a space on a new line so
            # we autocomplete all the top level commands.
            return self._current['commands']

        last_word = line.split()[-1]
        if last_word in self.arg_metadata or last_word in self._global_options:
            # The last thing we completed was an argument, record
            # this as self.last_arg
            self.last_option = last_word
        if line[-1] == ' ':
            # At this point the user has autocompleted a command
            # or an argument and has hit space.  If they've
            # just completed a command, we need to change the
            # current context and traverse into the subcommand.
            # "ec2 "
            #      ^--here, need to traverse into "ec2"
            #
            # Otherwise:
            # "ec2 --no-validate-ssl "
            #                        ^-- here, stay on "ec2" context.
            if not last_word.startswith('-'):
                next_command = self._current['children'].get(last_word)
                if next_command is not None:
                    self._current = next_command
                    self._current_name = last_word
                    self.cmd_path.append(self._current_name)
            elif last_word in self.arg_metadata and \
                    self.arg_metadata[last_word]['example']:
                # Then this is an arg with a shorthand example so we'll
                # suggest that example.
                return [self.arg_metadata[last_word]['example']]
            # Even if we don't change context, we still want to
            # autocomplete all the commands for the current context
            # in either of the above two cases.
            return self._current['commands'][:]
        elif last_word.startswith('-'):
            # TODO: cache this for the duration of the current context.
            # We don't need to recompute this until the args are
            # different.
            all_args = self._get_all_args()
            if self.match_fuzzy:
                return fuzzy_search(last_word, all_args)
            else:
                return substring_search(last_word, all_args)
        if self.match_fuzzy:
            return fuzzy_search(last_word, self._current['commands'])
        else:
            return substring_search(last_word, self._current['commands'])
Example #4
0
def test_subsequences(search, corpus, expected):
    actual = fuzzy_search(search, corpus)
    assert actual == expected
Example #5
0
    def autocomplete(self, line):
        """Given a line, return a list of suggestions."""
        current_length = len(line)
        self._current_line = line
        if current_length == 1 and self._last_position > 1:
            # Reset state.  This is likely from a user completing
            # a previous command.
            self.reset()
        elif current_length < self._last_position:
            # The user has hit backspace.  We'll need to check
            # the current words.
            return self._handle_backspace()
        elif not line:
            return []
        elif current_length != self._last_position + 1:
            return self._complete_from_full_parse()

        # This position is important.  We only update the _last_position
        # after we've checked the special cases above where that value
        # matters.
        self._last_position = len(line)
        if line and not line.strip():
            # Special case, the user hits a space on a new line so
            # we autocomplete all the top level commands.
            return self._current['commands']

        last_word = line.split()[-1]
        if last_word in self.arg_metadata or last_word in self._global_options:
            # The last thing we completed was an argument, record
            # this as self.last_arg
            self.last_option = last_word
        if line[-1] == ' ':
            # At this point the user has autocompleted a command
            # or an argument and has hit space.  If they've
            # just completed a command, we need to change the
            # current context and traverse into the subcommand.
            # "ec2 "
            #      ^--here, need to traverse into "ec2"
            #
            # Otherwise:
            # "ec2 --no-validate-ssl "
            #                        ^-- here, stay on "ec2" context.
            if not last_word.startswith('-'):
                next_command = self._current['children'].get(last_word)
                if next_command is not None:
                    self._current = next_command
                    self._current_name = last_word
                    self.cmd_path.append(self._current_name)
            elif last_word in self.arg_metadata and \
                    self.arg_metadata[last_word]['example']:
                # Then this is an arg with a shorthand example so we'll
                # suggest that example.
                return [self.arg_metadata[last_word]['example']]
            # Even if we don't change context, we still want to
            # autocomplete all the commands for the current context
            # in either of the above two cases.
            return self._current['commands'][:]
        elif last_word.startswith('-'):
            # TODO: cache this for the duration of the current context.
            # We don't need to recompute this until the args are
            # different.
            all_args = self._get_all_args()
            if self.match_fuzzy:
                return fuzzy_search(last_word, all_args)
            else:
                return substring_search(last_word, all_args)
        if self.match_fuzzy:
            return fuzzy_search(last_word, self._current['commands'])
        else:
            return substring_search(last_word, self._current['commands'])
Example #6
0
def test_subsequences(search, corpus, expected):
    actual = fuzzy_search(search, corpus)
    assert actual == expected