1" Vim reST syntax file 2" Language: reStructuredText documentation format 3" Maintainer: Marshall Ward <[email protected]> 4" Previous Maintainer: Nikolai Weibull <[email protected]> 5" Website: https://github.com/marshallward/vim-restructuredtext 6" Latest Revision: 2020-03-31 7 8if exists("b:current_syntax") 9 finish 10endif 11 12let s:cpo_save = &cpo 13set cpo&vim 14 15syn case ignore 16 17syn match rstTransition /^[=`:.'"~^_*+#-]\{4,}\s*$/ 18 19syn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis, 20 \ rstInterpretedText,rstInlineLiteral,rstSubstitutionReference, 21 \ rstInlineInternalTargets,rstFootnoteReference,rstHyperlinkReference 22 23syn region rstLiteralBlock matchgroup=rstDelimiter 24 \ start='\(^\z(\s*\).*\)\@<=::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!' 25 \ contains=@NoSpell 26 27syn region rstQuotedLiteralBlock matchgroup=rstDelimiter 28 \ start="::\_s*\n\ze\z([!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]\)" 29 \ end='^\z1\@!' contains=@NoSpell 30 31syn region rstDoctestBlock oneline display matchgroup=rstDelimiter 32 \ start='^>>>\s' end='^$' 33 34syn region rstTable transparent start='^\n\s*+[-=+]\+' end='^$' 35 \ contains=rstTableLines,@rstCruft 36syn match rstTableLines contained display '|\|+\%(=\+\|-\+\)\=' 37 38syn region rstSimpleTable transparent 39 \ start='^\n\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 40 \ end='^$' 41 \ contains=rstSimpleTableLines,@rstCruft 42syn match rstSimpleTableLines contained display 43 \ '^\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 44syn match rstSimpleTableLines contained display 45 \ '^\%(\s*\)\@>\%(\%(-\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(-\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 46 47syn cluster rstDirectives contains=rstFootnote,rstCitation, 48 \ rstHyperlinkTarget,rstExDirective 49 50syn match rstExplicitMarkup '^\s*\.\.\_s' 51 \ nextgroup=@rstDirectives,rstComment,rstSubstitutionDefinition 52 53" "Simple reference names are single words consisting of alphanumerics plus 54" isolated (no two adjacent) internal hyphens, underscores, periods, colons 55" and plus signs." 56let s:ReferenceName = '[[:alnum:]]\%([-_.:+]\?[[:alnum:]]\+\)*' 57 58syn keyword rstTodo contained FIXME TODO XXX NOTE 59 60execute 'syn region rstComment contained' . 61 \ ' start=/.*/' 62 \ ' skip=+^$+' . 63 \ ' end=/^\s\@!/ contains=rstTodo' 64 65execute 'syn region rstFootnote contained matchgroup=rstDirective' . 66 \ ' start=+\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]\_s+' . 67 \ ' skip=+^$+' . 68 \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell' 69 70execute 'syn region rstCitation contained matchgroup=rstDirective' . 71 \ ' start=+\[' . s:ReferenceName . '\]\_s+' . 72 \ ' skip=+^$+' . 73 \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell' 74 75syn region rstHyperlinkTarget contained matchgroup=rstDirective 76 \ start='_\%(_\|[^:\\]*\%(\\.[^:\\]*\)*\):\_s' skip=+^$+ end=+^\s\@!+ 77 78syn region rstHyperlinkTarget contained matchgroup=rstDirective 79 \ start='_`[^`\\]*\%(\\.[^`\\]*\)*`:\_s' skip=+^$+ end=+^\s\@!+ 80 81syn region rstHyperlinkTarget matchgroup=rstDirective 82 \ start=+^__\_s+ skip=+^$+ end=+^\s\@!+ 83 84execute 'syn region rstExDirective contained matchgroup=rstDirective' . 85 \ ' start=+' . s:ReferenceName . '::\_s+' . 86 \ ' skip=+^$+' . 87 \ ' end=+^\s\@!+ contains=@rstCruft,rstLiteralBlock' 88 89execute 'syn match rstSubstitutionDefinition contained' . 90 \ ' /|.*|\_s\+/ nextgroup=@rstDirectives' 91 92function! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_right) 93 " Only escape the first char of a multichar delimiter (e.g. \* inside **) 94 if a:start[0] == '\' 95 let first = a:start[0:1] 96 else 97 let first = a:start[0] 98 endif 99 100 execute 'syn match rstEscape'.a:name.' +\\\\\|\\'.first.'+'.' contained' 101 102 execute 'syn region rst' . a:name . 103 \ ' start=+' . a:char_left . '\zs' . a:start . 104 \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' . 105 \ a:middle . 106 \ ' end=+' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+' . 107 \ ' contains=rstEscape' . a:name 108 109 execute 'hi def link rstEscape'.a:name.' Special' 110endfunction 111 112function! s:DefineInlineMarkup(name, start, middle, end) 113 let middle = a:middle != "" ? 114 \ (' skip=+\\\\\|\\' . a:middle . '\|\s' . a:middle . '+') : 115 \ "" 116 117 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'") 118 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '"', '"') 119 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '(', ')') 120 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\[', '\]') 121 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '{', '}') 122 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '<', '>') 123 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '’', '’') 124 " TODO: Additional Unicode Pd, Po, Pi, Pf, Ps characters 125 126 call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|\%ua0\|[/:]\)', '') 127 128 execute 'syn match rst' . a:name . 129 \ ' +\%(^\|\s\|\%ua0\|[''"([{</:]\)\zs' . a:start . 130 \ '[^[:space:]' . a:start[strlen(a:start) - 1] . ']' 131 \ a:end . '\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' 132 133 execute 'hi def link rst' . a:name . 'Delimiter' . ' rst' . a:name 134endfunction 135 136call s:DefineInlineMarkup('Emphasis', '\*', '\*', '\*') 137call s:DefineInlineMarkup('StrongEmphasis', '\*\*', '\*', '\*\*') 138call s:DefineInlineMarkup('InterpretedTextOrHyperlinkReference', '`', '`', '`_\{0,2}') 139call s:DefineInlineMarkup('InlineLiteral', '``', "", '``') 140call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}') 141call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`') 142 143" Sections are identified through their titles, which are marked up with 144" adornment: "underlines" below the title text, or underlines and matching 145" "overlines" above the title. An underline/overline is a single repeated 146" punctuation character that begins in column 1 and forms a line extending at 147" least as far as the right edge of the title text. 148" 149" It is difficult to count characters in a regex, but we at least special-case 150" the case where the title has at least three characters to require the 151" adornment to have at least three characters as well, in order to handle 152" properly the case of a literal block: 153" 154" this is the end of a paragraph 155" :: 156" this is a literal block 157syn match rstSections "\v^%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+$" 158 \ contains=@Spell 159syn match rstSections "\v^%(([=`:.'"~^_*+#-])\1{2,}\n)?.{3,}\n([=`:.'"~^_*+#-])\2{2,}$" 160 \ contains=@Spell 161 162" TODO: Can’t remember why these two can’t be defined like the ones above. 163execute 'syn match rstFootnoteReference contains=@NoSpell' . 164 \ ' +\%(\s\|^\)\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+' 165 166execute 'syn match rstCitationReference contains=@NoSpell' . 167 \ ' +\%(\s\|^\)\[' . s:ReferenceName . '\]_\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' 168 169execute 'syn match rstHyperlinkReference' . 170 \ ' /\<' . s:ReferenceName . '__\=\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)/' 171 172syn match rstStandaloneHyperlink contains=@NoSpell 173 \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]" 174 175syn region rstCodeBlock contained matchgroup=rstDirective 176 \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s*\(\S*\)\?\s*\n\%(\s*:.*:\s*.*\s*\n\)*\n\ze\z(\s\+\)+ 177 \ skip=+^$+ 178 \ end=+^\z1\@!+ 179 \ contains=@NoSpell 180syn cluster rstDirectives add=rstCodeBlock 181 182if !exists('g:rst_syntax_code_list') 183 " A mapping from a Vim filetype to a list of alias patterns (pattern 184 " branches to be specific, see ':help /pattern'). E.g. given: 185 " 186 " let g:rst_syntax_code_list = { 187 " \ 'cpp': ['cpp', 'c++'], 188 " \ } 189 " 190 " then the respective contents of the following two rST directives: 191 " 192 " .. code:: cpp 193 " 194 " auto i = 42; 195 " 196 " .. code:: C++ 197 " 198 " auto i = 42; 199 " 200 " will both be highlighted as C++ code. As shown by the latter block 201 " pattern matching will be case-insensitive. 202 let g:rst_syntax_code_list = { 203 \ 'vim': ['vim'], 204 \ 'java': ['java'], 205 \ 'cpp': ['cpp', 'c++'], 206 \ 'lisp': ['lisp'], 207 \ 'php': ['php'], 208 \ 'python': ['python'], 209 \ 'perl': ['perl'], 210 \ 'sh': ['sh'], 211 \ } 212elseif type(g:rst_syntax_code_list) == type([]) 213 " backward compatibility with former list format 214 let s:old_spec = g:rst_syntax_code_list 215 let g:rst_syntax_code_list = {} 216 for s:elem in s:old_spec 217 let g:rst_syntax_code_list[s:elem] = [s:elem] 218 endfor 219endif 220 221for s:filetype in keys(g:rst_syntax_code_list) 222 unlet! b:current_syntax 223 " guard against setting 'isk' option which might cause problems (issue #108) 224 let prior_isk = &l:iskeyword 225 let s:alias_pattern = '' 226 \.'\%(' 227 \.join(g:rst_syntax_code_list[s:filetype], '\|') 228 \.'\)' 229 230 exe 'syn include @rst'.s:filetype.' syntax/'.s:filetype.'.vim' 231 exe 'syn region rstDirective'.s:filetype 232 \.' matchgroup=rstDirective fold' 233 \.' start="\c\%(sourcecode\|code\%(-block\)\=\)::\s\+'.s:alias_pattern.'\_s*\n\ze\z(\s\+\)"' 234 \.' skip=#^$#' 235 \.' end=#^\z1\@!#' 236 \.' contains=@NoSpell,@rst'.s:filetype 237 exe 'syn cluster rstDirectives add=rstDirective'.s:filetype 238 239 " reset 'isk' setting, if it has been changed 240 if &l:iskeyword !=# prior_isk 241 let &l:iskeyword = prior_isk 242 endif 243 unlet! prior_isk 244endfor 245 246" Enable top level spell checking 247syntax spell toplevel 248 249" TODO: Use better syncing. 250syn sync minlines=50 linebreaks=2 251 252hi def link rstTodo Todo 253hi def link rstComment Comment 254hi def link rstSections Title 255hi def link rstTransition rstSections 256hi def link rstLiteralBlock String 257hi def link rstQuotedLiteralBlock String 258hi def link rstDoctestBlock PreProc 259hi def link rstTableLines rstDelimiter 260hi def link rstSimpleTableLines rstTableLines 261hi def link rstExplicitMarkup rstDirective 262hi def link rstDirective Keyword 263hi def link rstFootnote String 264hi def link rstCitation String 265hi def link rstHyperlinkTarget String 266hi def link rstExDirective String 267hi def link rstSubstitutionDefinition rstDirective 268hi def link rstDelimiter Delimiter 269hi def link rstInterpretedTextOrHyperlinkReference Identifier 270hi def link rstInlineLiteral String 271hi def link rstSubstitutionReference PreProc 272hi def link rstInlineInternalTargets Identifier 273hi def link rstFootnoteReference Identifier 274hi def link rstCitationReference Identifier 275hi def link rstHyperLinkReference Identifier 276hi def link rstStandaloneHyperlink Identifier 277hi def link rstCodeBlock String 278if exists('g:rst_use_emphasis_colors') 279 " TODO: Less arbitrary color selection 280 hi def rstEmphasis ctermfg=13 term=italic cterm=italic gui=italic 281 hi def rstStrongEmphasis ctermfg=1 term=bold cterm=bold gui=bold 282else 283 hi def rstEmphasis term=italic cterm=italic gui=italic 284 hi def rstStrongEmphasis term=bold cterm=bold gui=bold 285endif 286 287let b:current_syntax = "rst" 288 289let &cpo = s:cpo_save 290unlet s:cpo_save 291