def load_emacs_system_bindings(registry, filter=None): handle = create_handle_decorator(registry, filter) has_focus = filters.HasFocus(SYSTEM_BUFFER) @handle(Keys.Escape, '!', filter=~has_focus) def _(event): """ M-'!' opens the system prompt. """ event.cli.focus_stack.push(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.focus_stack.pop() @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.focus_stack.pop()
def load_emacs_search_bindings(registry, filter=None, search_buffer_name='search'): handle = create_handle_decorator(registry, filter) has_focus = filters.HasFocus(search_buffer_name) @handle(Keys.ControlG, filter=has_focus) # NOTE: the reason for not also binding Escape to this one, is that we want # Alt+Enter to accept input directly in incremental search mode. def _(event): """ Abort an incremental search and restore the original line. """ search_line = event.cli.buffers[search_buffer_name] event.current_buffer.exit_isearch(restore_original_line=True) search_line.reset() event.cli.focus_stack.pop() @handle(Keys.ControlJ, filter=has_focus) def _(event): """ When enter pressed in isearch, quit isearch mode. (Multiline isearch would be too complicated.) """ search_line = event.cli.buffers[search_buffer_name] search_line.reset() event.cli.buffers[event.cli.focus_stack.previous].exit_isearch() event.cli.focus_stack.pop() @handle(Keys.ControlR, filter=~has_focus) def _(event): event.cli.focus_stack.push(search_buffer_name) buffer = event.cli.buffers[event.cli.focus_stack.previous] buffer.incremental_search(IncrementalSearchDirection.BACKWARD) @handle(Keys.ControlS, filter=~has_focus) def _(event): event.cli.focus_stack.push(search_buffer_name) buffer = event.cli.buffers[event.cli.focus_stack.previous] buffer.incremental_search(IncrementalSearchDirection.FORWARD) @handle(Keys.ControlR, filter=has_focus) @handle(Keys.Up, filter=has_focus) def _(event): buffer = event.cli.buffers[event.cli.focus_stack.previous] buffer.incremental_search(IncrementalSearchDirection.BACKWARD) @handle(Keys.ControlS, filter=has_focus) @handle(Keys.Down, filter=has_focus) def _(event): buffer = event.cli.buffers[event.cli.focus_stack.previous] buffer.incremental_search(IncrementalSearchDirection.FORWARD)
def load_vi_system_bindings(registry, vi_state, filter=None, system_buffer_name='system'): assert isinstance(vi_state, ViState) has_focus = filters.HasFocus(system_buffer_name) navigation_mode = ViStateFilter( vi_state, InputMode.NAVIGATION) & ~filters.HasSelection() handle = create_handle_decorator(registry, filter) @handle('!', filter=~has_focus & navigation_mode) def _(event): """ '!' opens the system prompt. """ event.cli.focus_stack.push(system_buffer_name) vi_state.input_mode = InputMode.INSERT @handle(Keys.Escape, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) def _(event): """ Cancel system prompt. """ vi_state.input_mode = InputMode.NAVIGATION event.cli.buffers[system_buffer_name].reset() event.cli.focus_stack.pop() @handle(Keys.ControlJ, filter=has_focus) def _(event): """ Run system command. """ vi_state.input_mode = InputMode.NAVIGATION system_buffer = event.cli.buffers[system_buffer_name] event.cli.run_system_command(system_buffer.text) system_buffer.reset(append_to_history=True) # Focus previous buffer again. event.cli.focus_stack.pop()
def CreatePromptLayout(config, lexer=None, is_password=False, get_prompt_tokens=None, get_continuation_tokens=None, get_bottom_status_tokens=None, get_bottom_toolbar_tokens=None, extra_input_processors=None, multiline=False, show_help=True, wrap_lines=True): """Create a container instance for the prompt.""" assert get_bottom_status_tokens is None or callable( get_bottom_status_tokens) assert get_bottom_toolbar_tokens is None or callable( get_bottom_toolbar_tokens) assert get_prompt_tokens is None or callable(get_prompt_tokens) assert not (config.prompt and get_prompt_tokens) multi_column_completion_menu = filters.to_cli_filter( config.multi_column_completion_menu) multiline = filters.to_cli_filter(multiline) if get_prompt_tokens is None: get_prompt_tokens = lambda _: [(token.Token.Prompt, config.prompt)] has_before_tokens, get_prompt_tokens_1, get_prompt_tokens_2 = ( shortcuts._split_multiline_prompt(get_prompt_tokens)) # pylint: disable=protected-access # TODO(b/35347840): reimplement _split_multiline_prompt to remove # protected-access. # Create processors list. input_processors = [ 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.) processors.HighlightSearchProcessor(preview_search=True), filters.HasFocus(enums.SEARCH_BUFFER)), processors.HighlightSelectionProcessor(), processors.ConditionalProcessor( processors.AppendAutoSuggestion(), filters.HasFocus(enums.DEFAULT_BUFFER) & ~filters.IsDone()), processors.ConditionalProcessor(processors.PasswordProcessor(), is_password), ] if extra_input_processors: input_processors.extend(extra_input_processors) # Show the prompt before the input using the DefaultPrompt processor. # This also replaces it with reverse-i-search and 'arg' when required. # (Only for single line mode.) # (DefaultPrompt should always be at the end of the processors.) input_processors.append( processors.ConditionalProcessor( prompt.DefaultPrompt(get_prompt_tokens_2), ~multiline)) # Create toolbars toolbars = [] if config.fixed_prompt_position: help_height = dimension.LayoutDimension.exact(config.help_lines) help_filter = (show_help & ~filters.IsDone() & filters.RendererHeightIsKnown()) else: help_height = dimension.LayoutDimension(preferred=config.help_lines, max=config.help_lines) help_filter = (show_help & UserTypingFilter & ~filters.IsDone() & filters.RendererHeightIsKnown()) toolbars.append( containers.ConditionalContainer(layout.HSplit([ layout.Window( controls.FillControl(char=screen.Char('_', token.Token.HSep)), height=dimension.LayoutDimension.exact(1)), layout.Window(help_window.HelpWindowControl( default_char=screen.Char(' ', token.Token.Toolbar)), height=help_height), ]), filter=help_filter)) if (config.bottom_status_line and get_bottom_status_tokens or config.bottom_bindings_line and get_bottom_toolbar_tokens): windows = [] windows.append( layout.Window( controls.FillControl(char=screen.Char('_', token.Token.HSep)), height=dimension.LayoutDimension.exact(1))) if config.bottom_status_line and get_bottom_status_tokens: windows.append( layout.Window(controls.TokenListControl( get_bottom_status_tokens, default_char=screen.Char(' ', token.Token.Toolbar)), height=dimension.LayoutDimension.exact(1))) if config.bottom_bindings_line and get_bottom_toolbar_tokens: windows.append( layout.Window(controls.TokenListControl( get_bottom_toolbar_tokens, default_char=screen.Char(' ', token.Token.Toolbar)), height=dimension.LayoutDimension.exact(1))) toolbars.append( containers.ConditionalContainer(layout.HSplit(windows), filter=~filters.IsDone() & filters.RendererHeightIsKnown())) def GetHeight(cli): """Determine the height for the input buffer.""" # 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 cli.config.completion_menu_lines and not cli.is_done: # Reserve the space, either when there are completions, or when # `complete_while_typing` is true and we expect completions very # soon. buf = cli.current_buffer # if UserTypingFilter(cli) or not buf.text or buf.complete_state: if UserTypingFilter(cli) or buf.complete_state: return dimension.LayoutDimension( min=cli.config.completion_menu_lines + 1) return dimension.LayoutDimension() # Create and return Container instance. return layout.HSplit([ # The main input, with completion menus floating on top of it. containers.FloatContainer( layout.HSplit([ containers.ConditionalContainer( layout.Window( controls.TokenListControl(get_prompt_tokens_1), dont_extend_height=True, wrap_lines=wrap_lines, ), filters.Condition(has_before_tokens), ), layout.Window( controls.BufferControl( input_processors=input_processors, lexer=lexer, # Enable preview_search, we want to have immediate # feedback in reverse-i-search mode. preview_search=True, ), get_height=GetHeight, left_margins=[ # In multiline mode, use the window margin to display # the prompt and continuation tokens. margins.ConditionalMargin( margins.PromptMargin(get_prompt_tokens_2, get_continuation_tokens), filter=multiline, ), ], wrap_lines=wrap_lines, ), ]), [ # Completion menus. layout.Float( xcursor=True, ycursor=True, content=menus.CompletionsMenu( max_height=16, scroll_offset=1, extra_filter=(filters.HasFocus(enums.DEFAULT_BUFFER) & ~multi_column_completion_menu), ), ), layout.Float( ycursor=True, content=menus.MultiColumnCompletionsMenu( show_meta=True, extra_filter=(filters.HasFocus(enums.DEFAULT_BUFFER) & multi_column_completion_menu), ), ), ], ), pt_toolbars.ValidationToolbar(), pt_toolbars.SystemToolbar(), # In multiline mode, we use two toolbars for 'arg' and 'search'. containers.ConditionalContainer(pt_toolbars.ArgToolbar(), multiline), containers.ConditionalContainer(pt_toolbars.SearchToolbar(), multiline), ] + toolbars)
def load_vi_search_bindings(registry, vi_state, filter=None, search_buffer_name=SEARCH_BUFFER): assert isinstance(vi_state, ViState) has_focus = filters.HasFocus(search_buffer_name) navigation_mode = ~has_focus & (ViStateFilter( vi_state, InputMode.NAVIGATION) | filters.HasSelection()) handle = create_handle_decorator(registry, filter) @handle('/', filter=navigation_mode) @handle(Keys.ControlS, filter=~has_focus) def _(event): """ Vi-style forward search. """ # Set the ViState. event.cli.search_state.direction = IncrementalSearchDirection.FORWARD vi_state.input_mode = InputMode.INSERT # Focus search buffer. event.cli.focus_stack.push(search_buffer_name) @handle('?', filter=navigation_mode) @handle(Keys.ControlR, filter=~has_focus) def _(event): """ Vi-style backward search. """ # Set the ViState. event.cli.search_state.direction = IncrementalSearchDirection.BACKWARD # Focus search buffer. event.cli.focus_stack.push(search_buffer_name) vi_state.input_mode = InputMode.INSERT @handle(Keys.ControlJ, filter=has_focus) def _(event): """ Apply the search. (At the / or ? prompt.) """ input_buffer = event.cli.buffers[event.cli.focus_stack.previous] search_buffer = event.cli.buffers[search_buffer_name] # Update search state. if search_buffer.text: event.cli.search_state.text = search_buffer.text # Apply search. input_buffer.apply_search(event.cli.search_state) # Add query to history of search line. search_buffer.append_to_history() search_buffer.reset() # Focus previous document again. vi_state.input_mode = InputMode.NAVIGATION event.cli.focus_stack.pop() def search_buffer_is_empty(cli): """ Returns True when the search buffer is empty. """ return cli.buffers[search_buffer_name].text == '' @handle(Keys.Escape, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) @handle(Keys.Backspace, filter=has_focus & Condition(search_buffer_is_empty)) def _(event): """ Cancel search. """ vi_state.input_mode = InputMode.NAVIGATION event.cli.focus_stack.pop() event.cli.buffers[search_buffer_name].reset()
def load_emacs_search_bindings(registry, filter=None): handle = create_handle_decorator(registry, filter) has_focus = filters.HasFocus(SEARCH_BUFFER) @handle(Keys.ControlG, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) # NOTE: the reason for not also binding Escape to this one, is that we want # Alt+Enter to accept input directly in incremental search mode. def _(event): """ Abort an incremental search and restore the original line. """ search_buffer = event.cli.buffers[SEARCH_BUFFER] search_buffer.reset() event.cli.focus_stack.pop() @handle(Keys.ControlJ, filter=has_focus) def _(event): """ When enter pressed in isearch, quit isearch mode. (Multiline isearch would be too complicated.) """ input_buffer = event.cli.buffers[event.cli.focus_stack.previous] search_buffer = event.cli.buffers[SEARCH_BUFFER] # Update search state. if search_buffer.text: event.cli.search_state.text = search_buffer.text # Apply search. input_buffer.apply_search(event.cli.search_state, include_current_position=True) # Add query to history of search line. search_buffer.append_to_history() search_buffer.reset() # Focus previous document again. event.cli.focus_stack.pop() @handle(Keys.ControlR, filter=~has_focus) def _(event): event.cli.search_state.direction = IncrementalSearchDirection.BACKWARD event.cli.focus_stack.push(SEARCH_BUFFER) @handle(Keys.ControlS, filter=~has_focus) def _(event): event.cli.search_state.direction = IncrementalSearchDirection.FORWARD event.cli.focus_stack.push(SEARCH_BUFFER) @handle(Keys.ControlR, filter=has_focus) @handle(Keys.Up, filter=has_focus) def _(event): # Update search_state. search_state = event.cli.search_state direction_changed = search_state.direction != IncrementalSearchDirection.BACKWARD search_state.text = event.cli.buffers[SEARCH_BUFFER].text search_state.direction = IncrementalSearchDirection.BACKWARD # Apply search to current buffer. if not direction_changed: input_buffer = event.cli.buffers[event.cli.focus_stack.previous] input_buffer.apply_search(event.cli.search_state, include_current_position=False, count=event.arg) @handle(Keys.ControlS, filter=has_focus) @handle(Keys.Down, filter=has_focus) def _(event): # Update search_state. search_state = event.cli.search_state direction_changed = search_state.direction != IncrementalSearchDirection.FORWARD search_state.text = event.cli.buffers[SEARCH_BUFFER].text search_state.direction = IncrementalSearchDirection.FORWARD # Apply search to current buffer. if not direction_changed: input_buffer = event.cli.buffers[event.cli.focus_stack.previous] input_buffer.apply_search(event.cli.search_state, include_current_position=False, count=event.arg)
def load_emacs_search_bindings(registry, get_search_state=None, filter=None): handle = create_handle_decorator(registry, filter) has_focus = filters.HasFocus(SEARCH_BUFFER) assert get_search_state is None or callable(get_search_state) if not get_search_state: def get_search_state(cli): return cli.search_state @handle(Keys.ControlG, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) # NOTE: the reason for not also binding Escape to this one, is that we want # Alt+Enter to accept input directly in incremental search mode. def _(event): """ Abort an incremental search and restore the original line. """ search_buffer = event.cli.buffers[SEARCH_BUFFER] search_buffer.reset() event.cli.pop_focus() @handle(Keys.ControlJ, filter=has_focus) def _(event): """ When enter pressed in isearch, quit isearch mode. (Multiline isearch would be too complicated.) """ input_buffer = event.cli.buffers.previous(event.cli) search_buffer = event.cli.buffers[SEARCH_BUFFER] # Update search state. if search_buffer.text: get_search_state(event.cli).text = search_buffer.text # Apply search. input_buffer.apply_search(get_search_state(event.cli), include_current_position=True) # Add query to history of search line. search_buffer.append_to_history() search_buffer.reset() # Focus previous document again. event.cli.pop_focus() @handle(Keys.ControlR, filter=~has_focus) def _(event): get_search_state( event.cli).direction = IncrementalSearchDirection.BACKWARD event.cli.push_focus(SEARCH_BUFFER) @handle(Keys.ControlS, filter=~has_focus) def _(event): get_search_state( event.cli).direction = IncrementalSearchDirection.FORWARD event.cli.push_focus(SEARCH_BUFFER) def incremental_search(cli, direction, count=1): " Apply search, but keep search buffer focussed. " # Update search_state. search_state = get_search_state(cli) direction_changed = search_state.direction != direction search_state.text = cli.buffers[SEARCH_BUFFER].text search_state.direction = direction # Apply search to current buffer. if not direction_changed: input_buffer = cli.buffers.previous(cli) input_buffer.apply_search(search_state, include_current_position=False, count=count) @handle(Keys.ControlR, filter=has_focus) @handle(Keys.Up, filter=has_focus) def _(event): incremental_search(event.cli, IncrementalSearchDirection.BACKWARD, count=event.arg) @handle(Keys.ControlS, filter=has_focus) @handle(Keys.Down, filter=has_focus) def _(event): incremental_search(event.cli, IncrementalSearchDirection.FORWARD, count=event.arg)
def load_vi_search_bindings(registry, vi_state, filter=None, search_buffer_name='search'): assert isinstance(vi_state, ViState) has_focus = filters.HasFocus(search_buffer_name) navigation_mode = ~has_focus & (ViStateFilter( vi_state, InputMode.NAVIGATION) | filters.HasSelection()) handle = create_handle_decorator(registry, filter) @handle('/', filter=navigation_mode) @handle(Keys.ControlS) def _(event): """ Vi-style forward search. """ vi_state.search_direction = direction = IncrementalSearchDirection.FORWARD vi_state.input_mode = InputMode.INSERT if event.cli.focus_stack.current != search_buffer_name: event.cli.focus_stack.push(search_buffer_name) event.cli.buffers[event.cli.focus_stack.previous].incremental_search( direction) @handle('?', filter=navigation_mode) @handle(Keys.ControlR) def _(event): """ Vi-style backward search. """ vi_state.search_direction = direction = IncrementalSearchDirection.BACKWARD vi_state.input_mode = InputMode.INSERT if event.cli.focus_stack.current != search_buffer_name: event.cli.focus_stack.push(search_buffer_name) event.cli.buffers[event.cli.focus_stack.previous].incremental_search( direction) @handle(Keys.ControlJ, filter=has_focus) def _(event): """ Enter at the / or ? prompt. """ search_buffer = event.cli.buffers[search_buffer_name] vi_state.input_mode = InputMode.NAVIGATION # Add query to history of search line. search_buffer.add_to_history() search_buffer.reset() # Focus previous document again. event.cli.focus_stack.pop() @handle(Keys.Any, filter=has_focus) def _(event): """ Insert text after the / or ? prompt. """ event.cli.current_buffer.insert_text(event.data) # Set current search search text as line search text. buffer = event.cli.buffers[event.cli.focus_stack.previous] buffer.set_search_text(event.cli.current_buffer.text) @handle(Keys.Escape, filter=has_focus) @handle(Keys.ControlC, filter=has_focus) def _(event): """ Cancel search. """ vi_state.input_mode = InputMode.NAVIGATION event.cli.focus_stack.pop() event.current_buffer.exit_isearch(restore_original_line=True) event.cli.buffers[search_buffer_name].reset()