简体   繁体   English

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

[英]How to call interactive Emacs Lisp function with a prefix argument, from another Emacs Lisp function?

I want to write an Emacs Lisp function that will turn on flyspell-mode regardless of the current state of the mode. 我想编写一个Emacs Lisp函数,无论flyspell-mode的当前状态如何,都会打开flyspell-mode模式。 Function flyspell-mode-on is deprecated. 函数flyspell-mode-on已弃用。 The documentation suggests that a positive prefix argument will turn flyspell-mode , but unfortunately running 文档表明,正前缀参数将变为flyspell-mode ,但遗憾的是运行

(flyspell-mode 1)

results in an error message: 导致错误消息:

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

If I could figure out how to call flyspell-mode with a prefix argument, I believe I could solve this problem. 如果我能弄清楚如何使用前缀参数调用flyspell-mode ,我相信我可以解决这个问题。

The most relevant section I can find in the Emacs Lisp manual is the section entitled "Interactive Call", which describes such commands as call-interactively . 我在Emacs Lisp手册中可以找到的最相关的部分是标题为“交互式呼叫”的部分,它将这些命令描述为call-interactively This is emphatically not what I want. 这显然不是我想要的。

(The ultimate problem I am trying to solve is to create a mode hook that turns on the mode regardless of its current state.) (我试图解决的最终问题是创建一个模式挂钩,无论当前状态如何,都会打开模式。)

NB The title of the question emacs lisp call function with prefix argument programmatically makes it appear to be related, but that question was asking about how to create an interactive command, and the issue was ultimately resolved by using call-interactively . NB问题的标题emacs lisp调用函数带有前缀参数以编程方式使其看起来是相关的,但该问题是询问如何创建交互式命令,并且问题最终通过call-interactively解决。


EDIT : This question is moot; 编辑 :这个问题没有实际意义; I have found an alternate solution to my original problem: 我找到了原始问题的替代解决方案:

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

But I would still like to know how to call an Emacs Lisp function with a prefix argument, from another Emacs Lisp function, with nothing interactive. 但我仍然想知道如何从另一个Emacs Lisp函数调用带有前缀参数的Emacs Lisp函数, 没有任何交互。


UPDATE : Perhaps I should have asked why I was getting that error message... 更新 :也许我应该问为什么我收到错误消息...

It looks like your version of Flyspell mode does not follow the minor mode conventions , which require that you can turn on a minor mode with (name-of-mode t) or any positive prefix argument, turn it off with (name-of-mode 0) any negative prefix argument, and toggle it with (name-of-mode nil) . 看起来您的Flyspell模式版本不遵循次要模式约定 ,这要求您可以使用(name-of-mode t)或任何正前缀参数打开次要模式,将其关闭(name-of-mode 0)任何负前缀参数,并用(name-of-mode nil)切换它。

If you have the latest version of Flyspell, a bug report might be in order. 如果你有最新版本的Flyspell,可能会有错误报告。 I have the version shipped with GNU Emacs 23.2 on my machine, and it respects the convention. 我在我的机器上有GNU Emacs 23.2附带的版本,它遵守惯例。 My version also defines two functions turn-on-flyspell and turn-off-flyspell , both trivial wrappers around flyspell-mode ; 我的版本还定义了两个函数turn-on-flyspellturn-off-flyspell ,这两个函数都是关于flyspell-mode简单包装器; functions with such names are common, but not official conventions. 具有此类名称的函数很常见,但不是官方惯例。 The functions flyspell-mode-on and flyspell-mode-off are apparently intended for internal use. flyspell-mode-onflyspell-mode-off功能显然是供内部使用的。

As a general matter, commands read the current prefix argument from the current-prefix-arg variable. 一般来说,命令从current-prefix-arg变量中读取当前前缀参数。 Don't confuse that with prefix-arg , which is the value for the next command (only a few commands like universal-argument touch this variable). 不要将它与prefix-arg混淆,后者是下一个命令的值(只有几个命令,如universal-argument touch this变量)。 Thus, if you need to pass a prefix argument when calling a function, bind or set current-prefix-arg . 因此,如果在调用函数时需要传递前缀参数,请绑定或设置current-prefix-arg

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

If you are not calling a function interactively, then the (interactive) declaration is not used to obtain the arguments. 如果不是以交互方式调用函数,则不使用(interactive)声明来获取参数。

In the vast majority of cases, you do not need to worry about whether an argument can be a "prefix argument" for non-interactive calls; 在绝大多数情况下,您无需担心参数是否可以成为非交互式调用的“前缀参数”; just check the function documentation, and pass the value you need for whatever it is you want to do. 只需检查功能文档,并传递您想要做的任何事情所需的值。

If for some reason you do need to replicate sending a prefix argument in a non-interactive context, you will need to check that function's (interactive) declaration and determine exactly how it is using that argument, and ensure that you replicate that behaviour for the argument you do pass. 如果出于某种原因,您确实需要复制在非交互式上下文中发送前缀参数,则需要检查该函数的(interactive)声明并确定它是如何使用该参数的,并确保为此复制该行为。你通过的论点。

For full details, see: 有关详细信息,请参阅:

  • Ch f interactive RET CH˚F interactive RET
  • M-: (info "(elisp) Prefix Command Arguments") RET M- :( (info "(elisp) Prefix Command Arguments") RET

In more complex cases where the function changes its behaviour based on the current-prefix-arg variable, you may be able to set that variable directly. 在更复杂的情况下,函数根据current-prefix-arg变量更改其行为,您可以直接设置该变量。

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

I can think of this.. Should be more better 我能想到这个......应该会更好

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

UPDATE: I can run this directly.. what am i missing from the question.? 更新:我可以直接运行这个问题。我在问题中缺少什么。

(flyspell-mode '(4))

EDITED: Removed quote for lambda expression (I added this note because SX forces an edit to be at least six characters long, so this can be deleted). EDITED:删除了lambda表达式的引用(我添加了这个注释,因为SX强制编辑长度至少为六个字符,因此可以删除)。

See my comment for the fix to the source of your problem. 请参阅我的评论以解决您的问题来源。 As for the answer to your question, the way the prefix arg is turned into some kind of Lisp argument depends on the interactive spec, so the only way to do it reliably (ie without prior knowledge such as the fact that it's a minor mode function) is to call the function interactively: 至于你的问题的答案,前缀arg转换成某种Lisp参数的方式取决于interactive规范,所以唯一的方法是可靠地做到这一点(即没有先验知识,例如它是一个小模式函数的事实)是以交互方式调用函数:

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

FWIW, the `flyspell-mode' function has accepted an argument (as in "(flyspell-mode 1)") at least since Emacs-21, so I don't know how you got that error. FWIW,`flyspell-mode'函数已经接受了一个参数(如“(flyspell-mode 1)”),至少从Emacs-21开始,所以我不知道你是怎么得到那个错误的。

But while I'm here, I might as well point out that (add-hook 'text-mode-hook 'flyspell-mode) has changed meaning in Emacs-24: instead of meaning "toggle flyspell-mode in text modes" it will now mean "enable flyspell-mode in text modes". 但是当我在这里时,我不妨指出(add-hook'text-mode-hook'flyspell-mode)在Emacs-24中改变了意义:而不是意味着“在文本模式中切换flyspell-mode”它现在意味着“在文本模式下启用flyspell-mode”。 It's a backward-incompatible change, but I believe it will fix more latent bugs than it will introduce. 这是一个向后不兼容的变化,但我相信它会修复比它引入的更多潜在错误。

我不是Emacs和Elisp的主人( 还有 ))但我认为在这种情况下你可以使用 Ctrl - u 1 Alt - x flyspell-mode

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM