diff options
author | Vivien Kraus <vivien@planete-kraus.eu> | 2022-10-06 21:02:35 +0200 |
---|---|---|
committer | Vivien Kraus <vivien@planete-kraus.eu> | 2022-10-06 21:15:20 +0200 |
commit | 95c3c983e87d5ee1fb02848f1315cb65a7c6fa0c (patch) | |
tree | 616e4386e8755f206da7e6c983364e6f73f5f02d | |
parent | fe08dcdb9220bf5b8b42ea503637e20ddbb818eb (diff) |
Use a formatter instead of trying to strip space.
-rw-r--r-- | mped.xml | 160 | ||||
-rw-r--r-- | tangle-bootstrap.xsl | 76 |
2 files changed, 42 insertions, 194 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" /> diff --git a/tangle-bootstrap.xsl b/tangle-bootstrap.xsl index ffe19f5..baa9669 100644 --- a/tangle-bootstrap.xsl +++ b/tangle-bootstrap.xsl @@ -7,7 +7,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> @@ -16,75 +17,14 @@ _MPED_EOF </xsl:text> </xsl:template> - <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 match="docbook:programlisting[@language = 'xml']" mode="source-code-formatter"> + <xsl:text>xmllint --format -</xsl:text> </xsl:template> - <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" mode="source-code-formatter"> + <xsl:text>cat</xsl:text> </xsl:template> - <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> - <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> <xsl:template match="text()"/> <xsl:template match="mped:copy" mode="copy-source-code"> |