<?xml version="1.0" encoding="UTF-8"?>
<!--

 Author: Silian Della Ragione <silian87@gechi.it>
 Copyright (C) 2005 Silian Della Ragione <silian87@gechi.it>
 Copyright (C) 2008 Steve Frécinaux <code@istique.net>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.

 You should have received a copy of the GNU Library General Public
 License along with this library; if not, write to the
 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.

-->
<language id="sh" _name="sh" version="2.0" _section="Scripts">
  <metadata>
    <property name="mimetypes">text/x-shellscript;application/x-shellscript;text/x-sh</property>
    <property name="globs">*.sh</property>
    <property name="line-comment-start">#</property>
  </metadata>

  <styles>
    <style id="comment"             _name="Comment"             map-to="def:comment"/>
    <style id="shebang"             _name="Shebang"             map-to="def:shebang"/>
    <style id="function"            _name="Function"            map-to="def:function"/>
    <style id="string"              _name="String"              map-to="def:string"/>
    <style id="keyword"             _name="Keyword"             map-to="def:keyword"/>
    <style id="variable"            _name="Variable"            map-to="def:type"/> <!-- FIXME: need to sort out proper styles for variables -->
    <style id="variable-definition" _name="Variable Definition" map-to="sh:variable"/>
    <style id="others"              _name="Others"              map-to="def:keyword"/>
    <style id="common-command"      _name="Common Commands"     map-to="def:keyword"/>
    <style id="here-doc-bound"      _name="Heredoc Bound"       map-to="def:keyword"/>
    <style id="subshell"            _name="Subshell"            map-to="def:preprocessor"/>
  </styles>

  <definitions>

    <!-- we cannot use def:shell-like-comment, because
         m4.lang needs to replace this context -->
    <context id="line-comment" style-ref="comment" end-at-line-end="true">
      <start>(?&lt;!\S)#</start>
      <include>
        <context ref="def:in-comment"/>
      </include>
    </context>

    <context id="double-quoted-string" style-ref="string">
      <start>"</start>
      <end>"</end>
      <include>
        <!-- highlight escaped chars -->
        <context style-ref="def:special-char">
            <match>\\[$`"\\]</match>
        </context>
        <!-- skip backslash where it's not an escaping char -->
        <context>
            <match>\\</match>
        </context>
        <context ref="def:line-continue"/>
	<context ref="variable"/>
	<context ref="backtick-subshell"/>
      </include>
    </context>

    <context id="single-quoted-string" style-ref="string">
      <start>'</start>
      <end>'</end>
    </context>

    <context id="subshell">
      <start>\(</start>
      <end>\)</end>
      <include>
        <context sub-pattern="0" where="start" style-ref="keyword"/>
        <context sub-pattern="0" where="end" style-ref="keyword"/>
        <context ref="sh"/>
      </include>
    </context>

    <context id="backtick-subshell" style-ref="subshell">
      <start>`</start>
      <end>`</end>
      <include>
        <context ref="def:escape"/>
        <context ref="def:line-continue"/>
        <context ref="variable"/>
        <context ref="built-in-command"/>
        <context ref="common-command"/>
        <context ref="single-quoted-string"/>
        <context ref="double-quoted-string"/>
      </include>
    </context>

    <context id="punctuator" style-ref="others">
      <match>[;\|&amp;/]</match>
    </context>

    <context id="function" style-ref="function">
      <match>\b[a-zA-Z_][a-zA-Z0-9_]+[ \t]*\(\)</match>
    </context>

    <context id="redirection" style-ref="others">
      <keyword>&gt;&amp;+[0-9]</keyword>
      <keyword>\b[0-9]+&gt;&amp;</keyword>
      <keyword>\b[0-9]+&gt;&amp;+[0-9]</keyword>
      <keyword>\b[0-9]+&gt;</keyword>
      <keyword>&gt;&gt;</keyword>
      <keyword>\b[0-9]+&gt;&gt;</keyword>
      <keyword>&lt;&amp;[0-9]</keyword>
      <keyword>\b[0-9]+&lt;&amp;</keyword>
      <keyword>\b[0-9]+&lt;&amp;[0-9]</keyword>
      <keyword>\b[0-9]+&lt;</keyword>
      <keyword>&lt;&lt;+[0-9]</keyword>
      <keyword>\b[0-9]+&lt;&lt;</keyword>
    </context>

    <context id="here-doc">
      <start extended="true" dupnames="true">
        &lt;&lt;-?\s*\\?(
          \"(?P&lt;HDB&gt;\S+)\" | # "EOF"
          \'(?P&lt;HDB&gt;\S+)\' | # 'EOF'
          (?P&lt;HDB&gt;\S+)       # EOF
        )$
      </start>
      <end>^\t*\%{HDB@start}$</end>
      <include>
        <context sub-pattern="0" where="start" style-ref="here-doc-bound"/>
        <context sub-pattern="0" where="end" style-ref="here-doc-bound"/>
      </include>
    </context>

    <context id="operator" style-ref="function">
      <keyword>\-a\b</keyword>
      <keyword>\-b\b</keyword>
      <keyword>\-c\b</keyword>
      <keyword>\-d\b</keyword>
      <keyword>\-e\b</keyword>
      <keyword>\-f\b</keyword>
      <keyword>\-g\b</keyword>
      <keyword>\-h\b</keyword>
      <keyword>\-k\b</keyword>
      <keyword>\-p\b</keyword>
      <keyword>\-r\b</keyword>
      <keyword>\-s\b</keyword>
      <keyword>\-t\b</keyword>
      <keyword>\-u\b</keyword>
      <keyword>\-w\b</keyword>
      <keyword>\-x\b</keyword>
      <keyword>\-O\b</keyword>
      <keyword>\-G\b</keyword>
      <keyword>\-L\b</keyword>
      <keyword>\-S\b</keyword>
      <keyword>\-N\b</keyword>
      <keyword>\-nt\b</keyword>
      <keyword>\-ot\b</keyword>
      <keyword>\-ef\b</keyword>
      <keyword>\-o\b</keyword>
      <keyword>\-z\b</keyword>
      <keyword>\-n\b</keyword>
      <keyword>&lt;</keyword>
      <keyword>&gt;</keyword>
      <keyword>\!=</keyword>
      <keyword>\-eq\b</keyword>
      <keyword>\-ne\b</keyword>
      <keyword>\-lt\b</keyword>
      <keyword>\-le\b</keyword>
      <keyword>\-gt\b</keyword>
      <keyword>\-ge\b</keyword>
    </context>

    <context id="variable" style-ref="variable">
      <match>\$+[!@?*#\${a-zA-Z0-9_][}a-zA-Z0-9_]*</match>
    </context>

    <context id="variable-definition">
      <match>(^|(?&lt;=then|else|do|export))\s*([a-zA-Z_][a-zA-Z0-9_]*)\=</match>
      <include>
        <context sub-pattern="2" style-ref="variable-definition"/>
      </include>
    </context>

    <context id="built-in-command-1" style-ref="keyword">
      <prefix></prefix>
      <suffix></suffix>
      <keyword>\!</keyword>
      <keyword>\{</keyword>
      <keyword>\}</keyword>
      <keyword>\:</keyword>
      <keyword>(?&lt;=\s)\.(?=\s)</keyword>
    </context>

    <context id="for-command">
      <start>\bfor\b</start>
      <end>\bin\b</end>
      <include>
        <context sub-pattern="0" where="start" style-ref="keyword"/>
        <context sub-pattern="0" where="end" style-ref="keyword"/>
        <context style-ref="variable-definition" once-only="true">
          <match>\w+</match>
        </context>
      </include>
    </context>

    <context id="built-in-command-2" style-ref="keyword">
      <prefix>(?&lt;![^\s;\(\)])</prefix>
      <suffix>(?![^\s;\(\)])</suffix>
      <keyword>do</keyword>
      <keyword>done</keyword>
      <keyword>elif</keyword>
      <keyword>else</keyword>
      <keyword>else</keyword>
      <keyword>fi</keyword>
      <keyword>for</keyword>
      <keyword>function</keyword>
      <keyword>if</keyword>
      <keyword>in</keyword>
      <keyword>select</keyword>
      <keyword>then</keyword>
      <keyword>until</keyword>
      <keyword>while</keyword>
      <keyword>bash</keyword>
      <keyword>alias</keyword>
      <keyword>bg</keyword>
      <keyword>bind</keyword>
      <keyword>break</keyword>
      <keyword>builtin</keyword>
      <keyword>cd</keyword>
      <keyword>command</keyword>
      <keyword>compgen</keyword>
      <keyword>complete</keyword>
      <keyword>continue</keyword>
      <keyword>declare</keyword>
      <keyword>dirs</keyword>
      <keyword>disown</keyword>
      <keyword>echo</keyword>
      <keyword>enable</keyword>
      <keyword>eval</keyword>
      <keyword>exec</keyword>
      <keyword>exit</keyword>
      <keyword>export</keyword>
      <keyword>fc</keyword>
      <keyword>fg</keyword>
      <keyword>getopts</keyword>
      <keyword>hash</keyword>
      <keyword>help</keyword>
      <keyword>history</keyword>
      <keyword>jobs</keyword>
      <keyword>kill</keyword>
      <keyword>let</keyword>
      <keyword>local</keyword>
      <keyword>logout</keyword>
      <keyword>podp</keyword>
      <keyword>printf</keyword>
      <keyword>pushd</keyword>
      <keyword>pwd</keyword>
      <keyword>read</keyword>
      <keyword>readonly</keyword>
      <keyword>return</keyword>
      <keyword>set</keyword>
      <keyword>shift</keyword>
      <keyword>shopt</keyword>
      <keyword>source</keyword>
      <keyword>suspend</keyword>
      <keyword>test</keyword>
      <keyword>times</keyword>
      <keyword>trap</keyword>
      <keyword>type</keyword>
      <keyword>typeset</keyword>
      <keyword>ulimit</keyword>
      <keyword>umask</keyword>
      <keyword>unalias</keyword>
      <keyword>unset</keyword>
      <keyword>wait</keyword>
    </context>

    <context id="built-in-command">
      <include>
        <context ref="built-in-command-1"/>
        <context ref="for-command"/>
        <context ref="built-in-command-2"/>
      </include>
    </context>

    <context id="common-command" style-ref="common-command">
      <prefix>(?&lt;![\w\-\.])</prefix>
      <suffix>(?![\w\-\.])</suffix>
      <keyword>cp</keyword>
      <keyword>rm</keyword>
      <keyword>mv</keyword>
      <keyword>which</keyword>
      <keyword>cat</keyword>
      <keyword>grep</keyword>
      <keyword>sed</keyword>
      <keyword>awk</keyword>
      <keyword>mkdir</keyword>
      <keyword>rmdir</keyword>
      <keyword>ls</keyword>
      <keyword>ps</keyword>
      <keyword>killall</keyword>
      <keyword>pidof</keyword>
      <keyword>diff</keyword>
      <keyword>head</keyword>
      <keyword>tail</keyword>
      <keyword>chown</keyword>
      <keyword>chmod</keyword>
      <keyword>dd</keyword>
      <keyword>find</keyword>
      <keyword>locate</keyword>
      <keyword>tar</keyword>
      <keyword>gunzip</keyword>
      <keyword>gzip</keyword>
      <keyword>bunzip2</keyword>
      <keyword>bzip2</keyword>
      <keyword>zip</keyword>
      <keyword>unzip</keyword>
      <keyword>mount</keyword>
      <keyword>umount</keyword>
      <keyword>sh</keyword>
      <keyword>clear</keyword>
      <keyword>wget</keyword>
      <keyword>date</keyword>
      <keyword>dir</keyword>
      <keyword>du</keyword>
      <keyword>expr</keyword>
      <keyword>su</keyword>
      <keyword>passwd</keyword>
      <keyword>man</keyword>
      <keyword>info</keyword>
      <keyword>id</keyword>
      <keyword>ifconfig</keyword>
      <keyword>gcc</keyword>
      <keyword>make</keyword>
      <keyword>ld</keyword>
      <keyword>ln</keyword>
      <keyword>lsmod</keyword>
      <keyword>insmod</keyword>
      <keyword>modprobe</keyword>
      <keyword>less</keyword>
      <keyword>more</keyword>
      <keyword>patch</keyword>
      <keyword>ping</keyword>
      <keyword>pkg-config</keyword>
      <keyword>nice</keyword>
      <keyword>renice</keyword>
      <keyword>file</keyword>
      <keyword>sudo</keyword>
      <keyword>beep</keyword>
      <keyword>tempfile</keyword>
      <keyword>touch</keyword>
      <keyword>eject</keyword>
      <keyword>uname</keyword>
      <keyword>uptime</keyword>
      <keyword>whoami</keyword>
      <keyword>who</keyword>
      <keyword>whereis</keyword>
      <keyword>sleep</keyword>
      <keyword>dialog</keyword>
      <keyword>xdialog</keyword>
      <keyword>zenity</keyword>
      <keyword>sort</keyword>
      <keyword>uniq</keyword>
    </context>

    <context id="case">
      <start>\bcase\b</start>
      <end>\besac\b</end>
      <include>
        <context sub-pattern="0" where="start" style-ref="keyword"/>
        <context sub-pattern="0" where="end" style-ref="keyword"/>
        <context ref="double-quoted-string"/>
        <context ref="single-quoted-string"/>
        <context style-ref="others">
          <match>[^\)\s]+\s*\)|;;</match>
        </context>
        <context ref="sh"/>
      </include>
    </context>

    <context id="sh">
      <include>
        <context ref="def:shebang" style-ref="shebang"/>
        <context ref="line-comment"/>
        <context ref="def:escape"/>
        <context ref="single-quoted-string"/>
        <context ref="double-quoted-string"/>
        <context ref="subshell"/>
        <context ref="backtick-subshell"/>
        <context ref="case"/>
        <context ref="punctuator"/>
        <context ref="function"/>
        <context ref="here-doc"/>
        <context ref="redirection"/>
        <context ref="operator"/>
        <context ref="variable"/>
        <context ref="variable-definition"/>
        <context ref="built-in-command"/>
        <context ref="common-command"/>
      </include>
    </context>

  </definitions>
</language>
