def __init__(self, pymux): self.pymux = pymux def get_search_state(cli): " Return the currently active SearchState. (The one for the focussed pane.) " return pymux.arrangement.get_active_pane(cli).search_state # Start from this KeyBindingManager from prompt_toolkit, to have basic # editing functionality for the command line. These key binding are # however only active when the following `enable_all` condition is met. self.registry = MergedRegistry([ ConditionalRegistry( registry=load_key_bindings( enable_auto_suggest_bindings=True, enable_search= False, # We have our own search bindings, that support multiple panes. enable_extra_page_navigation=True, get_search_state=get_search_state), filter=(HasFocus(COMMAND) | HasFocus(PROMPT) | InScrollBuffer(pymux)) & ~HasPrefix(pymux), ), load_mouse_bindings(), self._load_builtins(), _load_search_bindings(pymux), ]) self._prefix = (Keys.ControlB, ) self._prefix_binding = None # Load initial bindings. self._load_prefix_binding() # Custom user configured key bindings. # { (needs_prefix, key) -> (command, handler) } self.custom_bindings = {}
def register_ipython_shortcuts(registry, shell): """Set up the prompt_toolkit keyboard shortcuts for IPython""" insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode))( newline_or_execute_outer(shell)) registry.add_binding(Keys.ControlBackslash)(force_exit) registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) ))(previous_history_or_previous_completion) registry.add_binding( Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))(next_history_or_next_completion) registry.add_binding(Keys.ControlG, filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions()))(dismiss_completion) registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))(reset_buffer) registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))(reset_search_buffer) supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) registry.add_binding(Keys.ControlZ, filter=supports_suspend)(suspend_to_bg) # Ctrl+I == Tab registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & cursor_in_leading_ws))(indent_buffer) registry.add_binding( Keys.ControlO, filter=(HasFocus(DEFAULT_BUFFER) & EmacsInsertMode()))(newline_with_copy_margin) if shell.display_completions == 'readlinelike': registry.add_binding( Keys.ControlI, filter=( HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & ~cursor_in_leading_ws))(display_completions_like_readline) if sys.platform == 'win32': registry.add_binding(Keys.ControlV, filter=(HasFocus(DEFAULT_BUFFER) & ~ViMode()))(win_paste)
def __init__(self, editor, manager, window_arrangement): self.editor = editor # Back reference to editor. self.manager = manager self.window_arrangement = window_arrangement # Mapping from (`window_arrangement.Window`, `EditorBuffer`) to a frame # (Layout instance). # We keep this as a cache in order to easily reuse the same frames when # the layout is updated. (We don't want to create new frames on every # update call, because that way, we would loose some state, like the # vertical scroll offset.) self._frames = {} self._fc = FloatContainer( content=VSplit([ Window(BufferControl()) # Dummy window ]), floats=[ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=12, scroll_offset=2, extra_filter=~HasFocus(COMMAND_BUFFER))), Float(content=BufferListOverlay(editor), bottom=1, left=0), Float(bottom=1, left=0, right=0, height=1, content=CompletionsToolbar( extra_filter=HasFocus(COMMAND_BUFFER) & ~bufferlist_overlay_visible_filter & Condition(lambda cli: editor.show_wildmenu))), Float(bottom=1, left=0, right=0, height=1, content=ValidationToolbar()), Float(bottom=1, left=0, right=0, height=1, content=MessageToolbarBar(editor)), Float(content=WelcomeMessageWindow(editor), height=WELCOME_MESSAGE_HEIGHT, width=WELCOME_MESSAGE_WIDTH), ] ) self.layout = FloatContainer( content=HSplit([ TabsToolbar(editor), self._fc, CommandLine(), ReportMessageToolbar(editor), SystemToolbar(), SearchToolbar(vi_mode=True), ]), floats=[ Float(right=0, height=1, bottom=0, width=5, content=SimpleArgToolbar()), ] )
def create_python_input_window(): def menu_position(cli): """ When there is no autocompletion menu to be shown, and we have a signature, set the pop-up position at `bracket_start`. """ b = cli.buffers[DEFAULT_BUFFER] if b.complete_state is None and python_input.signatures: row, col = python_input.signatures[0].bracket_start index = b.document.translate_row_col_to_index(row - 1, col) return index return Window( BufferControl( buffer_name=DEFAULT_BUFFER, lexer=lexer, input_processors=[ ConditionalProcessor( processor=HighlightSearchProcessor( preview_search=True), filter=HasFocus(SEARCH_BUFFER), ), HighlightSelectionProcessor(), DisplayMultipleCursors(DEFAULT_BUFFER), # Show matching parentheses, but only while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & Condition(lambda cli: python_input. highlight_matching_parenthesis)), ConditionalProcessor(processor=AppendAutoSuggestion(), filter=~IsDone()) ] + extra_buffer_processors, menu_position=menu_position, # Make sure that we always see the result of an reverse-i-search: preview_search=True, ), left_margins=[PythonPromptMargin(python_input)], # Scroll offsets. The 1 at the bottom is important to make sure the # cursor is never below the "Press [Meta+Enter]" message which is a float. scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4), # As long as we're editing, prefer a minimal height of 6. get_height=(lambda cli: (None if cli.is_done or python_input. show_exit_confirmation else input_buffer_height)), wrap_lines=Condition(lambda cli: python_input.wrap_lines), )
def _layout_options(self): """ Return the current layout option for the current Terminal InteractiveShell """ return { 'lexer': IPythonPTLexer(), 'reserve_space_for_menu': self.space_for_menu, 'get_prompt_tokens': self.prompts.in_prompt_tokens, 'get_continuation_tokens': self.prompts.continuation_prompt_tokens, 'multiline': True, 'display_completions_in_columns': (self.display_completions == 'multicolumn'), # Highlight matching brackets, but only when this setting is # enabled, and only when the DEFAULT_BUFFER has the focus. 'extra_input_processors': [ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & Condition(lambda cli: self.highlight_matching_brackets)) ], }
def load_emacs_system_bindings(registry, filter=None): handle = create_handle_decorator(registry, filter & EmacsMode()) has_focus = HasFocus(SYSTEM_BUFFER) @handle(Keys.Escape, '!', filter=~has_focus) def _(event): """ M-'!' opens the system prompt. """ event.cli.push_focus(SYSTEM_BUFFER) @handle(Keys.Escape, filter=has_focus) @handle(Keys.ControlG, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) def _(event): """ Cancel system prompt. """ event.cli.buffers[SYSTEM_BUFFER].reset() event.cli.pop_focus() @handle(Keys.ControlJ, filter=has_focus) def _(event): """ Run system command. """ system_line = event.cli.buffers[SYSTEM_BUFFER] event.cli.run_system_command(system_line.text) system_line.reset(append_to_history=True) # Focus previous buffer again. event.cli.pop_focus()
def _build_cli(self, history): def set_vi_mode(value): self.vi_mode = value key_binding_manager = mssqlcli_bindings( get_vi_mode_enabled=lambda: self.vi_mode, set_vi_mode_enabled=set_vi_mode) def prompt_tokens(_): prompt = self.get_prompt() return [(Token.Prompt, prompt)] def get_continuation_tokens(cli, width): continuation = self.multiline_continuation_char * (width - 1) + ' ' return [(Token.Continuation, continuation)] get_toolbar_tokens = create_toolbar_tokens_func( lambda: self.vi_mode, None, None, None) layout = create_prompt_layout( lexer=PygmentsLexer(PostgresLexer), reserve_space_for_menu=self.min_num_menu_lines, get_prompt_tokens=prompt_tokens, get_continuation_tokens=get_continuation_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=self.wider_completion_menu, multiline=True, extra_input_processors=[ # Highlight matching brackets while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), ]) with self._completer_lock: buf = MssqlBuffer(auto_suggest=AutoSuggestFromHistory(), always_multiline=self.multi_line, multiline_mode=self.multiline_mode, completer=self.completer, history=history, complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) editing_mode = EditingMode.VI if self.vi_mode else EditingMode.EMACS application = Application( style=style_factory(self.syntax_style, self.cli_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, ignore_case=True, editing_mode=editing_mode) cli = CommandLineInterface(application=application, eventloop=self.eventloop) return cli
def __init__(self, editor): def get_tokens(cli): eb = editor.window_arrangement.active_editor_buffer lineno = eb.buffer.document.cursor_position_row errors = eb.report_errors for e in errors: if e.lineno == lineno: return e.message_token_list return [] super(ReportMessageToolbar, self).__init__( get_tokens, filter=~HasFocus(COMMAND_BUFFER) & ~HasSearch() & ~HasFocus('system'))
def _build_cli(self, history): def get_message(): prompt = self.context.get_prompt(self.default_prompt) return [('class:prompt', prompt)] prompt_app = PromptSession( message=get_message, complete_style=CompleteStyle.COLUMN, completer=ThreadedCompleter( DynamicCompleter(lambda: self.completer)), complete_while_typing=True, editing_mode=EditingMode.VI, enable_system_prompt=True, enable_suspend=True, history=history, input_processors=[ # Highlight matching brackets while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}', ), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), # Render \t as 4 spaces instead of "^I" TabsProcessor(char1=' ', char2=' ') ], key_bindings=get_key_bindings(), search_ignore_case=True, ) return prompt_app
def create_tutorial_layout(lex): """ layout for example tutorial """ lexer, _, _ = get_lexers(lex, None, None) layout_full = HSplit([ FloatContainer( Window(BufferControl(input_processors=input_processors, lexer=lexer, preview_search=Always()), get_height=get_height), [ Float(xcursor=True, ycursor=True, content=CompletionsMenu( max_height=MAX_COMPLETION, scroll_offset=1, extra_filter=(HasFocus(DEFAULT_BUFFER)))) ]), ConditionalContainer(HSplit([ get_hline(), get_param(lexer), get_hline(), Window(content=BufferControl(buffer_name='example_line', lexer=lexer), ), Window(TokenListControl(get_tutorial_tokens, default_char=Char(' ', Token.Toolbar)), height=D.exact(1)), ]), filter=~IsDone() & RendererHeightIsKnown()) ]) return layout_full
def _extra_prompt_options(self): """ Return the current layout option for the current Terminal InteractiveShell """ def get_message(): return PygmentsTokens(self.prompts.in_prompt_tokens()) return { 'complete_in_thread': False, 'lexer':IPythonPTLexer(), 'reserve_space_for_menu':self.space_for_menu, 'message': get_message, 'prompt_continuation': ( lambda width, lineno, is_soft_wrap: PygmentsTokens(self.prompts.continuation_prompt_tokens(width))), 'multiline': True, 'complete_style': self.pt_complete_style, # Highlight matching brackets, but only when this setting is # enabled, and only when the DEFAULT_BUFFER has the focus. 'input_processors': [ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & Condition(lambda: self.highlight_matching_brackets))], }
def __init__(self): super(CommandLine, self).__init__(BufferControl( buffer_name=COMMAND_BUFFER, input_processors=[BeforeInput.static(':')], lexer=create_command_lexer()), height=LayoutDimension.exact(1), filter=HasFocus(COMMAND_BUFFER))
def build_cli(self): # TODO: Optimize index suggestion to serve indices options only at the needed position, such as 'from' indices_list = self.es_executor.indices_list sql_completer = WordCompleter(self.keywords_list + self.functions_list + indices_list, ignore_case=True) # https://stackoverflow.com/a/13726418 denote multiple unused arguments of callback in Python def get_continuation(width, *_): continuation = self.multiline_continuation_char * (width - 1) + " " return [("class:continuation", continuation)] prompt_app = PromptSession( lexer=PygmentsLexer(SqlLexer), completer=sql_completer, complete_while_typing=True, # TODO: add history, refer to pgcli approach # history=history, style=style_factory(self.syntax_style, self.cli_style), prompt_continuation=get_continuation, multiline=es_is_multiline(self), auto_suggest=AutoSuggestFromHistory(), input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars="[](){}"), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone(), ) ], tempfile_suffix=".sql", ) return prompt_app
def create_python_input_window(): def menu_position(cli): """ When there is no autocompletion menu to be shown, and we have a signature, set the pop-up position at `bracket_start`. """ b = cli.buffers['default'] if b.complete_state is None and settings.signatures: row, col = settings.signatures[0].bracket_start index = b.document.translate_row_col_to_index(row - 1, col) return index return Window( BufferControl( buffer_name=DEFAULT_BUFFER, lexer=lexer, show_line_numbers=ShowLineNumbersFilter(settings, 'default'), input_processors=[ # Show matching parentheses, but only while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), HighlightSearchProcessor(preview_search=Always()), HighlightSelectionProcessor()] + extra_buffer_processors, menu_position=menu_position, # Make sure that we always see the result of an reverse-i-search: preview_search=Always(), ), # As long as we're editing, prefer a minimal height of 6. get_height=(lambda cli: (None if cli.is_done else D(min=6))), )
def _build_cli(self): eventloop = create_eventloop() if self._options.persistent_history: history = FileHistory( os.path.join( os.path.expanduser("~"), ".{}_history".format(self._ctx.binary_name) ) ) else: history = InMemoryHistory() layout = create_prompt_layout( lexer=PygmentsLexer(NubiaLexer), reserve_space_for_menu=5, get_prompt_tokens=self.get_prompt_tokens, get_rprompt_tokens=self._status_bar.get_rprompt_tokens, get_bottom_toolbar_tokens=self._status_bar.get_tokens, display_completions_in_columns=False, multiline=True, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars="[](){}"), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone(), ) ], ) buf = Buffer( completer=self._completer, history=history, auto_suggest=self._suggestor, complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT, ) # If EDITOR does not exist, take EMACS # if it does, try fit the EMACS/VI pattern using upper editor = getattr( EditingMode, os.environ.get("EDITOR", EditingMode.EMACS).upper(), EditingMode.EMACS, ) application = Application( style=shell_style, buffer=buf, editing_mode=editor, key_bindings_registry=self._registry, layout=layout, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, ignore_case=True, ) cli = CommandLineInterface(application=application, eventloop=eventloop) return cli
def _build_cli(self, history): def get_message(): prompt = self.get_prompt(self.prompt_format) return [(u'class:prompt', prompt)] def get_continuation(width): continuation = self.multiline_continuation_char * (width - 1) + ' ' return [(u'class:continuation', continuation)] get_toolbar_tokens = create_toolbar_tokens_func(self) if self.wider_completion_menu: complete_style = CompleteStyle.MULTI_COLUMN else: complete_style = CompleteStyle.COLUMN with self._completer_lock: self.prompt_session = PromptSession( message=get_message, style=style_factory(self.syntax_style, self.cli_style), # Layout options. lexer=PygmentsLexer(PostgresLexer), prompt_continuation=get_continuation, bottom_toolbar=get_toolbar_tokens, complete_style=complete_style, input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), #FIXME: what is this? # Render \t as 4 spaces instead of "^I" TabsProcessor(char1=u' ', char2=u' ') ], reserve_space_for_menu=self.min_num_menu_lines, # Buffer options. multiline=mssql_is_multiline(self), completer=ThreadedCompleter( DynamicCompleter(lambda: self.completer)), history=history, auto_suggest=AutoSuggestFromHistory(), complete_while_typing=True, # Key bindings. enable_system_prompt=True, enable_open_in_editor=True, # Other options. key_bindings=mssqlcli_bindings(self), editing_mode=EditingMode.VI if self.vi_mode else EditingMode.EMACS, search_ignore_case=True) return self.prompt_session
def add_custom_binding(self, key_name, command, arguments, needs_prefix=False): """ Add custom binding (for the "bind-key" command.) Raises ValueError if the give `key_name` is an invalid name. :param key_name: Pymux key name, for instance "C-a" or "M-x". """ assert isinstance(key_name, six.text_type) assert isinstance(command, six.text_type) assert isinstance(arguments, list) # Unbind previous key. self.remove_custom_binding(key_name, needs_prefix=needs_prefix) # Translate the pymux key name into a prompt_toolkit key sequence. # (Can raise ValueError.) keys_sequence = pymux_key_to_prompt_toolkit_key_sequence(key_name) # Create handler and add to Registry. if needs_prefix: filter = HasPrefix(self.pymux) else: filter = ~HasPrefix(self.pymux) filter = filter & ~(WaitsForConfirmation(self.pymux) | HasFocus(COMMAND) | HasFocus(PROMPT)) def key_handler(event): " The actual key handler. " call_command_handler(command, self.pymux, event.cli, arguments) self.pymux.get_client_state(event.cli).has_prefix = False self.registry.add_binding(*keys_sequence, filter=filter)(key_handler) # Store key in `custom_bindings` in order to be able to call # "unbind-key" later on. k = (needs_prefix, key_name) self.custom_bindings[k] = CustomBinding(key_handler, command, arguments)
def _create_cli(self): """Creates the prompt_toolkit's CommandLineInterface. Args: * None. Returns: None. """ history = FileHistory(os.path.expanduser('~/.saws-history')) 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( self.set_color, self.get_color, self.set_fuzzy_match, self.get_fuzzy_match, self.set_shortcut_match, self.get_shortcut_match, self.refresh_resources_and_options, self.handle_docs) style_factory = StyleFactory(self.theme) application = Application( mouse_support=False, 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)
def __init__(self, pymux): self.pymux = pymux def enable_vi_mode(cli): " Return True when Vi mode is currently active. " client_state = pymux.get_client_state(cli) if client_state.confirm_text or client_state.prompt_command or client_state.command_mode: return pymux.status_keys_vi_mode else: return pymux.mode_keys_vi_mode def get_search_state(cli): " Return the currently active SearchState. (The one for the focussed pane.) " return pymux.arrangement.get_active_pane(cli).search_state # Start from this KeyBindingManager from prompt_toolkit, to have basic # editing functionality for the command line. These key binding are # however only active when the following `enable_all` condition is met. self.pt_key_bindings_manager = pt_KeyBindingManager( enable_vi_mode=Condition(enable_vi_mode), enable_all=(HasFocus(COMMAND) | HasFocus(PROMPT) | InScrollBuffer(pymux)) & ~HasPrefix(pymux), enable_auto_suggest_bindings=True, enable_search= False, # We have our own search bindings, that support multiple panes. enable_extra_page_navigation=True, get_vi_state=self._get_vi_state, get_search_state=get_search_state) self.registry = self.pt_key_bindings_manager.registry self._prefix = (Keys.ControlB, ) self._prefix_binding = None # Load initial bindings. self._load_builtins() self._load_prefix_binding() _load_search_bindings(pymux, self.registry, self._get_vi_state) # Custom user configured key bindings. # { (needs_prefix, key) -> (command, handler) } self.custom_bindings = {}
def __init__(self, shell_ctx): self.shell_ctx = shell_ctx @Condition def show_default(_): return self.shell_ctx.is_showing_default @Condition def show_symbol(_): return self.shell_ctx.is_symbols @Condition def show_progress(_): progress = get_progress_message() done = get_done() return progress != '' and not done @Condition def has_default_scope(_): return self.shell_ctx.default_command == '' self.has_default_scope = has_default_scope self.show_default = show_default self.show_symbol = show_symbol self.show_progress = show_progress # TODO fix this somehow self.input_processors = [ ConditionalProcessor( # By default, only highlight search when the search # input has the focus. (Note that this doesn't mean # there is no search: the Vi 'n' binding for instance # still allows to jump to the next match in # navigation mode.) HighlightSearchProcessor(preview_search=Always()), HasFocus(SEARCH_BUFFER)), HighlightSelectionProcessor(), ConditionalProcessor( AppendAutoSuggestion(), HasFocus(DEFAULT_BUFFER) & self.has_default_scope) ]
def _load_prefix_binding(self): """ Load the prefix key binding. """ pymux = self.pymux registry = self.registry # Remove previous binding. if self._prefix_binding: self.registry.remove_binding(self._prefix_binding) # Create new Python binding. @registry.add_binding( *self._prefix, filter=~(HasPrefix(pymux) | HasFocus(COMMAND) | HasFocus(PROMPT) | WaitsForConfirmation(pymux))) def enter_prefix_handler(event): " Enter prefix mode. " pymux.get_client_state(event.cli).has_prefix = True self._prefix_binding = enter_prefix_handler
def loop(cmd, history_file): buf = create_buffer(cmd, history_file) key_bindings = KeyBindings() bind_keys(buf, key_bindings) layout = create_layout( buffer=buf, multiline=True, lexer=SqlLexer, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) ], get_bottom_toolbar_tokens=lambda: get_toolbar_tokens(cmd), get_prompt_tokens=lambda: [('class:prompt', 'cr> ')]) output = get_default_output() app = Application(layout=layout, style=style_from_pygments_cls(CrateStyle), key_bindings=merge_key_bindings( [key_bindings, load_open_in_editor_bindings()]), editing_mode=_get_editing_mode(), output=output) cmd.get_num_columns = lambda: output.get_size().columns while True: try: text = app.run() if text: cmd.process(text) buf.reset() except ProgrammingError as e: if '401' in e.message: username = cmd.username password = cmd.password cmd.username = input('Username: '******'Bye!') return
def create_default_layout(message='', lexer=None, is_password=False, reserve_space_for_menu=False, get_bottom_toolbar_tokens=None): """ Generate default layout. """ assert get_bottom_toolbar_tokens is None or callable(get_bottom_toolbar_tokens) # Create processors list. input_processors = [HighlightSearchProcessor(), HighlightSelectionProcessor()] if is_password: input_processors.extend([PasswordProcessor(), DefaultPrompt(message)]) else: input_processors.append(DefaultPrompt(message)) # Create bottom toolbar. if get_bottom_toolbar_tokens: toolbars = [Window(TokenListControl(get_bottom_toolbar_tokens, default_char=Char(' ', Token.Toolbar)), height=LayoutDimension.exact(1), filter=~IsDone())] else: toolbars = [] 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: return LayoutDimension(min=8) else: return LayoutDimension() # Create and return Layout instance. return HSplit([ FloatContainer( Window( BufferControl( input_processors=input_processors, lexer=lexer, # Enable preview_search, we want to have immediate feedback # in reverse-i-search mode. preview_search=Always()), get_height=get_height, ), [ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, extra_filter=HasFocus(DEFAULT_BUFFER))) ] ), ValidationToolbar(), SystemToolbar(), ] + toolbars)
def _build_cli(self, history): def set_vi_mode(value): self.vi_mode = value key_binding_manager = pgcli_bindings( get_vi_mode_enabled=lambda: self.vi_mode, set_vi_mode_enabled=set_vi_mode) def prompt_tokens(_): return [(Token.Prompt, '%s> ' % self.pgexecute.dbname)] def get_continuation_tokens(cli, width): return [(Token.Continuation, '.' * (width - 1) + ' ')] get_toolbar_tokens = create_toolbar_tokens_func( lambda: self.vi_mode, self.completion_refresher.is_refreshing) layout = create_prompt_layout( lexer=PygmentsLexer(PostgresLexer), reserve_space_for_menu=4, get_prompt_tokens=prompt_tokens, get_continuation_tokens=get_continuation_tokens, get_bottom_toolbar_tokens=get_toolbar_tokens, display_completions_in_columns=self.wider_completion_menu, multiline=True, extra_input_processors=[ # Highlight matching brackets while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()), ]) with self._completer_lock: buf = PGBuffer(always_multiline=self.multi_line, completer=self.completer, history=history, complete_while_typing=Always(), accept_action=AcceptAction.RETURN_DOCUMENT) application = Application( style=style_factory(self.syntax_style, self.cli_style), layout=layout, buffer=buf, key_bindings_registry=key_binding_manager.registry, on_exit=AbortAction.RAISE_EXCEPTION, on_abort=AbortAction.RETRY, ignore_case=True) cli = CommandLineInterface(application=application) return cli
def create_layout(self, exam_lex, toolbar_lex): """ creates the layout """ lexer, exam_lex, toolbar_lex = get_lexers(self.shell_ctx.lexer, exam_lex, toolbar_lex) if not any( isinstance(processor, DefaultPrompt) for processor in self.input_processors): self.input_processors.append(DefaultPrompt(self.get_prompt_tokens)) layout_lower = ConditionalContainer(HSplit([ get_anyhline(self.shell_ctx.config), get_descriptions(self.shell_ctx.config, exam_lex, lexer), get_examplehline(self.shell_ctx.config), get_example(self.shell_ctx.config, exam_lex), ConditionalContainer(get_hline(), filter=self.show_default | self.show_symbol), ConditionalContainer(Window(content=BufferControl( buffer_name='default_values', lexer=lexer)), filter=self.show_default), ConditionalContainer(get_hline(), filter=self.show_default & self.show_symbol), ConditionalContainer(Window( content=BufferControl(buffer_name='symbols', lexer=exam_lex)), filter=self.show_symbol), ConditionalContainer(Window( content=BufferControl(buffer_name='progress', lexer=lexer)), filter=self.show_progress), Window(content=BufferControl(buffer_name='bottom_toolbar', lexer=toolbar_lex), ), ]), filter=~IsDone() & RendererHeightIsKnown()) layout_full = HSplit([ FloatContainer( Window( BufferControl(input_processors=self.input_processors, lexer=lexer, preview_search=Always()), get_height=get_height, ), [ Float(xcursor=True, ycursor=True, content=CompletionsMenu( max_height=MAX_COMPLETION, scroll_offset=1, extra_filter=(HasFocus(DEFAULT_BUFFER)))) ]), layout_lower ]) return layout_full
def create_cli_layout(self): from .lexer import AzureShellLexer lexer = AzureShellLexer return create_default_layout( message=u'azure> ', reserve_space_for_menu=8, lexer=lexer, extra_input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) ])
def _build_prompt_app(self, history): key_bindings = cli_bindings(self) def get_message(): prompt = self.get_prompt(self.prompt) if len(prompt) > self.MAX_LEN_PROMPT: prompt = self.get_prompt('\\r:\\d> ') return [('class:prompt', prompt)] def get_continuation(width, line_number, is_soft_wrap): continuation = ' ' * (width - 1) + ' ' return [('class:continuation', continuation)] def show_suggestion_tip(): return self.iterations < 2 get_toolbar_tokens = create_toolbar_tokens_func( self, show_suggestion_tip) with self._completer_lock: if self.key_bindings == 'vi': editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS self.prompt_app = PromptSession( lexer=PygmentsLexer(Lexer), reserve_space_for_menu=self.get_reserved_space(), message=get_message, prompt_continuation=get_continuation, bottom_toolbar=get_toolbar_tokens, complete_style=CompleteStyle.COLUMN, input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone()) ], tempfile_suffix='.sql', completer=DynamicCompleter(lambda: self.completer), history=history, auto_suggest=AutoSuggestFromHistory(), complete_while_typing=True, multiline=cli_is_multiline(self), style=style_factory(self.syntax_style, self.cli_style), include_default_pygments_style=False, key_bindings=key_bindings, enable_open_in_editor=True, enable_system_prompt=True, editing_mode=editing_mode, search_ignore_case=True)
def create_default_layout(message='', lexer=None, is_password=False, reserve_space_for_menu=False, get_bottom_toolbar_tokens=None): """ Generate default layout. """ assert get_bottom_toolbar_tokens is None or callable(get_bottom_toolbar_tokens) # Create processors list. if is_password: input_processors = [PasswordProcessor(), DefaultPrompt(message)] else: input_processors = [DefaultPrompt(message)] # Create bottom toolbar. if get_bottom_toolbar_tokens: toolbars = [Window(TokenListControl(get_bottom_toolbar_tokens, default_char=Char(' ', Token.Toolbar)), height=LayoutDimension.exact(1), filter=~IsDone())] else: toolbars = [] 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: return LayoutDimension(min=8) else: return LayoutDimension() # Create and return Layout instance. return HSplit([ FloatContainer( Window( BufferControl( input_processors=input_processors, lexer=lexer), get_height=get_height, ), [ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, extra_filter=HasFocus('default'))) ] ), ValidationToolbar(), SystemToolbar(), ] + toolbars)
def load_bindings(key_bindings_manager): handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() @key_bindings_manager.registry.add_binding(Keys.ControlL)#, eager=True) def clear_(event): clear() print(env.welcome) PROMPT = env.prompt PROMPT = PROMPT.replace(r"\u", env.user).replace(r"\w", env.directory) print(unicode_(PROMPT), end="") @key_bindings_manager.registry.add_binding(Keys.ControlB) def list_(event): print("\n".join(ls(env, [], {}))) PROMPT = env.prompt PROMPT = PROMPT.replace(r"\u", env.user).replace(r"\w", env.directory) print(env.default_color, end="") print(unicode_(PROMPT), end="") @handle(Keys.ControlJ, filter= ~has_selection & (ViInsertMode() | EmacsInsertMode()) & HasFocus(DEFAULT_BUFFER) & IsMultiline()) def _(event): """ Behaviour of the Enter key. Auto indent after newline/Enter. (When not in Vi navigaton mode, and when multiline is enabled.) """ b = event.current_buffer empty_lines_required = 2 def at_the_end(b): """ we consider the cursor at the end when there is no text after the cursor, or only whitespace. """ text = b.document.text_after_cursor return text == '' or (text.isspace() and not '\n' in text) if at_the_end(b) and (b.document.text.replace(' ', '').endswith('\n' * (empty_lines_required - 1)) or (b.document.text.replace("\n", "").endswith(";"))): # When the cursor is at the end, and we have an empty line: # drop the empty lines, but return the value. b.document = Document( text=b.text.rstrip(), cursor_position=len(b.text.rstrip())) b.accept_action.validate_and_handle(event.cli, b) else: _auto_newline(b)
def _extra_prompt_options(self): """ Return the current layout option for the current Terminal InteractiveShell """ def get_message(): return PygmentsTokens(self.prompts.in_prompt_tokens()) if self.editing_mode == 'emacs': # with emacs mode the prompt is (usually) static, so we call only # the function once. With VI mode it can toggle between [ins] and # [nor] so we can't precompute. # here I'm going to favor the default keybinding which almost # everybody uses to decrease CPU usage. # if we have issues with users with custom Prompts we can see how to # work around this. get_message = get_message() options = { 'complete_in_thread': False, 'lexer': IPythonPTLexer(), 'reserve_space_for_menu': self.space_for_menu, 'message': get_message, 'prompt_continuation': (lambda width, lineno, is_soft_wrap: PygmentsTokens( self.prompts.continuation_prompt_tokens(width))), 'multiline': True, 'complete_style': self.pt_complete_style, # Highlight matching brackets, but only when this setting is # enabled, and only when the DEFAULT_BUFFER has the focus. 'input_processors': [ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & Condition(lambda: self.highlight_matching_brackets)) ], } if not PTK3: options['inputhook'] = self.inputhook return options