Vim 中的片段与缩写

Snippets vs. Abbreviations in Vim

使用 "snippets" 插件有什么优点 and/or 缺点,例如snipmate, ultisnips, for VIM as opposed to simply using the builtin "abbreviations" 功能?

是否有声明 iabbrcabbr 等的特定用例。缺乏 一些 主要片段插件提供的功能?我未能找到这两个 "features" 及其各自实现之间的彻底比较。

正如@peter-rincker 在评论中指出的那样:

It should be noted that abbreviations can execute code as well. Often via <c-r>= or via an expression abbreviation (<expr>). Example which expands @@ to the current file's path: :iabbrev @@ <c-r>=expand('%:p')<cr>

作为 python 的示例,让我们比较 Vim 中的一个 snipmate 片段和一个缩写,用于为 class 声明插入行。

Snipmate

# New Class
snippet cl 
  class ${1:ClassName}(${2:object}):
    """${3:docstring for }"""
    def __init__(self, ${4:arg}):
      ${5:super(, self).__init__()}
      self. =  
      

Vim脚本

au FileType python :iabbr cl class ClassName(object):<CR><Tab>"""docstring for ClassName"""<CR>def __init__(self, arg):<CR><Tab>super(ClassName, self).__init__()<CR>self.arg = arg

当 Vim 的 abbr:help template 时,我是否遗漏了 "snippets" 的一些基本功能,或者我假设它们在大多数情况下是矫枉过正的?模板能够做 所有 大部分 的片段吗?

我认为实现代码片段更容易,而且它们提供了额外的 aesthetic/visual 功能。例如,如果我在 Vim 中使用 abbr 并在 vim 中使用其他插件 running/testing python 代码——例如syntastic, pytest, ropevim, pep8,等等——我是否错过了代码片段提供的一些关键功能?

片段更强大。

根据实施情况,片段可以让您更改(或接受默认值)多个占位符,甚至可以在片段展开时执行代码。

例如 ultisnips,你可以让它执行 shell 命令,vimscript 和 Python 代码。

一个(ultisnips)例子:

snippet hdr "General file header" b
# file: `!v expand('%:t')`
# vim:fileencoding=utf-8:ft=`!v &filetype`
# 
#
# Author: ${2:J. Doe} ${3:<jdoe@gmail.com>}
# Created: `!v strftime("%F %T %z")`
# Last modified: `!v strftime("%F %T %z")`
endsnippet

这会为您提供三个要填写的占位符(它为其中两个提供默认值),并设置文件名、文件类型和当前日期和时间。

单词"snippet"之后,起始行包含三项;

  • 触发字符串,
  • 描述和
  • 片段选项。

我个人主要使用 b 选项,其中片段在行首展开,而 w 选项在触发字符串从单词开头展开时展开片段.

请注意,您必须键入触发字符串 ,然后输入实际触发扩展的键或组合键。因此,除非您希望 .

,否则片段不会展开

此外,片段可以按文件类型专门化。假设您要定义四级标题,h1 .. h4。您可以对相同的名称进行不同的扩展,例如HTML、markdown、LaTeX 或重组文本文件。

片段

Vim 的本地缩写的粗略超集。以下是要点:

  • 仅在按键时触发
  • 使用用户可以在其间跳转的占位符
  • 只存在于插入模式
  • 动态扩展

缩写

非常适合常见的拼写错误和小片段。

  • Vim 原生,因此不需要插件
  • 通常在空格或 <c-]>
  • 处展开
  • 触发文本的一些特殊规则(参见:h abbreviations
  • 可以通过:cabbrev在命令模式下使用(通常用于创建命令别名)
  • 没有占位符
  • 动态扩展

结论

在大多数情况下,片段更强大,并提供其他编辑器喜欢的许多功能,但您可以同时使用这两种功能,而且很多人都在使用。缩写享有本地化的优势,这对远程环境很有用。缩写还有另一个明显的优势,那就是可以在命令模式下使用。

片段就像类固醇的内置:abbreviate,通常有:

  • 参数插入:您可以在片段内的不同位置插入(键入或select)文本片段。缩写只展开一次。
  • 镜像:参数可能会在代码段的其他地方重复(甚至可能以转换的方式),通常会在您键入时更新。
  • multiple stops inside: 你可以在片段中从一个点跳到另一个点,有时甚至递归地在一个片段中扩展片段。

snippet plugin的评价有三点:一是snippet engine本身的特性,二是作者或他人提供的snippet的质量和广度;第三,添加新片段是多么容易。

任何可以用代码片段完成的事情都可以用缩写来完成,反之亦然。你可以有(镜像或不镜像)带有缩写的占位符,你可以有上下文相关的片段。

有两个重要区别:

  • 当输入缩写文本并点击非单词字符(或 esc)时,会触发缩写。片段按需触发,可以使用快捷方式(无需键入 while + tab。w + tab 可能就足够了)。
  • 定义新片段(或维护旧片段)比定义缩写要容易得多。使用缩写,a lot of boiler plate code is required when we want to do neat things.

还有一些其他差异。例如,缩写总是在任何地方触发。在注释或字符串上下文中看到 for 扩展为 for(placeholder) {\n} 肯定不是最终用户所期望的。使用片段,这不再是问题:我们可以期望最终用户在要求扩展片段时知道他在做什么。不过,我们可以建议 context-aware snippets 在评论中将 throw 扩展为 @throw {domain::exception} {explanation},或在其他地方扩展为 throw domain::exception({message});