《elisp 每日一练》—— Major Mode mode line 显示

《elisp 每日一练》—— Major Mode mode line 显示

Masimaro
2026-09-21 / 0 评论 / 0 阅读 / 正在检测是否收录...

在前面我们介绍了 Minor Mode 是如何在mode line中显示的。简单来说就是 mode line 的显示依靠 mode-line-format,默认的format 中存在一个名为 mode-line-modes 的符号,它会解析并显示 minor-mode-alist 的内容。在定义 minor mode 的时候通过关键字 lighter 传入的文字在调用 add-minor-mode 时会被加入 minor-mode-alist 中,在mode处于启用状态时显示。

define-derived-mode 中没有这样的关键字,它是直接通过宏参数赋值给 mode-name 进行显示。今天我们来看看背后发生了什么

背景知识

我们以 scratch buffer 为例。在Emacs中可以查到 mode-name 的值为 "Lisp Interaction"。

前面在讨论 mode-line-format 的时候提到过,当前加载mode的信息位于 mode-line-modes 变量中,我们查看该变量找到关键信息(在最开始的位置):

(:propertize (#1="" mode-name)
             help-echo "Major mode
mouse-1: Display major mode menu
mouse-2: Show help for major mode
mouse-3: Toggle minor modes"
             mouse-face mode-line-highlight
             local-map
             (keymap ...))

根据我们前面介绍的 mode-line-format 格式,#1 是一个引用标记,等价于空字符,所以这部分显示的就单单只是 mode-name 的值

练习

各位读者在配置Emacs或者vim的 lsp 的时候会发现,一些插件会显示lsp 服务器的状态例如显示 lsp[connected] 字样表示已经连接上了lsp服务器。我们来尝试一下利用 mode-line-format 来模拟一下这个状态。

首先我们定义一些模拟函数

(defvar my/lsp-test-status nil
  "模拟 LSP 连接状态。取值如 nil、'connected。")

(defun my/test-lsp-connect ()
  (interactive)
  (setq my/lsp-test-status 'connected)
  (force-mode-line-update))

(defun my/test-lsp-disconnect ()
  (interactive)
  (setq my/lsp-test-status nil)
  (force-mode-line-update))

然后我们还需要一个根据状态查找显示字符串的函数:

(defun my/test-lsp-status ()
  "根据 `my/lsp-test-status' 返回要显示的字符串。"
  (pcase my/lsp-test-status
    ('connected " lsp [connected]")
    (_ "")))

最后我们定义一个对应的 Major Mode。根据文档,NAME 变量本身应该传入一个字符串,所以我们实际上不能直接在 NAME 字段输入列表作为显示内容,而应该在外部进行修改。

(define-derived-mode my/lsp-test-mode nil "Test"
  "演示动态 mode-name。"
  (setq mode-name '(:eval (concat "Test" (my/test-lsp-status)))))

总结

本节的内容比较简单,实际上读者在阅读并理解了之前分析 minor mode 中显示的文章之后,本节内容差不多能无师自通了。唯一需要注意的是 NAME 参数在文档中已经明确说明是字符串。所以如果想要实现动态更新的话,可能要在后面修改 mode-name 的值。

0

评论 (0)

取消