首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
283 阅读
2
从零开始配置 vim(15)——状态栏配置
168 阅读
3
nvim番外之将配置的插件管理器更新为lazy
159 阅读
4
2018总结与2019规划
145 阅读
5
PDF标准详解(五)——图形状态
121 阅读
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
登录
Search
标签搜索
c++
c
学习笔记
windows
emacs
elisp
文本操作术
编辑器
NeoVim
Vim
win32
读书笔记
VimScript
linux
文本编辑器
投资理财
Java
反汇编
OLEDB
数据库编程
Masimaro
累计撰写
435
篇文章
累计收到
32
条评论
首页
栏目
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
页面
归档
友情链接
关于
搜索到
1
篇与
的结果
2026-09-16
《elisp 每日一练》——Major Mode 初步探索
在前面的文章中,我们详细分析了关于 minor mode 对于各种资源的管理,最后以一个修改宏增加参数的例子结束了关于minor mode 的话题。今天我们正式进入有关 Major Mode 的话题背景知识与Minor Mode 不同,一个buffer 只能有一个Major Mode。我们可以使用宏 define-derived-mode 来定义 Major Mode。你可能会感觉很奇怪,为什么minor mode 的定义是使用 define-minor-mode 而 Major Mode 是不是使用 define-major-mode 来定义了。这是因为 Major Mode 引入了继承机制。(define-derived-mode CHILD PARENT NAME [DOCSTRING] [KEYWORD-ARGS...] &rest BODY)CHILD 新定义的Major Mode 的名称,与 define-minor-mode 的第一个参数相同PARENT 父类Major Mode 的名称NAME Major 的字符串名称KEYWORD-ARGS 可选的关键字参数对,用于精细控制模式的初始化行为我们还是用一个最简单的例子看看它展开之后是什么样子的(define-derived-mode my/foucs-mode nil "My Focus")展开之后,显示如下内容:(progn (defvar my/foucs-mode-hook nil) (unless (get 'my/foucs-mode-hook 'variable-documentation) (put 'my/foucs-mode-hook 'variable-documentation "Hook run after entering `my/foucs-mode'.\nNo problems result if this variable is not bound.\n`add-hook' automatically binds it. (This is true for all hook variables.)")) (unless (boundp 'my/foucs-mode-map) (put 'my/foucs-mode-map 'definition-name 'my/foucs-mode)) (with-no-warnings (defvar my/foucs-mode-map (make-sparse-keymap))) (unless (get 'my/foucs-mode-map 'variable-documentation) (put 'my/foucs-mode-map 'variable-documentation (purecopy "Keymap for `my/foucs-mode'."))) (progn (defvar my/foucs-mode-syntax-table) (unless (boundp 'my/foucs-mode-syntax-table) (put 'my/foucs-mode-syntax-table 'definition-name 'my/foucs-mode) (defvar my/foucs-mode-syntax-table (make-syntax-table))) (unless (get 'my/foucs-mode-syntax-table 'variable-documentation) (put 'my/foucs-mode-syntax-table 'variable-documentation (purecopy "Syntax table for `my/foucs-mode'.")))) (progn (defvar my/foucs-mode-abbrev-table) (unless (boundp 'my/foucs-mode-abbrev-table) (put 'my/foucs-mode-abbrev-table 'definition-name 'my/foucs-mode) (defvar my/foucs-mode-abbrev-table (progn (define-abbrev-table 'my/foucs-mode-abbrev-table nil) my/foucs-mode-abbrev-table))) (unless (get 'my/foucs-mode-abbrev-table 'variable-documentation) (put 'my/foucs-mode-abbrev-table 'variable-documentation (purecopy "Abbrev table for `my/foucs-mode'.")))) (if (fboundp 'derived-mode-set-parent) (derived-mode-set-parent 'my/foucs-mode 'nil) (put 'my/foucs-mode 'derived-mode-parent 'nil)) nil (defun my/foucs-mode nil "Major-mode.\nUses keymap `my/foucs-mode-map', abbrev table\n`my/foucs-mode-abbrev-table' and syntax-table\n`my/foucs-mode-syntax-table'.\n\nThis mode runs the hook `my/foucs-mode-hook', as the final or\npenultimate step during initialization.\n\n\\{my/foucs-mode-map}" (interactive) (delay-mode-hooks (kill-all-local-variables) (setq major-mode 'my/foucs-mode) (setq mode-name "My Focus") nil (use-local-map my/foucs-mode-map) (set-syntax-table my/foucs-mode-syntax-table) (setq local-abbrev-table my/foucs-mode-abbrev-table)) (run-mode-hooks 'my/foucs-mode-hook)))这段内容看起来比 define-minor-mode 生成的要简短一些。我们还是来看看它每一步都做了什么:首先定义并文档化了一系列的变量: hook、mode—keymap、syntax-table、abbrev-table通过 derived-mode-set-parent 记录mode间继承的父子关系定义了一个对应的 mode 函数请注意,这个函数与 minor mode 不同,它并不是一个切换的函数,也没有定义记录 mode 开启或者关闭的标志变量。这是因为Major Mode 本身在设计时就不支持随意的关闭或者开启。从设计上,每个buffer 必须有一个,但是最多只能有一个 Major Mode, Major Mode 是不支持随意开关的,如果想要替换Major Mode,它是强制清空上一个Major Mode 的所有设置并加载新的。所以每次调用这个mode函数实质上是强行占领了之前mode 的位置。有了这个前提,我们再来看看这个函数具体的操作。函数所有的代码都被包裹在 delay-mode-hooks 宏中,这个宏可以保证里面的所有代码在hook之前运行。通过 kill-all-local-variables 清理当前buffer的所有 buffer local 变量记录当前 major mode 到变量 major-mode 中设置变量 mode-name 为我们传入的mode 的use-local-map 来给mode安装快捷键映射set-syntax-table 和 local-abbrev-table 设置当前的 syntax table 和 abbrev table最后才运行对应的hook总结从这里我们看到,设计上 major mode 一个buffer 有且只有一个,所以在设计上就比较简单粗暴,它不考虑多个mode并存或者切换的场景,它简单的清理前任留下来的东西,直接加入自己的。所以它的代码比minor mode 要简单的多。但是它涉及到的概念可一点也不比 minor mode 少,除了hook、keymap 这些我们经常见到的内容,还有 syntax table、abbrev table和继承这类概念。这些我会在后面的文章中一一介绍
2026年09月16日
0 阅读
0 评论
0 点赞