diff --git a/IPython/terminal/interactiveshell.py b/IPython/terminal/interactiveshell.py index 0953d32..f2bc579 100644 --- a/IPython/terminal/interactiveshell.py +++ b/IPython/terminal/interactiveshell.py @@ -12,8 +12,19 @@ from IPython.utils.py3compat import input from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title from IPython.utils.process import abbrev_cwd from traitlets import ( - Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union, - Any, validate + Bool, + Unicode, + Dict, + Integer, + observe, + Instance, + Type, + default, + Enum, + Union, + Any, + validate, + Float, ) from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode @@ -142,6 +153,25 @@ class TerminalInteractiveShell(InteractiveShell): help="Add shortcuts from 'emacs' insert mode to 'vi' insert mode.", ).tag(config=True) + modal_cursor = Bool( + True, + help=""" + Cursor shape changes depending on vi mode: beam in vi insert mode, + block in nav mode, underscore in replace mode.""", + ).tag(config=True) + + ttimeoutlen = Float( + 0.01, + help="""The time in milliseconds that is waited for a key code + to complete.""", + ).tag(config=True) + + timeoutlen = Float( + 0.5, + help="""The time in milliseconds that is waited for a mapped key + sequence to complete.""", + ).tag(config=True) + autoformatter = Unicode(None, help="Autoformatter to reformat Terminal code. Can be `'black'` or `None`", allow_none=True diff --git a/IPython/terminal/shortcuts.py b/IPython/terminal/shortcuts.py index ed35b2a..f92babd 100644 --- a/IPython/terminal/shortcuts.py +++ b/IPython/terminal/shortcuts.py @@ -19,6 +19,7 @@ from prompt_toolkit.filters import (has_focus, has_selection, Condition, from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.key_binding.bindings import named_commands as nc +from prompt_toolkit.key_binding.vi_state import InputMode, ViState from IPython.utils.decorators import undoc @@ -160,6 +161,32 @@ def create_ipython_shortcuts(shell): for keys, cmd in keys_cmd_dict.items(): kb.add(*keys, filter=focused_insert & ebivim)(cmd) + def get_input_mode(self): + if sys.version_info[0] == 3: + app = get_app() + app.ttimeoutlen = shell.ttimeoutlen + app.timeoutlen = shell.timeoutlen + + return self._input_mode + + def set_input_mode(self, mode): + shape = {InputMode.NAVIGATION: 2, InputMode.REPLACE: 4}.get(mode, 6) + cursor = "\x1b[{} q".format(shape) + + if hasattr(sys.stdout, "_cli"): + write = sys.stdout._cli.output.write_raw + else: + write = sys.stdout.write + + write(cursor) + sys.stdout.flush() + + self._input_mode = mode + + if shell.editing_mode == "vi" and shell.modal_cursor: + ViState._input_mode = InputMode.INSERT + ViState.input_mode = property(get_input_mode, set_input_mode) + return kb @@ -341,4 +368,4 @@ if sys.platform == 'win32': return except ClipboardEmpty: return - event.current_buffer.insert_text(text.replace('\t', ' ' * 4)) + event.current_buffer.insert_text(text.replace("\t", " " * 4)) diff --git a/docs/autogen_shortcuts.py b/docs/autogen_shortcuts.py index 2cd9019..38af9b1 100755 --- a/docs/autogen_shortcuts.py +++ b/docs/autogen_shortcuts.py @@ -41,12 +41,14 @@ def multi_filter_str(flt): log_filters = {'_AndList': 'And', '_OrList': 'Or'} log_invert = {'_Invert'} -class _DummyTerminal(object): +class _DummyTerminal: """Used as a buffer to get prompt_toolkit bindings """ handle_return = None input_transformer_manager = None display_completions = None + editing_mode = "emacs" + ipy_bindings = create_ipython_shortcuts(_DummyTerminal()).bindings