diff --git a/examples/ptpython_config/config.py b/examples/ptpython_config/config.py index ff8b8ac1..371421fe 100644 --- a/examples/ptpython_config/config.py +++ b/examples/ptpython_config/config.py @@ -119,6 +119,12 @@ def configure(repl): # Syntax. repl.enable_syntax_highlighting = True + # Get into Vi navigation mode at startup + repl.vi_start_in_nav_mode = False + + # Preserve last used Vi input mode between main loop iterations + repl.vi_keep_last_used_mode = False + # Install custom colorscheme named 'my-colorscheme' and use it. """ repl.install_ui_colorscheme('my-colorscheme', _custom_ui_colorscheme) diff --git a/ptpython/python_input.py b/ptpython/python_input.py index c4bbbd0c..2bb47fca 100644 --- a/ptpython/python_input.py +++ b/ptpython/python_input.py @@ -298,6 +298,12 @@ def __init__( # (Never run more than one at the same time.) self._get_signatures_thread_running: bool = False + # Get into Vi navigation mode at startup + self.vi_start_in_nav_mode: bool = False + + # Preserve last used Vi input mode between main loop iterations + self.vi_keep_last_used_mode: bool = False + self.style_transformation = merge_style_transformations( [ ConditionalStyleTransformation( diff --git a/ptpython/repl.py b/ptpython/repl.py index 4b8edf2a..7cba463f 100644 --- a/ptpython/repl.py +++ b/ptpython/repl.py @@ -22,6 +22,7 @@ merge_formatted_text, ) from prompt_toolkit.formatted_text.utils import fragment_list_width +from prompt_toolkit.key_binding.vi_state import InputMode from prompt_toolkit.patch_stdout import patch_stdout as patch_stdout_context from prompt_toolkit.shortcuts import clear_title, print_formatted_text, set_title from prompt_toolkit.utils import DummyContext @@ -70,9 +71,19 @@ def prompt() -> str: # This happens when the user used `asyncio.run()`. old_loop = None + # Capture the current input_mode in order to restore it after reset, + # for ViState.reset() sets it to InputMode.INSERT unconditionally and + # doesn't accept any arguments despite the docstring says otherwise. + def pre_run(last_input_mode=self.app.vi_state.input_mode): + if self.vi_keep_last_used_mode: + self.app.vi_state.input_mode = last_input_mode + + if not self.vi_keep_last_used_mode and self.vi_start_in_nav_mode: + self.app.vi_state.input_mode = InputMode.NAVIGATION + asyncio.set_event_loop(self.pt_loop) try: - return self.app.run() # inputhook=inputhook) + return self.app.run(pre_run) # inputhook=inputhook) finally: # Restore the original event loop. asyncio.set_event_loop(old_loop) @@ -360,6 +371,10 @@ def get_locals(): if configure: configure(repl) + # Set Vi input mode + if repl.vi_start_in_nav_mode: + repl.app.vi_state.input_mode = InputMode.NAVIGATION + # Start repl. patch_context: ContextManager = patch_stdout_context() if patch_stdout else DummyContext()