【问题标题】:Passing a function to a parameter in elisp将函数传递给elisp中的参数
【发布时间】:2014-03-04 09:59:45
【问题描述】:

我将以下代码添加到我的.emacs 文件中。

(defun delete-right-window ()
  (interactive)
  (windmove-right)
  (delete-window))

(defun delete-left-window ()
  (interactive)
  (windmove-left)
  (delete-window))

(defun delete-below-window ()
  (interactive)
  (windmove-down)
  (delete-window))

(defun delete-above-window ()
  (interactive)
  (windmove-up)
  (delete-window))

(global-set-key (kbd "C-s-<right>") 'delete-right-window)
(global-set-key (kbd "C-s-<left>") 'delete-left-window)
(global-set-key (kbd "C-s-<down>") 'delete-below-window)
(global-set-key (kbd "C-s-<up>") 'delete-above-window)

如您所见,大部分代码都是重复的。 我阅读了How do I pass a function as a parameter to in elisp? 并尝试将代码重构为传递windmove-* 函数,如下所示:

(defun delete-other-window (callback)
  (interactive)
  (funcall callback)
  (delete-window))
...

(defun delete-right ()
  (delete-other-window 'windmove-right))

我这样绑定击键:

(global-set-key (kbd "C-s-<right>") 'delete-right)

但是当我点击C-s-&lt;right&gt;时它不起作用,只在迷你缓冲区中显示Wrong type argument: commandp, delete-right

我遗漏了什么或者我应该怎么做才能正确处理代码?

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    这里有一个修复:

    (defun delete-after (fn)
      `(lambda () (interactive)
          (,fn)
          (delete-window)))
    
    (global-set-key (kbd "C-s-<right>") (delete-after 'windmove-right))
    (global-set-key (kbd "C-s-<left>") (delete-after 'windmove-left))
    (global-set-key (kbd "C-s-<down>") (delete-after 'windmove-down))
    (global-set-key (kbd "C-s-<up>") (delete-after 'windmove-up))
    

    【讨论】:

    • 好的,这里有一个刚刚开始学习 elisp 的用户。你真的认为提供一个使用 lambda 和反引号等高级技巧生成匿名函数的解决方案是一个好主意,尤其是当他已经有了一种简单、直接的方法来实现它的时候?
    • 是的。在提出问题之前,操作的实现问题已经明确解决。 OP 要求优雅,我向他展示。
    • 将 lambda 绑定到键或将其添加到钩子从来都不是优雅的。当用户检查一个键绑定到什么或一个钩子包含什么时,匿名 lambda 就像死路一条,里面有一堆瓦砾(当然是带着一粒盐;)
    • 在我的 Emacs 中,f1 k 显示了匿名 lambda 的代码。有人可能会说它更有效,因为我不必跳到定义来查看源代码:)
    • 嗨 indydancer。 IMO 我期待很多不同的答案。同样的答案价值不高。你不这么认为吗?所以abo-abo的回答对我来说很有价值。我认为 OP 只是期望答案的人之一。所以你不需要回答只是OP。如果您还有其他可能的答案,请发布。谢谢。
    【解决方案2】:

    要将一个函数变成一个命令,你需要给它加上特殊的interactive

    (defun delete-right ()
      (interactive)
      (delete-other-window 'windmove-right))
    

    【讨论】:

    • interactive 应该位于绑定到击键的函数内。谢谢。
    【解决方案3】:

    您的代码的问题在于绑定到键的函数应该是交互式的。不是它调用的函数之一:

    (defun delete-other-window (callback)
      (funcall callback)
      (delete-window))
    
    (defun delete-right ()
      (interactive)
      (delete-other-window 'windmove-right))
    

    你也可以使用宏:

    (defmacro defun-delete-other-window (direction)
      `(defun ,(intern (concat "delete-" direction)) ()
         (interactive)
         (,(intern (concat "windmove-" direction)))
         (delete-window)))
    
    (defun-delete-other-window "right")
    

    【讨论】:

    • 宏方法的一个小缺点是您不能再跳转到例如windmove-right.
    • 谢谢你教我interactive应该在绑定按键的函数里。将interactive移动到delete-right后,效果很好。
    猜你喜欢
    • 2010-09-17
    • 2018-06-30
    • 1970-01-01
    • 2011-10-09
    • 2013-01-27
    • 2022-08-20
    • 2021-04-18
    相关资源
    最近更新 更多