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

如何从另一个Emacs Lisp函数调用带有前缀参数的交互式Emacs Lisp函数?,emacs,elisp,Emacs,Elisp,我想编写一个Emacs Lisp函数,该函数将启用flyspell模式,而不管模式的当前状态如何。不推荐使用上的功能flyspell模式。文档表明,正前缀参数将变为flyspell模式,但不幸的是正在运行 (flyspell-mode 1) 结果显示错误消息: Wrong number of arguments: (lambda (flyspell-mode 1)), 0 如果我能想出如何使用前缀参数调用flyspell mode,我相信我能解决这个问题 在Emacs Lisp手册中,我能找

我想编写一个Emacs Lisp函数,该函数将启用
flyspell模式
,而不管模式的当前状态如何。不推荐使用上的功能
flyspell模式。文档表明,正前缀参数将变为
flyspell模式
,但不幸的是正在运行

(flyspell-mode 1)
结果显示错误消息:

Wrong number of arguments: (lambda (flyspell-mode 1)), 0
如果我能想出如何使用前缀参数调用
flyspell mode
,我相信我能解决这个问题

在Emacs Lisp手册中,我能找到的最相关的部分是标题为“交互式调用”的部分,它描述了诸如
交互式调用
之类的命令。这显然不是我想要的

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

注意:问题的标题似乎是相关的,但该问题是关于如何创建交互式命令的,最终通过使用
交互式调用
解决了该问题


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

(add-hook 'text-mode-hook
          (function (lambda ()
                      (require 'flyspell)
                      (if flyspell-mode nil (flyspell-mode)))))
但我仍然想知道如何从另一个Emacs Lisp函数调用带有前缀参数的Emacs Lisp函数,而不需要任何交互



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

如果您不是以交互方式调用函数,那么
(交互)
声明不用于获取参数

在绝大多数情况下,您不必担心参数是否可以作为非交互式调用的“前缀参数”;只需检查函数文档,并传递所需的值即可

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

有关详细信息,请参阅:

  • C-hf
    interactive
    RET
  • M-:
    (信息“(elisp)前缀命令参数”)
    RET
在更复杂的情况下,如果函数根据
当前前缀arg
变量更改其行为,则可以直接设置该变量

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

我不是Emacs和Elisp master(尚未),但我认为在这种情况下,Ctrl-u
1
Alt-x
flyspell模式

我可以想到这一点。。应该更好

(call-interactively (lambda ()
                       (interactive)
                       (flyspell-mode '(4))))
更新: 我可以直接运行这个。。我在这个问题上遗漏了什么

(flyspell-mode '(4))

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

您的Flyspell模式版本似乎没有遵循,这要求您可以使用
(模式t的名称)
或任何正前缀参数打开次要模式,使用
(模式0的名称)
任何负前缀参数将其关闭,并使用
(模式nil的名称)
将其切换

如果您有最新版本的Flyspell,可能需要一份bug报告。我的机器上安装了GNU Emacs 23.2附带的版本,它遵守了约定。我的版本还定义了两个函数
打开flyspell
关闭flyspell
,这两个函数都是围绕
flyspell模式的小包装;具有此类名称的函数是常见的,但不是官方约定。功能
flyspell mode on
flyspell mode off
显然是供内部使用的

一般来说,命令从变量中读取当前前缀参数。不要将其与
前缀arg
混淆,后者是下一个命令的值(只有少数命令,如
通用参数
会接触此变量)。因此,如果在调用函数时需要传递前缀参数,请绑定或设置
当前前缀arg

(let ((current-prefix-arg t))
  (flyspell-mode))

FWIW,`flyspell mode'函数至少在Emacs-21之后接受了一个参数(如“(flyspell mode 1)”),所以我不知道您是如何得到这个错误的


但在这里,我不妨指出(添加hook‘text mode hook’flyspell mode)改变了Emacs-24中的含义:它现在的意思不是“在文本模式中切换flyspell mode”,而是“在文本模式中启用flyspell mode”。这是一个向后不兼容的更改,但我相信它将修复比它引入的更多的潜在错误。

请参阅我的评论,以了解问题根源的修复方法。至于您问题的答案,前缀arg转换为某种Lisp参数的方式取决于
interactive
规范,因此可靠地执行此操作的唯一方法(即在事先不知道(例如它是次要模式函数)是交互调用函数:

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

这将是一个交互式呼叫。我正在运行emacs 21,因为emacsen 22和23在我使用的一些传统模式中造成了一些损失,但不再维护。@Norman Ramsey哇,这已经过时了。至于您为什么会收到此错误消息,除了版本中的
flyspell mode
函数没有任何参数,直接读取
current prefix arg
;这是在以后版本中修复的设计缺陷。嗨,诺曼。真正的问题是您编写了
(lambda(flyspell模式1))
,而不是
(lambda()(flyspell模式1))
,因此Emacs将
(flyspell模式1)
作为参数列表,而不是表达式进行计算。