xref: /vim-8.2.3635/runtime/syntax/rst.vim (revision 577fadfc)
1" Vim 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: 2018-12-29
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='::\_s*\n\ze\z(\s\+\)' skip='^$' end='^\z1\@!'
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  execute 'syn region rst' . a:name .
94        \ ' start=+' . a:char_left . '\zs' . a:start .
95        \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' .
96        \ a:middle .
97        \ ' end=+\S' . a:end . '\ze\%($\|\s\|[''"’)\]}>/:.,;!?\\-]\)+'
98endfunction
99
100function! s:DefineInlineMarkup(name, start, middle, end)
101  let middle = a:middle != "" ?
102        \ (' skip=+\\\\\|\\' . a:middle . '+') :
103        \ ""
104
105  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'")
106  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '"', '"')
107  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '(', ')')
108  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\[', '\]')
109  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '{', '}')
110  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '<', '>')
111  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '’', '’')
112  " TODO: Additional Unicode Pd, Po, Pi, Pf, Ps characters
113
114  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|\%ua0\|[/:]\)', '')
115
116  execute 'syn match rst' . a:name .
117        \ ' +\%(^\|\s\|\%ua0\|[''"([{</:]\)\zs' . a:start .
118        \ '[^[:space:]' . a:start[strlen(a:start) - 1] . ']'
119        \ a:end . '\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+'
120
121  execute 'hi def link rst' . a:name . 'Delimiter' . ' rst' . a:name
122endfunction
123
124call s:DefineInlineMarkup('Emphasis', '\*', '\*', '\*')
125call s:DefineInlineMarkup('StrongEmphasis', '\*\*', '\*', '\*\*')
126call s:DefineInlineMarkup('InterpretedTextOrHyperlinkReference', '`', '`', '`_\{0,2}')
127call s:DefineInlineMarkup('InlineLiteral', '``', "", '``')
128call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}')
129call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`')
130
131" Sections are identified through their titles, which are marked up with
132" adornment: "underlines" below the title text, or underlines and matching
133" "overlines" above the title. An underline/overline is a single repeated
134" punctuation character that begins in column 1 and forms a line extending at
135" least as far as the right edge of the title text.
136"
137" It is difficult to count characters in a regex, but we at least special-case
138" the case where the title has at least three characters to require the
139" adornment to have at least three characters as well, in order to handle
140" properly the case of a literal block:
141"
142"    this is the end of a paragraph
143"    ::
144"       this is a literal block
145syn match   rstSections "\v^%(([=`:.'"~^_*+#-])\1+\n)?.{1,2}\n([=`:.'"~^_*+#-])\2+$"
146    \ contains=@Spell
147syn match   rstSections "\v^%(([=`:.'"~^_*+#-])\1{2,}\n)?.{3,}\n([=`:.'"~^_*+#-])\2{2,}$"
148    \ contains=@Spell
149
150" TODO: Can’t remember why these two can’t be defined like the ones above.
151execute 'syn match rstFootnoteReference contains=@NoSpell' .
152      \ ' +\%(\s\|^\)\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+'
153
154execute 'syn match rstCitationReference contains=@NoSpell' .
155      \ ' +\%(\s\|^\)\[' . s:ReferenceName . '\]_\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+'
156
157execute 'syn match rstHyperlinkReference' .
158      \ ' /\<' . s:ReferenceName . '__\=\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)/'
159
160syn match   rstStandaloneHyperlink  contains=@NoSpell
161      \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]"
162
163syn region rstCodeBlock contained matchgroup=rstDirective
164      \ start=+\%(sourcecode\|code\%(-block\)\=\)::\s\+.*\_s*\n\ze\z(\s\+\)+
165      \ skip=+^$+
166      \ end=+^\z1\@!+
167      \ contains=@NoSpell
168syn cluster rstDirectives add=rstCodeBlock
169
170if !exists('g:rst_syntax_code_list')
171    " A mapping from a Vim filetype to a list of alias patterns (pattern
172    " branches to be specific, see ':help /pattern'). E.g. given:
173    "
174    "   let g:rst_syntax_code_list = {
175    "       \ 'cpp': ['cpp', 'c++'],
176    "       \ }
177    "
178    " then the respective contents of the following two rST directives:
179    "
180    "   .. code:: cpp
181    "
182    "       auto i = 42;
183    "
184    "   .. code:: C++
185    "
186    "       auto i = 42;
187    "
188    " will both be highlighted as C++ code. As shown by the latter block
189    " pattern matching will be case-insensitive.
190    let g:rst_syntax_code_list = {
191        \ 'vim': ['vim'],
192        \ 'java': ['java'],
193        \ 'cpp': ['cpp', 'c++'],
194        \ 'lisp': ['lisp'],
195        \ 'php': ['php'],
196        \ 'python': ['python'],
197        \ 'perl': ['perl'],
198        \ 'sh': ['sh'],
199        \ }
200elseif type(g:rst_syntax_code_list) == type([])
201    " backward compatibility with former list format
202    let s:old_spec = g:rst_syntax_code_list
203    let g:rst_syntax_code_list = {}
204    for s:elem in s:old_spec
205        let g:rst_syntax_code_list[s:elem] = [s:elem]
206    endfor
207endif
208
209for s:filetype in keys(g:rst_syntax_code_list)
210    unlet! b:current_syntax
211    " guard against setting 'isk' option which might cause problems (issue #108)
212    let prior_isk = &l:iskeyword
213    let s:alias_pattern = ''
214                \.'\%('
215                \.join(g:rst_syntax_code_list[s:filetype], '\|')
216                \.'\)'
217
218    exe 'syn include @rst'.s:filetype.' syntax/'.s:filetype.'.vim'
219    exe 'syn region rstDirective'.s:filetype
220                \.' matchgroup=rstDirective fold'
221                \.' start="\c\%(sourcecode\|code\%(-block\)\=\)::\s\+'.s:alias_pattern.'\_s*\n\ze\z(\s\+\)"'
222                \.' skip=#^$#'
223                \.' end=#^\z1\@!#'
224                \.' contains=@NoSpell,@rst'.s:filetype
225    exe 'syn cluster rstDirectives add=rstDirective'.s:filetype
226
227    " reset 'isk' setting, if it has been changed
228    if &l:iskeyword !=# prior_isk
229        let &l:iskeyword = prior_isk
230    endif
231    unlet! prior_isk
232endfor
233
234" Enable top level spell checking
235syntax spell toplevel
236
237" TODO: Use better syncing.
238syn sync minlines=50 linebreaks=2
239
240hi def link rstTodo                         Todo
241hi def link rstComment                      Comment
242hi def link rstSections                     Title
243hi def link rstTransition                   rstSections
244hi def link rstLiteralBlock                 String
245hi def link rstQuotedLiteralBlock           String
246hi def link rstDoctestBlock                 PreProc
247hi def link rstTableLines                   rstDelimiter
248hi def link rstSimpleTableLines             rstTableLines
249hi def link rstExplicitMarkup               rstDirective
250hi def link rstDirective                    Keyword
251hi def link rstFootnote                     String
252hi def link rstCitation                     String
253hi def link rstHyperlinkTarget              String
254hi def link rstExDirective                  String
255hi def link rstSubstitutionDefinition       rstDirective
256hi def link rstDelimiter                    Delimiter
257hi def link rstInterpretedTextOrHyperlinkReference  Identifier
258hi def link rstInlineLiteral                String
259hi def link rstSubstitutionReference        PreProc
260hi def link rstInlineInternalTargets        Identifier
261hi def link rstFootnoteReference            Identifier
262hi def link rstCitationReference            Identifier
263hi def link rstHyperLinkReference           Identifier
264hi def link rstStandaloneHyperlink          Identifier
265hi def link rstCodeBlock                    String
266if exists('g:rst_use_emphasis_colors')
267    " TODO: Less arbitrary color selection
268    hi def rstEmphasis          ctermfg=13 term=italic cterm=italic gui=italic
269    hi def rstStrongEmphasis    ctermfg=1 term=bold cterm=bold gui=bold
270else
271    hi def rstEmphasis          term=italic cterm=italic gui=italic
272    hi def rstStrongEmphasis    term=bold cterm=bold gui=bold
273endif
274
275let b:current_syntax = "rst"
276
277let &cpo = s:cpo_save
278unlet s:cpo_save
279