13

My modeline is cluttered. Can I make it display pictures instead of mode names?

I could use unicode Emoji (such as for Python or for Coq), but some machines on which I use my Emacs config do not have the right fonts pre-installed (ideally, I'd also like to reuse this technique in a mode that I'm writing, so I can't expect users to have the right font setup).

I tried adding an :image display property to the modeline lighter of a toy minor-mode, but nothing appeared in the modeline:

(define-minor-mode my/test-mode
  "Test mode."
  :lighter (propertize " " 'display '(image :type imagemagick
                                             :file "/home/clement/.emacs.d/rooster.png")))

TWEmoji rooster (https://raw.githubusercontent.com/twitter/twemoji/gh-pages/72x72/1f413.png)

Clément
  • 3,924
  • 1
  • 22
  • 37

2 Answers2

12

The mode line is rendered from a list of segments, each of which come with their own special rules. See Mode Line Data for the details. The symbol section contains a crucial hint to make your code work:

Unless SYMBOL is marked as “risky” (i.e., it has a non-‘nil’ ‘risky-local-variable’ property), all text properties specified in SYMBOL’s value are ignored. This includes the text properties of strings in SYMBOL’s value, as well as all ‘:eval’ and ‘:propertize’ forms in it. (The reason for this is security: non-risky variables could be set automatically from file variables without prompting the user.)

I suspect nyan-mode is doing it in a less than ideal way, so here's my minimal example:

(defvar my-nyan-mode-lighter
  (list " " (propertize ":3" 'display
                        `(image :type imagemagick
                                :file ,(expand-file-name "~/nyan.png")))))
(put 'my-nyan-mode-lighter 'risky-local-variable t)

(define-minor-mode my-nyan-mode
  "Nyan mode"
  :lighter my-nyan-mode-lighter)

(my-nyan-mode)

The reason why I use a list of a space and an image is because it is convention to start a lighter with a space for separating it from the preceding ones.

wasamasa
  • 21,803
  • 1
  • 65
  • 97
  • Actually, did you try this in `emacs -Q`? It works great with smart-mode-line enabled, but I can't make it work when I start from a bare Emacs. – Clément Dec 28 '15 at 01:45
  • Huh, you're right. I'll check what else is missing. – wasamasa Dec 28 '15 at 09:33
  • OK, I've figured it out. Apparently that package just uses strings inside a format string whereas the real deal walks through the mode line segments individually and does only recognize strings that are propertized from start to end, so I've went for a list of two strings to have a separator. – wasamasa Dec 28 '15 at 10:17
  • Brillian, many thanks! The list tricks the mode line formatter into not applying the top-level `:propertize` of the default `mode-line-format`. – Clément Dec 28 '15 at 14:44
  • @wasamasa Wow, that's nice. Now when you mouse over the image, there is a generic menu ; how would one put entries in it? Just a simple string as a mouse hover message would be fine, too. – yPhil Jul 19 '17 at 19:53
  • Bonus question: How do you make a link (mouse-1) from this icon to, say, the `*scratch*` buffer? – yPhil Jul 19 '17 at 20:17
  • Comments are not for questions, if you want me to answer something, hand in a question please. – wasamasa Jul 19 '17 at 22:31
5

Good question.

You might try using something like this as the lighter: (concat " " (propertize " " 'display (create-image img-file))), where img-file is the name of your image file. (The first space char is just to separate this lighter from the previous one.)

Well, I just tried, using this code, but it did not work for me. You might try fiddling a bit more with it. Dunno whether it is possible.

(defvar my-lighter-string
        (concat " " (propertize " " 'display (create-image "/path/to/an/image/file.png"))))

(define-minor-mode foo "..." nil my-lighter-string)

The lighter just shows as an ordinary space char -- the display property does not seem to be respected.

If you don't get a good answer to this question, consider filing an Emacs enhancement request, using M-x report-emacs-bug.

One thing you can certainly do is to use one or two Unicode characters in the mode-line string. And you can use chars that are, in effect, graphics.

Drew
  • 75,699
  • 9
  • 109
  • 225