【问题标题】:Sending code from Python buffer to IPython session running from M-x ansi-term将代码从 Python 缓冲区发送到从 M-x ansi-term 运行的 IPython 会话
【发布时间】:2012-11-18 22:10:57
【问题描述】:

假设我在 Emacs 中使用 M-x ansi-term 打开了一个终端仿真器。这将使用我选择的 shell 在 Emacs 中打开一个缓冲区。假设我然后从这个 shell 运行ipython。我可以使用 Emacs 中的 Python 代码从另一个缓冲区向这个 ipython 会话发送代码吗?如果有怎么办?

【问题讨论】:

    标签: python emacs ipython


    【解决方案1】:

    为此我有一个次要模式(除了它不是特定于 IPython 的,我主要将它用于 shell 脚本):isend-mode

    您将如何使用它:

    1. 打开一个ansi-term 缓冲区:

      M-xansi-termRET/usr/bin/ipythonRET

    2. 使用要执行的代码打开缓冲区,并将其关联到解释器缓冲区:

      M-xisend-associateRET*ansi-term*RET

    3. 在 python 缓冲区中点击 C-RET 以将当前行发送到 ansi-term 缓冲区中的解释器。

    【讨论】:

    • 这太棒了弗朗西斯科。是否只支持发送当前行? (即与发送区域或完整缓冲区相反)。
    • 如果区域处于活动状态,它将发送它而不是发送当前行(实际上,它将发送该区域跨越的所有行,没有行将仅部分发送)。要发送整个缓冲区,我使用C-x h C-RET(但我很少使用它,因为我的主要用途是逐行或逐部分解释脚本)
    • 感谢@Francesco,我唯一注意到的是isend 不能很好地处理代码块中带有缩进的代码sn-ps。例如。如果我选择具有 if 块或 for 循环以及其他一些未缩进代码的代码,isend 将不会按照 IPython 期望的方式发送缩进。通过在 IPython 中调用 %paste 将选择的代码发送到 shell 不是更好吗? (即,您将让 isend 将代码复制到 Emacs 剪贴板,然后让它在 IPython 缓冲区中调用 %paste)。这将允许isend 处理任意复杂的代码片段。
    • 我认为您的问题与交互式 IPython 解释器在循环或其他缩进结构的末尾期望空行有关。默认情况下,isend 忽略这些行,但我上传了一个新版本,可以告诉它使用 (setq isend-skip-empty-lines nil) 发送空行。
    • 感谢弗朗西斯科。我尝试了新版本,但问题仍然存在。原因是缩进在 Python(和 IPython)中有意义,所以如果我选择来自循环内部的代码,IPython 会抱怨 unexpected indent,因为代码是缩进的。解决isend 问题的唯一方法是在将代码块发送到缓冲区之前从代码块中删除任何额外的缩进(但保持行之间的相对缩进)。我认为这将是一个优雅的解决方案,它也应该与其他 shell 一起使用(其他 shell 对缩进并不挑剔)。
    【解决方案2】:
    (defun send-buffer-to-ipython ()
      "Send current buffer to the running ipython process."
      (interactive)
      (let* ((ipython-buffer "*ansi-term*") ; the buffer name of your running terminal
             (proc (get-buffer-process ipython-buffer)))
        (unless proc
          (error "no process found"))
        (save-buffer)
        (process-send-string proc
                             (format "execfile(\"%s\")\n" (buffer-file-name)))
        (pop-to-buffer ipython-buffer)      ; show ipython and select it
        ;; (display-buffer ipython-buffer)  ; show ipython but don't select it
        ))
    

    然后将命令send-buffer-to-ipython 绑定到您喜欢的任何键。我把它绑定到C-c C-c

    (define-key python-mode-map [?\C-c ?\C-c] 'send-buffer-to-ipython)
    

    【讨论】:

    • 当文本很大时,我认为发送命令来加载和执行当前文件更好。这也是 python.el 的实现方式,只不过在 python.el 中python-send-region 将当前缓冲区的内容保存到临时文件并发送命令加载临时文件。
    【解决方案3】:

    使用 python-mode.el

    M-x 自定义变量 RET py-shell-name RET ansi-term

    M-x ansi-term RET ipython RET

    C-c C-c 来自 Python 缓冲区而不是在 IPython shell 中执行

    警告:shebang 在默认的 py-shell-name 之前

    https://launchpad.net/python-mode/trunk/6.0.12/+download/python-mode.el-6.0.12.tar.gz

    【讨论】:

    • 谢谢安德烈亚斯。 Caveat: a shebang precedes default py-shell-name 是什么意思。你的意思是,如果我要从中发送代码的脚本中有一个 shebang,那么 shebang 将优先于我的 py-shell-name 的值?
    • 是的。通过 ansi-term 执行的 AFAIS 仅在未设置 shebang 时才有效 - 这是一个错误。
    • Andreas,如果我有多个 ansi_term 缓冲区,我该如何设置?我可以将运行 IPython 的 Emacs 缓冲区重命名为其他名称并将其作为参数传递给 py-shell-name 吗?或者我们应该如何处理多个 ansi-terms?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2015-01-27
    • 2013-11-27
    • 2021-06-05
    • 1970-01-01
    • 2012-09-14
    相关资源
    最近更新 更多