1
votes

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?

1
Please add some pseudo-code showing an example of what you're hoping to be able to do, because your question is ambiguous.phils
The question is unclear. Also, when always returns nil (unless it causes a non-local exit and does not return), so your wrapping it in or is useless. If you want to not execute projectile-dired when evil-delete-buffer returns non-nil then use and instead of when (or do something else that has the same effect).Drew
@phils done :)..... @Drew thanks I'm newbie in emacs, I would use an if statement if that wouldn't work, but it worked, though I'll get that modified, thanks.ZzAntáres

1 Answers

1
votes

(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.