41.18 Icons

Emacs sometimes uses buttons (for clicking on) or small graphics (to illustrate something). Since Emacs is available on a wide variety of systems with different capabilities, and users have different preferences, Emacs provides a facility to handle this in a convenient way, allowing customization, graceful degradation, accessibility, as well as themability: Icons.

The central macro here is define-icon, and here’s a simple example:

(define-icon outline-open button
  '((image "right.svg" "open.xpm" "open.pbm" :height line)
    (emoji "▶️")
    (symbol "▶" "➤")
    (text "open" :face icon-button))
  "Icon used for buttons for opening a section in outline buffers."
  :version "29.1"
  :help-echo "Open this section")

Which alternative will actually be displayed depends on the value of the user option icon-preference (see Icons in The GNU Emacs Manual) and on the results of run-time checks for what the current frame’s terminal can actually display.

The macro in the example above defines outline-open as an icon, and inherits properties from the icon called button (so this is meant as a clickable button to be inserted in a buffer). It is followed by a list of icon types along with the actual icon shapes themselves. In addition, there’s a doc string and various keywords that contain additional information and properties.

To instantiate an icon, you use icon-string, which will consult the current Customize theming, and the icon-preference user option, and finally what the Emacs is able to actually display. If icon-preference is (image emoji symbol text) (i.e., allowing all of these forms of icons), in this case, icon-string will first check that Emacs is able to display images at all, and then whether it has support for each of those different image formats. If that fails, Emacs will check whether Emacs can display emojis (in the current frame). If that fails, it’ll check whether it can display the symbol in question. If that fails, it’ll use the plain text version.

For instance, if icon-preference doesn’t contain image or emoji, it’ll skip those entries.

Code can confidently call icon-string in all circumstances and be sure that something readable will appear on the screen, no matter whether the user is on a graphical terminal or a text terminal, and no matter which features Emacs was built with.

Macro: define-icon name parent specs doc &rest keywords

Define an icon name, a symbol, with the display alternatives in spec, that can be later instantiated using icon-string. The name is the name of the resulting keyword.

The resulting icon will inherit specs from parent, and from their parent’s parents, and so on, and the lowest descendent element wins.

specs is a list of icon specifications. The first element of each specification is the type, and the rest is something that can be used as an icon of that type, and then optionally followed by a keyword list. The following icon types are available:

image

In this case, there may be many images listed as candidates. Emacs will choose the first one that the current Emacs instance can show. If an image is listed is an absolute file name, it’s used as is, but it’s otherwise looked up in the list image-load-path (see Defining Images).

emoji

This should be a (possibly colorful) emoji.

symbol

This should be a (monochrome) symbol character.

text

Icons should also have a textual fallback. This can also be used for the visually impaired: if icon-preference is just (text), all icons will be replaced by text.

Various keywords may follow the list of icon specifications. For instance:

(symbol "▶" "➤" :face icon-button)

Unknown keywords are ignored. The following keywords are allowed:

:face

The face to be used for the icon.

:height

This is only valid for image icons, and can be either a number (which specifies the height in pixels), or the symbol line, which will use the default line height in the currently selected window.

:width

This is only valid for image icons, and can be either a number (which specifies the width in pixels), or the symbol font, which will use the width in pixels of the current buffer’s default face font.

doc should be a doc string.

keywords is a list of keyword/value pairs. The following keywords are allowed:

:version

The (approximate) Emacs version this button first appeared. (This keyword is mandatory.)

:group

The customization group this icon belongs in. If not present, it is inferred.

:help-echo

The help string shown when hovering over the icon with the mouse pointer.

Function: icon-string icon

This function returns a string suitable for display in the current buffer for icon.

Function: icon-elements icon

Alternatively, you can get a “deconstructed” version of icon with this function. It returns a plist (see Property Lists) where the keys are string, face and image. (The latter is only present if the icon is represented by an image.) This can be useful if the icon isn’t to be inserted directly in the buffer, but needs some sort of pre-processing first.

Icons can be customized with M-x customize-icon. Themes can specify changes to icons with, for instance:

(custom-theme-set-icons
  'my-theme
  '(outline-open ((image :height 100)
                  (text " OPEN ")))
  '(outline-close ((image :height 100)
                   (text " CLOSE " :face warning))))