<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd"
[
	<!ENTITY funcname "[A-Za-z_:][A-Za-z0-9_:#&#37;@-]*">
	<!ENTITY varname  "[A-Za-z_][A-Za-z0-9_]*">
	<!ENTITY word     "[^|&amp;;()&lt;&gt;\s]+">	<!-- see man bash -->
	<!ENTITY eos      "(?=($|\s))">			<!-- eol or space following -->
	<!ENTITY noword   "(?![\w$+-])">		<!-- no word, $, + or - following -->
]>
<language name="Kommander (old parser)" version="2.07" kateversion="2.4" section="Scripts" extensions="*.kmdr" mimetype="application/x-shellscript" casesensitive="1" author="Wilbert Berendsen (wilbert@kde.nl), Andras Mantia (amantia@kde.org)" license="LGPL">

<!-- (c) 2004 by Wilbert Berendsen, wilbert@kde.nl
    Released under the LGPL, part of tdelibs/kate 
    
   Added Kommander specific highlighting.    
   (c) 2006 Andras Mantia, amantia@kde.org
-->

  <highlighting>
  
    <list name="kmdrdcopfunctions">
      <item>addUniqueItem</item>
      <item>associatedText</item>
      <item>cancel</item>
      <item>cellText</item>
      <item>clear</item>
      <item>checked</item>
      <item>children</item>
      <item>count</item>
      <item>currentColumn</item>
      <item>currentItem</item>
      <item>currentRow</item>
      <item>execute</item> 
      <item>findItem</item>
      <item>geometry</item>
      <item>global</item>
      <item>hasFocus</item>
      <item>insertColumn</item>
      <item>insertItem</item>
      <item>insertItems</item>
      <item>insertRow</item>
      <item>item</item>
      <item>itemDepth</item>
      <item>itemPath</item>
      <item>removeColumn</item>
      <item>removeItem</item>
      <item>removeRow</item>
      <item>selection</item>
      <item>setAssociatedText</item>
      <item>setChecked</item>
      <item>setCellText</item>
      <item>setCurrentItem</item>
      <item>setColumnCaption</item>
      <item>setEnabled</item>
      <item>setGlobal</item>
      <item>setMaximum</item>
      <item>setPixmap</item>
      <item>setRowCaption</item>
      <item>setSelection</item>
      <item>setText</item>
      <item>setVisible</item>
      <item>text</item>
      <item>type</item>
    </list>
    
    <list name="kmdrfunctions">
      <item>widgetText</item>
      <item>selectedWidgetText</item>
      <item>null</item>
      <item>pid</item>
      <item>dcopid</item>
      <item>parentPid</item>
      <item>debug</item>
      <item>echo</item>
      <item>env</item>
      <item>exec</item>
      <item>expr</item>
      <item>global</item>
      <item>i18n</item>
      <item>dialog</item>
      <item>readSetting</item>
      <item>setGlobal</item>
      <item>writeSetting</item>
      <item>dcop</item>
      <item>switchBlock</item>
      <item>execBegin</item>
      <item>forBlock</item>
      <item>forEachBlock</item>
      <item>ifBlock</item>
      <item>comment</item>
    </list>
    
    <list name="kmdrarray">
      <item>values</item>
      <item>keys</item>
      <item>clear</item>
      <item>count</item>
      <item>value</item>
      <item>remove</item>
      <item>setValue</item>
      <item>fromString</item>
      <item>toString</item>
    </list>
    
    <list name="kmdrstring">
      <item>length</item>
      <item>contains</item>
      <item>find</item>
      <item>findRev</item>
      <item>left</item>
      <item>right</item>
      <item>mid</item>
      <item>remove</item>
      <item>replace</item>
      <item>upper</item>
      <item>lower</item>
      <item>compare</item>
      <item>isEmpty</item>
      <item>isNumber</item>
      <item>section</item>
      <item>args</item>
      <item>round</item>
    </list>
    
    <list name="kmdrfile">
      <item>read</item>
      <item>write</item>
      <item>append</item>
      <item>exists</item>
    </list>
    
    <list name="kmdrinput">
      <item>color</item>
      <item>text</item>
      <item>password</item>
      <item>value</item>
      <item>double</item>
      <item>valueDouble</item>
      <item>openfile</item>
      <item>openfiles</item>
      <item>savefile</item>
      <item>directory</item>
    </list>
    
    <list name="kmdrmessage">
      <item>info</item>
      <item>error</item>
      <item>question</item>
      <item>warning</item>
    </list>
    
  
    <list name="keywords">
      <item> else </item>
      <item> for </item>
      <item> function </item>
      <item> in </item>
      <item> select </item>
      <item> until </item>
      <item> while </item>
      <item> . </item>
      <item> elif </item>
      <item> then </item>
      <item> set </item>
      <item> foreach </item>
      <item> end </item>
    </list>
    
    
    <list name="builtins">
      <item> : </item>
      <item> . </item>
      <item> source </item>
      <item> alias </item>
      <item> bg </item>
      <item> bind </item>
      <item> break </item>
      <item> builtin </item>
      <item> cd </item>
      <item> command </item>
      <item> compgen </item>
      <item> complete </item>
      <item> continue </item>
      <item> dirs </item>
      <item> disown </item>
      <item> echo </item>
      <item> enable </item>
      <item> eval </item>
      <item> exec </item>
      <item> exit </item>
      <item> fc </item>
      <item> fg </item>
      <item> getopts </item>
      <item> hash </item>
      <item> help </item>
      <item> history </item>
      <item> jobs </item>
      <item> kill </item>
      <item> let </item>
      <item> logout </item>
      <item> popd </item>
      <item> printf </item>
      <item> pushd </item>
      <item> pwd </item>
      <item> return </item>
      <item> set </item>
      <item> shift </item>
      <item> shopt </item>
      <item> suspend </item>
      <item> test </item>
      <item> times </item>
      <item> trap </item>
      <item> type </item>
      <item> ulimit </item>
      <item> umask </item>
      <item> unalias </item>
      <item> wait </item>
    </list>
    
    <list name="builtins_var">
      <item> export </item>
      <item> unset </item>
      <item> declare </item>
      <item> typeset </item>
      <item> local </item>
      <item> read </item>
      <item> readonly </item>
    </list>
    
    <list name="unixcommands">
      <!-- /bin -->
      <item> arch </item>
      <item> awk </item>
      <item> bash </item>
      <item> bunzip2 </item>
      <item> bzcat </item>
      <item> bzcmp </item>
      <item> bzdiff </item>
      <item> bzegrep </item>
      <item> bzfgrep </item>
      <item> bzgrep </item>
      <item> bzip2 </item>
      <item> bzip2recover </item>
      <item> bzless </item>
      <item> bzmore </item>
      <item> cat </item>
      <item> chattr </item>
      <item> chgrp </item>
      <item> chmod </item>
      <item> chown </item>
      <item> chvt </item>
      <item> cp </item>
      <item> date </item>
      <item> dd </item>
      <item> deallocvt </item>
      <item> df </item>
      <item> dir </item>
      <item> dircolors </item>
      <item> dmesg </item>
      <item> dnsdomainname </item>
      <item> domainname </item>
      <item> du </item>
      <item> dumpkeys </item>
      <item> echo </item>
      <item> ed </item>
      <item> egrep </item>
      <item> false </item>
      <item> fgconsole </item>
      <item> fgrep </item>
      <item> fuser </item>
      <item> gawk </item>
      <item> getkeycodes </item>
      <item> gocr </item>
      <item> grep </item>
      <item> groups </item>
      <item> gunzip </item>
      <item> gzexe </item>
      <item> gzip </item>
      <item> hostname </item>
      <item> igawk </item>
      <item> install </item>
      <item> kbd_mode </item>
      <item> kbdrate </item>
      <item> killall </item>
      <item> last </item>
      <item> lastb </item>
      <item> link </item>
      <item> ln </item>
      <item> loadkeys </item>
      <item> loadunimap </item>
      <item> login </item>
      <item> ls </item>
      <item> lsattr </item>
      <item> lsmod </item>
      <item> lsmod.old </item>
      <item> mapscrn </item>
      <item> mesg </item>
      <item> mkdir </item>
      <item> mkfifo </item>
      <item> mknod </item>
      <item> mktemp </item>
      <item> more </item>
      <item> mount </item>
      <item> mv </item>
      <item> nano </item>
      <item> netstat </item>
      <item> nisdomainname </item>
      <item> openvt </item>
      <item> pgawk </item>
      <item> pidof </item>
      <item> ping </item>
      <item> ps </item>
      <item> pstree </item>
      <item> pwd </item>
      <item> rbash </item>
      <item> readlink </item>
      <item> red </item>
      <item> resizecons </item>
      <item> rm </item>
      <item> rmdir </item>
      <item> run-parts </item>
      <item> sash </item>
      <item> sed </item>
      <item> setfont </item>
      <item> setkeycodes </item>
      <item> setleds </item>
      <item> setmetamode </item>
      <item> setserial </item>
      <item> sh </item>
      <item> showkey </item>
      <item> shred </item>
      <item> sleep </item>
      <item> ssed </item>
      <item> stat </item>
      <item> stty </item>
      <item> su </item>
      <item> sync </item>
      <item> tar </item>
      <item> tempfile </item>
      <item> touch </item>
      <item> true </item>
      <item> umount </item>
      <item> uname </item>
      <item> unicode_start </item>
      <item> unicode_stop </item>
      <item> unlink </item>
      <item> utmpdump </item>
      <item> uuidgen </item>
      <item> vdir </item>
      <item> wall </item>
      <item> wc </item>
      <item> ypdomainname </item>
      <item> zcat </item>
      <item> zcmp </item>
      <item> zdiff </item>
      <item> zegrep </item>
      <item> zfgrep </item>
      <item> zforce </item>
      <item> zgrep </item>
      <item> zless </item>
      <item> zmore </item>
      <item> znew </item>
      <item> zsh </item>

      <!-- some from /usr/bin -->
      <item> aclocal </item>
      <item> aconnect </item>
      <item> aplay </item>
      <item> apm </item>
      <item> apmsleep </item>
      <item> apropos </item>
      <item> ar </item>
      <item> arecord </item>
      <item> as </item>
      <item> as86 </item>
      <item> autoconf </item>
      <item> autoheader </item>
      <item> automake </item>
      <item> awk </item>
      <item> basename </item>
      <item> bc </item>
      <item> bison </item>
      <item> c++ </item>
      <item> cal </item>
      <item> cat </item>
      <item> cc </item>
      <item> cdda2wav </item>
      <item> cdparanoia </item>
      <item> cdrdao </item>
      <item> cd-read </item>
      <item> cdrecord </item>
      <item> chfn </item>
      <item> chgrp </item>
      <item> chmod </item>
      <item> chown </item>
      <item> chroot </item>
      <item> chsh </item>
      <item> clear </item>
      <item> cmp </item>
      <item> co </item>
      <item> col </item>
      <item> comm </item>
      <item> cp </item>
      <item> cpio </item>
      <item> cpp </item>
      <item> cut </item>
      <item> dc </item>
      <item> dd </item>
      <item> df </item>
      <item> diff </item>
      <item> diff3 </item>
      <item> dir </item>
      <item> dircolors </item>
      <item> directomatic </item>
      <item> dirname </item>
      <item> du </item>
      <item> env </item>
      <item> expr </item>
      <item> fbset </item>
      <item> file </item>
      <item> find </item>
      <item> flex </item>
      <item> flex++ </item>
      <item> fmt </item>
      <item> free </item>
      <item> ftp </item>
      <item> funzip </item>
      <item> fuser </item>
      <item> g++ </item>
      <item> gawk </item>
      <item> gc </item>
      <item> gcc </item>
      <item> gdb </item>
      <item> getent </item>
      <item> getopt </item>
      <item> gettext </item>
      <item> gettextize </item>
      <item> gimp </item>
      <item> gimp-remote </item>
      <item> gimptool </item>
      <item> gmake </item>
      <item> gs </item>
      <item> head </item>
      <item> hexdump </item>
      <item> id </item>
      <item> install </item>
      <item> join </item>
      <item> kill </item>
      <item> killall </item>
      <item> ld </item>
      <item> ld86 </item>
      <item> ldd </item>
      <item> less </item>
      <item> lex </item>
      <item> ln </item>
      <item> locate </item>
      <item> lockfile </item>
      <item> logname </item>
      <item> lp </item>
      <item> lpr </item>
      <item> ls </item>
      <item> lynx </item>
      <item> m4 </item>
      <item> make </item>
      <item> man </item>
      <item> mkdir </item>
      <item> mknod </item>
      <item> msgfmt </item>
      <item> mv </item>
      <item> namei </item>
      <item> nasm </item>
      <item> nawk </item>
      <item> nice </item>
      <item> nl </item>
      <item> nm </item>
      <item> nm86 </item>
      <item> nmap </item>
      <item> nohup </item>
      <item> nop </item>
      <item> od </item>
      <item> passwd </item>
      <item> patch </item>
      <item> pcregrep </item>
      <item> pcretest </item>
      <item> perl </item>
      <item> perror </item>
      <item> pidof </item>
      <item> pr </item>
      <item> printf </item>
      <item> procmail </item>
      <item> prune </item>
      <item> ps2ascii </item>
      <item> ps2epsi </item>
      <item> ps2frag </item>
      <item> ps2pdf </item>
      <item> ps2ps </item>
      <item> psbook </item>
      <item> psmerge </item>
      <item> psnup </item>
      <item> psresize </item>
      <item> psselect </item>
      <item> pstops </item>
      <item> rcs </item>
      <item> rev </item>
      <item> rm </item>
      <item> scp </item>
      <item> sed </item>
      <item> seq </item>
      <item> setterm </item>
      <item> shred </item>
      <item> size </item>
      <item> size86 </item>
      <item> skill </item>
      <item> slogin </item>
      <item> snice </item>
      <item> sort </item>
      <item> sox </item>
      <item> split </item>
      <item> ssh </item>
      <item> ssh-add </item>
      <item> ssh-agent </item>
      <item> ssh-keygen </item>
      <item> ssh-keyscan </item>
      <item> stat </item>
      <item> strings </item>
      <item> strip </item>
      <item> sudo </item>
      <item> suidperl </item>
      <item> sum </item>
      <item> tac </item>
      <item> tail </item>
      <item> tee </item>
      <item> test </item>
      <item> tr </item>
      <item> uniq </item>
      <item> unlink </item>
      <item> unzip </item>
      <item> updatedb </item>
      <item> updmap </item>
      <item> uptime </item>
      <item> users </item>
      <item> vmstat </item>
      <item> w </item>
      <item> wc </item>
      <item> wget </item>
      <item> whatis </item>
      <item> whereis </item>
      <item> which </item>
      <item> who </item>
      <item> whoami </item>
      <item> write </item>
      <item> xargs </item>
      <item> yacc </item>
      <item> yes </item>
      <item> zip </item>
      <item> zsoelim </item>
      
      <!-- others -->
      <item> dcop </item>
      <item> kdialog </item>
      <item> tdefile </item>
      <item> xhost </item>
      <item> xmodmap </item>
      <item> xset </item>
    </list>

            
    <contexts>
      <context attribute="Normal Text" lineEndContext="#stay" name="Start">
      	<IncludeRules context="FindAll" />
      </context>

<!-- ====== The following rulessets are meant to be included ======== -->
      <!-- FindAll tries to interpret everything -->
      <context attribute="Normal Text" lineEndContext="#stay" name="FindAll">
      	<IncludeRules context="FindComments" />
      	<IncludeRules context="FindCommands" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>
      
      <!-- FindMost tries to interpret anything except commands -->
      <context attribute="Normal Text" lineEndContext="#stay" name="FindMost">
      	<IncludeRules context="FindComments" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>


      <!-- FindComments consumes shell comments till EOL -->
      <context attribute="Normal Text" lineEndContext="#pop" name="FindComments">
      	<DetectChar attribute="Comment" context="Comment" char="#" firstNonSpace="true"/>
	<RegExpr attribute="Normal Text" context="Comment" String="[\s;](?=#)" />
      </context>
      <context attribute="Comment" lineEndContext="#pop" name="Comment">
	<IncludeRules context="##Alerts" />
      </context>
      
      <!-- FindCommentsParen consumes shell comments till EOL or a closing parenthese -->
      <context attribute="Normal Text" lineEndContext="#pop" name="FindCommentsParen">
      	<DetectChar attribute="Comment" context="CommentParen" char="#" firstNonSpace="true"/>
	<RegExpr attribute="Normal Text" context="CommentParen" String="[\s;](?=#)" />
      </context>
      <context attribute="Comment" lineEndContext="#pop" name="CommentParen">
      	<RegExpr attribute="Comment" context="#pop" String="[^)](?=\))" />
	<IncludeRules context="##Alerts" />
      </context>
      
      <!-- FindCommentsBackq consumes shell comments till EOL or a backquote -->
      <context attribute="Normal Text" lineEndContext="#pop" name="FindCommentsBackq">
      	<DetectChar attribute="Comment" context="CommentBackq" char="#" firstNonSpace="true"/>
	<RegExpr attribute="Normal Text" context="CommentBackq" String="[\s;](?=#)" />
      </context>
      <context attribute="Comment" lineEndContext="#pop" name="CommentBackq">
      	<RegExpr attribute="Comment" context="#pop" String="[^`](?=`)" />
	<IncludeRules context="##Alerts" />
      </context>
      
      
      <!-- FindCommands matches many items that can be expected outside strings, substitutions etc. -->
      <context attribute="Normal Text" lineEndContext="#stay" name="FindCommands">
      	<!-- start expression in double parentheses -->
      	<Detect2Chars attribute="Keyword" context="ExprDblParen" char="(" char1="(" beginRegion="expression" />
	<!-- start expression in double brackets -->
	<RegExpr attribute="Keyword" context="ExprDblBracket" String="\[\[&eos;" beginRegion="expression" column="0"/>
	<RegExpr attribute="Keyword" context="ExprDblBracket" String="\s\[\[&eos;" beginRegion="expression" />
	<!-- start expression in single brackets -->
	<RegExpr attribute="Builtin" context="ExprBracket" String="\[&eos;" beginRegion="expression" column="0"/>
	<RegExpr attribute="Builtin" context="ExprBracket" String="\s\[&eos;" beginRegion="expression" />
	<!-- start a group command with { -->
	<RegExpr attribute="Keyword" context="Group" String="\{&eos;" beginRegion="group" />
      	<!-- start a subshell -->
	<DetectChar attribute="Keyword" context="SubShell" char="(" beginRegion="subshell" />
	<!-- match do and if blocks -->
	<RegExpr attribute="Keyword" context="#stay" String="\bdo&noword;" beginRegion="do" />
      	<RegExpr attribute="Keyword" context="#stay" String="\bdone&noword;" endRegion="do" />
      	<RegExpr attribute="Keyword" context="#stay" String="\bif&noword;" beginRegion="if" />
      	<RegExpr attribute="Keyword" context="#stay" String="\bfi&noword;" endRegion="if" />
      	<!-- handle case as a special case -->
	<RegExpr attribute="Keyword" context="Case" String="\bcase&noword;" beginRegion="case" />
	<!-- handle command line options -->
	<RegExpr attribute="Option" context="#stay" String="-[A-Za-z0-9]+" />
	<RegExpr attribute="Option" context="#stay" String="--[a-z][A-Za-z0-9_-]*" />
	<!-- handle variable assignments -->
	<RegExpr attribute="Variable" context="Assign" String="\b&varname;=" />
	<RegExpr attribute="Variable" context="AssignSubscr" String="\b&varname;(?=\[[^]]+\]=)" />
	<!-- handle functions with function keyword before keywords -->
	<StringDetect attribute="Function" context="#stay" String=":()" />
	<RegExpr attribute="Keyword" context="FunctionDef" String="\bfunction\b" />
	<!-- handle keywords -->
	<keyword attribute="Keyword" context="#stay" String="keywords" />
	<keyword attribute="Builtin" context="#stay" String="builtins" />
        <keyword attribute="Command" context="#stay" String="unixcommands" />
	<!-- handle commands that have variable names as argument -->
	<keyword attribute="Builtin" context="VarName" String="builtins_var" />
        <!-- handle here-string -->
	<StringDetect attribute="Redirection" context="#stay" String="&lt;&lt;&lt;" />
	<!-- handle here document -->
	<StringDetect attribute="Redirection" context="HereDoc" String="&lt;&lt;" lookAhead="true" />
        <!-- handle process subst -->
        <RegExpr attribute="Redirection" context="ProcessSubst" String="[&lt;&gt;]\(" />
        <!-- handle redirection -->
        <RegExpr attribute="Redirection" context="#stay" String="([0-9]*(&gt;{1,2}|&lt;)(&amp;[0-9]+-?)?|&amp;&gt;|&gt;&amp;|[0-9]*&lt;&gt;)" />
	<!-- handle &, &&, | and || -->
	<RegExpr attribute="Control" context="#stay" String="([|&amp;])\1?" />
	<!-- mark function definitions without function keyword -->
        <RegExpr attribute="Function" context="#stay" String="&funcname;\s*\(\)" />
        <!-- Kommander rules -->        
        <RegExpr attribute="Comment" context="#stay" String="@#.*\s*" />
        <DetectChar attribute="KmdrMethod" context="DetectKmdr" char="@" lookAhead="true"/>
      </context>
      
      <!-- Kommander rules -->      
        
      <context attribute="KmdrMethod" lineEndContext="#pop" name="DetectKmdr">
        <RegExpr attribute="KmdrMethod" context="#stay" String="@&varname;" />        
        <DetectChar attribute="Normal Text" context="#pop" char="(" lookAhead="true"/>
        <DetectChar attribute="Normal Text" context="#pop" char=")" lookAhead="true"/>
        <RegExpr attribute="Normal Text" context="#pop" String="[\s\=\;\+\-\*\/\%]+" />
        <keyword attribute="DCOPMethod" context="#pop" String="kmdrdcopfunctions" />        
        <keyword attribute="KmdrMethod" context="#pop" String="kmdrfunctions" />        
        <keyword attribute="KmdrArray" context="#pop" String="kmdrarray" />        
        <keyword attribute="KmdrString" context="#pop" String="kmdrstring" />        
        <keyword attribute="KmdrFile" context="#pop" String="kmdrfile" />        
        <keyword attribute="KmdrInput" context="#pop" String="kmdrinput" />        
        <keyword attribute="KmdrMessage" context="#pop" String="kmdrmessage" />        
      </context>

      <!-- FindOthers contains various rules to mark different shell input -->
      <context attribute="Normal Text" lineEndContext="#stay" name="FindOthers">
	<RegExpr attribute="Escape" context="#stay" String="\\[][;&quot;\\'$`{}()|&amp;&lt;&gt;* ]" />
	<RegExpr attribute="Keyword" context="#stay" String="\\$" />
	<RegExpr attribute="Escape" context="#stay" String="\{(?!(\s|$))\S*\}" />
        <RegExpr attribute="Path" context="#stay" String="\.?/[\w_@.+-]+(?=([\s/):]|$))" />
	<!-- TODO: shell globs -->
      </context>
      
      <!-- FindStrings looks for single and double quoted strings, also with $-prefix -->
      <context attribute="Normal Text" lineEndContext="#stay" name="FindStrings">
	<DetectChar attribute="String SingleQ" context="StringSQ" char="'" />
	<DetectChar attribute="String DoubleQ" context="StringDQ" char="&quot;" />
	<Detect2Chars attribute="String SingleQ" context="StringEsc" char="$" char1="'" />
	<Detect2Chars attribute="String Transl." context="StringDQ" char="$" char1="&quot;" />
      </context>
            
      <!-- FindSubstitutions goes after anything starting with $ and ` and their escapes -->
      <context attribute="Normal Text" lineEndContext="#stay" name="FindSubstitutions">
	<RegExpr attribute="Variable" context="#stay" String="\$[*@#?$!_0-9-]" />
	<RegExpr attribute="Variable" context="Subscript" String="\$&varname;\[" />
	<RegExpr attribute="Variable" context="#stay" String="\$&varname;" />
	<RegExpr attribute="Variable" context="#stay" String="\$\{[*@#?$!_0-9-]\}" />
	<RegExpr attribute="Variable" context="#stay" String="\$\{#&varname;\}" />
	<RegExpr attribute="Variable" context="#stay" String="\$\{!&varname;\*?\}" />
	<RegExpr attribute="Variable" context="VarBrace" String="\$\{&varname;" />
	<RegExpr attribute="Variable" context="VarBrace" String="\$\{[*@#?$!_0-9-](?=[:#%/])" />
	<StringDetect attribute="Variable" context="ExprDblParenSubst" String="$((" beginRegion="expression" />
	<StringDetect attribute="Redirection" context="SubstFile" String="$(&lt;" />
        <StringDetect attribute="Variable" context="SubstCommand" String="$(" />
	<DetectChar attribute="Backquote" context="SubstBackq" char="`" />
	<RegExpr attribute="Escape" context="#stay" String="\\[`$\\]" />
      </context>

      
      

      
<!-- ====== These are the contexts that can be branched to ======= -->

      <!-- ExprDblParen consumes an expression started in command mode till )) -->
      <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParen">
      	<Detect2Chars attribute="Keyword" context="#pop" char=")" char1=")" endRegion="expression" />
	<DetectChar attribute="Normal Text" context="ExprSubParen" char="(" />
	<IncludeRules context="FindMost" />
      </context>
      
      <!-- ExprDblParenSubst like ExprDblParen but matches )) as Variable -->
      <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParenSubst">
      	<Detect2Chars attribute="Variable" context="#pop" char=")" char1=")" endRegion="expression" />
	<DetectChar attribute="Normal Text" context="ExprSubParen" char="(" />
	<IncludeRules context="FindMost" />
      </context>

      <!-- ExprSubParen consumes an expression till ) -->
      <context attribute="Normal Text" lineEndContext="#stay" name="ExprSubParen">
      	<DetectChar attribute="Normal Text" context="#pop" char=")" />
	<DetectChar attribute="Normal Text" context="ExprSubParen" char="(" />
	<IncludeRules context="FindMost" />
      </context>

      <!-- ExprBracket consumes an expression till ] -->
      <context attribute="Normal Text" lineEndContext="#stay" name="ExprBracket">
      	<RegExpr attribute="Builtin" context="#pop" String="\s\](?=($|[\s;|&amp;]))" endRegion="expression" />
      	<RegExpr attribute="Builtin" context="#pop" String="\](?=($|[\s;|&amp;]))" endRegion="expression" column="0"/>
	<DetectChar attribute="Normal Text" context="ExprSubParen" char="(" />
	<IncludeRules context="FindMost" />
      </context>

      <!-- ExprDblBracket consumes an expression till ]] -->
      <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracket">
      	<RegExpr attribute="Keyword" context="#pop" String="\s\]\](?=($|[\s;|&amp;]))" endRegion="expression" />
      	<RegExpr attribute="Keyword" context="#pop" String="\]\](?=($|[\s;|&amp;]))" endRegion="expression" column="0"/>
	<DetectChar attribute="Normal Text" context="ExprSubParen" char="(" />
	<IncludeRules context="FindMost" />
      </context>

      <!-- Group consumes shell input till } -->
      <context attribute="Normal Text" lineEndContext="#stay" name="Group">
	<DetectChar attribute="Keyword" context="#pop" char="}" endRegion="group" />
      	<IncludeRules context="FindAll" />
      </context>      

      <!-- SubShell consumes shell input till ) -->
      <context attribute="Normal Text" lineEndContext="#stay" name="SubShell">
	<DetectChar attribute="Keyword" context="#pop" char=")" endRegion="subshell" />
      	<IncludeRules context="FindAll" />
      </context>      

      <!-- Assign consumes an expression till EOL or whitespace -->
      <context attribute="Normal Text" lineEndContext="#pop" name="Assign" fallthrough="true" fallthroughContext="#pop">
      	<DetectChar attribute="Variable" context="AssignArray" char="(" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
	<RegExpr attribute="Normal Text" context="#stay" String="[\w:,+_./-]+" />
      </context>

      <!-- AssignArray consumes everything till ), marking assignments -->
      <context attribute="Normal Text" lineEndContext="#pop" name="AssignArray">
      	<DetectChar attribute="Variable" context="#pop" char=")" />
	<DetectChar attribute="Variable" context="Subscript" char="[" />
	<DetectChar attribute="Variable" context="Assign" char="=" />
	<IncludeRules context="FindMost" />
      </context>
      
      <!-- AssignSubscr first expects a [ then parses subscript and continues with '=value' -->
      <context attribute="Normal Text" lineEndContext="#pop" name="AssignSubscr" fallthrough="true" fallthroughContext="#pop">
      	<DetectChar attribute="Variable" context="Subscript" char="[" />
	<DetectChar attribute="Variable" context="Assign" char="=" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>

      <!-- Subscript consumes anything till ], marks as Variable -->
      <context attribute="Variable" lineEndContext="#stay" name="Subscript">
      	<DetectChar attribute="Variable" context="#pop" char="]" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>
      
      <!-- FunctionDef consumes a name, possibly with (), marks as Function -->
      <context attribute="Function" lineEndContext="#pop" name="FunctionDef" fallthrough="true" fallthroughContext="#pop">
      	<RegExpr attribute="Function" context="#pop" String="\s+&funcname;(\s*\(\))?" />
      </context>            
      
      <!-- VarName consumes spare variable names and assignments -->
      <context attribute="Normal Text" lineEndContext="#pop" name="VarName" fallthrough="true" fallthroughContext="#pop">
	<!-- handle command line options -->
	<RegExpr attribute="Option" context="#stay" String="-[A-Za-z0-9]+" />
	<RegExpr attribute="Option" context="#stay" String="--[a-z][A-Za-z0-9_-]*" />
	<RegExpr attribute="Variable" context="#stay" String="\b&varname;" />
	<DetectChar attribute="Variable" context="Subscript" char="[" />
	<DetectChar attribute="Variable" context="Assign" char="=" />
	<IncludeRules context="FindMost" />
	<!-- stay here in spaces and other safe characters -->
	<RegExpr attribute="Normal Text" context="#stay" String="[^]})|;`&amp;&gt;&lt;]" />
      </context>

      <!-- ProcessSubst handles <(command) and >(command) -->
      <context attribute="Normal Text" lineEndContext="#stay" name="ProcessSubst">
      	<DetectChar attribute="Redirection" context="#pop" char=")" />
	<IncludeRules context="FindCommentsParen" />
	<IncludeRules context="FindCommands" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>

      <!-- StringSQ consumes anything till ' -->            
      <context attribute="String SingleQ" lineEndContext="#stay" name="StringSQ">
        
        <DetectChar attribute="KmdrMethod" context="DetectKmdr" char="@" lookAhead="true"/>
      	<DetectChar attribute="String SingleQ" context="#pop" char="'" />
      </context>

      <!-- StringDQ consumes anything till ", substitutes vars and expressions -->
      <context attribute="String DoubleQ" lineEndContext="#stay" name="StringDQ">
        <DetectChar attribute="KmdrMethod" context="DetectKmdr" char="@" lookAhead="true"/>
      	<DetectChar attribute="String DoubleQ" context="#pop" char="&quot;" />
      	<RegExpr attribute="String Escape" context="#stay" String="\\[`&quot;\\$\n]" />
	<IncludeRules context="FindSubstitutions" />
      </context>
      
      <!-- StringEsc eats till ', but escaping many characters -->
      <context attribute="String SingleQ" lineEndContext="#stay" name="StringEsc">
      	<DetectChar attribute="String SingleQ" context="#pop" char="'" />
      	<RegExpr attribute="String Escape" context="#stay" String="\\[abefnrtv\\']" />
      	<RegExpr attribute="String Escape" context="#stay" String="\\([0-7]{1,3}|x[A-Fa-f0-9]{1,2}|c.)" />
      </context>

      <!-- VarBrace is called as soon as ${xxx is encoutered -->
      <context attribute="Variable" lineEndContext="#stay" name="VarBrace">
        <DetectChar attribute="Variable" context="#pop" char="}" />
      	<DetectChar attribute="Variable" context="Subscript" char="[" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />
	<!-- TODO: highlight various special parameter expansions } -->
      </context>
      
      <!-- SubstFile is called after a <( or >( is encoutered -->
      <context attribute="Normal Text" lineEndContext="#stay" name="SubstFile">
      	<DetectChar attribute="Redirection" context="#pop" char=")" />
	<IncludeRules context="FindCommentsParen" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>
      
      <!-- SubstCommand is called after a $( is encountered -->
      <context attribute="Normal Text" lineEndContext="#stay" name="SubstCommand">
      	<DetectChar attribute="Variable" context="#pop" char=")" />
	<IncludeRules context="FindCommentsParen" />
	<IncludeRules context="FindCommands" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>
      
      <!-- SubstBackq is called when a backquote is encountered -->
      <context attribute="Normal Text" lineEndContext="#stay" name="SubstBackq">
      	<DetectChar attribute="Keyword" context="#pop" char="`" />
	<IncludeRules context="FindCommentsBackq" />
	<IncludeRules context="FindCommands" />
	<IncludeRules context="FindStrings" />
	<IncludeRules context="FindSubstitutions" />      
	<IncludeRules context="FindOthers" />
      </context>

      <!-- Case is called after the case keyword is encoutered. We handle this because of
           the lonely closing parentheses that would otherwise disturb the expr matching -->
      <context attribute="Normal Text" lineEndContext="#stay" name="Case">
        <RegExpr attribute="Keyword" context="CaseIn" String="\sin\b" />
        <IncludeRules context="FindMost" />
      </context>

      <!-- CaseIn is called when the construct 'case ... in' has been found. -->
      <context attribute="Normal Text" lineEndContext="#stay" name="CaseIn">
        <RegExpr attribute="Keyword" context="#pop#pop" String="\besac(?=$|[\s;)])" endRegion="case" />
      	<DetectChar attribute="Keyword" context="CaseExpr" char=")" beginRegion="caseexpr" />
	<AnyChar attribute="Keyword" context="#stay" String="(|" />
        <IncludeRules context="FindMost" />
      </context>

      <!-- CaseExpr eats shell input till ;; -->
      <context attribute="Normal Text" lineEndContext="#stay" name="CaseExpr">
        <Detect2Chars attribute="Keyword" context="#pop" char=";" char1=";" endRegion="caseexpr" />
	<IncludeRules context="FindAll" />
      </context>

      <!-- HereDoc consumes Here-documents. It is called at the beginning of the "<<" construct. -->
      <context attribute="Normal Text" lineEndContext="#stay" name="HereDoc">
	<RegExpr attribute="Redirection" context="HereDocQ"   String="(&lt;&lt;\s*&quot;(&word;)&quot;)" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocQ"   String="(&lt;&lt;\s*'(&word;)')" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocQ"   String="(&lt;&lt;\s*\\(&word;))" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocNQ"  String="(&lt;&lt;(?!-)\s*(&word;))" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocIQ"  String="(&lt;&lt;-\s*&quot;(&word;)&quot;)" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocIQ"  String="(&lt;&lt;-\s*'(&word;)')" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocIQ"  String="(&lt;&lt;-\s*\\(&word;))" lookAhead="true" />
	<RegExpr attribute="Redirection" context="HereDocINQ" String="(&lt;&lt;-\s*(&word;))" lookAhead="true" />
	<StringDetect attribute="Redirection" context="#pop"  String="&lt;&lt;" /><!-- always met -->
      </context>

      <context attribute="Normal Text" lineEndContext="#pop" name="HereDocRemainder">
	<IncludeRules context="FindAll" />
      </context>

      <context attribute="Normal Text" lineEndContext="#stay" name="HereDocQ" dynamic="true">
	<RegExpr attribute="Redirection" context="HereDocRemainder" String="%1" dynamic="true" />
	<RegExpr attribute="Redirection" context="#pop#pop" String="%2[\s;]*$" dynamic="true" column="0"/>
      </context>

      <context attribute="Normal Text" lineEndContext="#stay" name="HereDocNQ" dynamic="true">
	<RegExpr attribute="Redirection" context="HereDocRemainder" String="%1" dynamic="true" />
	<RegExpr attribute="Redirection" context="#pop#pop" String="%2[\s;]*$" dynamic="true" column="0"/>
	<IncludeRules context="FindSubstitutions" />
      </context>

      <context attribute="Normal Text" lineEndContext="#stay" name="HereDocIQ" dynamic="true">
	<RegExpr attribute="Redirection" context="HereDocRemainder" String="%1" dynamic="true" />
	<RegExpr attribute="Redirection" context="#pop#pop" String="\s*%2[\s;]*$" dynamic="true" column="0"/>
      </context>

      <context attribute="Normal Text" lineEndContext="#stay" name="HereDocINQ" dynamic="true">
	<RegExpr attribute="Redirection" context="HereDocRemainder" String="%1" dynamic="true" />
	<RegExpr attribute="Redirection" context="#pop#pop" String="\s*%2[\s;]*$" dynamic="true" column="0"/>
	<IncludeRules context="FindSubstitutions" />
      </context>

    </contexts>
    
    <itemDatas>
      <itemData name="Normal Text"	defStyleNum="dsNormal" />
      <itemData name="Comment"		defStyleNum="dsComment" />
      <itemData name="Keyword" 		defStyleNum="dsKeyword" />
      <itemData name="Control" 		defStyleNum="dsKeyword" />
      <itemData name="Builtin" 		defStyleNum="dsKeyword" color="#808" />
      <itemData name="Command" 		defStyleNum="dsKeyword" color="#c0c" />
      <itemData name="Redirection" 	defStyleNum="dsKeyword" color="#238" />
      <itemData name="Escape" 		defStyleNum="dsDataType" />
      <itemData name="String SingleQ" 	defStyleNum="dsString" />
      <itemData name="String DoubleQ" 	defStyleNum="dsString" />
      <itemData name="Backquote" 	defStyleNum="dsKeyword" />
      <itemData name="String Transl." 	defStyleNum="dsString" />
      <itemData name="String Escape" 	defStyleNum="dsDataType" />
      <itemData name="Variable" 	defStyleNum="dsOthers" />
      <itemData name="Expression" 	defStyleNum="dsOthers" />
      <itemData name="Function" 	defStyleNum="dsChar" bold="1" />
      <itemData name="Path" 		defStyleNum="dsNormal" />
      <itemData name="Option" 		defStyleNum="dsNormal" />
      <itemData name="KmdrMethod" defStyleNum="dsKeyword" italic="1" color="#008000" />
      <itemData name="DCOPMethod" defStyleNum="dsKeyword" italic="1" color="#21E52B" />
      <itemData name="KmdrString" defStyleNum="dsKeyword" italic="1" color="#D0D000" />
      <itemData name="KmdrArray" defStyleNum="dsKeyword" italic="1" color="#C0C0FF" />
      <itemData name="KmdrFile" defStyleNum="dsKeyword" italic="1" color="#FF0000" />
      <itemData name="KmdrInput" defStyleNum="dsKeyword" italic="1" color="#FF8000" />
      <itemData name="KmdrMessage" defStyleNum="dsKeyword" italic="1" color="#800000" />
    </itemDatas>
  </highlighting>
  <general>
    <comments>
      <comment name="singleLine" start="@#"/>
    </comments>
    <keywords casesensitive="1" weakDeliminator="^%#[]$._{}:-" additionalDeliminator="`."/>
  </general>
</language>