Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IPython 5.0 and key bindings in console

The new release of IPython does not depend any more on readline but uses the pure Python library prompt-toolkit, solving maintenance problems on Apple's and Windows' systems.

A new feature is the ability to edit a multi-line code block, using the cursor keys to move freely in the code block — with this power it comes, at least for me, a problem: because a ret inserts a new line in your code, to pass the whole block to the interpreter you have to use the shortcut alt+ret or possibly the less convenient key sequence esc followed by ret.

I say, this is a problem, because my terminal emulator of choice is the XTerm and, on many Linux distributions, the shortcut alt+ret is not passed to the application but it is directly used by the XTerm in which IPython is running, to toggle the screen-fullness of the said terminal (@ThomasDickey, xterm's mantainer and co-author pointed out that, by default, xterm doesn't care to send to the application the modifier bit on Enter even when one unbinds the Fullscreen action).

For this reason I'd like to modify at least this specific IPython key binding.

I've found instructions (sort of) for the previouos versions, the readline based ones, of IPython that do not apply to the new, 5.0 version.

What I would need are instructions that lead me to find, in IPython's user documentation, the names of the possible actions that I can bind, the names of the shortcuts to bind with the actions and the procedure to follow to configure a new key binding.

Failing to have this type of canonical answer, I may be happy with a recipe to accomplish this specific keybinding, with the condition that the recipe still works in IPython 6.0

like image 950
gboffi Avatar asked Jul 29 '16 13:07

gboffi


People also ask

How do I use IPython console?

The IPython Console allows you to execute commands and interact with data inside IPython interpreters. To launch a new IPython instance, go to New console (default settings) under the Consoles menu, or use the keyboard shortcut Ctrl - T ( Cmd - T on macOS) when the console is focused.

How do I change my IPython interpreter?

You need to edit the file which starts IPython. On Linux you can enter it with: sudo nano $(which ipython) . Once you're inside the file change the shebang line to what ever Python interpreter you like. And directories that contain Python3.


3 Answers

You could change xterm's configuration.

xterm is configurable (and documented). In the xterm manual, the Default Key Bindings section shows the default binding for this key:

                        Alt <Key>Return:fullscreen() \n\

You can suppress that binding in more than one way:

  • using the omitTranslation resource to suppress the feature
  • setting the fullscreen resource to never

However, just suppressing it will not make it send something interesting (xterm ignores the modifier for Enter). Setting a translation resource works, e.g., in your $HOME/.Xdefaults file:

*VT100*translations:      #override \n\ 
     Alt <Key>Return: string("\033[27;3;13~")
like image 55
Thomas Dickey Avatar answered Oct 25 '22 00:10

Thomas Dickey


The ctrl+j or ctrl+m keyboard shortcuts are validating the entry.

like image 44
Vivian De Smedt Avatar answered Oct 25 '22 00:10

Vivian De Smedt


Modifying keyboard shortcuts in configuration when using prompt_toolkit is not (yet) possible; though it is pretty easy if you install IPython from source. If you look at the file IPython/terminal/shortcuts.py you will see that it contains the various logic; in particular you will find:

# Ctrl+J == Enter, seemingly
registry.add_binding(Keys.ControlJ,
                     filter=(HasFocus(DEFAULT_BUFFER)
                             & ~HasSelection()
                             & insert_mode
                    ))(newline_or_execute_outer(shell))

This bind CtrlJ (enter) to the function newline_or_execute_outer which is responsible for adding new lines; it's define later in the file. In particular if you press enter twice at the end of a block of code, it should execute the block without the need to use any other shortcuts.

Strip the logic that adds new lines:

def execute_outer(shell):
    def execute(event):
        """When the user presses return, insert a newline or execute the code."""
        b = event.current_buffer

        # some logic to also dismiss the completer

        b.accept_action.validate_and_handle(event.cli, b)
    return execute

Bind it around line 20-something:

registry.add_binding(Keys.ControlE,
                     filter=(HasFocus(DEFAULT_BUFFER)
                             & ~HasSelection()
                             & insert_mode
                    ))(execute_outer(shell))

And enjoy. If you are unhappy with the documentation we welcome help; For example, taking the gist of the answers there and contributing them back. It is a bit hurtful to read harsh comments when we do say in release notes:

New terminal interface

The overhaul of the terminal interface will probably cause a range of minor
issues for existing users. This is inevitable for such a significant
change, and we’ve done our best to minimise these issues. Some changes that
we’re aware of, with suggestions on how to handle them:

IPython no longer uses readline configuration (~/.inputrc). We hope that
the functionality you want (e.g. vi input mode) will be available by
configuring IPython directly (see Terminal IPython options). If something’s
missing, please file an issue.

...

Helping actually improving IPython to have configurable keybinding with actions name is also appreciated, so then you will be able to answer your own question.

like image 44
Matt Avatar answered Oct 25 '22 00:10

Matt