分享 Vim 插件:UltiSnips 让 Vim 飞起来

xiaoronglv · 2015年04月06日 · 最后由 posee 回复于 2018年10月07日 · 18979 次阅读

datetime

Sublime Text 中的代码块 (Snippets) 缩减了码字的过程,极大的提高编程效率,是非常方便的工具。当我把编辑器迁移到 Vim 后就开始寻觅一款适合自己的 Snippet 插件,以下是我折腾 Vim 代码块的经验总结。

初学 Vim,还有很多不懂的地方,若有纰漏,请及时指出。

Vim 比较流行的代码块引擎有 SnipMate 和 UltiSnips。目前越来越多的人选用 UltiSnips,它的优点有:

  • 可以在代码片段中中嵌入 python / vim / bash 代码,动态实现一些很酷功能 (后文有演示 demo)
  • 兼容 SnipMate
  • 支持正则
  • (据说) 响应速度更快,性能更好一些

UltiSnips 只是个引擎,需要搭配预设的代码块才能运转起来,以下是我创建的几个常用代码块。

# 当我在编辑器里输入 `test + tab`, 会自动补全以下代码
# test 'method name' do
#
# end

snippet "test" "test a method" r
$0
endsnippet


# 当我在编辑器里输入 `defs + tab`,会自动补全以下代码
# def self.method(*args)
#
# end

snippet "defs" "define a class method" r

def self.method${1:(${2:*args})}
  $0
end
endsnippet

在创建代码块的过程中我遇到很多问题,如 trigger 命名不合理,Tab 的跳转不高效等。我特别想借鉴别人撰写 snippet 的经验。这个世界上总是有一批又懒又聪明的程序员,我在 Github 中轻松搜到一个比较好的代码块合集,叫 honza/vim-snippets,几乎涵盖所有编程语言。

与其自己一个个创建代码块,不如先站在巨人的肩上,然后再慢慢折腾,于是乎我的折腾思路调整为

  1. 安装引擎 SirVer/ultisnips
  2. 安装代码块集合 honza/vim-snippets
  3. 添加自定义代码块,把优先级调高,覆盖掉 honza/vim-snippets 中不满意的代码片段。

step 1 安装 SirVer/ultisnips

使用 Vundle 管理 vim 插件,安装插件十分简便,在 .vimrc 中引入一行代码即可。

Plugin 'SirVer/ultisnips'

Step 2 安装代码块集合

Plugin 'honza/vim-snippets'

安装完后就可以在 Vim 中使用代码块了,以下是几个经常用到的代码片段 demo,是不是很酷?

  1. 插入当前日期 (trigger: date)

    date

  2. 插入当前时间 (trigger: datetime)

    datetime

  3. 插入一个大的注释框 (trigger: bbox)

    bbox

  4. 在 erb 中插入 if 语句

    ife

Step 3 创建自定义代码块

我们需要定制代码块来满足特殊需求,比如我希望在 rb 文件中输入 atc + tab 时可以快速的生成一个 ActiveSupport::Testcase,可以按照以下步骤实现这个功能。

3.1 在 ~/.vim 下创建文件夹,命名为 UltiSnips,用来存放自定义的代码块。

有的同学会直接修改 ~/.vim/bundle/vim-snippets 中的 snippets,建议不要这个干!因为这个目录是 Git 仓库,每次重装插件会丢失未提交的文件。

还是单独创建一个 UltiSnips 文件夹来保存自定义代码片段比较稳妥。

# UltiSnips 插件会自动加载这个文件夹下的文件
mkdir ~/.vim/UltiSnips

3.2 创建 ruby.snippets

touch ~/.vim/UltiSnips/ruby.snippets

代码块的文件命名是有讲究的,ruby.snippets 中定义的代码块只会在 rb 文件中生效;python.snippets 中定义的代码块只会在 py 文件中生效。

假如你想定义一个通用的代码块,在所有的文件类型中都能用,你可以把它定义在 all.snippets 中。

# ~/.vim/UltiSnips/ruby.snippets

snippet atc "test case of ActiveSupport::TestCase" !b
require 'test_helper'

class ${1:klass}Test < ActiveSupport::TestCase
   test '${2:case_name}' do
    ${0}
   end
end
endsnippet

atc

3.3 再举个 markdown 的例子

# when I type head + tab, I hope...
---
title: title
layout: post
guid: e1eff5aaf0db41198c0f4acfc5ba4a9c
date: 2015-04-02 21:45:31
tags:
  -
---

假如你用 jekyll 写博客,肯定对上面这段代码很熟。这是每篇博文头部的 head 信息 ,输入十分繁琐。

我特别希望在 markdown 文件中输入 head + tab 时可以自动生成博客的头部。自定义一个 markdown.snippets 就可解决这个问题。

# ~/.vim/UltiSnips/markdown.snippets

snippet head "Jekyll post header" b
---
title: ${1:title}
layout: post
guid: `!p
import uuid
if not snip.c:
  guid = uuid.uuid4().get_hex()
snip.rv = guid
`
date: `!v strftime("%Y-%m-%d %H:%M:%S")`
tags:
  - ${4}
---

${0}
endsnippet
# vim:ft=snippets:

这段代码中 guid 是用一段 Python 脚本生成的,date 是用 Vim 脚本生成的,${0} 代表 tab 最终停留的位置, b 代表 begin (snippet should be expanded only at the beginning of a line)。

head

It's cool!

总结

有好多 Vim er 高手不用代码块 (snippet) ,他们手工撸制每一行代码,喜欢原汁原味。每个人的偏好不同,使用 Snippet 真的极大的提高了工作效率。

参考资料

  1. xiaoronglv's vim config
  2. Why UltiSnips?
  3. Github: UltiSnips Source code
  4. UltiSnips Mannual

用了好几年的 vim,最后转 sublime 了

Plugin 'numbers.vim'
Plugin 'Raimondi/delimitMate'
Plugin 'mattn/emmet-vim'
Plugin 'bling/vim-airline'
Plugin 'bronson/vim-trailing-whitespace'
Plugin 'vim-scripts/molokai'
Plugin 'kien/ctrlp.vim'
Plugin 'ap/vim-css-color'
Plugin 'tpope/vim-dispatch'
Plugin 'tpope/vim-endwise'
Plugin 'tpope/vim-fugitive'
Plugin 'tpope/vim-surround'
Plugin 'tpope/vim-repeat'
Plugin 'tpope/vim-unimpaired'
Plugin 'tpope/vim-cucumber'
Plugin 'tpope/vim-git'
Plugin 'tpope/vim-haml'
Plugin 'tpope/vim-markdown'
Plugin 'tpope/vim-rails'
Plugin 'kchmck/vim-coffee-script'
Plugin 'pangloss/vim-javascript'
Plugin 'elzr/vim-json'
Plugin 'groenewege/vim-less'
Plugin 'sunaku/vim-ruby-minitest'
Plugin 'mmalecki/vim-node.js'
Plugin 'depuracao/vim-rdoc'
Plugin 'vim-ruby/vim-ruby'
Plugin 'slim-template/vim-slim'
Plugin 'cakebaker/scss-syntax.vim'
Plugin 'terryma/vim-multiple-cursors'
Plugin 'edsono/vim-matchit'
Plugin 'scrooloose/nerdcommenter'
Plugin 'scrooloose/nerdtree'
Plugin 'MarcWeber/vim-addon-mw-utils'
Plugin 'tomtom/tlib_vim'
Plugin 'garbas/vim-snipmate'
Plugin 'honza/vim-snippets'
Plugin 'ervandew/supertab'
Plugin 'mileszs/ack.vim'
Plugin 'itspriddle/ZoomWin'
Plugin 'honza/vim-snippets'
Plugin 'scrooloose/syntastic'
Plugin 'airblade/vim-gitgutter'
Plugin 'thoughtbot/vim-rspec'
Plugin 'digitaltoad/vim-jade'
Plugin 'nathanaelkane/vim-indent-guides'

这是我所有的插件 我用的是 vim-snipmate 用法和你的差不多 的确很方便

用了一年半 vim,最后转 sublime 了。

@chiangdi @yukihiro_matz 兄弟们都转 sublime 了 不期待下 neovim 吗 还是希望 vim 用户量再稍微多一点点啊

#5 楼 @leeboqiang vim 有的功能 sublime 都有,还更好和,还不折腾。neovim 还不知道什么时候能用

已经抛弃 Vim 多年。。其实 Sublime 也就这样了,后续的开发总是感觉不给力

已經轉投 Atom(with Vim Mode) 😄

说 Vim 有的功能 Sublime 都有的,只能说明你 Vim 水平还处在入门阶段!

#4 楼 @chiangdi vim 没 sublime 方便?

#6 楼 @yukihiro_matz 目前没有一个编辑器能有 vim 的快捷键方便

#12 楼 @ensonmj 目前大部分编辑器都提供 vim 模式的插件 😄

#13 楼 @MrPasserby 但大部分都是个皮毛

#12 楼 @ensonmj 我是 5 年的 vim 用户了吧,现在尝试用其它的

#15 楼 @yukihiro_matz 5 年不短了,不知你怎么用的,为啥说 vim 有的功能 sublime 都有,表示难以理解

#15 楼 @yukihiro_matz 准备换其他什么编辑器?

用其它编辑器时总想找个 VIM 模式插件,可以总是发现这儿或那儿不如 VIM 方便

强烈表示 vim 完爆 sublime

#17 楼 @lips sublime    现在也用 emacs

ultisnips 是比较好用

别用 vim-dispatch 了,Vim 8.0 出来后,我开发了个更顺手的插件,使用 8.0 原生异步 API,提供异步 git push,异步编译,异步更新 tags, 异步 grep 等功能,完美代替 vim-dispatch: https://github.com/skywind3000/asyncrun.vim

yukihiro_matz 回复

放弃 VIM 因为配置太麻烦么?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号