Snippets vim 使用
Snippets 就是一些代码模板,能用通过输入特定的关键词和热键(一般设定为Tab)来触发。它可以节省很多的时间,因为有些代码在编写过程中都是重复的。Vim 本身不支持Snippet功能,我现在使用UltiSnips并且把它和YouCompleteMe结合来使用,当然还有别的引擎和可以完成类似功能,如SnipMate, Neosnippet, Xptemplate
安装
使用v-plug来管理vim插件
在 ~/.vimrc中加入
Plug 'SirVer/ultisnips'
Plug 'honza/vim-snippets'
执行 : PlugInstall 安装两个插件,设置快捷键
let g:UltiSnipsExpandTrigger=""
let g:UltiSnipsJumpForwardTrigger=""
let g:UltiSnipsJumpBackwardTrigger=""
vim-snippets 介绍
vim-snippets 是在github上的一个包含了各种各样编程语言代码snippets文件的仓库。它是由社区维护的
其中: snippets/* 文件夹中的snippets是使用snipMate格式,UltiSnips/*是UltiSnips格式的
这时在vim-snippets中提供的snippets模板都可以使用了,当然你也可以自定义snippets更好的适应个人的编程习惯。
自定制snippet
snippet 加载方式
UltiSnips 中加载snippets文件方式是在相应的文件夹中找snippets文件,其中相应的文件夹是有两个参数来决定的
- g:UltiSnipsSnippetDirectories 配置搜索snippets文件的文件夹
- g:UltiSnipsSnippetsDir 定义自己的snippets文件放置的位置
比如你将你的snippets文件放在~/.vim/mycoolsnippets中,这时你的g:UltiSnipsSnippetDirectories配置应该是
let g:UltiSnipsSnippetDirectories=["UltiSnips", "mycoolsnippets"]
snippets 文件对应文件类型
snippets文件与文件类型的对应是通过文件的命名来完成的。
如果一个当前文档类型是ft,那么ft.snippets,ft_.snippets,ft/都会被使用,下面是具体例子
snippet filename | filetype |
---|---|
ruby.snippets | ruby |
perl.snippets | perl |
c.snippets | c |
c_my.snippets | c |
c/a | c |
c/b.snippets | c |
all.snippets | all |
all/a.snippets | all |
基本语法
使用#来注释
extends 关键字来组合snippet文件,比如在cpp.snippets第一行加入
```
extends c
```
那么在UltiSnipes激活cpp类型snippets文件的时候,会同时搜索c类型的snippets并激活
priority 关键字 来定义当前特性的权重
一行以snnipet开始来表示snippet代码的开始,一行以endsnippet开始来标记结束,snippet 代码就是在两行之间下面是一个Unix中sh文件类型的if语句的snippet
```
snippet if "if ... then (if)"
if ${2:[[ ${1:condition} ]]}; then
${0:#statements}
fi
endsnippet
```
第一行的采用下面的书写格式:
snippet triigger_word [ "description" [options]]
触发的单词(triigger_word),是必须的参数,描述(description)和 选项(options) 是可选的参数
triigger_word 是用来触发代码块的单词或字符串表达式,通常来讲是一个单词但是如果你想包含空格,可以使用引号来包裹,例如
snnippet "tab trigger"
description 是描述该snippet的作用,用来和别的相同的名称(triigger_word)作区分
选项
options 来控制snippet的表现,是一些单个字符的组合使用
- b Beginning of line 若果代码块中有这个选项,只有在触发关键字是改行第一个单词的情况下触发。换句话说,在该触发词之前只有空格。默认是在任何位置都能触发的。
- i In-word expansion 字内扩展 - 默认情况下,片段在该行第一个单词或者前面是一个或多个空格是触发。一个含有此选项snippet,会忽略前面的字母。换句话说,snippet可以再单词中间触发,会忽略前面的字母。换句话说,snippet可以再单词中间触发。
- w Word boundry 使用此选项,片段会在触发关键字匹匹配特定单词开头边界,和匹配特定单词结束边界是展开。换言之,触发关键字的前面和后面必须是分单词字符。单词字符是有‘iskeyword’设置的。
- r Reggular expression 触发关键字是python正则表达式。必须用引号包裹(或其他字符)
- t Do not expand tabs 忽略片段中的tab字符,默认情况下,代码片段在插入的时候回根据vim现有的关于tab的设置对代码片段中含有的tag字符进行正确的配置。如果含有次选项,snippet会忽略代码中的tab字符,原样添加
- s 在跳转下一个tab停止位时,删除在行尾出光标前的空白字符。
- m 删除代码片段右侧的空格
- e 自定义代码上下文
- A 代码片段会自动触发
结束行只有一个 ‘endsnippet’关键字
转义字符
在代码片段定义中,‘`’,'{','$'和'\'有特殊意义,如果想插入需要用‘\’进行转义
普通文本片段
创建 ‘~/.vim/UltiSnips/all.snippets’,文件,添加如下snippet代码
snippet bye "My mail signature"
Good bye, Sir. Hope to talk to you soon.
- Arthur, King of Britain
endsnippet
UltiSnips 会检测到你在写入一个.snippets文件,所有的变化会被激活。这是你在某个文件中输入‘bye’,按下tab键,‘bye’就会被代码替代。
观察模式替换
在Snippets中包含一个特殊的替换字符 ${VISUAl}。用来替换选中的文字。
在观察模式下选中一些文字,按下触发(g:UltiSnipsExpandTrigger)键,这是选中的文字会被删除,进入插入模式,输入触发关键字,触发代码模版,这时就能看到选择的文字在里面.
snippet t
${VISUAl: inside text/should/is/g}
endsnippet
在文件中写入
this should be coo
在观察模式选中 should,输入tab,然后输入t,tab,结果:
this is be coo
如果直接在输入模式下,t,tab 结果:
inside text
插值法
shell代码
Snippets中可以包含shell代码,插入的语法很简单, 将代码包含在反引号中‘`’,UltiSnips执行shell脚本是先创建一个临时脚本然后执行改脚本.shell代码将会被标准输出替代,所有shell代码语法都支持。比如,释伴行, !/usr/bin/perl,这样就可以用来使用perl程序了
例子,插入当前日期:
snippet today
Today is the `date +%d.%m.%y`.
endsnippet
结果:
Today is the 15.07.09.
vim脚本
你也可以使用Vim 脚本(通常称为Viml)。语法类似于shell脚本, 为了作区分在代码前加'!v'。
python
pythonr 插入到目前为止是最强大的。语法类似于Vim脚本,代码前是'!p'。
下面的变量会自动在puthon代码中创建
- fn 当前文件名
- path 当前文件完整路径
- t 替换的值,t[1] 就是 ${1}的文本
- snip UltiSnips.TextObjects. SnippetsUtil 对象实例.
- context 上下文环境结果
- match 只有在正则模式下。 返回正则匹配的结果
'snip' 对象提供了一下方法
- snip.mkline(line="",indent=None) 返回已准备号放入结果的行。
- snip.shift(amount=1) 被mkline用来在右侧升级默认的缩进等级,通过‘amout’倍数'shiftwidth'
- snip.unshift(amount=1) 被mkline用来在左侧升级默认的缩进等级,通过‘amout’倍数'shiftwidth'
- snip.reset_indet 重设缩进
- snip.opt(va,default) 查询变量var是否已经有值,如果有值那么返回,没有值返回default
'snip' 还提供了一些属性
- snip.rv 设置返回值,替代片段定义时的python块
- snip.c 当前文本的位置,在出入完成后会被设置成空,可以做非空校验,保证代码只执行一次
- snip.v 和${VISUAL}替换相关的属性 包含该snip.v.mode 模式(v,V,^V) snip.v.text 选中的文本
- snip.fn 文件名
- snip.basename 不包含扩展名的文件名
- snip.ft 文件类型
- snip.p 最后选择的替换内容.
例子: 下面的代码会克隆第一个tabstop但是会在右边以大写字母展示
snippet wow
${1:Text}`!p snip.rv = (75-2*len(t[1]))*' '+t[1].upper()`
endsnippet
结果:
Hello World HELLO WORLD
全局 Snippets
全局Snippets是一种重复使用代码的一种方式。只有python支持,使用关键字‘global’创建。
这些重复使用的代码可以放在一个外部一个python模块中,然后被引入。通过这种方式我们可以很方便的将全局的方法放入'~/.vim/pythonx’中,例如可以命名为'my_snippets_helper.py’
tabstop(触发中继) 和 placeholders
Snipts 是用来快速想文档中插入重复使用的文本。一般该文本会由不同的部分组成固定的结构。Tabstops(触发中继)用来简化变化部分的修改。通过Tanstop你可以很容易的在变化的内容上放置光标,进入内容输入,或者调到下一个输入内容处,知道所有内容输入完成。
tabstop的语法是一个'0’是一个特殊字符,它总是代表了最后一个tabstop,无论有多少tabstop被定义,如果没有定义‘0'
下面是个例子
snippet letter
Dear $1,
$0
Yours sincerely,
$2
endsnippet
输入:
letter
结果:
Dear Ben,
Thanks for suggesting UltiSnips!
Yours sincerely,
Paul
一般来说给tabstop设置默认值会很好有用。语法是‘${1:value}’
下面的代码是shell脚本中‘case’语句的代码片段
snippet case
case ${1:word} in
${2:pattern} ) $0;;
esac
endsnippet
输入
case$option-vverbose=true
输出:
case$option-vverbose=true
case $option in
-v ) verbose=true;;
esac
有的时候嵌套的tabstop也会很有帮助吗,可以正常写入嵌套的tabstop代码。
镜像
竟像是tabstop的重复。
参考链接
- vim-snippets
- UltiSnips