I've written regexes for markdown for emphasis and bold as follows:

syntax match PandocEmphasisMarker "\v(^|\s+)\zs_[^\n\t_ ]+([^_\n]|(\S_\S)|(\s_\S)|(\s+_\s+))+[^\n\t_ ]+_\ze($|\s+)" contains=PandocEmphasis
syntax match PandocEmphasis "\v\zs[^\n\t_ ]+([^_\n]|(\S_\S)|(\s_\S)|(\s+_\s+))+[^\n\t_ ]+\ze" contained

syntax match PandocStrongMarker "\v\zs\*[^\n*]+\*\ze" contains=PandocStrong
syntax match PandocStrong "\v\zs[^\n*]+\ze" contained

This yields the following (in my opinion correct) highlighting:

enter image description here

However, in Markdown there could be emphasis inside strong and strong inside emphasis as well. Since I already have the regexes so far, I'd like to allow them to mutually include each other.

I've tried with clusters as follows:

syntax cluster PandocEmphasisCluster contains=PandocEmphasis,PandocStrongMarker
syntax cluster PandocStrongCluster contains=PandocStrong,PandocEmphasisMarker

And then referenced those clusters from the "Marker" expressions using contains, but that did not work, it messed up the strong highlighting in my test file and the strong part inside an emphasized part was not made bold.

How can / should I make them contain each other?

This is also important for other things like ` inside emphasized or strong. Maybe I should use region somehow?


  • emphasis inside strong should still be strong, but also become emphasized.
  • strong inside emphasis should still be emphasized, but also become strong
  • effects should add up, that's what I want to achieve

If you have known start and end delimiters, you should use regions (:h :syn-region):

syntax region Emphasis start="\\\@<!\z(_\)" skip="\%(\s\|\\\)\@<=\z1\|\z1\k" end="\\\@<!\z1" keepend contains=Strong,Strike
syntax region Strong start="\\\@<!\z(\*\)" skip="\%(\s\|\\\)\@<=\z1\|\z1\k" end="\\\@<!\z1" keepend contains=Emphasis,Strike
syntax region Strike start="\\\@<!\z(\~\~\)" skip="\%(\s\|\\\)\@<=\z1\|\z1\k" end="\\\@<!\z1" keepend contains=Emphasis,Strong

highlight default link Emphasis WarningMsg
highlight default link Strong ErrorMsg
highlight default link Strike Conceal

The regions above use the syntax-specific capture group (:h /\z() which is great for broad patterns (e.g. if..endif, while..endwhile, etc.), but in this case, it's mainly for readability and avoiding some repetition.

Each region starts with the \z(\) atom to define your delimiter and they must end with what was captured (:h /\z1). Additionally, the delimiters can't be preceded by a backslash.

To skip the delimiters under certain circumstances, the \%(\s\|\\\)\@<=\z1\|\z1\k pattern is used: If it's preceded by whitespace or a backslash, or if it's followed by a keyword character, it should not be considered the end of the region.

Each region contains the others which allows nesting, giving us highlighting like this:

enter image description here

Existing plugins

I would like to point out that there are already a number of markdown syntax plugins available for Vim. There's nothing wrong with making your own, but there's plenty of reference material you could draw from, including one specifically made for pandoc.

  • I appreciate the effort, but it seems this also does not make the formattings add up. For example an emphasis inside a strong region should also still be strong and additionally have whatever formatting we specify for emphasis. Your answer's result looks great, but the formattings overwrite each other. Feb 10 '17 at 21:40
  • @Zelphir I explained how to nest them correctly and the highlights I chose were to clearly display that they were actually nesting. The extra effort to display them the way you want is your problem. To point you in the right direction: duplicate the regions and use different names for the nested highlights and style those accordingly. Be warned that the complexity of this increases with each nested highlight you want to treat this way. Users might not enjoy the effort in customizing this.
    – Tommy A
    Feb 10 '17 at 22:43

You can simply add the contains=<...> option to both the PandocEmphasis and PandocStrong to allow for nested matches:

syntax match PandocEmphasisMarker "\v(^|\s+)\zs_[^\n\t_ ]+([^_\n]|(\S_\S)|(\s_\S)|(\s+_\s+))+[^\n\t_ ]+_\ze($|\s+)" contains=PandocEmphasis
syntax match PandocEmphasis "\v\zs[^\n\t_ ]+([^_\n]|(\S_\S)|(\s_\S)|(\s+_\s+))+[^\n\t_ ]+\ze" contained contains=PandocStrongMarker

syntax match PandocStrongMarker "\v\zs\*[^\n*]+\*\ze" contains=PandocStrong
syntax match PandocStrong "\v\zs[^\n*]+\ze" contained  contains=PandocEmphasisMarker
  • No, this does not work as I thought it would. Now when there is emphasis inside of strong, it is not strong anymore, but only emphasized. For strong inside emphasis vice versa. Maybe I was not precise enough in explaining. I want their effects on the styling to add up. Nov 11 '16 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.