├── README.rst ├── autoload └── RstFold.vim ├── ftplugin └── rst.vim ├── indent └── rst.vim ├── syntax └── rst.vim └── tests ├── codeblocks.txt ├── comments.txt ├── doctest_block.txt ├── escape_delim.txt ├── footnotes_and_citations.txt ├── literal_block.txt ├── roles.txt ├── spellchecking.txt └── tables.txt /README.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Vim reStructuredText Runtime 3 | ============================ 4 | 5 | This is the development repository for Vim's reStructuredText syntax file. 6 | -------------------------------------------------------------------------------- /autoload/RstFold.vim: -------------------------------------------------------------------------------- 1 | " Author: Antony Lee 2 | " Description: Helper functions for reStructuredText syntax folding 3 | " Last Modified: 2018-12-29 4 | 5 | function s:CacheRstFold() 6 | if !g:rst_fold_enabled 7 | return 8 | endif 9 | 10 | let closure = {'header_types': {}, 'max_level': 0, 'levels': {}} 11 | function closure.Process(match) dict 12 | let curline = getcurpos()[1] 13 | if has_key(self.levels, curline - 1) 14 | " For over+under-lined headers, the regex will match both at the 15 | " overline and at the title itself; in that case, skip the second match. 16 | return 17 | endif 18 | let lines = split(a:match, '\n') 19 | let key = repeat(lines[-1][0], len(lines)) 20 | if !has_key(self.header_types, key) 21 | let self.max_level += 1 22 | let self.header_types[key] = self.max_level 23 | endif 24 | let self.levels[curline] = self.header_types[key] 25 | endfunction 26 | let save_cursor = getcurpos() 27 | let save_mark = getpos("'[") 28 | silent keeppatterns %s/\v^%(%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+)|%(%(([=`:.''"~^_*+#-])\3{2,}\n)?.{3,}\n([=`:.''"~^_*+#-])\4{2,})$/\=closure.Process(submatch(0))/gn 29 | call setpos('.', save_cursor) 30 | call setpos("'[", save_mark) 31 | let b:RstFoldCache = closure.levels 32 | endfunction 33 | 34 | function RstFold#GetRstFold() 35 | if !g:rst_fold_enabled 36 | return 37 | endif 38 | 39 | if !has_key(b:, 'RstFoldCache') 40 | call s:CacheRstFold() 41 | endif 42 | if has_key(b:RstFoldCache, v:lnum) 43 | return '>' . b:RstFoldCache[v:lnum] 44 | else 45 | return '=' 46 | endif 47 | endfunction 48 | 49 | function RstFold#GetRstFoldText() 50 | if !g:rst_fold_enabled 51 | return 52 | endif 53 | 54 | if !has_key(b:, 'RstFoldCache') 55 | call s:CacheRstFold() 56 | endif 57 | let indent = repeat(' ', b:RstFoldCache[v:foldstart] - 1) 58 | let thisline = getline(v:foldstart) 59 | " For over+under-lined headers, skip the overline. 60 | let text = thisline =~ '^\([=`:.''"~^_*+#-]\)\1\+$' ? getline(v:foldstart + 1) : thisline 61 | return indent . text 62 | endfunction 63 | -------------------------------------------------------------------------------- /ftplugin/rst.vim: -------------------------------------------------------------------------------- 1 | " reStructuredText filetype plugin file 2 | " Language: reStructuredText documentation format 3 | " Maintainer: Marshall Ward 4 | " Original Maintainer: Nikolai Weibull 5 | " Website: https://github.com/marshallward/vim-restructuredtext 6 | " Latest Revision: 2020-03-31 7 | 8 | if exists("b:did_ftplugin") 9 | finish 10 | endif 11 | let b:did_ftplugin = 1 12 | 13 | let s:cpo_save = &cpo 14 | set cpo&vim 15 | 16 | "Disable folding 17 | if !exists('g:rst_fold_enabled') 18 | let g:rst_fold_enabled = 0 19 | endif 20 | 21 | let b:undo_ftplugin = "setlocal comments< commentstring< expandtab< formatoptions<" 22 | 23 | setlocal comments=fb:.. commentstring=..\ %s expandtab 24 | setlocal formatoptions+=tcroql 25 | 26 | " reStructuredText standard recommends that tabs be expanded to 8 spaces 27 | " The choice of 3-space indentation is to provide slightly better support for 28 | " directives (..) and ordered lists (1.), although it can cause problems for 29 | " many other cases. 30 | " 31 | " More sophisticated indentation rules should be revisted in the future. 32 | 33 | if exists("g:rst_style") && g:rst_style != 0 34 | setlocal expandtab shiftwidth=3 softtabstop=3 tabstop=8 35 | let b:undo_ftplugin .= " | setlocal softtabstop< shiftwidth< tabstop<" 36 | endif 37 | 38 | if g:rst_fold_enabled != 0 && has('patch-7.3.867') " Introduced the TextChanged event. 39 | setlocal foldmethod=expr 40 | setlocal foldexpr=RstFold#GetRstFold() 41 | setlocal foldtext=RstFold#GetRstFoldText() 42 | augroup RstFold 43 | autocmd TextChanged,InsertLeave unlet! b:RstFoldCache 44 | augroup END 45 | let b:undo_ftplugin .= " | setlocal foldexpr< foldmethod< foldtext<" 46 | endif 47 | 48 | let &cpo = s:cpo_save 49 | unlet s:cpo_save 50 | -------------------------------------------------------------------------------- /indent/rst.vim: -------------------------------------------------------------------------------- 1 | " Vim indent file 2 | " Vim reST indent file 3 | " Language: reStructuredText Documentation Format 4 | " Maintainer: Marshall Ward 5 | " Previous Maintainer: Nikolai Weibull 6 | " Latest Revision: 2020-03-31 7 | 8 | if exists("b:did_indent") 9 | finish 10 | endif 11 | let b:did_indent = 1 12 | 13 | setlocal indentexpr=GetRSTIndent() 14 | setlocal indentkeys=!^F,o,O 15 | setlocal nosmartindent 16 | 17 | let b:undo_indent = "setlocal indentexpr< indentkeys< smartindent<" 18 | 19 | if exists("*GetRSTIndent") 20 | finish 21 | endif 22 | 23 | let s:itemization_pattern = '^\s*[-*+]\s' 24 | let s:enumeration_pattern = '^\s*\%(\d\+\|#\)\.\s\+' 25 | let s:note_pattern = '^\.\. ' 26 | 27 | function! s:get_paragraph_start() 28 | let paragraph_mark_start = getpos("'{")[1] 29 | return getline(paragraph_mark_start) =~ 30 | \ '\S' ? paragraph_mark_start : paragraph_mark_start + 1 31 | endfunction 32 | 33 | function GetRSTIndent() 34 | let lnum = prevnonblank(v:lnum - 1) 35 | if lnum == 0 36 | return 0 37 | endif 38 | 39 | let ind = indent(lnum) 40 | let line = getline(lnum) 41 | 42 | let psnum = s:get_paragraph_start() 43 | if psnum != 0 44 | if getline(psnum) =~ s:note_pattern 45 | let ind = max([3, ind]) 46 | endif 47 | endif 48 | 49 | if line =~ s:itemization_pattern 50 | let ind += 2 51 | elseif line =~ s:enumeration_pattern 52 | let ind += matchend(line, s:enumeration_pattern) 53 | endif 54 | 55 | let line = getline(v:lnum - 1) 56 | 57 | " Indent :FIELD: lines. Don’t match if there is no text after the field or 58 | " if the text ends with a sent-ender. 59 | if line =~ '^:.\+:\s\{-1,\}\S.\+[^.!?:]$' 60 | return matchend(line, '^:.\{-1,}:\s\+') 61 | endif 62 | 63 | if line =~ '^\s*$' 64 | execute lnum 65 | call search('^\s*\%([-*+]\s\|\%(\d\+\|#\)\.\s\|\.\.\|$\)', 'bW') 66 | let line = getline('.') 67 | if line =~ s:itemization_pattern 68 | let ind -= 2 69 | elseif line =~ s:enumeration_pattern 70 | let ind -= matchend(line, s:enumeration_pattern) 71 | elseif line =~ '^\s*\.\.' 72 | let ind -= 3 73 | endif 74 | endif 75 | 76 | return ind 77 | endfunction 78 | -------------------------------------------------------------------------------- /syntax/rst.vim: -------------------------------------------------------------------------------- 1 | " Vim reST syntax file 2 | " Language: reStructuredText documentation format 3 | " Maintainer: Marshall Ward 4 | " Previous Maintainer: Nikolai Weibull 5 | " Website: https://github.com/marshallward/vim-restructuredtext 6 | " Latest Revision: 2025-03-06 7 | 8 | if exists("b:current_syntax") 9 | finish 10 | endif 11 | 12 | let s:cpo_save = &cpo 13 | set cpo&vim 14 | 15 | syn case ignore 16 | 17 | syn match rstTransition /^[=`:.'"~^_*+#-]\{4,}\s*$/ 18 | 19 | syn cluster rstCruft contains=rstEmphasis,rstStrongEmphasis, 20 | \ rstInterpretedTextOrHyperlinkReference,rstInlineLiteral, 21 | \ rstSubstitutionReference, rstInlineInternalTargets,rstFootnoteReference, 22 | \ rstHyperlinkReference 23 | 24 | syn region rstLiteralBlock matchgroup=rstDelimiter 25 | \ start='\(^\z(\s*\).*\)\@<=::\n\s*\n' skip='^\s*$' end='^\(\z1\s\+\)\@!' 26 | \ contains=@NoSpell 27 | 28 | syn region rstQuotedLiteralBlock matchgroup=rstDelimiter 29 | \ start="::\_s*\n\ze\z([!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]\)" 30 | \ end='^\z1\@!' contains=@NoSpell 31 | 32 | syn region rstDoctestBlock matchgroup=rstDoctestBlockPrompt 33 | \ start='^>>>\s' end='^$' 34 | \ contains=rstDoctestBlockPrompt 35 | 36 | syn match rstDoctestBlockPrompt contained '^>>>\s' 37 | 38 | syn region rstTable transparent start='^\n\s*+[-=+]\+' end='^$' 39 | \ contains=rstTableLines,@rstCruft 40 | syn match rstTableLines contained display '|\|+\%(=\+\|-\+\)\=' 41 | 42 | syn region rstSimpleTable transparent 43 | \ start='^\n\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 44 | \ end='^$' 45 | \ contains=rstSimpleTableLines,@rstCruft 46 | syn match rstSimpleTableLines contained display 47 | \ '^\%(\s*\)\@>\%(\%(=\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(=\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 48 | syn match rstSimpleTableLines contained display 49 | \ '^\%(\s*\)\@>\%(\%(-\+\)\@>\%(\s\+\)\@>\)\%(\%(\%(-\+\)\@>\%(\s*\)\@>\)\+\)\@>$' 50 | 51 | syn cluster rstDirectives contains=rstFootnote,rstCitation, 52 | \ rstHyperlinkTarget,rstExDirective 53 | 54 | syn match rstExplicitMarkup '^\s*\.\.\_s' 55 | \ nextgroup=@rstDirectives,rstSubstitutionDefinition 56 | \ contains=rstComment 57 | 58 | " "Simple reference names are single words consisting of alphanumerics plus 59 | " isolated (no two adjacent) internal hyphens, underscores, periods, colons 60 | " and plus signs." 61 | let s:ReferenceName = '[[:alnum:]]\%([-_.:+]\?[[:alnum:]]\+\)*' 62 | 63 | syn keyword rstTodo contained FIXME TODO XXX NOTE 64 | 65 | syn region rstComment 66 | \ start='\v^\z(\s*)\.\.(\_s+[\[|_]|\_s+.*::)@!' skip=+^$+ end=/^\(\z1 \)\@!/ 67 | \ contains=@Spell,rstTodo 68 | 69 | " Note: Order matters for rstCitation and rstFootnote as the regex for 70 | " citations also matches numeric only patterns, e.g. [1], which are footnotes. 71 | " Since we define rstFootnote after rstCitation, it takes precedence, see 72 | " |:syn-define|. 73 | execute 'syn region rstCitation contained matchgroup=rstDirective' . 74 | \ ' start=+\[' . s:ReferenceName . '\]\_s+' . 75 | \ ' skip=+^$+' . 76 | \ ' end=+^\s\@!+ contains=@Spell,@rstCruft' 77 | 78 | execute 'syn region rstFootnote contained matchgroup=rstDirective' . 79 | \ ' start=+\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]\_s+' . 80 | \ ' skip=+^$+' . 81 | \ ' end=+^\s\@!+ contains=@Spell,@rstCruft' 82 | 83 | syn region rstHyperlinkTarget contained matchgroup=rstDirective 84 | \ start='_\%(_\|[^:\\]*\%(\\.[^:\\]*\)*\):\_s' skip=+^$+ end=+^\s\@!+ 85 | 86 | syn region rstHyperlinkTarget contained matchgroup=rstDirective 87 | \ start='_`[^`\\]*\%(\\.[^`\\]*\)*`:\_s' skip=+^$+ end=+^\s\@!+ 88 | 89 | syn region rstHyperlinkTarget matchgroup=rstDirective 90 | \ start=+^__\_s+ skip=+^$+ end=+^\s\@!+ 91 | 92 | execute 'syn region rstExDirective contained matchgroup=rstDirective' . 93 | \ ' start=+' . s:ReferenceName . '::\_s+' . 94 | \ ' skip=+^$+' . 95 | \ ' end=+^\s\@!+ contains=@Spell,@rstCruft,rstLiteralBlock,rstExplicitMarkup' 96 | 97 | execute 'syn match rstSubstitutionDefinition contained' . 98 | \ ' /|.*|\_s\+/ nextgroup=@rstDirectives' 99 | 100 | function! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_right) 101 | " Only escape the first char of a multichar delimiter (e.g. \* inside **) 102 | if a:start[0] == '\' 103 | let first = a:start[0:1] 104 | else 105 | let first = a:start[0] 106 | endif 107 | 108 | if a:start != '``' 109 | let rst_contains=' contains=@Spell,rstEscape' . a:name 110 | execute 'syn match rstEscape'.a:name.' +\\\\\|\\'.first.'+'.' contained' 111 | else 112 | let rst_contains=' contains=@Spell' 113 | endif 114 | 115 | execute 'syn region rst' . a:name . 116 | \ ' start=+' . a:char_left . '\zs' . a:start . 117 | \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' . 118 | \ a:middle . 119 | \ ' end=+' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+' . 120 | \ rst_contains 121 | 122 | if a:start != '``' 123 | execute 'hi def link rstEscape'.a:name.' Special' 124 | endif 125 | endfunction 126 | 127 | " TODO: The "middle" argument may no longer be useful here. 128 | function! s:DefineInlineMarkup(name, start, middle, end) 129 | if a:middle == '`' 130 | let middle = ' skip=+\s'.a:middle.'+' 131 | else 132 | let middle = ' skip=+\\\\\|\\' . a:middle . '\|\s' . a:middle . '+' 133 | endif 134 | 135 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'") 136 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '"', '"') 137 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '(', ')') 138 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\[', '\]') 139 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '{', '}') 140 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '<', '>') 141 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '’', '’') 142 | 143 | " TODO: Additional whitespace Unicode characters: Pd, Po, Pi, Pf, Ps 144 | call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|\%ua0\|[/:]\)', '') 145 | 146 | execute 'syn match rst' . a:name . 147 | \ ' +\%(^\|\s\|\%ua0\|[''"([{/:.,;!?\\-]\)+' 150 | 151 | execute 'hi def link rst' . a:name . 'Delimiter' . ' rst' . a:name 152 | endfunction 153 | 154 | call s:DefineInlineMarkup('Emphasis', '\*', '\*', '\*') 155 | call s:DefineInlineMarkup('StrongEmphasis', '\*\*', '\*', '\*\*') 156 | call s:DefineInlineMarkup('InterpretedTextOrHyperlinkReference', '`', '`', '`_\{0,2}') 157 | call s:DefineInlineMarkup('InlineLiteral', '``', '`', '``') 158 | call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}') 159 | call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`') 160 | 161 | " Sections are identified through their titles, which are marked up with 162 | " adornment: "underlines" below the title text, or underlines and matching 163 | " "overlines" above the title. An underline/overline is a single repeated 164 | " punctuation character that begins in column 1 and forms a line extending at 165 | " least as far as the right edge of the title text. 166 | " 167 | " It is difficult to count characters in a regex, but we at least special-case 168 | " the case where the title has at least three characters to require the 169 | " adornment to have at least three characters as well, in order to handle 170 | " properly the case of a literal block: 171 | " 172 | " this is the end of a paragraph 173 | " :: 174 | " this is a literal block 175 | syn match rstSections "\v^%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+$" 176 | \ contains=@Spell 177 | syn match rstSections "\v^%(([=`:.'"~^_*+#-])\1{2,}\n)?.{3,}\n([=`:.'"~^_*+#-])\2{2,}$" 178 | \ contains=@Spell 179 | 180 | " TODO: Can’t remember why these two can’t be defined like the ones above. 181 | execute 'syn match rstFootnoteReference contains=@NoSpell' . 182 | \ ' +\%(\s\|^\)\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+' 183 | 184 | execute 'syn match rstCitationReference contains=@NoSpell' . 185 | \ ' +\%(\s\|^\)\[' . s:ReferenceName . '\]_\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+' 186 | 187 | execute 'syn match rstHyperlinkReference' . 188 | \ ' /\<' . s:ReferenceName . '__\=\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)/' 189 | 190 | syn match rstStandaloneHyperlink contains=@NoSpell 191 | \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]" 192 | 193 | syn region rstCodeBlock contained matchgroup=rstDirective 194 | \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s*\(\S*\)\?\s*\n\%(\s*:.*:\s*.*\s*\n\)*\n\ze\z(\s\+\)+ 195 | \ skip=+^$+ 196 | \ end=+^\z1\@!+ 197 | \ contains=@NoSpell 198 | syn cluster rstDirectives add=rstCodeBlock 199 | 200 | if !exists('g:rst_syntax_code_list') 201 | " A mapping from a Vim filetype to a list of alias patterns (pattern 202 | " branches to be specific, see ':help /pattern'). E.g. given: 203 | " 204 | " let g:rst_syntax_code_list = { 205 | " \ 'cpp': ['cpp', 'c++'], 206 | " \ } 207 | " 208 | " then the respective contents of the following two rST directives: 209 | " 210 | " .. code:: cpp 211 | " 212 | " auto i = 42; 213 | " 214 | " .. code:: C++ 215 | " 216 | " auto i = 42; 217 | " 218 | " will both be highlighted as C++ code. As shown by the latter block 219 | " pattern matching will be case-insensitive. 220 | let g:rst_syntax_code_list = { 221 | \ 'vim': ['vim'], 222 | \ 'java': ['java'], 223 | \ 'cpp': ['cpp', 'c++'], 224 | \ 'lisp': ['lisp'], 225 | \ 'php': ['php'], 226 | \ 'python': ['python'], 227 | \ 'perl': ['perl'], 228 | \ 'sh': ['sh'], 229 | \ } 230 | elseif type(g:rst_syntax_code_list) == type([]) 231 | " backward compatibility with former list format 232 | let s:old_spec = g:rst_syntax_code_list 233 | let g:rst_syntax_code_list = {} 234 | for s:elem in s:old_spec 235 | let g:rst_syntax_code_list[s:elem] = [s:elem] 236 | endfor 237 | endif 238 | 239 | for s:filetype in keys(g:rst_syntax_code_list) 240 | unlet! b:current_syntax 241 | " guard against setting 'isk' option which might cause problems (issue #108) 242 | let prior_isk = &l:iskeyword 243 | let s:alias_pattern = '' 244 | \.'\%(' 245 | \.join(g:rst_syntax_code_list[s:filetype], '\|') 246 | \.'\)' 247 | 248 | exe 'syn include @rst'.s:filetype.' syntax/'.s:filetype.'.vim' 249 | exe 'syn region rstDirective'.s:filetype 250 | \.' matchgroup=rstDirective fold' 251 | \.' start="\c\%(sourcecode\|code\%(-block\)\=\)::\s\+'.s:alias_pattern.'\_s*\n\ze\z(\s\+\)"' 252 | \.' skip=#^$#' 253 | \.' end=#^\z1\@!#' 254 | \.' contains=@NoSpell,@rst'.s:filetype 255 | exe 'syn cluster rstDirectives add=rstDirective'.s:filetype 256 | 257 | " reset 'isk' setting, if it has been changed 258 | if &l:iskeyword !=# prior_isk 259 | let &l:iskeyword = prior_isk 260 | endif 261 | unlet! prior_isk 262 | endfor 263 | 264 | " Enable top level spell checking 265 | syntax spell toplevel 266 | 267 | exe "syn sync minlines=" . get(g:, 'rst_minlines', 50) . " linebreaks=2" 268 | 269 | hi def link rstTodo Todo 270 | hi def link rstComment Comment 271 | hi def link rstSections Title 272 | hi def link rstTransition rstSections 273 | hi def link rstLiteralBlock String 274 | hi def link rstQuotedLiteralBlock String 275 | hi def link rstDoctestBlock PreProc 276 | hi def link rstDoctestBlockPrompt rstDelimiter 277 | hi def link rstTableLines rstDelimiter 278 | hi def link rstSimpleTableLines rstTableLines 279 | hi def link rstExplicitMarkup rstDirective 280 | hi def link rstDirective Keyword 281 | hi def link rstFootnote String 282 | hi def link rstCitation String 283 | hi def link rstHyperlinkTarget String 284 | hi def link rstExDirective String 285 | hi def link rstSubstitutionDefinition rstDirective 286 | hi def link rstDelimiter Delimiter 287 | hi def link rstInterpretedTextOrHyperlinkReference Identifier 288 | hi def link rstInlineLiteral String 289 | hi def link rstSubstitutionReference PreProc 290 | hi def link rstInlineInternalTargets Identifier 291 | hi def link rstFootnoteReference Identifier 292 | hi def link rstCitationReference Identifier 293 | hi def link rstHyperLinkReference Identifier 294 | hi def link rstStandaloneHyperlink Identifier 295 | hi def link rstCodeBlock String 296 | if exists('g:rst_use_emphasis_colors') 297 | " TODO: Less arbitrary color selection 298 | hi def rstEmphasis ctermfg=13 term=italic cterm=italic gui=italic 299 | hi def rstStrongEmphasis ctermfg=1 term=bold cterm=bold gui=bold 300 | else 301 | hi def rstEmphasis term=italic cterm=italic gui=italic 302 | hi def rstStrongEmphasis term=bold cterm=bold gui=bold 303 | endif 304 | 305 | let b:current_syntax = "rst" 306 | 307 | let &cpo = s:cpo_save 308 | unlet s:cpo_save 309 | -------------------------------------------------------------------------------- /tests/codeblocks.txt: -------------------------------------------------------------------------------- 1 | Generic code block 2 | 3 | .. code:: 4 | 5 | int main(void) { 6 | return 0; 7 | } 8 | 9 | A recognized code block (rst_syntax_code_list) 10 | 11 | .. code:: cpp 12 | 13 | int main(void) { 14 | return 0; 15 | } 16 | 17 | Code block of language off list 18 | 19 | .. code:: fortran 20 | 21 | program main 22 | implicit none 23 | end program main 24 | 25 | Trailing whitespace 26 | 27 | .. code:: 28 | 29 | int main(void) { 30 | return 0; 31 | } 32 | 33 | Ignoring inline literals inside a code block 34 | 35 | .. code:: 36 | 37 | ls *.{c,h} 38 | 39 | Fields 40 | 41 | .. code:: 42 | :name: main 43 | :number-lines: 44 | 45 | int main(void) { 46 | return 0; 47 | } 48 | 49 | Fields with a named language (not currently working) 50 | 51 | .. code:: cpp 52 | :name: main 53 | :number-lines: 54 | 55 | int main(void) { 56 | return 0; 57 | } 58 | 59 | Code blocks require a blank line after the directive, so this should not 60 | highlight. (Note: currently fails) 61 | 62 | .. code:: 63 | int main(void) { 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tests/comments.txt: -------------------------------------------------------------------------------- 1 | .. this is a comment 2 | 3 | .. a-directive:: 4 | 5 | plain text 6 | 7 | .. a comment 8 | 9 | again, not a comment 10 | 11 | .. [#] not a comment either 12 | 13 | .. a-directive-with:: args 14 | 15 | .. _not-a-comment: 16 | 17 | .. _not-a-comment-either: some://url 18 | -------------------------------------------------------------------------------- /tests/doctest_block.txt: -------------------------------------------------------------------------------- 1 | Simple doctest with multiple lines of output. 2 | 3 | >>> print('this is a Doctest block') 4 | this is a Doctest block 5 | this is a Doctest block (repeat) 6 | 7 | Subsequent prompts ``>>>`` inside a single doctest block should be highlighted. 8 | 9 | >>> print('this is a Doctest block') 10 | this is a Doctest block 11 | >>> print('this is a second Doctest block') 12 | this is a second Doctest block 13 | 14 | Even more text. 15 | -------------------------------------------------------------------------------- /tests/escape_delim.txt: -------------------------------------------------------------------------------- 1 | Inline delimiters: 2 | 3 | start *Testing delimiters* end 4 | 5 | Escape character inside delimiter: 6 | 7 | start *This has\\a slash* end 8 | 9 | Escape the delimiter: 10 | 11 | start *This has\*a delimiter* end 12 | 13 | Delimiters with leading spaces do not act as delimiters: 14 | [space][delim][non-space]...[non-space][delim][space] 15 | 16 | start *This token * is not a delim* 17 | 18 | start *This token *is also not a delim* 19 | 20 | Double delimiters must also be supported: 21 | 22 | start **This is a double delim** end 23 | 24 | Double delimiter spaced inside of a double delimiter? 25 | 26 | start **This token ** is not a delim** end 27 | 28 | start **This token **is also not a delim** end 29 | 30 | Single delimiters are escaped inside of double delimiters 31 | 32 | start **This is \** a double delimiters inside a double delimiter** end 33 | 34 | start **This one is \*\* escaped twice** end 35 | 36 | Escape slashes inside delimiters. 37 | 38 | This should render a single slash. 39 | 40 | start *C:\\* end 41 | 42 | This should raise an error due to an unclosed delimiter. 43 | 44 | start *C:\* end 45 | 46 | (Putting a delimiter here* to balance the syntax highlighting error.) 47 | 48 | But there is an exception for the end of `` tokens: 49 | 50 | Inline literal without escape characters: 51 | 52 | start ``Text is highlighted`` end 53 | 54 | start ``This slash\is unescaped`` end 55 | 56 | start ``This has\\two slashes and is not escaped`` end 57 | 58 | start ``This slash\`is also not escaped`` end 59 | 60 | This renders a single slash and should not be escaped: 61 | 62 | start ``C:\`` end 63 | 64 | Space-separated inline literal tokens do not terminate the region: 65 | 66 | start ``C:\ `` C:\`` end 67 | 68 | This renders two slashes: 69 | 70 | start ``C:\\`` end 71 | 72 | The end 73 | -------------------------------------------------------------------------------- /tests/footnotes_and_citations.txt: -------------------------------------------------------------------------------- 1 | Text [1]_ with [#ref]_ footnotes [*]_ and [CIT200]_ citations. 2 | 3 | .. [1] I'm a footnote! 4 | .. [#ref] I'm a footnote, too. 5 | .. [*] I'm a footnote, too, too! 6 | .. [CIT200] I'm a citation. 7 | -------------------------------------------------------------------------------- /tests/literal_block.txt: -------------------------------------------------------------------------------- 1 | Literal block test cases 2 | ------------------------ 3 | 4 | This is a paragraph with a literal block. 5 | 6 | :: 7 | 8 | This is a valid literal block. 9 | 10 | This is a new paragraph. 11 | 12 | ---- 13 | 14 | I am a block of text 15 | 16 | I am a subblock of text 17 | 18 | :: 19 | 20 | I am a literal subblock 21 | 22 | I am still inside the subblock but outside the literal block. 23 | 24 | ---- 25 | 26 | Staggered block:: 27 | 28 | abc 29 | def 30 | 31 | End of block 32 | 33 | ---- 34 | 35 | Reverse staggered block:: 36 | 37 | abc 38 | def 39 | 40 | End of block 41 | 42 | ---- 43 | 44 | This example does not have an additional blank line, and should not render. 45 | 46 | :: 47 | This is not a valid literal block. 48 | 49 | ---- 50 | 51 | This example does not end with a blank line, and will usually raise an error. 52 | 53 | :: 54 | 55 | This is not a valid literal block. 56 | This paragraph invalidates the block. 57 | 58 | (Currently we do not indicate this error) 59 | 60 | ---- 61 | 62 | This paragraph has an inline literal block:: 63 | 64 | This is a valid literal block. 65 | 66 | ---- 67 | 68 | Whitespace before :: changes the substitution but is otherwise valid. :: 69 | 70 | This is a valid literal block. 71 | 72 | ---- 73 | 74 | An *inline* literal should not break the parsing. :: 75 | 76 | This is a valid literal block. 77 | 78 | This appears to be working now. 79 | 80 | ---- 81 | 82 | This is effectively an inline literal block with prior whitespace (``\n``), 83 | since the next line is considered part of the paragraph. 84 | :: 85 | 86 | This is a valid literal block. 87 | 88 | ---- 89 | 90 | The prepended blank line is optional. 91 | :: 92 | 93 | This is a valid literal block. 94 | 95 | ---- 96 | 97 | Here's one with some whitespace in its blank line. It should work. 98 | 99 | :: 100 | 101 | This is a valid literal block. 102 | 103 | ---- 104 | 105 | And here is multiple empty lines. 106 | 107 | :: 108 | 109 | 110 | 111 | This is a valid literal block. 112 | 113 | ---- 114 | 115 | And here is multiple empty lines with lots of random whitespace. 116 | 117 | :: 118 | 119 | 120 | 121 | 122 | This is a valid literal block. 123 | 124 | ---- 125 | 126 | This is the same except the final line also has whitespace. 127 | 128 | :: 129 | 130 | 131 | 132 | 133 | This is a valid literal block. 134 | 135 | ---- 136 | 137 | and now I'm done. 138 | -------------------------------------------------------------------------------- /tests/roles.txt: -------------------------------------------------------------------------------- 1 | Roles and interpreted text 2 | -------------------------- 3 | 4 | Roles such as :emphasis:`this one` but also :youneverheardofme:`custom roles` and :py:class:`domain roles` should be recognised in both :myrole:`pre` and `post`:myrole: post syntax. 5 | 6 | Field lists should not be recognised as roles: 7 | 8 | :Date: 2001-08-16 9 | :Version: 1 10 | :Authors: Me 11 | :Parameter i: integer 12 | 13 | 14 | The following text is taken from the `reStructuredText Markup Specification`_: 15 | 16 | In field lists, care must be taken when using interpreted text with explicit roles in field names: the role must be a suffix to the interpreted text. The following are recognized as field list items: 17 | 18 | :`field name`:code:: interpreted text with explicit role as suffix 19 | 20 | :a `complex`:code:\ field name: a backslash-escaped space 21 | is necessary 22 | 23 | The following are not recognized as field list items: 24 | 25 | ::code:`not a field name`: paragraph with interpreted text 26 | 27 | :code:`not a field name`: paragraph with interpreted text 28 | 29 | Edge cases: 30 | 31 | :field\:`name`: interpreted text (standard role) requires 32 | escaping the leading colon in a field name 33 | 34 | :field:\`name`: not interpreted text 35 | 36 | .. _reStructuredText Markup Specification: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#interpreted-text 37 | -------------------------------------------------------------------------------- /tests/spellchecking.txt: -------------------------------------------------------------------------------- 1 | Spell Checking 2 | ============== 3 | 4 | Normal text with wrrong woords should be spell checked. 5 | But so should text contained in inline markup, like these: 6 | 7 | *wrrong woords* 8 | **wrrong woords** 9 | `wrrong woords` 10 | ``wrrong woords`` 11 | |wrrong woords| 12 | _`wrrong woords` 13 | `wrrong woords`_ 14 | 15 | 16 | wrrong woords 17 | ------------- 18 | 19 | Headings should be spell checked. 20 | 21 | 22 | Lists 23 | ----- 24 | 25 | Lists should be spell checked 26 | 27 | * wrrong woords 28 | * wrronger woords 29 | 30 | 1. wrrong woords 31 | 2. wrronger woords 32 | 33 | Definition lists should be spell checked 34 | 35 | wrrong woords 36 | wrrong woords description 37 | 38 | also with classifiers: 39 | 40 | wrrong woords : wrronger woords 41 | wrrong woords description 42 | 43 | And so should field lists 44 | 45 | :wrrong woords: wrrong woords 46 | :wrronger woords: wrronger woords 47 | 48 | Option lists should probably only spell check the description but not the option name: 49 | 50 | -b wrrong woords 51 | --wrrong wrronger woords 52 | 53 | 54 | Literal Blocks 55 | -------------- 56 | 57 | Literal blocks should not be spell checked. 58 | 59 | Some text:: 60 | 61 | wrrong woords 62 | 63 | Some text:: 64 | 65 | > wrrong woords 66 | 67 | .. code:: 68 | 69 | wrrong woords 70 | 71 | .. code-block:: 72 | 73 | wrrong woords 74 | 75 | 76 | Line Blocks 77 | ----------- 78 | 79 | Line blocks should be spell checked: 80 | 81 | | wrrong woords 82 | | wrronger woords 83 | wrrongest woords 84 | | wrrong woords 85 | 86 | 87 | Block Quotes 88 | ------------ 89 | 90 | Some text 91 | 92 | wrrong woords 93 | 94 | -- Authorr nname 95 | 96 | 97 | Doctest Blocks 98 | -------------- 99 | 100 | Doctest block should not be spell checked: 101 | 102 | >>> wrrong woords 103 | wrronger woords 104 | 105 | 106 | Tables 107 | ------ 108 | 109 | Contents (header and body) of tables should be spell checked: 110 | 111 | +---------------+-----------------+ 112 | | wrrong woords | wrronger woords | 113 | +===============+=================+ 114 | | wrrong woords | wrronger woords | 115 | +---------------+-----------------+ 116 | | wrrong woords | wrronger woords | 117 | +---------------+-----------------+ 118 | 119 | Same for simple tables 120 | 121 | ============= =============== 122 | wrrong woords wrronger woords 123 | ============= =============== 124 | wrrong woords wrronger woords 125 | wrrong woords wrronger woords 126 | ============= =============== 127 | 128 | 129 | Footnotes and Citations 130 | ----------------------- 131 | 132 | The contents of footnotes [*]_ [#wrrong]_ and citations [woords]_ should be spell checked but not the footnote citation label itself. 133 | 134 | .. [*] wrrong woords 135 | .. [#wrrong] wrrong woords 136 | .. [woords] wrrong woords 137 | 138 | 139 | Hyperlink targets 140 | ----------------- 141 | 142 | Hyperlink targets should__ not be spell checked as they are either internal references or URLs. 143 | However the `wrrong words`_ in the text should be spell checked but not in the `target `_. 144 | 145 | .. __: wrrong woords 146 | .. _wrrong words: wrrong woords 147 | 148 | 149 | Directives 150 | ---------- 151 | 152 | Names of directives should not be spell checked: 153 | 154 | .. wrrong:: 155 | 156 | The contents of directives should be spell checked 157 | 158 | .. note:: wrrong woords 159 | 160 | .. wrrong:: 161 | 162 | wrrong woords 163 | 164 | Directive options should be spell checked (at least the options content should) 165 | 166 | .. directive:: 167 | :wrrong: woords 168 | 169 | wrronger woords 170 | 171 | 172 | Substitutions 173 | ------------- 174 | 175 | Substitutions |wrrong woords| which can contain text, should be spell checked. 176 | 177 | .. |wrrong woords| replace:: wrronger woords 178 | 179 | 180 | Comments 181 | -------- 182 | 183 | Comments should be spell checked 184 | 185 | .. wrrong woords 186 | -------------------------------------------------------------------------------- /tests/tables.txt: -------------------------------------------------------------------------------- 1 | +-------+--------+ 2 | | Hello | World | 3 | +-------+--------+ 4 | | Bye | Sun | 5 | +-------+--------+ 6 | 7 | The above table should be recognised as table and not as transition. 8 | 9 | Header 10 | ====== 11 | 12 | +-------+--------+ 13 | | Hello | World | 14 | +-------+--------+ 15 | | Bye | Sun | 16 | +-------+--------+ 17 | 18 | .. note:: 19 | 20 | A directive before a table used to confuse the table syntax. 21 | Below should be recognised as table not as transition. 22 | 23 | +-------+--------+ 24 | | Hello | World | 25 | +-------+--------+ 26 | | Bye | Sun | 27 | +-------+--------+ 28 | --------------------------------------------------------------------------------