diff options
Diffstat (limited to 'mped.xml')
-rw-r--r-- | mped.xml | 160 |
1 files changed, 34 insertions, 126 deletions
@@ -140,7 +140,8 @@ <xsl:value-of select="@mped:tangle-to" /> <xsl:text>")
</xsl:text> - <xsl:text>cat >> </xsl:text> + <xsl:apply-templates select="." mode="source-code-formatter" /> + <xsl:text> > </xsl:text> <xsl:value-of select="@mped:tangle-to" /> <xsl:text> << "_MPED_EOF"
</xsl:text> @@ -152,139 +153,45 @@ </programlisting> <para> This template starts by creating the directory where the file - should go, then fills the file with the source code. For this to - work, we need to do two things about the text of the program - listing: remove the first empty lines and the last empty - lines of the content (but preserve indentation). + should go, then fills the file with the source code. XML has a + precise behavior when it comes to whitespace preservation, but + it’s not always the prettiest when we write it with whitespace + output in mind. So, the code output is frequently not indented + correctly, and has too many empty lines. To counter this + effect, we use a code source <emphasis>formatter</emphasis>, a + program that reads source code and indents it correctly. For + XSLT, we can use <command>xmllint</command> from + <application>libxml2</application>. The important thing about + the formatter is that it should take its input from standard + input and write the formatted code to standard output. </para> - <para> - Let us start with removing leading or trailing empty - lines. Removing leading empty lines seems easier. - </para> - <programlisting language="xml" - xml:id="mped-private-leading-empty-lines"> - <![CDATA[ -<xsl:template name="mped-private-leading-empty-lines"> - <xsl:param name="indentation" select="''" /> - <xsl:param name="text" select="." /> - <xsl:choose> - <xsl:when test="substring($text, 1, 1) = '
'"> - <xsl:call-template name="mped-private-leading-empty-lines"> - <xsl:with-param name="indentation" select="''" /> - <xsl:with-param name="text" - select="substring($text, 2)" /> - </xsl:call-template> - </xsl:when> - - <xsl:when test="( - substring($text, 1, 1) = ' ' - or substring($text, 1, 1) = '	' - or substring($text, 1, 1) = ' ')"> - <xsl:call-template name="mped-private-leading-empty-lines"> - <xsl:with-param name="indentation" - select="concat($indentation, substring($text, 1, 1))" /> - <xsl:with-param name="text" - select="substring($text, 2)" /> - </xsl:call-template> - </xsl:when> - - <xsl:otherwise> - <xsl:value-of select="$indentation" /> - <xsl:value-of select="$text" /> - </xsl:otherwise> - </xsl:choose> -</xsl:template> - ]]> - </programlisting> - <para> - There are three different cases. If the text starts with a - newline, discard the indentation that we carried and the - newline. If the text starts with whitespace, carry it and look - at the next character. Otherwise, the whitespace that we carried - is indentation, so print it, and print the text. - </para> - <para> - To avoid exposing the carried indentation, it is better to mark - this template as internal and wrap it in a new template. - </para> - <programlisting language="xml" xml:id="remove-leading-empty-lines"> + <programlisting language="xml" xml:id="formatter-for-xml"> <![CDATA[ -<xsl:template name="remove-leading-empty-lines"> - <xsl:param name="text" select="." /> - <xsl:call-template name="mped-private-leading-empty-lines"> - <xsl:with-param name="indentation" select="''" /> - <xsl:with-param name="text" select="$text" /> - </xsl:call-template> +<xsl:template match="docbook:programlisting[@language = 'xml']" + mode="source-code-formatter"> + <xsl:text>xmllint --format -</xsl:text> </xsl:template> ]]> </programlisting> <para> - To remove trailing empty lines, the solution is easier since - there is no indentation to keep around: just discard all the - trailing whitespace. + If no formatter applies, then we can resort to + <command>cat</command>. </para> - <programlisting language="xml" xml:id="remove-trailing-whitespace"> + <programlisting language="xml" xml:id="default-formatter"> <![CDATA[ -<xsl:template name="remove-trailing-whitespace"> - <xsl:param name="text" select="." /> - <xsl:choose> - <xsl:when test="$text = ''"> - <xsl:value-of select="$text" /> - </xsl:when> - <xsl:otherwise> - <xsl:variable name="last" select="substring($text, string-length ($text), 1)" /> - <xsl:variable name="before" select="substring($text, 1, string-length ($text) - 1)" /> - <xsl:choose> - <xsl:when test="$last = ' ' or $last = '	' - or $last = ' ' or $last = ' '"> - <xsl:call-template name="remove-trailing-whitespace"> - <xsl:with-param name="text" select="$before" /> - </xsl:call-template> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$text" /> - </xsl:otherwise> - </xsl:choose> - </xsl:otherwise> - </xsl:choose> +<xsl:template match="docbook:programlisting" + mode="source-code-formatter"> + <xsl:text>cat</xsl:text> </xsl:template> ]]> </programlisting> <para> - Using these templates, we can process the program listing code - in the “copy-source-code” mode: if there is only one text node, - then remove the leading emtpy lines and trailing - whitespace. Otherwise, remove the leading emtpy lines from the - first text node and the trailing whitespace from the last text - node. By “first” (respectively, “last”) text node, I mean the - text node that has no preceding (respectively, following) - siblings. Maybe there are no such text nodes. + We also need to specify how the source code is copied. </para> <programlisting language="xml" xml:id="copy-source-code-text"> <![CDATA[ -<xsl:template match="text()[position() = 1 and position() = last()]" - mode="copy-source-code"> - <xsl:call-template name="remove-trailing-whitespace"> - <xsl:with-param name="text"> - <xsl:call-template name="remove-leading-empty-lines"> - <xsl:with-param name="text" select="." /> - </xsl:call-template> - </xsl:with-param> - </xsl:call-template> -</xsl:template> - -<xsl:template match="text()[position() = 1 and position() != last()]" - mode="copy-source-code"> - <xsl:call-template name="remove-leading-empty-lines"> - <xsl:with-param name="text" select="." /> - </xsl:call-template> -</xsl:template> - -<xsl:template match="text()[position() > 1 and position() = last()]" - mode="copy-source-code"> - <xsl:call-template name="remove-trailing-whitespace"> - <xsl:with-param name="text" select="." /> - </xsl:call-template> +<xsl:template match="text()" mode="copy-source-code"> + <xsl:value-of select="." /> </xsl:template> ]]> </programlisting> @@ -340,10 +247,12 @@ <para> The collection of all these templates gives the following: </para> - <programlisting language="xml" xml:id="whole-tangling-stylesheet" - mped:tangle-to="tangle.xsl"> - <![CDATA[ -<?xml version="1.0"?> + <programlisting + language="xml" + xml:id="whole-tangling-stylesheet" + mped:tangle-to="tangle.xsl" + ><![CDATA[<?xml version="1.0"?> + <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mped="https://labo.planete-kraus.eu/mped.git" @@ -353,9 +262,8 @@ <xsl:strip-space elements="*" /> ]]> <mped:copy linkend="tangle-programlisting" /> - <mped:copy linkend="mped-private-leading-empty-lines" /> - <mped:copy linkend="remove-leading-empty-lines" /> - <mped:copy linkend="remove-trailing-whitespace" /> + <mped:copy linkend="formatter-for-xml" /> + <mped:copy linkend="default-formatter" /> <mped:copy linkend="copy-source-code-text" /> <mped:copy linkend="ignore-text-other-than-source" /> <mped:copy linkend="tangle-mped-copy" /> |