3

How can I change the color of the fill-column-indicator and have the changes visible immediately?

(defun my:change-fci-color (color)
  (setq fci-rule-color color)
  (fci-redraw-frame))

The previous code doesn't change the color in existing buffers until the major mode is changed or I reload the buffer.

The following code works but feels like a gross hack.

(with-current-buffer "fill-column-indicator.el"
  (when fci-mode
    (turn-off-fci-mode)
    (turn-on-fci-mode)))

Ultimately, I want to change fci-rule-color based on the current theme's background color. So, when I change from a light theme to a dark theme, fci-rule-color remains a subtle shade off of the background color.

  • Since after collecting karma points one gets some mod's privileges, I can see you wanted to edit lawlist's answer. Why not post it as a separate answer instead of editing the existing one? – wvxvw Oct 8 '16 at 14:34
  • I didn't know it was a better option. I've moved my edits to a separate answer. – Joe Oct 9 '16 at 17:53
3

The following three lines of code in this specific order will immediately visibly update the fci-rule-color -- in this example, I am using the color "red".

(setq fci-rule-color "red")
(fci-make-overlay-strings)
(fci-update-all-windows t)
  • After a little bit more experimentation, this doesn't work for buffers that aren't visible when the code is run. I fell back to the turn-on, turn-off hack. – Joe Oct 6 '16 at 5:36
  • In addition to the window-list, you can loop through all buffers and operate on the ones where fci-mode is active. You would need to look at fci-upate-all-windows to see what makes it tick. You may wish to consider posting an alternative answer, or edit your question to contain a custom solution (e.g., underneath the question), rather than substantially modifying my own answer. My schedule is booked today and tomorrow, but if you need additional help, just let me know and I'll be able to lend a hand over the next few days as time permits. – lawlist Oct 6 '16 at 15:33
  • Thank you for the tip. I made an alternate answer so the proposed edit can get rejected. – Joe Oct 9 '16 at 17:54
3

Here's the complete end-to-end solution I ended up with based on lawlist's answer.

(defun my:color-is-closer-to-white-p (color)
  "Returns t if COLOR is closer to white than black."
  (< (color-distance color "white") (color-distance color "black")))

(defun my:get-subtle-color-from-background (percent-difference)
  "Gets a shade PERCENT-DIFFERENCE from the current background color.
If the color is closer to white, multiply percent-difference by 2
so it's easier to see."
  (let* ((current-background-color (face-background 'default)))
    (if (my:color-is-closer-to-white-p current-background-color)
        (color-darken-name current-background-color (* 2 percent-difference))
      (color-lighten-name current-background-color percent-difference))))

(defun my:change-fci-color (&rest args)
  "Change the fill-column-indicator based on the background.
ARGS is only used because we use this function as advice after
`load-theme'."
  (setq fci-rule-color (my:get-subtle-color-from-background 10))
  (let* ((wins (window-list (selected-frame) 'no-minibuf))
        (bufs (delete-dups (mapcar #'window-buffer wins))))
    (dolist (buf bufs)
      (with-current-buffer buf
        (when fci-mode
          (fci-make-overlay-strings)
          (fci-update-all-windows t))))))

(advice-add 'load-theme :after 'my:change-fci-color)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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