Reputation: 350
I'm using emacs with evil-mode, I want to map <leader>tt
to the function projectile-dired
however if a dired buffer is being shown then it should be mapped to the evil-delete-buffer
, so in essence creating a map to a toggle function.
After learning the basics of emacs lisp I came up with this solution:
(defun toggle-projectile-dired ()
"Toggles projectile-dired buffer."
(interactive)
(or
(when (derived-mode-p 'dired-mode)
(evil-delete-buffer (current-buffer)))
(projectile-dired)))
;; This is how the mapping is done
(evil-leader/set-key "tt" 'toggle-projectile-dired)
But what I did with this solution was to create a map to a function that in the end calls to another function.
While my solution works (and I'm fine with it) what I could not do was to return the function to be called (instead of calling it, as I did) how such approach should be written?
Or in other words, how to return a function name and make that mapping call the returning function?.
PD: This question is just for the sake of learn some elisp. Thanks!
EDIT:
Here is some pseudo code (javascript) of what I want to achieve:
function toggleProjectileDired() {
if (derivedModeP == 'dired-mode') {
// We're in dired buffer
return 'evilDeleteBuffer';
} else {
return 'projectileDired';
}
}
evilLeaderSetKey("tt", toggleProjectileDired());
My solution in pseudo code is:
function toggleProjectileDired() {
if (derivedModeP == 'dired-mode') {
// We're in dired buffer
evilDeleteBuffer();
} else {
projectileDired();
}
}
evilLeaderSetKey("tt", toggleProjectileDired);
As you can see, one returns the function name to be called while the other calls the function. How to return a function name to be called in elisp?
Upvotes: 1
Views: 432
Reputation: 73274
(Caveat: I don't use evil
, and am not familiar with its custom keybinding functions.)
The canonical approach to making a key do one thing in dired-mode
and another thing elsewhere is to define one binding in dired's keymap, and another binding in the global keymap (or whatever is appropriate). I would recommend that you try to follow this approach in most circumstances, because it makes it much simpler to see what's happening.
However, there is a way to do what you're asking for. These pages demonstrate some variations on the approach:
In essence you use the :filter
facility of menu items (n.b. menus are actually fancy keymaps in Emacs) to determine the command at run-time. Note that if the filter function returns nil
, Emacs treats it as if no binding exists in that keymap, and continues looking for a binding in the remaining keymaps; so this feature facilitates bindings which are only conditionally active.
A non-evil
version of your example might look like this:
(define-key global-map (kbd "<f6>")
`(menu-item "" projectile-dired
:filter ,(lambda (default)
(if (derived-mode-p 'dired-mode)
'evil-delete-buffer
default))))
Again, this would be more usual:
(global-set-key (kbd "<f6>") 'projectile-dired)
(eval-after-load "dired"
'(define-key dired-mode-map (kbd "<f6>") 'evil-delete-buffer))
FWIW, I actually think the general approach you started with is probably the best one in this instance. If typing KEY should always toggle dired
in that window, then binding it to a toggle-dired
command seems like the most self-explanatory implementation.
Upvotes: 1