【问题标题】:Change the Emacs “send code to interpreter” C-c C-r command in IPython-mode在 IPython 模式下更改 Emacs “发送代码到解释器” C-c C-r 命令
【发布时间】:2026-01-08 01:35:01
【问题描述】:

这里的问题与Change the "send code to interpreter" (C-c |) command in python-mode 相关(但不相同)和补充。

我在 Mac 10.9.5、Emacs 24.4、Python 2.7.8 和 IPython 2.2.0 上工作。

我的想法是更改C-c C-r emacs 命令以将IPython 模式下的区域/代码行发送到C-RET,就像使用R 时一样。这是因为我通常使用R,但从现在开始,我我将使用 R 和 Python(尤其是 IPython,我真的很喜欢),C-RET --已经是 R 中的发送代码命令 -- 对我来说似乎更舒服。

在这个问题开头引用的链接中,他们建议将以下行添加到.emacs 文件中,以将C-c | 命令更改为C-c C-r

(eval-after-load "python"
  '(progn
     (define-key python-mode-map (kbd "C-c C-r") 'python-shell-send-region)))

目前,.emacs 文件中的 python/IPython 配置如下所示:

;; Enable Python
(add-to-list 'load-path "/sw/lib/python-mode-1.0")
(load "python-mode")
(setq auto-mode-alist
      (cons '("\\.py$" . python-mode) auto-mode-alist))
(setq interpreter-mode-alist
  (cons '("python" . python-mode)
        interpreter-mode-alist))
(autoload 'python-mode "python-mode" "Python editing mode." t)

;; Ipython. This python-mode takes the Key-map and the menu
(when (executable-find "ipython")
  (setq
   python-shell-interpreter "ipython"
   python-shell-interpreter-args ""
   python-shell-prompt-regexp "In \\[[0-9]+\\]: "
   python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
   python-shell-completion-setup-code
   "from IPython.core.completerlib import module_completion"
   python-shell-completion-module-string-code
   "';'.join(module_completion('''%s'''))\n"
   python-shell-completion-string-code
   "';'.join(get_ipython().Completer.all_completions('''%s'''))\n"))

这是两种并行运行的 Python 模式,第二种(IPython,我一直使用的一种)采用键映射和菜单(顺便说一下,欢迎任何关于更好配置的建议。IPython部分基于:How to open IPython interpreter in emacs?)。

我曾尝试在我的 python 配置末尾添加前面描述的(eval-after-load "python" '(progn ... 命令(当然,将C-c C-r 更改为C-RETC-ret 甚至C-<return>)。

我也尝试过不同形式的 when (executable-find "ipython") ... 块(例如简单的 (define-key python-mode-map (kbd "C-c C-r") 'python-shell-send-region) )。但似乎没有任何效果。

因此,我的问题是:鉴于我的 Python/IPython 配置,我必须在我的 .emacs 文件中包含什么才能将 C-c C-r 命令更改为 (C-RET)

非常感谢!

【问题讨论】:

    标签: python macos emacs ipython


    【解决方案1】:

    使用 (kbd "RET")

    用 python.el 试试这个

    (eval-after-load "python"
      '(define-key python-mode-map [(control c)(kbd "RET")] 'python-shell-send-region))
    

    WRT python-mode.el:

    (eval-after-load "python-mode"
      '(define-key python-mode-map [(control c) (kbd "RET")] 'py-execute-region))
    

    顺便说一句,除非需要 IPython 独有的功能,否则建议通过通用 Python 从 Emacs 执行代码。 IPython 实现了一堆很酷的东西,看起来可能与 Emacs 正交,Emacs 也实现了很多很酷的东西。

    【讨论】:

    • 嗨安德烈亚斯,谢谢(再次!)。不幸的是,它不起作用(问题肯定在我这边)。我已经在我的(load "python-mode") 之后尝试了你的(eval-after-load "python-mode" '(define-key python-mode-map [(control c) (kbd "RET")] 'py-execute-region)),在配置结束时,到处都是,但它不起作用。我总是收到错误消息C-<return> undefined。也尝试过(以防万一:))C-c RET 和相同的结果。事实上,我从“scratch”开始,并使用橘子酱下载了 python-mode。也没有用。
    • 用marmalade安装python-mode后,配置的第一行看起来(add-to-list 'load-path "~/.emacs.d/elpa/python-mode-6.1.3/"),其余都一样。当我输入M-x run-python 时,我得到了一系列缩进错误(这可能值得另一个问题)但 IPython 似乎运行正常。仍然,C-RET 不起作用
    • @Javier py-execute-region 不打算从 shell 使用,而不是从源缓冲区使用。 python-mode-map 也仅驻留在源代码中:在 py-shell 中,它的 py-python-shell-mode-map resp。 py-ipython-shell-mode-map。它们在发送由 RET 完成时提供编辑命令。
    【解决方案2】:

    这里有一些东西很快就可以发送一条 python 线到 蟒蛇壳。我也经常在 R 中这样做。它还没有完全自动化,但我可能会有用。

    以下还有一些待制作:

    1. 必要时将线路发送到专用进程

    2. 分配本地密钥

      (defun my-python-line ()
       (interactive)
        (save-excursion
        (setq the_script_buffer (format (buffer-name)))
        (end-of-line)
        (kill-region (point) (progn (back-to-indentation) (point)))
        ;(setq the_py_buffer (format "*Python[%s]*" (buffer-file-name)))
        (setq the_py_buffer "*Python*")
        (switch-to-buffer-other-window  the_py_buffer)
        (goto-char (buffer-end 1))
        (yank)
        (comint-send-input)
        (switch-to-buffer-other-window the_script_buffer)
        (yank))
      )
      
      (global-set-key  (kbd "C-c n") 'my-python-line)
      

    更新

    我对代码做了一些改进:

    1. 即使没有python shell,也可以直接使用代码 还在运行。

    2. 已设置本地设置密钥

      只剩下专用的过程。随意在下面的答案中改进

      (defun my-python-line ()
      (interactive)
      (save-excursion
        (setq the_script_buffer (format (buffer-name)))
        (end-of-line)
        (kill-region (point) (progn (back-to-indentation) (point)))
        (if  (get-buffer  "*Python*")
        (message "")
        (run-python "ipython" nil nil))
        ;; (setq the_py_buffer (format "*Python[%s]*" (buffer-file-name)))
        (setq the_py_buffer "*Python*")
        (switch-to-buffer-other-window  the_py_buffer)
        (goto-char (buffer-end 1))
        (yank)
        (comint-send-input)
        (switch-to-buffer-other-window the_script_buffer)
        (yank))
        (end-of-line)
        (next-line)
        )
      
      (add-hook 'python-mode-hook
          (lambda ()
        (define-key python-mode-map "\C-cn" 'my-python-line)))
      

    【讨论】:

    • 有没有办法发送lines 直到line 完成。例如,发送“if True:”是没有意义的,但在缩进块中发送“if True:”及其以下行也是如此
    • 好建议!基本上我们只需要识别一个缩进块。我的 elisp 不太流利,无法立即给您答案,但我会考虑并及时通知您。
    • 请看我下面的回复
    【解决方案3】:

    我做了一些黑客攻击,这就是我所拥有的: 通过阅读代码,您应该能够知道它是如何工作的。

    (defun block-line-end ()
        (setq indentation (current-indentation))
        (forward-line)
        (while (> (current-indentation) indentation)
          (forward-line))
        (forward-line -1)
        (line-end-position))  
    (defun my-python-shell-send-region (&optional beg end)
        (interactive)
        (let ((beg (cond (beg beg)
                    ((region-active-p) (region-beginning))
                    (t (line-beginning-position))))
              (end (cond (end end)
                    ((region-active-p) 
                     (copy-marker (region-end)))
                    (t (block-line-end)))))
          (python-shell-send-region beg end))
        (forward-line))
    

    【讨论】: