When using ivy
, say I want the current match to be red when calling counsel-M-x
, but blue when calling counsel-find-file
.
Is there a simple way of changing ivy-current-match
depending on the function calling it?
Emacs Stack Exchange is a question and answer site for those using, extending or developing Emacs. It only takes a minute to sign up.
Sign up to join this communityAFAIK, there is no built-in support for this, but Ivy provides various hooks that you can plug your own logic into. Here is one way to achieve what you want, using the ivy-hooks-alist
user option:
(defvar my-ivy-match-faces
'((counsel-M-x (:background "red")))
"Alist mapping Ivy callers to a list of face specs.
Used by `my-ivy-remap-match-face', which see.")
(defun my-ivy-remap-match-face ()
"Locally remap `ivy-current-match' to caller-specific face specs.
Which face specs to apply for each caller is determined by
`my-ivy-match-faces'. If the current caller is unknown, or if
there is no entry for it, no remapping is applied."
(when-let* ((caller (ivy-state-caller ivy-last))
(specs (alist-get caller my-ivy-match-faces)))
(apply #'face-remap-add-relative 'ivy-current-match specs)))
(with-eval-after-load 'ivy
;; Remap the current match face as the default Ivy hook. Note that specifying
;; a different hook for a particular caller will override this setting.
(setf (alist-get t ivy-hooks-alist) #'my-ivy-remap-match-face))
The idea here is to look up the current Ivy caller (e.g. counsel-M-x
) right after Ivy has set up the minibuffer, and then locally remap[1] the ivy-current-match
face to a list of face specs of your choosing. In the sample code above, I have remapped the background to be red for counsel-M-x
(see the variable my-ivy-match-faces
).
Note that the way I modify ivy-hooks-alist
, namely by setting my-ivy-remap-match-face
as the default fallback hook, is kind of brittle. This is because any subsequent addition to this alist may override my-ivy-remap-match-face
. Vanilla Ivy does not modify ivy-hooks-alist
, so this is not an issue at the moment, but it may become one in the future or if you use other packages which modify this user option.
A more robust solution would then be to submit a feature request or PR[2] to make ivy-hooks-alist
more flexible, e.g. by supporting multiple hooks per caller, and always running the default fallback hooks.
If that is not an option, you can advise[3] specific entries in ivy-hooks-alist
to do your bidding. I will be happy to provide a sample implementation of this if asked.
ivy-current-match
. I tried to fix this by also remapping ivy-prompt-match
, but this doesn't seem to control the color of the matched characters.
– scaramouche
Feb 10 '20 at 18:56