0

Apologies if the question is poorly formulated, I am a beginner at understanding internals of Emacs/packages.

I am using using Doom Emacs, which provides Ivy as an interface for, for example, finding files.

I understand that custom actions can be created for acting on candidates. In my case (with Doom's Evil bindings), I select a candidate and hit C-o to open the actions menus

I wrote a function that opens the selected file in a vertical split rather than in the current window, and added it as an action.

However, I would like to call this function directly by hitting a keyboard shortcut when I'm in Ivy (as I'm filtering files/buffers and selecting a candidate), instead of having the additional step of opening the actions menu.

So, for example, when I open ivy in my personal config folder and select the file I want, I would like to:

  • Press RET to perform the default Ivy action (open the file in the current window)
  • Press C-v to open the file in a vertical split using my custom function
  • Possibly add more key mappings for other custom functions as well.

How might I be able to accomplish this?

3

1 Answer 1

3

However, I would like to call this function directly when I'm in Ivy (as I'm filtering files/buffers and selecting a candidate), instead of having the additional step of opening the actions menu. How might I be able to accomplish this?

If I understood correctly, you're trying to set this function as the default action.

If you're calling ivy-read yourself, you can pass this function as the value of the :action keyword. For example:

(defun my-echo (&rest args)
  "Echo ARGS."
  (message ">>> %s" args))

(ivy-read "Echo: " '("a" "b" "c") :action #'my-echo)

You can also modify the action list of an existing command, for example:

(ivy-add-actions #'ivy-switch-buffer '(("o" my-echo "echo")))

Here "o" is the default action key, so this will actually replace the previous default with my-echo.

For more on Ivy actions, see (info "(ivy) Actions").

Edit

Possibly add more key mappings for other custom functions as well.

If you're calling ivy-read directly, you can specify a custom keymap to be composed with ivy-minibuffer-map, for example:

(defun my-echo-candidate ()
  "Exit Ivy completion, echoing selected candidate."
  (interactive)
  (ivy-exit-with-action
   (lambda (cand)
     (message ">>> %s" cand))))

(ivy-read "Echo: " '("a" "b" "c")
          :keymap (easy-mmode-define-keymap '(("\C-v" . my-echo-candidate))))

Of course, to reuse your custom bindings, you can either create your own named keymap:

(defvar my-ivy-map
  (let ((map (make-sparse-keymap)))
    (define-key map "\C-v" #'my-echo-candidate)
    map)
  "Keymap to compose with `ivy-minibuffer-map'.")

or modify ivy-minibuffer-map directly (see (info "(ivy) Minibuffer key bindings")). This is probably your only option if you want to modify the minibuffer keymap of an Ivy command not under your direct control.

3
  • Thank you very much for taking the time to respond! I wasn't clear in my question and omitted a critical part: Rather than replacing or modifying the default action, I would like to map a key to calling my custom action in Ivy. So in the same way as RET calls the default "open" action, I would like for example C-v to call my custom function. Any idea how I might be able to do that?
    – gosha
    Apr 29, 2021 at 7:12
  • @gueorgui Thanks for clarifying. Let me know whether the updated answer addresses your question.
    – Basil
    Apr 29, 2021 at 17:32
  • Thank you, that's exactly what I was looking for. Accepted!
    – gosha
    Apr 29, 2021 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.