<?xml version='1.0'?>
<!-- Copyright (c) 2002 Felix Rosencrantz

 Information about this tool can be found at:
     http://www.oocities.org/f_rosencrantz/xml_completion.htm
 -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<!--
ActionTagGeneration says how to generate an action where only an action
tag is available.  Current values are:
    state     The action tag is used as a state name. (default)
    handler   The action tag is used as the argument to a function call of the
               function named '{$FunctionPrefix}_handle'
    default   Use the default action template.
    error     Fail if an action tag that is not defined is used.
    
-->
<xsl:param name="ActionTagGeneration" select="'state'"/>

<xsl:variable name="Includes"
              select="document(/completion/meta/includes/include/@file)"/>

<xsl:variable name="Root" select="/"/>

<xsl:variable name="BackCR"><xsl:text> \
</xsl:text>
  </xsl:variable>

<xsl:variable name="CR"><xsl:text>
</xsl:text>
</xsl:variable>


<!-- Prefix String for function names that are created -->
<xsl:variable name="FunctionPrefix">
    <xsl:choose>
        <xsl:when test="//subcommands/@prefix">
            <xsl:value-of select="//subcommands/@prefix"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="/completion/meta/filename"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

<!-- Starting point -->
<xsl:template match="/completion">

  <xsl:call-template name="FirstLine"></xsl:call-template>
  <xsl:choose>
    <xsl:when test="subcommands">
      <xsl:text>#Redefine command:</xsl:text>
      <xsl:value-of select="meta/filename"/>
      <xsl:value-of select="$CR"/>
      <xsl:text>_</xsl:text>
      <xsl:value-of select="meta/filename"/>
      <xsl:text>()</xsl:text>
      <xsl:value-of select="$CR"/>
      <xsl:text>{</xsl:text>
    </xsl:when>
  </xsl:choose>
  <xsl:apply-templates select="state_prolog"/>
  <xsl:apply-templates select="prolog"/>
  <xsl:if test="services/service">
    <xsl:apply-templates select="services"/>
  </xsl:if>
  <xsl:call-template name="Handle_States">
    <xsl:with-param name="states" select="states/state"/>
    <xsl:with-param name="action_root" select="services"/>
  </xsl:call-template>


  <xsl:choose>
    <xsl:when test="subcommands">
      <!-- End of redefine command -->
      <xsl:text>}</xsl:text>
      <xsl:apply-templates select="dispatch"/>
      <xsl:apply-templates select="subcommands"/>
      <xsl:value-of select="$CR"/>
      <xsl:text>#Now call redefined function</xsl:text>
      <xsl:value-of select="$CR"/>
      <xsl:text>_</xsl:text>
      <xsl:value-of select="meta/filename"/>
      <xsl:text> "$*"</xsl:text>
      <xsl:value-of select="$CR"/>
    </xsl:when>
  </xsl:choose>



</xsl:template>


<xsl:template name="FirstLine">
  <xsl:text>#compdef </xsl:text>
  <xsl:for-each select="//service">
    <xsl:value-of select="@name"/><xsl:text> </xsl:text>
  </xsl:for-each><xsl:text disable-output-escaping="yes"><![CDATA[
#Generated by]]></xsl:text>
    <xsl:for-each select="//meta/generation/gen_command">
        <xsl:text disable-output-escaping="yes"><![CDATA[
#   ]]></xsl:text><xsl:value-of select="."/>
    </xsl:for-each>
<xsl:text disable-output-escaping="yes"><![CDATA[
#   args.xsl
#   For details see:
#       http://www.oocities.org/f_rosencrantz/xml_completion.htm

]]></xsl:text>
</xsl:template>

<xsl:template match="prolog">
    <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="services">
  <xsl:choose>
    <xsl:when test="count(*) = 1">
      <xsl:apply-templates select="service"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text>case $service in
</xsl:text>
      <xsl:for-each select="service">
        <xsl:text>        "</xsl:text>
        <xsl:value-of select="@name"/>
        <xsl:text>")
</xsl:text>
        <xsl:apply-templates select="."/>
        <xsl:text>      ;;
</xsl:text>
      </xsl:for-each>
      <xsl:text>esac
</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="service">
  <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="arguments">
  <xsl:text>    _arguments </xsl:text>
  <xsl:apply-templates select="argoption"/> <xsl:text>\
</xsl:text>
</xsl:template>

<xsl:template match="argoption">
  <xsl:if test="(count(@use) = 0) or (@use = false())">
    <xsl:value-of select="name/text()"/>
    <xsl:text> </xsl:text>
  </xsl:if>
</xsl:template>

<xsl:template match="argspecs">
  <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="argspec">
  <xsl:variable name="here" select="."/>
  <xsl:variable name="ArgSpec">
    <xsl:apply-templates select="optspec"/>
    <xsl:for-each select="description">
      <xsl:variable name="desc">
        <xsl:apply-templates select="."/>
      </xsl:variable>
      <xsl:if test="not($desc = '')">
         <xsl:text>:</xsl:text>
         <xsl:value-of select="$desc"/>
      </xsl:if>
    </xsl:for-each>
    <xsl:if test="last_description">
      <xsl:text>:</xsl:text>
      <xsl:apply-templates select="last_description"/>
    </xsl:if>
    </xsl:variable>
  <xsl:variable name="apos" select='"&apos;"' />
  <xsl:variable name="quot" select="'&quot;'" />
  <xsl:choose>
    <xsl:when test="contains($ArgSpec,$apos) and contains($ArgSpec,$quot)">
      <xsl:message>
        Service <xsl:value-of select="ancestor::service/@name"/>
        Flag <xsl:value-of select="optspec/flagarg/@name"/>
        Has both single and double quotes... May generate syntax error with
        generated arguments call.
      </xsl:message>
      <!-- What the heck just use ' -->
      <xsl:text>                '</xsl:text>
      <xsl:value-of select="$ArgSpec"/>
      <xsl:text>'</xsl:text>
    </xsl:when>
    <xsl:when test="contains($ArgSpec,$quot)">
      <xsl:text>                '</xsl:text>
      <xsl:value-of select="$ArgSpec"/>
      <xsl:text>'</xsl:text>
    </xsl:when>
    <xsl:when test="contains($ArgSpec,$apos)">
      <xsl:text>                "</xsl:text>
      <xsl:value-of select="$ArgSpec"/>
      <xsl:text>"</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text>                '</xsl:text>
      <xsl:value-of select="$ArgSpec"/>
      <xsl:text>'</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
  <xsl:choose>
        <xsl:when test="position() != last()">
                <xsl:value-of select="$BackCR"/>
        </xsl:when>
        <xsl:when test="name($here/../following-sibling::*[1]) = 'code'">
                <xsl:if test="$here/../following-sibling::code[1]/@samecommand">
                        <xsl:value-of select="$BackCR"/>
                </xsl:if>
        </xsl:when>
        <xsl:otherwise>
                <xsl:value-of select="substring-after($BackCR,'\')"/>
        </xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="optspec">
        <xsl:if test="count(exclusionlist) != 0">
                <xsl:text>(</xsl:text>
                <xsl:for-each select="exclusionlist/flag">
                        <xsl:value-of select="text()"/>
                        <xsl:if test="position() != last()">
                                <xsl:text> </xsl:text>
                        </xsl:if>
                </xsl:for-each>
                <xsl:text>)</xsl:text>
        </xsl:if>

        <xsl:if test="count(anyposition) != 0">
                <xsl:text>*</xsl:text>
        </xsl:if>

        <xsl:if test="count(flagarg/more_than_once) != 0">
                <xsl:text>*</xsl:text>
        </xsl:if>

        <xsl:if test="count(flagarg/@name) != 0">
                <xsl:value-of select="flagarg/@name"/>
                    <!-- might make sense to put same_word under flagarg -->
                <xsl:if test="same_word">
                    <xsl:apply-templates select="same_word"/>
                </xsl:if>
        </xsl:if>
        <xsl:if test="count(position) != 0">
                <xsl:value-of select="position/@position"/>
        </xsl:if>
        <xsl:if test="not(normalize-space(flagarg/explanation) = '')">
                <xsl:text>[</xsl:text>
                <xsl:value-of select="normalize-space(flagarg/explanation)"/>
                <xsl:text>]</xsl:text>
        </xsl:if>
<words_only_normal_args/>
        <xsl:if test="words_only_normal_args">
            <xsl:text>:</xsl:text>
        </xsl:if>
</xsl:template>

<xsl:template match="same_word">
    <xsl:if test="@eq">
     <xsl:text>=</xsl:text>
    </xsl:if>
    <xsl:if test="@must">
     <xsl:text>-</xsl:text>
    </xsl:if>
</xsl:template>

<xsl:template match="description">
        <xsl:variable name="root" select="."/>
        <xsl:choose>
          <xsl:when test="not(normalize-space(message) = '')">
            <xsl:value-of select="normalize-space(message)"/>
          </xsl:when>
          <xsl:when
                test="@tag and $Includes//messagetemplate[@tag=$root/@tag]">
            <xsl:apply-templates
                select="$Includes//messagetemplate[@tag=$root/@tag]/message"/>
          </xsl:when>

          <xsl:when test="action/@tag and $Includes//messagetemplate[@tag=action/@tag]">
            <xsl:apply-templates
               select="$Includes//messagetemplate[@tag=action/@tag]/message"/>

          </xsl:when>
          <xsl:when test="action/@tag">
            <xsl:text>Handling Tag </xsl:text>
            <xsl:value-of select="action/@tag"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text> </xsl:text>
          </xsl:otherwise>
        </xsl:choose>
        <xsl:apply-templates select="action"/>
</xsl:template>

<xsl:template match="last_description">
     <xsl:text>*</xsl:text>
     <xsl:value-of select="ends_with_pattern/text()"/>
     <xsl:text>:</xsl:text>
     <xsl:if test="count(limit_words_to_arg) != 0">
          <xsl:text>:</xsl:text>
     </xsl:if>
     <xsl:value-of select="normalize-space(message/text())"/>
     <xsl:apply-templates select="action"/>
</xsl:template>

<xsl:template match="action">
    <xsl:if test="count(add_no_compadd_args) != 0">
      <xsl:text> </xsl:text>
    </xsl:if>
    <xsl:choose>
        <xsl:when test="command">
                <xsl:text>:</xsl:text>
                <xsl:value-of select="normalize-space(command)"/>
        </xsl:when>
        <xsl:when test="state">
                <xsl:text>:</xsl:text>
                <xsl:text>-&gt;</xsl:text>
                <xsl:value-of select="state/text()"/>
        </xsl:when>
    <xsl:when test="string-length(fixed_set/fixed_string/description/text()) > 1">
        <xsl:text>:</xsl:text>
        <xsl:text>((</xsl:text>
                <xsl:for-each select="fixed_set/fixed_string">
                <xsl:value-of select="value"/>
                <xsl:text>\:</xsl:text>
                <xsl:call-template name="backslash-space">
                     <xsl:with-param name="text" select="description/text()"/>
                     <xsl:with-param name="find_string" select="' '"/>
                     <xsl:with-param name="replace_string" select="'\ '"/>
                </xsl:call-template>
                <xsl:if test="position() != last()">
                        <xsl:text> </xsl:text>
                </xsl:if>
        </xsl:for-each>
                <xsl:text>))</xsl:text>
        </xsl:when>
        <xsl:when test="count(fixed_set)">
                <xsl:text>:</xsl:text>
                <xsl:text>(</xsl:text>
                <xsl:for-each select="fixed_set/fixed_string">
                <xsl:value-of select="value"/>
                <xsl:if test="position() != last()">
                        <xsl:text> </xsl:text>
                </xsl:if>
        </xsl:for-each>
                <xsl:text>)</xsl:text>
        </xsl:when>
        <xsl:when test="@tag">
            <xsl:call-template name="HandleTagAction">
              <xsl:with-param name="actionNode" select="."/>
            </xsl:call-template>
        </xsl:when>
        <!--  NO OTHERWISE -->
        </xsl:choose>
</xsl:template>


<!-- Pull actions from included defines file -->
<xsl:template name="HandleTagAction">
  <xsl:param name="actionNode"/>

  <xsl:choose>
    <xsl:when test="$Includes//actiontemplate[@tag=$actionNode/@tag]">
       <xsl:apply-templates select="$Includes//actiontemplate[@tag=$actionNode/@tag]/action"/>
    </xsl:when>
    <xsl:when test="$Includes//defaultactiontemplate and $ActionTagGeneration = 'default'">
        <xsl:apply-templates select="$Includes//defaultactiontemplate"/>
    </xsl:when>
    <xsl:when test="$ActionTagGeneration = 'state'">
        <xsl:text>:</xsl:text>
        <xsl:text>-&gt;</xsl:text>
        <xsl:value-of select="$actionNode/@tag"/>
    </xsl:when>
    <xsl:when test="$ActionTagGeneration = 'error'">
        <xsl:message>
            Unknown action tag <xsl:value-of select="$actionNode/@tag"/>
        </xsl:message>
    </xsl:when>
    <xsl:when test="$ActionTagGeneration = 'handler'">
       <xsl:variable name="action">
          <action>
            <command>
              <xsl:value-of select="$FunctionPrefix"/>_handle <xsl:value-of select="$actionNode/@tag"/>
            </command>
          </action>
       </xsl:variable>
       <xsl:apply-templates select="$action"/>
    </xsl:when>
    <xsl:otherwise>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="Handle_States">
 <xsl:param name="action_root"/>
 <xsl:param name="states"/>
    <xsl:variable name="bogus_included_states">
            <xsl:for-each select="$Includes//actiontemplate[state]">
                <xsl:choose>
                <xsl:when test="@tag = $action_root//action/@tag">
                    <xsl:text>.</xsl:text>
                </xsl:when>
                <xsl:when test="$ActionTagGeneration = 'state'">
                    <xsl:text>.</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="included_states">
            <xsl:for-each select="$Includes//actiontemplate[state]">
                <xsl:if test="@tag = $action_root//action/@tag">
                    <xsl:text>.</xsl:text>
                </xsl:if>
            </xsl:for-each>
            <xsl:if test="$ActionTagGeneration = 'state'">
                <xsl:for-each select="$action_root//action/@tag">
                    <xsl:choose>
                    <xsl:when test="$Includes//actiontemplate[@tag=current()]/state">
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text>.</xsl:text>
                    </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:if>
    </xsl:variable>
    <xsl:choose>
    <xsl:when test="count($states)!=0 or not(normalize-space($included_states) = '')">
    <xsl:text>case $state in
</xsl:text>
    <xsl:apply-templates select="$states"/>
    <xsl:for-each select="$Includes//actiontemplate[state]">
        <xsl:if test="@tag = $action_root//action/@tag">
            <xsl:apply-templates select="state"/>
        </xsl:if>
    </xsl:for-each>
    <xsl:if test="$ActionTagGeneration = 'state'">
        <!-- Should make sure we have unique tags -->
        <xsl:for-each select="$action_root//action/@tag">
            <xsl:sort/>
            <xsl:choose>
            <xsl:when test="$Includes//actiontemplate[@tag=current()]"/>
            <xsl:otherwise>
            <xsl:text>  "</xsl:text>
            <xsl:value-of select="current()"/>
            <xsl:text>")</xsl:text>
            <xsl:text>;;
</xsl:text>
            </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:if>
    <xsl:text>esac
    </xsl:text>
 </xsl:when>
 <xsl:otherwise/>
 </xsl:choose>
</xsl:template>

<xsl:template match="states"/>

<xsl:template match="state">
        <xsl:text>  "</xsl:text>
        <xsl:value-of select="name"/>
        <xsl:text>")</xsl:text>
        <xsl:apply-templates select="code"/>
        <xsl:text>;;
</xsl:text>
</xsl:template>

<xsl:template match="state_prolog">
<xsl:text> local context state line
           typeset -A opt_args
</xsl:text>
</xsl:template>

<xsl:template name="backslash-space">
<xsl:param name="text"/>
<xsl:param name="find_string"/>
<xsl:param name="replace_string"/>
<xsl:choose>
<xsl:when test="contains($text,$find_string)">
     <xsl:value-of select="concat(substring-before($text,$find_string),$replace_string)"/>
     <xsl:call-template name="backslash-space">
          <xsl:with-param name="text" select="substring-after($text,$find_string)"/>
          <xsl:with-param name="find_string" select="$find_string"/>
          <xsl:with-param name="replace_string" select="$replace_string"/>
     </xsl:call-template>
</xsl:when>
<xsl:otherwise>
     <xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>



<xsl:template match="subcommands">
    <xsl:text>

# subcommands
</xsl:text>
    <xsl:apply-templates select="*">
      <xsl:with-param name="prefix" select="@prefix"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="subcommand">
  <xsl:param name="prefix"/>

  <xsl:variable name="root" select="."/>
    <xsl:text>(( $+functions[</xsl:text><xsl:value-of select="$prefix"/><xsl:value-of select="$root/@name"/><xsl:text>] )) ||
</xsl:text><xsl:value-of select="$prefix"/><xsl:value-of select="$root/@name"/><xsl:text> () {
</xsl:text>
            <xsl:for-each select="*">
              <xsl:choose>
                <xsl:when test="name() = 'states'">
                  <xsl:if test="count(./*)">
                    <xsl:call-template name="Handle_States">
                       <xsl:with-param name="action_root" select="$root"/>
                       <xsl:with-param name="states" select="state"/>
                    </xsl:call-template>
                  </xsl:if>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:apply-templates select="." />
                </xsl:otherwise>
              </xsl:choose>
            </xsl:for-each>
<xsl:text>}

</xsl:text>
</xsl:template>

<xsl:template match="dispatch">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="code">
  <xsl:value-of select="text()"/>
</xsl:template>

<xsl:template match="subcommandlist">
  <xsl:choose>
    <xsl:when test="@style='list'">
      <xsl:for-each select="//subcommands/subcommand[not(@name = preceding::subcommand/@name)]">
            <xsl:value-of select="@name"/><xsl:text> </xsl:text>
      </xsl:for-each>

    </xsl:when>
    <xsl:otherwise>
        <xsl:message>Unknown &lt;subcommandlist&gt;/@style.</xsl:message>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<!-- Catch all to do nothin -->
<xsl:template match="*|@*|text()"/>

</xsl:stylesheet>