Emacs / Elisp / Closure / Toggle

时间:2012-04-16 03:06:23

标签: emacs closures elisp

我目前有以下内容:

(defun my-hide-code ()                                                                                                                         
  (interactive)                                                                                                                                
  (set-selective-display 2))                                                                                                                   

(defvar my-keys-minor-mode-map (make-keymap) "my-keys-minor-mode keymap.")                                                                     
(define-key my-keys-minor-mode-map (kbd "<f2>") 'my-hide-code)                                                                                 
(define-minor-mode my-keys-minor-mode                                                                                                          
  "use"                                                                                                                                        
  t " my-keys" 'my-keys-minor-mode-map)                                                                                                        
(my-keys-minor-mode 1)    

现在,我想在两者之间切换 (set-selective-display 2) 和 (set-selective-display'nil)

现在,如果我在计划中,我只会创建一个闭包,闭包将存储一个状态变量,这将允许我知道我在哪个州,以及如何切换。

然而,Elisp显然是一个lisp-2,变量和函数的范围不同。鉴于此,如何创建闭包/成为切换键?

3 个答案:

答案 0 :(得分:3)

Emacs 24支持词法绑定,因此可以编写真正的闭包。

请参阅: What are the new rules for variable scoping in Emacs 24?

请注意,动态绑定是使得Emacs可以自定义的非常的很大一部分,因此如果您正在编写可能对其他人有用的内容,请谨慎使用词法绑定 - 确保您defvar任何可能可能对某人有用的变量(当然,确保您想出所有那些不适合您的潜在用例!): )

对于Emacs&lt; 24,见:

答案 1 :(得分:2)

selective-display本身是包含您需要检查的状态的变量,因此您可以编写

(defun my-toggle-selective-display ()
  (interactive)
  (if selective-display
      (set-selective-display nil)
    (set-selective-display 2)))

对于一般的闭包,我很久以前就需要它们用于项目,并使用反引号替换将未加工符号插入函数定义以避免全局变量。 E.g。

(fset 'toggler
      (let ((toggle-var (make-symbol "toggle")))
        (set toggle-var nil)
        `(lambda () (interactive)
           (cond (,toggle-var
                  (setq ,toggle-var nil))
                 (t
                  (setq ,toggle-var t)))
           (message "toggle is %s" ,toggle-var))))

运行时产生

M-x toggler
toggle is t
M-x toggler
toggle is nil
M-x toggler
toggle is t
M-: (boundp 'toggle)
nil

我认为这可以作为一个kludge,但我知道没有其他方法可以像Emacs-Lisp中的闭包一样。

答案 2 :(得分:0)

以下是我在其他地方提供的关于如何创建真实(非虚假)的答案的链接 Elisp的关闭:

https://stackoverflow.com/a/14088107/1857114

我使用宏调用 defun ****。它适用于Emacs 24.2.1,但我不确定是什么 它的早期版本适用于。据推测,** defun 特殊形式将是 在未来的某个时间升级,宏将是不必要的。