diff --git a/IPython/terminal/interactiveshell.py b/IPython/terminal/interactiveshell.py index 3c7afd1..52f51ca 100644 --- a/IPython/terminal/interactiveshell.py +++ b/IPython/terminal/interactiveshell.py @@ -444,19 +444,23 @@ class TerminalInteractiveShell(InteractiveShell): "create": Bool(default=False), }, ), - help=f"""Add, disable or modifying shortcuts. + help="""Add, disable or modifying shortcuts. Each entry on the list should be a dictionary with ``command`` key identifying the target function executed by the shortcut and at least - one of the following:: + one of the following: + - ``match_keys``: list of keys used to match an existing shortcut, - ``match_filter``: shortcut filter used to match an existing shortcut, - ``new_keys``: list of keys to set, - ``new_filter``: a new shortcut filter to set The filters have to be composed of pre-defined verbs and joined by one - of the following conjunctions: ``&`` (and), ``|` (or), ``~`` (not). - The pre-defined verbs are: ({', '.join(KEYBINDING_FILTERS)}). + of the following conjunctions: ``&`` (and), ``|`` (or), ``~`` (not). + The pre-defined verbs are: + + {} + To disable a shortcut set ``new_keys`` to an empty list. To add a shortcut add key ``create`` with value ``True``. @@ -467,9 +471,13 @@ class TerminalInteractiveShell(InteractiveShell): ``new_keys`` can be omitted which will result in reuse of the existing filter/keys. - Only shortcuts defined in IPython (and not default prompt toolkit - shortcuts) can be modified or disabled. - """, + Only shortcuts defined in IPython (and not default prompt-toolkit + shortcuts) can be modified or disabled. The full list of shortcuts, + command identifiers and filters is available under + :ref:`terminal-shortcuts-list`. + """.format( + "\n ".join([f"- `{k}`" for k in KEYBINDING_FILTERS]) + ), ).tag(config=True) @observe("shortcuts") diff --git a/IPython/terminal/shortcuts/__init__.py b/IPython/terminal/shortcuts/__init__.py index fee2b59..9711c81 100644 --- a/IPython/terminal/shortcuts/__init__.py +++ b/IPython/terminal/shortcuts/__init__.py @@ -185,10 +185,16 @@ AUTO_SUGGEST_BINDINGS = [ "default_buffer_focused & (ebivim | ~vi_insert_mode)", ), Binding( - auto_suggest.accept_in_vi_insert_mode, ["c-e"], "focused_insert_vi & ebivim" + auto_suggest.accept_in_vi_insert_mode, + ["c-e"], + "vi_insert_mode & default_buffer_focused & ebivim", + ), + Binding(auto_suggest.accept, ["c-f"], "vi_insert_mode & default_buffer_focused"), + Binding( + auto_suggest.accept_word, + ["escape", "f"], + "vi_insert_mode & default_buffer_focused & ebivim", ), - Binding(auto_suggest.accept, ["c-f"], "focused_insert_vi"), - Binding(auto_suggest.accept_word, ["escape", "f"], "focused_insert_vi & ebivim"), Binding( auto_suggest.accept_token, ["c-right"], @@ -249,7 +255,7 @@ AUTO_SUGGEST_BINDINGS = [ SIMPLE_CONTROL_BINDINGS = [ - Binding(cmd, [key], "focused_insert_vi & ebivim") + Binding(cmd, [key], "vi_insert_mode & default_buffer_focused & ebivim") for key, cmd in { "c-a": nc.beginning_of_line, "c-b": nc.backward_char, @@ -262,7 +268,7 @@ SIMPLE_CONTROL_BINDINGS = [ ALT_AND_COMOBO_CONTROL_BINDINGS = [ - Binding(cmd, list(keys), "focused_insert_vi & ebivim") + Binding(cmd, list(keys), "vi_insert_mode & default_buffer_focused & ebivim") for keys, cmd in { # Control Combos ("c-x", "c-e"): nc.edit_and_execute, diff --git a/IPython/terminal/shortcuts/filters.py b/IPython/terminal/shortcuts/filters.py index c14d11d..a4a6213 100644 --- a/IPython/terminal/shortcuts/filters.py +++ b/IPython/terminal/shortcuts/filters.py @@ -190,7 +190,6 @@ KEYBINDING_FILTERS = { "is_windows_os": is_windows_os, "auto_match": auto_match, "focused_insert": (vi_insert_mode | emacs_insert_mode) & default_buffer_focused, - "focused_insert_vi": vi_insert_mode & default_buffer_focused, "not_inside_unclosed_string": not_inside_unclosed_string, "readline_like_completions": readline_like_completions, "preceded_by_paired_double_quotes": preceding_text( @@ -203,7 +202,6 @@ KEYBINDING_FILTERS = { "preceded_by_two_double_quotes": preceding_text(r'^.*""$'), "preceded_by_two_single_quotes": preceding_text(r"^.*''$"), "followed_by_closing_paren_or_end": following_text(r"[,)}\]]|$"), - # match "preceded_by_opening_round_paren": preceding_text(r".*\($"), "preceded_by_opening_bracket": preceding_text(r".*\[$"), "preceded_by_opening_brace": preceding_text(r".*\{$"), diff --git a/docs/source/config/details.rst b/docs/source/config/details.rst index 3cc310a..925f49d 100644 --- a/docs/source/config/details.rst +++ b/docs/source/config/details.rst @@ -200,10 +200,20 @@ With (X)EMacs >= 24, You can enable IPython in python-mode with: Keyboard Shortcuts ================== +.. versionadded:: 8.10 + +You can modify, disable or modify keyboard shortcuts for IPython Terminal using +:std:configtrait:`TerminalInteractiveShell.shortcuts` traitlet. + +The list of shortcuts is available in the Configuring IPython :ref:`terminal-shortcuts-list` section. + +Advanced configuration +---------------------- + .. versionchanged:: 5.0 -You can customise keyboard shortcuts for terminal IPython. Put code like this in -a :ref:`startup file `:: +Creating custom commands requires adding custom code to a +:ref:`startup file `:: from IPython import get_ipython from prompt_toolkit.enums import DEFAULT_BUFFER diff --git a/docs/source/config/shortcuts/index.rst b/docs/source/config/shortcuts/index.rst index e361ec2..42fd6ac 100755 --- a/docs/source/config/shortcuts/index.rst +++ b/docs/source/config/shortcuts/index.rst @@ -1,8 +1,10 @@ +.. _terminal-shortcuts-list: + ================= IPython shortcuts ================= -Available shortcuts in an IPython terminal. +Shortcuts available in an IPython terminal. .. note:: @@ -12,7 +14,10 @@ Available shortcuts in an IPython terminal. * Comma-separated keys, e.g. :kbd:`Esc`, :kbd:`f`, indicate a sequence which can be activated by pressing the listed keys in succession. * Plus-separated keys, e.g. :kbd:`Esc` + :kbd:`f` indicate a combination which requires pressing all keys simultaneously. -* Hover over the ⓘ icon in the filter column to see when the shortcut is active.g +* Hover over the ⓘ icon in the filter column to see when the shortcut is active. + +You can use :std:configtrait:`TerminalInteractiveShell.shortcuts` configuration +to modify, disable or add shortcuts. .. role:: raw-html(raw) :format: html diff --git a/docs/source/whatsnew/pr/shortcuts-config-traitlet.rst b/docs/source/whatsnew/pr/shortcuts-config-traitlet.rst new file mode 100644 index 0000000..8d3ce11 --- /dev/null +++ b/docs/source/whatsnew/pr/shortcuts-config-traitlet.rst @@ -0,0 +1,21 @@ +Terminal shortcuts customization +================================ + +Previously modifying shortcuts was only possible by hooking into startup files +and practically limited to adding new shortcuts or removing all shortcuts bound +to a specific key. This release enables users to override existing terminal +shortcuts, disable them or add new keybindings. + +For example, to set the :kbd:`right` to accept a single character of auto-suggestion +you could use:: + + my_shortcuts = [ + { + "command": "IPython:auto_suggest.accept_character", + "new_keys": ["right"] + } + ] + %config TerminalInteractiveShell.shortcuts = my_shortcuts + +You can learn more in :std:configtrait:`TerminalInteractiveShell.shortcuts` +configuration reference. \ No newline at end of file