【问题标题】:Custom IPython Notebook keyboard shortcut to duplicate current line in edit mode自定义 IPython Notebook 键盘快捷键以在编辑模式下复制当前行
【发布时间】:2015-05-28 11:45:10
【问题描述】:

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

虽然我的尝试表明“ctrl-alt-down”是表示快捷方式序列的不正确方式,但我找不到keyboard_manager 的任何文档。

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

【问题讨论】:

    标签: javascript keyboard-shortcuts ipython-notebook


    【解决方案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

    结果

    在下一个环境中测试

    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
    

    【讨论】:

    • 我没有看到这样的目录。需要自己添加目录吗?我也在使用 4.4.0 版本。
    • @Newskooler 在“jupyter config”路径中添加子目录“config”时为我工作(但在 Windows 上)。您可以尝试通过 jupyter_config_dir() 检查路径是否正确,如stackoverflow.com/questions/32170197/…
    • 为我工作,谢谢!可能的改进:复制以制表符开头的行时防止加倍制表符;)
    • 在 Mac (10.13.6) Firefox (88.0.1) 上对我没有帮助。我将 pcDefault 更改为 macDefault 但没有任何反应。我什至无法理解在我开始 jupyther 实验室时我的 custom.js 是否启动时没有任何错误
    【解决方案2】:

    这是对this great answer 的简单调整,满足了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);
    };
    

    【讨论】:

      【解决方案3】:

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

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

      其余代码保持不变。这是完整的 sn-p。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-28
        • 1970-01-01
        • 1970-01-01
        • 2017-06-01
        • 2011-01-03
        相关资源
        最近更新 更多