如果没有活动区域 python-模式,emacs elisp 发送行

emacs elisp send line if no region active python-mode

我想创建一个命令,如果该区域处于活动状态,则发送该区域,如果不活动,则评估当前 line/statement 并进一步指向下一个语句。

我从 This solution. 开始 现在我无法让 (python-shell-send-region) 工作,因为我不知道如何将区域的开始和结束传递给它。

到目前为止我有这个:

 (defun my-python-send-region (&optional beg end)   
   (interactive)   
    (if (use-region-p)
      (python-shell-send-region)    (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 (line-end-position)))))
     (python-shell-send-region beg end)
     (python-nav-forward-statement))))

 (add-hook 'python-mode-hook
       (lambda ()
     (define-key python-mode-map "\C-cn" 'my-python-send-region)))

更新: 根据 Andreas 和 Legoscia 的建议,我稍微改变了结构。

现在我得到一个错误 (Invalid function: (setq beg (point)) for:

 (defun my-python-send-region (&optional beg end)
  (interactive)
  (if (use-region-p)
    (python-shell-send-region (region-beginning) (region-end))
   ((setq beg (point))
    (python-nav-end-of-statement)
    (setq end (point))
    (python-shell-send-region (beg) (end)))
    (python-nav-forward-statement))))

但是,这有效:

 (defun my-python-send-region (&optional beg end)
 (interactive)
 (setq beg (point))
 (python-nav-end-of-statement)
 (setq end (point))
 (python-shell-send-region beg end))

本部分:

(if (use-region-p)
  (python-shell-send-region)

您需要将区域的开始和结束传递给python-shell-send-region。它仅在交互调用时自动获取这些值。当您从 Lisp 代码中调用它时,您需要显式传递值:

(python-shell-send-region (region-beginning) (region-end))

另一种可能有效的方法是尝试使用 melpa 的 whole-line-or-region 包。这个包设置了一些东西,这样如果你调用一个需要区域的命令,但没有定义区域,它基本上会设置一个等于当前行的区域。本质上,这会导致在当前行上没有定义区域时期望区域工作的命令。我的 init.org 文件中有这个

Allow region oriented commands to work on the current line if no region is defined.

   #+BEGIN_SRC emacs-lisp
     (use-package whole-line-or-region
       :ensure t
       :diminish whole-line-or-region-mode
       :config
       (whole-line-or-region-mode t)
       (make-variable-buffer-local 'whole-line-or-region-mode))

更新的答案:python-shell-send-defun 并不总是发送当前的 statement/line (it is not meant to do that),所以我用函数替换了它来自 elpy

(defun python-shell-send-region-or-line nil
  "Sends from python-mode buffer to a python shell, intelligently."
  (interactive)
  (cond ((region-active-p)
     (setq deactivate-mark t)
     (python-shell-send-region (region-beginning) (region-end))
 ) (t (python-shell-send-current-statement))))

(defun python-shell-send-current-statement ()
"Send current statement to Python shell.
Taken from elpy-shell-send-current-statement"
(interactive)
(let ((beg (python-nav-beginning-of-statement))
    (end (python-nav-end-of-statement)))
(python-shell-send-string (buffer-substring beg end)))
(python-nav-forward-statement))

我使用 cond for if 以防我想添加案例。设置deactivate-mark是如果选中则取消选中区域。如果没有选择区域,我还会向前导航 python 语句。