├── doc ├── UltiSnips_zh.txt ├── demo.gif ├── examples │ ├── autojump-if-empty │ │ ├── README.md │ │ ├── demo.gif │ │ └── snippet.gif │ ├── snippets-aliasing │ │ ├── README.md │ │ └── demo.gif │ └── tabstop-generation │ │ ├── README.md │ │ └── demo.gif └── tags └── readme.md /doc/UltiSnips_zh.txt: -------------------------------------------------------------------------------- 1 | *UltiSnips.txt* For Vim version 7.0 or later. 2 | 3 | The Ultimate Plugin for Snippets in Vim~ 4 | 5 | UltiSnips *snippet* *snippets* *UltiSnips* 6 | 7 | 1. 概述 |UltiSnips-description| 8 | 1.1 必要条件(依赖) |UltiSnips-requirements| 9 | 1.2 鸣谢 |UltiSnips-acknowledgments| 10 | 2. 安装和更新 |UltiSnips-installnupdate| 11 | 3. 设置和命令 |UltiSnips-settings| 12 | 3.1 命令 |UltiSnips-commands| 13 | 3.2 触发 |UltiSnips-triggers| 14 | 3.2.1 使用自定义触发函数 |UltiSnips-trigger-functions| 15 | 3.2.2 自定义自动命令 |UltiSnips-custom-autocommands| 16 | 3.2.3 Python模块的路径 |UltiSnips-python-module-path| 17 | 3.3 片段文件的搜索路径 |UltiSnips-snippet-search-path| 18 | 3.4 当心关于选择模式键映射 |UltiSnips-warning-smappings| 19 | 3.5 函数 |UltiSnips-functions| 20 | 3.5.1 UltiSnips#AddSnippetWithPriority |UltiSnips#AddSnippetWithPriority| 21 | 3.5.2 UltiSnips#Anon |UltiSnips#Anon| 22 | 3.5.3 UltiSnips#SnippetsInCurrentScope |UltiSnips#SnippetsInCurrentScope| 23 | 3.6 缺少python支持的警告 |UltiSnips-python-warning| 24 | 4. 语法 |UltiSnips-syntax| 25 | 4.1 添加snippets(片段) |UltiSnips-adding-snippets| 26 | 4.1.1 字符转义 |UltiSnips-character-escaping| 27 | 4.2 纯文本片段 |UltiSnips-plaintext-snippets| 28 | 4.3 选择模式占位符 |UltiSnips-visual-placeholder| 29 | 4.4 插入 |UltiSnips-interpolation| 30 | 4.4.1 shell脚本 |UltiSnips-shellcode| 31 | 4.4.2 vim脚本 |UltiSnips-vimscript| 32 | 4.4.3 python脚本 |UltiSnips-python| 33 | 4.4.4 全局的snippets(片段) |UltiSnips-globals| 34 | 4.5 Tabstops and Placeholders |UltiSnips-tabstops| 35 | 4.6 镜像 |UltiSnips-mirrors| 36 | 4.7 转换 |UltiSnips-transformations| 37 | 4.7.1 替换字符串 |UltiSnips-replacement-string| 38 | 4.7.2 演示 |UltiSnips-demos| 39 | 4.8 清除片段 |UltiSnips-clearing-snippets| 40 | 4.9 上下文片段 |UltiSnips-context-snippets| 41 | 4.10 片段行为 |UltiSnips-snippet-actions| 42 | 4.10.1 Pre-expand actions |UltiSnips-pre-expand-actions| 43 | 4.10.2 Post-expand actions |UltiSnips-post-expand-actions| 44 | 4.10.3 Post-jump actions |UltiSnips-post-jump-actions| 45 | 4.11 自动触发 |UltiSnips-autotrigger| 46 | 5. UltiSnips 和其他插件 |UltiSnips-other-plugins| 47 | 5.1 已经集成的插件 |UltiSnips-integrations| 48 | 5.2 扩展 UltiSnips |UltiSnips-extending| 49 | 6. 帮助我们 |UltiSnips-helping| 50 | 7. 贡献者 |UltiSnips-contributors| 51 | 52 | 这个插件仅仅工作在 'nocompatible' 设置的前提下 53 | {vi 没有这个特性,不能使用该插件} 54 | {只有在编译时加入了 |+python| 或 |+python3| 特性才能使用该插件} 55 | 56 | 57 | ============================================================================== 58 | 1. 概述 *UltiSnips-description* 59 | 60 | UltiSnips为vim编辑器提供snippet(文本、代码片段)管理。一个snippet是一小段文本,它 61 | 经常被重复使用,或者它本身就包括很多重复片段。UltiSnips让你仅仅通过几个键就能插 62 | 入一个snippet。snippet在结构化文本例如源代码中很常见,但也可用于一般的文本编辑, 63 | 例如,在电子邮件中插入一个签名,或者是在一个文本文件中插入当前时间。 64 | (注:以下称snippets为片段) 65 | 66 | @SirVer发布了几个简短的演示介绍UltiSnips,讲述了它的特性和使用方法 67 | 68 | http://www.sirver.net/blog/2011/12/30/first-episode-of-ultisnips-screencast/ 69 | http://www.sirver.net/blog/2012/01/08/second-episode-of-ultisnips-screencast/ 70 | http://www.sirver.net/blog/2012/02/05/third-episode-of-ultisnips-screencast/ 71 | http://www.sirver.net/blog/2012/03/31/fourth-episode-of-ultisnips-screencast/ 72 | 73 | 在 [Vimcasts](http://vimcasts.org) 还有三个很优秀的讲述UltiSnips的视频 74 | 75 | http://vimcasts.org/episodes/meet-ultisnips/ 76 | http://vimcasts.org/episodes/ultisnips-python-interpolation/ 77 | http://vimcasts.org/episodes/ultisnips-visual-placeholder/ 78 | 79 | 1.1 必要条件(依赖) *UltiSnips-requirements* 80 | ------------------ 81 | 82 | 该插件要求vim版本必须是 Vim version 7.4 或以上,而且必须设置为'nocompatible' 83 | 84 | 该插件在python 2.7,3.3,3.4版本下经过测试,不保证其他版本正常工作 85 | 86 | Python 2.x 或者 Python 3.x 的接口必须是可用的。也就是说,vim编译的时候必须加入 87 | 了|+python| 或 |+python3| 特性。下面的命令展示了如何测试你的vim编译时是否加入了这些 88 | 特性。如有有相应的特性,就会输出1,否则输出0。 89 | 90 | 测试vim编译时是否加了python2.x特性; 91 | :echo has("python") 92 | The python version Vim is linked against can be found with: > 93 | :py import sys; print(sys.version) 94 | 95 | 测试vim编译时是否加了python3.x特性; 96 | :echo has("python3") 97 | The python version Vim is linked against can be found with: > 98 | :py3 import sys; print(sys.version) 99 | 100 | Note vim可能使用的不是系统的python安装的python版本,所以确保检查过了vim使用的 101 | python版本 102 | 103 | UltiSnips会尝试自动指定一个编译vim时使用的python版本。 104 | 不幸的是,在某些版本的vim下,自动指定不能正常工作。 105 | 这时,你就必须明确告诉UltiSnips使用哪个版本的python,通过使用 106 | 'UltiSnipsUsePythonVersion' 用全局变量 107 | 108 | 指定为python2.x版本: > 109 | let g:UltiSnipsUsePythonVersion = 2 110 | 111 | 指定为python3.x版本: > 112 | let g:UltiSnipsUsePythonVersion = 3 113 | 114 | 115 | 1.2 鸣谢 *UltiSnips-acknowledgments* 116 | ------------------- 117 | 118 | UltiSnips的灵感来自于TextMate软件的snippet功能(http://macromates.com/), 119 | TextMate是Mac OS X下的一款图形化编辑器,在vim中管理片段并不是什么新鲜事。我 想感 120 | 谢Michael Sanders,snipMate的作者,对于一些实现细节,我借用了他的插件,并被允许 121 | 使用他的片段。 122 | 123 | ============================================================================= 124 | 2. 安装和更新 *UltiSnips-installnupdate* 125 | 126 | 推荐的获取UltiSnips的方式是在github上关注 SirVer/ultisnips,master分支一直是稳定 127 | 版本 128 | 129 | 使用 Pathogen: *UltiSnips-using-pathogen* 130 | 131 | 如果你是一个 pathogen 用户,你可以从github上UltiSnips的官方源获取: > 132 | 133 | $ cd ~/.vim/bundle && git clone git://github.com/SirVer/ultisnips.git 134 | 135 | 如果你还想要默认准备好的片段,同时跟踪: > 136 | 137 | $ cd ~/.vim/bundle && git clone git://github.com/honza/vim-snippets.git 138 | 139 | 查看 pathogen 的文档获取更多关于如何更新一个插件的详细信息 140 | 141 | 142 | 使用一个下载的版本: *UltiSnips-using-a-downloaded-packet* 143 | 144 | 下载压缩包并解压到一个你喜欢的位置。然后把这个目录加到你的vim的runtime path中, 145 | 你可以使用下面的代码,把它加到你的 vimrc 文件中即可 > 146 | set runtimepath+=~/.vim/ultisnips_rep 147 | 148 | UltiSnips 允许需要vim位于 ftdetect/ 目录下的vim源码。不幸的是,vim只允许它出现 149 | 在 .vim 目录中。因此你必须 链接或拷贝 它们 > 150 | mkdir -p ~/.vim/ftdetect/ 151 | ln -s ~/.vim/ultisnips_rep/ftdetect/* ~/.vim/ftdetect/ 152 | 153 | 重启vim,UltiSnips就可以工作了,想要查看帮助文档,使用下面的命令 > 154 | :helptags ~/.vim/ultisnips_rep/doc 155 | :help UltiSnips 156 | 157 | UltiSnips 和 片段一起工作,默认的 片段 可以从这里找到: 158 | https://github.com/honza/vim-snippets 159 | 160 | ============================================================================= 161 | 3. 设置和命令 *UltiSnips-settings* 162 | 163 | 3.1 命令 *UltiSnips-commands* 164 | -------- 165 | *:UltiSnipsEdit* 166 | UltiSnipsEdit 命令可以打开一个当前文件类型专用的片段定义文件。如果不存在该文 167 | 件,将会创建一个新的,如果有多个文件会展示一个列表以供选择。 如果使用 168 | UltiSnipsEdit! 所有公共的片段文件也会加入到该列表以供选择。 169 | 170 | 有几个变量和 UltiSnipsEdit 命令相关 171 | 172 | *g:UltiSnipsEditSplit* 173 | g:UltiSnipsEditSplit 定义了编辑"窗口"如何打开,可选的值如下 174 | |normal| 默认,在当前"窗口"打开 175 | |horizontal| 水平切分"窗口"并打开 176 | |vertical| 垂直切分窗口并打开 177 | |context| 水平或垂直切分窗口并打开,依赖于具体 178 | 的环境 179 | 180 | *g:UltiSnipsSnippetsDir* 181 | g:UltiSnipsSnippetsDir 182 | 定义了自定义片段文件的存放位置。比如,如果设置为 183 | "~/.vim/mydir/UltiSnips" 而当前 'filetype' 是 "cpp", 184 | 然后,:UltiSnipsEdit 将会打开 185 | "~/.vim/mydir/UltiSnips/cpp.snippets",前提是有这个 186 | 文件,如果它不存在,:UltiSnipsEdit 将会在 187 | g:UltiSnipsSnippetDirectories 查看存在的文件,如果没 188 | 有找到,:UltiSnipsEdit 将会在 g:UltiSnipsSnippetsDir 189 | 目录下打开一个新的文件 190 | Note 目录名为 "snippets" 的目录留给snipMate,不能使 191 | 用 192 | 193 | *g:UltiSnipsSnippetDirectories* 194 | g:UltiSnipsSnippetDirectories 195 | 定义了查找片段文件的目录,不要把这个变量和上一个 196 | 混了,要查看更多信息,参见 197 | |UltiSnips-snippet-search-path|部分 198 | 199 | *g:UltiSnipsEnableSnipMate* 200 | g:UltiSnipsEnableSnipMate 201 | 开启在 &runtimepath 下查找 SnipMate 的片段功能。 202 | UltiSnips在查找 SnipMate 的片段的时候将会只会找 203 | 名为 'snippets' 的目录。默认为 "1",所以UltiSnips会 204 | 查找 SnipMate 的片段。 205 | 206 | 207 | 208 | *:UltiSnipsAddFiletypes* 209 | UltiSnipsAddFiletypes 命令允许显示合并其他的文件类型的片段到当前缓冲区。比如 210 | 如你想编辑一个 a.rst 文件,但是你想同时可以使用lua的片段,就可以使用 > 211 | 212 | :UltiSnipsAddFiletypes rst.lua 213 | 214 | 使用点文件类型语法。顺序很重要,这里的第一个文件类型将会被 UltiSnipsEdit 使用, 215 | 而且出来的列表的顺序是按照这里的顺序来的。因此,你可以添加这个到你的 216 | ftplugin/rails.vim 文件 > 217 | 218 | :UltiSnipsAddFiletypes rails.ruby 219 | 220 | 我首先提到rails是因为我在使用 UltiSnipsEdit 的时候是想编辑rails的片段文件, 221 | 而且rails的等价的片段应该覆盖ruby的片段。现在的优先级将是 rails -> ruby 222 | -> all。如果你有一些特殊的代码片段应该有比ruby片段更低的优先级,你可以 > 223 | 224 | :UltiSnipsAddFiletypes ruby.programming 225 | 226 | 优先级将会是 rails -> rubu -> programming -> all 227 | 228 | 3.2 触发 *UltiSnips-triggers* 229 | -------- 230 | 231 | *g:UltiSnipsExpandTrigger* *g:UltiSnipsListSnippets* 232 | *g:UltiSnipsJumpForwardTrigger* *g:UltiSnipsJumpBackwardTrigger* 233 | 你可以通过设置全局变量来定义用于触发 UltiSnips 的键。这些变量定义了一些键,用来 234 | 展开一个片段,在一个片段中向前跳和向后跳,以及在列出在当前位置所有可以展开的片段 235 | 。注意,有些终端下不发送 给运行的程序。这些变量的默认值是 > 236 | g:UltiSnipsExpandTrigger 237 | g:UltiSnipsListSnippets 238 | g:UltiSnipsJumpForwardTrigger 239 | g:UltiSnipsJumpBackwardTrigger 240 | 241 | 为了尽量不影响其他键映射,这些映射只有在可以展开片段,可以向前向后跳的时候才会 242 | 生效 243 | 244 | g:UltiSnipsJumpBackwardTrigger 的默认值会影响内置的补全函数 |i_CTRL-X_CTRL-K|。一 245 | 个解决方法是添加下面这行到你的vimrc中,或者使用一个类似于 Supertab 和 246 | YouCompleteMe 的插件 > 247 | inoremap 248 | 249 | 3.2.1 使用自定义触发函数 *UltiSnips-trigger-functions* 250 | ------------------------ 251 | 252 | 对于高级用户,有4个函数可以直接映射到某个键,这和之前定义的触发按键是一致的 > 253 | g:UltiSnipsExpandTrigger <--> UltiSnips#ExpandSnippet 254 | g:UltiSnipsJumpForwardTrigger <--> UltiSnips#JumpForwards 255 | g:UltiSnipsJumpBackwardTrigger <--> UltiSnips#JumpBackwards 256 | 257 | 如果你将 g:UltiSnipsExpandTrigger 和 g:UltiSnipsJumpForwardTrigger 设置为相同的 258 | 值,你将会使用的函数式 UltiSnips#ExpandSnippetOrJump. 259 | 260 | UltiSnips#ExpandSnippet, UltiSnips#ExpandSnippetOrJump, UltiSnips#JumpForwards, 261 | UltiSnips#JumpBackwards,这些函数每次被调用,一个全局变量的值都会被设置,这个变 262 | 量包含了相应的方法的返回值 263 | 264 | 相应的变量和函数是 265 | UltiSnips#ExpandSnippet --> g:ulti_expand_res (0: fail, 1: success) 266 | UltiSnips#ExpandSnippetOrJump --> g:ulti_expand_or_jump_res (0: fail, 1: expand, 2: jump) 267 | UltiSnips#JumpForwards --> g:ulti_jump_forwards_res (0: fail, 1: success) 268 | UltiSnips#JumpBackwards --> g:ulti_jump_backwards_res (0: fail, 1: success) 269 | 270 | 查看这些返回值可能派上用场,如果你想映射一个键去展开或跳跃,但是上面的函数都没有 271 | 成功,你想调用其他的函数。UltiSnips已经为supertab适配好了这些,不过这允许你微调 272 | 你的tab键的使用 273 | 274 | 用法如下:你要定义一个函数 > 275 | 276 | let g:ulti_expand_or_jump_res = 0 "default value, just set once 277 | function! Ulti_ExpandOrJump_and_getRes() 278 | call UltiSnips#ExpandSnippetOrJump() 279 | return g:ulti_expand_or_jump_res 280 | endfunction 281 | 282 | 然后你像这样定义你的键映射 > 283 | 284 | inoremap =(Ulti_ExpandOrJump_and_getRes() > 0)?"":IMAP_Jumpfunc('', 0) 285 | 286 | 如果你在当前位置不能展开或跳跃,被调用将会是替代函数 IMAP_Jumpfunc('', 0) 287 | 288 | 3.2.2 自定义自动命令 *UltiSnips-custom-autocommands* 289 | -------------------- 290 | 291 | Note 自动命令必须不以任何方式改变缓冲区。如果添加,删除,修改了行将会混淆 292 | UltiSnips,可能会搞乱你的片段内容 293 | 294 | *UltiSnipsEnterFirstSnippet* *UltiSnipsExitLastSnippet* 295 | 为了和其他插件最大兼容,UltiSnips在一个片段被展开直到这个片段结束的时候设置了一 296 | 些特殊的状态,包括键映射和自动命令。为了覆盖这些默认设置,提供了下列的用户自动 297 | 命令(it fires the following "User" autocommand) > 298 | 299 | UltiSnipsEnterFirstSnippet 300 | UltiSnipsExitLastSnippet 301 | 302 | 举个例子,为了在这些事件触发的使用调用一对自定义函数,你可以这样做: > 303 | 304 | autocmd! User UltiSnipsEnterFirstSnippet 305 | autocmd User UltiSnipsEnterFirstSnippet call CustomInnerKeyMapper() 306 | autocmd! User UltiSnipsExitLastSnippet 307 | autocmd User UltiSnipsExitLastSnippet call CustomInnerKeyUnmapper() 308 | 309 | Note 片段展开的时候可能是嵌套在另外一个展开的片段里的,这时候 310 | |UltiSnipsEnterFirstSnippet| 只会在最外层的片段被展开时触发一次,而 311 | |UltiSnipsExitLastSnippet|只会在最外层的片段被结束时触发一次,对于嵌套的片段展开 312 | 他们都不会触发 313 | 314 | 315 | 316 | 3.2.3 Python模块的路径 *UltiSnips-python-module-path* 317 | ---------------------- 318 | 319 | 对于更高级的用法,你可以直接编写python函数,并在其中使用 UltiSnips 的python模块 320 | 321 | 这是一个小小的示例函数,用来展开一个片段: > 322 | 323 | function! s:Ulti_ExpandSnip() 324 | Python << EOF 325 | import sys, vim 326 | from UltiSnips import UltiSnips_Manager 327 | UltiSnips_Manager.expand() 328 | EOF 329 | return "" 330 | endfunction 331 | 332 | 3.3 snippets 文件的搜索路径 *UltiSnips-snippet-search-path* 333 | --------------------------- 334 | 335 | UltiSnips的snippets(片段)定义文件存放在一个或多个文件夹中。有几个变量用来表示这 336 | 些目录,以及定义UltiSnips如何加载代码片段 337 | 338 | 片段定义文件存放在 片段 文件夹。一个 片段 文件夹必须是一个定义在 339 | 'runtimepath' 中的目录的子目录。变量 g:UltiSnipsSnippetDirectories 定义了一个名 340 | 称列表,用于 片段 目录。Note "snippets" 是留给 snipMate 的片段的,不能使用。 341 | 默认的定义如下 > 342 | 343 | let g:UltiSnipsSnippetDirectories=["UltiSnips"] 344 | 345 | UltiSnips 会在 'runtimepath' 中定义的目录中搜索,看是否有子目录的名词是定义在 346 | g:UltiSnipsSnippetDirectories中的。比如,如果你把你的 片段 文件放在一个.vim的 347 | 子文件夹"mycoolsnippets"中,你希望它能和 UltiSnips 一起工作,那么就把下面这行加 348 | 到你的vimrc中 > 349 | let g:UltiSnipsSnippetDirectories=["UltiSnips", "mycoolsnippets"] 350 | 如果你不想使用第三方插件提供的片段,这样定义 > 351 | let g:UltiSnipsSnippetDirectories=["mycoolsnippets"] 352 | 353 | 你还可以通过设置 b:UltiSnipsSnippetDirectories ,对一个缓冲区重新定义基于缓冲区 354 | 的搜索路径,这个变量优先于全局变量 355 | 356 | |UltiSnips-adding-snippets| 解释了对于一个给定的文件类型,那些文件会被解析 357 | 358 | 如果这个变量中只指定了一个目录,而且这个目录是指定为绝对路径,UltiSnips将不会在 359 | &runtimepath 中寻找 片段 文件,这样做能够明显提升速度,通常可以这样做 > 360 | 361 | let g:UltiSnipsSnippetDirectories=[$HOME.'/.vim/UltiSnips'] 362 | 363 | 然而,你将无法使用第三方插件提供的片段,你需要将它们复制到你选择的目录中 364 | 365 | 366 | 3.4 当心关于选择模式键映射 *UltiSnips-warning-smappings* 367 | -------------------------- 368 | 369 | Vim 的关于 |mapmode-s| 的帮助文档: > 370 | 备注: 在选择模式映射可显示字符容易引起用户的混淆。最好直接用 :xmap 和 :smap 371 | 来映射可显示字符。或者在定义映射后使用 :sunmap。 372 | 373 | 然而,大多数vim插件,包括一些默认的vim插件,没有坚持这样做,在一个片段中, 374 | UltiSnips通过选择模式来标记要被覆盖的内容,已经存在的 Visual+Select 的键映射将会 375 | 受影响。因此,UltiSnips使用一个 |:sunmap| 命令删除每个选择模式的可以打印字符的键映 376 | 射。没有动其他的映射。特别的,不改变现有普通,插入或选择模式映射。 377 | 378 | 如果你不需要这种行为,在你的vimrc中添加这句来禁用它 > 379 | let g:UltiSnipsRemoveSelectModeMappings = 0 380 | 381 | 如果你想为某些特定的键映射禁用这个特性,把他们添加到忽略映射列表中。比如,下面这 382 | 行放到你的vimrc中将会取消所有选择模式的键映射,除了在它的完整定义(像|:smap|展示的 383 | 那样)中包含了"somePlugin"以及"otherPlugin"的键映射 > 384 | 385 | let g:UltiSnipsRemoveSelectModeMappings = 1 386 | let g:UltiSnipsMappingsToIgnore = [ "somePlugin", "otherPlugin" ] 387 | 388 | 389 | 3.5 函数 *UltiSnips-functions* 390 | -------- 391 | 392 | UltiSnips 提供了一些函数可以扩展核心功能 393 | 394 | 395 | 3.5.1 UltiSnips#AddSnippetWithPriority *UltiSnips#AddSnippetWithPriority* 396 | 397 | 第一个函数是 UltiSnips#AddSnippetWithPriority(trigger, value, description, 398 | options, filetyp, priority). 它添加了一个新的 片段,通过使用提供的 trigger(触 399 | 发片段的字符串),value(片段本身), description 和 options,这个片段被添加到当 400 | 前的文件类型(current list of snippets 是这个意思么),查看 |UltiSnips-syntax|了解 401 | 每个参数的意义。priority 是一个数字,定义了哪个片段优先级更高。了解 priority 更 402 | 多信息请查看 |UltiSnips-add-snippets|。 403 | 404 | 405 | 3.5.2 UltiSnips#Anon *UltiSnips#Anon* 406 | 407 | 第二个函数是 UltiSnips#Anon(value, ...). 它展开一个匿名的片段。匿名的片段现场定 408 | 义并立即展开然后丢弃,匿名片段不添加到全局的片段列表,所以他们不能重用,除非再 409 | 调用该函数。该函数接受可选的参数,按照这个顺序:trigger, description, options。 410 | 参数和|UltiSnips#AddSnippetWithPriority|的同名函数一致。trigger 和 options 参数可 411 | 以改变片段被展开的方式,同样的选项可以在片段定义中被指定。在这里可以查看玩着的列 412 | 表 |UltiSnips-snippet-options|。description 在这里没有使用 413 | 414 | 一个可以做例子的用例可能是从一个 reStructuredText 插件里提取的这行 > 415 | 416 | inoremap $$ $$=UltiSnips#Anon(':latex:\`$1\`', '$$') 417 | 418 | 一旦输入两个 $ 片段就会被展开 419 | Note: The right-hand side of the mapping starts with an immediate retype of 420 | the '$$' trigger and passes '$$' to the function as the trigger argument. 421 | This is required in order for UltiSnips to have access to the characters 422 | typed so it can determine if the trigger matches or not. 423 | 424 | 3.5.3 UltiSnips#SnippetsInCurrentScope *UltiSnips#SnippetsInCurrentScope* 425 | 426 | 第三个函数是 UltiSnips#SnippetsInCurrentScope,相当于是snipMate的 427 | GetSnipsInCurrentScope 函数 428 | 429 | 这个函数简单的返回一个vim字典,里面装了可以有当前单词触发的片段,如果你需要当前 430 | 缓冲区的所有片段片段的信息,你可以通过将1(表示所有)作为这个函数的第一个参数,并 431 | 使用一个全局的变量 g:current_ulti_dict_info 来获取结果(看下面的例子) 432 | 433 | 这个函数没有添加任何新的功能,但是允许第三方插件集成当前可用的片段。 434 | 435 | 这类第三方插件的一个例子就是SnippetCompleteSnipMate,使用GetSnipsInCurrentScope 436 | 函数整合当前可用片段与用户定义的缩写,并在一个补全菜单中提供 437 | 438 | 这个脚本位于 439 | http://www.vim.org/scripts/script.php?script_id=4276. 440 | Note: 如果你查看上面的网页,会发现它列出两个依赖,SnippetComplete plugin 和 441 | snipmate. 442 | 你需要SnippetComplete插件,但你显然不需要snipmate,你只需要定义函数 443 | GetSnipsInCurrentScope。把下面的代码加到你的vimrc: > 444 | function! GetSnipsInCurrentScope() 445 | return UltiSnips#SnippetsInCurrentScope() 446 | endfunction 447 | 448 | 449 | 关于如何使用这个函数的第二个例子,考虑下面的函数和映射定义: 450 | 451 | function! ExpandPossibleShorterSnippet() 452 | if len(UltiSnips#SnippetsInCurrentScope()) == 1 "only one candidate... 453 | let curr_key = keys(UltiSnips#SnippetsInCurrentScope())[0] 454 | normal diw 455 | exe "normal a" . curr_key 456 | exe "normal a " 457 | return 1 458 | endif 459 | return 0 460 | endfunction 461 | inoremap =(ExpandPossibleShorterSnippet() == 0? '': UltiSnips#ExpandSnippet()) 462 | 463 | 如果你的片段的触发器是 lorem,你输入 lor,而且你没有任何其他片段的触发器匹配lor, 464 | 然后摁将会展开lorem的片段。 465 | 466 | 关于使用这个函数的第三个例子是提取当前缓冲区的所有片段 467 | 468 | function! GetAllSnippets() 469 | call UltiSnips#SnippetsInCurrentScope(1) 470 | let list = [] 471 | for [key, info] in items(g:current_ulti_dict_info) 472 | let parts = split(info.location, ':') 473 | call add(list, { 474 | \"key": key, 475 | \"path": parts[0], 476 | \"linenr": parts[1], 477 | \"description": info.description, 478 | \}) 479 | endfor 480 | return list 481 | endfunction 482 | 483 | 新的变量 g:current_ulti_dict_info 用来避免和其他已存在的第三方插件冲突,这个定义 484 | 包含了文件路径和行号 485 | 486 | 487 | 3.6 缺少python支持的警告 *UltiSnips-python-warning* 488 | ------------------------ 489 | 490 | 当UltiSnips被加载的时候,它会检查vim编译和运行时的python支持。如果没有检测到,会 491 | 显示一个警告并跳过加载 492 | 493 | 如果你想抑制这个警告信息,你可以添加这行到你的vimrc文件 > 494 | 495 | let g:UltiSnipsNoPythonWarning = 1 496 | 497 | 如果你的vim配置文件在多个系统间共享,而其中的一些可能没有编译vim的pyton支持, 498 | 这可能是有用的 499 | 500 | ============================================================================= 501 | 4. 语法 *UltiSnips-syntax* 502 | 503 | 这章描述了如何编写自己的片段以及片段定义语法。例子是用来帮助说明的。 504 | 505 | 506 | 4.1 添加片段 *UltiSnips-adding-snippets* 507 | ------------ 508 | 509 | 查看|UltiSnips-snippet-search-path|,这里解释了哪个包含了片段定义的文件夹会被加载 510 | 511 | 这里使用了一个类似于vim指定 |ftplugin| 的策略,UltiSnips迭代片段定义的目录,查找 512 | 和下面匹配的文件名:ft.snippets, ft_*.snippets, 或ft/*,"ft"是当前缓冲区的 513 | "filetype",而"*"是类似于shell的通配符匹配任何字符串包括空字符串。下面展示了一些 514 | 典型的片段文件及其关联的文件类型。 515 | 516 | snippet filename filetype ~ 517 | ruby.snippets ruby 518 | perl.snippets perl 519 | c.snippets c 520 | c_my.snippets c 521 | c/a c 522 | c/b.snippets c 523 | all.snippets *all 524 | all/a.snippets *all 525 | 526 | * 'all' 文件类型是独有的。它表示这里的片段适用于任何文件,不论编辑的文件类型是什 527 | 么。例如,一个日期插入片段就适合放假 all.snippets 文件中。 528 | 529 | UltiSnips支持vim的点文件类型语法。例如,如果你为 CUDA C++ 框架定义一个点文件类型, 530 | ":set ft=cuda.cpp",UltiSnips将会搜索并激活cuda和cpp文件的文件类型的片段 531 | 532 | 片段文件的语法很简单。任何以 # 开始的行都是注释。注释会被 UltiSnips 忽略。是用注 533 | 释来做片段的文档 534 | 535 | 以关键字啊 'extends' 开始的行提供了一种组合片段文件的方法。当 'extends' 关键字包 536 | 含在一个片段文件中,它指定 UltiSnips 把指定的文件类型的片段包括进来 537 | 538 | 这个语法看起来像这样: > 539 | extends ft1, ft2, ft3 540 | 541 | 例如,在cpp.snippets的第一行看起来就像这样: > 542 | extends c 543 | 当UltiSnips为一个cpp文件激活片段,它首先查看所有的的c片段,并激活他们。这是一个 544 | 方便的从一般片段创建专用片段的方式。多个 'extends' 允许出现在一个片段文件中,他 545 | 们可以出现在文件的任何地方。 546 | 547 | 548 | 以关键字 'priority' 开始的行设置了当前片段文件中在该行之后的的所有片段的优先级, 549 | 一个片段文件中的片段的默认的优先级是0。当以个片段应该被展开的时候,UltiSnips会收 550 | 集所有激活的片段文件中的所有能被当前触发器触发的片段,并且默认选中优先级最高的一 551 | 个。例如,所有的内置(shipped)的片段优先级都小于0,所以用户定义的片段总是会覆盖 552 | 内置(shipped)的片段。 553 | 554 | 555 | 以关键字 'snippet' 开始的一行标记了一个片段定义的开始,而以关键字 'endsnippet' 556 | 开始的一行标记着一个片段定义的结束。片段的定义就在这两行中间。这里是一个unix的 557 | shell脚本文件类型的if语句的片段定义 558 | 559 | snippet if "if ... then (if)" 560 | if ${2:[[ ${1:condition} ]]}; then 561 | ${0:#statements} 562 | fi 563 | endsnippet 564 | 565 | 开始行要符合下面的格式: > 566 | 567 | snippet tab_trigger [ "description" [ options ] ] 568 | 569 | tab_trigger 是必须的,但 description 和 opotions 是可选的 570 | 571 | 'tab_trigger'使用来触发片段的单词或字符串。 572 | Generally a single word is used but the tab_trigger can include spaces 573 | 如果你希望有包含空格,你必须把触发器包到一个引号里面 > 574 | 575 | snippet "tab trigger" [ "description" [ options ] ] 576 | 577 | 引号不是触发器的一部分,键入: tab trigger 再摁展开片段的键 578 | 579 | 使用引号将带空格的触发器包裹起来并不是技术上必须的。任何匹配的字符都可以。比如说, 580 | 这行就是一个有效的片段的开始 > 581 | snippet !tab trigger! [ "description" [ options ] ] 582 | 583 | 通过使用其他字符来包裹触发器,引号可以包括在触发器中 > 584 | snippet !"tab trigger"! [ "description" [ options ] ] 585 | 586 | 我们只要键入:"tab trigger"就能激活这个片段 587 | 588 | 'description' 是一个描述片段的字符串。为一个片段添加描述文档,有利于和其他具有 589 | 相同触发器的片段区分开。当一个片段被激活,但是匹配多个触发器(译者认为是:当一个 590 | 触发器被激活,但是匹配多个片段),UltiSnips 会展示一个列表,其中列出了所有匹配的 591 | 片段和它们的描述。然后用户就可以选择他们想要的那个片段。 592 | 593 | *UltiSnips-snippet-options* 594 | 595 | 'options' 则控制着片段的行为。'options' 通过单个字符指定。 596 | 片段的'options'选项如果有多个当做一个单词连起来写即可,不需要加空格。 597 | 598 | 599 | 目前支持下面的options(选项): > 600 | b 一行的开始 - 有这个选项的片段只有在触发器是一行的第一个单词(如果触发器是多 601 | 个单词也看做一个)时才能被展开。换句话说,只要触发器前面是空白就能展开。而 602 | 默认是可以在任何位置展开片段,不管前面是不是非空白字符。 603 | 604 | i 在单词中展开 - 默认只有在触发器是一行的第一个单词或者它被放在空白字符之间 605 | 才能被展开。有这个选项的片段会忽略触发器被放在哪。也就是说,片段可以在一 606 | 个单词中间被触发展开。 607 | 608 | w 单词边界 - 使用了这个选项,只有在触发器的开始和结束处都位于单词边界,才能 609 | 被展开。也就是说触发器必须放在一个非单词字符后面。单词字符由 'iskeyword' 610 | 设置。使用这个选项的一个例子,当触发器在一个标点符号后面,这个标点符号不是 611 | 另一个触发器的最后字符,这个触发器可以被展开(如果这个片段使用了这个选项)。 612 | 613 | r 正则表达式 - 使用这个选项,触发器应当是一个python的正则表达式。如果当前键 614 | 入的字符串匹配定义的正则表达式。Note: 正则表达式必须被引号括起来(或者用其 615 | 他字符包裹)不论它是否包含空格,就像一个多个单词的触发器那样(见上文)。匹配 616 | 的结果会作为本地变量"match"传递给片段中的任何python代码。 617 | 618 | t 不要展开制表符 - 如果一个片段定义中包括了领头的制表符,默认UltiSnips会根 619 | 据vim的下列缩进设置来展开制表符 'shiftwidth', 'softtabstop', 'expandtab' 620 | 和'tabstop'(比如说,如果设置了'expandtab',制表符会被空格替代),如果设置 621 | 了这个选项,UltiSnips就会忽略vim的这些设置,插入制表符本身。比如说,这个 622 | 设置对使用制表符来约定格式的片段很有用。 623 | 624 | s 在跳到下一个插入点前,立即移除行尾光标前的空白字符。如果在某一个插入点, 625 | 在行尾有可选的文本,这将是很有用的。 626 | 627 | m 在一个片段中,减掉所有右边的空白字符。当片段中包含空行,并且需要在展开后 628 | 也保持空。如果没有这个选项,在片段中的空行上将会有缩进字符。 629 | 630 | e 上下文片段 - 使用这个选项,片段的展开将不仅仅被前面的字符控制,还会被给出 631 | 的python表达式控制。这个选项可以和其他选项一起指定,比如说'b'。查看 632 | |UltiSnips-context-snippets|获取详细信息。 633 | 634 | A 当条件满足时,片段会被自动地触发并展开。查看 |UltiSnips-autotrigger| 获取 635 | 详细信息。 636 | 637 | 结束行是 'endsnippet' 关键字单独在一行 > 638 | 639 | endsnippet 640 | 641 | 当解析片段文件的时候,UltiSnips会出去'endsnippet'结束行后的换行符。 642 | 643 | 644 | 4.1.1 字符转义: *UltiSnips-character-escaping* 645 | 646 | 在片段的定义中,字符'`','}','$','\'有特殊意义,如果要插入这些字符,使用'\'来 647 | 转义他们。 648 | 649 | 650 | 4.2 纯文本片段 *UltiSnips-plaintext-snippets* 651 | -------------- 652 | 653 | 为了说明纯文本片段,让我们以一个小的例子开始。你可以自己尝试这些例子。很简单,只 654 | 要用vim编辑一个新的文件就可以。作为例子的片段会被添加到 'all.snippets',所以你 655 | 可能想要在vim中打开并便捷它。 > 656 | ~/.vim/UltiSnips/all.snippets 657 | 658 | 把这个加到 'all.snippets' 并保存 659 | 660 | ------------------- SNIP ------------------- 661 | snippet bye "My mail signature" 662 | Good bye, Sir. Hope to talk to you soon. 663 | - Arthur, King of Britain 664 | endsnippet 665 | ------------------- SNAP ------------------- 666 | 667 | 当你修改了一个片段文件,UltiSnips会自动检测到并加载改动。所以,在一个空的缓冲区 668 | 中,键入触发器'bye',然后按键。 669 | 670 | bye --> 671 | Good bye, Sir. Hope to talk to you soon. 672 | - Arthur, King of Britain 673 | 674 | 单词'bye'将会被片段中定义的文本替换。 675 | 676 | 677 | 4.3 选择模式占位符 *UltiSnips-visual-placeholder* 678 | ------------------ 679 | 680 | 片段中可以包含一个特殊的占位符,叫做 ${VISUAL}。${VISUAL} 将会在展开的时候被替换 681 | 为展开之前选中的文本。 682 | 683 | 为了查看一个带有${VISUAL}的片段如何工作,定义一个带有该占位符的片段,使用vim的 684 | 选择模式选中一些字符,然后键入你想展开的片段的触发器(见g:UltiSnipsExpandTrigger) 685 | 。选中的文本会被删除,你被带入了插入模式。然后键入触发器再按展开触发器的键。在 686 | 片段被展开的同时,之前选中的文字被放到了${VISUAL}所在的位置。 687 | 688 | ${VISUAL}占位符可以包含默认的文本,当片段没有在选择模式下被展开的时候将会使用默 689 | 认文本替换${VISUAL}占位符。语法就像这样: > 690 | ${VISUAL:default text} 691 | 692 | ${VISUAL}占位符还可以定义一个转换(查看|UltiSnips-transformations|)。语法就像这样: > 693 | ${VISUAL:default/search/replace/option}. 694 | 695 | 这是一个很简单的例子用来说明选择模式转换。片段将会拿走选中的文本,然后用 "is" 替 696 | 换掉每个 "should",然后用tags把结果包裹起来。 697 | 698 | ------------------- SNIP ------------------- 699 | snippet t 700 | ${VISUAL:inside text/should/is/g} 701 | endsnippet 702 | ------------------- SNAP ------------------- 703 | 704 | 从这行文字开始吧: > 705 | this should be cool 706 | 707 | 把贯标放到单词 "should" 上,然后键入:viw(选择模式 -> 选择一个单词)。然后键入 708 | ,键入 "t" 然后再键入 。结果是: > 709 | -> this is be cool 710 | 711 | 如果你没有在选择模式下展开这个片段(比如,在插入模式下插入 t,你将会得到): > 712 | inside text 713 | 714 | 715 | 4.4 插入 *UltiSnips-interpolation* 716 | -------- 717 | 718 | 4.4.1 shell脚本: *UltiSnips-shellcode* 719 | 720 | 片段文件中可以包含shell脚本。把一个shell命令放到一个片段中,然后当片段被展开的 721 | 时候,shell脚本会被shell执行所产生的输出替换。shell脚本的语法很简单:把代码包裹 722 | 在反引号总,'`'。当片段被展开,UltiSnips会首先将他写入一个临时脚本,然后执行它。 723 | shell脚本会被标准输出的结果替换。任何你能在脚本中运行的东西都能用到shell脚本中。 724 | 包括一个 shebang 行,比如说 #!/usr/bin/perl,然后你的片段就能使用其他程序来运行 725 | 脚本,例如perl。 726 | 727 | 这儿有一些例子。片段使用了一个shell命令去插入当前日期。 728 | 729 | ------------------- SNIP ------------------- 730 | snippet today 731 | Today is the `date +%d.%m.%y`. 732 | endsnippet 733 | ------------------- SNAP ------------------- 734 | 735 | today -> 736 | Today is the 15.07.09. 737 | 738 | 739 | This example inserts the current date using perl. 740 | 这个例子使用perl插入当前日期。 741 | 742 | ------------------- SNIP ------------------- 743 | snippet today 744 | Today is `#!/usr/bin/perl 745 | @a = localtime(); print $a[3] . '.' . $a[4] . '.' . ($a[5]+1900);`. 746 | endsnippet 747 | ------------------- SNAP ------------------- 748 | today -> 749 | Today is 15.6.2009. 750 | 751 | 752 | 4.4.2 vim脚本: *UltiSnips-vimscript* 753 | 754 | 你也可以使用vim脚本(有时也叫作vimL)来插入。语法和shell脚本本很相似。把代码包裹 755 | 到反引号中,为了区分它是一个vim脚本,用 '!v' 作为代码的开始。这里是一个计算当前 756 | 行的单词数的例子: 757 | 758 | ------------------- SNIP ------------------- 759 | snippet indent 760 | Indent is: `!v indent(".")`. 761 | endsnippet 762 | ------------------- SNAP ------------------- 763 | (note the 4 spaces in front): indent -> 764 | (note the 4 spaces in front): Indent is: 4. 765 | 766 | 767 | 4.4.3 Python: *UltiSnips-python* 768 | 769 | python脚本插入是迄今为止最强大的。除了使用'!p'开始之外,语法就像vim脚本一样。 770 | python脚本可以通过使用 shebang 行'#!/usr/bin/python'来运行,但是使用 '!p' 可以 771 | 和一些预定义对象和变量一起使用,它们可以简化和缩短代码。例如,一个 'snip' 对象 772 | 的实例隐含在python代码中。使用 '!p' 指定的python代码和另一种方式是不同的。通常 773 | 一个片段被展开,将会使用代码的标准输出来提换代码部分。但是在python脚本中,'snip' 774 | 的实例的属性'rv'将会用来替换代码。标准输出会被忽略。 775 | 776 | 在python脚本中自动定义的变量是这些: > 777 | 778 | fn - 当前文件名 779 | path - 当前文件的完整路径 780 | t - 占位符的值,t[1] 就是 ${1} 表示的文本,以此类推 781 | snip - UltiSnips.TextObjects.SnippetUtil 对象的实例。有一些简化插入处理的 782 | 方法 783 | context - 上下文条件的结果。 参见 |UltiSnips-context-snippets| 784 | 785 | 'snip' 对象提供了下列方法: > 786 | 787 | snip.mkline(line="", indent=None): 788 | is None, then mkline prepends spaces and/or tabs appropriate to the 789 | current 'tabstop' and 'expandtab' variables. 790 | 返回一行将要添加到结果中的文本。如果indent参数为None,该函数会根据当前 791 | 的 'tabstop' 和 'expandtab' 设置来添加 空格和/或制表符的缩进。 792 | 793 | snip.shift(amount=1): 794 | 根据 'shiftwidth' 定义和空格数,'amount' times 来转换 mkline 使用的缩进 795 | 级别。 796 | 797 | snip.unshift(amount=1): 798 | 根据 'shiftwidth' 设置的空格数目,'amount' times,转换mkline使用的默认的 799 | 缩进级别 800 | 801 | snip.reset_indent(): 802 | 重置内置的缩进级别为其初始值。 803 | 804 | snip.opt(var, default): 805 | 检查是否设置了vim变量 'var'。如果设置了,就返回变量的值,否则,返回默认 806 | 值 807 | 808 | 'snip' 对象提供了一些属性: > 809 | 810 | snip.rv: 811 | 'rv'是返回值,这个文本将会替换掉片段中定义的python代码块,它被初始化为空 812 | 的字符串。This description the 'res' variable. 813 | 814 | snip.c: 815 | 表示片段中当前在python代码块位置的文本。一旦插入完成他就被设置为空。因此 816 | 你可以检查 if snip.c != "" 来确保插入只进行了一次。 817 | This deprecates the "cur" variable. 818 | 819 | snip.v: 820 | 封装了关于 ${VISUAL} 占位符的数据。有两个属性: 821 | snip.v.mode ('v', 'V', '^V', 参见 |visual-mode| ) 822 | snip.v.text 被选中的文本 823 | 824 | snip.fn: 825 | 当前文件的文件名。 826 | 827 | snip.basename: 828 | 当前文件的不到扩展名的文件名。 829 | 830 | snip.ft: 831 | 当前文件类型。 832 | 833 | snip.p: 834 | 最后选定的占位符。包含占位符对象,占位符对象包含以下属性: 835 | 836 | 'current_text' - 在选中文本的时候,占位符对应的文本 837 | 'start' - placeholder start on the moment of selection; 838 | 'end' - placeholder end on the moment of selection; 839 | 840 | 为了方便你的使用,'snip'还提供了下列操作: > 841 | 842 | snip >> amount: 843 | Equivalent to snip.shift(amount) 844 | snip << amount: 845 | Equivalent to snip.unshift(amount) 846 | snip += line: 847 | Equivalent to "snip.rv += '\n' + snip.mkline(line)" 848 | 849 | 任何定义在python代码块中的变量可以在其他在同一个片段中的python代码块中使用。当然 850 | python模块'vim','re','os','string','random'已经被预加载到片段中的python代码 851 | 块了。其他模块可以使用python的'import'语句来导入。 852 | 853 | python代码块允许创建非常灵活得片段。举个例子,下面的片段镜像第一个插入点的文本 854 | 到同一行并右对齐,而且转换成了大写。 855 | 856 | ------------------- SNIP ------------------- 857 | snippet wow 858 | ${1:Text}`!p snip.rv = (75-2*len(t[1]))*' '+t[1].upper()` 859 | endsnippet 860 | ------------------- SNAP ------------------- 861 | wowHello World -> 862 | Hello World HELLO WORLD 863 | 864 | 下面的片段正则表达式选项,使用python的匹配对象说明正则表达式分组。这表明片段的 865 | 展开依赖于定义片段时使用的触发器,而触发器本身是可以变化的。 866 | 867 | ------------------- SNIP ------------------- 868 | snippet "be(gin)?( (\S+))?" "begin{} / end{}" br 869 | \begin{${1:`!p 870 | snip.rv = match.group(3) if match.group(2) is not None else "something"`}} 871 | ${2:${VISUAL}} 872 | \end{$1}$0 873 | endsnippet 874 | ------------------- SNAP ------------------- 875 | becenter -> 876 | \begin{center} 877 | 878 | \end{center} 879 | ------------------- SNAP ------------------- 880 | be center -> 881 | \begin{center} 882 | 883 | \end{center} 884 | 885 | 第二种形式是第一种的变种,都会产生相同的结果,但是它说明了正则表达式分组是如何 886 | 工作的。使用正则表达式的这种发哪个是有一些缺点: 887 | 1. 如果你同时使用展开片段和补全的话,当你键入"be form",期待它来补全 888 | "be formatted",你最终你将得到上面的 SNAP,但这不是你想要的。 889 | 2. 片段将会难以读懂。 890 | 891 | 然而,最大的优势是,你可以创建考虑触发器之前的文本的片段。这样,你就可以使用它来 892 | 创建后缀片段,这在一些IDE中非常流行。(触发的时候会根据触发器之前的文本得到不同的 893 | 可触发列表) 894 | 895 | ------------------- SNIP ------------------- 896 | snippet "(\w+).par" "Parenthesis (postfix)" r 897 | (`!p snip.rv = match.group(1)`$1)$0 898 | endsnippet 899 | ------------------- SNAP ------------------- 900 | something.par -> 901 | (something) 902 | 903 | ------------------- SNIP ------------------- 904 | snippet "([^\s].*)\.return" "Return (postfix)" r 905 | return `!p snip.rv = match.group(1)`$0 906 | endsnippet 907 | ------------------- SNAP ------------------- 908 | value.return -> 909 | return value 910 | 911 | 912 | 4.4.4 全局片段: *UltiSnips-globals* 913 | 914 | 全局片段提供了一种在多个片段中重用一些通用代码的方式。目前只支持python代码。执行 915 | 全局片段的内容的结果会被放到片段文件中每个python代码块的全局数据域中。要创建一个 916 | 全局片段,使用关键字 'global' 代替 'snippet',对于python代码,使用 '!p' 作为触发 917 | 器。列入,下面的片段作为最后一个例子,他们将产生相同的输出。无论如何,用这样的语 918 | 法,'upper_right' 就可以被其他片段重用。 919 | 920 | ------------------- SNIP ------------------- 921 | global !p 922 | def upper_right(inp): 923 | return (75 - 2 * len(inp))*' ' + inp.upper() 924 | endglobal 925 | 926 | snippet wow 927 | ${1:Text}`!p snip.rv = upper_right(t[1])` 928 | endsnippet 929 | ------------------- SNAP ------------------- 930 | wowHello World -> 931 | Hello World HELLO WORLD 932 | 933 | python的全局函数可以被保存到一个python模块然后被导入。这使得全局函数可以很容易地 934 | 在所有片段文件中被访问到。自从vim7.4以后,你可以直接把python文件放到 935 | ~/.vim/python/ 然后直接导入它们到你的片段中。举个例子,使用 936 | ~/.vim/pythonx/my_snippets_helpers.py > 937 | 938 | global !p 939 | from my_snippet_helpers import * 940 | endglobal 941 | 942 | 943 | 4.5 插入点和占位符 *UltiSnips-tabstops* *UltiSnips-placeholders* 944 | ------------------ 945 | 946 | 片段用来在一个文档中快速插入重用的文本。通常这个文本有固定的结构和变化的成分。 947 | 插入点可以用来简单的改变变化的内容,插入你想要的内容,然后跳到下一个变化的部分, 948 | 插入内容,然后继续知道所有的变化的部分都完成。 949 | 950 | 插入点的语法是一个 $ 符号紧跟着一个数字,例如,'$1'。插入点遵循从一号开始然后按 951 | 顺序排列,'$0'是一个特殊的插入点。不论有多少插入点被定义,它总是片段中的最后一个 952 | 插入点。如果没有定义 '$0','$0'将默认被定义在片段的末尾。 953 | 954 | 这里是一个简单的例子 955 | 956 | ------------------- SNIP ------------------- 957 | snippet letter 958 | Dear $1, 959 | $0 960 | Yours sincerely, 961 | $2 962 | endsnippet 963 | ------------------- SNAP ------------------- 964 | letterBenPaulThanks for suggesting UltiSnips!-> 965 | Dear Ben, 966 | Thanks for suggesting UltiSnips! 967 | Yours sincerely, 968 | Paul 969 | 970 | 你可以使用跳到下一个插入点,用跳到上一个插入点。键没有被用作跳 971 | 到下一个插入点是因为很多人(包括我)使用来补全。查看 |UltiSnips-triggers| 来 972 | 获得有关为插入点定义不同的键的帮助 973 | 974 | 为一个插入点设置默认值常常是有用的。默认值可能是变量值常用的部分,或者是一个词 975 | 或短语,提醒你这里应该输入什么。要插入默认值,语法是 '${1:value}'。 976 | 977 | 下面的例子说明了一个shell脚本的case语句的片段。插入点使用默认值来提醒用户应该输 978 | 入什么值 979 | 980 | ------------------- SNIP ------------------- 981 | snippet case 982 | case ${1:word} in 983 | ${2:pattern} ) $0;; 984 | esac 985 | endsnippet 986 | ------------------- SNAP ------------------- 987 | 988 | case$option-vverbose=true 989 | case $option in 990 | -v ) verbose=true;; 991 | esac 992 | 993 | 994 | 有是有在一个插入点中放一个插入点是很有用的。要这样做,简单地将嵌套的插入点作为 995 | 默认文本的一部分即可。考虑下面的例子,它说明了一个html的标签片段 996 | 997 | ------------------- SNIP ------------------- 998 | snippet a 999 | 1000 | $0 1001 | 1002 | endsnippet 1003 | ------------------- SNAP ------------------- 1004 | 1005 | 当这个片段被展开,第一个插入点有一个默认值'http://www.example.com'。如果你想要 1006 | 'http://'模式,跳到下一个插入点。他有一个默认值'example.com'。它可以被任何你想 1007 | 插入的域名替换 1008 | 1009 | agoogle.comGoogle -> 1010 | 1011 | Google 1012 | 1013 | 1014 | 如果在第一个插入点你想要不同的url模式,或是替换默认的url用一个命令的锚,'#name', 1015 | 你可以键入你想要的值。 1016 | 1017 | a#topTop -> 1018 | 1019 | Top 1020 | 1021 | 1022 | 在最后一个例子中,在第一个插入点插入任何文本来替换默认值,包括第二个插入点也可以 1023 | 被键入的文本覆盖。所以第二个插入点本质上被删除了,当执行跳到下一个插入点, 1024 | UltiSnipsa移动到剩下的下一个插入点'$0'。这个特性可以用来有意的给用户提供可选的插 1025 | 入点值。 1026 | 1027 | 这里有一个例子来说明它。 1028 | 1029 | ------------------- SNIP ------------------- 1030 | snippet a 1031 | 1032 | $0 1033 | 1034 | endsnippet 1035 | ------------------- SNAP ------------------- 1036 | 1037 | 这里,'$1' 标记了第一个插入点。它假设你总想要添加一个href属性的值。输入url后按 1038 | ,跳到第二个插入点,'$2'。这个插入点事可选的。默认值是 'class="link"'。你可 1039 | 以按 接受这个插入点,然后就会跳到第三个插入点,$3,然后你键入class属性的 1040 | 值,或者,在第二个插入点你可以按 退格键从而用空字符串替换第二个插入点的默认文本, 1041 | 也就是删除它。在这两种情况下,继续按就可以跳到最后在标签内的插入点。 1042 | 1043 | ahttp://www.google.comvisitedGoogle -> 1044 | 1045 | Google 1046 | 1047 | 1048 | ahttp://www.google.comGoogle -> 1049 | 1050 | Google 1051 | 1052 | 1053 | 默认值中还可以包含镜像,转换和插入。 1054 | 1055 | 1056 | 4.6 镜像 *UltiSnips-mirrors* 1057 | -------- 1058 | 1059 | 镜像可以重复一个插入点的内容。在一个片段展开后,当你在一个插入点插入内容,该插入 1060 | 点的所有的镜像都会被同样的值替换。要给一个插入点做一个镜像,只需要简单的再插入 1061 | 这个插入点一次,使用 $ 符号并跟上一个数字的语法,例如,'$1' 1062 | 1063 | 在一个片段中,一个插入点可以被镜像多次,而且一个片段中可以有多插入点存在镜像。一 1064 | 个插入点的镜像可以有一个默认值。只需要第一个插入点有默认值,镜像插入点会自动拥有 1065 | 这个默认值。 1066 | 1067 | 镜像方便于使用开始结束标签,例如,Tex的 'begin' 和 'end' 标签,XML 和 HTML 的标 1068 | 签,还有C的 #ifndef 代码块。这里有一些片段的例子。 1069 | 1070 | ------------------- SNIP ------------------- 1071 | snippet env 1072 | \begin{${1:enumerate}} 1073 | $0 1074 | \end{$1} 1075 | endsnippet 1076 | ------------------- SNAP ------------------- 1077 | envitemize -> 1078 | \begin{itemize} 1079 | 1080 | \end{itemize} 1081 | 1082 | ------------------- SNIP ------------------- 1083 | snippet ifndef 1084 | #ifndef ${1:SOME_DEFINE} 1085 | #define $1 1086 | $0 1087 | #endif /* $1 */ 1088 | endsnippet 1089 | ------------------- SNAP ------------------- 1090 | ifndefWIN32 -> 1091 | #ifndef WIN32 1092 | #define WIN32 1093 | 1094 | #endif /* WIN32 */ 1095 | 1096 | 1097 | 4.7 转换 *UltiSnips-transformations* 1098 | -------- 1099 | 1100 | Note: 转换有一些难以理解,所以这章被分成了两部分。第一部分描述转换及其与法,第二 1101 | 部分用一些演示说明了转换。 1102 | 1103 | 转换就像镜像一样,但又不是仅仅从原位置逐字复制,一个正则表达式将匹配一个插入点的 1104 | 内容,然后一个转换被应用到匹配的部分。UltiSnips中的转换功能和它的语法和TextMate 1105 | 的转换特别相似。 1106 | 1107 | 一个转换的语法大致如下: > 1108 | ${ 1111 | tab_stop_no - 要引用的插入点的编号 1112 | regular_expression - 引用的插入点中和正则表达式匹配的内容 1113 | replacement - 替换字符串,下面详细说明 1114 | options - 正则表达式的选项 1115 | 1116 | 选项可以是下面几个字符的任何组合: > 1117 | g - 全局替换 1118 | 默认情况下,只有第一个匹配正则表达式的部分会被替换。使用这个选项,所有 1119 | 匹配的内容都会被替换。 1120 | i - 不区分大小写 1121 | 默认情况下,正则表达式匹配是大小写敏感的。使用这个选项,正则表达式的 1122 | 匹配将在忽略大小写的情况下完成。 1123 | m - 多行模式 1124 | 默认情况下,'^'和'$'特殊字符仅引用于这个字符串的开始和结束。所以如果你 1125 | 选择了多行模式,转换将是把他们作为一个完整的单行字符串处理。使用这个选 1126 | 项,'^'和'$'特殊字符匹配一个字符串中的任何行的开始和结束(使 1127 | 换行符分隔 - '\n') 1128 | By default, the '^' and '$' special characters only apply to the 1129 | start and end of the entire string; so if you select multiple lines, 1130 | transformations are made on them entirely as a whole single line 1131 | string. With this option, '^' and '$' special characters match the 1132 | start or end of any line within a string ( separated by newline 1133 | character - '\n' ). 1134 | a - ascii 转换 1135 | 默认情况下,转换在原始的utf-8编码下工作。使用这个选项,匹配将会在相应 1136 | 的 ASCII 字符中完成,例如,'à' 将会变成 'a',这个选项需要python模块 1137 | 'unidecode'的支持 1138 | 1139 | 正则表达式的语法已经超出了本文档的范围。内部使用的是python正则表达式,所以 're' 1140 | 模块可以作为一个指导,查看http://docs.python.org/library/re.html。 1141 | 1142 | 替换字符的语法是唯一的。下一段将描述它的细节。 1143 | 1144 | 4.7.1 替换字符串: *UltiSnips-replacement-string* 1145 | 1146 | 替换字符串可以包含 $编号 的变量,例如,$1,表示正则表达式中的(匹配)组。$0 变量 1147 | 是特殊的用来产生整个匹配。替换字符串也可以包括特殊的转义序列: > 1148 | \u - 大写下一个字符 1149 | \l - 小写下一个字符 1150 | \U - 大写所有 \E 之前的字符 1151 | \L - 小写所有 \E 值钱的字符 1152 | \E - End upper or lowercase started with \L or \U 1153 | \n - 一个新行 1154 | \t - 一个换行符 1155 | 1156 | 最终,替换字符串可以包含有条件的替换,通过使用这样的语法(?no:text:other text)。 1157 | 它的意思是,如果组 $编号 不匹配,就插入 "text",否则插入"other text"。"other text" 1158 | 是可选的,而且如果没有提供默认值就是空字符串,""。这个特性很强大。它允许你添加可 1159 | 选的文本到片段中。 1160 | 1161 | 1162 | 4.7.2 演示: *UltiSnips-demos* 1163 | 1164 | 转换是非常强大的,但是往往语法非常复杂。希望下面的演示能说明转换功能功能。 1165 | 1166 | 演示: 大写一个字符 1167 | ------------------- SNIP ------------------- 1168 | snippet title "Title transformation" 1169 | ${1:a text} 1170 | ${1/\w+\s*/\u$0/} 1171 | endsnippet 1172 | ------------------- SNAP ------------------- 1173 | titlebig small -> 1174 | big small 1175 | Big small 1176 | 1177 | 1178 | 演示: 大写一个字符并全局替换 1179 | ------------------- SNIP ------------------- 1180 | snippet title "Titlelize in the Transformation" 1181 | ${1:a text} 1182 | ${1/\w+\s*/\u$0/g} 1183 | endsnippet 1184 | ------------------- SNAP ------------------- 1185 | titlethis is a title -> 1186 | this is a title 1187 | This Is A Title 1188 | 1189 | 1190 | 演示: ASCII转码 1191 | ------------------- SNIP ------------------- 1192 | snippet ascii "Replace non ascii chars" 1193 | ${1: an accentued text} 1194 | ${1/.*/$0/a} 1195 | endsnippet 1196 | ------------------- SNAP ------------------- 1197 | asciià la pêche aux moules 1198 | à la pêche aux moules 1199 | a la peche aux moules 1200 | 1201 | 1202 | 演示: 正则表达式分组 1203 | 这是一个只能的c风格的printf片段,第二个插入点只有在第一个插入点中存在格式 1204 | 化字符(%)的时候才出现。 1205 | 1206 | ------------------- SNIP ------------------- 1207 | snippet printf 1208 | printf("${1:%s}\n"${1/([^%]|%%)*(%.)?.*/(?2:, :\);)/}$2${1/([^%]|%%)*(%.)?.*/(?2:\);)/} 1209 | endsnippet 1210 | ------------------- SNAP ------------------- 1211 | printfHello // End of line -> 1212 | printf("Hello\n"); // End of line 1213 | 1214 | But 1215 | printfA is: %sA // End of line -> 1216 | printf("A is: %s\n", A); // End of line 1217 | 1218 | 1219 | 在捆绑的片段中,还有很多使用转换的例子 1220 | There are many more examples of what can be done with transformations in the 1221 | bundled snippets. 1222 | 1223 | 1224 | 4.8 清除片段 *UltiSnips-clearing-snippets* 1225 | 1226 | 要从当前文件类型中移除片段,使用'clearsnippets'指令。 1227 | 1228 | ------------------- SNIP ------------------- 1229 | clearsnippets 1230 | ------------------- SNAP ------------------- 1231 | 1232 | 'clearsnippets' 会移除所有优先级低于当前片段的片段。举个例子,下面的例子中会移除 1233 | 所有优先级 <= 1 的片段,尽管片段定义在'clearsnippets'之后。 1234 | 1235 | ------------------- SNIP ------------------- 1236 | priority 1 1237 | clearsnippets 1238 | 1239 | priority -1 1240 | snippet example "Cleared example" 1241 | This will never be expanded. 1242 | endsnippet 1243 | ------------------- SNAP ------------------- 1244 | 1245 | 要溢出一个或多个特定的片段,提供片段的触发器作为'clearsnippets'命令的参数,下面 1246 | 的例子就会移除触发器为'trigger1'和'trigger2'的片段。 1247 | 1248 | ------------------- SNIP ------------------- 1249 | clearsnippets trigger1 trigger2 1250 | ------------------- SNAP ------------------- 1251 | 1252 | 1253 | 4.9 上下文片段 *UltiSnips-context-snippets* 1254 | 1255 | 上下文片段可以通过在片段定义的时候使用'e'选项来定义。 1256 | 1257 | 这种情况下,片段应该使用这种语法定义: > 1258 | 1259 | snippet tab_trigger "description" "expression" options 1260 | 1261 | 上下文可以使用这种语法使用特殊的头定义: > 1262 | 1263 | context "expression" 1264 | snippet tab_trigger "description" options 1265 | 1266 | 'expression' 可以是任何python表达式。如果'expression'执行结果为'True',那么 1267 | 表达式必须使用双引号括起来。 1268 | If 'expression' evaluates to 'True', then this snippet will be chosen for 1269 | expansion. 1270 | 1271 | 下列的pytyon模块会被自动导入到'expression'执行的环境: 're', 'os', 'vim', 1272 | 'string', 'random' 1273 | 1274 | 全局变量 `snip`将会提供下列属性: 1275 | 'snip.window' - 'vim.current.window' 的别名 1276 | 'snip.buffer' - 'vim.current.window.buffer' 的别名 1277 | 'snip.cursor' - 光标对象,就像 'vim.current.window.cursor', 但是从0开始索引, 1278 | 而且有下面的内容 1279 | 其他方法: 1280 | - 'preserve()' - 执行前后跳跃动作的特殊方法 1281 | - 'set(line, column)' - 将光标设置到指定的行和列 1282 | - 'to_vim_cursor()' - 返回索引从1开始的光标,适合用来设定 1283 | 'vim.current.window.cursor' 1284 | 'snip.line' 和 'snip.column' - 光标位置的别名,从0开始索引 1285 | 'snip.visual_mode' - ('v', 'V', '^V', 参见 |visual-mode|); 1286 | 'snip.visual_text' - 上次选择模式选择的文本 1287 | 'snip.last_placeholder' - 之前的片段的上一个激活的占位符,有下列特性: 1288 | - 'current_text' - 选中时占位符对应的文本 1289 | - 'start' - placeholder start on the moment of selection; 1290 | - 'end' - placeholder end on the moment of selection; 1291 | 1292 | 1293 | 1294 | ------------------- SNIP ------------------- 1295 | snippet r "return" "re.match('^\s+if err ', snip.buffer[snip.line-1])" be 1296 | return err 1297 | endsnippet 1298 | ------------------- SNAP ------------------- 1299 | 1300 | 只有上一行以'if err'前缀开头,这个片段才会展开为'return err' 1301 | 1302 | Note: 上下文片段优先于非上下文片段。这使得在上下文不匹配的时候,使用非上下文片段 1303 | 作为备选成为可能 1304 | 1305 | ------------------- SNIP ------------------- 1306 | snippet i "if ..." b 1307 | if $1 { 1308 | $2 1309 | } 1310 | endsnippet 1311 | 1312 | snippet i "if err != nil" "re.match('^\s+[^=]*err\s*:?=', snip.buffer[snip.line-1])" be 1313 | if err != nil { 1314 | $1 1315 | } 1316 | endsnippet 1317 | ------------------- SNAP ------------------- 1318 | 1319 | 如果上一行匹配'err :='前缀的话,这个片段被会展开成 'if err != nil',否则默认的 1320 | 'if'片段会被展开。 1321 | 1322 | 将上下文条件转义到一个单独的模块是一个不错的注意,这样它就能被其他UltiSnips用户使 1323 | 用。这样,模块需要使用'global'关键字导入,就像这样: > 1324 | 1325 | ------------------- SNIP ------------------- 1326 | global !p 1327 | import my_utils 1328 | endglobal 1329 | 1330 | snippet , "return ..., nil/err" "my_utils.is_return_argument(snip)" ie 1331 | , `!p if my_utils.is_in_err_condition(): 1332 | snip.rv = "err" 1333 | else: 1334 | snip.rv = "nil"` 1335 | endsnippet 1336 | ------------------- SNAP ------------------- 1337 | 1338 | 只要光标位于返回语句,这个片段才会被展开,然后它将会展开为'err'或'nil',这要看 1339 | 光标处于哪一种if语句中。 1340 | 这个例子中的'is_return_argument' 和 'is_in_err_condition' 是一个叫做 'my_utiils' 1341 | 的自定义python模块的一部分。 1342 | 1343 | 上下文条件可以返回任何值,只要python能将它用于'if'语句,如果被认为是'True',片段 1344 | 就会被展开。'condition' 的真值在片段内部的'snip.context'变量中可用 1345 | 1346 | ------------------- SNIP ------------------- 1347 | snippet + "var +=" "re.match('\s*(.*?)\s*:?=', snip.buffer[snip.line-1])" ie 1348 | `!p snip.rv = snip.context.group(1)` += $1 1349 | endsnippet 1350 | ------------------- SNAP ------------------- 1351 | 1352 | 这个片段会被展开成 'val +=',从'val :='开始。 1353 | (That snippet will expand to 'var1 +=' after line, which begins from 'var1 :='.) 1354 | 1355 | *UltiSnips-capture-placeholder* 1356 | 1357 | 通过使用下面的的技巧,你可以从前一个片段中捕获占位符对应的文本: 1358 | ------------------- SNIP ------------------- 1359 | snippet = "desc" "snip.last_placeholder" Ae 1360 | `!p snip.rv = snip.context.current_text` == nil 1361 | endsnippet 1362 | ------------------- SNAP ------------------- 1363 | 1364 | That snippet will be expanded only if you will replace selected tabstop in 1365 | other snippet (like, as in 'if ${1:var}') and will replace that tabstop by 1366 | tabstop value following by ' == nil'. 1367 | 1368 | 1369 | 4.10 片段行为 *UltiSnips-snippet-actions* 1370 | ------------- 1371 | 1372 | 片段行为是一个特殊的python代码,可以在片段的生命周期的特定的点执行。 1373 | 1374 | 有三种类型的片段行为: 1375 | 1376 | * Pre-expand - 在触发器条件满足后,片段真正被展开前执行。 1377 | * Post-expand - * 在片段被展开之后,插入内容被第一次确认,在跳到第一个插入点之前 1378 | 执行 1379 | * Jump - 在跳到上一个或下一个插入点之后执行 1380 | 1381 | Specified code will be evaluated at stages defined above and same global 1382 | variables and modules will be available that are stated in 1383 | the |UltiSnips-context-snippets| section. 1384 | 1385 | *UltiSnips-buffer-proxy* 1386 | 1387 | Note: special variable called 'snip.buffer' should be used for all buffer 1388 | modifications. Not 'vim.current.buffer' and not 'vim.command("...")', because 1389 | of in that case UltiSnips will not be able to track changes in buffer from 1390 | actions. 1391 | 1392 | 'snip.buffer' has the same interface as 'vim.current.window.buffer'. 1393 | 1394 | 4.10.1 Pre-expand 行为 *UltiSnips-pre-expand-actions* 1395 | 1396 | Pre-expand actions can be used to match snippet in one location and then 1397 | expand it in the different location. Some useful cases are: correcting 1398 | indentation for snippet; expanding snippet for function declaration in another 1399 | function body with moving expansion point beyond initial function; performing 1400 | extract method refactoring via expanding snippet in different place. 1401 | 1402 | Pre-expand action declared as follows: > 1403 | pre_expand "python code here" 1404 | snippet ... 1405 | endsnippet 1406 | 1407 | Buffer can be modified in pre-expand action code through variable called 1408 | 'snip.buffer', snippet expansion position will be automatically adjusted. 1409 | 1410 | If cursor line (where trigger was matched) need to be modified, then special 1411 | variable method 'snip.cursor.set(line, column)' must be called with the 1412 | desired cursor position. In that case UltiSnips will not remove any matched 1413 | trigger text and it should be done manually in action code. 1414 | 1415 | To addition to the scope variables defined above 'snip.visual_content' will be 1416 | also declared and will contain text that was selected before snippet expansion 1417 | (similar to $VISUAL placeholder). 1418 | 1419 | Following snippet will be expanded at 4 spaces indentation level no matter 1420 | where it was triggered. 1421 | 1422 | ------------------- SNIP ------------------- 1423 | pre_expand "snip.buffer[snip.line] = ' '*4; snip.cursor.set(line, 4)" 1424 | snippet d 1425 | def $1(): 1426 | $0 1427 | endsnippet 1428 | ------------------- SNAP ------------------- 1429 | 1430 | Following snippet will move the selected code to the end of file and create 1431 | new method definition for it: 1432 | 1433 | ------------------- SNIP ------------------- 1434 | pre_expand "del snip.buffer[snip.line]; snip.buffer.append(''); snip.cursor.set(len(snip.buffer)-1, 0)" 1435 | snippet x 1436 | def $1(): 1437 | ${2:${VISUAL}} 1438 | endsnippet 1439 | ------------------- SNAP ------------------- 1440 | 1441 | 4.10.2 Post-expand 行为 *UltiSnips-post-expand-actions* 1442 | 1443 | Post-expand actions can be used to perform some actions based on the expanded 1444 | snippet text. Some cases are: code style formatting (e.g. inserting newlines 1445 | before and after method declaration), apply actions depending on python 1446 | interpolation result. 1447 | 1448 | Post-expand action declared as follows: > 1449 | post_expand "python code here" 1450 | snippet ... 1451 | endsnippet 1452 | 1453 | Buffer can be modified in post-expand action code through variable called 1454 | 'snip.buffer', snippet expansion position will be automatically adjusted. 1455 | 1456 | Variables 'snip.snippet_start' and 'snip.snippet_end' will be defined at the 1457 | action code scope and will point to positions of the start and end of expanded 1458 | snippet accordingly in the form '(line, column)'. 1459 | 1460 | Note: 'snip.snippet_start' and 'snip.snippet_end' will automatically adjust to 1461 | the correct positions if post-action will insert or delete lines before 1462 | expansion. 1463 | 1464 | Following snippet will expand to method definition and automatically insert 1465 | additional newline after end of the snippet. It's very useful to create a 1466 | function that will insert as many newlines as required in specific context. 1467 | 1468 | ------------------- SNIP ------------------- 1469 | post_expand "snip.buffer[snip.snippet_end[0]+1:snip.snippet_end[0]+1] = ['']" 1470 | snippet d "Description" b 1471 | def $1(): 1472 | $2 1473 | endsnippet 1474 | ------------------- SNAP ------------------- 1475 | 1476 | 4.10.3 Post-jump 行为 *UltiSnips-post-jump-actions* 1477 | 1478 | Post-jump actions can be used to trigger some code based on user input into 1479 | the placeholders. Notable use cases: expand another snippet after jump or 1480 | anonymous snippet after last jump (e.g. perform move method refactoring and 1481 | then insert new method invokation); insert heading into TOC after last jump. 1482 | 1483 | Jump-expand action declared as follows: > 1484 | post_jump "python code here" 1485 | snippet ... 1486 | endsnippet 1487 | 1488 | Buffer can be modified in post-jump action code through variable called 1489 | 'snip.buffer', snippet expansion position will be automatically adjusted. 1490 | 1491 | Next variables and methods will be also defined in the action code scope: 1492 | * 'snip.tabstop' - number of tabstop jumped onto; 1493 | * 'snip.jump_direction' - '1' if jumped forward and '-1' otherwise; 1494 | * 'snip.tabstops' - list with tabstop objects, see above; 1495 | * 'snip.snippet_start' - (line, column) of start of the expanded snippet; 1496 | * 'snip.snippet_end' - (line, column) of end of the expanded snippet; 1497 | * 'snip.expand_anon()' - alias for 'UltiSnips_Manager.expand_anon()'; 1498 | 1499 | Tabstop object has several useful properties: 1500 | * 'start' - (line, column) of the starting position of the tabstop (also 1501 | accessible as 'tabstop.line' and 'tabstop.col'). 1502 | * 'end' - (line, column) of the ending position; 1503 | * 'current_text' - text inside the tabstop. 1504 | 1505 | Following snippet will insert section in the Table of Contents in the vim-help 1506 | file: 1507 | 1508 | ------------------- SNIP ------------------- 1509 | post_jump "if snip.tabstop == 0: insert_toc_item(snip.tabstops[1], snip.buffer)" 1510 | snippet s "section" b 1511 | `!p insert_delimiter_0(snip, t)`$1`!p insert_section_title(snip, t)` 1512 | `!p insert_delimiter_1(snip, t)` 1513 | $0 1514 | endsnippet 1515 | ------------------- SNAP ------------------- 1516 | 1517 | 'insert_toc_item' will be called after first jump and will add newly entered 1518 | section into the TOC for current file. 1519 | 1520 | Note: It is also possible to trigger snippet expansion from the jump action. 1521 | In that case method 'snip.cursor.preserve()' should be called, so UltiSnips 1522 | will know that cursor is already at the required position. 1523 | 1524 | Following example will insert method call at the end of file after user jump 1525 | out of method declaration snippet. 1526 | 1527 | ------------------- SNIP ------------------- 1528 | global !p 1529 | def insert_method_call(name): 1530 | vim.command('normal G') 1531 | snip.expand_anon(name + '($1)\n') 1532 | endglobal 1533 | 1534 | post_jump "if snip.tabstop == 0: insert_method_call(snip.tabstops[1].current_text)" 1535 | snippet d "method declaration" b 1536 | def $1(): 1537 | $2 1538 | endsnippet 1539 | ------------------- SNAP ------------------- 1540 | 1541 | 4.11 自动触发 *UltiSnips-autotrigger* 1542 | ------------- 1543 | 1544 | Note: vim至少要有7.4.214版本才支持这个特性。 1545 | 1546 | 许多的语言只能出现在特定额地方,所以可以使用非手动触发的片段。 1547 | 1548 | 片段可以被标记为自动触发的,通过在定义片段的时候使用特殊的 'A' 选项。 1549 | 1550 | 在片段被定义为自动触发后,每次键入都会检查片段条件,一旦条件满足,片段就会被触发。 1551 | 1552 | *Warning:* 使用这个特性可能严重地拖慢vim的速度。如果你发现了这个问题,在这里提交 1553 | 一个issue,github.com/SirVer/UltiSnips。 1554 | 1555 | 考虑下面的片段,这可能对Go语言编程是有帮助的。 1556 | ------------------- SNIP ------------------- 1557 | snippet "^p" "package" rbA 1558 | package ${1:main} 1559 | endsnippet 1560 | 1561 | snippet "^m" "func main" rbA 1562 | func main() { 1563 | $1 1564 | } 1565 | endsnippet 1566 | ------------------- SNAP ------------------- 1567 | 1568 | 当 "p" 字符出现在一行的开始,它将会自动展开成 "package main"。"m" 字符也一样,不 1569 | 需要手动在 "m" 之后按触发键。 1570 | 1571 | ============================================================================== 1572 | 5. UltiSnips 和其他插件 *UltiSnips-other-plugins* 1573 | 1574 | 5.1 已经集成的插件 *UltiSnips-integrations* 1575 | ------------------ 1576 | 1577 | UltiSnips已经内置支持了一些通用的插件,还有一些其他的插件意识到了UltiSnips,并使 1578 | 用它来提升用户体验。这是一个不完整的列表,如果你希望你的插件在这里列出,只需要发 1579 | 送一个 pull request。 1580 | 1581 | *UltiSnips-snipMate* 1582 | 1583 | snipMate - UltiSnips是snipMate的替代品,并兼容snipMate。它有着更多的特性,所以移 1584 | 植snippet片段任然是一个好主意。但是切换并不是完全无痛的。UltiSnips正在努力真正 1585 | 的兼容snipMate,比如,递归的插入点在 snipMate 中是不受支持的(但是在UltiSnips中当 1586 | 然要支持)。 1587 | 1588 | YouCompleteMe - 为 UltiSnips 提供开箱即用的支持,它为snippet片段提供了一个非常好 1589 | 的补全对话框 1590 | 1591 | neocomplete - UltiSnips 使用了 neocomplete 的一部分源码,因此提供开箱即用的补全 1592 | 对话框支持 1593 | 1594 | unite - UltiSnips使用了unite的部分源码。例如你可以这样使用它,把下面的方法和映射 1595 | 添加到你的 vimrc: > 1596 | 1597 | function! UltiSnipsCallUnite() 1598 | Unite -start-insert -winheight=100 -immediately -no-empty ultisnips 1599 | return '' 1600 | endfunction 1601 | 1602 | inoremap =(pumvisible()? "\C-E>":"")=UltiSnipsCallUnite() 1603 | nnoremap a=(pumvisible()? "\C-E>":"")=UltiSnipsCallUnite() 1604 | 1605 | 不论是插入不是还是普通模式,当你按下 你将会打开一个unite界面,里面是匹配的 1606 | snippet片段。按下回车键将会展开响应的snippet片段。如果只有一个片段匹配光标前的 1607 | 文本,片段将会在你按下 的时候就展开。 1608 | 1609 | Supertab - UltiSnips内置了对Supertab的支持。只需要使用两个插件的足够新的版本,使 1610 | 用 将既能展开一个snippet片段,也能按照 Supertab 的定义工作。 1611 | 1612 | 5.2 扩展 UltiSnips *UltiSnips-extending* 1613 | ------------------ 1614 | 1615 | UltiSnips允许其他插件动态添加snippet片段。因为UltiSnips由python开发,所以整合也是 1616 | 基于python的。可以在 `test.py` 找到一个小例子,搜索 AddNewSnippetSource。如果你 1617 | 将UltiSnips和你的插件做了整合,请在github上联系我们,以便我们将其加入到文档中。 1618 | 1619 | ============================================================================= 1620 | 6. 帮助我们 *UltiSnips-helping* 1621 | 1622 | UltiSnips 需要vim社区的帮助来持续改进。请考虑加入我们的工作,通过提供新的特性或 1623 | 提交bug报告。 1624 | 1625 | * 在 GitHub 上克隆这个仓库 (git clone * git@github.com:SirVer/ultisnips.git),做 1626 | 出你自己的修改并在 GitHub 上提交一个 pull request。 1627 | * 制作一个补丁,提交一个bug请求(request)或特性请求(request) (如下) 并附上这个补丁 1628 | 1629 | 你可以通过在我们的 issue tracker 上提交bug或修复bug来做出贡献: 1630 | https://github.com/sirver/ultisnips/issues 1631 | 1632 | ============================================================================= 1633 | 7. 贡献者 *UltiSnips-contributors* 1634 | 1635 | UltiSnips由Holger在2009年6月启动并维护到2015年12月(@SirVer SirVer@gmx.de)。它现在 1636 | 由 Stanislav Seletskiy 维护(@seletskiy)。 1637 | 1638 | This is the list of contributors pre-git in chronological order. For a full 1639 | list of contributors take the union of this set and the authors according to 1640 | git log. 1641 | 1642 | JCEB - Jan Christoph Ebersbach 1643 | Michael Henry 1644 | Chris Chambers 1645 | Ryan Wooden 1646 | rupa - Rupa Deadwyler 1647 | Timo Schmiade 1648 | blueyed - Daniel Hahler 1649 | expelledboy - Anthony Jackson 1650 | allait - Alexey Bezhan 1651 | peacech - Charles Gunawan 1652 | guns - Sung Pae 1653 | shlomif - Shlomi Fish 1654 | pberndt - Phillip Berndt 1655 | thanatermesis-elive - Thanatermesis 1656 | rico-ambiescent - Rico Sta. Cruz 1657 | Cody Frazer 1658 | suy - Alejandro Exojo 1659 | grota - Giuseppe Rota 1660 | iiijjjii - Jim Karsten 1661 | fgalassi - Federico Galassi 1662 | lucapette 1663 | Psycojoker - Laurent Peuch 1664 | aschrab - Aaron Schrab 1665 | stardiviner - NagatoPain 1666 | skeept - Jorge Rodrigues 1667 | buztard 1668 | stephenmckinney - Steve McKinney 1669 | Pedro Algarvio - s0undt3ch 1670 | Eric Van Dewoestine - ervandew 1671 | Matt Patterson - fidothe 1672 | Mike Morearty - mmorearty 1673 | Stanislav Golovanov - JazzCore 1674 | David Briscoe - DavidBriscoe 1675 | Keith Welch - paralogiki 1676 | Zhao Cai - zhaocai 1677 | John Szakmeister - jszakmeister 1678 | Jonas Diemer - diemer 1679 | Romain Giot - rgiot 1680 | Sergey Alexandrov - taketwo 1681 | Brian Mock - saikobee 1682 | Gernot Höflechner - LFDM 1683 | Marcelo D Montu - mMontu 1684 | Karl Yngve Lervåg - lervag 1685 | Pedro Ferrari - petobens 1686 | Ches Martin - ches 1687 | Christian - Oberon00 1688 | Andrew Ruder - aeruder 1689 | Mathias Fußenegger - mfussenegger 1690 | Kevin Ballard - kballard 1691 | Ahbong Chang - cwahbong 1692 | Glenn Griffin - ggriffiniii 1693 | Michael - Pyrohh 1694 | Stanislav Seletskiy - seletskiy 1695 | Pawel Palucki - ppalucki 1696 | Dettorer - dettorer 1697 | Zhao Jiarong - kawing-chiu 1698 | Ye Ding - dyng 1699 | Greg Hurrell - wincent 1700 | 1701 | vim:tw=78:ts=8:ft=help:norl: 1702 | -------------------------------------------------------------------------------- /doc/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linfee/ultisnips-zh-doc/21205695b0de754e70b4bca0bab266cd0d40db23/doc/demo.gif -------------------------------------------------------------------------------- /doc/examples/autojump-if-empty/README.md: -------------------------------------------------------------------------------- 1 | # Autojump from tabstop when it's empty 2 | 3 | UltiSnips offers enough API to support automatic jump from one tabstop to 4 | another when some condition is encountered. 5 | 6 | One example of applying that behaviour is jump on the next placeholder when 7 | current becomes empty when user types `` or another erase sequence when 8 | tabstop is active. 9 | 10 | Let's imagine, that we have following snippet: 11 | 12 | ![snippet](https://raw.githubusercontent.com/SirVer/ultisnips/master/doc/examples/autojump-if-empty/snippet.gif) 13 | 14 | First placeholder, surrounded by braces, can be erased by user, but then 15 | surrounding quotes will left untouched, and user should remove quotes and 16 | one space, and only then jump to next placeholder, that equals to **5** total 17 | keypresses: BackSpace (erase placeholder), BackSpace and 18 | Delete (erase braces), Delete (erase space), 19 | Ctrl+J (jump to next placeholder). 20 | 21 | However, with UltiSnips, it can be done via only one keypress: 22 | BackSpace: 23 | 24 | ![demo](https://raw.githubusercontent.com/SirVer/ultisnips/master/doc/examples/autojump-if-empty/demo.gif) 25 | 26 | ## Implementation 27 | 28 | Using awesome [vim-pythonx 29 | library](https://github.com/reconquest/vim-pythonx/blob/master/pythonx/px/snippets.py), 30 | which provides set of functions to make coding little bit easier. 31 | 32 | ``` 33 | global !p 34 | import px.snippets 35 | endglobal 36 | 37 | global !p 38 | # This function will jump to next placeholder when first is empty. 39 | def jump_to_second_when_first_is_empty(snip): 40 | if px.snippets.get_jumper_position(snip) == 1: 41 | if not px.snippets.get_jumper_text(snip): 42 | px.snippets.advance_jumper(snip) 43 | 44 | # This function will clean up first placeholder when this is empty. 45 | def clean_first_placeholder(snip): 46 | # Jumper is a helper for performing jumps in UltiSnips. 47 | px.snippets.make_jumper(snip) 48 | 49 | if snip.tabstop == 2: 50 | line = snip.buffer[snip.cursor[0]] 51 | snip.buffer[snip.cursor[0]] = \ 52 | line[:snip.tabstops[1].start[1]-2] + \ 53 | line[snip.tabstops[1].end[1]+1:] 54 | snip.cursor.set( 55 | snip.cursor[0], 56 | snip.cursor[1] - 3, 57 | ) 58 | endglobal 59 | 60 | context "px.snippets.make_context(snip)" 61 | post_jump "clean_first_placeholder(snip)" 62 | snippet x "Description" b 63 | `!p jump_to_second_when_first_is_empty(snip) 64 | `func (${1:blah}) $2() { 65 | $3 66 | } 67 | endsnippet 68 | ``` 69 | -------------------------------------------------------------------------------- /doc/examples/autojump-if-empty/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linfee/ultisnips-zh-doc/21205695b0de754e70b4bca0bab266cd0d40db23/doc/examples/autojump-if-empty/demo.gif -------------------------------------------------------------------------------- /doc/examples/autojump-if-empty/snippet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linfee/ultisnips-zh-doc/21205695b0de754e70b4bca0bab266cd0d40db23/doc/examples/autojump-if-empty/snippet.gif -------------------------------------------------------------------------------- /doc/examples/snippets-aliasing/README.md: -------------------------------------------------------------------------------- 1 | # Aliases for snippets 2 | 3 | ![gif](https://raw.githubusercontent.com/SirVer/ultisnips/master/doc/examples/snippets-aliasing/demo.gif) 4 | 5 | Let's imagine we're editing shell file and we need to debug some vars. 6 | 7 | Essentially, we will end up with snippet like that, that will automatically 8 | insert location of the debug statement and variable name. 9 | 10 | Example of that snippet is shown below: 11 | 12 | ``` 13 | snippet pr "print debug" bw 14 | `!p 15 | prefix = t[1] + ": %q\\n' " 16 | prefix = "{}:{}: {}".format( 17 | os.path.basename(px.buffer.get().name), 18 | str(px.cursor.get()[0]), 19 | prefix 20 | ) 21 | `printf 'XXXXXX `!p snip.rv=prefix`$1 >&2 22 | endsnippet 23 | ``` 24 | 25 | Now, we want to use same debug snippet, but dump variable to the file. 26 | How can we do it? 27 | 28 | Simple, declare new snippet in that way: 29 | 30 | ``` 31 | post_jump "px.snippets.expand(snip)" 32 | snippet pd "Description" b 33 | pr$1 >${2:/tmp/debug} 34 | endsnippet 35 | ``` 36 | 37 | This snippet will expand `pr` snippet automatically (note `pr$1` part) after 38 | jumping to the first placeholder (jump will be done automatically by UltiSnips 39 | engine). 40 | 41 | `px.snippets.expand(snip)` is declared in that way: 42 | 43 | ```python 44 | def expand(snip, jump_pos=1): 45 | if snip.tabstop != jump_pos: 46 | return 47 | 48 | vim.eval('feedkeys("\=UltiSnips#ExpandSnippet()\")') 49 | ``` 50 | 51 | `px.buffer.get()` and `px.cursor.get()` are simple helpers for the 52 | `vim.current.window.buffer` and `vim.current.window.cursor`. 53 | -------------------------------------------------------------------------------- /doc/examples/snippets-aliasing/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linfee/ultisnips-zh-doc/21205695b0de754e70b4bca0bab266cd0d40db23/doc/examples/snippets-aliasing/demo.gif -------------------------------------------------------------------------------- /doc/examples/tabstop-generation/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic tabstop generation 2 | 3 | ![gif](https://raw.githubusercontent.com/SirVer/ultisnips/master/doc/examples/tabstop-generation/demo.gif) 4 | 5 | UltiSnips at the present day is more than snippet engine. It's more like 6 | constructor, where you can implement some complex features without prior 7 | feature implementation in the snippet by itself. 8 | 9 | One of that features is dynamic tabstop generation. 10 | 11 | Consider case, where you want set of snippets for inserting latex rows of 12 | various lengths. No-brainer solution is just implement snippet for every 13 | row length you're possible will want, like this: 14 | 15 | ``` 16 | snippet tr9 "LaTeX table row of length nine" 17 | $1 & $2 & $3 & $4 & $5 & $6 & $7 & $8 & $9 18 | endsnippet 19 | ``` 20 | 21 | But soon it becomes a burden to maintain that kind of snippets. 22 | 23 | Gladly, tabstops can be generated by using anonymous snippet expansion: 24 | 25 | ``` 26 | global !p 27 | def create_row_placeholders(snip): 28 | # retrieving singlee line from current string and treat it like tabstops 29 | # count 30 | placeholders_amount = int(snip.buffer[snip.line].strip()) 31 | 32 | # erase current line 33 | snip.buffer[snip.line] = '' 34 | 35 | # create anonymous snippet with expected content and number of tabstops 36 | anon_snippet_body = ' & '.join(['$' + str(i+1) 37 | for i in range(placeholders_amount)]) 38 | 39 | # expand anonymous snippet 40 | snip.expand_anon(anon_snippet_body) 41 | endglobal 42 | 43 | post_jump "create_row_placeholders(snip)" 44 | snippet "tr(\d+)" "latex table row variable" br 45 | `!p snip.rv = match.group(1)` 46 | endsnippet 47 | ``` 48 | 49 | Snippet is declared via regular expression and will expand to any required 50 | number of fields in row. 51 | -------------------------------------------------------------------------------- /doc/examples/tabstop-generation/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Linfee/ultisnips-zh-doc/21205695b0de754e70b4bca0bab266cd0d40db23/doc/examples/tabstop-generation/demo.gif -------------------------------------------------------------------------------- /doc/tags: -------------------------------------------------------------------------------- 1 | :UltiSnipsAddFiletypes UltiSnips.txt /*:UltiSnipsAddFiletypes* 2 | :UltiSnipsAddFiletypes UltiSnips_zh.txt /*:UltiSnipsAddFiletypes* 3 | :UltiSnipsEdit UltiSnips.txt /*:UltiSnipsEdit* 4 | :UltiSnipsEdit UltiSnips_zh.txt /*:UltiSnipsEdit* 5 | UltiSnips UltiSnips.txt /*UltiSnips* 6 | UltiSnips UltiSnips_zh.txt /*UltiSnips* 7 | UltiSnips#AddSnippetWithPriority UltiSnips.txt /*UltiSnips#AddSnippetWithPriority* 8 | UltiSnips#AddSnippetWithPriority UltiSnips_zh.txt /*UltiSnips#AddSnippetWithPriority* 9 | UltiSnips#Anon UltiSnips.txt /*UltiSnips#Anon* 10 | UltiSnips#Anon UltiSnips_zh.txt /*UltiSnips#Anon* 11 | UltiSnips#SnippetsInCurrentScope UltiSnips.txt /*UltiSnips#SnippetsInCurrentScope* 12 | UltiSnips#SnippetsInCurrentScope UltiSnips_zh.txt /*UltiSnips#SnippetsInCurrentScope* 13 | UltiSnips-acknowledgments UltiSnips.txt /*UltiSnips-acknowledgments* 14 | UltiSnips-acknowledgments UltiSnips_zh.txt /*UltiSnips-acknowledgments* 15 | UltiSnips-adding-snippets UltiSnips.txt /*UltiSnips-adding-snippets* 16 | UltiSnips-adding-snippets UltiSnips_zh.txt /*UltiSnips-adding-snippets* 17 | UltiSnips-autotrigger UltiSnips.txt /*UltiSnips-autotrigger* 18 | UltiSnips-autotrigger UltiSnips_zh.txt /*UltiSnips-autotrigger* 19 | UltiSnips-buffer-proxy UltiSnips.txt /*UltiSnips-buffer-proxy* 20 | UltiSnips-buffer-proxy UltiSnips_zh.txt /*UltiSnips-buffer-proxy* 21 | UltiSnips-capture-placeholder UltiSnips.txt /*UltiSnips-capture-placeholder* 22 | UltiSnips-capture-placeholder UltiSnips_zh.txt /*UltiSnips-capture-placeholder* 23 | UltiSnips-character-escaping UltiSnips.txt /*UltiSnips-character-escaping* 24 | UltiSnips-character-escaping UltiSnips_zh.txt /*UltiSnips-character-escaping* 25 | UltiSnips-clearing-snippets UltiSnips.txt /*UltiSnips-clearing-snippets* 26 | UltiSnips-clearing-snippets UltiSnips_zh.txt /*UltiSnips-clearing-snippets* 27 | UltiSnips-commands UltiSnips.txt /*UltiSnips-commands* 28 | UltiSnips-commands UltiSnips_zh.txt /*UltiSnips-commands* 29 | UltiSnips-context-snippets UltiSnips.txt /*UltiSnips-context-snippets* 30 | UltiSnips-context-snippets UltiSnips_zh.txt /*UltiSnips-context-snippets* 31 | UltiSnips-contributors UltiSnips.txt /*UltiSnips-contributors* 32 | UltiSnips-contributors UltiSnips_zh.txt /*UltiSnips-contributors* 33 | UltiSnips-custom-autocommands UltiSnips.txt /*UltiSnips-custom-autocommands* 34 | UltiSnips-custom-autocommands UltiSnips_zh.txt /*UltiSnips-custom-autocommands* 35 | UltiSnips-demos UltiSnips.txt /*UltiSnips-demos* 36 | UltiSnips-demos UltiSnips_zh.txt /*UltiSnips-demos* 37 | UltiSnips-description UltiSnips.txt /*UltiSnips-description* 38 | UltiSnips-description UltiSnips_zh.txt /*UltiSnips-description* 39 | UltiSnips-extending UltiSnips.txt /*UltiSnips-extending* 40 | UltiSnips-extending UltiSnips_zh.txt /*UltiSnips-extending* 41 | UltiSnips-functions UltiSnips.txt /*UltiSnips-functions* 42 | UltiSnips-functions UltiSnips_zh.txt /*UltiSnips-functions* 43 | UltiSnips-globals UltiSnips.txt /*UltiSnips-globals* 44 | UltiSnips-globals UltiSnips_zh.txt /*UltiSnips-globals* 45 | UltiSnips-helping UltiSnips.txt /*UltiSnips-helping* 46 | UltiSnips-helping UltiSnips_zh.txt /*UltiSnips-helping* 47 | UltiSnips-installnupdate UltiSnips.txt /*UltiSnips-installnupdate* 48 | UltiSnips-installnupdate UltiSnips_zh.txt /*UltiSnips-installnupdate* 49 | UltiSnips-integrations UltiSnips.txt /*UltiSnips-integrations* 50 | UltiSnips-integrations UltiSnips_zh.txt /*UltiSnips-integrations* 51 | UltiSnips-interpolation UltiSnips.txt /*UltiSnips-interpolation* 52 | UltiSnips-interpolation UltiSnips_zh.txt /*UltiSnips-interpolation* 53 | UltiSnips-mirrors UltiSnips.txt /*UltiSnips-mirrors* 54 | UltiSnips-mirrors UltiSnips_zh.txt /*UltiSnips-mirrors* 55 | UltiSnips-other-plugins UltiSnips.txt /*UltiSnips-other-plugins* 56 | UltiSnips-other-plugins UltiSnips_zh.txt /*UltiSnips-other-plugins* 57 | UltiSnips-placeholders UltiSnips.txt /*UltiSnips-placeholders* 58 | UltiSnips-placeholders UltiSnips_zh.txt /*UltiSnips-placeholders* 59 | UltiSnips-plaintext-snippets UltiSnips.txt /*UltiSnips-plaintext-snippets* 60 | UltiSnips-plaintext-snippets UltiSnips_zh.txt /*UltiSnips-plaintext-snippets* 61 | UltiSnips-post-expand-actions UltiSnips.txt /*UltiSnips-post-expand-actions* 62 | UltiSnips-post-expand-actions UltiSnips_zh.txt /*UltiSnips-post-expand-actions* 63 | UltiSnips-post-jump-actions UltiSnips.txt /*UltiSnips-post-jump-actions* 64 | UltiSnips-post-jump-actions UltiSnips_zh.txt /*UltiSnips-post-jump-actions* 65 | UltiSnips-pre-expand-actions UltiSnips.txt /*UltiSnips-pre-expand-actions* 66 | UltiSnips-pre-expand-actions UltiSnips_zh.txt /*UltiSnips-pre-expand-actions* 67 | UltiSnips-python UltiSnips.txt /*UltiSnips-python* 68 | UltiSnips-python UltiSnips_zh.txt /*UltiSnips-python* 69 | UltiSnips-python-module-path UltiSnips.txt /*UltiSnips-python-module-path* 70 | UltiSnips-python-module-path UltiSnips_zh.txt /*UltiSnips-python-module-path* 71 | UltiSnips-python-warning UltiSnips.txt /*UltiSnips-python-warning* 72 | UltiSnips-python-warning UltiSnips_zh.txt /*UltiSnips-python-warning* 73 | UltiSnips-replacement-string UltiSnips.txt /*UltiSnips-replacement-string* 74 | UltiSnips-replacement-string UltiSnips_zh.txt /*UltiSnips-replacement-string* 75 | UltiSnips-requirements UltiSnips.txt /*UltiSnips-requirements* 76 | UltiSnips-requirements UltiSnips_zh.txt /*UltiSnips-requirements* 77 | UltiSnips-settings UltiSnips.txt /*UltiSnips-settings* 78 | UltiSnips-settings UltiSnips_zh.txt /*UltiSnips-settings* 79 | UltiSnips-shellcode UltiSnips.txt /*UltiSnips-shellcode* 80 | UltiSnips-shellcode UltiSnips_zh.txt /*UltiSnips-shellcode* 81 | UltiSnips-snipMate UltiSnips.txt /*UltiSnips-snipMate* 82 | UltiSnips-snipMate UltiSnips_zh.txt /*UltiSnips-snipMate* 83 | UltiSnips-snippet-actions UltiSnips.txt /*UltiSnips-snippet-actions* 84 | UltiSnips-snippet-actions UltiSnips_zh.txt /*UltiSnips-snippet-actions* 85 | UltiSnips-snippet-options UltiSnips.txt /*UltiSnips-snippet-options* 86 | UltiSnips-snippet-options UltiSnips_zh.txt /*UltiSnips-snippet-options* 87 | UltiSnips-snippet-search-path UltiSnips.txt /*UltiSnips-snippet-search-path* 88 | UltiSnips-snippet-search-path UltiSnips_zh.txt /*UltiSnips-snippet-search-path* 89 | UltiSnips-syntax UltiSnips.txt /*UltiSnips-syntax* 90 | UltiSnips-syntax UltiSnips_zh.txt /*UltiSnips-syntax* 91 | UltiSnips-tabstops UltiSnips.txt /*UltiSnips-tabstops* 92 | UltiSnips-tabstops UltiSnips_zh.txt /*UltiSnips-tabstops* 93 | UltiSnips-transformations UltiSnips.txt /*UltiSnips-transformations* 94 | UltiSnips-transformations UltiSnips_zh.txt /*UltiSnips-transformations* 95 | UltiSnips-trigger-functions UltiSnips.txt /*UltiSnips-trigger-functions* 96 | UltiSnips-trigger-functions UltiSnips_zh.txt /*UltiSnips-trigger-functions* 97 | UltiSnips-triggers UltiSnips.txt /*UltiSnips-triggers* 98 | UltiSnips-triggers UltiSnips_zh.txt /*UltiSnips-triggers* 99 | UltiSnips-using-a-downloaded-packet UltiSnips.txt /*UltiSnips-using-a-downloaded-packet* 100 | UltiSnips-using-a-downloaded-packet UltiSnips_zh.txt /*UltiSnips-using-a-downloaded-packet* 101 | UltiSnips-using-pathogen UltiSnips.txt /*UltiSnips-using-pathogen* 102 | UltiSnips-using-pathogen UltiSnips_zh.txt /*UltiSnips-using-pathogen* 103 | UltiSnips-vimscript UltiSnips.txt /*UltiSnips-vimscript* 104 | UltiSnips-vimscript UltiSnips_zh.txt /*UltiSnips-vimscript* 105 | UltiSnips-visual-placeholder UltiSnips.txt /*UltiSnips-visual-placeholder* 106 | UltiSnips-visual-placeholder UltiSnips_zh.txt /*UltiSnips-visual-placeholder* 107 | UltiSnips-warning-smappings UltiSnips.txt /*UltiSnips-warning-smappings* 108 | UltiSnips-warning-smappings UltiSnips_zh.txt /*UltiSnips-warning-smappings* 109 | UltiSnips.txt UltiSnips.txt /*UltiSnips.txt* 110 | UltiSnips.txt UltiSnips_zh.txt /*UltiSnips.txt* 111 | UltiSnipsEnterFirstSnippet UltiSnips.txt /*UltiSnipsEnterFirstSnippet* 112 | UltiSnipsEnterFirstSnippet UltiSnips_zh.txt /*UltiSnipsEnterFirstSnippet* 113 | UltiSnipsExitLastSnippet UltiSnips.txt /*UltiSnipsExitLastSnippet* 114 | UltiSnipsExitLastSnippet UltiSnips_zh.txt /*UltiSnipsExitLastSnippet* 115 | Warning: UltiSnips.txt /*Warning:* 116 | Warning: UltiSnips_zh.txt /*Warning:* 117 | g:UltiSnipsEditSplit UltiSnips.txt /*g:UltiSnipsEditSplit* 118 | g:UltiSnipsEditSplit UltiSnips_zh.txt /*g:UltiSnipsEditSplit* 119 | g:UltiSnipsEnableSnipMate UltiSnips.txt /*g:UltiSnipsEnableSnipMate* 120 | g:UltiSnipsEnableSnipMate UltiSnips_zh.txt /*g:UltiSnipsEnableSnipMate* 121 | g:UltiSnipsExpandTrigger UltiSnips.txt /*g:UltiSnipsExpandTrigger* 122 | g:UltiSnipsExpandTrigger UltiSnips_zh.txt /*g:UltiSnipsExpandTrigger* 123 | g:UltiSnipsJumpBackwardTrigger UltiSnips.txt /*g:UltiSnipsJumpBackwardTrigger* 124 | g:UltiSnipsJumpBackwardTrigger UltiSnips_zh.txt /*g:UltiSnipsJumpBackwardTrigger* 125 | g:UltiSnipsJumpForwardTrigger UltiSnips.txt /*g:UltiSnipsJumpForwardTrigger* 126 | g:UltiSnipsJumpForwardTrigger UltiSnips_zh.txt /*g:UltiSnipsJumpForwardTrigger* 127 | g:UltiSnipsListSnippets UltiSnips.txt /*g:UltiSnipsListSnippets* 128 | g:UltiSnipsListSnippets UltiSnips_zh.txt /*g:UltiSnipsListSnippets* 129 | g:UltiSnipsSnippetDirectories UltiSnips.txt /*g:UltiSnipsSnippetDirectories* 130 | g:UltiSnipsSnippetDirectories UltiSnips_zh.txt /*g:UltiSnipsSnippetDirectories* 131 | g:UltiSnipsSnippetsDir UltiSnips.txt /*g:UltiSnipsSnippetsDir* 132 | g:UltiSnipsSnippetsDir UltiSnips_zh.txt /*g:UltiSnipsSnippetsDir* 133 | not UltiSnips.txt /*not* 134 | snippet UltiSnips.txt /*snippet* 135 | snippet UltiSnips_zh.txt /*snippet* 136 | snippets UltiSnips.txt /*snippets* 137 | snippets UltiSnips_zh.txt /*snippets* 138 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ulti-zh-doc 2 | =========== 3 | 4 | [UltiSnips](https://github.com/SirVer/ultisnips)是我非常喜欢的vim插件之一, 5 | 它真的非常强大,而且非常流畅。 6 | 7 | __注意__: 这仅仅只UltiSnips的文档的翻译,到[这里](https://github.com/SirVer/ultisnips) 8 | 获取UltiSnips插件的相关信息 9 | 10 | 如果你觉得这个翻译帮助到了你,可以给我个 __star__ 。也欢迎指出我的翻译中的问题。 11 | 12 | --- 13 | 14 | 中文档的安装使用方法 15 | -------------------- 16 | 17 | 假设你正在使用[Vundle](https://github.com/gmarik/Vundle.vim),可以直接添加下面 18 | 的配置到你的 `.vimrc` 中,如果是使用的其他插件管理器,请调整为对应的格式 19 | 20 | Plugin 'Linfee/ultisnips-zh-doc' 21 | 22 | __注意:__你需要先加载 ultisnips-zh-doc 再加载 UltiSnips 才能保证打开中文文档。 23 | 24 | --- 25 | 26 | UltiSnips简介 27 | ------------- 28 | 29 | UltiSnips是vim代码片段终极解决方案。特有很多特性并且运行非常流畅。 30 | 31 | ![GIF Demo](https://raw.github.com/SirVer/ultisnips/master/doc/demo.gif) 32 | 33 | 这个演示中,我正在编辑一个python文件。我首先展开了`#!`片段,然后是`class`片段。 34 | 补全菜单使用的是[YouCompleteMe](https://github.com/Valloric/YouCompleteMe), 35 | UltiSnips同样集成了[neocomplete](https://github.com/Shougo/neocomplete.vim)。我可 36 | 以在各个插入点之间跳跃并插入文本,同时还会在代码片段的其他位置自动插入文本:当 37 | 我添加`Animal`作为一个基类,`__init__`方法会同时更新,添加调用基类的构造器的代码, 38 | 当我添加一个参数到构造器中,它会自动被赋值给实例变量。然后我插入了我的个人的代码 39 | 片段,`print`用来调试。注意我离开了插入模式,插入了另一个代码片段,然后又回来给 40 | `__init__`方法添加了一个新的参数,而此时类的代码片段依然是激活的并且添加了另一个 41 | 实例变量。 42 | 43 | UltiSnips的官方主页是在 . 44 | 你可以在这里提交 pull request 和 issues。 45 | 46 | UltiSnips于2009年6月由@SirVer创建。在2015年12月,维护工作移交给了 47 | [@seletskiy](https://github.com/seletskiy). 48 | 49 | 你可以使用UltiSnips来干什么? 50 | ---------------------------- 51 | 52 | 高级代码片段: 53 | * [Snippets Aliases](doc/examples/snippets-aliasing/README.md) 54 | * [Dynamic Tabstops/Tabstop Generation](doc/examples/tabstop-generation/README.md) 55 | 56 | 快速开始 57 | -------- 58 | 59 | 这里假定你正在使用 [Vundle](https://github.com/gmarik/Vundle.vim),你可以把这些 60 | 加到你的`.vimrc` 中来安装UltiSnips,如果是其他插件管理器,请调整为对应的格式。 61 | 62 | " 这句放到你的插件列表中 63 | Plugin 'SirVer/ultisnips' 64 | 65 | " 代码片段和核心是分开,如果你想要默认代码片段,也加上这行 66 | Plugin 'honza/vim-snippets' 67 | 68 | " 有关触发代码片段的配置,如果你使用了 YouCompleteMe 就不要使用 tab 了 69 | let g:UltiSnipsExpandTrigger="" 70 | let g:UltiSnipsJumpForwardTrigger="" 71 | let g:UltiSnipsJumpBackwardTrigger="" 72 | 73 | " 如果你希望使用 :UltiSnipsEdit 的时候可以垂直切分你的窗口来编辑 74 | let g:UltiSnipsEditSplit="vertical" 75 | 76 | 这里有非常详尽的 UltiSnips 文档 77 | [documentation](https://github.com/SirVer/ultisnips/blob/master/doc/UltiSnips.txt). 78 | 79 | 当然,这里还有中文版文档 80 | [文档](https://github.com/Linfee/ultisnips-zh-doc/blob/master/doc/UltiSnips_zh.txt). 81 | 82 | 83 | 截屏 84 | ---- 85 | 86 | 这里发布了一些高级用法的截屏: 87 | 88 | - [Episode 1: What are snippets and do I need them?](http://www.sirver.net/blog/2011/12/30/first-episode-of-ultisnips-screencast/) 89 | - [Episode 2: Creating Basic Snippets](http://www.sirver.net/blog/2012/01/08/second-episode-of-ultisnips-screencast/) 90 | - [Episode 3: What's new in version 2.0](http://www.sirver.net/blog/2012/02/05/third-episode-of-ultisnips-screencast/) 91 | - [Episode 4: Python Interpolation](http://www.sirver.net/blog/2012/03/31/fourth-episode-of-ultisnips-screencast/) 92 | 93 | [Vimcasts](http://vimcasts.org) 上有三集非常优秀的讲述 UltiSnips 的视频: 94 | 95 | - [Meet UltiSnips](http://vimcasts.org/episodes/meet-ultisnips/) 96 | - [Using Python interpolation in UltiSnips snippets](http://vimcasts.org/episodes/ultisnips-python-interpolation/) 97 | - [Using selected text in UltiSnips snippets](http://vimcasts.org/episodes/ultisnips-visual-placeholder/) 98 | --------------------------------------------------------------------------------