diff --git a/saws/keys.py b/saws/keys.py index d0c4d97f..03965e29 100644 --- a/saws/keys.py +++ b/saws/keys.py @@ -15,9 +15,8 @@ from __future__ import unicode_literals from __future__ import print_function -from prompt_toolkit.key_binding.manager import KeyBindingManager -from prompt_toolkit.keys import Keys - +from prompt_toolkit.key_binding import KeyBindings +from prompt_toolkit.application import run_in_terminal class KeyManager(object): """Creates a Key Manager. @@ -44,15 +43,15 @@ def __init__(self, set_color, get_color, None. """ self.manager = None - self._create_key_manager(set_color, get_color, - set_fuzzy_match, get_fuzzy_match, - set_shortcut_match, get_shortcut_match, - refresh_resources_and_options, handle_docs) - - def _create_key_manager(self, set_color, get_color, - set_fuzzy_match, get_fuzzy_match, - set_shortcut_match, get_shortcut_match, - refresh_resources_and_options, handle_docs): + self.key_bindings = self._create_key_bindings( + set_color, get_color, set_fuzzy_match, get_fuzzy_match, + set_shortcut_match, get_shortcut_match, + refresh_resources_and_options, handle_docs) + + def _create_key_bindings(self, set_color, get_color, + set_fuzzy_match, get_fuzzy_match, + set_shortcut_match, get_shortcut_match, + refresh_resources_and_options, handle_docs): """Creates and initializes the keybinding manager. Args: @@ -74,13 +73,10 @@ def _create_key_manager(self, set_color, get_color, assert callable(get_shortcut_match) assert callable(refresh_resources_and_options) assert callable(handle_docs) - self.manager = KeyBindingManager( - enable_search=True, - enable_abort_and_exit_bindings=True, - enable_system_bindings=True, - enable_auto_suggest_bindings=True) - @self.manager.registry.add_binding(Keys.F2) + kb = KeyBindings() + + @kb.add('f2') def handle_f2(_): """Enables/Disables color output. @@ -92,7 +88,7 @@ def handle_f2(_): """ set_color(not get_color()) - @self.manager.registry.add_binding(Keys.F3) + @kb.add('f3') def handle_f3(_): """Enables/Disables fuzzy matching. @@ -104,7 +100,7 @@ def handle_f3(_): """ set_fuzzy_match(not get_fuzzy_match()) - @self.manager.registry.add_binding(Keys.F4) + @kb.add('f4') def handle_f4(_): """Enables/Disables shortcut matching. @@ -116,7 +112,7 @@ def handle_f4(_): """ set_shortcut_match(not get_shortcut_match()) - @self.manager.registry.add_binding(Keys.F5) + @kb.add('f5') def handle_f5(event): """Refreshes AWS resources. @@ -128,7 +124,7 @@ def handle_f5(event): """ event.cli.run_in_terminal(refresh_resources_and_options) - @self.manager.registry.add_binding(Keys.F9) + @kb.add('f9') def handle_f9(_): """Inputs the "docs" command when the `F9` key is pressed. @@ -140,8 +136,8 @@ def handle_f9(_): """ handle_docs(from_fkey=True) - @self.manager.registry.add_binding(Keys.F10) - def handle_f10(_): + @kb.add('f10') + def handle_f10(event): """Quits when the `F10` key is pressed. Args: @@ -150,9 +146,9 @@ def handle_f10(_): Returns: None. """ - raise EOFError + event.app.exit() - @self.manager.registry.add_binding(Keys.ControlSpace) + @kb.add('c-space') def handle_ctrl_space(event): """Initializes autocompletion at the cursor. @@ -172,3 +168,5 @@ def handle_ctrl_space(event): b.complete_next() else: event.cli.start_completion(select_first=False) + + return kb diff --git a/saws/main.py b/saws/main.py index f6fd135b..324a5085 100644 --- a/saws/main.py +++ b/saws/main.py @@ -38,8 +38,7 @@ def cli(): try: saws = Saws() saws.run_cli() - except (EOFError, KeyboardInterrupt): - saws.aws_cli.set_return_value(None) + except EOFError: saws.config_obj.write() diff --git a/saws/saws.py b/saws/saws.py index 92af4212..cdfa0380 100644 --- a/saws/saws.py +++ b/saws/saws.py @@ -21,18 +21,17 @@ import subprocess import traceback import webbrowser -from prompt_toolkit import AbortAction, Application, CommandLineInterface from prompt_toolkit.enums import DEFAULT_BUFFER -from prompt_toolkit.filters import Always, HasFocus, IsDone -from prompt_toolkit.interface import AcceptAction +from prompt_toolkit.shortcuts import PromptSession +from prompt_toolkit.filters import HasFocus, IsDone from prompt_toolkit.layout.processors import \ HighlightMatchingBracketProcessor, ConditionalProcessor -from prompt_toolkit.buffer import Buffer -from prompt_toolkit.shortcuts import create_default_layout, create_eventloop +from prompt_toolkit.lexers import PygmentsLexer from prompt_toolkit.history import FileHistory -from prompt_toolkit.key_binding.input_processor import KeyPress +from prompt_toolkit.key_binding.key_processor import KeyPress from prompt_toolkit.keys import Keys from prompt_toolkit.auto_suggest import AutoSuggestFromHistory +from prompt_toolkit.completion import ThreadedCompleter from awscli import completer as awscli_completer from .completer import AwsCompleter from .lexer import CommandLexer @@ -74,8 +73,7 @@ def __init__(self, refresh_resources=True): Returns: None. """ - self.aws_cli = None - self.key_manager = None + self.prompt = None self.config = Config() self.config_obj = self.config.read_configuration() self.theme = self.config_obj[self.config.MAIN][self.config.THEME] @@ -248,7 +246,7 @@ def handle_docs(self, text=None, from_fkey=False): base_url = 'http://docs.aws.amazon.com/cli/latest/reference/' index_html = 'index.html' if text is None: - text = self.aws_cli.current_buffer.document.text + text = self.prompt.app.current_buffer.document.text # If the user hit the F9 key, append 'docs' to the text if from_fkey: text = text.strip() + ' ' + AwsCommands.AWS_DOCS @@ -365,9 +363,9 @@ def _handle_keyboard_interrupt(self, e, platform): raise e else: # Clear the renderer and send a carriage return - self.aws_cli.renderer.clear() - self.aws_cli.input_processor.feed(KeyPress(Keys.ControlM, u'')) - self.aws_cli.input_processor.process_keys() + self.prompt.app.renderer.clear() + self.prompt.app.key_processor.feed(KeyPress(Keys.ControlM, u'')) + self.prompt.app.key_processor.process_keys() def _process_command(self, text): """Processes the input command, called by the cli event loop @@ -406,26 +404,8 @@ def _create_cli(self): toolbar = Toolbar(self.get_color, self.get_fuzzy_match, self.get_shortcut_match) - layout = create_default_layout( - message='saws> ', - reserve_space_for_menu=8, - lexer=CommandLexer, - get_bottom_toolbar_tokens=toolbar.handler, - extra_input_processors=[ - ConditionalProcessor( - processor=HighlightMatchingBracketProcessor( - chars='[](){}'), - filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) - ] - ) - cli_buffer = Buffer( - history=history, - auto_suggest=AutoSuggestFromHistory(), - enable_history_search=True, - completer=self.completer, - complete_while_typing=Always(), - accept_action=AcceptAction.RETURN_DOCUMENT) - self.key_manager = KeyManager( + + key_manager = KeyManager( self.set_color, self.get_color, self.set_fuzzy_match, @@ -434,20 +414,31 @@ def _create_cli(self): self.get_shortcut_match, self.refresh_resources_and_options, self.handle_docs) + style_factory = StyleFactory(self.theme) - application = Application( - mouse_support=False, + + self.prompt = PromptSession( + message='saws> ', + reserve_space_for_menu=8, + lexer=PygmentsLexer(CommandLexer), + bottom_toolbar=toolbar.handler, + input_processors=[ + ConditionalProcessor( + processor=HighlightMatchingBracketProcessor( + chars='[](){}'), + filter=HasFocus(DEFAULT_BUFFER) & ~IsDone())], + auto_suggest=AutoSuggestFromHistory(), + enable_history_search=True, + completer=ThreadedCompleter(self.completer), + complete_while_typing=True, + enable_system_prompt=True, + key_bindings=key_manager.key_bindings, style=style_factory.style, - layout=layout, - buffer=cli_buffer, - key_bindings_registry=self.key_manager.manager.registry, - on_exit=AbortAction.RAISE_EXCEPTION, - on_abort=AbortAction.RETRY, - ignore_case=True) - eventloop = create_eventloop() - self.aws_cli = CommandLineInterface( - application=application, - eventloop=eventloop) + mouse_support=False, + include_default_pygments_style=False, + history=history, + #ignore_case=True, + ) def run_cli(self): """Runs the main loop. @@ -461,5 +452,9 @@ def run_cli(self): print('Version:', __version__) print('Theme:', self.theme) while True: - document = self.aws_cli.run(reset_current_buffer=True) - self._process_command(document.text) + try: + text = self.prompt.prompt() + except KeyboardInterrupt: + pass + else: + self._process_command(text) diff --git a/saws/style.py b/saws/style.py index 297098c8..43bfa2c1 100644 --- a/saws/style.py +++ b/saws/style.py @@ -13,9 +13,8 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from pygments.token import Token from pygments.util import ClassNotFound -from prompt_toolkit.styles import default_style_extensions, style_from_dict +from prompt_toolkit.styles import merge_styles, style_from_pygments_cls, Style import pygments.styles @@ -56,22 +55,20 @@ def style_factory(self, name): style = pygments.styles.get_style_by_name('native') # Create styles dictionary. - styles = {} - styles.update(style.styles) - styles.update(default_style_extensions) - styles.update({ - Token.Menu.Completions.Completion.Current: 'bg:#00aaaa #000000', - Token.Menu.Completions.Completion: 'bg:#008888 #ffffff', - Token.Scrollbar: 'bg:#00aaaa', - Token.Scrollbar.Button: 'bg:#003333', - Token.Toolbar: 'bg:#222222 #cccccc', - Token.Toolbar.Off: 'bg:#222222 #696969', - Token.Toolbar.On: 'bg:#222222 #ffffff', - Token.Toolbar.Search: 'noinherit bold', - Token.Toolbar.Search.Text: 'nobold', - Token.Toolbar.System: 'noinherit bold', - Token.Toolbar.Arg: 'noinherit bold', - Token.Toolbar.Arg.Text: 'nobold' - }) - - return style_from_dict(styles) + return merge_styles([ + style_from_pygments_cls(style), + Style.from_dict({ + 'scrollbar': 'bg:#00aaaa', + 'scrollbar.button': 'bg:#003333', + 'completion-menu.completion': 'bg:#008888 #ffffff', + 'completion-menu.completion.current': 'bg:#00aaaa #000000', + 'system-toolbar': 'noinherit bold', + 'search-toolbar': 'noinherit bold', + 'search-toolbar.text': 'nobold', + 'arg-toolbar': 'noinherit bold', + 'arg-toolbar.text': 'nobold', + 'bottom-toolbar': 'bg:#222222 #cccccc', + 'toolbar.off': 'bg:#222222 #696969', + 'toolbar.on': 'bg:#222222 #ffffff', + }) + ]) diff --git a/saws/toolbar.py b/saws/toolbar.py index 21668b37..29f2ef0e 100644 --- a/saws/toolbar.py +++ b/saws/toolbar.py @@ -57,40 +57,38 @@ def _create_toolbar_handler(self, color_cfg, fuzzy_cfg, shortcuts_cfg): assert callable(fuzzy_cfg) assert callable(shortcuts_cfg) - def get_toolbar_items(_): + def get_toolbar_items(): """Returns bottom menu items. - Args: - * _: An instance of prompt_toolkit's Cli (not used). - Returns: A list of Token.Toolbar. """ if color_cfg(): - color_token = Token.Toolbar.On + color_token = 'class:toolbar.on' color = 'ON' else: - color_token = Token.Toolbar.Off + color_token = 'class:toolbar.off' color = 'OFF' if fuzzy_cfg(): - fuzzy_token = Token.Toolbar.On + fuzzy_token = 'class:toolbar.on' fuzzy = 'ON' else: - fuzzy_token = Token.Toolbar.Off + fuzzy_token = 'class:toolbar.off' fuzzy = 'OFF' if shortcuts_cfg(): - shortcuts_token = Token.Toolbar.On + shortcuts_token = 'class:toolbar.on' shortcuts = 'ON' else: - shortcuts_token = Token.Toolbar.Off + shortcuts_token = 'class:toolbar.off' shortcuts = 'OFF' + return [ (color_token, ' [F2] Color: {0} '.format(color)), (fuzzy_token, ' [F3] Fuzzy: {0} '.format(fuzzy)), (shortcuts_token, ' [F4] Shortcuts: {0} '.format(shortcuts)), - (Token.Toolbar, ' [F5] Refresh '), - (Token.Toolbar, ' [F9] Docs '), - (Token.Toolbar, ' [F10] Exit ') + ('', ' [F5] Refresh '), + ('', ' [F9] Docs '), + ('', ' [F10] Exit ') ] return get_toolbar_items