在emacs 中快速对区域进行符号包裹的简洁方案(类似vim-surround)
1 前言
写代码或者是一些富文本文件时, 经常会遇到这样的场景: 已经写好了一串代码或者文字, 想要方便地给这些东西加上一个符号包括起来, 例如对一个条件判断语句 a==b
加上括号变成 (a==b)
, 或者对一段markdown 或 org 文件加上标记. 如果每次都需要手动在开始和结尾的地方加上左括号和右括号, 无疑非常麻烦.
2 常见方案
vim 给出了 vim-surround 方案, 功能强大但按键稍微繁琐. emacs 的实现方案非常多, 右 paredit, smartparents, parinfer, awesome-pair 等, 它们的功能强大提供了多种对于s-exp 的操作, wrap pair 只是其中的一个非常小的功能, 前两个似乎还存在一些性能问题.
这些包都比较重且我们使用的功能相对较少, 无疑会增大学习成本和个人配置的维护压力. 因此我把目光转向了 emacs 的内置方案.
3 内置方案与修改
emacs 中有一个 insert-parentheses
的函数, 默认绑定在 "M-("
按键, 可以在一段选定的文字附近添加 “(” 和 “)”, 看起来已经满足我们的部分需求了. 文档如下:
(defun insert-parentheses (&optional arg)
"Enclose following ARG sexps in parentheses.
Leave point after open-paren.
A negative ARG encloses the preceding ARG sexps instead.
No argument is equivalent to zero: just insert `()' and leave point between.
If `parens-require-spaces' is non-nil, this command also inserts a space
before and after, depending on the surrounding characters.
If region is active, insert enclosing characters at region boundaries.
This command assumes point is not in a string or comment."
(interactive "P")
(insert-pair arg ?\( ?\)))
仅有一个对于小括号的补全当然不能满足我们的需求, 可以发现, 这个函数的关键在于对 insert-pair
传递的第三和第四个函数, insert-pair
的代码实现较为复杂, 我们这里不多展开,
模仿 insert-parentheses
简单修改便得到如下的函数, 分别对应
' '
, " "
, ` '
, * *
, [ ]
, { }
等情况.
(defun insert-quotations (&optional arg)
"Enclose following ARG sexps in quotation marks.
Leave point after open-paren."
(interactive "*P")
(insert-pair arg ?\' ?\'))
(defun insert-quotes (&optional arg)
"Enclose following ARG sexps in quotes.
Leave point after open-quote."
(interactive "*P")
(insert-pair arg ?\" ?\"))
(defun insert-backquote (&optional arg)
"Enclose following ARG sexps in quotations with backquote.
Leave point after open-quotation."
(interactive "*P")
(insert-pair arg ?\` ?\'))
(defun insert-star (&optional arg)
"Enclose following ARG sexps in stars.
Leave point after open-quotation."
(interactive "*P")
(insert-pair arg ?\* ?\*))
(defun insert-bracket (&optional arg)
"Enclose following ARG sexps in brackets.
Leave point after open-quotation."
(interactive "*P")
(insert-pair arg ?\[ ?\]))
(defun insert-curly (&optional arg)
"Enclose following ARG sexps in curly braces.
Leave point after open-quotation."
(interactive "*P")
(insert-pair arg ?\{ ?\}))
(defun insert-equate (&optional arg)
"Enclose following ARG sexps in equations.
Leave point after open-quotation."
(interactive "*P")
(insert-pair arg ?\= ?\=))
然后将这些函数分别绑定到自己喜欢的按键就可以使用了. 当然, 还可以根据需要对上面的函数添加更复杂的符号, 比如 html 的相关标记等. emacs 内置功能简单而强大.