如何从另一个Emacs Lisp函数调用具有前缀参数的交互式Emacs Lisp函数?

时间:2012-02-22 01:10:23

标签: emacs elisp

我想编写一个Emacs Lisp函数,无论模式的当前状态如何,都会打开flyspell-mode。函数flyspell-mode-on已弃用。文档表明,正前缀参数将转为flyspell-mode,但遗憾的是运行

(flyspell-mode 1)

会出现错误消息:

Wrong number of arguments: (lambda (flyspell-mode 1)), 0

如果我能弄清楚如何使用前缀参数调用flyspell-mode,我相信我可以解决这个问题。

我在Emacs Lisp手册中找到的最相关的部分是标题为“交互式呼叫”的部分,它描述了call-interactively等命令。这显然不是我想要的。

(我试图解决的最终问题是创建一个模式挂钩,无论其当前状态如何,都会打开模式。)

N.B。问题emacs lisp call function with prefix argument programmatically的标题使其看似相关,但该问题是询问如何创建交互式命令,并且最终使用call-interactively解决了该问题。


编辑:这个问题没有实际意义;我找到了原始问题的替代解决方案:

(add-hook 'text-mode-hook
          (function (lambda ()
                      (require 'flyspell)
                      (if flyspell-mode nil (flyspell-mode)))))

但是我仍然想知道如何用另一个Emacs Lisp函数调用带有前缀参数的Emacs Lisp函数,其中 nothing 是交互式的。


更新:也许我应该问为什么我收到错误消息...

6 个答案:

答案 0 :(得分:9)

看起来您的Flyspell模式版本不遵循minor mode conventions,这要求您可以使用(name-of-mode t)或任何正前缀参数打开辅助模式,并使用{{1}将其关闭任何否定前缀参数,并将其与(name-of-mode 0)切换。

如果你有最新版本的Flyspell,可能会有错误报告。我在我的机器上有GNU Emacs 23.2附带的版本,它遵守惯例。我的版本还定义了两个函数(name-of-mode nil)turn-on-flyspell,两个函数都围绕turn-off-flyspell;具有此类名称的函数很常见,但不是官方惯例。函数flyspell-modeflyspell-mode-on显然是供内部使用。

一般情况下,命令从current-prefix-arg变量读取当前前缀参数。不要将其与flyspell-mode-off混淆,后者是下一个命令的值(只有少数命令,如prefix-arg触摸此变量)。因此,如果在调用函数时需要传递前缀参数,请绑定或设置universal-argument

current-prefix-arg

答案 1 :(得分:4)

如果您没有以交互方式调用函数,则(interactive)声明不会用于获取参数。

在绝大多数情况下,您无需担心参数是否可以成为非交互式调用的“前缀参数”;只需检查功能文档,并传递您想要做的任何所需的值。

如果由于某种原因你需要复制在非交互式上下文中发送前缀参数,则需要检查该函数的(interactive)声明并确定它是如何使用该参数的,并确保你复制你传递的参数的行为。

有关详细信息,请参阅:

  • C-h f interactive RET
  • M - : (info "(elisp) Prefix Command Arguments") RET

在函数根据current-prefix-arg变量更改其行为的更复杂情况下,您可以直接设置该变量。

(let ((current-prefix-arg '(4)))
  (foo current-prefix-arg))

答案 2 :(得分:2)

我能想到这个......应该会更好一些

(call-interactively (lambda ()
                       (interactive)
                       (flyspell-mode '(4))))

更新: 我可以直接运行..我在问题中缺少什么。?

(flyspell-mode '(4))

EDITED:删除了lambda表达式的引用(我添加了这个注释,因为SX强制编辑长度至少为六个字符,因此可以删除)。

答案 3 :(得分:1)

FWIW,`flyspell-mode'函数已经接受了一个参数(如“(flyspell-mode 1)”),至少从Emacs-21开始,所以我不知道你是怎么得到这个错误的。

但是当我在这里时,我不妨指出(add-hook'text-mode-hook'flyspell-mode)在Emacs-24中改变了意义:而不是意味着“在文本中切换flyspell-mode”模式“它现在意味着”在文本模式下启用flyspell-mode“。这是一个向后不兼容的变化,但我相信它会解决比它引入的更多潜在错误。

答案 4 :(得分:1)

请参阅我的评论以解决您的问题来源。至于你的问题的答案,前缀arg转换成某种Lisp参数的方式取决于interactive规范,所以唯一的方法是可靠地做到这一点(即没有先验知识,例如它的事实小模式功能)是以交互方式调用该函数:

(let ((current-prefix-arg '(4)))
  (call-interactively 'flyspell-mode))

答案 5 :(得分:0)

我不是Emacs和Elisp的主人(;))但我认为在这种情况下you may use Ctrl - u 1 Alt - x flyspell-mode