Javascript – Custom IPython Notebook keyboard shortcut to duplicate current line in edit mode


In the IPython Notebook environment, it is possible to define custom keyboard shortcuts using the IPython Javascript API. Using the %%javascript magic, one may write a javascript within IPython's interactive console as follows (example described here):


IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {
    help : 'run cell',
    help_index : 'zz',
    handler : function (event) {
        return false;

I'd like to write a javascript that creates a shortcut during edit mode that binds Ctrl-Alt-Down to the action of 'duplicate current line'—that is, move the cursor to the start of the current line, select the line, copy the line, return, paste. Essentially, I want to emulate the keyboard shortcut of Eclipse, or Ctrl-d in Notepad++, or C-a C-SPACE C-n M-w C-y in Emacs. The javascript file will take the form of the following:


IPython.keyboard_manager.edit_shortcuts.add_shortcut('ctrl-alt-down', {
    help : 'run cell',
    help_index : 'zz',
    handler : function (event) {
        [Code that duplicates the line];
        return false;

though my attempts suggest 'ctrl-alt-down' is the incorrect way to represent the shortcut sequence, and I can't find any documentation for the keyboard_manager.

I'd rather not go with an (e.g.,) AutoHotKey solution since I want to restrict this shortcut to the edit mode of IPython Notebook.

Best Solution


Create a new JS file under ~/.jupyter/custom/custom.js if it does not exist and add the next code:

* Duplicate a current line in the Jupyter Notebook
* Used only CodeMirror API -
CodeMirror.keyMap.pcDefault["Ctrl-Down"] = function(cm){

    // get a position of a current cursor in a current cell
    var current_cursor = cm.doc.getCursor();

    // read a content from a line where is the current cursor
    var line_content = cm.doc.getLine(current_cursor.line);

    // go to the end the current line

    // make a break for a new line

    // filled a content of the new line content from line above it

    // restore position cursor on the new line
    cm.doc.setCursor(current_cursor.line + 1,;

Step 2.

Restart Jupyter


enter image description here

Tested in a next environment

wlysenko@wlysenko-Aspire ~ $ google-chrome --version
Google Chrome 53.0.2785.116 
wlysenko@wlysenko-Aspire ~ $ jupyter --version
wlysenko@wlysenko-Aspire ~ $ uname -a
Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux