diff --git a/awsshell/app.py b/awsshell/app.py index 40b93c3..496df08 100644 --- a/awsshell/app.py +++ b/awsshell/app.py @@ -234,6 +234,7 @@ def __init__(self, completer, model_completer, docs, self._dot_cmd = DotCommandHandler() self._env = os.environ.copy() self._profile = None + self.prompt_tokens = u'aws> ' self._input = input self._output = output @@ -282,7 +283,10 @@ def run(self): while True: try: document = self.cli.run(reset_current_buffer=True) - text = document.text + if self.model_completer.context and isinstance(self.model_completer.context, list): + text = " ".join(self.model_completer.context) + " " + document.text + else: + text = document.text except InputInterrupt: pass except (KeyboardInterrupt, EOFError): @@ -300,6 +304,25 @@ def run(self): if text.startswith('!'): # Then run the rest as a normally shell command. full_cmd = text[1:] + elif text.startswith('@') and len(text.split()) == 1: + # Add word as context to completions + self.model_completer.context.append(text.split()[0].strip('@')) + self.model_completer.reset() + self.prompt_tokens = u'aws ' + ' '.join(self.model_completer.context) + u' > ' + self.refresh_cli = True + self.cli.request_redraw() + continue + elif 'exit' in text.split(): + # Remove most recently added context + if self.model_completer.context: + self.model_completer.context.pop() + if self.model_completer.context: + self.prompt_tokens = u'aws ' + ' '.join(self.model_completer.context) + u' > ' + else: + self.prompt_tokens = u'aws > ' + self.refresh_cli = True + self.cli.request_redraw() + continue else: full_cmd = 'aws ' + text self.history.append(full_cmd) @@ -331,7 +354,7 @@ def create_layout(self, display_completions_in_columns, toolbar): if self.config_section['theme'] == 'none': lexer = None return create_default_layout( - self, u'aws> ', lexer=lexer, reserve_space_for_menu=True, + self, self.prompt_tokens, lexer=lexer, reserve_space_for_menu=True, display_completions_in_columns=display_completions_in_columns, get_bottom_toolbar_tokens=toolbar.handler) diff --git a/awsshell/autocomplete.py b/awsshell/autocomplete.py index 360b8c3..fff13f0 100644 --- a/awsshell/autocomplete.py +++ b/awsshell/autocomplete.py @@ -24,6 +24,7 @@ def __init__(self, index_data, match_fuzzy=True): # This will get populated as a command is completed. self.cmd_path = [self._current_name] self.match_fuzzy = match_fuzzy + self.context = [] self._cache_all_args = [] @property @@ -43,6 +44,15 @@ def reset(self): self._last_position = 0 self.last_option = '' self.cmd_path = [self._current_name] + for context in self.context: + next_command = self._current['children'].get(context) + if not next_command: + self.context.remove(context) + self.reset() + return + self._current = next_command + self._current_name = context + self.cmd_path.append(self._current_name) self._cache_all_args = [] def autocomplete(self, line): diff --git a/tests/unit/test_autocomplete.py b/tests/unit/test_autocomplete.py index 0bb2f46..f103e89 100644 --- a/tests/unit/test_autocomplete.py +++ b/tests/unit/test_autocomplete.py @@ -380,3 +380,31 @@ def test_global_arg_metadata_property(index_data): } completer = AWSCLIModelCompleter(index_data) assert '--global1' in completer.global_arg_metadata + +def test_add_context_changes_context(index_data): + index_data['aws']['commands'] = ['ec2'] + index_data['aws']['children'] = { + 'ec2': { + 'commands': ['create-tags'], + 'argument_metadata': {}, + 'arguments': [], + 'children': { + 'create-tags': { + 'commands': [], + 'argument_metadata': { + '--resources': {'example': '', 'minidoc': 'foo'}, + }, + 'arguments': ['--resources'], + 'children': {}, + } + } + } + } + completer = AWSCLIModelCompleter(index_data) + completer.reset() + completer.autocomplete('c') + assert completer.autocomplete('c') == ['ec2'] + completer.context = ['ec2'] + completer.reset() + completer.autocomplete('c') + assert completer.autocomplete('c') == ['create-tags']