24.2.9 主模式示例

文本模式或许是除基本模式外最简单的模式。以下摘自 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))

emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike