1" Vim syntax file
2" Language:         reStructuredText documentation format
3" Maintainer:       Nikolai Weibull <now@bitwi.se>
4" Latest Revision:  2010-01-23
5
6if exists("b:current_syntax")
7  finish
8endif
9
10let s:cpo_save = &cpo
11set cpo&vim
12
13syn case ignore
14
15syn match   rstSections "^\%(\([=`:.'"~^_*+#-]\)\1\+\n\)\=.\+\n\([=`:.'"~^_*+#-]\)\2\+$"
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'
51      \ nextgroup=@rstDirectives,rstComment,rstSubstitutionDefinition
52
53let s:ReferenceName = '[[:alnum:]]\+\%([_.-][[:alnum:]]\+\)*'
54
55syn keyword     rstTodo             contained FIXME TODO XXX NOTE
56
57execute 'syn region rstComment contained' .
58      \ ' start=/.*/'
59      \ ' end=/^\s\@!/ contains=rstTodo'
60
61execute 'syn region rstFootnote contained matchgroup=rstDirective' .
62      \ ' start=+\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]\_s+' .
63      \ ' skip=+^$+' .
64      \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell'
65
66execute 'syn region rstCitation contained matchgroup=rstDirective' .
67      \ ' start=+\[' . s:ReferenceName . '\]\_s+' .
68      \ ' skip=+^$+' .
69      \ ' end=+^\s\@!+ contains=@rstCruft,@NoSpell'
70
71syn region rstHyperlinkTarget contained matchgroup=rstDirective
72      \ start='_\%(_\|[^:\\]*\%(\\.[^:\\]*\)*\):\_s' skip=+^$+ end=+^\s\@!+
73
74syn region rstHyperlinkTarget contained matchgroup=rstDirective
75      \ start='_`[^`\\]*\%(\\.[^`\\]*\)*`:\_s' skip=+^$+ end=+^\s\@!+
76
77syn region rstHyperlinkTarget matchgroup=rstDirective
78      \ start=+^__\_s+ skip=+^$+ end=+^\s\@!+
79
80execute 'syn region rstExDirective contained matchgroup=rstDirective' .
81      \ ' start=+' . s:ReferenceName . '::\_s+' .
82      \ ' skip=+^$+' .
83      \ ' end=+^\s\@!+ contains=@rstCruft'
84
85execute 'syn match rstSubstitutionDefinition contained' .
86      \ ' /|' . s:ReferenceName . '|\_s\+/ nextgroup=@rstDirectives'
87
88function! s:DefineOneInlineMarkup(name, start, middle, end, char_left, char_right)
89  execute 'syn region rst' . a:name .
90        \ ' start=+' . a:char_left . '\zs' . a:start .
91        \ '\ze[^[:space:]' . a:char_right . a:start[strlen(a:start) - 1] . ']+' .
92        \ a:middle .
93        \ ' end=+\S' . a:end . '\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+'
94endfunction
95
96function! s:DefineInlineMarkup(name, start, middle, end)
97  let middle = a:middle != "" ?
98        \ (' skip=+\\\\\|\\' . a:middle . '+') :
99        \ ""
100
101  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, "'", "'")
102  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '"', '"') 
103  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '(', ')') 
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
108  call s:DefineOneInlineMarkup(a:name, a:start, middle, a:end, '\%(^\|\s\|[/:]\)', '')
109
110  execute 'syn match rst' . a:name .
111        \ ' +\%(^\|\s\|[''"([{</:]\)\zs' . a:start .
112        \ '[^[:space:]' . a:start[strlen(a:start) - 1] . ']'
113        \ a:end . '\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+'
114
115  execute 'hi def link rst' . a:name . 'Delimiter' . ' rst' . a:name
116endfunction
117
118call s:DefineInlineMarkup('Emphasis', '\*', '\*', '\*')
119call s:DefineInlineMarkup('StrongEmphasis', '\*\*', '\*', '\*\*')
120call s:DefineInlineMarkup('InterpretedTextOrHyperlinkReference', '`', '`', '`_\{0,2}')
121call s:DefineInlineMarkup('InlineLiteral', '``', "", '``')
122call s:DefineInlineMarkup('SubstitutionReference', '|', '|', '|_\{0,2}')
123call s:DefineInlineMarkup('InlineInternalTargets', '_`', '`', '`')
124
125" TODO: Can’t remember why these two can’t be defined like the ones above.
126execute 'syn match rstFootnoteReference contains=@NoSpell' .
127      \ ' +\[\%(\d\+\|#\%(' . s:ReferenceName . '\)\=\|\*\)\]_+'
128
129execute 'syn match rstCitationReference contains=@NoSpell' .
130      \ ' +\[' . s:ReferenceName . '\]_\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)+'
131
132execute 'syn match rstHyperlinkReference' .
133      \ ' /\<' . s:ReferenceName . '__\=\ze\%($\|\s\|[''")\]}>/:.,;!?\\-]\)/'
134
135syn match   rstStandaloneHyperlink  contains=@NoSpell
136      \ "\<\%(\%(\%(https\=\|file\|ftp\|gopher\)://\|\%(mailto\|news\):\)[^[:space:]'\"<>]\+\|www[[:alnum:]_-]*\.[[:alnum:]_-]\+\.[^[:space:]'\"<>]\+\)[[:alnum:]/]"
137
138" TODO: Use better syncing.  I don’t know the specifics of syncing well enough,
139" though.
140syn sync minlines=50 linebreaks=1
141
142hi def link rstTodo                         Todo
143hi def link rstComment                      Comment
144hi def link rstSections                     Type
145hi def link rstTransition                   Type
146hi def link rstLiteralBlock                 String
147hi def link rstQuotedLiteralBlock           String
148hi def link rstDoctestBlock                 PreProc
149hi def link rstTableLines                   rstDelimiter
150hi def link rstSimpleTableLines             rstTableLines
151hi def link rstExplicitMarkup               rstDirective
152hi def link rstDirective                    Keyword
153hi def link rstFootnote                     String
154hi def link rstCitation                     String
155hi def link rstHyperlinkTarget              String
156hi def link rstExDirective                  String
157hi def link rstSubstitutionDefinition       rstDirective
158hi def link rstDelimiter                    Delimiter
159" TODO: I dunno...
160hi def      rstEmphasis                     term=italic cterm=italic gui=italic
161hi def link rstStrongEmphasis               Special
162"term=bold cterm=bold gui=bold
163hi def link rstInterpretedTextOrHyperlinkReference  Identifier
164hi def link rstInlineLiteral                String
165hi def link rstSubstitutionReference        PreProc
166hi def link rstInlineInternalTargets        Identifier
167hi def link rstFootnoteReference            Identifier
168hi def link rstCitationReference            Identifier
169hi def link rstHyperLinkReference           Identifier
170hi def link rstStandaloneHyperlink          Identifier
171
172let b:current_syntax = "rst"
173
174let &cpo = s:cpo_save
175unlet s:cpo_save
176