Reputation:
I currently have the following:
(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)
Now, I want to toggle between (set-selective-display 2) and (set-selective-display 'nil)
Now, if I was in scheme, I would just create a s closure, and the closure would store a state variable, which would allow me to know which state I was in, and how to toggle.
However, Elisp is apparently a lisp-2 where variables and functions have different scope. Given this, how do I create closures / have be a toggle key?
Upvotes: 1
Views: 449
Reputation: 366
Here is a link to an answer I gave elsewhere about how to create real (not fake) closures in Elisp:
https://stackoverflow.com/a/14088107/1857114
I use a macro I call defun****. It works in Emacs 24.2.1 but I'm not sure what earlier versions it works for. Presumably the **defun special form will be upgraded some time in the future and the macro will be unnecessary.
Upvotes: 0
Reputation: 5532
selective-display
itself is the variable that contains the state you need to check, so you can write
(defun my-toggle-selective-display ()
(interactive)
(if selective-display
(set-selective-display nil)
(set-selective-display 2)))
As for closures in general, I had need of them for a project long ago and resorted to inserting uninterned symbols into a function definition using backquote substitution to avoid global variables. 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))))
which when run produces
M-x toggler
toggle is t
M-x toggler
toggle is nil
M-x toggler
toggle is t
M-: (boundp 'toggle)
nil
I guess this qualifies as a kludge, but I know of no other way to get anything like a closure in Emacs-Lisp.
Upvotes: 2
Reputation: 73314
Emacs 24 supports lexical binding, so real closures can be written.
See: What are the new rules for variable scoping in Emacs 24?
Just be aware that dynamic binding is a very large part of what makes Emacs so customizable, so use lexical binding with due care if you are writing something which may be of use to others -- ensure that you defvar
any variable which might potentially be useful for someone to override (ensuring, of course, that you think up all those potential use-cases that don't apply to you! :)
For Emacs < 24, see:
Upvotes: 3