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