abbrew
abbrev 是 abbreviation 的缩写。这个模块的主要功能也是定义宏,并在文档 中把宏展开。总的来说,abbrev 提供了缩写展开功能,对于输入频次比较高的 文本可以减少输入工作。
abbrew 定义
abbrev 的定义使用 C-x a 作为快捷键前缀,或者说凡是和 abbrev 有关的功能 大多使用这个前缀。
-
C-x a g (add-global-abbrev)可以将光标位置前面的词加入全局 abbrev table 中,并提示你输入这个词对应的缩写。若要加入当前 buffer 对应 major mode 的 abbrev table 的话,可以使用
-
C-x a l (add-mode-abbrev),它只对该 mode 生效。
-
C-x a i g (inverse-add-global-abbrev)全局模式
-
C-x a i l (inverse-add-mode-abbrev)读取光标前的词作为缩写词,而要 求用户你输入展开结果。
-
C-u - C-x a g 或C-u - C-x a l 要删除某个 abbrev
除了绑定在快捷键上的这些函数,通过使用 define-global-abbrev 和 define-mode-abbrev 命令,我们也可以定义相应的 abbrev。要修改某个已定 义的 abbrev 的话,使用新的定义将它覆盖就可以了。
abbrew 展开
如果我们不想让 abbrev 展开,我们可以在输入 abbrev 后按下 C-q 来告诉 abbrev-mode 不进行展开。
一只常见的情况谁忘记了定义的abbrev,可以通过list-abbrevs命令来 查看所 有的定义。
如果不小心展开了某个 abbrev,你可以使用 Undo 来撤销展开,它会使你 回到展开前的状态。你也可是使用 unexpand-abbrev 来进行撤销操作。
如果没有打开 abbrev-mode 的,可以使用 C-x a e (expand-abbrev)来进 行展开。它的行为与 abbrev-mode 有效与否无关。
配置示例
abbrev的默认配置一般在.emacs.d/abbrev_defs文件中.里面的配置是自动保存 的,只能存一些简单的定义,稍微复杂一点的定义,需要定义。 以下是我的配置,配合skeleton使用:
(provide 'myabbrev)
(add-hook 'org-mode-hook (lambda () (abbrev-mode t)))
;; abbev and skeleton
(define-skeleton skel-org-block
"Insert an org block, querying for type."
"Type: "
"#+begin_" str "\n"
_ - \n
"#+end_" str "\n")
(define-abbrev org-mode-abbrev-table "sblk" "" 'skel-org-block)
(define-skeleton skel-org-block-ditaa
"Insert a org ditaa block, querying for filename."
"File (no extension): "
"#+begin_src ditaa :file " str ".png :cache yes\n"
_ - \n
"#+end_src\n")
(define-abbrev org-mode-abbrev-table "sditaa" "" 'skel-org-block-ditaa)
(define-skeleton skel-org-beamer
"Insert an org block, querying for type."
"Type: "
"# -*- mode: snippet -*-\n"
"#+TITLE: " str \n
"#+AUTHOR: xxx \n"
"#+EMAIL: xxxx@xxx.com \n"
"#+DESCRIPTION: \n"
"#+KEYWORDS: \n"
"#+OPTIONS: H:2 num:t toc:t \\n:nil @:t ::t |:t ^:{} -:t f:t *:t <:t\n"
"#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc\n"
"#+EXPORT_SELECT_TAGS: export\n"
"#+EXPORT_EXCLUDE_TAGS: noexport\n"
"#+startup: beamer\n"
"#+LaTeX_CLASS: beamer\n"
"#+LaTeX_CLASS_OPTIONS: [bigger]\n"
"#+columns: %45ITEM %10BEAMER_env(Env) %10BEAMER_act(Act)%4BEAMER_col(Col) %8BEAMER_opt(Opt)\n"
@ _)
(define-abbrev org-mode-abbrev-table "beamh" "" 'skel-org-beamer)
(define-skeleton skel-defun
"Insert a defun template."
"Name: "
"(defun " str " (" @ - ")" \n
"(" @ _ ")" \n)
(define-abbrev org-mode-abbrev-table "defun" "" 'skel-defun)
(define-abbrev org-mode-abbrev-table "footz" "#+attr_latex: :font \\footnotesize" "")
(define-skeleton read-two-vars
"Prompt the user for two variables, and use them in a skeleton."
""
> "variable A is " (setq v1 (skeleton-read "Variable A? ")) \n
> "variable B is " (setq v2 (skeleton-read "Variable B? ")) \n
> "A: " v1 " B: " v2 \n)
(define-abbrev org-mode-abbrev-table "twov" "" 'read-two-vars)
(define-skeleton skel-org-orgh
"Insert a org head."
"Name: "
"#+TITLE:" str \n
"#+OPTIONS: author:nil ^:{}")
(define-abbrev org-mode-abbrev-table "orgh" "" 'skel-org-orgh)
(define-skeleton skel-org-picv
"Insert a hugo head."
"Name: "
"#+CAPTION: " (setq v1 (skeleton-read "caption? ")) \n
"#+ATTR_HTML: :title " v1 " :align "(skeleton-read "centre/right/left? ")\n
"#+ATTR_HTML: :width "(setq v2 (skeleton-read "width %? "))"%" " :height "v2"%\n")
(define-abbrev org-mode-abbrev-table "pich" "" 'skel-org-picv)
动态 abbrev
除了说主动定义 abbrev 后再使用外,我们还可以使用所谓的动态 abbrev,它 不使用定义的 abbrev,而是从 buffer 中找到符合展开的词来进行展开。它不 会主动触发,需要你主动使用它。
举例来说的话,当你输入了 “does this follow”,然后输入 “fo”,在按下 M-/ (dabbrev-expand)后会插入 “follow” 来作为 “fo” 的展开结果。这是因为 “follow” 是 buffer 中从头到当前位置离 “fo” 最近的,且以 “fo” 开头的词。 当你多次按下 M-/ 时,emacs 会从后往前找匹配的内容来作为展开结果。在找 完所有可能的结果后,它又会回到最初值。变量 dabbrev-limit 可用来指定从 后往前找的最远距离(也就是最多往前找几个)。对该命令使用数字参数的话, 就代表使用第参数个找到的内容来进行展开。
在找完当前的 buffer 后,继续使用 M-/ ,emacs 会在其他 buffer 中查找。 可用 dabbrev-check-all-buffers 和 dabbrev-check-other-buffers 来控制 emacs 是否查找其他 buffer。要控制 emacs 搜索其他 buffer 的行为,可以对 dabbrev-ignored-buffer-names 和 dabbrev-ignored-buffer-regexps 进行设 置,前者是要跳过的 buffer 名字组成的表,后者是要跳过的 buffer 的名字匹 配正则。如果 buffer 的名字符合两者之一,那么 emacs 会跳过该 buffer。
若使用负数作为 M-/ 的数字参数,那么 M-/ 会向下而非向上搜索,到达 buffer 末尾时再去其他 buffer 搜索,最后才考虑原 buffer 中向上的内容。
skeleton
skeleton的部分内容,参考了以下链接 https://www.emacswiki.org/emacs/SkeletonMode
简单定义
以下的例子,简单的输入一个定义事项
(define-skeleton hello-world-skeleton
"Write a greeting"
"Type name of user: "
"hello, " str "!")
默认值
(define-skeleton hello-world-skeleton
"Write a greeting"
"Type name of user: "
"hello, " str | "this is the default input!")
输入多个参数
可以定义多个入参输入,参考配置示例,也可以直接用skeleton-read读输入数据, 不记录。
(define-skeleton read-two-vars
"Prompt the user for two variables, and use them in a skeleton."
""
> "variable A is " (setq v1 (skeleton-read "Variable A? ")) \n
> "variable B is " (skeleton-read "Variable B? ") \n
> "A: " v1 " B: " v1 \n)
焦点移动
可以知道最后输入焦点的位置。
(define-skeleton skel-defun
"Insert a defun template."
"Name: "
"(defun " str " (" @ - ")" \n
"(" @ _ ")" \n)
焦点移动部分,还没太搞明白,暂时只知道可以最好停留在-的位置。