]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/xmode/modes/batch.xml
xmode.modes: updating with recent xmode files
[factor.git] / basis / xmode / modes / batch.xml
index ebfe13affdea91ec4ff47c0cb950f6d540320548..663477a4dd035395550288ff67ca4f62cbd3a7e5 100644 (file)
-<?xml version="1.0"?>\r
-\r
-<!DOCTYPE MODE SYSTEM "xmode.dtd">\r
-\r
-<!--\r
-       09-10-2003 - Mirco Bova\r
-       Added some new batch commands using win2K help as reference.\r
-\r
-       04-12-2001 - Mirco Bova\r
-       this file is based on the original JEdit batch.xml mode.\r
-       The main upgrade consisting in adding the standard MS-DOS\r
-       commands as keywords and functions:\r
-       - keywords =            internal shell commands;\r
-       -       functions =             standard MS-DOS commands (.exe or .com in DOS or\r
-                                                                       windows\command directory).\r
-\r
-       Minor enhancements by Alex Jacoby on 28-feb-2003\r
--->\r
-\r
-<!-- The keywords and functions here defined are those of MS-DOS 6.22,\r
-                plus a few as of Windows XP.\r
- -->\r
-\r
-<MODE>\r
-       <PROPS>\r
-               <PROPERTY NAME="lineComment" VALUE="rem" />\r
-               <PROPERTY NAME="indentOpenBrackets" VALUE="(" />\r
-               <PROPERTY NAME="indentCloseBrackets" VALUE=")" />\r
-       </PROPS>\r
-       <RULES IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">\r
-               <!-- 'echo off' statements -->\r
-               <SEQ TYPE="KEYWORD3">@</SEQ>\r
-\r
-               <SEQ TYPE="OPERATOR">+</SEQ>\r
-               <SEQ TYPE="OPERATOR">|</SEQ>\r
-               <SEQ TYPE="OPERATOR">&amp;</SEQ>\r
-               <SEQ TYPE="OPERATOR">!</SEQ>\r
-               <SEQ TYPE="OPERATOR">&gt;</SEQ>\r
-               <SEQ TYPE="OPERATOR">&lt;</SEQ>\r
-\r
-               <!-- labels - eg ":test" or "goto :test" -->\r
-               <MARK_FOLLOWING AT_WORD_START="TRUE" TYPE="LABEL">:</MARK_FOLLOWING>\r
-\r
-               <!-- comments -->\r
-               <EOL_SPAN_REGEXP AT_WHITESPACE_END="TRUE" HASH_CHAR="REM" TYPE="COMMENT1">REM\s</EOL_SPAN_REGEXP>\r
-\r
-               <!-- literals -->\r
-               <SPAN TYPE="LITERAL1" NO_LINE_BREAK="TRUE">\r
-                       <BEGIN>"</BEGIN>\r
-                       <END>"</END>\r
-               </SPAN>\r
-\r
-               <!-- variables -->\r
-               <SEQ TYPE="KEYWORD2">%0</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%1</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%2</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%3</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%4</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%5</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%6</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%7</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%8</SEQ>\r
-               <SEQ TYPE="KEYWORD2">%9</SEQ>\r
-               <!-- for-loop variable (one char after %%) -->\r
-               <SEQ_REGEXP TYPE="KEYWORD2"\r
-                                       HASH_CHAR="%%"\r
-                                       AT_WORD_START="TRUE"\r
-                                       >%%[\p{Alpha}]</SEQ_REGEXP>\r
-               <SPAN TYPE="KEYWORD2" NO_LINE_BREAK="TRUE">\r
-                       <BEGIN>%</BEGIN>\r
-                       <END>%</END>\r
-               </SPAN>\r
-\r
-               <KEYWORDS>\r
-                       <!-- KEYWORD1 are internal MS-DOS shell commands -->\r
-                       <KEYWORD1>cd</KEYWORD1>\r
-                       <KEYWORD1>chdir</KEYWORD1>\r
-                       <KEYWORD1>md</KEYWORD1>\r
-                       <KEYWORD1>mkdir</KEYWORD1>\r
-\r
-                       <KEYWORD1>cls</KEYWORD1>\r
-\r
-                       <KEYWORD1>for</KEYWORD1>\r
-                       <KEYWORD1>if</KEYWORD1>\r
-\r
-                       <KEYWORD1>echo</KEYWORD1>\r
-                       <KEYWORD1>echo.</KEYWORD1>\r
-\r
-                       <KEYWORD1>move</KEYWORD1>\r
-                       <KEYWORD1>copy</KEYWORD1>\r
-                       <KEYWORD1>move</KEYWORD1>\r
-                       <KEYWORD1>ren</KEYWORD1>\r
-                       <KEYWORD1>del</KEYWORD1>\r
-                       <KEYWORD1>set</KEYWORD1>\r
-\r
-                       <!-- new KEYWORDS from Win2K help -->\r
-                       <KEYWORD1>call</KEYWORD1>\r
-                       <KEYWORD1>exit</KEYWORD1>\r
-                       <KEYWORD1>setlocal</KEYWORD1>\r
-                       <KEYWORD1>shift</KEYWORD1>\r
-                       <KEYWORD1>endlocal</KEYWORD1>\r
-                       <KEYWORD1>pause</KEYWORD1>\r
-\r
-                       <!-- KEYWORD2 are commands options -->\r
-\r
-                       <KEYWORD2>defined</KEYWORD2>\r
-                       <KEYWORD2>exist</KEYWORD2>\r
-                       <KEYWORD2>errorlevel</KEYWORD2>\r
-\r
-                       <!-- new KEYWORD options from Win2K help -->\r
-                       <KEYWORD2>else</KEYWORD2>\r
-\r
-                       <KEYWORD2>in</KEYWORD2>\r
-                       <KEYWORD2>do</KEYWORD2>\r
-\r
-                       <KEYWORD2>NUL</KEYWORD2>\r
-                       <KEYWORD2>AUX</KEYWORD2>\r
-                       <KEYWORD2>PRN</KEYWORD2>\r
-\r
-                       <KEYWORD1>not</KEYWORD1>\r
-\r
-                       <!-- goto is a special case we want to distinguish it -->\r
-                       <KEYWORD3>goto</KEYWORD3>\r
-\r
-                       <!-- FUNCTION are standard MS-DOS commands -->\r
-                       <!-- (those you find as stand-alone .exe or .com) in win95 %windows_root%\command folder -->\r
-                       <FUNCTION>APPEND</FUNCTION>\r
-                       <FUNCTION>ATTRIB</FUNCTION>\r
-                       <FUNCTION>CHKDSK</FUNCTION>\r
-                       <FUNCTION>CHOICE</FUNCTION>\r
-                       <FUNCTION>DEBUG</FUNCTION>\r
-                       <FUNCTION>DEFRAG</FUNCTION>\r
-                       <FUNCTION>DELTREE</FUNCTION>\r
-                       <FUNCTION>DISKCOMP</FUNCTION>\r
-                       <FUNCTION>DISKCOPY</FUNCTION>\r
-                       <FUNCTION>DOSKEY</FUNCTION>\r
-                       <FUNCTION>DRVSPACE</FUNCTION>\r
-                       <FUNCTION>EMM386</FUNCTION>\r
-                       <FUNCTION>EXPAND</FUNCTION>\r
-                       <FUNCTION>FASTOPEN</FUNCTION>\r
-                       <FUNCTION>FC</FUNCTION>\r
-                       <FUNCTION>FDISK</FUNCTION>\r
-                       <FUNCTION>FIND</FUNCTION>\r
-                       <FUNCTION>FORMAT</FUNCTION>\r
-                       <FUNCTION>GRAPHICS</FUNCTION>\r
-                       <FUNCTION>KEYB</FUNCTION>\r
-                       <FUNCTION>LABEL</FUNCTION>\r
-                       <FUNCTION>LOADFIX</FUNCTION>\r
-                       <FUNCTION>MEM</FUNCTION>\r
-                       <FUNCTION>MODE</FUNCTION>\r
-                       <FUNCTION>MORE</FUNCTION>\r
-                       <FUNCTION>MOVE</FUNCTION>\r
-                       <FUNCTION>MSCDEX</FUNCTION>\r
-                       <FUNCTION>NLSFUNC</FUNCTION>\r
-                       <FUNCTION>POWER</FUNCTION>\r
-                       <FUNCTION>PRINT</FUNCTION>\r
-                       <FUNCTION>RD</FUNCTION>\r
-                       <FUNCTION>REPLACE</FUNCTION>\r
-                       <FUNCTION>RESTORE</FUNCTION>\r
-                       <FUNCTION>SETVER</FUNCTION>\r
-                       <FUNCTION>SHARE</FUNCTION>\r
-                       <FUNCTION>SORT</FUNCTION>\r
-                       <FUNCTION>SUBST</FUNCTION>\r
-                       <FUNCTION>SYS</FUNCTION>\r
-                       <FUNCTION>TREE</FUNCTION>\r
-                       <FUNCTION>UNDELETE</FUNCTION>\r
-                       <FUNCTION>UNFORMAT</FUNCTION>\r
-                       <FUNCTION>VSAFE</FUNCTION>\r
-                       <FUNCTION>XCOPY</FUNCTION>\r
-               </KEYWORDS>\r
-       </RULES>\r
-</MODE>\r
+<?xml version="1.0"?>
+
+<!DOCTYPE MODE SYSTEM "xmode.dtd">
+
+<!--
+       Token types:
+               KEYWORD1        Internal shell commands - Fast
+               KEYWORD2        DOS-style %1, %%v, %variables%
+               KEYWORD3        Common commands arguments and glue keywords
+               KEYWORD4        Standard device names (NUL, CON, COM1, etc.)
+               FUNCTION        External commands - Slow
+               MARKUP          NT-style expanded !variables!
+               LITERAL1        Quoted "strings"
+               LITERAL2        Echo arguments
+               COMMENT1        REM remarks
+               COMMENT2        :: or :# Fake labels used as comments
+               COMMENT4        %# Fake variables used as comments #%
+
+       Known issues:
+       - The ^ escape character is not detected at all, so some rules fire when they shouldn't.
+       - The word FOR, used as an argument to another command, will trigger the rule set="FOR".
+         This usually causes the rest of the line to be mistakenly coloured as INVALID.
+         Fortunately, this does not happen with (echo For example) because of echo's own rules that prevent this.
+       - Same phenomenons with the word REM.
+       - The DO is not always detected when using a complex pipeline within a FOR /f %%f IN ('pipeline') DO ...
+
+       To do:
+       - Find why ESCAPE="^" does not work.
+       - Find a general way to parse the (command [arguments]) syntax.
+         This is complicated by the fact that I/O redirections may be present ahead of the command.
+         So the actual syntax is ([I/O redirection] command [arguments and other I/O redirections])
+       - Find a way to parse the (IF VALUE1==VALUE2 command) syntax.
+       - Parse the SET command, and flag as comment the trailing characters it ignores.
+
+        2016-12-07 - Jean-Francois Larvoire
+        Fixed indentation when a comment followed the opening parenthesis.
+        Avoid detecting arguments containing a : as labels. (Which caused the rest of the line to be flagged as comment)
+
+        2016-11-29 - Jean-Francois Larvoire
+        Added :: and :# and %#...#% comment markers.
+        Added !variables!.
+        Added %* argument line variable.
+        Added %~ qualifiers for %N command-line arguments and %%f loop variables.
+        Added many new internal and external commands added in XP, Vista, and Windows 7.
+        Recursively apply %variable% rules within !variable! rules within "string" rules.
+        Verify the FOR loops syntax, and flag common errors as INVALID. Ex: missing IN or DO.
+        Added partial support for IF, CALL, ECHO syntaxes.
+        Added < > X>&Y | & && || ( ) pilelining and sequencing operators.
+
+       2003-10-09 - Mirco Bova
+       Added some new batch commands using win2K help as reference.
+
+       2003-02-28 - Alex Jacoby
+       Minor enhancements.
+
+       2001-12-04 - Mirco Bova
+       this file is based on the original JEdit batch.xml mode.
+       The main upgrade consisting in adding the standard MS-DOS
+       commands as keywords and functions:
+       - keywords =            internal shell commands;
+       - functions =           standard MS-DOS commands (.exe or .com in DOS or
+                                                         windows\command directory).
+-->
+
+<MODE>
+       <PROPS>
+               <PROPERTY NAME="lineComment" VALUE="rem" />
+               <PROPERTY NAME="indentNextLines" VALUE="(^|.*\s+)\(([^()]|\([^()]+\))*$" />
+               <PROPERTY NAME="unindentThisLine"  VALUE="^([^()]|\([^()]+\))*\).*$" />
+               <PROPERTY NAME="unindentNextLines" VALUE="^([^()]|\([^()]+\))*\).*$" />
+               <PROPERTY NAME="electricKeys" VALUE="()" /><!-- Apply the last 3 rules every time () are pressed -->
+               <PROPERTY NAME="wordBreakChars" VALUE="()&amp;|&lt;&gt;,;=" /><!-- Unused? -->
+               <PROPERTY NAME="noWordSep" VALUE="_.[]{}/\-#$*?" /><!-- Doc says: Word breaks = Any non-alphanumeric not in this list -->
+       </PROPS>
+
+       <RULES IGNORE_CASE="TRUE" NO_WORD_SEP="_.[]{}/\-#$*?" HIGHLIGHT_DIGITS="FALSE">
+               <!-- Parenthesis blocks (Used for group piping) -->
+               <IMPORT DELEGATE="Parenthesis_blocks"/>
+
+               <!-- Pipelining operators -->
+               <IMPORT DELEGATE="Pipeline_operators"/>
+
+               <!-- Anything else has to be a single command -->
+               <IMPORT DELEGATE="@Command"/>
+       </RULES>
+
+       <!-- A label, or one command, possibly not echoed, and its arguments -->
+       <RULES SET="@Command" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- Fake :: or :# labels used for remarks. Also protect everything up to the end of line, even & operators -->
+               <!-- Must be defined before :labels to be detected -->
+               <!-- Do not use AT_WHITESPACE_END="TRUE", because comments can be located after an & operator -->
+               <EOL_SPAN_REGEXP TYPE="COMMENT4" AT_WORD_START="TRUE" HASH_CHAR="">\s*:[:#]</EOL_SPAN_REGEXP>
+
+               <!-- :labels. Anything that follows is ignored by the parser, even & operators, and can be used as a comment -->
+               <!-- Do use AT_WHITESPACE_END="TRUE", else the rule will fire for arguments containing a : -->
+               <EOL_SPAN_REGEXP MATCH_TYPE="LABEL" TYPE="COMMENT4" AT_WHITESPACE_END="TRUE" HASH_CHAR="">(?:.?[,;=\s]*):[^+:,;=\s]+</EOL_SPAN_REGEXP>
+
+               <!-- '@echo off' command prefix -->
+               <EOL_SPAN AT_WORD_START="TRUE" TYPE="OPERATOR" DELEGATE="Command">@</EOL_SPAN>
+
+               <!-- <SEQ_REGEXP HASH_CHARS="   " DELEGATE="Command">\s+</SEQ_REGEXP>-->
+               <IMPORT DELEGATE="Command"/>
+       </RULES>
+
+       <!-- One command and its arguments -->
+       <RULES SET="Command" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- Argument separators -->
+               <SEQ TYPE="OPERATOR">,</SEQ>
+               <SEQ TYPE="OPERATOR">;</SEQ>
+               <SEQ TYPE="OPERATOR">=</SEQ>
+
+               <!-- REM remarks cover the whole line, even if it contains & operators -->
+               <EOL_SPAN_REGEXP TYPE="COMMENT1" AT_WORD_START="TRUE" HASH_CHAR="REM">REM\b</EOL_SPAN_REGEXP>
+
+               <!-- DOS-style %variables% -->
+               <IMPORT DELEGATE="Percent_Variable"/>
+
+               <!-- NT-style expanded !variables! -->
+               <IMPORT DELEGATE="Expand_Variable"/>
+
+               <!-- String literals -->
+               <IMPORT DELEGATE="Quoted_string"/>
+
+               <!-- Commands with special syntaxes -->
+               <IMPORT DELEGATE="Special_commands"/>
+
+               <!-- All internal and external commands -->
+               <IMPORT DELEGATE="Known_commands"/>
+
+               <!-- Standard device names -->
+               <IMPORT DELEGATE="Device_names"/>
+       </RULES>
+
+       <!-- All internal and external commands -->
+       <RULES SET="Known_commands" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <KEYWORDS>
+                       <!-- KEYWORD1 are internal MS-DOS shell commands -->
+                       <KEYWORD1>break</KEYWORD1>
+                       <KEYWORD3>call</KEYWORD3>       <!-- call is a special case we want to distinguish as a KEYWORD3 -->
+                       <KEYWORD1>cd</KEYWORD1>
+                       <!-- <KEYWORD1>chcp</KEYWORD1>  This became an external command in NT -->
+                       <KEYWORD1>chdir</KEYWORD1>
+                       <KEYWORD1>cls</KEYWORD1>
+                       <KEYWORD1>copy</KEYWORD1>
+                       <!-- <KEYWORD1>ctty</KEYWORD1>  This became an external command in NT -->
+                       <KEYWORD1>date</KEYWORD1>
+                       <KEYWORD1>del</KEYWORD1>
+                       <KEYWORD1>dir</KEYWORD1>
+                       <KEYWORD1>echo</KEYWORD1>
+                       <KEYWORD1>echo.</KEYWORD1>
+                       <KEYWORD1>echo(</KEYWORD1>
+                       <KEYWORD1>erase</KEYWORD1>
+                       <KEYWORD1>exit</KEYWORD1>
+                       <KEYWORD1>for</KEYWORD1>
+                       <KEYWORD3>goto</KEYWORD3>       <!-- goto is a special case we want to distinguish as a KEYWORD3 -->
+                       <KEYWORD1>if</KEYWORD1>
+                       <KEYWORD1>lfnfor</KEYWORD1>
+                       <KEYWORD1>lh</KEYWORD1>
+                       <KEYWORD1>loadhigh</KEYWORD1>
+                       <KEYWORD1>lock</KEYWORD1>
+                       <KEYWORD1>md</KEYWORD1>
+                       <KEYWORD1>mkdir</KEYWORD1>
+                       <KEYWORD1>path</KEYWORD1>
+                       <KEYWORD1>pause</KEYWORD1>
+                       <KEYWORD1>prompt</KEYWORD1>
+                       <KEYWORD1>rd</KEYWORD1>
+                       <!-- <KEYWORD1>rem</KEYWORD1>   remarks are processed separately -->
+                       <KEYWORD1>ren</KEYWORD1>
+                       <KEYWORD1>rename</KEYWORD1>
+                       <KEYWORD1>rmdir</KEYWORD1>
+                       <KEYWORD1>set</KEYWORD1>
+                       <KEYWORD1>shift</KEYWORD1>
+                       <KEYWORD1>time</KEYWORD1>
+                       <!-- <KEYWORD1>truename</KEYWORD1> This undocumented internal DOS command was not implemented in NT -->
+                       <KEYWORD1>type</KEYWORD1>
+                       <KEYWORD1>unlock</KEYWORD1>
+                       <KEYWORD1>ver</KEYWORD1>
+                       <KEYWORD1>verify</KEYWORD1>
+                       <KEYWORD1>vol</KEYWORD1>
+
+                       <!-- New internal commands in Win2K -->
+                       <KEYWORD1>endlocal</KEYWORD1>
+                       <KEYWORD1>move</KEYWORD1>       <!-- This was an external command in DOS -->
+                       <KEYWORD1>setlocal</KEYWORD1>
+                       <KEYWORD1>start</KEYWORD1>
+                       <KEYWORD1>subst</KEYWORD1>      <!-- This was an external command in DOS -->
+
+                       <!-- New internal commands in XP (Some may be in Win2K already) -->
+                       <KEYWORD1>assoc</KEYWORD1>
+                       <KEYWORD1>color</KEYWORD1>
+                       <KEYWORD1>dpath</KEYWORD1>
+                       <KEYWORD1>ftype</KEYWORD1>
+                       <KEYWORD1>keys</KEYWORD1>
+                       <KEYWORD1>popd</KEYWORD1>
+                       <KEYWORD1>pushd</KEYWORD1>
+                       <KEYWORD1>title</KEYWORD1>
+
+                       <!-- New internal commands in Vista -->
+                       <KEYWORD1>mklink</KEYWORD1>
+
+                       <!-- Theare are NO new internal commands in Windows 7 to Windows 10 -->
+
+                       <!-- ECHO and VERIFY and BREAK associated keywords -->
+                       <KEYWORD3>on</KEYWORD3>
+                       <KEYWORD3>off</KEYWORD3>
+
+                       <!-- FOR associated keywords -->
+                       <!-- Must _not_ be defined here, to allow catching all invalid FOR syntaxes
+                       <KEYWORD3>in</KEYWORD3>
+                       <KEYWORD3>do</KEYWORD3>
+                       -->
+
+                       <!-- IF associated keywords -->
+                       <KEYWORD3>not</KEYWORD3>
+                       <KEYWORD3>exist</KEYWORD3>
+                       <KEYWORD3>errorlevel</KEYWORD3>
+                       <KEYWORD3>==</KEYWORD3>
+                       <!-- New IF keywords in Win2K -->
+                       <KEYWORD1>defined</KEYWORD1>
+                       <KEYWORD1>else</KEYWORD1>
+                       <!-- New IF keywords in XP (May be in Win2K already) -->
+                       <KEYWORD3>equ</KEYWORD3>
+                       <KEYWORD3>neq</KEYWORD3>
+                       <KEYWORD3>lss</KEYWORD3>
+                       <KEYWORD3>leq</KEYWORD3>
+                       <KEYWORD3>gtr</KEYWORD3>
+                       <KEYWORD3>geq</KEYWORD3>
+
+                       <!-- SETLOCAL associated keywords -->
+                       <KEYWORD3>disableextensions</KEYWORD3>
+                       <KEYWORD3>enableextensions</KEYWORD3>
+                       <KEYWORD3>disabledelayedexpansion</KEYWORD3>
+                       <KEYWORD3>enabledelayedexpansion</KEYWORD3>
+
+                       <!-- FUNCTION are standard DOS or WIN32 console commands -->
+                       <!-- Standard MS-DOS commands -->
+                       <!-- (those you find as stand-alone .exe or .com) in win95 %windows_root%\command folder -->
+                       <FUNCTION>append</FUNCTION>
+                       <FUNCTION>attrib</FUNCTION>
+                       <FUNCTION>chkdsk</FUNCTION>
+                       <FUNCTION>choice</FUNCTION>
+                       <FUNCTION>command</FUNCTION>
+                       <FUNCTION>debug</FUNCTION>
+                       <FUNCTION>defrag</FUNCTION>
+                       <FUNCTION>deltree</FUNCTION>
+                       <FUNCTION>diskcomp</FUNCTION>
+                       <FUNCTION>diskcopy</FUNCTION>
+                       <FUNCTION>doskey</FUNCTION>
+                       <FUNCTION>drvspace</FUNCTION>
+                       <FUNCTION>emm386</FUNCTION>
+                       <FUNCTION>expand</FUNCTION>
+                       <FUNCTION>fastopen</FUNCTION>
+                       <FUNCTION>fc</FUNCTION>
+                       <FUNCTION>fdisk</FUNCTION>
+                       <FUNCTION>find</FUNCTION>
+                       <FUNCTION>format</FUNCTION>
+                       <FUNCTION>graphics</FUNCTION>
+                       <FUNCTION>graftabl</FUNCTION>
+                       <FUNCTION>keyb</FUNCTION>
+                       <FUNCTION>label</FUNCTION>
+                       <FUNCTION>loadfix</FUNCTION>
+                       <FUNCTION>mem</FUNCTION>
+                       <FUNCTION>mode</FUNCTION>
+                       <FUNCTION>more</FUNCTION>
+                       <FUNCTION>move</FUNCTION>
+                       <FUNCTION>mscdex</FUNCTION>
+                       <FUNCTION>net</FUNCTION>
+                       <FUNCTION>nlsfunc</FUNCTION>
+                       <FUNCTION>power</FUNCTION>
+                       <FUNCTION>print</FUNCTION>
+                       <FUNCTION>replace</FUNCTION>
+                       <FUNCTION>restore</FUNCTION>
+                       <FUNCTION>scandisk</FUNCTION>
+                       <FUNCTION>setver</FUNCTION>
+                       <FUNCTION>share</FUNCTION>
+                       <FUNCTION>sort</FUNCTION>
+                       <FUNCTION>subst</FUNCTION>
+                       <FUNCTION>sys</FUNCTION>
+                       <FUNCTION>tree</FUNCTION>
+                       <FUNCTION>undelete</FUNCTION>
+                       <FUNCTION>unformat</FUNCTION>
+                       <FUNCTION>vsafe</FUNCTION>
+                       <FUNCTION>xcopy</FUNCTION>
+
+                       <!-- Additional Win9X commands -->
+                       <FUNCTION>cscript</FUNCTION>
+                       <FUNCTION>cvt</FUNCTION>
+                       <FUNCTION>extract</FUNCTION>
+                       <FUNCTION>iextract</FUNCTION>
+                       <FUNCTION>scanreg</FUNCTION>
+                       <FUNCTION>sulfnbk</FUNCTION>
+                       <FUNCTION>xcopy32</FUNCTION>
+
+                       <!-- Additional XP console commands (Most were in Win2K already) -->
+                       <FUNCTION>arp</FUNCTION>
+                       <FUNCTION>at</FUNCTION>
+                       <FUNCTION>bootcfg</FUNCTION>
+                       <FUNCTION>cacls</FUNCTION>
+                       <FUNCTION>chcp</FUNCTION>       <!-- This was an internal command in DOS -->
+                       <FUNCTION>chkntfs</FUNCTION>
+                       <FUNCTION>cipher</FUNCTION>
+                       <FUNCTION>cmd</FUNCTION>
+                       <FUNCTION>comp</FUNCTION>
+                       <FUNCTION>compact</FUNCTION>
+                       <FUNCTION>convert</FUNCTION>
+                       <FUNCTION>ctty</FUNCTION>       <!-- This was an internal command in DOS -->
+                       <FUNCTION>diskpart</FUNCTION>
+                       <FUNCTION>driverquery</FUNCTION>
+                       <FUNCTION>eventcreate</FUNCTION>
+                       <FUNCTION>findstr</FUNCTION>
+                       <FUNCTION>fsutil</FUNCTION>
+                       <FUNCTION>ftp</FUNCTION>
+                       <FUNCTION>getmac</FUNCTION>
+                       <FUNCTION>help</FUNCTION>
+                       <FUNCTION>hostname</FUNCTION>
+                       <FUNCTION>ipconfig</FUNCTION>
+                       <FUNCTION>logman</FUNCTION>
+                       <FUNCTION>logoff</FUNCTION>
+                       <FUNCTION>makecab</FUNCTION>
+                       <FUNCTION>mountvol</FUNCTION>
+                       <FUNCTION>msg</FUNCTION>
+                       <FUNCTION>nbtstat</FUNCTION>
+                       <FUNCTION>netsh</FUNCTION>
+                       <FUNCTION>netstat</FUNCTION>
+                       <FUNCTION>nslookup</FUNCTION>
+                       <FUNCTION>openfiles</FUNCTION>
+                       <FUNCTION>pathping</FUNCTION>
+                       <FUNCTION>ping</FUNCTION>
+                       <FUNCTION>powercfg</FUNCTION>
+                       <FUNCTION>qprocess</FUNCTION>
+                       <FUNCTION>rasdial</FUNCTION>
+                       <FUNCTION>recover</FUNCTION>
+                       <FUNCTION>reg</FUNCTION>
+                       <FUNCTION>regini</FUNCTION>
+                       <FUNCTION>reset</FUNCTION>
+                       <FUNCTION>route</FUNCTION>
+                       <FUNCTION>runas</FUNCTION>
+                       <FUNCTION>sc</FUNCTION>
+                       <FUNCTION>schtasks</FUNCTION>
+                       <FUNCTION>shutdown</FUNCTION>
+                       <FUNCTION>systeminfo</FUNCTION>
+                       <FUNCTION>taskkill</FUNCTION>
+                       <FUNCTION>tasklist</FUNCTION>
+                       <FUNCTION>telnet</FUNCTION>
+                       <FUNCTION>tftp</FUNCTION>
+                       <FUNCTION>tracert</FUNCTION>
+                       <FUNCTION>tsconn</FUNCTION>
+                       <FUNCTION>tsdisconn</FUNCTION>
+                       <FUNCTION>tskill</FUNCTION>
+                       <FUNCTION>w32tm</FUNCTION>
+                       <FUNCTION>winrs</FUNCTION>
+                       <FUNCTION>wmic</FUNCTION>
+
+                       <!-- Additional Vista console commands -->
+                       <FUNCTION>bcdedit</FUNCTION>
+                       <FUNCTION>choice</FUNCTION>
+                       <FUNCTION>certutil</FUNCTION>
+                       <FUNCTION>change</FUNCTION>
+                       <FUNCTION>clip</FUNCTION>
+                       <FUNCTION>forfiles</FUNCTION>
+                       <FUNCTION>icacls</FUNCTION>
+                       <FUNCTION>pnputil</FUNCTION>
+                       <FUNCTION>query</FUNCTION>
+                       <FUNCTION>quser</FUNCTION>
+                       <FUNCTION>setx</FUNCTION>
+                       <FUNCTION>timeout</FUNCTION>
+                       <FUNCTION>waitfor</FUNCTION>
+                       <FUNCTION>where</FUNCTION>
+                       <FUNCTION>whoami</FUNCTION>
+
+                       <!-- Additional Windows 7 console commands -->
+                       <FUNCTION>bcdboot</FUNCTION>
+                       <FUNCTION>dism</FUNCTION>
+                       <FUNCTION>djoin</FUNCTION>
+                       <FUNCTION>setspn</FUNCTION>
+                       <FUNCTION>tzutil</FUNCTION>
+               </KEYWORDS>
+       </RULES>
+
+       <!-- DOS-style %variables% -->
+       <RULES SET="Percent_Variable" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- Fake %# variables #% used for commenting sections of a line -->
+               <!-- Must be defined before other %variables% to be detected -->
+               <SPAN_REGEXP TYPE="COMMENT2" HASH_CHAR="%#" NO_LINE_BREAK="TRUE">
+                        <BEGIN>%#</BEGIN>
+                        <END>#%</END>
+                </SPAN_REGEXP>
+               <!-- %%N arguments -->
+               <SEQ TYPE="KEYWORD2">%*</SEQ>
+               <SEQ_REGEXP TYPE="KEYWORD2" HASH_CHAR="%" AT_WORD_START="FALSE"
+                                       >%(~[fdpnxsatz]*($[^:]+:)?)?[\d]</SEQ_REGEXP>
+               <!-- for-loop %%v variable (one char after %%) -->
+               <SEQ_REGEXP TYPE="KEYWORD2" HASH_CHAR="%" AT_WORD_START="FALSE"
+                                       >%%(~[fdpnxsatz]*(\$[^:]+:)?)?[^,;="&amp;|%!\s]</SEQ_REGEXP>
+               <!-- %variables% -->
+               <SEQ_REGEXP TYPE="KEYWORD2" HASH_CHAR="%" AT_WORD_START="FALSE"
+                                       >%[^%]*%</SEQ_REGEXP>
+       </RULES>
+
+       <!-- NT-style !variables! -->
+       <RULES SET="_Expand_Variable" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE" DEFAULT="MARKUP">
+               <!-- DOS-style %variables% inside NT-style !variables! -->
+               <IMPORT DELEGATE="Percent_Variable"/>
+       </RULES>
+       <RULES SET="Expand_Variable" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- NT-style !variables! -->
+               <SPAN TYPE="MARKUP" NO_LINE_BREAK="TRUE" DELEGATE="_Expand_Variable">
+                       <BEGIN>!</BEGIN>
+                       <END>!</END>
+               </SPAN>
+       </RULES>
+
+       <!-- "Quoted strings" -->
+       <RULES SET="_Quoted_string" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE" DEFAULT="LITERAL1">
+               <!-- DOS-style %variables% inside "Quoted strings" -->
+               <IMPORT DELEGATE="Percent_Variable"/>
+               <!-- NT-style !variables! inside "Quoted strings"-->
+               <IMPORT DELEGATE="Expand_Variable"/>
+       </RULES>
+       <RULES SET="Quoted_string" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE">
+               <SPAN TYPE="LITERAL1" NO_LINE_BREAK="TRUE" DELEGATE="_Quoted_string">
+                       <BEGIN>"</BEGIN>
+                       <END>"</END>
+               </SPAN>
+       </RULES>
+
+       <!-- Standard device names -->
+       <RULES SET="Device_names" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ_REGEXP TYPE="KEYWORD4" AT_WORD_START="TRUE" HASH_CHAR="NUL">NUL\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="KEYWORD4" AT_WORD_START="TRUE" HASH_CHAR="AUX">AUX\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="KEYWORD4" AT_WORD_START="TRUE" HASH_CHAR="PRN">PRN\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="KEYWORD4" AT_WORD_START="TRUE" HASH_CHAR="CON">CON\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="KEYWORD4" AT_WORD_START="TRUE" HASH_CHAR="COM">COM\d+\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="KEYWORD4" AT_WORD_START="TRUE" HASH_CHAR="LPT">LPT\d+\b</SEQ_REGEXP>
+       </RULES>
+
+       <!-- Pipeling and sequencing operators -->
+       <RULES SET="Pipeline_operators" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ_REGEXP TYPE="OPERATOR" HASH_CHAR="^">\^$</SEQ_REGEXP><!-- Line continuation character. TO DO: The delegation should continue on next line -->
+               <SEQ_REGEXP TYPE="OPERATOR" AT_WORD_START="TRUE" HASH_CHARS="&gt;0123456789">\d*&gt;(&amp;\d+)?</SEQ_REGEXP><!-- Ex: > or >> or 2> or 2>&1 -->
+               <SEQ TYPE="OPERATOR">&lt;</SEQ>
+               <SEQ TYPE="OPERATOR" DELEGATE="MAIN">&amp;&amp;</SEQ>
+               <SEQ TYPE="OPERATOR" DELEGATE="MAIN">&amp;</SEQ>
+               <SEQ TYPE="OPERATOR" DELEGATE="MAIN">||</SEQ>
+               <SEQ TYPE="OPERATOR" DELEGATE="MAIN">|</SEQ>
+               <!-- TO DO: Why aren't these ) caught by RULES SET="Parenthesis_blocks" below ?
+                    I'd like to flag only the extra ) as invalid here! -->
+               <SEQ TYPE="OPERATOR" DELEGATE="MAIN">)</SEQ>
+       </RULES>
+
+       <!-- A block of commands within a pair of parenthesis -->
+       <RULES SET="Parenthesis_blocks" DEFAULT="NULL">
+               <SPAN MATCH_TYPE="OPERATOR" NO_LINE_BREAK="FALSE" DELEGATE="MAIN">
+                        <BEGIN>(</BEGIN>
+                        <END>)</END>
+                </SPAN>
+       </RULES>
+
+       <!-- Commands with special syntaxes -->
+       <RULES SET="Special_commands" DEFAULT="NULL">
+               <!-- FOR loops -->
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="FOR"  DELEGATE="FOR">FOR\b</EOL_SPAN_REGEXP>
+               <!-- IF ... ELSE ... -->
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="IF"   DELEGATE="IF">IF\b</EOL_SPAN_REGEXP>
+               <!-- CALL and GOTO :label -->
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="CALL" DELEGATE="CALL">CALL\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="GOTO" DELEGATE="CALL">GOTO\b</EOL_SPAN_REGEXP>
+               <!-- ECHO message. DOS documented ECHO.message to display any string. NT supports a few other characters, like ECHO(message -->
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="ECHO" DELEGATE="ECHO.">ECHO[./\\:+(]</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="ECHO" DELEGATE="ECHO">ECHO\b</EOL_SPAN_REGEXP>
+
+               <!-- Commands with free arguments that are _not_ keywords -->
+               <!-- Workaround to avoid triggering the other rules above, if one of the arguments is FOR, IF, CALL, ... -->
+               <!-- The correct way to do this would be to find a general way to parse the (command [arguments]) syntax -->
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="SET"  DELEGATE="Arguments">SET\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="CD"   DELEGATE="Arguments">CD\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="MD"   DELEGATE="Arguments">MD\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD1" AT_WORD_START="TRUE" HASH_CHAR="RD"   DELEGATE="Arguments">RD\b</EOL_SPAN_REGEXP>
+       </RULES>
+
+       <!-- Arguments -->
+       <RULES SET="Arguments" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE" DEFAULT="NULL">
+               <IMPORT DELEGATE="Pipeline_operators"/>
+               <IMPORT DELEGATE="Percent_Variable"/>
+               <IMPORT DELEGATE="Expand_Variable"/>
+               <IMPORT DELEGATE="Quoted_string"/>
+               <IMPORT DELEGATE="Device_names"/>
+       </RULES>
+
+       <!-- FOR loops -->
+       <RULES SET="FOR" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ TYPE="KEYWORD3" AT_WORD_START="TRUE" DELEGATE="FOR /D">/D</SEQ>
+               <SEQ TYPE="KEYWORD3" AT_WORD_START="TRUE" DELEGATE="FOR /F">/F</SEQ>
+               <SEQ TYPE="KEYWORD3" AT_WORD_START="TRUE" DELEGATE="FOR /L">/L</SEQ>
+               <SEQ TYPE="KEYWORD3" AT_WORD_START="TRUE" DELEGATE="FOR /R">/R</SEQ>
+               <SEQ TYPE="NULL">/</SEQ>
+               <IMPORT DELEGATE="FOR %%"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect the %%v loop variable, and nothing else -->
+       <RULES SET="FOR %%" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ_REGEXP TYPE="INVALID"  HASH_CHAR="%%" DELEGATE="FOR IN">%%[^,;="&amp;|%!\s]\S</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="KEYWORD2" HASH_CHAR="%%" DELEGATE="FOR IN">%%[^,;="&amp;|%!\s]</SEQ_REGEXP>
+               <SEQ TYPE="NULL">%%</SEQ>
+               <SEQ TYPE="NULL">%</SEQ>
+               <IMPORT DELEGATE="INVALID"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect for /d arguments -->
+       <RULES SET="FOR /D" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="FOR %%"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect for /f arguments -->
+       <RULES SET="FOR /F" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="Quoted_string"/>
+               <IMPORT DELEGATE="FOR %%"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect for /l arguments -->
+       <RULES SET="FOR /L" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="FOR %%"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect for /r arguments -->
+       <RULES SET="FOR /R" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- The pathname that follows /r is either quoted -->
+               <IMPORT DELEGATE="Quoted_string"/>
+               <!-- Or it's a sequence of pathname characters that do not need quoting -->
+               <SEQ_REGEXP TYPE="NULL" DELEGATE="FOR %%">[^%\*\?""&lt;&gt;\|\(\)\s]+</SEQ_REGEXP>
+               <IMPORT DELEGATE="FOR %%"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect the for IN keyword, and nothing else -->
+       <RULES SET="FOR IN" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="IN" DELEGATE="FOR LIST">IN\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="NULL" AT_WORD_START="TRUE" HASH_CHAR="I">I\b</SEQ_REGEXP><!-- Avoid showing an error while typing the I of IN -->
+               <IMPORT DELEGATE="INVALID"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect the for (list) DO sequence -->
+       <RULES SET="FOR LIST" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- Special case of for ... in ('for ... ^(loop^)') -->
+               <SPAN MATCH_TYPE="OPERATOR" NO_LINE_BREAK="FALSE" DELEGATE="FOR /F ()">
+                        <BEGIN>^(</BEGIN>
+                        <END>^)</END>
+                </SPAN>
+               <!-- DOS-style (list of files) -->
+               <SPAN MATCH_TYPE="OPERATOR" NO_LINE_BREAK="FALSE" DELEGATE="FOR /F ()">
+                        <BEGIN>(</BEGIN>
+                        <END>)</END>
+                </SPAN>
+               <IMPORT DELEGATE="FOR DO"/><!-- Anything else is invalid here -->
+       </RULES>
+       <!-- Expect the for /F (list or 'command') -->
+       <RULES SET="FOR /F ()" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- NT-style 'command' or `command` -->
+               <SPAN_REGEXP MATCH_TYPE="OPERATOR" HASH_CHAR="" NO_LINE_BREAK="FALSE" DELEGATE="'Command'">
+                        <BEGIN>(['`])</BEGIN>
+                        <END REGEXP="TRUE">$1</END>
+                </SPAN_REGEXP>
+               <!-- DOS-style list -->
+               <IMPORT DELEGATE="Arguments"/>
+       </RULES>
+       <!-- NT-style 'command' or `command` -->
+       <RULES SET="'Command'" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <!-- 
+               <SEQ_REGEXP DELEGATE="FOR DO">'\s*\)</SEQ_REGEXP>
+               -->
+               <!-- Standard device names -->
+               <IMPORT DELEGATE="Device_names"/>
+               <!-- All internal and external commands -->
+               <IMPORT DELEGATE="Known_commands"/>
+               <!-- TO DO: Why can't we delegate this to MAIN? (Breaks the end of block detection) -->
+               <!-- Known bug: Even with this workaround, an & in the pipeline will break the end of ') block detection -->
+               <IMPORT DELEGATE="Arguments"/>
+       </RULES>
+       <!-- Expect the for DO keyword -->
+       <RULES SET="FOR DO" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="DO" DELEGATE="MAIN">DO\b</SEQ_REGEXP>
+               <SEQ_REGEXP TYPE="NULL" AT_WORD_START="TRUE" HASH_CHAR="D">D\b</SEQ_REGEXP><!-- Avoid showing an error while typing the D of DO -->
+               <IMPORT DELEGATE="INVALID"/><!-- Anything else is invalid here -->
+       </RULES>
+
+       <!-- IF ... ELSE ... -->
+       <RULES SET="IF" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="NOT" DELEGATE="IFF">NOT\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="/I"  DELEGATE="IF COMPARE">/I\b</EOL_SPAN_REGEXP>
+               <IMPORT DELEGATE="IFF"/>
+       </RULES>
+       <RULES SET="IFF" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="DEF" DELEGATE="IF DEFINED">DEFINED\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="EXI" DELEGATE="IF EXIST">EXIST\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="ERR" DELEGATE="IF ERRORLEVEL">ERRORLEVEL\b</EOL_SPAN_REGEXP>
+               <EOL_SPAN_REGEXP TYPE="KEYWORD3" AT_WORD_START="TRUE" HASH_CHAR="CMD" DELEGATE="IF CMDEXTVERSION">CMDEXTVERSION\b</EOL_SPAN_REGEXP>
+               <IMPORT DELEGATE="IF COMPARE"/>
+       </RULES>
+       <RULES SET="IF DEFINED" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="MAIN"/><!-- For lack of a better solution -->
+       </RULES>
+       <RULES SET="IF EXIST" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="MAIN"/><!-- For lack of a better solution -->
+       </RULES>
+       <RULES SET="IF ERRORLEVEL" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="MAIN"/><!-- For lack of a better solution -->
+       </RULES>
+       <RULES SET="IF CMDEXTVERSION" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <IMPORT DELEGATE="MAIN"/><!-- For lack of a better solution -->
+       </RULES>
+       <RULES SET="IF COMPARE" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE">
+               <SEQ TYPE="KEYWORD3">==</SEQ>
+               <IMPORT DELEGATE="MAIN"/><!-- For lack of a better solution -->
+       </RULES>
+
+       <!-- CALL and GOTO :label -->
+       <RULES SET="CALL" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE" DEFAULT="NULL">
+               <IMPORT DELEGATE="Pipeline_operators"/>
+               <IMPORT DELEGATE="Percent_Variable"/>
+               <IMPORT DELEGATE="Expand_Variable"/>
+               <IMPORT DELEGATE="Quoted_string"/>
+               <IMPORT DELEGATE="Device_names"/>
+               <!-- labels - eg "call :test" or "goto :test" -->
+               <EOL_SPAN_REGEXP AT_WORD_START="TRUE" HASH_CHAR=":" TYPE="LABEL" DELEGATE="Arguments">:[^+:,;=\s]+</EOL_SPAN_REGEXP>
+       </RULES>
+
+       <!-- ECHO message -->
+       <RULES SET="ECHO" IGNORE_CASE="TRUE" HIGHLIGHT_DIGITS="FALSE" DEFAULT="LITERAL4">
+               <!-- TO DO: (echo Off we go) is valid, and outputs the 3 words. How to catch that and color all 3 as LITERAL4? -->
+               <EOL_SPAN_REGEXP AT_WORD_START="TRUE" HASH_CHAR="O" TYPE="KEYWORD3" DELEGATE="ECHO.">(ON|OFF)\b</EOL_SPAN_REGEXP>
+               <IMPORT DELEGATE="ECHO."/>
+       </RULES>
+       <RULES SET="ECHO." IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="FALSE" DEFAULT="LITERAL4">
+               <IMPORT DELEGATE="Pipeline_operators"/>
+               <IMPORT DELEGATE="Percent_Variable"/>
+               <IMPORT DELEGATE="Expand_Variable"/>
+               <IMPORT DELEGATE="Quoted_string"/>
+               <IMPORT DELEGATE="Device_names"/>
+       </RULES>
+
+       <!-- Empty ruleset to delegate to for spots where any non-whitespace is invalid -->
+       <RULES SET="INVALID" DEFAULT="INVALID">
+               <!-- Limit the error to one line -->
+               <EOL_SPAN_REGEXP TYPE="INVALID">\S.*</EOL_SPAN_REGEXP>
+       </RULES>
+</MODE>