42.18 图标

Emacs 有时会使用可点击按钮或小型图形用于内容示意。由于 Emacs 运行在能力各异的多种系统上,且用户偏好不同,Emacs 提供了一套便捷机制来处理这类需求,支持自定义、优雅降级、无障碍访问以及主题化:Icons

核心宏为 define-icon,以下是简单示例:

(define-icon outline-open button
  '((image "right.svg" "open.xpm" "open.pbm" :height line)
    (emoji "▶️")
    (symbol "▶" "➤")
    (text "open" :face icon-button))
  "用于在大纲缓冲区中打开章节的按钮图标。"
  :version "29.1"
  :help-echo "Open this section")

实际显示哪种备选形式,取决于用户选项 icon-preference(see Icons in The GNU Emacs Manual)以及运行时对当前框架终端实际显示能力的检测结果。

上例中的宏将 outline-open 定义为图标,并继承名为 button 的图标的属性(因此该图标为可插入缓冲区的可点击按钮)。其后跟随一列 图标类型(icon types) 及对应的图标形态,此外还有文档字符串和包含附加信息与属性的多个关键字。

要实例化图标,可使用 icon-string,它会参考当前自定义主题、用户选项 icon-preference 以及 Emacs 实际可显示的内容。若 icon-preference(image emoji symbol text)(即允许所有图标形式),icon-string 会先检查 Emacs 是否支持显示图像,再依次检查各图像格式;若不支持则检查当前框架能否显示表情符号;仍不支持则检查能否显示指定符号;最后降级为纯文本形式。

例如,若 icon-preference 不包含 imageemoji,则会跳过对应条目。

代码可在任何场景下放心调用 icon-string,并确保屏幕上会出现可读内容,无论用户使用图形终端还是文本终端,也无论 Emacs 编译时启用了哪些功能。

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

定义一个符号类型的图标 name,其显示备选方案在 spec 中,后续可通过 icon-string 实例化。name 为最终生成的关键字名称。

生成的图标会继承 parent 及其上层父图标的规格,层级最低的后代优先级最高。

specs 为图标规格列表。每个规格的第一个元素为类型,后续为该类型可用的图标内容,最后可接关键字列表。支持以下图标类型:

image

此下列出多个图像作为候选。Emacs 会选择当前实例可显示的第一个图像。若图像为绝对路径文件名则直接使用,否则在 image-load-path 列表中查找(see 定义图像)。

emoji

应为(可彩色的)表情符号。

symbol

应为(单色)符号字符。

text

图标应提供文本降级方案。该形式也可用于视障用户:若 icon-preference 仅为 (text),所有图标将替换为文本。

图标规格列表后可跟随多个关键字,例如:

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

未知关键字会被忽略。支持以下关键字:

:face

图标使用的文本视觉样式。

:height

仅对 image 图标有效,可为数值(指定像素高度)或符号 line(使用当前选中窗口的默认行高)。

:width

仅对 image 图标有效,可为数值(指定像素宽度)或符号 font(使用当前缓冲区默认文本视觉样式字体的像素宽度)。

doc 应为文档字符串。

keywords 为关键字/值对列表,支持以下关键字:

:version

该图标首次出现的(大致)Emacs 版本。(此关键字为必填项。)

:group

该图标所属的自定义组。未指定时自动推断。

:help-echo

鼠标指针悬停在图标上时显示的帮助字符串。

Function: icon-string icon

此函数返回适用于在当前缓冲区显示的 icon 字符串。

Function: icon-elements icon

你也可以通过此函数获取 icon 的“解构”形式。它返回一个属性列表(see 属性列表),键为 stringfaceimage(仅当图标由图像表示时存在)。若图标不直接插入缓冲区而需要预处理,此函数会很有用。

图标可通过 M-x customize-icon 自定义。主题可通过如下方式修改图标:

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