1" Vim syntax file 2" Language: XML 3" Maintainer: Christian Brabandt <[email protected]> 4" Repository: https://github.com/chrisbra/vim-xml-ftplugin 5" Previous Maintainer: Johannes Zellner <[email protected]> 6" Author: Paul Siegmann <[email protected]> 7" Last Changed: Nov 03, 2019 8" Filenames: *.xml 9" Last Change: 10" 20190923 - Fix xmlEndTag to match xmlTag (vim/vim#884) 11" 20190924 - Fix xmlAttribute property (amadeus/vim-xml@d8ce1c946) 12" 20191103 - Enable spell checking globally 13 14" CONFIGURATION: 15" syntax folding can be turned on by 16" 17" let g:xml_syntax_folding = 1 18" 19" before the syntax file gets loaded (e.g. in ~/.vimrc). 20" This might slow down syntax highlighting significantly, 21" especially for large files. 22" 23" CREDITS: 24" The original version was derived by Paul Siegmann from 25" Claudio Fleiner's html.vim. 26" 27" REFERENCES: 28" [1] http://www.w3.org/TR/2000/REC-xml-20001006 29" [2] http://www.w3.org/XML/1998/06/xmlspec-report-19980910.htm 30" 31" as <[email protected]> pointed out according to reference [1] 32" 33" 2.3 Common Syntactic Constructs 34" [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender 35" [5] Name ::= (Letter | '_' | ':') (NameChar)* 36" 37" NOTE: 38" 1) empty tag delimiters "/>" inside attribute values (strings) 39" confuse syntax highlighting. 40" 2) for large files, folding can be pretty slow, especially when 41" loading a file the first time and viewoptions contains 'folds' 42" so that folds of previous sessions are applied. 43" Don't use 'foldmethod=syntax' in this case. 44 45 46" Quit when a syntax file was already loaded 47if exists("b:current_syntax") 48 finish 49endif 50 51let s:xml_cpo_save = &cpo 52set cpo&vim 53 54syn case match 55 56" Allow spell checking in tag values, 57" there is no syntax region for that, 58" so enable spell checking in top-level elements 59" <tag>This text is spell checked</tag> 60syn spell toplevel 61 62" mark illegal characters 63syn match xmlError "[<&]" 64 65" strings (inside tags) aka VALUES 66" 67" EXAMPLE: 68" 69" <tag foo.attribute = "value"> 70" ^^^^^^^ 71syn region xmlString contained start=+"+ end=+"+ contains=xmlEntity,@Spell display 72syn region xmlString contained start=+'+ end=+'+ contains=xmlEntity,@Spell display 73 74 75" punctuation (within attributes) e.g. <tag xml:foo.attribute ...> 76" ^ ^ 77" syn match xmlAttribPunct +[-:._]+ contained display 78syn match xmlAttribPunct +[:.]+ contained display 79 80" no highlighting for xmlEqual (xmlEqual has no highlighting group) 81syn match xmlEqual +=+ display 82 83 84" attribute, everything before the '=' 85" 86" PROVIDES: @xmlAttribHook 87" 88" EXAMPLE: 89" 90" <tag foo.attribute = "value"> 91" ^^^^^^^^^^^^^ 92" 93syn match xmlAttrib 94 \ +[-'"<]\@1<!\<[a-zA-Z:_][-.0-9a-zA-Z:_]*\>\%(['"]\@!\|$\)+ 95 \ contained 96 \ contains=xmlAttribPunct,@xmlAttribHook 97 \ display 98 99 100" namespace spec 101" 102" PROVIDES: @xmlNamespaceHook 103" 104" EXAMPLE: 105" 106" <xsl:for-each select = "lola"> 107" ^^^ 108" 109if exists("g:xml_namespace_transparent") 110syn match xmlNamespace 111 \ +\(<\|</\)\@2<=[^ /!?<>"':]\+[:]\@=+ 112 \ contained 113 \ contains=@xmlNamespaceHook 114 \ transparent 115 \ display 116else 117syn match xmlNamespace 118 \ +\(<\|</\)\@2<=[^ /!?<>"':]\+[:]\@=+ 119 \ contained 120 \ contains=@xmlNamespaceHook 121 \ display 122endif 123 124 125" tag name 126" 127" PROVIDES: @xmlTagHook 128" 129" EXAMPLE: 130" 131" <tag foo.attribute = "value"> 132" ^^^ 133" 134syn match xmlTagName 135 \ +\%(<\|</\)\@2<=[^ /!?<>"']\++ 136 \ contained 137 \ contains=xmlNamespace,xmlAttribPunct,@xmlTagHook 138 \ display 139 140 141if exists('g:xml_syntax_folding') 142 143 " start tag 144 " use matchgroup=xmlTag to skip over the leading '<' 145 " 146 " PROVIDES: @xmlStartTagHook 147 " 148 " EXAMPLE: 149 " 150 " <tag id="whoops"> 151 " s^^^^^^^^^^^^^^^e 152 " 153 syn region xmlTag 154 \ matchgroup=xmlTag start=+<[^ /!?<>"']\@=+ 155 \ matchgroup=xmlTag end=+>+ 156 \ contained 157 \ contains=xmlError,xmlTagName,xmlAttrib,xmlEqual,xmlString,@xmlStartTagHook 158 159 160 " highlight the end tag 161 " 162 " PROVIDES: @xmlTagHook 163 " (should we provide a separate @xmlEndTagHook ?) 164 " 165 " EXAMPLE: 166 " 167 " </tag> 168 " ^^^^^^ 169 " 170 syn region xmlEndTag 171 \ matchgroup=xmlTag start=+</[^ /!?<>"']\@=+ 172 \ matchgroup=xmlTag end=+>+ 173 \ contained 174 \ contains=xmlTagName,xmlNamespace,xmlAttribPunct,@xmlTagHook 175 176 " tag elements with syntax-folding. 177 " NOTE: NO HIGHLIGHTING -- highlighting is done by contained elements 178 " 179 " PROVIDES: @xmlRegionHook 180 " 181 " EXAMPLE: 182 " 183 " <tag id="whoops"> 184 " <!-- comment --> 185 " <another.tag></another.tag> 186 " <empty.tag/> 187 " some data 188 " </tag> 189 " 190 syn region xmlRegion 191 \ start=+<\z([^ /!?<>"']\+\)+ 192 \ skip=+<!--\_.\{-}-->+ 193 \ end=+</\z1\_\s\{-}>+ 194 \ end=+/>+ 195 \ fold 196 \ contains=xmlTag,xmlEndTag,xmlCdata,xmlRegion,xmlComment,xmlEntity,xmlProcessing,@xmlRegionHook,@Spell 197 \ keepend 198 \ extend 199 200else 201 202 " no syntax folding: 203 " - contained attribute removed 204 " - xmlRegion not defined 205 " 206 syn region xmlTag 207 \ matchgroup=xmlTag start=+<[^ /!?<>"']\@=+ 208 \ matchgroup=xmlTag end=+>+ 209 \ contains=xmlError,xmlTagName,xmlAttrib,xmlEqual,xmlString,@xmlStartTagHook 210 211 syn region xmlEndTag 212 \ matchgroup=xmlTag start=+</[^ /!?<>"']\@=+ 213 \ matchgroup=xmlTag end=+>+ 214 \ contains=xmlTagName,xmlNamespace,xmlAttribPunct,@xmlTagHook 215 216endif 217 218 219" &entities; compare with dtd 220syn match xmlEntity "&[^; \t]*;" contains=xmlEntityPunct 221syn match xmlEntityPunct contained "[&.;]" 222 223if exists('g:xml_syntax_folding') 224 225 " The real comments (this implements the comments as defined by xml, 226 " but not all xml pages actually conform to it. Errors are flagged. 227 syn region xmlComment 228 \ start=+<!+ 229 \ end=+>+ 230 \ contains=xmlCommentStart,xmlCommentError 231 \ extend 232 \ fold 233 234else 235 236 " no syntax folding: 237 " - fold attribute removed 238 " 239 syn region xmlComment 240 \ start=+<!+ 241 \ end=+>+ 242 \ contains=xmlCommentStart,xmlCommentError 243 \ extend 244 245endif 246 247syn match xmlCommentStart contained "<!" nextgroup=xmlCommentPart 248syn keyword xmlTodo contained TODO FIXME XXX 249syn match xmlCommentError contained "[^><!]" 250syn region xmlCommentPart 251 \ start=+--+ 252 \ end=+--+ 253 \ contained 254 \ contains=xmlTodo,@xmlCommentHook,@Spell 255 256 257" CData sections 258" 259" PROVIDES: @xmlCdataHook 260" 261syn region xmlCdata 262 \ start=+<!\[CDATA\[+ 263 \ end=+]]>+ 264 \ contains=xmlCdataStart,xmlCdataEnd,@xmlCdataHook,@Spell 265 \ keepend 266 \ extend 267 268" using the following line instead leads to corrupt folding at CDATA regions 269" syn match xmlCdata +<!\[CDATA\[\_.\{-}]]>+ contains=xmlCdataStart,xmlCdataEnd,@xmlCdataHook 270syn match xmlCdataStart +<!\[CDATA\[+ contained contains=xmlCdataCdata 271syn keyword xmlCdataCdata CDATA contained 272syn match xmlCdataEnd +]]>+ contained 273 274 275" Processing instructions 276" This allows "?>" inside strings -- good idea? 277syn region xmlProcessing matchgroup=xmlProcessingDelim start="<?" end="?>" contains=xmlAttrib,xmlEqual,xmlString 278 279 280if exists('g:xml_syntax_folding') 281 282 " DTD -- we use dtd.vim here 283 syn region xmlDocType matchgroup=xmlDocTypeDecl 284 \ start="<!DOCTYPE"he=s+2,rs=s+2 end=">" 285 \ fold 286 \ contains=xmlDocTypeKeyword,xmlInlineDTD,xmlString 287else 288 289 " no syntax folding: 290 " - fold attribute removed 291 " 292 syn region xmlDocType matchgroup=xmlDocTypeDecl 293 \ start="<!DOCTYPE"he=s+2,rs=s+2 end=">" 294 \ contains=xmlDocTypeKeyword,xmlInlineDTD,xmlString 295 296endif 297 298syn keyword xmlDocTypeKeyword contained DOCTYPE PUBLIC SYSTEM 299syn region xmlInlineDTD contained matchgroup=xmlDocTypeDecl start="\[" end="]" contains=@xmlDTD 300syn include @xmlDTD <sfile>:p:h/dtd.vim 301unlet b:current_syntax 302 303 304" synchronizing 305" TODO !!! to be improved !!! 306 307syn sync match xmlSyncDT grouphere xmlDocType +\_.\(<!DOCTYPE\)\@=+ 308" syn sync match xmlSyncDT groupthere NONE +]>+ 309 310if exists('g:xml_syntax_folding') 311 syn sync match xmlSync grouphere xmlRegion +\_.\(<[^ /!?<>"']\+\)\@=+ 312 " syn sync match xmlSync grouphere xmlRegion "<[^ /!?<>"']*>" 313 syn sync match xmlSync groupthere xmlRegion +</[^ /!?<>"']\+>+ 314endif 315 316syn sync minlines=100 317 318 319" The default highlighting. 320hi def link xmlTodo Todo 321hi def link xmlTag Function 322hi def link xmlTagName Function 323hi def link xmlEndTag Identifier 324if !exists("g:xml_namespace_transparent") 325 hi def link xmlNamespace Tag 326endif 327hi def link xmlEntity Statement 328hi def link xmlEntityPunct Type 329 330hi def link xmlAttribPunct Comment 331hi def link xmlAttrib Type 332 333hi def link xmlString String 334hi def link xmlComment Comment 335hi def link xmlCommentStart xmlComment 336hi def link xmlCommentPart Comment 337hi def link xmlCommentError Error 338hi def link xmlError Error 339 340hi def link xmlProcessingDelim Comment 341hi def link xmlProcessing Type 342 343hi def link xmlCdata String 344hi def link xmlCdataCdata Statement 345hi def link xmlCdataStart Type 346hi def link xmlCdataEnd Type 347 348hi def link xmlDocTypeDecl Function 349hi def link xmlDocTypeKeyword Statement 350hi def link xmlInlineDTD Function 351 352let b:current_syntax = "xml" 353 354let &cpo = s:xml_cpo_save 355unlet s:xml_cpo_save 356 357" vim: ts=8 358