From 881dbaf8d81d48c68bfc8713f37dd5744ad1f67e Mon Sep 17 00:00:00 2001 From: Michael Beer Date: Tue, 8 Aug 2017 14:09:42 +0200 Subject: [PATCH] added session toolbar * shows the current session user * shows the handler nodes connected with --- src/crate/crash/layout.py | 102 ++++++++++++++++++++++++++++++++++++++ src/crate/crash/repl.py | 32 +++++++++--- 2 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 src/crate/crash/layout.py diff --git a/src/crate/crash/layout.py b/src/crate/crash/layout.py new file mode 100644 index 00000000..dbd9c464 --- /dev/null +++ b/src/crate/crash/layout.py @@ -0,0 +1,102 @@ +from prompt_toolkit.filters import IsDone, HasFocus, RendererHeightIsKnown, to_cli_filter, Condition +from prompt_toolkit.enums import DEFAULT_BUFFER +from prompt_toolkit.token import Token +from prompt_toolkit.layout import Window, HSplit, VSplit, Float +from prompt_toolkit.layout.containers import ConditionalContainer, FloatContainer +from prompt_toolkit.layout.dimension import LayoutDimension +from prompt_toolkit.layout.controls import TokenListControl, BufferControl, FillControl +from prompt_toolkit.layout.lexers import PygmentsLexer +from prompt_toolkit.layout.screen import Char +from prompt_toolkit.layout.menus import CompletionsMenu +from prompt_toolkit.layout.toolbars import TokenListToolbar +from prompt_toolkit.layout.margins import PromptMargin, ConditionalMargin +from prompt_toolkit.layout.utils import token_list_width + +__all__ = ( + 'create_layout', +) + +def create_layout(message='', lexer=None, + reserve_space_for_menu=8, + get_prompt_tokens=None, + get_bottom_toolbar_tokens=None, + input_processors=None, multiline=False, + wrap_lines=True): + + sidebar_token = [ + (Token.Toolbar.Status.Key, "[ctrl+d]"), + (Token.Toolbar.Status, " Exit") + ] + sidebar_width = token_list_width(sidebar_token) + + multiline = to_cli_filter(multiline) + get_prompt_tokens = lambda _: [(Token.Prompt, message)] + get_sidebar_tokens = lambda _: sidebar_token + lexer = PygmentsLexer(lexer, sync_from_start=True) + + def get_height(cli): + # If there is an autocompletion menu to be shown, make sure that our + # layout has at least a minimal height in order to display it. + if reserve_space_for_menu and not cli.is_done: + buff = cli.current_buffer + + # Reserve the space, either when there are completions, or when + # `complete_while_typing` is true and we expect completions very + # soon. + if buff.complete_while_typing() or buff.complete_state is not None: + return LayoutDimension(min=reserve_space_for_menu) + + return LayoutDimension() + + # Create and return Container instance. + return HSplit([ + VSplit([ + HSplit([ + # The main input, with completion menus floating on top of it. + FloatContainer( + HSplit([ + Window( + BufferControl( + input_processors=input_processors, + lexer=lexer), + get_height=get_height, + wrap_lines=wrap_lines, + left_margins=[ + # In multiline mode, use the window margin to display + # the prompt and continuation tokens. + ConditionalMargin( + PromptMargin(get_prompt_tokens), + filter=multiline + ) + ], + ), + ]), + [ + # Completion menu + Float(xcursor=True, + ycursor=True, + content=CompletionsMenu( + max_height=16, + scroll_offset=1, + extra_filter=HasFocus(DEFAULT_BUFFER))), + ] + ) + ]) + ]), + ] + [ + VSplit([ + ConditionalContainer( + Window( + TokenListControl(get_bottom_toolbar_tokens), + height=LayoutDimension.exact(1) + ), + filter=~IsDone() & RendererHeightIsKnown()), + ConditionalContainer( + Window( + TokenListControl(get_sidebar_tokens), + height=LayoutDimension.exact(1), + width=LayoutDimension.exact(sidebar_width) + ), + filter=~IsDone() & RendererHeightIsKnown()) + ]) + ]) diff --git a/src/crate/crash/repl.py b/src/crate/crash/repl.py index 6bdf53be..29ffc665 100644 --- a/src/crate/crash/repl.py +++ b/src/crate/crash/repl.py @@ -31,7 +31,8 @@ Number, Literal, String, - Error) + Error, + Token) from prompt_toolkit.completion import Completer, Completion from prompt_toolkit.history import FileHistory @@ -46,12 +47,11 @@ ConditionalProcessor ) from prompt_toolkit.key_binding.manager import KeyBindingManager -from prompt_toolkit.shortcuts import (create_prompt_layout, - create_output, +from prompt_toolkit.shortcuts import (create_output, create_eventloop) from .commands import Command - +from .layout import create_layout MAX_HISTORY_LENGTH = 10000 @@ -79,6 +79,8 @@ class CrateStyle(Style): Literal: '#ae81ff', String: '#f4a33d', Error: '#ff3300', + Token.Toolbar.Status.Key: 'bg:#222222 #ffffaa', + Token.Toolbar.Status: 'bg:#222222' } @@ -274,21 +276,37 @@ def create_buffer(cmd, history_file): def loop(cmd, history_file): + + def session_toolbar(cli): + tokens = [] + + if cmd.is_conn_avaliable(): + tokens.extend([(Token.Toolbar.Status.Key, 'USER: '), + (Token.Toolbar.Status, cmd.username), + (Token.Toolbar.Status, ' | '), + (Token.Toolbar.Status.Key, 'HOSTS: '), + (Token.Toolbar.Status, ', '.join([n for n in cmd.last_connected_servers]))]) + else: + tokens.extend([(Token.Toolbar.Status, 'not connected')]) + + return tokens + key_binding_manager = KeyBindingManager( enable_search=True, enable_abort_and_exit_bindings=True, enable_system_bindings=True, enable_open_in_editor=True ) - layout = create_prompt_layout( + layout = create_layout( message=u'cr> ', multiline=True, lexer=SqlLexer, - extra_input_processors=[ + input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) - ] + ], + get_bottom_toolbar_tokens=session_toolbar ) application = Application( layout=layout,