有没有办法让vim不将HTTP URL和电子邮件地址标记为拼写错误?或者,更笼统地说,是列出有效拼写正则表达式的方法?

#1 楼

您可以添加自定义语法规则,并为它们提供
@nospell关键字,
这将告诉Vim不要对该语法匹配应用拼写检查。例如:

:syn match UrlNoSpell "\w\+:\/\/[^[:space:]]\+" contains=@NoSpell


以上内容适用于文本文件和某些文件类型(例如
markdown),但不适用于所有文件类型。 >
请注意,我在这里使用了一个非常简单的正则表达式;请参阅如何从文本中解析URL的替代方法。


对于其他文件类型,您需要做更多的工作。例如,对于python文件,注释位于pythonComment/usr/share/vim/vim74/syntax/python.vim
组中:

syn match   pythonComment   "#.*$" contains=pythonTodo,@Spell


要覆盖此内容,我们需要做:

:syn match UrlNoSpellComment "\w\+:\/\/[^[:space:]]\+" contains=@NoSpell containedin=pythonComment
:highlight def link UrlNoSpellComment Comment


诀窍是添加一个先前匹配的语法匹配列表,其中我们的
自定义语法匹配可能包含在containedin=中,这告诉Vim查找
UrlNoSpell匹配项内的正则表达式。

我们还需要使用pythonComment设置正确的颜色,因为这些颜色不是
继承的。

您需要在多个地方执行此操作,例如对于Python字符串:

:syn match UrlNoSpellString "\w\+:\/\/[^[:space:]]\+" contains=@NoSpell containedin=pythonString
:highlight def link UrlNoSpellString String


我们需要2个不同的语法匹配组,以便可以应用正确的语法突出显示。 br />
当然,对于其他文件类型,您需要使用其他highlight语法
匹配项... AFAIK没有“通用”解决方案,而是在其中查找正确的
containedin=应该不太困难。


请注意,所有上面的命令必须在语法文件之后执行;
有两种方法可以执行此操作:



从命令或键映射中,必须调用此命令每次手动。例如

fun! NoUrlSpell()
    if &filetype == 'python'
        :syn match UrlNoSpellComment "\w\+:\/\/[^[:space:]]\+" contains=@NoSpell containedin=pythonComment
        :highlight def link UrlNoSpellComment Comment
        :syn match UrlNoSpellString "\w\+:\/\/[^[:space:]]\+" contains=@NoSpell containedin=pythonString
        :highlight def link UrlNoSpellString String
    elseif &filetype == 'ruby'
        " ...
    else
        syn match   pythonComment   "#.*$" contains=pythonTodo,@Spell
    endif
endfun
command NoUrlSpell :call NoUrlSpell()


将命令放入/usr/share/vim/vim74/syntax/*.vim中。 Vim将拾取这些文件并在默认语法文件之后执行它们(请参见:
~/.vim/after/syntax/[filetype].vim)。


#2 楼

Martin Tournoij的其他出色回答无法达到我的预期效果-可能是由于我利用了diraol出色的python-mode插件,而不是Vim的Python默认语法文件。

为了避免在Python注释,字符串或字符串中突出显示URI。在python-mode下的docstrings中,将以下简洁的单行代码添加到您特定于用户的~/.vim/after/syntax/python.vim文件中:

syntax match NoSpellUriPython '\w\+:\/\/[^[:space:]]\+' transparent contained containedin=pythonComment,python.*String contains=@NoSpell


就这样。至关重要的是,请注意,这会将马丁回答中的十二行分开压缩为一行。怎么样?小学,我亲爱的基于Vim的Watson。我们添加:


transparent关键字,指示Vim从其父语法(例如注释,字符串)继承该子语法的高亮属性。这使我们能够避免为每个子语法组显式地重述highlight def link
contained关键字,可防止该子语法超出其父语法的边界(例如,EOL表示注释,字符串定界符表示字符串)。 />所有父语法组均以逗号分隔到containedin关键字。 .*正则表达式运算符使我们能够以最小的痛苦和最大的前向兼容性巧妙地匹配所有Python字符串语法组(即pythonStringpythonUniStringpythonRawStringpythonUniRawStringpythonDocstring)。

尽管在技术上有效,但嵌入了vimscript Martin的回答违反了DRY(请勿重复自己)原则。另请参阅类似的答案以获取更多详细信息。

但是等等...还有更多。

为大荣耀而作的改进

I'我已经决定对Vim过于幼稚的默认拼写检查和第三方插件(例如Spelunker,无条件地对整个缓冲区进行拼写检查,而不仅仅是对注释和字符串进行编码)感到烦恼…… 。 </gasp>

经过良好测试的Vim代码段可以避免对Python注释和字符串中的所有以下内容进行拼写检查:


URI(如上所述)。

CamelCase标识符。

snake_case标识符。

UPPERCASE标识符。

@-前缀标识符(例如@muhdecorator)。

"-分隔的文件类型文件名(例如,"muh_module.py")。

:-分隔的子字符串(例如,:func:`re.sub`中的:func:)。
分隔的子字符串(例如,re.sub在:func:`re.sub`中。)

将以下部分或全部添加到您特定于用户的~/.vim/after/syntax/python.vim文件中,并随着Vim实际上一次对RightStuff™进行拼写检查而大吃一惊:

" Avoid spell checking URIs.
syntax match NoSpellPythonUri /\v\w+:\/\/[^[:space:]]+/ transparent contained containedin=pythonComment,python.*String contains=@NoSpell

" Avoid spell checking both CamelCase-formatted identifiers and uppercase
" identifiers. Since most languages (excluding Raku) prohibit Unicode in
" identifiers, these matches are intentionally confined to ASCII codepoints
" (e.g., "[A-Z]" rather than "[[:upper:]]").
syntax match NoSpellPythonCaps /\v<[A-Z]([A-Z0-9]{-1,}|[a-z0-9]+[A-Z0-9].{-})>/ transparent contained containedin=pythonComment,python.*String contains=@NoSpell

"FIXME: For unknown reasons, enabling this and *ONLY* this "syntax" statement
"causes subtle (but horrible) failures across "python-mode" indentation and
"syntax highlighting. While lamentable, we need "python-mode" more than we need
"to avoid spell checking snake_case-formatted identifiers. See also this
"currently unresolved upstream issue:
"    https://github.com/python-mode/python-mode/issues/1083
"
" " Avoid spell checking snake_case-formatted identifiers.
" syntax match NoSpellPythonSnake
"   \ /\v<\w+_.{-1,}>/ transparent
"   \ contained containedin=pythonComment,python.*String contains=@NoSpell

" Avoid spell checking "@"-prefixed identifiers.
syntax match NoSpellPythonDecorator /\v\@[a-zA-Z].{-}>/ transparent contained containedin=pythonComment,python.*String contains=@NoSpell

" Avoid spell checking ":"-delimited substrings.
syntax match NoSpellPythonColons /\v:[^:]+:/ transparent contained containedin=pythonComment,python.*String contains=@NoSpell

" Avoid spell checking "`"-delimited substrings.
syntax match NoSpellPythonTicks /\v`[^`]+`/ transparent contained containedin=pythonComment,python.*String contains=@NoSpell

" Avoid spell checking '"'-delimited filetyped filenames matched as a
" double-quoted substring containing a filename prefix, a period, and one to
" four characters comprising a filetype.
syntax match NoSpellPythonPath /\v"[^"]+.[^"]{1,4}"/ transparent contained containedin=pythonComment,python.*String contains=@NoSpell


当然,以上所有内容都可以(并且应该)简化为与一个类似于哥斯拉的正则表达式相匹配的单行代码,包括我在内的任何人都不会能够维护甚至阅读。为了所有人的理智,我没有这样做。

如果不是我的人想制作一个由GitHub托管的Vim插件,将上述内容扩展到其他流行的语言,那就太好了。伙计们,Vim的默认拼写检查实现几乎已经存在。它只需要开源社区的帮助即可。

在此之前,StackOverflow可能永远与您在一起!

评论


在这里写答案时,我有点想出了整个Vim语法突出显示的内容。老实说,我并不总是知道自己在做什么,因此,尤其是一些较旧的答案可能不尽人意。

–马丁·图尔诺伊(Martin Tournoij)
20-4-11在9:13



马丁,你太谦虚了。没有您的“破冰”答案,我和许多其他人甚至都不知道从哪里开始。感谢您开始这个编辑聚会!罗马也许不是一天建成的,但至少现在我们可以一拼而过了。

– Cecil咖喱
20-4-14在3:43