def custom_keybindings(bindings, **kw): from prompt_toolkit.filters import EmacsInsertMode, ViInsertMode from xonsh.ptk_shell.key_bindings import carriage_return handler = bindings.add insert_mode = ViInsertMode() | EmacsInsertMode() abbrev = Abbreviation() @handler(" ", filter=IsMultiline() & insert_mode) def handle_space(event): buffer = event.app.current_buffer add_space = True if not abbrev.revert(buffer): position_changed = abbrev.expand(buffer) if position_changed: add_space = False if add_space: buffer.insert_text(" ") @handler(Keys.ControlJ, filter=IsMultiline() & insert_mode & ~completion_is_selected) @handler(Keys.ControlM, filter=IsMultiline() & insert_mode & ~completion_is_selected) def multiline_carriage_return(event): buffer = event.app.current_buffer current_char = buffer.document.current_char if not current_char or current_char.isspace(): abbrev.expand(buffer) carriage_return(buffer, event.cli)
def custom_keybindings(bindings, **kw): from xonsh2.ptk_shell.key_bindings import carriage_return from prompt_toolkit.filters import EmacsInsertMode, ViInsertMode handler = bindings.add insert_mode = ViInsertMode() | EmacsInsertMode() @handler(" ", filter=IsMultiline() & insert_mode) def handle_space(event): buffer = event.app.current_buffer if not revert_abbrev(buffer): expand_abbrev(buffer) if last_expanded is None or not set_cursor_position(buffer): buffer.insert_text(" ") @handler(Keys.ControlJ, filter=IsMultiline() & insert_mode & ~completion_is_selected) @handler(Keys.ControlM, filter=IsMultiline() & insert_mode & ~completion_is_selected) def multiline_carriage_return(event): buffer = event.app.current_buffer current_char = buffer.document.current_char if not current_char or current_char.isspace(): expand_abbrev(buffer) carriage_return(buffer, event.cli)
def custom_keybindings(bindings, **kw): if ptk_shell_type() == "prompt_toolkit2": from xonsh.ptk2.key_bindings import carriage_return from prompt_toolkit.filters import EmacsInsertMode, ViInsertMode handler = bindings.add insert_mode = ViInsertMode() | EmacsInsertMode() else: from xonsh.ptk.key_bindings import carriage_return from prompt_toolkit.filters import to_filter handler = bindings.registry.add_binding insert_mode = to_filter(True) @handler(" ", filter=IsMultiline() & insert_mode) def handle_space(event): buffer = event.app.current_buffer expand_abbrev(buffer) buffer.insert_text(" ") @handler( Keys.ControlJ, filter=IsMultiline() & insert_mode & ~completion_is_selected ) @handler( Keys.ControlM, filter=IsMultiline() & insert_mode & ~completion_is_selected ) def multiline_carriage_return(event): buffer = event.app.current_buffer current_char = buffer.document.current_char if not current_char or current_char.isspace(): expand_abbrev(buffer) carriage_return(buffer, event.cli)
def load_xonsh_bindings(key_bindings_manager): """ Load custom key bindings. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() @handle(Keys.Tab, filter=TabShouldInsertIndentFilter()) def _(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlX, Keys.ControlE, filter=~has_selection) def open_editor(event): """ Open current buffer in editor """ event.current_buffer.open_in_editor(event.cli) @handle(Keys.BackTab) def insert_literal_tab(event): """ Insert literal tab on Shift+Tab instead of autocompleting """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlD, filter=ctrl_d_condition) def call_exit_alias(event): """Use xonsh exit function""" b = event.cli.current_buffer b.accept_action.validate_and_handle(event.cli, b) exit([]) @handle(Keys.ControlJ, filter=IsMultiline()) def multiline_carriage_return(event): """ Wrapper around carriage_return multiline parser """ b = event.cli.current_buffer carriage_return(b, event.cli) @handle(Keys.Left, filter=BeginningOfLine()) def wrap_cursor_back(event): """Move cursor to end of previous line unless at beginning of document""" b = event.cli.current_buffer b.cursor_up(count=1) relative_end_index = b.document.get_end_of_line_position() b.cursor_right(count=relative_end_index) @handle(Keys.Right, filter=EndOfLine()) def wrap_cursor_forward(event): """Move cursor to beginning of next line unless at end of document""" b = event.cli.current_buffer relative_begin_index = b.document.get_start_of_line_position() b.cursor_left(count=abs(relative_begin_index)) b.cursor_down(count=1)
def load_modified_bindings(registry, filter=Always()): handle = create_handle_decorator(registry, filter) has_selection = HasSelection() def at_the_end(b): text = b.document.text_after_cursor return text == '' or (text.isspace() and not '\n' in text) def lexes(b): try: tokenize(b.text) except Exception: return False return True @handle(Keys.ControlJ, filter=~has_selection & IsMultiline() & ~HasSearch(), save_before=False) def _(event): b = event.current_buffer # We don't need full validation here, just test if hy # can lex the text if at_the_end(b) and lexes(b): 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) @handle(Keys.ControlJ, filter=~has_selection & ~IsMultiline() & ~HasSearch(), save_before=False) def _(event): b = event.current_buffer if at_the_end(b) and lexes(b): b.accept_action.validate_and_handle(event.cli, b) else: auto_newline(b)
def main(): hy_repl = HyREPL() eventloop = create_eventloop() validator = HyValidator() history = FileHistory(expanduser("~/.pthy_history")) def src_is_multiline(): if app and app.buffer: text = app.buffer.document.text if '\n' in text: return True return False app = create_default_application( "λ: ", validator=validator, multiline=Condition(src_is_multiline), lexer=HyLexer, style=HyStyle, history=history, completer=HyCompleter(hy_repl), display_completions_in_columns=True, extra_input_processors=[ ConditionalProcessor(processor=HighlightMatchingBracketProcessor(), filter=~IsDone()) ]) # Somewhat ugly trick to add a margin to the multiline input # without needing to define a custom layout app.layout.children[0].children[ 1].content.content.margin = ConditionalMargin(NumberredMargin(), filter=IsMultiline()) cli = CommandLineInterface(application=app, eventloop=eventloop) load_modified_bindings(app.key_bindings_registry) hy_repl.cli = cli try: while True: try: code_obj = cli.run() hy_repl.evaluate(code_obj.text) except KeyboardInterrupt: pass except EOFError: pass finally: eventloop.close()
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 load_xonsh_bindings(key_bindings_manager): """ Load custom key bindings. """ handle = key_bindings_manager.registry.add_binding @handle(Keys.Tab, filter=TabShouldInsertIndentFilter()) def _(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.BackTab) def insert_literal_tab(event): """ Insert literal tab on Shift+Tab instead of autocompleting """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlJ, filter=IsMultiline()) def multiline_carriage_return(event): """ Wrapper around carriage_return multiline parser """ b = event.cli.current_buffer carriage_return(b, event.cli)
def load_xonsh_bindings(key_bindings): """ Load custom key bindings. """ handle = key_bindings.add has_selection = HasSelection() insert_mode = ViInsertMode() | EmacsInsertMode() @handle(Keys.Tab, filter=tab_insert_indent) def insert_indent(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ env = builtins.__xonsh__.env event.cli.current_buffer.insert_text(env.get("INDENT")) @handle(Keys.ControlX, Keys.ControlE, filter=~has_selection) def open_editor(event): """ Open current buffer in editor """ event.current_buffer.open_in_editor(event.cli) @handle(Keys.BackTab, filter=insert_mode) def insert_literal_tab(event): """ Insert literal tab on Shift+Tab instead of autocompleting """ b = event.current_buffer if b.complete_state: b.complete_previous() else: env = builtins.__xonsh__.env event.cli.current_buffer.insert_text(env.get("INDENT")) @handle("(", filter=autopair_condition & whitespace_or_bracket_after) def insert_right_parens(event): event.cli.current_buffer.insert_text("(") event.cli.current_buffer.insert_text(")", move_cursor=False) @handle(")", filter=autopair_condition) def overwrite_right_parens(event): buffer = event.cli.current_buffer if buffer.document.current_char == ")": buffer.cursor_position += 1 else: buffer.insert_text(")") @handle("[", filter=autopair_condition & whitespace_or_bracket_after) def insert_right_bracket(event): event.cli.current_buffer.insert_text("[") event.cli.current_buffer.insert_text("]", move_cursor=False) @handle("]", filter=autopair_condition) def overwrite_right_bracket(event): buffer = event.cli.current_buffer if buffer.document.current_char == "]": buffer.cursor_position += 1 else: buffer.insert_text("]") @handle("{", filter=autopair_condition & whitespace_or_bracket_after) def insert_right_brace(event): event.cli.current_buffer.insert_text("{") event.cli.current_buffer.insert_text("}", move_cursor=False) @handle("}", filter=autopair_condition) def overwrite_right_brace(event): buffer = event.cli.current_buffer if buffer.document.current_char == "}": buffer.cursor_position += 1 else: buffer.insert_text("}") @handle("'", filter=autopair_condition) def insert_right_quote(event): buffer = event.cli.current_buffer if buffer.document.current_char == "'": buffer.cursor_position += 1 elif whitespace_or_bracket_before() and whitespace_or_bracket_after(): buffer.insert_text("'") buffer.insert_text("'", move_cursor=False) else: buffer.insert_text("'") @handle('"', filter=autopair_condition) def insert_right_double_quote(event): buffer = event.cli.current_buffer if buffer.document.current_char == '"': buffer.cursor_position += 1 elif whitespace_or_bracket_before() and whitespace_or_bracket_after(): buffer.insert_text('"') buffer.insert_text('"', move_cursor=False) else: buffer.insert_text('"') @handle(Keys.Backspace, filter=autopair_condition) def delete_brackets_or_quotes(event): """Delete empty pair of brackets or quotes""" buffer = event.cli.current_buffer before = buffer.document.char_before_cursor after = buffer.document.current_char if any( [before == b and after == a for (b, a) in ["()", "[]", "{}", "''", '""']] ): buffer.delete(1) buffer.delete_before_cursor(1) @handle(Keys.ControlD, filter=ctrl_d_condition) def call_exit_alias(event): """Use xonsh exit function""" b = event.cli.current_buffer b.validate_and_handle() xonsh_exit([]) @handle(Keys.ControlJ, filter=IsMultiline()) @handle(Keys.ControlM, filter=IsMultiline()) def multiline_carriage_return(event): """ Wrapper around carriage_return multiline parser """ b = event.cli.current_buffer carriage_return(b, event.cli) @handle(Keys.ControlJ, filter=should_confirm_completion) @handle(Keys.ControlM, filter=should_confirm_completion) def enter_confirm_completion(event): """Ignore <enter> (confirm completion)""" event.current_buffer.complete_state = None @handle(Keys.Escape, filter=should_confirm_completion) def esc_cancel_completion(event): """Use <ESC> to cancel completion""" event.cli.current_buffer.cancel_completion() @handle(Keys.Escape, Keys.ControlJ) def execute_block_now(event): """Execute a block of text irrespective of cursor position""" b = event.cli.current_buffer b.validate_and_handle() @handle(Keys.Left, filter=beginning_of_line) def wrap_cursor_back(event): """Move cursor to end of previous line unless at beginning of document """ b = event.cli.current_buffer b.cursor_up(count=1) relative_end_index = b.document.get_end_of_line_position() b.cursor_right(count=relative_end_index) @handle(Keys.Right, filter=end_of_line) def wrap_cursor_forward(event): """Move cursor to beginning of next line unless at end of document""" b = event.cli.current_buffer relative_begin_index = b.document.get_start_of_line_position() b.cursor_left(count=abs(relative_begin_index)) b.cursor_down(count=1) @handle(Keys.ControlM, filter=IsSearching()) @handle(Keys.ControlJ, filter=IsSearching()) def accept_search(event): search.accept_search()
def load_xonsh_bindings(key_bindings_manager): """ Load custom key bindings. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() insert_mode = ViInsertMode() | EmacsInsertMode() @handle(Keys.Tab, filter=tab_insert_indent) def insert_indent(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlX, Keys.ControlE, filter=~has_selection) def open_editor(event): """ Open current buffer in editor """ event.current_buffer.open_in_editor(event.cli) @handle(Keys.BackTab, filter=insert_mode) def insert_literal_tab(event): """ Insert literal tab on Shift+Tab instead of autocompleting """ b = event.current_buffer if b.complete_state: b.complete_previous() else: event.cli.current_buffer.insert_text(env.get('INDENT')) @handle('(', filter=autopair_condition) def insert_right_parens(event): event.cli.current_buffer.insert_text('(') event.cli.current_buffer.insert_text(')', move_cursor=False) @handle(')', filter=autopair_condition) def overwrite_right_parens(event): buffer = event.cli.current_buffer if buffer.document.current_char == ')': buffer.cursor_position += 1 else: buffer.insert_text(')') @handle('[', filter=autopair_condition) def insert_right_bracket(event): event.cli.current_buffer.insert_text('[') event.cli.current_buffer.insert_text(']', move_cursor=False) @handle(']', filter=autopair_condition) def overwrite_right_bracket(event): buffer = event.cli.current_buffer if buffer.document.current_char == ']': buffer.cursor_position += 1 else: buffer.insert_text(']') @handle('\'', filter=autopair_condition) def insert_right_quote(event): buffer = event.cli.current_buffer if buffer.document.current_char == '\'': buffer.cursor_position += 1 else: buffer.insert_text('\'') buffer.insert_text('\'', move_cursor=False) @handle('"', filter=autopair_condition) def insert_right_double_quote(event): buffer = event.cli.current_buffer if buffer.document.current_char == '"': buffer.cursor_position += 1 else: buffer.insert_text('"') buffer.insert_text('"', move_cursor=False) @handle(Keys.ControlD, filter=ctrl_d_condition) def call_exit_alias(event): """Use xonsh exit function""" b = event.cli.current_buffer b.accept_action.validate_and_handle(event.cli, b) xonsh_exit([]) @handle(Keys.ControlJ, filter=IsMultiline()) def multiline_carriage_return(event): """ Wrapper around carriage_return multiline parser """ b = event.cli.current_buffer carriage_return(b, event.cli) @handle(Keys.ControlJ, filter=should_confirm_completion) def enter_confirm_completion(event): """Ignore <enter> (confirm completion)""" event.current_buffer.complete_state = None @handle(Keys.Escape, filter=should_confirm_completion) def esc_cancel_completion(event): """Use <ESC> to cancel completion""" event.cli.current_buffer.cancel_completion() @handle(Keys.Escape, Keys.ControlJ) def execute_block_now(event): """Execute a block of text irrespective of cursor position""" b = event.cli.current_buffer b.accept_action.validate_and_handle(event.cli, b) @handle(Keys.Left, filter=beginning_of_line) def wrap_cursor_back(event): """Move cursor to end of previous line unless at beginning of document """ b = event.cli.current_buffer b.cursor_up(count=1) relative_end_index = b.document.get_end_of_line_position() b.cursor_right(count=relative_end_index) @handle(Keys.Right, filter=end_of_line) def wrap_cursor_forward(event): """Move cursor to beginning of next line unless at end of document""" b = event.cli.current_buffer relative_begin_index = b.document.get_start_of_line_position() b.cursor_left(count=abs(relative_begin_index)) b.cursor_down(count=1) @handle(Keys.ControlI, filter=insert_mode) def generate_completions(event): """ Tab-completion: where the first tab completes the common suffix and the second tab lists all the completions. Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. """ b = event.current_buffer def second_tab(): if b.complete_state: b.complete_next() else: event.cli.start_completion(select_first=False) # On the second tab-press, or when already navigating through # completions. if event.is_repeat or b.complete_state: second_tab() else: event.cli.start_completion(insert_common_part=True, select_first=False)
def load_python_bindings(key_bindings_manager, settings): """ Custom key bindings. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() @handle(Keys.F2) def _(event): """ Show/hide sidebar. """ settings.show_sidebar = not settings.show_sidebar @handle(Keys.F3) def _(event): """ Shange completion style. """ # Toggle between combinations. settings.show_completions_toolbar, settings.show_completions_menu = { (False, False): (False, True), (False, True): (True, False), (True, False): (False, False), }[settings.show_completions_toolbar, settings.show_completions_menu] @handle(Keys.F4) def _(event): """ Toggle between Vi and Emacs mode. """ key_bindings_manager.enable_vi_mode = not key_bindings_manager.enable_vi_mode @handle(Keys.F5) def _(event): """ Enable/Disable complete while typing. """ settings.complete_while_typing = not settings.complete_while_typing @handle(Keys.F6) def _(event): """ Enable/Disable paste mode. """ settings.paste_mode = not settings.paste_mode @handle(Keys.F8) def _(event): """ Show/hide signature. """ settings.show_signature = not settings.show_signature @handle(Keys.F9) def _(event): """ Show/hide docstring window. """ settings.show_docstring = not settings.show_docstring @handle(Keys.F10) def _(event): """ Show/hide line numbers """ settings.show_line_numbers = not settings.show_line_numbers @handle(Keys.Tab, filter=~has_selection & TabShouldInsertWhitespaceFilter()) def _(event): """ When tab should insert whitespace, do that instead of completion. """ event.cli.current_buffer.insert_text(' ') @handle(Keys.ControlJ, filter=~has_selection & ~(ViModeEnabled(key_bindings_manager) & ViStateFilter( key_bindings_manager.vi_state, InputMode.NAVIGATION)) & HasFocus('default') & 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 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 settings.paste_mode: # In paste mode, always insert text. b.insert_text('\n') elif at_the_end(b) and b.document.text.replace(' ', '').endswith('\n'): if b.validate(): # 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.append_to_history() event.cli.set_return_value(b.document) else: auto_newline(b)
def load_xonsh_bindings(key_bindings_manager): """ Load custom key bindings. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() insert_mode = ViInsertMode() | EmacsInsertMode() @handle(Keys.Tab, filter=TabShouldInsertIndentFilter()) def _(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlX, Keys.ControlE, filter=~has_selection) def open_editor(event): """ Open current buffer in editor """ event.current_buffer.open_in_editor(event.cli) @handle(Keys.BackTab) def insert_literal_tab(event): """ Insert literal tab on Shift+Tab instead of autocompleting """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlD, filter=ctrl_d_condition) def call_exit_alias(event): """Use xonsh exit function""" b = event.cli.current_buffer b.accept_action.validate_and_handle(event.cli, b) xonsh_exit([]) @handle(Keys.ControlJ, filter=IsMultiline()) def multiline_carriage_return(event): """ Wrapper around carriage_return multiline parser """ b = event.cli.current_buffer carriage_return(b, event.cli) @handle(Keys.Left, filter=BeginningOfLine()) def wrap_cursor_back(event): """Move cursor to end of previous line unless at beginning of document""" b = event.cli.current_buffer b.cursor_up(count=1) relative_end_index = b.document.get_end_of_line_position() b.cursor_right(count=relative_end_index) @handle(Keys.Right, filter=EndOfLine()) def wrap_cursor_forward(event): """Move cursor to beginning of next line unless at end of document""" b = event.cli.current_buffer relative_begin_index = b.document.get_start_of_line_position() b.cursor_left(count=abs(relative_begin_index)) b.cursor_down(count=1) @handle(Keys.ControlI, filter=insert_mode) def generate_completions(event): """ Tab-completion: where the first tab completes the common suffix and the second tab lists all the completions. Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. """ b = event.current_buffer def second_tab(): if b.complete_state: b.complete_next() else: event.cli.start_completion(select_first=False) # On the second tab-press, or when already navigating through # completions. if event.is_repeat or b.complete_state: second_tab() else: event.cli.start_completion(insert_common_part=True, select_first=False)
def load_python_bindings(key_bindings_manager, settings, add_buffer, close_current_buffer): """ Custom key bindings. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() vi_navigation_mode = ViStateFilter(key_bindings_manager.vi_state, InputMode.NAVIGATION) & \ ~ HasSelection() @handle(Keys.F2) def _(event): """ Show/hide sidebar. """ settings.show_sidebar = not settings.show_sidebar @handle(Keys.F3) def _(event): """ Shange completion style. """ # Toggle between combinations. settings.show_completions_toolbar, settings.show_completions_menu = { (False, False): (False, True), (False, True): (True, False), (True, False): (False, False), }[settings.show_completions_toolbar, settings.show_completions_menu] @handle(Keys.F4) def _(event): """ Toggle between Vi and Emacs mode. """ key_bindings_manager.enable_vi_mode = not key_bindings_manager.enable_vi_mode @handle(Keys.F6) def _(event): """ Enable/Disable paste mode. """ settings.paste_mode = not settings.paste_mode @handle(Keys.F7) def _(event): """ Enable/Disable multiline mode. """ settings.currently_multiline = not settings.currently_multiline @handle(Keys.F8) def _(event): """ Show/hide signature. """ settings.show_signature = not settings.show_signature @handle(Keys.F9) def _(event): """ Show/hide docstring window. """ settings.show_docstring = not settings.show_docstring @handle(Keys.F10) def _(event): """ Show/hide line numbers """ settings.show_line_numbers = not settings.show_line_numbers @handle(Keys.F5) def _(event): """ Show all buffers """ settings.show_all_buffers = not settings.show_all_buffers @handle('g', 't', filter=vi_navigation_mode) @handle(Keys.ControlRight) def _(event): """ Focus next tab. """ focus_next_buffer(event.cli) @handle('g', 'T', filter=vi_navigation_mode) @handle(Keys.ControlLeft) def _(event): """ Focus previous tab. """ focus_previous_buffer(event.cli) # @handle(Keys.F5, filter=filters.HasFocus('default') & ~has_selection) # XXX: use current tab # def _(event): # """ # Merge the previous entry from the history on top. # """ # buffer = event.cli.buffers['default'] # # buffer.text = buffer._working_lines[buffer.working_index - 1] + '\n' + buffer.text # buffer._working_lines = buffer._working_lines[:buffer.working_index - 1] + buffer._working_lines[buffer.working_index:] # buffer.working_index -= 1 @handle(Keys.ControlT, filter=IsPythonBufferFocussed() & ~has_selection) def _(event): """ Create a new Python buffer. """ add_buffer() @handle(Keys.ControlD, filter=IsPythonBufferFocussed()) def _(event): """ Close Python buffer. """ close_current_buffer() @handle(Keys.Tab, filter=~has_selection) def _(event): """ When the 'tab' key is pressed with only whitespace character before the cursor, do autocompletion. Otherwise, insert indentation. """ buffer = event.cli.current_buffer current_char = buffer.document.current_line_before_cursor if not current_char or current_char.isspace(): buffer.insert_text(' ') else: buffer.complete_next() @handle(Keys.ControlJ, filter=~has_selection & ~(ViModeEnabled(key_bindings_manager) & ViStateFilter( key_bindings_manager.vi_state, InputMode.NAVIGATION)) & IsPythonBufferFocussed() & IsMultiline()) def _(event): """ Auto indent after newline/Enter. (When not in Vi navigaton mode, and when multiline is enabled.) """ buffer = event.current_buffer if settings.paste_mode: buffer.insert_text('\n') else: auto_newline(buffer)
def load_python_bindings(key_bindings_manager, python_input): """ Custom key bindings. """ sidebar_visible = Condition(lambda cli: python_input.show_sidebar) handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() vi_mode_enabled = Condition(lambda cli: python_input.vi_mode) @handle(Keys.ControlL) def _(event): """ Clear whole screen and render again -- also when the sidebar is visible. """ event.cli.renderer.clear() @handle(Keys.F2) def _(event): """ Show/hide sidebar. """ python_input.show_sidebar = not python_input.show_sidebar @handle(Keys.F3) def _(event): """ Select from the history. """ python_input.enter_history(event.cli) @handle(Keys.F4) def _(event): """ Toggle between Vi and Emacs mode. """ python_input.vi_mode = not python_input.vi_mode @handle(Keys.F6) def _(event): """ Enable/Disable paste mode. """ python_input.paste_mode = not python_input.paste_mode @handle(Keys.Tab, filter= ~sidebar_visible & ~has_selection & TabShouldInsertWhitespaceFilter()) def _(event): """ When tab should insert whitespace, do that instead of completion. """ event.cli.current_buffer.insert_text(' ') @handle(Keys.ControlJ, filter= ~sidebar_visible & ~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 = python_input.accept_input_on_enter or 10000 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 python_input.paste_mode: # In paste mode, always insert text. b.insert_text('\n') elif at_the_end(b) and b.document.text.replace(' ', '').endswith( '\n' * (empty_lines_required - 1)): if b.validate(): # 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) @handle(Keys.ControlD, filter=~sidebar_visible & Condition(lambda cli: # Only when the `confirm_exit` flag is set. python_input.confirm_exit and # And the current buffer is empty. cli.current_buffer_name == DEFAULT_BUFFER and not cli.current_buffer.text)) def _(event): """ Override Control-D exit, to ask for confirmation. """ python_input.show_exit_confirmation = True
def load_xonsh_bindings(key_bindings_manager): """ Load custom key bindings. """ handle = key_bindings_manager.registry.add_binding env = builtins.__xonsh_env__ indent_ = env.get('INDENT') DEDENT_TOKENS = frozenset(['raise', 'return', 'pass', 'break', 'continue']) @handle(Keys.Tab, filter=TabShouldInsertIndentFilter()) def _(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.BackTab) def insert_literal_tab(event): """ Insert literal tab on Shift+Tab instead of autocompleting """ event.cli.current_buffer.insert_text(env.get('INDENT')) @handle(Keys.ControlJ, filter=IsMultiline()) def multiline_carriage_return(event): """ Preliminary parser to determine if 'Enter' key should send command to the xonsh parser for execution or should insert a newline for continued input. Current 'triggers' for inserting a newline are: - Not on first line of buffer and line is non-empty - Previous character is a colon (covers if, for, etc...) - User is in an open paren-block - Line ends with backslash - Any text exists below cursor position (relevant when editing previous multiline blocks) """ b = event.cli.current_buffer # indent after a colon if b.document.char_before_cursor == ':': b.newline() b.insert_text(indent_, fire_event=False) # if current line isn't blank, check dedent tokens elif (not (len(b.document.current_line) == 0 or b.document.current_line.isspace()) and b.document.current_line.split(maxsplit=1)[0] in DEDENT_TOKENS): b.newline(copy_margin=True) _ = b.delete_before_cursor(count=len(indent_)) elif (not b.document.on_first_line and not (len(b.document.current_line) == 0 or b.document.current_line.isspace())): b.newline(copy_margin=True) elif b.document.char_before_cursor == '\\': b.newline() elif b.document.find_next_word_beginning() is not None: b.newline(copy_margin=True) elif not can_compile(b.document.text): b.newline() else: b.accept_action.validate_and_handle(event.cli, b)
def load_xonsh_bindings(ptk_bindings: KeyBindingsBase) -> KeyBindingsBase: """ Load custom key bindings. Parameters ---------- ptk_bindings : The default prompt toolkit bindings. We need these to add aliases to them. """ key_bindings = KeyBindings() handle = key_bindings.add has_selection = HasSelection() insert_mode = ViInsertMode() | EmacsInsertMode() if XSH.env["XONSH_CTRL_BKSP_DELETION"]: # Not all terminal emulators emit the same keys for backspace, therefore # ptk always maps backspace ("\x7f") to ^H ("\x08"), and all the backspace bindings are registered for ^H. # This means we can't re-map backspace and instead we register a new "real-ctrl-bksp" key. # See https://github.com/xonsh/xonsh/issues/4407 if ON_WINDOWS: # On windows BKSP is "\x08" and CTRL-BKSP is "\x7f" REAL_CTRL_BKSP = "\x7f" # PTK uses a second mapping from prompt_toolkit.input import win32 as ptk_win32 ptk_win32.ConsoleInputReader.mappings[b"\x7f"] = REAL_CTRL_BKSP # type: ignore else: REAL_CTRL_BKSP = "\x08" # Prompt-toolkit allows using single-character keys that aren't in the `Keys` enum. ansi_escape_sequences.ANSI_SEQUENCES[REAL_CTRL_BKSP] = REAL_CTRL_BKSP # type: ignore ansi_escape_sequences.REVERSE_ANSI_SEQUENCES[REAL_CTRL_BKSP] = REAL_CTRL_BKSP # type: ignore @handle(REAL_CTRL_BKSP, filter=insert_mode) def delete_word(event): """Delete a single word (like ALT-backspace)""" get_by_name("backward-kill-word").call(event) @handle(Keys.Tab, filter=tab_insert_indent) def insert_indent(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ env = XSH.env event.cli.current_buffer.insert_text(env.get("INDENT")) @handle(Keys.Tab, filter=~tab_insert_indent & tab_menu_complete) def menu_complete_select(event): """Start completion in menu-complete mode, or tab to next completion""" b = event.current_buffer if b.complete_state: b.complete_next() else: b.start_completion(select_first=True) @handle(Keys.ControlX, Keys.ControlE, filter=~has_selection) def open_editor(event): """Open current buffer in editor""" event.current_buffer.open_in_editor(event.cli) @handle(Keys.BackTab, filter=insert_mode) def insert_literal_tab(event): """Insert literal tab on Shift+Tab instead of autocompleting""" b = event.current_buffer if b.complete_state: b.complete_previous() else: env = XSH.env event.cli.current_buffer.insert_text(env.get("INDENT")) def generate_parens_handlers(left, right): @handle(left, filter=autopair_condition) def insert_left_paren(event): buffer = event.cli.current_buffer if has_selection(): wrap_selection(buffer, left, right) elif whitespace_or_bracket_after(): buffer.insert_text(left) buffer.insert_text(right, move_cursor=False) else: buffer.insert_text(left) @handle(right, filter=autopair_condition) def overwrite_right_paren(event): buffer = event.cli.current_buffer if buffer.document.current_char == right: buffer.cursor_position += 1 else: buffer.insert_text(right) generate_parens_handlers("(", ")") generate_parens_handlers("[", "]") generate_parens_handlers("{", "}") def generate_quote_handler(quote): @handle(quote, filter=autopair_condition) def insert_quote(event): buffer = event.cli.current_buffer if has_selection(): wrap_selection(buffer, quote, quote) elif buffer.document.current_char == quote: buffer.cursor_position += 1 elif whitespace_or_bracket_before() and whitespace_or_bracket_after(): buffer.insert_text(quote) buffer.insert_text(quote, move_cursor=False) else: buffer.insert_text(quote) generate_quote_handler("'") generate_quote_handler('"') @handle(Keys.Backspace, filter=autopair_condition) def delete_brackets_or_quotes(event): """Delete empty pair of brackets or quotes""" buffer = event.cli.current_buffer before = buffer.document.char_before_cursor after = buffer.document.current_char if any( [before == b and after == a for (b, a) in ["()", "[]", "{}", "''", '""']] ): buffer.delete(1) buffer.delete_before_cursor(1) @handle(Keys.ControlD, filter=ctrl_d_condition) def call_exit_alias(event): """Use xonsh exit function""" b = event.cli.current_buffer b.validate_and_handle() xonsh_exit([]) @handle(Keys.ControlJ, filter=IsMultiline() & insert_mode) @handle(Keys.ControlM, filter=IsMultiline() & insert_mode) def multiline_carriage_return(event): """Wrapper around carriage_return multiline parser""" b = event.cli.current_buffer carriage_return(b, event.cli) @handle(Keys.ControlJ, filter=should_confirm_completion) @handle(Keys.ControlM, filter=should_confirm_completion) def enter_confirm_completion(event): """Ignore <enter> (confirm completion)""" event.current_buffer.complete_state = None @handle(Keys.Escape, filter=should_confirm_completion) def esc_cancel_completion(event): """Use <ESC> to cancel completion""" event.cli.current_buffer.cancel_completion() @handle(Keys.Escape, Keys.ControlJ) def execute_block_now(event): """Execute a block of text irrespective of cursor position""" b = event.cli.current_buffer b.validate_and_handle() @handle(Keys.Left, filter=beginning_of_line) def wrap_cursor_back(event): """Move cursor to end of previous line unless at beginning of document """ b = event.cli.current_buffer b.cursor_up(count=1) relative_end_index = b.document.get_end_of_line_position() b.cursor_right(count=relative_end_index) @handle(Keys.Right, filter=end_of_line) def wrap_cursor_forward(event): """Move cursor to beginning of next line unless at end of document""" b = event.cli.current_buffer relative_begin_index = b.document.get_start_of_line_position() b.cursor_left(count=abs(relative_begin_index)) b.cursor_down(count=1) @handle(Keys.ControlM, filter=IsSearching()) @handle(Keys.ControlJ, filter=IsSearching()) def accept_search(event): search.accept_search() @handle(Keys.ControlZ) def skip_control_z(event): """Prevents the writing of ^Z to the prompt, if Ctrl+Z was pressed during the previous command. """ pass @handle(Keys.ControlX, Keys.ControlX, filter=has_selection) def _cut(event): """Cut selected text.""" data = event.current_buffer.cut_selection() event.app.clipboard.set_data(data) @handle(Keys.ControlX, Keys.ControlC, filter=has_selection) def _copy(event): """Copy selected text.""" data = event.current_buffer.copy_selection() event.app.clipboard.set_data(data) @handle(Keys.ControlV, filter=insert_mode | has_selection) def _yank(event): """Paste selected text.""" buff = event.current_buffer if buff.selection_state: buff.cut_selection() get_by_name("yank").call(event) def create_alias(new_keys, original_keys): bindings = ptk_bindings.get_bindings_for_keys(tuple(original_keys)) for original_binding in bindings: handle(*new_keys, filter=original_binding.filter)(original_binding.handler) # Complete a single auto-suggestion word create_alias([Keys.ControlRight], ["escape", "f"]) return key_bindings
def load_bindings(key_bindings_manager): """ Load keybindings into prompt_toolkit. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() # for some reason Pylint doesn't think this function is "used" @key_bindings_manager.registry.add_binding(Keys.ControlL) def clear_(event): # pylint: disable=unused-variable """ Clear the screen. """ clear() print(env.welcome) print(env.get_prompt(), end="") @handle(Keys.Tab, filter=TabShouldInsertWhitespaceFilter()) def _(event): """ When tab should insert whitespace, do that instead of completion. """ event.cli.current_buffer.insert_text(' ') # prompt_toolkit _wants_ these two methods (they have different filter # attributes) @handle(Keys.ControlJ, filter=~has_selection & (ViInsertMode() | EmacsInsertMode()) & HasFocus(DEFAULT_BUFFER) & IsMultiline()) def _(event): # pylint: disable=function-redefined """ Behaviour of the Enter key. Auto indent after newline/Enter. (When not in Vi navigaton mode, and when multiline is enabled.) """ current_buffer = event.current_buffer empty_lines_required = 2 def at_the_end(ptk_buffer): """ we consider the cursor at the end when there is no text after the cursor, or only whitespace. """ text = ptk_buffer.document.text_after_cursor return text == '' or (text.isspace() and not '\n' in text) def all_blocks_closed(ptk_buffer): """Return True when all Ergonomica code blocks are closed.""" return tokenize(ptk_buffer.text).count("(") == tokenize( ptk_buffer.text).count(")") if at_the_end(current_buffer)\ and (current_buffer.document.text.replace(' ', '') .endswith('\n' * (empty_lines_required - 1) ) or all_blocks_closed(current_buffer)): current_buffer.document = Document( text=current_buffer.text.rstrip(), cursor_position=len(current_buffer.text.rstrip())) current_buffer.accept_action.validate_and_handle( event.cli, current_buffer) else: _auto_newline(current_buffer)
def load_xonsh_bindings() -> KeyBindingsBase: """ Load custom key bindings. """ key_bindings = KeyBindings() handle = key_bindings.add has_selection = HasSelection() insert_mode = ViInsertMode() | EmacsInsertMode() @handle(Keys.Tab, filter=tab_insert_indent) def insert_indent(event): """ If there are only whitespaces before current cursor position insert indent instead of autocompleting. """ env = builtins.__xonsh__.env event.cli.current_buffer.insert_text(env.get("INDENT")) @handle(Keys.Tab, filter=~tab_insert_indent & tab_menu_complete) def menu_complete_select(event): """Start completion in menu-complete mode, or tab to next completion""" b = event.current_buffer if b.complete_state: b.complete_next() else: b.start_completion(select_first=True) @handle(Keys.ControlX, Keys.ControlE, filter=~has_selection) def open_editor(event): """Open current buffer in editor""" event.current_buffer.open_in_editor(event.cli) @handle(Keys.BackTab, filter=insert_mode) def insert_literal_tab(event): """Insert literal tab on Shift+Tab instead of autocompleting""" b = event.current_buffer if b.complete_state: b.complete_previous() else: env = builtins.__xonsh__.env event.cli.current_buffer.insert_text(env.get("INDENT")) def generate_parens_handlers(left, right): @handle(left, filter=autopair_condition) def insert_left_paren(event): buffer = event.cli.current_buffer if has_selection(): wrap_selection(buffer, left, right) elif whitespace_or_bracket_after(): buffer.insert_text(left) buffer.insert_text(right, move_cursor=False) else: buffer.insert_text(left) @handle(right, filter=autopair_condition) def overwrite_right_paren(event): buffer = event.cli.current_buffer if buffer.document.current_char == right: buffer.cursor_position += 1 else: buffer.insert_text(right) generate_parens_handlers("(", ")") generate_parens_handlers("[", "]") generate_parens_handlers("{", "}") def generate_quote_handler(quote): @handle(quote, filter=autopair_condition) def insert_quote(event): buffer = event.cli.current_buffer if has_selection(): wrap_selection(buffer, quote, quote) elif buffer.document.current_char == quote: buffer.cursor_position += 1 elif whitespace_or_bracket_before() and whitespace_or_bracket_after(): buffer.insert_text(quote) buffer.insert_text(quote, move_cursor=False) else: buffer.insert_text(quote) generate_quote_handler("'") generate_quote_handler('"') @handle(Keys.Backspace, filter=autopair_condition) def delete_brackets_or_quotes(event): """Delete empty pair of brackets or quotes""" buffer = event.cli.current_buffer before = buffer.document.char_before_cursor after = buffer.document.current_char if any( [before == b and after == a for (b, a) in ["()", "[]", "{}", "''", '""']] ): buffer.delete(1) buffer.delete_before_cursor(1) @handle(Keys.ControlD, filter=ctrl_d_condition) def call_exit_alias(event): """Use xonsh exit function""" b = event.cli.current_buffer b.validate_and_handle() xonsh_exit([]) @handle(Keys.ControlJ, filter=IsMultiline() & insert_mode) @handle(Keys.ControlM, filter=IsMultiline() & insert_mode) def multiline_carriage_return(event): """Wrapper around carriage_return multiline parser""" b = event.cli.current_buffer carriage_return(b, event.cli) @handle(Keys.ControlJ, filter=should_confirm_completion) @handle(Keys.ControlM, filter=should_confirm_completion) def enter_confirm_completion(event): """Ignore <enter> (confirm completion)""" event.current_buffer.complete_state = None @handle(Keys.Escape, filter=should_confirm_completion) def esc_cancel_completion(event): """Use <ESC> to cancel completion""" event.cli.current_buffer.cancel_completion() @handle(Keys.Escape, Keys.ControlJ) def execute_block_now(event): """Execute a block of text irrespective of cursor position""" b = event.cli.current_buffer b.validate_and_handle() @handle(Keys.Left, filter=beginning_of_line) def wrap_cursor_back(event): """Move cursor to end of previous line unless at beginning of document """ b = event.cli.current_buffer b.cursor_up(count=1) relative_end_index = b.document.get_end_of_line_position() b.cursor_right(count=relative_end_index) @handle(Keys.Right, filter=end_of_line) def wrap_cursor_forward(event): """Move cursor to beginning of next line unless at end of document""" b = event.cli.current_buffer relative_begin_index = b.document.get_start_of_line_position() b.cursor_left(count=abs(relative_begin_index)) b.cursor_down(count=1) @handle(Keys.ControlM, filter=IsSearching()) @handle(Keys.ControlJ, filter=IsSearching()) def accept_search(event): search.accept_search() @handle(Keys.ControlZ) def skip_control_z(event): """Prevents the writing of ^Z to the prompt, if Ctrl+Z was pressed during the previous command. """ pass @handle(Keys.ControlX, Keys.ControlX, filter=has_selection) def _cut(event): """Cut selected text.""" data = event.current_buffer.cut_selection() event.app.clipboard.set_data(data) @handle(Keys.ControlX, Keys.ControlC, filter=has_selection) def _copy(event): """Copy selected text.""" data = event.current_buffer.copy_selection() event.app.clipboard.set_data(data) @handle(Keys.ControlV, filter=insert_mode | has_selection) def _yank(event): """Paste selected text.""" buff = event.current_buffer if buff.selection_state: buff.cut_selection() get_by_name("yank").call(event) return key_bindings