文本模式或许是除基本模式外最简单的模式。以下摘自 text-mode.el 的代码片段展示了上述诸多规范的用法:
;; 为此模式创建语法表。
(defvar text-mode-syntax-table
(let ((st (make-syntax-table)))
(modify-syntax-entry ?\" ". " st)
(modify-syntax-entry ?\\ ". " st)
;; Add 'p' so M-c on 'hello' leads to 'Hello', not 'hello'.
(modify-syntax-entry ?' "w p" st)
...
st)
"Syntax table used while in `text-mode'.")
以下是实际模式命令的定义方式:
(define-derived-mode text-mode nil "Text"
"用于编辑人类可读文本的主模式。
该模式中,段落仅以空行或空白行分隔。
因此可充分使用自适应填充功能
(参见变量 `adaptive-fill-mode')。
\\{text-mode-map}
启用文本模式时会运行通用钩子 `text-mode-hook'。"
(setq-local require-final-newline mode-require-final-newline))
三种 Lisp 模式(Lisp 模式、Emacs Lisp 模式、Lisp 交互模式)相比文本模式功能更多,代码也相应更复杂。以下摘自 lisp-mode.el 的片段展示了这类模式的实现方式。
以下为 Lisp 模式语法表与缩写表的定义:
;; 创建模式专用的表变量。
(define-abbrev-table 'lisp-mode-abbrev-table ()
"Abbrev table for Lisp mode.")
(defvar lisp-mode-syntax-table
(let ((table (make-syntax-table lisp--mode-syntax-table)))
(modify-syntax-entry ?\[ "_ " table)
(modify-syntax-entry ?\] "_ " table)
(modify-syntax-entry ?# "' 14" table)
(modify-syntax-entry ?| "\" 23bn" table)
table)
"Syntax table used in `lisp-mode'.")
三种 Lisp 相关模式共用大量代码。例如,Lisp 模式与 Emacs Lisp 模式继承自 Lisp 数据模式,而 Lisp 交互模式继承自 Emacs Lisp 模式。
Lisp 数据模式会设置 comment-start 变量以处理 Lisp 注释:
(setq-local comment-start ";") ...
不同 Lisp 模式的按键映射略有差异。例如,Lisp 模式将 C-c C-z 绑定到 run-lisp,而其他 Lisp 模式则没有该绑定。不过所有 Lisp 模式共用部分命令,以下代码设置了这些共用命令:
(defvar-keymap lisp-mode-shared-map :parent prog-mode-map :doc "各类 Lisp 模式共用命令的按键映射。" "C-M-q" #'indent-sexp "DEL" #'backward-delete-char-untabify)
以下为 Lisp 模式的按键映射设置代码:
(defvar-keymap lisp-mode-map :doc "普通 Lisp 模式的按键映射。 本映射继承 `lisp-mode-shared-map' 中的所有命令。" :parent lisp-mode-shared-map "C-M-x" #'lisp-eval-defun "C-c C-z" #'run-lisp)
最后是 Lisp 模式的主模式命令定义:
(define-derived-mode lisp-mode lisp-data-mode "Lisp"
"用于编辑非 GNU Emacs Lisp 的其他 Lisp 代码的主模式。
常用命令:
删除操作回退时会将制表符转换为空格。
空行分隔段落。分号开头为注释。
\\{lisp-mode-map}
`run-lisp' 既可用于启动下级 Lisp 进程,
也可切换回已存在的 Lisp 进程。"
(setq-local find-tag-default-function 'lisp-find-tag-default)
(setq-local comment-start-skip
"\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
(setq imenu-case-fold-search t))