在外部编辑器中编辑IPython单元格

时间:2015-02-03 21:50:15

标签: vim editor cell ipython-notebook

在IPython笔记本中使用键盘快捷键会很棒,这样可以在外部编辑器(例如gvim)中编辑当前单元格的内容。也许只需将当前单元格的内容复制到临时文件中,在其上启动gvim,并在每次保存文件时更新当前单元格(并在退出gvim时删除临时文件)。此外,如果从浏览器编辑单元格,也可以更新临时文件,以便gvim知道文件已更改。

我知道像vim-ipython和ipython-vimception这样的项目,但它们并不符合我的需求。我认为浏览器足以满足简单的需求,但是当需要更强大的编辑功能时,无需重新发明轮子。

你知道IPython笔记本中是否存在这样的功能吗?

感谢。

4 个答案:

答案 0 :(得分:10)

这就是我想出的。我添加了2个快捷方式:

  • 'g'用当前单元格的内容启动gvim(你可以用你喜欢的任何文本编辑器替换gvim)。
  • 'u'用gvim保存的内容更新当前单元格的内容。

因此,当您想使用首选编辑器编辑单元格时,点击“g”,对单元格进行所需的更改,将文件保存在编辑器中(并退出),然后点击“u”。

只需执行此单元格即可启用这些功能:

%%javascript

IPython.keyboard_manager.command_shortcuts.add_shortcut('g', {
    handler : function (event) {
        var input = IPython.notebook.get_selected_cell().get_text();
        var cmd = "f = open('.toto.py', 'w');f.close()";
        if (input != "") {
            cmd = '%%writefile .toto.py\n' + input;
        }
        IPython.notebook.kernel.execute(cmd);
        cmd = "import os;os.system('gvim .toto.py')";
        IPython.notebook.kernel.execute(cmd);
        return false;
    }}
);

IPython.keyboard_manager.command_shortcuts.add_shortcut('u', {
    handler : function (event) {
        function handle_output(msg) {
            var ret = msg.content.text;
            IPython.notebook.get_selected_cell().set_text(ret);
        }
        var callback = {'output': handle_output};
        var cmd = "f = open('.toto.py', 'r');print(f.read())";
        IPython.notebook.kernel.execute(cmd, {iopub: callback}, {silent: false});
        return false;
    }}
);

答案 1 :(得分:1)

基于@ david-brochart接受的答案,我已经将他的代码包装成魔术函数,所以现在我只需要在笔记本中运行魔术java -cp myjar.jar;. com.mycompany.MyClass 行为了能够通过Gvim为整个笔记本编辑任何单元格的内容(我可以在我的系统上运行的任何其他笔记本中重复使用相同的魔术)。

如果您想要做类似的事情,只需在ipython启动文件夹中创建一个名为 my_magic_functions.py 的文件(您的ipython启动路径可能类似于{{1} })然后将以下代码放在该文件中(并保存):

%gvim

现在启动你的Jupyter笔记本内核,你应该可以在一个单元格中键入~/.ipython/profile_default/startup(你可以使用自动完成来查找新的魔术命令),然后运行单元格以启用编辑Gvim中的笔记本电脑内容。您将收到一条输出消息,通知您魔术命令生效:

  

现在可以通过Gvim编辑单元格内容。从命令模式使用''在Gvim中打开当前单元格内容。之后':wq'来自Gvim,使用' u'在命令模式下更新单元格内容。

感谢this stackoverflow问题中的人们,以及为了给我提供将其结合在一起的成分。 : - )

答案 2 :(得分:1)

@ david-brochart的上述代码段是一个不错的技巧,但它有几个缺点:

  • 很容易丢失数据,例如不小心在错误的单元格上按了'u'。
  • 在编辑文件时,Python内核被阻止。
  • 内核的全局名称空间被污染。
  • 不可能同时编辑多个单元格。
  • 剩余的'.toto.py'文件保留在磁盘上。
  • 文件扩展名不取决于单元格类型。

这是一个改进的版本,可以解决上述所有问题。它仍然是一个hack(例如,在内核繁忙时不可能开始编辑单元),但是在实践中它已经足够好了。它仍然滥用计算内核来读写文件并启动编辑器,但是这样做的方式是尽可能减少副作用。

要使用此代码段,必须在Jupyter单元中执行。它也可以添加到 df[['lat', 'lon']] = df['coordinates'].apply(pd.Series) 。默认情况下,将启动“ emacsclient -c”,但是可以用任何其他编辑器代替。只有一个键(默认为“ e”)可以将单元格换成文件并启动编辑器,或者读取文件并将内容重新插入单元格。

~/.jupyter/custom/custom.js

答案 3 :(得分:1)

对于使用IPython terminal 应用程序发现此问题的人,有一个内置的键盘快捷键,其中会使用当前单元格的内容启动$EDITOR。保存并退出编辑器会用保存的文件替换(但尚未执行)单元格的内容。

默认键盘快捷键是<F2>键。这对应于IPython设置IPython.terminal.shortcuts.open_input_in_editor

相关问题