" Vim reST syntax file " Language: reStructuredText documentation format " Maintainer: Marshall Ward " Previous Maintainer: Nikolai Weibull " Website: https://github.com/marshallward/vim-restructuredtext " Latest Revision: 2020-03-31 if exists("b:current_syntax") finish endif let s:cpo_save = &cpo set cpo&vim syn case ignore syn match rstTransition /^[=`:.'"~^_*+#-]\{4,}\s*$/ syn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis, \ rstInterpretedText,rstInlineLiteral,rstSubstitutionReference, \ rstInlineInternalTargets,rstFootnoteReference,rstHyperlinkReference syn region rstLiteralBlock matchgroup=rstDelimiter \ start='\(^\z(\s*\).*\)\@<=::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!' \ contains=@NoSpell syn region rstQuotedLiteralBlock matchgroup=rstDelimiter \ start="::\_s*\n\ze\z([!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]\)" \ end='^\z1\@!' contains=@NoSpell syn region rstDoctestBlock oneline display matchgroup=rstDelimiter \ start='^>>>\s' end='^$' syn region rstTable transparent start='^\n\s*+[-=+]\+' end='^$' \ contains=rstTableLines,@rstCruft syn match rstTableLines contained display '|\|+\%(=\+\|-\+\)\=' syn region rstSimpleTable transparent \ start='^\n\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' \ end='^$' \ contains=rstSimpleTableLines,@rstCruft syn match rstSimpleTableLines contained display \ '^\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' syn match rstSimpleTableLines contained display \ '^\%(\s*\)\@>\%(\%(-\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(-\+\)\@>\%(\s*\)\@>\)\+\)\@>$' syn cluster rstDirectives contains=rstFootnote,rstCitation, \ rstHyperlinkTarget,rstExDirective syn match rstExplicitMarkup '^\s*\.\.\_s' \ nextgroup=@rstDirectives,rstComment,rstSubstitutionDefinition " "Simple reference names are single words consisting of alphanumerics plus " isolated (no two adjacent) internal hyphens, underscores, periods, colons " and plus signs." let s:ReferenceName = '[[:alnum:]]\%([-_.:+]\?[[:alnum:]]\+\)*' syn keyword rstTodo contained FIXME TODO XXX NOTE execute 'syn region rstComment contained' . \ ' start=/.*/' \ ' skip=+^$+' . \ ' end=/^\s\@!/ contains=rstTodo' execute 'syn region rstFootnote contained matchgroup=rstDirective' . \ ' start=+\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]\_s+' . \ ' skip=+^$+' . \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell' execute 'syn region rstCitation contained matchgroup=rstDirective' . \ ' start=+\[' . s:ReferenceName . '\]\_s+' . \ ' skip=+^$+' . \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell' syn region rstHyperlinkTarget contained matchgroup=rstDirective \ start='_\%(_\|[^:\\]*\%(\\.[^:\\]*\)*\):\_s' skip=+^$+ end=+^\s\@!+ syn region rstHyperlinkTarget contained matchgroup=rstDirective \ start='_`[^`\\]*\%(\\.[^`\\]*\)*`:\_s' skip=+^$+ end=+^\s\@!+ syn region rstHyperlinkTarget matchgroup=rstDirective \ start=+^__\_s+ skip=+^$+ end=+^\s\@!+ execute 'syn region rstExDirective contained matchgroup=rstDirective' . \ ' start=+' . s:ReferenceName . '::\_s+' . \ ' skip=+^$+' . \ ' end=+^\s\@!+ contains=@rstCruft,rstLiteralBlock' execute 'syn match rstSubstitutionDefinition contained' . \ ' /|.*|\_s\+/ nextgroup=@rstDirectives' function! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_right) " Only escape the first char of a multichar delimiter (e.g. \* inside **) if a:start[0] == '\' let first = a:start[0:1] else let first = a:start[0] endif execute 'syn match rstEscape'.a:name.' +\\\\\|\\'.first.'+'.' contained' execute 'syn region rst' . a:name . \ ' start=+' . a:char_left . '\zs' . a:start . \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' . \ a:middle . \ ' end=+' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+' . \ ' contains=rstEscape' . a:name execute 'hi def link rstEscape'.a:name.' Special' endfunction function! s:DefineInlineMarkup(name, start, middle, end) let middle = a:middle != "" ? \ (' skip=+\\\\\|\\' . a:middle . '\|\s' . a:middle . '+') : \ "" call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'") call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '"', '"') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '(', ')') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\[', '\]') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '{', '}') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '<', '>') call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '’', '’') " TODO: Additional Unicode Pd, Po, Pi, Pf, Ps characters call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|\%ua0\|[/:]\)', '') execute 'syn match rst' . a:name . \ ' +\%(^\|\s\|\%ua0\|[''"([{/:.,;!?\\-]\)+' execute 'hi def link rst' . a:name . 'Delimiter' . ' rst' . a:name endfunction call s:DefineInlineMarkup('Emphasis', '\*', '\*', '\*') call s:DefineInlineMarkup('StrongEmphasis', '\*\*', '\*', '\*\*') call s:DefineInlineMarkup('InterpretedTextOrHyperlinkReference', '`', '`', '`_\{0,2}') call s:DefineInlineMarkup('InlineLiteral', '``', "", '``') call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}') call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`') " Sections are identified through their titles, which are marked up with " adornment: "underlines" below the title text, or underlines and matching " "overlines" above the title. An underline/overline is a single repeated " punctuation character that begins in column 1 and forms a line extending at " least as far as the right edge of the title text. " " It is difficult to count characters in a regex, but we at least special-case " the case where the title has at least three characters to require the " adornment to have at least three characters as well, in order to handle " properly the case of a literal block: " " this is the end of a paragraph " :: " this is a literal block syn match rstSections "\v^%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+$" \ contains=@Spell syn match rstSections "\v^%(([=`:.'"~^_*+#-])\1{2,}\n)?.{3,}\n([=`:.'"~^_*+#-])\2{2,}$" \ contains=@Spell " TODO: Can’t remember why these two can’t be defined like the ones above. execute 'syn match rstFootnoteReference contains=@NoSpell' . \ ' +\%(\s\|^\)\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+' execute 'syn match rstCitationReference contains=@NoSpell' . \ ' +\%(\s\|^\)\[' . s:ReferenceName . '\]_\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' execute 'syn match rstHyperlinkReference' . \ ' /\<' . s:ReferenceName . '__\=\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)/' syn match rstStandaloneHyperlink contains=@NoSpell \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]" syn region rstCodeBlock contained matchgroup=rstDirective \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s*\(\S*\)\?\s*\n\%(\s*:.*:\s*.*\s*\n\)*\n\ze\z(\s\+\)+ \ skip=+^$+ \ end=+^\z1\@!+ \ contains=@NoSpell syn cluster rstDirectives add=rstCodeBlock if !exists('g:rst_syntax_code_list') " A mapping from a Vim filetype to a list of alias patterns (pattern " branches to be specific, see ':help /pattern'). E.g. given: " " let g:rst_syntax_code_list = { " \ 'cpp': ['cpp', 'c++'], " \ } " " then the respective contents of the following two rST directives: " " .. code:: cpp " " auto i = 42; " " .. code:: C++ " " auto i = 42; " " will both be highlighted as C++ code. As shown by the latter block " pattern matching will be case-insensitive. let g:rst_syntax_code_list = { \ 'vim': ['vim'], \ 'java': ['java'], \ 'cpp': ['cpp', 'c++'], \ 'lisp': ['lisp'], \ 'php': ['php'], \ 'python': ['python'], \ 'perl': ['perl'], \ 'sh': ['sh'], \ } elseif type(g:rst_syntax_code_list) == type([]) " backward compatibility with former list format let s:old_spec = g:rst_syntax_code_list let g:rst_syntax_code_list = {} for s:elem in s:old_spec let g:rst_syntax_code_list[s:elem] = [s:elem] endfor endif for s:filetype in keys(g:rst_syntax_code_list) unlet! b:current_syntax " guard against setting 'isk' option which might cause problems (issue #108) let prior_isk = &l:iskeyword let s:alias_pattern = '' \.'\%(' \.join(g:rst_syntax_code_list[s:filetype], '\|') \.'\)' exe 'syn include @rst'.s:filetype.' syntax/'.s:filetype.'.vim' exe 'syn region rstDirective'.s:filetype \.' matchgroup=rstDirective fold' \.' start="\c\%(sourcecode\|code\%(-block\)\=\)::\s\+'.s:alias_pattern.'\_s*\n\ze\z(\s\+\)"' \.' skip=#^$#' \.' end=#^\z1\@!#' \.' contains=@NoSpell,@rst'.s:filetype exe 'syn cluster rstDirectives add=rstDirective'.s:filetype " reset 'isk' setting, if it has been changed if &l:iskeyword !=# prior_isk let &l:iskeyword = prior_isk endif unlet! prior_isk endfor " Enable top level spell checking syntax spell toplevel " TODO: Use better syncing. syn sync minlines=50 linebreaks=2 hi def link rstTodo Todo hi def link rstComment Comment hi def link rstSections Title hi def link rstTransition rstSections hi def link rstLiteralBlock String hi def link rstQuotedLiteralBlock String hi def link rstDoctestBlock PreProc hi def link rstTableLines rstDelimiter hi def link rstSimpleTableLines rstTableLines hi def link rstExplicitMarkup rstDirective hi def link rstDirective Keyword hi def link rstFootnote String hi def link rstCitation String hi def link rstHyperlinkTarget String hi def link rstExDirective String hi def link rstSubstitutionDefinition rstDirective hi def link rstDelimiter Delimiter hi def link rstInterpretedTextOrHyperlinkReference Identifier hi def link rstInlineLiteral String hi def link rstSubstitutionReference PreProc hi def link rstInlineInternalTargets Identifier hi def link rstFootnoteReference Identifier hi def link rstCitationReference Identifier hi def link rstHyperLinkReference Identifier hi def link rstStandaloneHyperlink Identifier hi def link rstCodeBlock String if exists('g:rst_use_emphasis_colors') " TODO: Less arbitrary color selection hi def rstEmphasis ctermfg=13 term=italic cterm=italic gui=italic hi def rstStrongEmphasis ctermfg=1 term=bold cterm=bold gui=bold else hi def rstEmphasis term=italic cterm=italic gui=italic hi def rstStrongEmphasis term=bold cterm=bold gui=bold endif let b:current_syntax = "rst" let &cpo = s:cpo_save unlet s:cpo_save