From aff85c641192ca9420d5ce3a119740d90f82cb9c Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Fri, 2 Oct 2015 22:12:34 -0700 Subject: [PATCH] Improve fenced code block matching The previous fenced code block matching did not support the syntax used by [Kramdown][1] or fully support the syntax described in [CommonMark][2]. The differences are: * Kramdown requires \~ instead of \` in fences (CommonMark permits \~) * Both permit code fences to have more than 3 \~ or \` characters * Both require the closing fence to have as many chars as the opening * Both permit the closing fence to have extra fence chars * CommonMark explicitly forbids \` in the fence info string This is likely the case with other Markdown variants, but these are the only two that I have considered when authoring this commit. This commit implements all of the above mentioned changes. The change is mostly straight-forward. The only exception is that the end matching is a little subtle since one of `\z2` and `\z3` will be empty, using the more natural expression `\z2*\|\z3*` can hang the regex matcher. The `\%(\z2\z3)*` expression is a bit less obvious but works reliably. Note that I did not include any changes relating to the Pandoc syntax mentioned in #65 and #74. If this syntax is desired, I can adjust this commit to include it. [1]: http://kramdown.gettalong.org/syntax.html#fenced-code-blocks [2]: http://spec.commonmark.org/0.22/#code-fence Signed-off-by: Kevin Locke --- syntax/markdown.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/syntax/markdown.vim b/syntax/markdown.vim index 49dbe3a..8b16226 100644 --- a/syntax/markdown.vim +++ b/syntax/markdown.vim @@ -85,14 +85,14 @@ exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start= syn region markdownCode matchgroup=markdownCodeDelimiter start="`" end="`" keepend contains=markdownLineStart syn region markdownCode matchgroup=markdownCodeDelimiter start="`` \=" end=" \=``" keepend contains=markdownLineStart -syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*```.*$" end="^\s*```\ze\s*$" keepend +syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*\z(\z(`\)\{3,}\|\z(\~\)\{3,}\)[^`]*$" end="^\s*\z1\%(\z2\z3\)*\ze\s*$" keepend syn match markdownFootnote "\[^[^\]]\+\]" syn match markdownFootnoteDefinition "^\[^[^\]]\+\]:" if main_syntax ==# 'markdown' for s:type in g:markdown_fenced_languages - exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*```\s*'.matchstr(s:type,'[^=]*').'\>.*$" end="^\s*```\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') + exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*\z(\z(`\)\{3,}\|\z(\~\)\{3,}\)\s*'.matchstr(s:type,'[^=]*').'\>[^`]*$" end="^\s*\z1\%(\z2\z3\)*\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') endfor unlet! s:type endif