Vim中的Snippets和Abbreviations区别

18
使用“片段”插件(例如snipmate, ultisnips)与仅使用内置的“ abbreviations”功能相比,有哪些优缺点?
在声明iabbrcabbr等时,是否存在特定用例缺少片段插件提供的一些重要功能?我无法找到这两个“功能”及其各自实现之间的全面比较。
正如@peter-rincker在评论中指出的那样:
请注意,缩写也可以执行代码。通常是通过<c-r>=或表达式缩写(<expr>)来实现的。例如,将@@扩展为当前文件的路径::iabbrev @@ <c-r>=expand('%:p')<cr> 以python为例,让我们比较一下Snipmate代码片段和Vim中用于插入类声明行的缩写。
# New Class
snippet cl 
  class ${1:ClassName}(${2:object}):
    """${3:docstring for $1}"""
    def __init__(self, ${4:arg}):
      ${5:super($1, self).__init__()}
      self.$4 = $4 
      ${6}

Vimscript

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模板能够完成片段所做的大部分工作时?我假设实现片段更容易,并且它们提供了额外的美学/视觉特性。例如,如果我在Vim中使用abbr以及其他插件来运行/测试Python代码--例如syntastic, pytest, ropevim, pep8等--我是否错过了一些片段提供的关键功能?

请您能否提供一个代码片段插件的具体示例? - Kevin
1
点击这里查看如何使用ultisnips的演示。然后思考如何使用缩写实现相同的功能。 :) - lcd047
正如@peter-rincker在评论中指出的那样,您可以通过<c-r>=...使用vimscript实现相同的功能。我认为使用代码片段以及一些美学/视觉特性更容易实现。 - ILMostro_7
1
我从来不知道iabbr可以执行代码!谢谢!谢谢!我有提到过吗?谢谢!! - caffeinemachine
4个回答

8

所有可以使用代码片段实现的功能都可以使用缩写来实现,反之亦然。您可以使用缩写(镜像或非镜像)来设置占位符,也可以使用上下文敏感的代码片段。

这里有两个重要的区别:

  • 当输入缩写文本并按下非单词字符(或esc)时,触发缩写。而代码片段则是按需触发,可以使用快捷方式(无需键入while+ tab,只需键入w+ tab即可)。
  • 定义新的代码片段(或维护旧的代码片段)比定义缩写要容易得多。对于缩写,我们需要大量样板代码才能做出好看的效果

还有一些其他的区别。例如,缩写总是在任何地方触发。而在注释或字符串上下文中将for展开为for(placeholder) {\n}肯定不是最终用户所期望的。但是,使用代码片段,这不再是问题:我们可以期望最终用户在请求展开代码片段时知道自己在做什么。尽管如此,我们仍然可以提供上下文感知的代码片段,在注释中将throw扩展为@throw {domain::exception} {explanation},或在其他地方将其扩展为throw domain::exception({message});


1
虽然我在精神上同意其他答案中的一些观点,但从逻辑上讲,这个答案更接近胜利者,因此被接受。多年过去了,对我仍然适用,但仍然很接近 :) - ILMostro_7
“可以用片段完成的所有操作都可以用缩写完成”这个说法(已经)不再正确。通过Ultisnip的VISUAL区域,您可以选择枚举定义,触发开关片段,并在开关中生成所有情况。您也可以轻松地使用映射来完成此操作,但是没有:vabbreviate以接受区域作为输入。 - idbrii
1
@idbrii 在视觉选择上应用缩写确实没有任何意义。相当于它的是视觉模式下的x映射。 (请注意,我正在维护的mu-template已经支持视觉和正常模式扩展很长时间了。)但这是一个好观点:我们可以为不同模式使用单个片段,而我们需要更多的工作来获得缩写+xmap的等效物。 - Luc Hermitte

5

片段

比Vim本地缩写更加强大的一种功能。以下是其亮点:

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

缩写

非常适合纠正常见的拼写错误和使用小片段。

  • Vim提供原生支持,无需插件
  • 通常在空格或上扩展
  • 触发文本有一些特殊规则(请参见:h abbreviations)
  • 可以通过:cabbrev命令在命令模式下使用(常用于创建命令别名)
  • 没有占位符
  • 动态扩展

结论

总的来说,片段比缩写更加强大,并提供了许多其他编辑器所享有的功能,但您可以同时使用这两个功能,很多人都这样做。缩写享受原生支持的好处,这对于远程环境非常有用。缩写还有另一个明显的优势,即可以在命令模式下使用。


这就是我一直在做的,同时使用两种方法;但这似乎有些过度了,可能是因为我不知道如何充分利用代码片段。 - ILMostro_7
1
mu-template有一些可以在可视模式下触发的片段(环绕功能)。我认为其他片段引擎也有类似的功能。并且使用缩写词确实可以实现占位符。 - Luc Hermitte

5

片段功能更强大。

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

例如,使用ultisnips,您可以让它执行shell命令、vimscript以及Python代码。

以下是(ultisnips)示例:

snippet hdr "General file header" b
# file: `!v expand('%:t')`
# vim:fileencoding=utf-8:ft=`!v &filetype`
# ${1}
#
# 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或restructuredtext文件中,您可以使相同名称的片段扩展方式不同。


3
需要注意的是,缩写也可以执行代码。通常是通过 <c-r>= 或表达式缩写 (<expr>) 来实现。以下是一个示例,将 @@ 扩展为当前文件的路径::iabbrev @@ <c-r>=expand('%:p')<cr> - Peter Rincker
有趣!我不知道缩写可以做到那样。但我必须承认自从安装了ultisnips以来,我很少使用缩写。 - Roland Smith
感谢您的回复;至于文件类型专业化,我认为您也可以使用vimscript来实现:au FileType html... - ILMostro_7
你对Vim-snipmate和ultisnips有什么看法?ultisnips更强大吗? - alpha_989

4

片段就像内置的:abbreviate功能一样,但通常带有以下特点:

  • 参数插入:您可以在片段内的不同位置插入(输入或选择)文本片段。缩写只会扩展一次。
  • 镜像:参数可以在片段的其他地方(可能甚至是转换后的形式)重复出现,并通常随着您的输入而更新。
  • 多个停止点:您可以在片段内从一个点跳到另一个点,有时甚至可以递归地展开片段。

在评估片段插件时有三个要素:首先,评估片段引擎本身的功能;其次,评估作者或其他人提供的片段质量和广度;第三,评估添加新片段的难度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接