Emacs: 缩写模式(abbrev-mode)

本文介绍在Emacs中,如何使用内置的缩写模式来定义“缩写”,以实现快速而强大的文本扩展。

不需要按TAB, 只需要输入简短字符后接一个空格。

实现

This is a test: a global abbrev for demo puposes, 23:14:18 , Hello Jasper , 🦄 

abbrev-mode 基本使用

;;;; 缩写模式基础使用

(define-abbrev global-abbrev-table "metest" "a global abbrev for demo puposes") ; 定义全局缩写
(define-abbrev text-mode-abbrev-table "metest" "text-mode abbrev expansion here") ; 定义text-mode缩写
(define-abbrev org-mode-abbrev-table "metest" "org-mode abbrev") ; 定义org-mode缩写

;; metest global-abbrev-table
a global abbrev for demo puposes
;; metest text-mode
text-mode abbrev expansion here
;; metext org-mode
org-mode abbrev 

abbrev-mode 如何开启,

它是本地缓存, 使用继承来引用abbrev-mode

;;;; `abbrev-mode' is buffer-local
;; 因为是abbre-mode是本地缓存,它只会在你配置文件中生效
(abbrev-mode 1) ; 这样配置是错误的

;; 真正想要配置它,要将其设置为major-mode主模式
;; Parent modes: `prog-mode' (programming), `text-mode' (prose)
;; 方法1 添加钩子
(add-hook 'text-mode-hook 'abbrev-mode)

交互式缩写

;;; 缩写插入当前时间
(defun my-current-time ()
  (insert (format-time-string "%T")))

(my-current-time)   ;C-x C-e 21:29:29

(define-abbrev global-abbrev-table "medyn" "" 'my-current-time) ; medyna 扩展为空,同时引用钩子函数my-current-time

;; medyn
21:32:30 

;;; 交互式缩写插入字符
;; 交互式函数
(defun my-greet-person (name)
  (interactive (list (read-string "Greet person: ")))
  (insert (format "Hello %s" name)))

(my-greet-person "Ja") ; C-x C-e Hello Ja
;; M-x my-greet-person 回车输入字符 Jasper
Hello Jasper

;; 适合缩写的交互式函数, 在缩写中没有调用参数
(defun my-greet-person ()
  (interactive)
  (insert (format "Hello %s" (read-string "Greet persion: "))))

(define-abbrev global-abbrev-table "mehi" "" 'my-greet-person)
;; mehi 输入字符串Jasper
Hello Jasper 

插入表情符号

默认情况下,table表中内容仅被视为 abev ,是由什么字符组成。

(define-abbrev global-abbrev-table ":uni" "🦄")

;; :uni 什么也不会发声,因为表情符号不是词组
;; hello :uni uni  在单词后使用M-b我们可以发现光标停留在:冒号后,
;; 冒号不被识别为单词成分,所以会跳过它

;;; 必须设置缩写的属性才行
;; 在帮助手册中描述 (info "(elisp) Abbrev Table Properties")
;; 正则匹配缩写 和 词组在哪结束
(abbrev-table-put global-abbrev-table :regexp "\\(?:^\\|[\t\s]+\\)\\(?1:[:_].*\\|.*\\)")

test
:test
_test

 test
 :test 
 _test

;; M-x re-builder 正则查看"\\(?:^\\|[\t\s]+\\)\\(?1:[:_].*\\|.*\\)" 匹配的内容

;; :uni
🦄

;;; 组合 This is a test: metest, medyn, mehi , :uni
This is a test: a global abbrev for demo puposes, 23:14:18 , Hello Jasper , 🦄 

完整内容

;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with ‘C-x C-f’ and enter text in its buffer.

;;;; 缩写模式基础使用

(define-abbrev global-abbrev-table "metest" "a global abbrev for demo puposes") ; 定义全局缩写
(define-abbrev text-mode-abbrev-table "metest" "text-mode abbrev expansion here") ; 定义text-mode缩写
(define-abbrev org-mode-abbrev-table "metest" "org-mode abbrev") ; 定义org-mode缩写

;; metest global-abbrev-table
a global abbrev for demo puposes
;; metest text-mode
text-mode abbrev expansion here
;; metext org-mode
org-mode abbrev 

;;;; `abbrev-mode' is buffer-local
;; 因为是abbre-mode是本地缓存,它只会在你配置文件中生效
(abbrev-mode 1) ; 这样配置是错误的

;; 真正想要配置它,要将其设置为major-mode主模式
;; Parent modes: `prog-mode' (programming), `text-mode' (prose)
;; 方法1 添加钩子
(add-hook 'text-mode-hook 'abbrev-mode)

;;;; 交互式缩写
;;; 缩写插入当前时间
(defun my-current-time ()
  (insert (format-time-string "%T")))

(my-current-time)   ;C-x C-e 21:29:29

(define-abbrev global-abbrev-table "medyn" "" 'my-current-time) ; medyna 扩展为空,同时引用钩子函数my-current-time

;; medyn
21:32:30 

;;; 交互式缩写插入字符
;; 交互式函数
(defun my-greet-person (name)
  (interactive (list (read-string "Greet person: ")))
  (insert (format "Hello %s" name)))

(my-greet-person "Ja") ; C-x C-e Hello Ja
;; M-x my-greet-person 回车输入字符 Jasper
Hello Jasper

;; 适合缩写的交互式函数, 在缩写中没有调用参数
(defun my-greet-person ()
  (interactive)
  (insert (format "Hello %s" (read-string "Greet persion: "))))

(define-abbrev global-abbrev-table "mehi" "" 'my-greet-person)
;; mehi 输入字符串Jasper
Hello Jasper 

;;;; 插入表情符号 
(define-abbrev global-abbrev-table ":uni" "🦄")

;; :uni 什么也不会发声,因为表情符号不是词组
;; hello :uni uni  在单词后使用M-b我们可以发现光标停留在:冒号后,
;; 冒号不被识别为单词成分,所以会跳过它

;;; 必须设置缩写的属性才行
;; 在帮助手册中描述 (info "(elisp) Abbrev Table Properties")
;; 正则匹配缩写 和 词组在哪结束
(abbrev-table-put global-abbrev-table :regexp "\\(?:^\\|[\t\s]+\\)\\(?1:[:_].*\\|.*\\)")

test
:test
_test

 test
 :test 
 _test

;; M-x re-builder 正则查看"\\(?:^\\|[\t\s]+\\)\\(?1:[:_].*\\|.*\\)" 匹配的内容

;; :uni
🦄

;;; 组合 This is a test: metest, medyn, mehi , :uni
This is a test: a global abbrev for demo puposes, 23:14:18 , Hello Jasper , 🦄