Vim Markdown语法高亮(列表项和代码块冲突)

11
我决定学习更多关于vim和它的语法高亮。我正在为Markdown创建自己的语法文件,使用示例来帮助其他人。我已经看到了mkd.vim,它也有这个问题。我的问题在于列表项和代码块高亮之间。
代码块定义
  • 第一行为空
  • 第二行以至少4个空格或1个制表符开始
  • 块以空行结束
示例:
Regular text

    this is code, monospaced and left untouched by markdown
    another line of code

Regular Text

我的Vim代码块语法:

syn match mkdCodeBlock   /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=mkdCodeBlock  

hi link mkdCodeBlock  comment

无序列表项 定义

  • 第一行为空白
  • 第二行以 [-+*] 开头,后跟一个空格
  • 列表以一个空白行和一个正常(非列表)行结束
  • 在项目之间可以添加任意数量的空白行
  • 通过缩进(4个空格或1个制表符)指定子列表
  • 列表项后的普通文本行将作为该列表项的延续

示例:

Regular text

- item 1

    - sub item 1
    - sub item 2
- item 2
this is part of item 2
so is this


- item 3, still in the same list
    - sub item 1
    - sub item 2

Regular text, list ends above

我为 Vim 编写了一个无序列表项定义的语法(我只高亮显示 [-+*]):

syn region  mkdListItem start=/\s*[-*+]\s\+/ matchgroup=pdcListText end=".*" contained nextgroup=mkdListItem,mkdListSkipNL contains=@Spell skipnl 
syn match mkdListSkipNL /\s*\n/ contained nextgroup=mkdListItem,mkdListSkipNL skipnl

hi link mkdListItem  operator

我无法在列表最后两个规则和代码块中实现高亮。

以下是导致语法高亮出现问题的示例:

Regular text

- Item 1
- Item 2
part of item 2

    - these 2 line should be highlighted as a list item
    - but they are highlighted as a code block

我目前还无法弄清楚如何让高亮显示按照我想要的方式工作


忘记添加一个"global"语法规则,它在下面列出的两个规则中都使用。这是为了确保它们以空行开头。

syn match mkdBlankLine   /^\s*\n/    nextgroup=mkdCodeBlock,mkdListItem transparent

另外注意:我应该更清楚地表达。在我的语法文件中,列表规则出现在引用块规则之前。



很酷。这让我终于想学习vim脚本了。 :) - jop
3个回答

7

请确保 mkdListItem 的定义在 mkdCodeBlock 的定义之后,像这样:

syn match mkdCodeBlock   /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=mkdCodeBlock  
hi link mkdCodeBlock  comment

syn region  mkdListItem start=/\s*[-*+]\s\+/ matchgroup=pdcListText end=".*" contained nextgroup=mkdListItem,mkdListSkipNL contains=@Spell skipnl 
syn match mkdListSkipNL /\s*\n/ contained nextgroup=mkdListItem,mkdListSkipNL skipnl
hi link mkdListItem  operator

syn match mkdBlankLine   /^\s*\n/    nextgroup=mkdCodeBlock,mkdListItem transparent

Vim文档中在:help :syn-define中提到:

"如果在同一位置匹配了多个项目,则最后定义的项目获胜。因此,您可以通过使用与先前定义的语法项匹配的项来覆盖先前定义的语法项。但是,关键字始终在匹配或区域之前。具有匹配大小写的关键字始终在不区分大小写的关键字之前。"


你说得对。我已经更新了我的问题(底部),我的列表规则在引用块规则之前。 你能否将你的示例翻转一下,这样引用块就在列表之前。然后我就可以接受你的答案了。 - Tao Zhyn

1

hcs42是正确的。我现在记得读到那部分了,但是直到hcs24提醒我才想起来。

这是我的更新语法(还有其他一些微调),可以正常工作:

"""""""""""""""""""""""""""""""""""""""
" 代码块:
" 缩进至少4个空格或1个制表符 " 此规则必须出现在mkdListItem之后,否则高亮显示会出错 syn match mkdCodeBlock /\(\s\{4,}\|\t\{1,}\).*\n/ contained nextgroup=mkdCodeBlock
""""""""""""""""""""""""""""""""""""""" " 列表:
" 这前两个规则需要放在最前面,否则高亮显示会出错
" 在当前行或下一行继续列表 syn match mkdListCont /\s*[^-+*].*/ contained nextgroup=mkdListCont,mkdListItem,mkdListSkipNL contains=@Spell skipnl transparent
" 跳过空行 syn match mkdListSkipNL /\s*\n/ contained nextgroup=mkdListItem,mkdListSkipNL
" 无序列表 syn match mkdListItem /\s*[-*+]\s\+/ contained nextgroup=mkdListSkipNL,mkdListCont skipnl

0

Tao Zhyn,这可能涵盖了您的用例,但它并不包括Markdown语法。在Markdown中,列表项可以包含代码块。您可以在此处查看我的解决方案。

简而言之,问题在于vim不允许您说出像“与其容器具有相同缩进+4个空格的块”这样的话。我找到的唯一解决方案是为每种可能包含在列表项中的块的每个缩进级别生成规则(实际上我支持42个缩进级别,但这是一个任意的数字)

因此,我有markdownCodeBlockInListItemAtLevel1,它必须包含在markdownListItemAtLevel1中,并且需要至少8个前导空格,然后是markdownCodeBlockInListItemAtLevel2,它必须包含在markdownListItemAtLevel2中,该列表项必须包含在markdownListItemAtLevel1中,并且需要至少10个前导空格,等等...

我知道已经过去了几年,但也许有人会认为这个答案很有帮助,因为所有基于缩进的语法都面临着同样的问题。


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