1*d1caa941SBram Moolenaar" Vim reST syntax file 242eeac35SBram Moolenaar" Language: reStructuredText documentation format 37b61a546SBram Moolenaar" Maintainer: Marshall Ward <[email protected]> 47b61a546SBram Moolenaar" Previous Maintainer: Nikolai Weibull <[email protected]> 57571d55fSBram Moolenaar" Website: https://github.com/marshallward/vim-restructuredtext 6*d1caa941SBram Moolenaar" Latest Revision: 2020-03-31 7071d4279SBram Moolenaar 842eeac35SBram Moolenaarif exists("b:current_syntax") 9071d4279SBram Moolenaar finish 10071d4279SBram Moolenaarendif 11071d4279SBram Moolenaar 1242eeac35SBram Moolenaarlet s:cpo_save = &cpo 1342eeac35SBram Moolenaarset cpo&vim 1442eeac35SBram Moolenaar 15071d4279SBram Moolenaarsyn case ignore 16071d4279SBram Moolenaar 175c73622aSBram Moolenaarsyn match rstTransition /^[=`:.'"~^_*+#-]\{4,}\s*$/ 18071d4279SBram Moolenaar 19779b74b2SBram Moolenaarsyn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis, 20779b74b2SBram Moolenaar \ rstInterpretedText,rstInlineLiteral,rstSubstitutionReference, 21779b74b2SBram Moolenaar \ rstInlineInternalTargets,rstFootnoteReference,rstHyperlinkReference 22779b74b2SBram Moolenaar 23779b74b2SBram Moolenaarsyn region rstLiteralBlock matchgroup=rstDelimiter 24*d1caa941SBram Moolenaar \ start='\(^\z(\s*\).*\)\@<=::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!' 25779b74b2SBram Moolenaar \ contains=@NoSpell 26779b74b2SBram Moolenaar 27779b74b2SBram Moolenaarsyn region rstQuotedLiteralBlock matchgroup=rstDelimiter 28779b74b2SBram Moolenaar \ start="::\_s*\n\ze\z([!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]\)" 29779b74b2SBram Moolenaar \ end='^\z1\@!' contains=@NoSpell 30779b74b2SBram Moolenaar 31779b74b2SBram Moolenaarsyn region rstDoctestBlock oneline display matchgroup=rstDelimiter 3242eeac35SBram Moolenaar \ start='^>>>\s' end='^$' 33071d4279SBram Moolenaar 3442eeac35SBram Moolenaarsyn region rstTable transparent start='^\n\s*+[-=+]\+' end='^$' 3542eeac35SBram Moolenaar \ contains=rstTableLines,@rstCruft 36779b74b2SBram Moolenaarsyn match rstTableLines contained display '|\|+\%(=\+\|-\+\)\=' 37779b74b2SBram Moolenaar 3842eeac35SBram Moolenaarsyn region rstSimpleTable transparent 39899dddf8SBram Moolenaar \ start='^\n\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 4042eeac35SBram Moolenaar \ end='^$' 4142eeac35SBram Moolenaar \ contains=rstSimpleTableLines,@rstCruft 4242eeac35SBram Moolenaarsyn match rstSimpleTableLines contained display 43899dddf8SBram Moolenaar \ '^\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 44779b74b2SBram Moolenaarsyn match rstSimpleTableLines contained display 45779b74b2SBram Moolenaar \ '^\%(\s*\)\@>\%(\%(-\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(-\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 46071d4279SBram Moolenaar 47779b74b2SBram Moolenaarsyn cluster rstDirectives contains=rstFootnote,rstCitation, 48779b74b2SBram Moolenaar \ rstHyperlinkTarget,rstExDirective 49071d4279SBram Moolenaar 507b61a546SBram Moolenaarsyn match rstExplicitMarkup '^\s*\.\.\_s' 51779b74b2SBram Moolenaar \ nextgroup=@rstDirectives,rstComment,rstSubstitutionDefinition 52071d4279SBram Moolenaar 5391f84f6eSBram Moolenaar" "Simple reference names are single words consisting of alphanumerics plus 5491f84f6eSBram Moolenaar" isolated (no two adjacent) internal hyphens, underscores, periods, colons 5591f84f6eSBram Moolenaar" and plus signs." 5691f84f6eSBram Moolenaarlet s:ReferenceName = '[[:alnum:]]\%([-_.:+]\?[[:alnum:]]\+\)*' 57071d4279SBram Moolenaar 58779b74b2SBram Moolenaarsyn keyword rstTodo contained FIXME TODO XXX NOTE 59071d4279SBram Moolenaar 60779b74b2SBram Moolenaarexecute 'syn region rstComment contained' . 61779b74b2SBram Moolenaar \ ' start=/.*/' 624c05fa08SBram Moolenaar \ ' skip=+^$+' . 63779b74b2SBram Moolenaar \ ' end=/^\s\@!/ contains=rstTodo' 64071d4279SBram Moolenaar 65779b74b2SBram Moolenaarexecute 'syn region rstFootnote contained matchgroup=rstDirective' . 66779b74b2SBram Moolenaar \ ' start=+\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]\_s+' . 67779b74b2SBram Moolenaar \ ' skip=+^$+' . 68779b74b2SBram Moolenaar \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell' 69071d4279SBram Moolenaar 70779b74b2SBram Moolenaarexecute 'syn region rstCitation contained matchgroup=rstDirective' . 71779b74b2SBram Moolenaar \ ' start=+\[' . s:ReferenceName . '\]\_s+' . 72779b74b2SBram Moolenaar \ ' skip=+^$+' . 73779b74b2SBram Moolenaar \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell' 74071d4279SBram Moolenaar 75779b74b2SBram Moolenaarsyn region rstHyperlinkTarget contained matchgroup=rstDirective 76779b74b2SBram Moolenaar \ start='_\%(_\|[^:\\]*\%(\\.[^:\\]*\)*\):\_s' skip=+^$+ end=+^\s\@!+ 77071d4279SBram Moolenaar 78779b74b2SBram Moolenaarsyn region rstHyperlinkTarget contained matchgroup=rstDirective 79779b74b2SBram Moolenaar \ start='_`[^`\\]*\%(\\.[^`\\]*\)*`:\_s' skip=+^$+ end=+^\s\@!+ 80071d4279SBram Moolenaar 81779b74b2SBram Moolenaarsyn region rstHyperlinkTarget matchgroup=rstDirective 82779b74b2SBram Moolenaar \ start=+^__\_s+ skip=+^$+ end=+^\s\@!+ 83779b74b2SBram Moolenaar 84779b74b2SBram Moolenaarexecute 'syn region rstExDirective contained matchgroup=rstDirective' . 85779b74b2SBram Moolenaar \ ' start=+' . s:ReferenceName . '::\_s+' . 86779b74b2SBram Moolenaar \ ' skip=+^$+' . 8712969c04SBram Moolenaar \ ' end=+^\s\@!+ contains=@rstCruft,rstLiteralBlock' 88779b74b2SBram Moolenaar 89779b74b2SBram Moolenaarexecute 'syn match rstSubstitutionDefinition contained' . 9091f84f6eSBram Moolenaar \ ' /|.*|\_s\+/ nextgroup=@rstDirectives' 91779b74b2SBram Moolenaar 92779b74b2SBram Moolenaarfunction! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_right) 93*d1caa941SBram Moolenaar " Only escape the first char of a multichar delimiter (e.g. \* inside **) 94*d1caa941SBram Moolenaar if a:start[0] == '\' 95*d1caa941SBram Moolenaar let first = a:start[0:1] 96*d1caa941SBram Moolenaar else 97*d1caa941SBram Moolenaar let first = a:start[0] 98*d1caa941SBram Moolenaar endif 99*d1caa941SBram Moolenaar 100*d1caa941SBram Moolenaar execute 'syn match rstEscape'.a:name.' +\\\\\|\\'.first.'+'.' contained' 101*d1caa941SBram Moolenaar 102779b74b2SBram Moolenaar execute 'syn region rst' . a:name . 103779b74b2SBram Moolenaar \ ' start=+' . a:char_left . '\zs' . a:start . 10425394022SBram Moolenaar \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' . 105779b74b2SBram Moolenaar \ a:middle . 106*d1caa941SBram Moolenaar \ ' end=+' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+' . 107*d1caa941SBram Moolenaar \ ' contains=rstEscape' . a:name 108*d1caa941SBram Moolenaar 109*d1caa941SBram Moolenaar execute 'hi def link rstEscape'.a:name.' Special' 110779b74b2SBram Moolenaarendfunction 111779b74b2SBram Moolenaar 112779b74b2SBram Moolenaarfunction! s:DefineInlineMarkup(name, start, middle, end) 113779b74b2SBram Moolenaar let middle = a:middle != "" ? 114*d1caa941SBram Moolenaar \ (' skip=+\\\\\|\\' . a:middle . '\|\s' . a:middle . '+') : 115779b74b2SBram Moolenaar \ "" 116779b74b2SBram Moolenaar 117779b74b2SBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'") 118779b74b2SBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '"', '"') 119779b74b2SBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '(', ')') 120779b74b2SBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\[', '\]') 121779b74b2SBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '{', '}') 122779b74b2SBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '<', '>') 1237571d55fSBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '’', '’') 1247571d55fSBram Moolenaar " TODO: Additional Unicode Pd, Po, Pi, Pf, Ps characters 125779b74b2SBram Moolenaar 12691f84f6eSBram Moolenaar call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|\%ua0\|[/:]\)', '') 127779b74b2SBram Moolenaar 128779b74b2SBram Moolenaar execute 'syn match rst' . a:name . 12991f84f6eSBram Moolenaar \ ' +\%(^\|\s\|\%ua0\|[''"([{</:]\)\zs' . a:start . 130779b74b2SBram Moolenaar \ '[^[:space:]' . a:start[strlen(a:start) - 1] . ']' 131779b74b2SBram Moolenaar \ a:end . '\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' 132779b74b2SBram Moolenaar 133779b74b2SBram Moolenaar execute 'hi def link rst' . a:name . 'Delimiter' . ' rst' . a:name 134779b74b2SBram Moolenaarendfunction 135779b74b2SBram Moolenaar 136779b74b2SBram Moolenaarcall s:DefineInlineMarkup('Emphasis', '\*', '\*', '\*') 137779b74b2SBram Moolenaarcall s:DefineInlineMarkup('StrongEmphasis', '\*\*', '\*', '\*\*') 138779b74b2SBram Moolenaarcall s:DefineInlineMarkup('InterpretedTextOrHyperlinkReference', '`', '`', '`_\{0,2}') 139779b74b2SBram Moolenaarcall s:DefineInlineMarkup('InlineLiteral', '``', "", '``') 140779b74b2SBram Moolenaarcall s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}') 141779b74b2SBram Moolenaarcall s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`') 142779b74b2SBram Moolenaar 14391f84f6eSBram Moolenaar" Sections are identified through their titles, which are marked up with 14491f84f6eSBram Moolenaar" adornment: "underlines" below the title text, or underlines and matching 14591f84f6eSBram Moolenaar" "overlines" above the title. An underline/overline is a single repeated 14691f84f6eSBram Moolenaar" punctuation character that begins in column 1 and forms a line extending at 14791f84f6eSBram Moolenaar" least as far as the right edge of the title text. 14891f84f6eSBram Moolenaar" 14991f84f6eSBram Moolenaar" It is difficult to count characters in a regex, but we at least special-case 15091f84f6eSBram Moolenaar" the case where the title has at least three characters to require the 15191f84f6eSBram Moolenaar" adornment to have at least three characters as well, in order to handle 15291f84f6eSBram Moolenaar" properly the case of a literal block: 15391f84f6eSBram Moolenaar" 15491f84f6eSBram Moolenaar" this is the end of a paragraph 15591f84f6eSBram Moolenaar" :: 15691f84f6eSBram Moolenaar" this is a literal block 15791f84f6eSBram Moolenaarsyn match rstSections "\v^%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+$" 15891f84f6eSBram Moolenaar \ contains=@Spell 15991f84f6eSBram Moolenaarsyn match rstSections "\v^%(([=`:.'"~^_*+#-])\1{2,}\n)?.{3,}\n([=`:.'"~^_*+#-])\2{2,}$" 16091f84f6eSBram Moolenaar \ contains=@Spell 161345efa01SBram Moolenaar 162779b74b2SBram Moolenaar" TODO: Can’t remember why these two can’t be defined like the ones above. 163779b74b2SBram Moolenaarexecute 'syn match rstFootnoteReference contains=@NoSpell' . 16491f84f6eSBram Moolenaar \ ' +\%(\s\|^\)\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+' 165779b74b2SBram Moolenaar 166779b74b2SBram Moolenaarexecute 'syn match rstCitationReference contains=@NoSpell' . 16791f84f6eSBram Moolenaar \ ' +\%(\s\|^\)\[' . s:ReferenceName . '\]_\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' 168779b74b2SBram Moolenaar 169779b74b2SBram Moolenaarexecute 'syn match rstHyperlinkReference' . 17025394022SBram Moolenaar \ ' /\<' . s:ReferenceName . '__\=\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)/' 171779b74b2SBram Moolenaar 172779b74b2SBram Moolenaarsyn match rstStandaloneHyperlink contains=@NoSpell 173779b74b2SBram Moolenaar \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]" 174779b74b2SBram Moolenaar 17597d62497SBram Moolenaarsyn region rstCodeBlock contained matchgroup=rstDirective 176*d1caa941SBram Moolenaar \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s*\(\S*\)\?\s*\n\%(\s*:.*:\s*.*\s*\n\)*\n\ze\z(\s\+\)+ 17797d62497SBram Moolenaar \ skip=+^$+ 1787b61a546SBram Moolenaar \ end=+^\z1\@!+ 17997d62497SBram Moolenaar \ contains=@NoSpell 18097d62497SBram Moolenaarsyn cluster rstDirectives add=rstCodeBlock 18197d62497SBram Moolenaar 18297d62497SBram Moolenaarif !exists('g:rst_syntax_code_list') 18391f84f6eSBram Moolenaar " A mapping from a Vim filetype to a list of alias patterns (pattern 18491f84f6eSBram Moolenaar " branches to be specific, see ':help /pattern'). E.g. given: 18591f84f6eSBram Moolenaar " 18691f84f6eSBram Moolenaar " let g:rst_syntax_code_list = { 18791f84f6eSBram Moolenaar " \ 'cpp': ['cpp', 'c++'], 18891f84f6eSBram Moolenaar " \ } 18991f84f6eSBram Moolenaar " 19091f84f6eSBram Moolenaar " then the respective contents of the following two rST directives: 19191f84f6eSBram Moolenaar " 19291f84f6eSBram Moolenaar " .. code:: cpp 19391f84f6eSBram Moolenaar " 19491f84f6eSBram Moolenaar " auto i = 42; 19591f84f6eSBram Moolenaar " 19691f84f6eSBram Moolenaar " .. code:: C++ 19791f84f6eSBram Moolenaar " 19891f84f6eSBram Moolenaar " auto i = 42; 19991f84f6eSBram Moolenaar " 20091f84f6eSBram Moolenaar " will both be highlighted as C++ code. As shown by the latter block 20191f84f6eSBram Moolenaar " pattern matching will be case-insensitive. 20291f84f6eSBram Moolenaar let g:rst_syntax_code_list = { 20391f84f6eSBram Moolenaar \ 'vim': ['vim'], 20491f84f6eSBram Moolenaar \ 'java': ['java'], 20591f84f6eSBram Moolenaar \ 'cpp': ['cpp', 'c++'], 20691f84f6eSBram Moolenaar \ 'lisp': ['lisp'], 20791f84f6eSBram Moolenaar \ 'php': ['php'], 20891f84f6eSBram Moolenaar \ 'python': ['python'], 20991f84f6eSBram Moolenaar \ 'perl': ['perl'], 21091f84f6eSBram Moolenaar \ 'sh': ['sh'], 21191f84f6eSBram Moolenaar \ } 21291f84f6eSBram Moolenaarelseif type(g:rst_syntax_code_list) == type([]) 21391f84f6eSBram Moolenaar " backward compatibility with former list format 21491f84f6eSBram Moolenaar let s:old_spec = g:rst_syntax_code_list 21591f84f6eSBram Moolenaar let g:rst_syntax_code_list = {} 21691f84f6eSBram Moolenaar for s:elem in s:old_spec 21791f84f6eSBram Moolenaar let g:rst_syntax_code_list[s:elem] = [s:elem] 21891f84f6eSBram Moolenaar endfor 21997d62497SBram Moolenaarendif 22097d62497SBram Moolenaar 22191f84f6eSBram Moolenaarfor s:filetype in keys(g:rst_syntax_code_list) 22297d62497SBram Moolenaar unlet! b:current_syntax 2237d76c804SBram Moolenaar " guard against setting 'isk' option which might cause problems (issue #108) 2247d76c804SBram Moolenaar let prior_isk = &l:iskeyword 22591f84f6eSBram Moolenaar let s:alias_pattern = '' 22691f84f6eSBram Moolenaar \.'\%(' 22791f84f6eSBram Moolenaar \.join(g:rst_syntax_code_list[s:filetype], '\|') 22891f84f6eSBram Moolenaar \.'\)' 22991f84f6eSBram Moolenaar 23091f84f6eSBram Moolenaar exe 'syn include @rst'.s:filetype.' syntax/'.s:filetype.'.vim' 23191f84f6eSBram Moolenaar exe 'syn region rstDirective'.s:filetype 23291f84f6eSBram Moolenaar \.' matchgroup=rstDirective fold' 23391f84f6eSBram Moolenaar \.' start="\c\%(sourcecode\|code\%(-block\)\=\)::\s\+'.s:alias_pattern.'\_s*\n\ze\z(\s\+\)"' 23497d62497SBram Moolenaar \.' skip=#^$#' 235a02a551eSBram Moolenaar \.' end=#^\z1\@!#' 23691f84f6eSBram Moolenaar \.' contains=@NoSpell,@rst'.s:filetype 23791f84f6eSBram Moolenaar exe 'syn cluster rstDirectives add=rstDirective'.s:filetype 23891f84f6eSBram Moolenaar 2397d76c804SBram Moolenaar " reset 'isk' setting, if it has been changed 2407d76c804SBram Moolenaar if &l:iskeyword !=# prior_isk 2417d76c804SBram Moolenaar let &l:iskeyword = prior_isk 2427d76c804SBram Moolenaar endif 2437d76c804SBram Moolenaar unlet! prior_isk 24497d62497SBram Moolenaarendfor 24597d62497SBram Moolenaar 24691f84f6eSBram Moolenaar" Enable top level spell checking 24791f84f6eSBram Moolenaarsyntax spell toplevel 24891f84f6eSBram Moolenaar 249203d04d7SBram Moolenaar" TODO: Use better syncing. 250203d04d7SBram Moolenaarsyn sync minlines=50 linebreaks=2 251203d04d7SBram Moolenaar 25242eeac35SBram Moolenaarhi def link rstTodo Todo 25342eeac35SBram Moolenaarhi def link rstComment Comment 2549b451250SBram Moolenaarhi def link rstSections Title 2559b451250SBram Moolenaarhi def link rstTransition rstSections 256779b74b2SBram Moolenaarhi def link rstLiteralBlock String 257779b74b2SBram Moolenaarhi def link rstQuotedLiteralBlock String 25842eeac35SBram Moolenaarhi def link rstDoctestBlock PreProc 259779b74b2SBram Moolenaarhi def link rstTableLines rstDelimiter 26042eeac35SBram Moolenaarhi def link rstSimpleTableLines rstTableLines 261779b74b2SBram Moolenaarhi def link rstExplicitMarkup rstDirective 26242eeac35SBram Moolenaarhi def link rstDirective Keyword 263779b74b2SBram Moolenaarhi def link rstFootnote String 264779b74b2SBram Moolenaarhi def link rstCitation String 265779b74b2SBram Moolenaarhi def link rstHyperlinkTarget String 266779b74b2SBram Moolenaarhi def link rstExDirective String 267779b74b2SBram Moolenaarhi def link rstSubstitutionDefinition rstDirective 268779b74b2SBram Moolenaarhi def link rstDelimiter Delimiter 269779b74b2SBram Moolenaarhi def link rstInterpretedTextOrHyperlinkReference Identifier 270779b74b2SBram Moolenaarhi def link rstInlineLiteral String 271779b74b2SBram Moolenaarhi def link rstSubstitutionReference PreProc 272779b74b2SBram Moolenaarhi def link rstInlineInternalTargets Identifier 273779b74b2SBram Moolenaarhi def link rstFootnoteReference Identifier 274779b74b2SBram Moolenaarhi def link rstCitationReference Identifier 275779b74b2SBram Moolenaarhi def link rstHyperLinkReference Identifier 276779b74b2SBram Moolenaarhi def link rstStandaloneHyperlink Identifier 27797d62497SBram Moolenaarhi def link rstCodeBlock String 27891f84f6eSBram Moolenaarif exists('g:rst_use_emphasis_colors') 27991f84f6eSBram Moolenaar " TODO: Less arbitrary color selection 28091f84f6eSBram Moolenaar hi def rstEmphasis ctermfg=13 term=italic cterm=italic gui=italic 28191f84f6eSBram Moolenaar hi def rstStrongEmphasis ctermfg=1 term=bold cterm=bold gui=bold 28291f84f6eSBram Moolenaarelse 28391f84f6eSBram Moolenaar hi def rstEmphasis term=italic cterm=italic gui=italic 28491f84f6eSBram Moolenaar hi def rstStrongEmphasis term=bold cterm=bold gui=bold 28591f84f6eSBram Moolenaarendif 286071d4279SBram Moolenaar 287071d4279SBram Moolenaarlet b:current_syntax = "rst" 288071d4279SBram Moolenaar 28942eeac35SBram Moolenaarlet &cpo = s:cpo_save 29042eeac35SBram Moolenaarunlet s:cpo_save 291