xref: /vim-8.2.3635/runtime/syntax/rst.vim (revision 81ea1dfb)
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