Skip to content

示例代码片段

Vsnips 使用时, 会尽可能兼容 Vim 中 Ultisnips 插件. 对于非 Vim 用户, 如果你只是想创建一些片段, 可以不必做太多考虑, 但是若与其他用户分享代码片段, 请尽量在 Vim 与 VSCode 中都确保运行成功.

最简单片段

此种片段不需要与任何变量交互, 因此兼容性最佳.

snippet dbg "Use IPython to debug"
# ---------- XXX: Can't GIT add [START] ---------- #
import IPython
IPython.embed(using=False)
# ---------- XXX: Can't GIT add  [END]  ---------- #
endsnippe

与 Vim 变量, 函数的交互的代码片段

Vsnips 提供了对于 vimrc 中定义变量的查找, 在解析代码片段时, 会将vim中的变量进行替换, 以下方的代码片段为例.

snippet title "Hexo post header" b
---
layout: post
title: `!p snip.rv = get_markdown_title(snip)`
date: `!v strftime("%Y-%m-%d %H:%M:%S")`
author: `!v g:snips_author`
tags: 
description: ${3}
categories: Docs
photos:  
toc: true

---

${0}
endsnippet

使用!v开头的表示需要由 Vim 来解析, 上面的片段中!v strftime("%Y-%m-%d %H:%M:%S"), !v g:snips_author有两个 Vim 变量. strftime为时间的处理, g:snips_author表示引用在 vimrc 中定义的变量(let g:snips_author="corvo").

解析时替换

在 Vim 中使用 UltiSnips 时, 可以使用!p snip.rv表示此占位符由 Python 解析, 以下方代码为例:

snippet ifmain "ifmain" b
if __name__ == `!p snip.rv = get_quoting_style(snip)`__main__`!p snip.rv = get_quoting_style(snip)`:
    ${1:${VISUAL:main()}}
endsnippe

代码中有!p snip.rv = get_quoting_style(snip)这个函数, 这些函数先前均是由 Python 编写, 虽然我将插件功能移植到 VSCode, 但直接解析 Python 函数是有难度的, 所以在 Vsnips 中, 需要我们针对这些函数重写一份 JavaScript 代码,

  • 原始 Python 代码
def get_quoting_style(snip):
    style = snip.opt("g:ultisnips_python_quoting_style", "double")
    if style == 'single':
        return SINGLE_QUOTES
    return DOUBLE_QUOTE
  • 重写后的 JavaScript 代码
function get_quoting_style() {
  let style = VIM_VARS_MAP.get("ultisnips_python_quoting_style") || "double";
  if (style === "single") {
    return SINGLE_QUOTES;
  }

  return DOUBLE_QUOTES;
}

需要获取当前文件属性的代码片段

上方的自定义函数可以在解析 snippet 代码片段时直接替换, 但是有一些函数, 例如我们想要获取当前文件的文件名, 就需要动态的处理这个函数. Vsnips 的策略是生成中间函数, 该种类型的函数使用 JavaScript编写, 如果片段中存在 JavaScript 模板函数, 我们将会在补全时根据上下文信息进行替换.

Vsnips 中, 自定义了一类函数, !js {func_name}的形式替换进模板. 仍然以这个标题为例:

snippet title "Hexo post header" b
---
layout: post
title: `!p snip.rv = get_markdown_title(snip)`
date: `!v strftime("%Y-%m-%d %H:%M:%S")`
author: `!v g:snips_author`
tags: 
description: ${3}
categories: Docs
photos:  
toc: true

---

${0}
endsnippet

get_markdown_title是需要根据当前位置的上下文片段来确定的, 在 Vsnips 中, 此种类型的参数在书写时, 需要两部分代码,

// 函数1: 告诉 Vsnips , 此函数为 JavaScript 函数, 函数名称为 js_markdown_title.
function get_markdown_title() {
  return jsFuncDecorator("js_markdown_title");  // `!js js_markdown_title`
}

// 函数2: 真正触发补全操作时, 这个 JavaScript 函数会被调用, 并返回 markdown 文件对应的文件名.
function js_markdown_title(vsContext: VSnipContext) {
  let fn = vsContext.document.fileName;
  return path.basename(fn, path.extname(fn));
}

VsnipContext 是对 VSCode api 的一层封装, 的具体定义请查看 vsnip_context.