2014-03-04 31 views
3

我将下面的代码添加到我的.emacs文件中。将函数传递给elisp中的参数

(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-<right>它不工作,只在迷你缓冲区中显示Wrong type argument: commandp, delete-right

我错过了什么,或者该怎么做才能正确使用代码?

回答

2

这里有一个修复:

(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)) 
+0

好了,下面我们就谁是刚刚开始学习elisp的用户。你真的认为提供一个解决方案是一个好主意,它使用lambda和backticks等进步技巧产生匿名函数,特别是当他已经有一个简单而直接的方法来实现这个功能时? – Lindydancer

+0

是的。在问题提出之前,操作系统的实现问题已经清楚地解决了。 OP是要求优雅,我展示给他。 –

+0

将lambda绑定到键或将其添加到钩子永远不会优雅。当用户检查一个键是绑定的还是一个钩子包含的时候,一个匿名lambda就像是一个死胡同,里面有一堆瓦砾(当然是用一粒盐做的) – Lindydancer

2

为了使功能变成命令,需要特殊形式interactive添加到它:

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

'interactive'应该位于与击键绑定的函数内。谢谢。 – ntalbs

2

的问题与您的代码是,它的函数绑定到应该交互的密钥。不是函数之一调用它:

(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") 
+0

宏观方法的一个小缺点是,你不能再跳转到 的定义。 'windmove-right'。 –

+0

谢谢你教我“交互式”应该在绑定到按键的功能中。在将'interactive'移动到'delete-right'后,它运行良好。 – ntalbs