1

I frequently click on another application when I'm doing something in the minibuffer, and then I've forgotten I was in the minibuffer when I come back to emacs. I would like to highlight the minibuffer when it's active, but I'm in another emacs window. I have a solution that almost works.

(let ((bufs '(("0" . nil) ("1" . nil))))
  (defun tg/minibuf-conspicuous-when-active-hook ()
    (dolist (buf bufs)
      (if (and (not (minibufferp)) (active-minibuffer-window))
          (with-current-buffer (get-buffer (concat " *Minibuf-" (car buf) "*"))
            ;;(message "1-- %s %s" (car buf) bufs)
            (setcdr buf (face-remap-add-relative 'default :background "#355E3B")))
        (when (cdr buf)
          (with-current-buffer (get-buffer (concat " *Minibuf-" (car buf) "*"))
            ;;(message "2-- %s %s" (car buf) bufs)
            (face-remap-remove-relative (cdr buf))))))))
    (add-hook 'buffer-list-update-hook 'tg/minibuf-conspicuous-when-active-hook)
    (add-hook 'window-configuration-change-hook 'tg/minibuf-conspicuous-when-active-hook)

The reason I need both buffer-list-update-hook and window-configuration-change-hook is because there are some cases where buffer-list-update-hook is never called. This works if I move to another window within emacs and then back to the minibuffer. However, if I click on another application and then back, the minibuffer gets stuck on the new color I've set until I cancel. I can see from the debug messages that it is calling face-remap-remove-relative, but for some reason, it doesn't seem to work. In fact, I can replace that line with the following, and it works as expected.

            (face-remap-add-relative 'default :background "#000000")

Is there something I need to do to make it apply face-remap-remove-relative? Is there a simpler way to do this?

0

1 Answer 1

1

Minibuffer is selected Minibuffer is selected

Minibuffer is DE-selected Minibuffer is DE-selected

(require 'hi-lock)

(defcustom my-minibuf-active-and-selected-face 'hi-green ; You can set this to nil
  "The face specification used by when minibuffer is active and selected.
It may contain any value suitable for a `face' text property,
including a face name, a list of face names, a face attribute
plist, etc."
  :type '(choice (face)
                 (repeat :tag "List of faces" face)
                 (plist :tag "Face property list"))
  :group 'display)

(defcustom my-minibuf-active-and-deselected-face 'hi-salmon
  "The face specification used by when minibuffer is active and de-selected.
It may contain any value suitable for a `face' text property,
including a face name, a list of face names, a face attribute
plist, etc."
  :type '(choice (face)
                 (repeat :tag "List of faces" face)
                 (plist :tag "Face property list"))
  :group 'display)

;; current remapping cookie for  buffer-face-mode
(defvar-local my-minibuf-face-remapping nil)

(defun my-minibuf-update-mapping (face)
  ;; Remove existing mapping
  (when my-minibuf-face-remapping
    (face-remap-remove-relative my-minibuf-face-remapping)
    (setq my-minibuf-face-remapping nil))
  ;; Add new mapping
  (setq my-minibuf-face-remapping
        (face-remap-add-relative 'default face))
  ;; Update
  (force-window-update (current-buffer)))

(defun my-minibuf-selected-or-deselected-function (w)
  (cond
   ;; Minibuffer has been selected
   ((and (eq w (minibuffer-window))
         (eq w (selected-window)))
    (my-minibuf-update-mapping my-minibuf-active-and-selected-face))
   ;; Minibuffer has been deselected
   ((and (eq w (minibuffer-window))
         (not (eq w (selected-window))))
    (with-selected-window (minibuffer-window)
      (my-minibuf-update-mapping my-minibuf-active-and-deselected-face)))))

(add-hook 'minibuffer-setup-hook
          (defun install-minibuf-selected-or-deselected-function ()
            (add-hook 'window-selection-change-functions
                      'my-minibuf-selected-or-deselected-function nil t)))
4
  • I might be able to use this to simplify what I have, but it doesn't address my problem. The issue is I want to restore the default minibuffer colors, not change them to another color.
    – Todd
    Sep 23, 2022 at 13:06
  • I have updated the snippet. Based on what you want, set my-minibuf-active-and-selected-face to nil. The secret sauce missing from your snippet is the equivalent of what the variable my-minibuf-face-remapping in my snippet.
    – user31220
    Sep 24, 2022 at 8:20
  • It looks like force-window-update is the magic sauce. I've now noticed that my solution fails sometimes during buffer preview with vertico. I'm hoping this will fix these edge cases. I will try it tomorrow.
    – Todd
    Sep 24, 2022 at 12:56
  • Fantastic! I'm wondering why my-minibuf-selected-or-deselected-function is added as a hook inside minibuffer-setup-hook. Is it automatically removed when you exit the minibuffer?
    – Todd
    Sep 25, 2022 at 18:26

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.