自定义IPython Notebook键盘快捷键,可在编辑模式下复制当前行

时间:2015-03-24 23:40:06

标签: javascript keyboard-shortcuts ipython-notebook

在IPython Notebook环境中,可以使用IPython Javascript API定义自定义键盘快捷键。使用%%javascript魔法,可以在IPython的交互式控制台中编写一个javascript,如下所示(示例描述为here):

%%javascript

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

我想编写一个javascript,在编辑模式下创建一个快捷方式,将Ctrl-Alt-Down绑定到'复制当前行' ---即移动光标到当前行的开头,选择行,复制行,返回,粘贴。本质上,我想模仿Eclipse的键盘快捷键,或Notepad ++中的Ctrl-d,或Emacs中的C-a C-SPACE C-n M-w C-y。 javascript文件将采用以下形式:

%%javascript

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;
    }}
);

虽然我的尝试建议&#c; ctrl-alt-down'是表示快捷方式序列的错误方法,我无法找到keyboard_manager的任何文档。

我不想使用(例如)AutoHotKey解决方案,因为我想将此快捷方式限制为IPython Notebook的编辑模式。

3 个答案:

答案 0 :(得分:13)

<强>步骤1。

~/.jupyter/custom/custom.js下创建一个新的JS文件(如果它不存在)并添加下一个代码:

/**
*
* Duplicate a current line in the Jupyter Notebook
* Used only CodeMirror API - https://codemirror.net
*
**/
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
    CodeMirror.commands.goLineEnd(cm);

    // make a break for a new line
    CodeMirror.commands.newlineAndIndent(cm);

    // filled a content of the new line content from line above it
    cm.doc.replaceSelection(line_content);

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

第2步。

重启Jupyter

<强>结果

enter image description here

在下一个环境中测试

wlysenko@wlysenko-Aspire ~ $ google-chrome --version
Google Chrome 53.0.2785.116 
wlysenko@wlysenko-Aspire ~ $ jupyter --version
4.1.0
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

答案 1 :(得分:1)

这是对Seti Volkylany的好答案的简单调整,满足了dasWesen的要求,避免将标签翻倍。此版本使用CodeMirror的goLineStartSmart函数仅转到当前行文本的开头,因此在复制文本时,它不会抓住前导空格或制表符。

如Seti的帖子所述,将代码放入文件〜/ .jupyter / custom / custom.js

在Windows上,我在C:\Users\YourUserName中找到了.jupyter文件夹,然后不得不创建\custom文件夹和custom.js文件。重新启动Jupyter即可完成更改。

CodeMirror.keyMap.pcDefault["Ctrl-Down"] = function(cm){

    // get current cursor position
    var current_cursor = cm.doc.getCursor();

    // First go to end of line, to avoid the problem where if cursor was at start
    // of indented text, goLineStartSmart would go to very beginning of line,
    // and so we'd get unwanted tabs/spaces in the getRange function.
    CodeMirror.commands.goLineEnd(cm);
    // now we can safely call goLineStartSmart
    CodeMirror.commands.goLineStartSmart(cm);
    var start_cursor = cm.doc.getCursor();
    var start = {'line': start_cursor.line, 'ch': start_cursor.ch};

    // go to the end of line
    CodeMirror.commands.goLineEnd(cm);
    var end_cursor = cm.doc.getCursor();
    var end = {'line': end_cursor.line, 'ch': end_cursor.ch};

    // get content
    var line_content = cm.doc.getRange(start, end);

    // make a break for a new line
    CodeMirror.commands.newlineAndIndent(cm);

    // filled a content of the new line content from line above it
    cm.doc.replaceSelection(line_content);

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

答案 2 :(得分:0)

PADYMKO提供了一个很好的答案https://stackoverflow.com/a/40505055/11784913。但是,如果您是Mac用户,则需要对其进行一些修改。您需要将代码的第一行更改为:

CodeMirror.keyMap.macDefault["Ctrl-Down"] = function(cm){

其余代码保持不变。这是完整的代码段。

CodeMirror.keyMap.macDefault["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
    CodeMirror.commands.goLineEnd(cm);

    // make a break for a new line
    CodeMirror.commands.newlineAndIndent(cm);

    // filled a content of the new line content from line above it
    cm.doc.replaceSelection(line_content);

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