在Spacemacs中为Yasnippet添加自定义snippet
Table of Contents
Yasnippet能够将少量的输入内容扩展为一个代码模板从而节省时间. YASnippet包含了大量特定mode下的snippets,它能将这些snippet扩展为任何东西,从简单的替换为另一段文本到一段允许你在各参数间遍历的代码块. 在这个视频中可以看到Yasnippet的演示.
要使用某个snippet很简单,只需要输入缩写然后按下 M-/
就行了. 比如,在html-mode下输入 div
然后按下 M-/
就会扩展为 <div id="▮" class="▯">▯</div>
. 并且光标放在让你输入id值的位置上,你再按一下 TAB
键就又会跳转到输入class值的位置,最后再按一下 TAB
会跳转到输入 div
内容的位置.
你也可以将yasnippet与自动补全功能整合起来,从自动补全菜单中选择想要的snippet.
Spacemacs对于它支持的语言大多内置了大量的snippets. 而且,YASnippets的模板系统也很容易学习. 下面就让我们看看在Spacemacs中如何自定义snippet吧.
一般来说,yasnippets扩展函数的快捷键是TAB,但是该快捷键在Spacemacs被其他功能占用了,因此使用M-/代替该快捷键. 如果你想要的仅仅是纯粹的替换一段文本,你可以试试 Emacs Abbrev mode.
1 Adding your private snippets to Spacemacs
你可以将你自己的snippet定义文件放到 ~/.emacs.d/private/snippets
目录下. 具体来说,你需要在该目录下创建一个与相关mode同名的文件夹(比如markdown-mode). 在这个文件夹中再以缩写为名创建snippet定义文件.
例如,若我要为markdown-mode定义一个缩写为wip的snippet,则我要创建的文件为 ~/.emacs.d/private/snippets/markdown-mode/wip
.
要使新snippet生效,你可以重启Spacemacs或者在snippet文件的buffer中运行 M-x yas-load-snippet-buffer
. 随后该snippet就会在所有的markdown-mode buffer中生效了.
1.1 Managing your snippets
虽然可以把自定义的snippet放在private snippets目录中,但该目录并没有纳入版本控制. 因此你不用担心自定义的snippet会被Spacemacs所覆盖,但也意味着这些snippets也不会被备份起来.
若你将自定义snippet放在 ~/.spacemacs.d/snippets/modename-mode/
这样的目录下,则你就可以使用Git或类似的版本控制工具将之管理起来了.
2 How to write a snippet
一般来说,每个snippet模板都存放在各自的文件中,且文件名与缩写一致. 因此一个缩写为 wip
的snippet定义在名为 wip
的文件中, 且该文件存放在以相关Emacs mode为名的目录中.
一个snippet模板的基本架构如下:
#key : the name of the snippet you type #name : A description of the snippet (this shows in autocompletion menu too) #contributor: John Stevenson <john@jr0cket.co.uk> # -- Add the content you want to replace the snippet name with when it expands
其中的内容可以是简单的一段文本,也可以是一段包含占位符的代码结构,扩展后每次按下tab就会把光标跳转到下一个占位符的位置. 你甚至还可以在模板中使用Elisp代码.
2.1 Example: Simple text replacement
我经常要用markdown mode来写东西. 当我写markdown时经常要凸出显示还有哪些章节是尚未完成的. 因此我创建了一个名为 wip
的snippet来帮我输入这段常用的信息.
#key : wip #name : WorkInProgress #contributor: John Stevenson <john@jr0cket.co.uk> # -- > **Fixme** work in progress
当你用 M-/
扩展这段snippet时,snippet的名字就会替代为它的内容了.
2.2 Example: Using tab stops
html-mode下有一个名为form的snippet,让我们来看一下这个snippet. 该snippet会扩展为一个html form,同时允许你在method,id,action和content属性之间跳转.
#contributor : Jimmy Wu <frozenthrone88@gmail.com> #name :<form method="..." id="..." action="..."></form> # -- <form method="$1" id="$2" action="$3"> $0 </form>
这个snippet与上面那个简单的例子类似,不同之处在于它用$符和数字设置了占位符. 当扩展上面那个snippet时,snippet的名字也会被它的内容所替代,但不仅如此,光标也会放置在第一个定位符$1处. 每次你按下TAB键就会把光标移动到下一个定位符处.
$0表示snippet的退出点,在这个地方按下TAB键的作用与在YASnippet外的作用一致.
3 Creating a snippet from existing text
创建新snippet的最快的方法莫过于直接利用snippet扩展后的内容了.
若只是为了简单的文本替换,则你只需要选中扩展后的文本,然后调用 helm-yas-create-snippet-on-region
, 保存自动生成的snippet为缩写名称就行了.
若需要创建带定位符的代码结构,则需要选中扩展后的代码结构,调用 helm-yas-create-snippet-on-region
, 然后编辑snippet,用$1,$2,$3,$4之类的定位符替代里面的内容就好.
3.1 Example: Create a simple text replacement
当我写博客时,我会用一个图片缩略图来指示文章的顶部. 我不想每次都手工录入这一段,因此我创建了一个snippet.
首先我选中新snippet要扩展成的内容,在本例中就是 {% img img-thumbnail /images/spacemacs.png %}
.
然后我调用函数 helm-yas-create-snippet-on-region
. 它会提示我输入该snippet所属的mode是那个,这里我输入 markdown-mode
, 然后会提示输入该snippet文件存放的位置,输入 ~/.emacs/private/snippets/markdown-mode/imgtmb-spacemacs
. 然后就会有一个新的buffer创建出来了,且snippet的内容已经填好了.
# -*- mode: snippet -*- #name : imgtmb-spacemacs #key : imgtmb-spacemacs #contributor : jr0cket # -- {% img img-thumbnail /images/spacemacs.png %}
这个新产生的snippet buffer中的name和key的值自动被设置为该snippet的文件名: imgtmb-spacemacs. snippet的主体内容也自动填充为我选择的文本了. 因此只需要保存这个snippet就行了.
4 Testing your snippets
写好snippet后,可以通过运行 M-x yas-tryout-snippet
来测试一下. 该命令会在合适的major mode下新开一个空白的buffer,你可以在这个buffer中输入缩写,然后按下 M-/
测试该snippet.
若你想在已有的buffer中试用一下该snippet,需要先用 M-x yas-load-snippet-buffer
加载该snippet并关闭关闭该snippet buffer(必要时会提示保存该buffer).
这些命令在Spacemacs中没有预设快捷键,不过你可以手工为它们设置快捷键. 这种快捷键一般以
C-o
为前缀,例如设置C-o C-s
来测试snippet,C-o C-s
来加载snippet.
5 Adding yas-snippets to autocompletion in Spacemacs
在Spacemacs中启用autocompletion layer后,就能在自动补全菜单中显示YASnippets的内容了.
不过默认情况下,auto-completion是不会将snippet作为补全项的,你需要设置 auto-completion-enable-snippets-in-popup
为 t
.
(setq-default dotspacemacs-configuration-layers '((auto-completion :variables auto-completion-enable-snippets-in-popup t)))
6 Summary
想了解更多YASnippets与autocompletion的话,请查看Github repository for Spacemacs autocompletion layer.
想了解更多如何编写自定义的snipplet,参见下面这些链接: