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

我目前无法弄清楚如何让突出显示以我想要的方式工作


忘记添加下面列出的两个规则中使用的“全局”语法规则。这是为了确保它们以空行开头。

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

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


4

3 回答 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

“如果多个项目在同一位置匹配,则定义为 LAST 的项目获胜。因此,您可以使用与相同文本匹配的项目覆盖先前定义的语法项目。但关键字始终位于匹配项或区域之前。并且大小写匹配的关键字总是在忽略大小写的关键字之前。”

于 2008-09-26T07:43:12.497 回答
1

hcs42 是正确的。我确实记得现在读过那部分,但我忘记了,直到 hcs24 提醒我。

这是我更新的语法(其他一些调整)有效:

"""""""""""""""""""""""""""""""""""""""""
" 代码块:

" 缩进至少 4 个空格或 1 个制表符
" 这个规则必须出现在 mkdListItem 中,否则突出显示会搞砸
同步匹配 mkdCodeBlock /\(\s\{4,}\|\t\{1,}\).*\n/ 包含 nextgroup=mkdCodeBlock  

"""""""""""""""""""""""""""""""""""""""""
" 列表:

" 前两条规则必须放在首位,否则突出显示将是
“不正确

" 继续当前行或下一行的列表
syn match mkdListCont /\s*[^-+*].*/ contains nextgroup=mkdListCont,mkdListItem,mkdListSkipNL contains=@Spell skipnl transparent

" 跳过空行
同步匹配 mkdListSkipNL /\s*\n/ 包含 nextgroup=mkdListItem,mkdListSkipNL

" 无序列表
syn match mkdListItem /\s*[-*+]\s\+/ 包含 nextgroup=mkdListSkipNL,mkdListCont skipnl
于 2008-09-26T22:09:31.173 回答
0

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

TL;博士; 问题是 vim 不允许你说这样的话:一个与其容器具有相同缩进的块 + 4 个空格。我找到的唯一解决方案是为每种类型的块生成规则,这些块可以包含在每个缩进级别的列表项中(实际上我支持 42 级缩进,但它是一个任意数字)

所以我有 markdownCodeBlockInListItemAtLevel1必须包含在 markdownListItemAtLevel1 中,它需要至少有 8 个前导空格,然后 markdownCodeBlockInListItemAtLevel2必须包含在 markdownListItemAtLevel2 中,必须包含在 markdownListItemAtLevel1 蚂蚁需要至少 10 个前导空格,ecc ...

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

于 2014-03-23T17:00:38.490 回答