summaryrefslogtreecommitdiffstats
path: root/kate/data/rpmspec.xml
blob: f93abe526a00b59c458e2edb6b2a9f396ef0091b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd" [
  <!ENTITY a_valid_char_in_macro_names "A-Za-z0-9_">
  <!ENTITY command_section_name "(prep|build|pre|preun|install|post|postun|clean|files|trigger|triggerin|triggerun|triggerpostun|verifyscript|check|pretrans|posttrans)">
  <!ENTITY arch "(alpha|alphaev5|alphaev56|alphaev6|alphaev67|alphapca56|amd64|armv3l|armv4b|armv4l|armv4tl|armv5b|armv5l|armv5teb|armv5tejl|armv5tel|armv6l|armv7l|atariclone|atarist|atariste|ataritt|athlon|axp|em64t|falcon|fat|geode|hades|hppa|hppa1\.0|hppa1\.1|hppa1\.2|hppa2\.0|hppa64|i370|i386|i486|i586|i686|ia32e|ia64|IP|m68k|m68kmint|milan|mips|mipsel|noarch|osfmach3_i386|osfmach3_i486|osfmach3_i586|osfmach3_i686|osfmach3_ppc|parisc|pentium3|pentium4|powerpc|powerpc64|powerppc|ppc|ppc32dy4|ppc64|ppc64iseries|ppc64pseries|ppc8260|ppc8560|ppciseries|ppcpseries|rs6000|s390|s390x|sgi|sh|sh3|sh4|sh4a|sparc|sparc64|sparc64v|sparcv8|sparcv9|sparcv9v|sun4|sun4c|sun4d|sun4m|sun4u|x86_64|xtensa)">
  <!ENTITY os "(AIX|AmigaOS|BSD_OS|bsdi|bsdi4\.0|cygwin32|CYGWIN32_95|CYGWIN32_NT|Darwin|darwin|Darwin|FreeBSD|FreeMiNT|HP-UX|hpux10|hpux10\.00|hpux10\.01|hpux10\.10|hpux10\.20|hpux10\.30|hpux11\.00|hpux9\.04|hpux9\.05|hpux9\.07|IRIX|Irix|IRIX|IRIX64|Irix64|IRIX64|Linux|Linux\/390|Linux\/ESA|machten|MacOSX|macosx|MacOSX|MiNT|mint|MiNT|mint|MiNT|mint|MP_RAS|ncr-sysv4\.2|ncr-sysv4\.3|NEXTSTEP|NextStep|OS\/390|OSF1|osf1|osf3\.2|osf4\.0|SCO_SV|SCO_SV3\.2v5\.0\.2|solaris|solaris2\.3|solaris2\.4|solaris2\.5|solaris2\.6|solaris2\.7|SunOS|SunOS4|SunOS5|TOS|UNIX_SV|VM\/ESA)">
  <!ENTITY arch_conditionals_names "(ifarch|ifnarch)">
  <!ENTITY os_conditionals_names "(ifos|ifnos)">
  <!ENTITY lookahead_whitespace_eol "(?=($| |\t))">
]>
<language name="RPM Spec" version="2.03" kateversion="2.4" section="Other" extensions="*.spec" mimetype="" license="public domain">

<!-- The entities "arch" and "os" are based on /usr/lib/rpm/rpmrc (in the version coming with openSUSE 11.4). -->

  <highlighting>

    <list name="weekdays">
      <item> Mon </item>
      <item> Tue </item>
      <item> Wed </item>
      <item> Thu </item>
      <item> Fri </item>
      <item> Sat </item>
      <item> Sun </item>
    </list>

    <list name="month names">
      <item> Jan </item>
      <item> Feb </item>
      <item> Mar </item>
      <item> Apr </item>
      <item> May </item>
      <item> Jun </item>
      <item> Jul </item>
      <item> Aug </item>
      <item> Sep </item>
      <item> Oct </item>
      <item> Nov </item>
      <item> Dec </item>
    </list>

    <list name="days">
      <item> 1 </item>
      <item> 2 </item>
      <item> 3 </item>
      <item> 4 </item>
      <item> 5 </item>
      <item> 6 </item>
      <item> 7 </item>
      <item> 8 </item>
      <item> 9 </item>
      <item> 01 </item>
      <item> 02 </item>
      <item> 03 </item>
      <item> 04 </item>
      <item> 05 </item>
      <item> 06 </item>
      <item> 07 </item>
      <item> 08 </item>
      <item> 09 </item>
      <item> 10 </item>
      <item> 11 </item>
      <item> 12 </item>
      <item> 13 </item>
      <item> 14 </item>
      <item> 15 </item>
      <item> 16 </item>
      <item> 17 </item>
      <item> 18 </item>
      <item> 19 </item>
      <item> 20 </item>
      <item> 21 </item>
      <item> 22 </item>
      <item> 23 </item>
      <item> 24 </item>
      <item> 25 </item>
      <item> 26 </item>
      <item> 27 </item>
      <item> 28 </item>
      <item> 29 </item>
      <item> 30 </item>
      <item> 31 </item>
    </list>

    <contexts>
      <!-- "package section" is the context for the package defination. As it is the first context
      in this file, it is also the context with which the interpreter starts. -->
      <context attribute="Error" lineEndContext="#stay" name="package section">
        <!-- Handle tags: -->
        <RegExpr attribute="Tag" context="tag_line_value" String="((Icon)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_os" String="((ExclusiveOs|ExcludeOs)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_arch" String="((BuildArch|BuildArchitectures|ExclusiveArch|ExcludeArch)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_package" String="((Conflicts|Obsoletes|Provides|Requires|Requires\(.*\)|Enhances|Suggests|BuildConflicts|BuildRequires|Recommends|PreReq)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_integer" String="((Epoch|Serial|Nosource|Nopatch)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_switch" String="((AutoReq|AutoProv|AutoReqProv)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_string" String="((Copyright|License|Summary|Summary\(.*\)|Distribution|Vendor|Packager|Group|Source\d*|Patch\d*|BuildRoot|Prefix)[ \t]*:[ \t]*)" column="0" />
        <RegExpr attribute="Tag" context="tag_line_string_only_one_word" String="((Name|Version|Release|Url|URL)[ \t]*:[ \t]*)" column="0" />
        <!-- Handle % -->
        <AnyChar context="macro entry in package section" String="%$" lookAhead="true" />
        <!-- Handle comments. "# norootforbuild" is displayed like a tag. -->
        <RegExpr context="Comment" String="[ \t]*#" column="0" lookAhead="true" />
                <!-- Spaces are okay -->
        <DetectSpaces attribute="Fallback for separator spaces" />
        <!-- Fallback value for every non-space -->
        <!--RegExpr attribute="Error" context="#stay" String="[^\s]" /-->
      </context>

      <!-- "macro entry in package section" is used for lines in the package section that start
      with a macro. It recognizes macros. Everything else is treated as normal text. This context
      is used to prevent to highlight syntax errors after macros. With the next line break, this
      context will switch back ("#pop"). -->
      <context attribute="Shell commands" lineEndContext="#pop" name="macro entry in package section">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "package section start line" simply is used for the parameters after the
      "%package" macro. With the next line break, it will switch to the
      "package section" context which will handle everything else. -->
      <context attribute="Shell commands" lineEndContext="package section" name="package section start line">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "command section" is a generic context for all secions (like %prep, %build, %install...)
      where you can enter shell commands. -->
      <context attribute="Shell commands" lineEndContext="#stay" name="command section">
        <!-- Handle \ -->
        <RegExpr attribute="Escaped character" String="\\." />
        <DetectChar attribute="Line break" char="\" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
        <!-- Handle comments. "# norootforbuild" is displayed like a tag. -->
        <RegExpr context="Comment" String="[ \t]*#" column="0" lookAhead="true" />
      </context>

      <!-- "changelog section" is the context for the changelog. By default, everything that is
      not recognized especially, is interpretated as changelog text. -->
      <context attribute="String" lineEndContext="#stay" name="changelog section">
        <!-- Handle calender date -->
        <DetectChar attribute="Tag" context="changelog_weekday" char="*" column="0" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
        <!-- Handle comments. "# norootforbuild" is displayed like a tag. -->
        <RegExpr context="Comment" String="[ \t]*#" column="0" lookAhead="true" />
      </context>

      <!-- "description section start line" simply is used for the parameters after the
      "%description" macro. With the next line break, it will switch to the
      "description section" context which will handle the content of the description. -->
      <context attribute="Shell commands" lineEndContext="description section" name="description section start line">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "description section" is a follow-up context of "description section start line". See
      there for further details. -->
      <context attribute="String" lineEndContext="#stay" name="description section">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
        <!-- Handle comments. "# norootforbuild" is displayed like a tag. -->
        <RegExpr context="Comment" String="[ \t]*#" column="0" lookAhead="true" />
      </context>

      <!-- This is a convenience context that is handling comments automatically. Furthermore it
      handles "# norootforbuild" because it looks like a comment. If a context supports comments,
      simple use "<RegExpr context="Comment" String="[ \t]*#" column="0" lookAhead="true" />".
      (This context relies on the asumption that # is the first non-whitespace. We have to
      guarantee this when calling this context! -->
      <context attribute="Comment" lineEndContext="#pop" name="Comment">
        <!-- While indeeted comments are not allowed by the standard (see section "Comments" at
        http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-specfile-syntax.html#id1961462),
        rpmbuild accepts them nevertheless. We highlight them as comments, but we mark the
        indeet. -->
        <RegExpr attribute="Hint" context="#stay" String="[ \t]+(?=#)" column="0" />
	<!-- Handle "# norootforbuild" and some of its miss-spellings. -->
        <StringDetect attribute="Tag" context="every_non_whitespace_is_warning" String="# norootforbuild" column="0" />
        <RegExpr attribute="Warning" context="#stay" String="#[ \t]*norootforbuild" />
        <!-- Warning on single percent ("%"), but not on double percent ("%%"): -->
        <Detect2Chars attribute="Comment" char="%" char1="%"/>
        <DetectChar attribute="Warning" char="%"/>
        <IncludeRules context="##Alerts"/> <!-- Alert -->
      </context>

      <!-- "every_non_whitespace_is_error" is a simple helper context. It switchs back to the
      previous context at the end of the line. -->
      <context attribute="Fallback for separator spaces" lineEndContext="#pop" name="every_non_whitespace_is_error">
        <RegExpr attribute="Error" context="#stay" String="[^\s]" />
      </context>

      <!-- "every_non_whitespace_is_warning" is a simple helper context. It switchs back to the
      previous context at the end of the line. -->
      <context attribute="Fallback for separator spaces" lineEndContext="#pop" name="every_non_whitespace_is_warning">
        <RegExpr attribute="Warning" context="#stay" String="[^\s]" />
      </context>

      <!-- "tag_line_value" is a context for enumeration values. It makes no further syntax
      check. -->
      <context attribute="Enumeration" lineEndContext="#pop" name="tag_line_value">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "tag_line_string" is a context for string values. It makes no further syntax
      check. -->
      <context attribute="String" lineEndContext="#pop" name="tag_line_string">
        <!-- Handle \ -->
        <RegExpr attribute="Escaped character" String="\\[^%]" />
        <RegExpr attribute="Escaped character" String="\\(?=(\%))" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "tag_line_string_only_one_word" is a context for string values. The first word is
      highlighted as string, but after the first space (normal space, tab...), all other
      words are highlighted as error. WARNING: This context requieres that there is no space at
      the begin! -->
      <context attribute="String" lineEndContext="#pop" name="tag_line_string_only_one_word">
        <!-- Handle \ -->
        <RegExpr attribute="Escaped character" String="\\[^%]" />
        <RegExpr attribute="Escaped character" String="\\(?=(\%))" />
        <!-- Handle % -->
        <AnyChar context="tag_line_string" String="%$" lookAhead="true" />
        <!-- Handle spaces -->
        <DetectSpaces context="every_non_whitespace_is_error" />
      </context>

      <!-- "tag_line_integer" is a context for integer values. Non-integer context is marked as
      error. -->
      <context attribute="Error" lineEndContext="#pop" name="tag_line_integer">
        <Int attribute="Integer" context="every_non_whitespace_is_error" />
        <!-- Handle % -->
        <AnyChar context="tag_line_integer_without_syntax_check" String="%$" lookAhead="true" />
        <RegExpr context="every_non_whitespace_is_error" String="." lookAhead="true" />
      </context>

      <!-- "tag_line_os" is a context for values that define the operation system. Unknown values
      are marked as error. -->
      <context attribute="Warning" lineEndContext="#pop" name="tag_line_os">
        <!-- Spaces are okay -->
        <DetectSpaces attribute="Fallback for separator spaces" />
        <!-- Recognize valid values -->
        <RegExpr attribute="Enumeration" String="&os;&lookahead_whitespace_eol;" />
        <!-- Handle % -->
        <AnyChar context="tag_line_value" String="%$" lookAhead="true" />
      </context>

      <!-- "tag_line_integer_without_syntax_check" is a context that is used internally by
      "tag_line_integer" after macros. -->
      <context attribute="Integer" lineEndContext="#pop" name="tag_line_integer_without_syntax_check">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "tag_line_arch" is a context for values that define the computer type. Unknown values
      are marked as error. -->
      <context attribute="Warning" lineEndContext="#pop" name="tag_line_arch">
        <!-- Spaces are okay -->
        <DetectSpaces attribute="Fallback for separator spaces" />
        <!-- Recognize valid values -->
        <RegExpr attribute="Enumeration" String="&arch;&lookahead_whitespace_eol;" />
        <!-- Handle % -->
        <AnyChar context="tag_line_value" String="%$" lookAhead="true" />
      </context>

      <!-- "tag_line_package" is a context for dependency handling. The keywords <= >= == < > are
      recognized and highlighted as keywords. Thee rest is simply highlighted as enumeration. See
      http://docs.fedoraproject.org/drafts/rpm-guide-en/ch-specfile-syntax.html#id3045258 and
      http://docs.fedoraproject.org/drafts/rpm-guide-en/ch-advanced-packaging.html#id2979270 for
      details -->
      <context attribute="Enumeration" lineEndContext="#pop" name="tag_line_package">
        <AnyChar attribute="Keyword" context="#stay" String="()" /> <!-- See http://rpm5.org/docs/api/dependencies.html about the parentheses -->
        <Detect2Chars attribute="Keyword" context="#stay" char="&lt;" char1="="/>
        <Detect2Chars attribute="Keyword" context="#stay" char="&gt;" char1="="/>
        <Detect2Chars attribute="Keyword" context="#stay" char="=" char1="="/>
        <AnyChar attribute="Keyword" context="#stay" String="=&lt;&gt;," />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- "tag_line_switch" is a context that accepts "0", "1", "yes" and "no" as value.
      Everything else is an error. See http://www.rpm.org/max-rpm-snapshot/s1-rpm-depend-auto-depend.html
      and http://www.rpm.org/max-rpm/s1-rpm-inside-tags.html#S3-RPM-INSIDE-AUTOREQPROV-TAG -->
      <context attribute="Error" lineEndContext="#pop" name="tag_line_switch">
        <AnyChar attribute="Enumeration" context="every_non_whitespace_is_error" String="01" />
        <Detect2Chars attribute="Enumeration" context="every_non_whitespace_is_error" char="n" char1="o"/>
        <StringDetect attribute="Enumeration" context="every_non_whitespace_is_error" String="yes" />
        <!-- Handle % -->
        <AnyChar context="tag_line_value" String="%$" lookAhead="true" />
        <RegExpr context="every_non_whitespace_is_error" String="." lookAhead="true" />
      </context>

      <!-- A context that doesn't test for format errors in the changelog date anymore. Necessary
      if macros are used. -->
      <context attribute="Tag" lineEndContext="#pop" name="changelog_generic">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

     <!-- A context that handles the weekday in the changelog date. -->
      <context attribute="Tag" lineEndContext="#pop" name="changelog_weekday">
        <DetectSpaces/>
        <keyword context="changelog_month" attribute="Tag" String="weekdays" />
        <!-- % handling without format errors in the date of the changelog -->
        <AnyChar context="changelog_generic" String="%$" lookAhead="true" />
        <RegExpr context="changelog_month" attribute="Error" String="\S*" />
      </context>

     <!-- A context that handles the month in the changelog date. -->
      <context attribute="Tag" lineEndContext="#pop" name="changelog_month">
        <DetectSpaces/>
        <keyword context="changelog_day" attribute="Tag" String="month names" />
        <!-- % handling without format errors in the date of the changelog -->
        <AnyChar context="changelog_generic" String="%$" lookAhead="true" />
        <RegExpr context="changelog_day" attribute="Error" String="\S*" />
      </context>

     <!-- A context that handles the day in the changelog date. -->
      <context attribute="Tag" lineEndContext="#pop" name="changelog_day">
        <DetectSpaces/>
        <keyword context="changelog_year" attribute="Tag" String="days" />
        <!-- % handling without format errors in the date of the changelog -->
        <AnyChar context="changelog_generic" String="%$" lookAhead="true" />
        <RegExpr context="changelog_year" attribute="Error" String="\S*" />
      </context>

     <!-- A context that handles the year in the changelog date. -->
      <context attribute="Tag" lineEndContext="#pop" name="changelog_year">
        <DetectSpaces/>
        <RegExpr context="changelog_header" attribute="Tag" String="(\d{4})&lookahead_whitespace_eol;" />
        <!-- % handling without format errors in the date of the changelog -->
        <AnyChar context="changelog_generic" String="%$" lookAhead="true" />
        <RegExpr context="changelog_header" attribute="Error" String="\S*" />
      </context>

     <!-- A context that handles the text after the date in a changelog (name, e-mail...). -->
      <context attribute="Tag" lineEndContext="#pop" name="changelog_header">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- Handles everything that comes after %ifos etc... -->
      <context attribute="Warning" lineEndContext="#pop" name="parameters after ifos">
        <!-- Spaces are okay -->
        <DetectSpaces attribute="Fallback for separator spaces" />
        <!-- Recognize valid values -->
        <RegExpr attribute="Enumeration" String="&os;&lookahead_whitespace_eol;" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- Handles everything that comes after %ifarch etc... -->
      <context attribute="Warning" lineEndContext="#pop" name="parameters after ifarch">
        <!-- Spaces are okay -->
        <DetectSpaces attribute="Fallback for separator spaces" />
        <!-- Recognize valid values -->
        <RegExpr attribute="Enumeration" String="&arch;&lookahead_whitespace_eol;" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- Handles expressions after conditionals. -->
      <context attribute="Error" lineEndContext="#pop" name="expression after _if_ statement">
        <!-- spaces should not be "Error" (which is the default for unrecognized entities) -->
        <DetectSpaces attribute="Fallback for separator spaces" context="#stay" />
        <!-- %if recognizes && || > < >= <= == != ! and () -->
        <AnyChar attribute="Keyword" context="#stay" String="()" />
        <Detect2Chars attribute="Keyword" context="#stay" char="&amp;" char1="&amp;"/>
        <Detect2Chars attribute="Keyword" context="#stay" char="&lt;" char1="="/>
        <Detect2Chars attribute="Keyword" context="#stay" char="&gt;" char1="="/>
        <Detect2Chars attribute="Keyword" context="#stay" char="=" char1="="/>
        <Detect2Chars attribute="Keyword" context="#stay" char="!" char1="="/>
        <AnyChar attribute="Keyword" context="#stay" String="!&lt;&gt;" />
        <Detect2Chars attribute="Keyword" context="#stay" char="|" char1="|"/>
        <!-- %if interpretates values either as integer or as string -->
        <Int attribute="Integer" context="#stay" />
        <DetectIdentifier attribute="String" context="#stay" />
        <DetectChar attribute="String" context="quoted strings in if statements" char="&quot;" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

      <!-- This context handles quoted strings in %if statements. WARNING: Make sure that you
      switch to this context _after_ parsing the starting ", because at the first occurrence
      of " this context switches back. -->
      <context attribute="String" lineEndContext="#pop" name="quoted strings in if statements">
        <!-- Handle \ -->
        <RegExpr attribute="Escaped character" String="\\[^&quot;]" />
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
        <!-- Switch back at the end of the quoted string -->
        <DetectChar attribute="String" context="#pop" char="&quot;" />
      </context>

      <!-- Context for %define -->
      <context attribute="Fallback for separator spaces" lineEndContext="#pop" name="macro defination">
        <DetectSpaces />
        <RegExpr attribute="Enumeration" context="macro defination content" String="[&a_valid_char_in_macro_names;]*&lookahead_whitespace_eol;" />
        <RegExpr attribute="Error" context="macro defination content" String="[^ \t]*" />
      </context>

      <!-- Context for the content of a macro defination. -->
      <context attribute="String" lineEndContext="#pop" name="macro defination content">
        <DetectSpaces />
        <LineContinue attribute="Line break" context="#stay"/>
        <DetectChar attribute="Warning" char="\" />
      </context>

      <!-- Context for %undefine -->
      <context attribute="Fallback for separator spaces" lineEndContext="#pop" name="undefine macro">
        <DetectSpaces />
        <RegExpr attribute="Enumeration" context="every_non_whitespace_is_error" String="[&a_valid_char_in_macro_names;]*&lookahead_whitespace_eol;" />
        <RegExpr attribute="Error" context="every_non_whitespace_is_error" String="." />
      </context>

      <!-- This context handles automatically all type of macros, keywords and so on that start with % or $.
      It expects a string starting with % or $ (otherwise, this context will fail!). -->
      <context attribute="Fallback for separator spaces" lineEndContext="#pop" name="handle_percent">
        <Detect2Chars attribute="Escaped character" context="#pop" char="%" char1="%"/>
        <!-- Keywords: -->
        <RegExpr attribute="Keyword" context="expression after _if_ statement" String="%(if!?)&lookahead_whitespace_eol;" firstNonSpace="true" beginRegion="if_block" />
        <RegExpr attribute="Keyword" context="parameters after ifarch" String="%&arch_conditionals_names;&lookahead_whitespace_eol;" firstNonSpace="true" beginRegion="if_block" />
        <RegExpr attribute="Keyword" context="parameters after ifos" String="%&os_conditionals_names;&lookahead_whitespace_eol;" firstNonSpace="true" beginRegion="if_block" />
        <RegExpr attribute="Keyword" context="every_non_whitespace_is_error" String="%else&lookahead_whitespace_eol;" firstNonSpace="true" endRegion="if_block" beginRegion="if_block" />
        <RegExpr attribute="Keyword" context="every_non_whitespace_is_error" String="%endif&lookahead_whitespace_eol;" firstNonSpace="true" endRegion="if_block" />
        <RegExpr attribute="Keyword" context="macro defination" String="%(define|global)&lookahead_whitespace_eol;" firstNonSpace="true" />
        <RegExpr attribute="Keyword" context="undefine macro" String="%undefine&lookahead_whitespace_eol;" firstNonSpace="true" />
        <!-- If a command section starts (=section macro at begin of the line), we switch
             to the corresponding context. There will never be a return to THIS context...: -->
        <RegExpr attribute="Section" context="package section start line" String="%package&lookahead_whitespace_eol;" column="0" />
        <RegExpr attribute="Section" context="description section start line" String="%description&lookahead_whitespace_eol;" column="0" />
        <RegExpr attribute="Section" context="command section" String="%&command_section_name;&lookahead_whitespace_eol;" column="0" />
        <RegExpr attribute="Section" context="changelog section" String="%changelog&lookahead_whitespace_eol;" column="0" />
        <!-- Handle normal macros -->
        <RegExpr attribute="Error" context="#pop" String="%([\{\(][ \t]{0,}){0,1}(if|&arch_conditionals_names;|&os_conditionals_names;|else|endif|define|global|undefine|package|description|&command_section_name;|changelog)(?=($|[^&a_valid_char_in_macro_names;]))" />
        <RegExpr attribute="Macro call" context="macro content in parenthesis" String="%[&a_valid_char_in_macro_names;]*\(" />
        <RegExpr attribute="Macro call" context="macro content in braces" String="(%|\$)\{" />
        <RegExpr attribute="Macro call" context="#pop" String="(%|\$)([&a_valid_char_in_macro_names;]{1,}|\*|\#)(?=($|[^&a_valid_char_in_macro_names;]))" /> <!-- ')' and '}' are only allowed as macro terminator in the lookahead because when you do something like %__make %{?jobs:-j %jobs}, then the "%jobs" is a valid macro. However, the disadvantage is that a line like "%abc} isn't marked as error. But it is to complicate to distinguish this properly. -->
        <RegExpr attribute="Error" context="#pop" String="(%|\$)([&a_valid_char_in_macro_names;]{1,}|\*|\#)" />
        <AnyChar attribute="Error" context="#pop" String="%$" /> <!-- a single % or $ is also an error -->
      </context>

      <!-- Used internally by "handle_percent" -->
      <context attribute="Macro call" lineEndContext="#pop#pop" name="macro content in parenthesis">
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
        <DetectChar attribute="Macro call" context="#pop#pop" char=")" />
        <AnyChar attribute="Error" context="#stay" String="({}" />
      </context>

      <!-- Used internally by "handle_percent" -->
      <context attribute="Macro call" lineEndContext="#pop#pop" name="macro content in braces">
        <DetectChar attribute="Macro call" context="#pop#pop" char="}" />
        <AnyChar attribute="Error" context="#stay" String="({)" />
        <!--(This seems to be confusing instead of helping)AnyChar attribute="Keyword" context="#stay" String="!?:" /-->
        <!-- Handle % -->
        <AnyChar context="handle_percent" String="%$" lookAhead="true" />
      </context>

    </contexts>

    <itemDatas>
      <!-- "Shell commands" is used for the sections like %prep, %build or %install, where you write
      shell commands. -->
      <itemData name="Shell commands" defStyleNum="dsNormal"/>
      <!-- "Fallback for separator spaces" is used as a fallback context for spaces between
      different contexts. For example: "%if 1 <= %number" has the contexts Keyword,
      Integer, Keyword and Macro call. But the spaces between? They are using THIS
      context. -->
      <itemData name="Fallback for separator spaces" defStyleNum="dsNormal"/>
      <itemData name="Keyword" defStyleNum="dsKeyword"/>
      <itemData name="Comment" defStyleNum="dsComment"/>
      <itemData name="Tag" defStyleNum="dsDataType"/>
      <!-- "Enumeration" is used for data types where you can't use arbitrary strings but have 
      to use predefined values (like in "Provides:" or "%undefine"). -->
      <itemData name="Enumeration" defStyleNum="dsOthers"/>
      <itemData name="String" defStyleNum="dsString"/>
      <itemData name="Integer" defStyleNum="dsDecVal"/>
      <!-- "Error" is used for problems that will always produce an error in the interpretation
      process. -->
      <itemData name="Error" defStyleNum="dsError"/>
      <!-- "Warning" is used for problems that will maybe produce an error in the interpretation
      process or will lead to unexpected results. -->
      <itemData name="Warning" defStyleNum="dsError"/>
      <!-- "Hint" is used for problems that will never produce an error in the interpretation
      process and will always work like expected (the interpreter has error tolerance),
      but that are claimed as bad or invalid .spec following the documentation. -->
      <itemData name="Hint" defStyleNum="dsError"/>
      <itemData name="Macro call" defStyleNum="dsFunction"/>
      <itemData name="Section" defStyleNum="dsRegionMarker"/>
      <itemData name="Escaped character" defStyleNum="dsChar"/>
      <itemData name="Line break" defStyleNum="dsKeyword"/>
    </itemDatas>

  </highlighting>

  <general>
    <!-- defining all word deliminators except space and tab as weak -->
    <keywords casesensitive="1" weakDeliminator=".():!+,-&lt;=&gt;%&amp;*/;?[]^{|}~\," />
    <comments>
      <comment name="singleLine" start="#"/>
    </comments>
  </general>

</language>