Discussion:
Recognising \end{macrocode}
(too old to reply)
Peter Flynn
2024-02-05 00:03:57 UTC
Permalink
I'm using doc and dox to document a package which includes some XSLT
code which generates a .dtx file, and therefore includes the strings
'% \begin{macrocode}' and '% \end{macrocode}' inside the code to
be documented, eg

% \begin{macrocode}
<xsl:text>% \begin{macrocode}&#xa;</xsl:text>
<xsl:if test="db:constraintdef[db:cmdsynopsis[db:command]]">
<xsl:for-each select="db:constraintdef/db:cmdsynopsis/db:command">
<xsl:value-of select="."/>
<xsl:text>&#xa;</xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text>% \end{macrocode}&#xa;</xsl:text>
% \end{macrocode}

Although the string '% \end{macrocode}' occurs *within* the line, and
not at the start of the line, it is still being recognised as the end of
! Misplaced alignment tab character &.
l.15885 ... <xsl:text>% \end{macrocode}&
#xa;</xsl:text>
I can't figure out why you would want to use a tab mark
Is there a way to configure doc/dox to recognise the end of the
environment only when the '% \end{macrocode}' occurs at the beginning
of a line?

Peter
Peter Flynn
2024-02-05 17:03:38 UTC
Permalink
Post by Peter Flynn
I'm using doc and dox to document a package which includes some XSLT
code which generates a .dtx file, and therefore includes the
strings '% \begin{macrocode}' and '% \end{macrocode}' inside
the code to be documented,
[...]
Post by Peter Flynn
Although the string '% \end{macrocode}' occurs *within* the line,
and not at the start of the line, it is still being recognised as the
I have managed to create a MWE for this.

------------------------------8<------------------------------
% \iffalse meta-comment
% A test
% \fi
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[2015/01/01]
%<package>\ProvidesPackage{test}[2023/12/30 v1.26
%<package> Test]
%<*driver>
\PassOptionsToPackage{svgnames}{xcolor}
\documentclass[11pt]{ltxdoc}
\usepackage{dox}%
\usepackage{fontspec}%
\usepackage{xcolor}%
\usepackage{hypdoc}%
\hypersetup{linkcolor=DarkGreen,citecolor=DarkRed,
urlcolor=Blue,colorlinks=true}
\usepackage{hyperref}%
\hypersetup{linkcolor=DarkGreen,citecolor=DarkRed,
urlcolor=Blue,colorlinks=true}
\hypersetup{pdfauthor={Peter Flynn},
pdftitle={The test LaTeX2e document package},
pdfsubject={Testing123},
pdfkeywords={latex,typesetting},
pdfproducer={XeLateX with hyperref},
pdfcreator={Emacs with psgml, ClassPack with Saxon, LaTeX from
TeX Live}}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}\raggedright
\DocInput{test.dtx}
\end{document}
%</driver>
% \fi
%
% \CheckSum{7}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
% Digits \0\1\2\3\4\5\6\7\8\9
% Exclamation \! Double quote \" Hash (number) \#
% Dollar \$ Percent \% Ampersand \&
% Acute accent \' Left paren \( Right paren \)
% Asterisk \* Plus \+ Comma \,
% Minus \- Point \. Solidus \/
% Colon \: Semicolon \; Less than \<
% Equals \= Greater than \> Question mark \?
% Commercial at \@ Left bracket \[ Backslash \\
% Right bracket \] Circumflex \^ Underscore \_
% Grave accent \` Left brace \{ Vertical bar \|
% Right brace \} Tilde \~}
%
% \GetFileInfo{test.dtx}
% \def\fileversion{1.26}
% \def\filedate{2023/12/30}
% \title{The \textsf{test} \LaTeXe\ package\thanks{%
% This document corresponds to \textsf{test}
% \textit{v.}\ \fileversion , dated \filedate.}
% \\[1em]\Large
% Testing dox/doc
% \\[1ex]\large
% on XSLT generating DTX}
% \author{Peter Flynn}
% \maketitle
% \renewcommand{\abstractname}{Summary}\thispagestyle{empty}
% \begin{abstract}
% Test
% \end{abstract}
% \clearpage
% \tableofcontents
% \clearpage
% \section{Test}
% Test
% \clearpage
% \StopEventually{\label{endcode}%
% \clearpage
% \addcontentsline{toc}{section}{Change History}%
% \label{changehistory}%
% \PrintChanges
% \clearpage
% \label{codeindex}%
% \addcontentsline{toc}{section}{Index}%
% \PrintIndex}
% \iffalse
%<*package>
% \fi
% \clearpage
% \section{The \textsf{test} macros}
% \iffalse
%</package>
% \fi
% \iffalse
%<*testscript>
% \fi
% \clearpage
% \section{The \emph{test.xsl} script}
% \setcounter{CodelineNo}{0}
% Now look: this normal usage works fine
% Identify the file origin, date, time, etc.\par
% \begin{macrocode}
<!-- The test.xsl script 24-02-04T21:01:06 -->
% \end{macrocode}
% Here we show the XSLT to handle a DocBook <sect1>
% IMPORTANT: it is supposed to generate the DTX code as-is
% between <xsl:text> and </xsl:text>
% \begin{macrocode}
<xsl:template match="db:sect1">
<!-- process sect1 content -->
<xsl:apply-templates/>
<xsl:if test="@xml:id='options'">
<xsl:text>% Now invoke the options.\par
% \iffalse
%% Now invoke the options.
% \fi
% \begin{macrocode}
\ExecuteOptions{</xsl:text>
<xsl:value-of
select="descendant::db:annotation/@xreflabel"/>
<xsl:text>}
\ProcessOptions\relax
% \end{macrocode}&#xa;</xsl:text>
</xsl:if>
<xsl:call-template name="checkpackages">
<xsl:with-param name="pos" select="'after'"/>
<xsl:with-param name="loc" select="."/>
</xsl:call-template>
</xsl:if>
</xsl:template>
% \end{macrocode}
% That's all, folks!
% \iffalse
%</db2dtxscript>
% \fi
% \Finale
------------------------------8<------------------------------

Cut that out into test.dtx and run through XeLaTeX.

Peter
Ulrich D i e z
2024-02-05 18:19:42 UTC
Permalink
Post by Peter Flynn
I have managed to create a MWE for this.
[...]
Post by Peter Flynn
Cut that out into test.dtx and run through XeLaTeX.
Does the following code do what you want?

Sincerely

Ulrich


% \iffalse meta-comment
% A test
% \fi
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[2015/01/01]
%<package>\ProvidesPackage{test}[2023/12/30 v1.26
%<package> Test]
%<*driver>
\PassOptionsToPackage{svgnames}{xcolor}
\documentclass[11pt]{ltxdoc}

\makeatletter
%=======================================================================
% \MyReplicate{<amount>}{<tokens>}
% After triggering two expansion-steps <tokens> are appended to the
% token stream <amount> times.
% E.g., \MyReplicate{10}{X} yields XXXXXXXXXX
%-----------------------------------------------------------------------
% Define a TeX-number-quantity of non-positive value
\@ifdefinable\MyStopromannumeral{\chardef\MyStopromannumeral=`\^^00}%
%-----------------------------------------------------------------------
% Define Paraphernalia:
\newcommand\Myfot[2]{#1}%
\newcommand\Mysot[2]{#2}%
\newcommand\Myexchg[2]{#2#1}%
%-----------------------------------------------------------------------
% Define the loop:
\newcommand\MyReplicate[2]{%
% #1 amount of replications
% #2 tokens to replicate
\romannumeral\expandafter\Myexchg
\expandafter{\romannumeral\number\number#1 000\relax}%
{\MyReplicateloop{#2}{}}%
}%
\newcommand\MyReplicateloop[3]{%
% #1 tokens to replicate
% #2 replications gathered so far
% #3 lowercase letter m or \relax
\ifx#3\relax\expandafter\Mysot\else\expandafter\Myfot\fi
{\MyReplicateloop{#1}{#2#1}}%
{\MyStopromannumeral#2}%
}%
%=======================================================================
% \NeutralizeOneUnstarredEndMacrocode replaces the delimiter
% % \end{macrocode} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeOneStarredEndMacrocode replaces the delimiter
% % \end{macrocode*} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
\begingroup
\catcode`\|=0
\catcode`\[=1
\catcode`\]=2
\catcode`\{=12
\catcode`\}=12
\catcode`\%=12
\catcode`\Y=14
\catcode`\\=\active
|def|NeutralizerDefiner#1#2#3#4[Y
|gdef#1##1%#2#2#2#2\end{macrocode#4}[##1%#2#2#2#2\end{#3acrocode#4}]Y
]Y
|catcode`|m =12Y
|catcode`| =|active
|@ifdefinable|NeutralizeOneUnstarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneUnstarredEndMacrocode][ ][m][]Y
]Y
|catcode`| =12Y
|@ifdefinable|NeutralizeOneStarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneStarredEndMacrocode][ ][m][*]Y
]Y
|endgroup
%=======================================================================
% \NeutralizeInstancesOfUnstarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeInstancesOfStarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode*} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
\newcommand\NeutralizeInstancesOfUnstarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneUnstarredEndMacrocode}%
}%
\newcommand\NeutralizeInstancesOfStarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneStarredEndMacrocode}%
}%
%=======================================================================
% Patch the environments macrocode and macrocode* of the package doc
% so that by redefining the macro \SkipMacrocodeEndings accordingly
% you can have these environments ignore as many instances of the
% ending phrase of the environment in question as denoted by
% \SkipMacrocodeEndings while scanning for the end of that environment.
\def\SkipMacrocodeEndings{0}%
\@namedef{macrocode*}{%
\***@code
\NeutralizeInstancesOfStarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\def\macrocode{%
\***@code
\frenchspacing\@vobeyspaces
\NeutralizeInstancesOfUnstarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\makeatother

\usepackage{dox}%
\usepackage{fontspec}%
\usepackage{xcolor}%
\usepackage{hypdoc}%
\hypersetup{linkcolor=DarkGreen,citecolor=DarkRed,
urlcolor=Blue,colorlinks=true}
\usepackage{hyperref}%
\hypersetup{linkcolor=DarkGreen,citecolor=DarkRed,
urlcolor=Blue,colorlinks=true}
\hypersetup{pdfauthor={Peter Flynn},
pdftitle={The test LaTeX2e document package},
pdfsubject={Testing123},
pdfkeywords={latex,typesetting},
pdfproducer={XeLateX with hyperref},
pdfcreator={Emacs with psgml, ClassPack with Saxon, LaTeX from TeX Live}}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}\raggedright
\DocInput{test.dtx}
\end{document}
%</driver>
% \fi
%
% \CheckSum{8}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
% Digits \0\1\2\3\4\5\6\7\8\9
% Exclamation \! Double quote \" Hash (number) \#
% Dollar \$ Percent \% Ampersand \&
% Acute accent \' Left paren \( Right paren \)
% Asterisk \* Plus \+ Comma \,
% Minus \- Point \. Solidus \/
% Colon \: Semicolon \; Less than \<
% Equals \= Greater than \> Question mark \?
% Commercial at \@ Left bracket \[ Backslash \\
% Right bracket \] Circumflex \^ Underscore \_
% Grave accent \` Left brace \{ Vertical bar \|
% Right brace \} Tilde \~}
%
% \GetFileInfo{test.dtx}
% \def\fileversion{1.26}
% \def\filedate{2023/12/30}
% \title{The \textsf{test} \LaTeXe\ package\thanks{%
% This document corresponds to \textsf{test}
% \textit{v.}\ \fileversion , dated \filedate.}
% \\[1em]\Large
% Testing dox/doc
% \\[1ex]\large
% on XSLT generating DTX}
% \author{Peter Flynn}
% \maketitle
% \renewcommand{\abstractname}{Summary}\thispagestyle{empty}
% \begin{abstract}
% Test
% \end{abstract}
% \clearpage
% \tableofcontents
% \clearpage
% \section{Test}
% Test
% \clearpage
% \StopEventually{\label{endcode}%
% \clearpage
% \addcontentsline{toc}{section}{Change History}%
% \label{changehistory}%
% \PrintChanges
% \clearpage
% \label{codeindex}%
% \addcontentsline{toc}{section}{Index}%
% \PrintIndex}
% \iffalse
%<*package>
% \fi
% \clearpage
% \section{The \textsf{test} macros}
% \iffalse
%</package>
% \fi
% \iffalse
%<*testscript>
% \fi
% \clearpage
% \section{The \emph{test.xsl} script}
% \setcounter{CodelineNo}{0}
% Now look: this normal usage works fine
% Identify the file origin, date, time, etc.\par
% \begin{macrocode}
<!-- The test.xsl script 24-02-04T21:01:06 -->
% \end{macrocode}
% Here we show the XSLT to handle a DocBook <sect1>
% IMPORTANT: it is supposed to generate the DTX code as-is
% between <xsl:text> and </xsl:text>
% \begingroup ^^A-----------------------------------------------
% \def\SkipMacrocodeEndings{1}%
% \begin{macrocode}
<xsl:template match="db:sect1">
<!-- process sect1 content -->
<xsl:apply-templates/>
<xsl:if test="@xml:id='options'">
<xsl:text>% Now invoke the options.\par
% \iffalse
%% Now invoke the options.
% \fi
% \begin{macrocode}
\ExecuteOptions{</xsl:text>
<xsl:value-of
select="descendant::db:annotation/@xreflabel"/>
<xsl:text>}
\ProcessOptions\relax
% \end{macrocode}&#xa;</xsl:text>
</xsl:if>
<xsl:call-template name="checkpackages">
<xsl:with-param name="pos" select="'after'"/>
<xsl:with-param name="loc" select="."/>
</xsl:call-template>
</xsl:if>
</xsl:template>
% \end{macrocode}
% \endgroup ^^A-------------------------------------------------
% That's all, folks!
% \iffalse
%</db2dtxscript>
% \fi
% \Finale
Ulrich D i e z
2024-02-05 19:23:17 UTC
Permalink
[I just realized that the code for macrocode* lacks \relax, so let's fix this:]
Post by Peter Flynn
I have managed to create a MWE for this.
[...]
Post by Peter Flynn
Cut that out into test.dtx and run through XeLaTeX.
Does the following code do what you want?

Sincerely

Ulrich


% \iffalse meta-comment
% A test
% \fi
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[2015/01/01]
%<package>\ProvidesPackage{test}[2023/12/30 v1.26
%<package> Test]
%<*driver>
\PassOptionsToPackage{svgnames}{xcolor}
\documentclass[11pt]{ltxdoc}

\makeatletter
%=======================================================================
% \MyReplicate{<amount>}{<tokens>}
% After triggering two expansion-steps <tokens> are appended to the
% token stream <amount> times.
% E.g., \MyReplicate{10}{X} yields XXXXXXXXXX
%-----------------------------------------------------------------------
% Define a TeX-number-quantity of non-positive value
\@ifdefinable\MyStopromannumeral{\chardef\MyStopromannumeral=`\^^00}%
%-----------------------------------------------------------------------
% Define Paraphernalia:
\newcommand\Myfot[2]{#1}%
\newcommand\Mysot[2]{#2}%
\newcommand\Myexchg[2]{#2#1}%
%-----------------------------------------------------------------------
% Define the loop:
\newcommand\MyReplicate[2]{%
% #1 amount of replications
% #2 tokens to replicate
\romannumeral\expandafter\Myexchg
\expandafter{\romannumeral\number\number#1 000\relax}%
{\MyReplicateloop{#2}{}}%
}%
\newcommand\MyReplicateloop[3]{%
% #1 tokens to replicate
% #2 replications gathered so far
% #3 lowercase letter m or \relax
\ifx#3\relax\expandafter\Mysot\else\expandafter\Myfot\fi
{\MyReplicateloop{#1}{#2#1}}%
{\MyStopromannumeral#2}%
}%
%=======================================================================
% \NeutralizeOneUnstarredEndMacrocode replaces the delimiter
% % \end{macrocode} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeOneStarredEndMacrocode replaces the delimiter
% % \end{macrocode*} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
\begingroup
\catcode`\|=0
\catcode`\[=1
\catcode`\]=2
\catcode`\{=12
\catcode`\}=12
\catcode`\%=12
\catcode`\Y=14
\catcode`\\=\active
|def|NeutralizerDefiner#1#2#3#4[Y
|gdef#1##1%#2#2#2#2\end{macrocode#4}[##1%#2#2#2#2\end{#3acrocode#4}]Y
]Y
|catcode`|m =12|relaxY
|catcode`| =|activeY
|@ifdefinable|NeutralizeOneUnstarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneUnstarredEndMacrocode][ ][m][]Y
]Y
|catcode`| =12|relaxY
|@ifdefinable|NeutralizeOneStarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneStarredEndMacrocode][ ][m][*]Y
]Y
|endgroup
%=======================================================================
% \NeutralizeInstancesOfUnstarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeInstancesOfStarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode*} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
\newcommand\NeutralizeInstancesOfUnstarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneUnstarredEndMacrocode}%
}%
\newcommand\NeutralizeInstancesOfStarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneStarredEndMacrocode}%
}%
%=======================================================================
% Patch the environments macrocode and macrocode* of the package doc
% so that by redefining the macro \SkipMacrocodeEndings accordingly
% you can have these environments ignore as many instances of the
% ending phrase of the environment in question as denoted by
% \SkipMacrocodeEndings while scanning for the end of that environment.
\def\SkipMacrocodeEndings{0}%
\@namedef{macrocode*}{%
\***@code
\NeutralizeInstancesOfStarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\def\macrocode{%
\***@code
\frenchspacing\@vobeyspaces
\NeutralizeInstancesOfUnstarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\makeatother

\usepackage{dox}%
\usepackage{fontspec}%
\usepackage{xcolor}%
\usepackage{hypdoc}%
\hypersetup{linkcolor=DarkGreen,citecolor=DarkRed,
urlcolor=Blue,colorlinks=true}
\usepackage{hyperref}%
\hypersetup{linkcolor=DarkGreen,citecolor=DarkRed,
urlcolor=Blue,colorlinks=true}
\hypersetup{pdfauthor={Peter Flynn},
pdftitle={The test LaTeX2e document package},
pdfsubject={Testing123},
pdfkeywords={latex,typesetting},
pdfproducer={XeLateX with hyperref},
pdfcreator={Emacs with psgml, ClassPack with Saxon, LaTeX from TeX Live}}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}\raggedright
\DocInput{test.dtx}
\end{document}
%</driver>
% \fi
%
% \CheckSum{8}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
% Digits \0\1\2\3\4\5\6\7\8\9
% Exclamation \! Double quote \" Hash (number) \#
% Dollar \$ Percent \% Ampersand \&
% Acute accent \' Left paren \( Right paren \)
% Asterisk \* Plus \+ Comma \,
% Minus \- Point \. Solidus \/
% Colon \: Semicolon \; Less than \<
% Equals \= Greater than \> Question mark \?
% Commercial at \@ Left bracket \[ Backslash \\
% Right bracket \] Circumflex \^ Underscore \_
% Grave accent \` Left brace \{ Vertical bar \|
% Right brace \} Tilde \~}
%
% \GetFileInfo{test.dtx}
% \def\fileversion{1.26}
% \def\filedate{2023/12/30}
% \title{The \textsf{test} \LaTeXe\ package\thanks{%
% This document corresponds to \textsf{test}
% \textit{v.}\ \fileversion , dated \filedate.}
% \\[1em]\Large
% Testing dox/doc
% \\[1ex]\large
% on XSLT generating DTX}
% \author{Peter Flynn}
% \maketitle
% \renewcommand{\abstractname}{Summary}\thispagestyle{empty}
% \begin{abstract}
% Test
% \end{abstract}
% \clearpage
% \tableofcontents
% \clearpage
% \section{Test}
% Test
% \clearpage
% \StopEventually{\label{endcode}%
% \clearpage
% \addcontentsline{toc}{section}{Change History}%
% \label{changehistory}%
% \PrintChanges
% \clearpage
% \label{codeindex}%
% \addcontentsline{toc}{section}{Index}%
% \PrintIndex}
% \iffalse
%<*package>
% \fi
% \clearpage
% \section{The \textsf{test} macros}
% \iffalse
%</package>
% \fi
% \iffalse
%<*testscript>
% \fi
% \clearpage
% \section{The \emph{test.xsl} script}
% \setcounter{CodelineNo}{0}
% Now look: this normal usage works fine
% Identify the file origin, date, time, etc.\par
% \begin{macrocode}
<!-- The test.xsl script 24-02-04T21:01:06 -->
% \end{macrocode}
% Here we show the XSLT to handle a DocBook <sect1>
% IMPORTANT: it is supposed to generate the DTX code as-is
% between <xsl:text> and </xsl:text>
% \begingroup ^^A-----------------------------------------------
% \def\SkipMacrocodeEndings{1}%
% \begin{macrocode}
<xsl:template match="db:sect1">
<!-- process sect1 content -->
<xsl:apply-templates/>
<xsl:if test="@xml:id='options'">
<xsl:text>% Now invoke the options.\par
% \iffalse
%% Now invoke the options.
% \fi
% \begin{macrocode}
\ExecuteOptions{</xsl:text>
<xsl:value-of
select="descendant::db:annotation/@xreflabel"/>
<xsl:text>}
\ProcessOptions\relax
% \end{macrocode}&#xa;</xsl:text>
</xsl:if>
<xsl:call-template name="checkpackages">
<xsl:with-param name="pos" select="'after'"/>
<xsl:with-param name="loc" select="."/>
</xsl:call-template>
</xsl:if>
</xsl:template>
% \end{macrocode}
% \endgroup ^^A-------------------------------------------------
% That's all, folks!
% \iffalse
%</db2dtxscript>
% \fi
% \Finale
Ulrich D i e z
2024-02-05 17:55:02 UTC
Permalink
I'm using doc and dox to document a package which includes some XSLT code which generates a .dtx file, and therefore includes the strings
'%    \begin{macrocode}' and '%    \end{macrocode}' inside the code to be documented, eg
%    \begin{macrocode}
  <xsl:text>%    \begin{macrocode}&#xa;</xsl:text>
   <xsl:if test="db:constraintdef[db:cmdsynopsis[db:command]]">
    <xsl:for-each select="db:constraintdef/db:cmdsynopsis/db:command">
      <xsl:value-of select="."/>
      <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
  </xsl:if>
  <xsl:text>%    \end{macrocode}&#xa;</xsl:text>
%    \end{macrocode}
! Misplaced alignment tab character &.
l.15885 ...    <xsl:text>%    \end{macrocode}&
                                                  #xa;</xsl:text>
I can't figure out why you would want to use a tab mark
Is there a way to configure doc/dox to recognise the end of the environment only when the '%    \end{macrocode}' occurs at the beginning of a line?
I don't know dox.

As far as I know, the package doc does not provide facilities for
configuring such behavior.

How about patching the environments macrocode and macrocode* of the
package doc so that you can specify the amount of ending-phrases
of these environments that should be ignored when scanning for the end
of an instance of such an environment.

However, patching these environments is a crucial action as with the
development of the package doc the internals of these environments
may be subject to change so that patching needs to be adapted to those
changes.

I assume that the doc package version number v3.0m dated 2022/11/13
is in use (currently - February 5, 2024 - the most recent one) and
wrote a patch so that by (re)defining the macro \SkipMacrocodeEndings
accordingly you can have these environments ignore as many instances
of the ending phrase of the environment in question as denoted by
\SkipMacrocodeEndings while scanning for the end of that environment.

Internally this is done by scanning for delimiters
% \end{macrocode}
respective
% \end{macrocode*}
(tokenized in verbatim catciode-régime with categories of
spaces and backslashes as determined by the environments)
and replacing m of category 11(letter) by m of category 12(other)
so that the delimiter-matching of the mechanism that scans for the
end of the environment won't match.

With this patch you can do things like

% \begingroup
% \def\SkipMacrocodeEndings{3}
% \begin{macrocode}
something
% \end{macrocode} % 1st ending phrase not considered the end.
% \end{macrocode} % 2nd ending phrase not considered the end.
% \end{macrocode} % 3rd ending phrase not considered the end.
% \end{macrocode} % this ending-phrase is considered the end.
% \endgroup

I **think** this patch does not interfere with the indexing-
and glossary-machineries of the package doc, but be picky anyway
when checking whether the output is as desired.



-----[Snip]-Begin of file mytest.tex------------------------------------
%\errorcontextlines=10000

% Let's create a file myfile.dtx:
\begin{filecontents*}{myfile.dtx}
% \begingroup
% \def\SkipMacrocodeEndings{1}%
% \begin{macrocode}
<xsl:text>% \begin{macrocode}&#xa;</xsl:text>
<xsl:if test="db:constraintdef[db:cmdsynopsis[db:command]]">
<xsl:for-each select="db:constraintdef/db:cmdsynopsis/db:command">
<xsl:value-of select="."/>
<xsl:text>&#xa;</xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text>% \end{macrocode}&#xa;</xsl:text>
% \end{macrocode}
% \endgroup
\end{filecontents*}

\documentclass[a4paper]{article}
\usepackage{doc}

\makeatletter
%=======================================================================
% \MyReplicate{<amount>}{<tokens>}
% After triggering two expansion-steps <tokens> are appended to the
% token stream <amount> times.
% E.g., \MyReplicate{10}{X} yields XXXXXXXXXX
%-----------------------------------------------------------------------
% Define a TeX-number-quantity of non-positive value
\@ifdefinable\MyStopromannumeral{\chardef\MyStopromannumeral=`\^^00}%
%-----------------------------------------------------------------------
% Define Paraphernalia:
\newcommand\Myfot[2]{#1}%
\newcommand\Mysot[2]{#2}%
\newcommand\Myexchg[2]{#2#1}%
%-----------------------------------------------------------------------
% Define the loop:
\newcommand\MyReplicate[2]{%
% #1 amount of replications
% #2 tokens to replicate
\romannumeral\expandafter\Myexchg
\expandafter{\romannumeral\number\number#1 000\relax}%
{\MyReplicateloop{#2}{}}%
}%
\newcommand\MyReplicateloop[3]{%
% #1 tokens to replicate
% #2 replications gathered so far
% #3 lowercase letter m or \relax
\ifx#3\relax\expandafter\Mysot\else\expandafter\Myfot\fi
{\MyReplicateloop{#1}{#2#1}}%
{\MyStopromannumeral#2}%
}%
%=======================================================================
% \NeutralizeOneUnstarredEndMacrocode replaces the delimiter
% % \end{macrocode} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeOneStarredEndMacrocode replaces the delimiter
% % \end{macrocode*} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
\begingroup
\catcode`\|=0
\catcode`\[=1
\catcode`\]=2
\catcode`\{=12
\catcode`\}=12
\catcode`\%=12
\catcode`\Y=14
\catcode`\\=\active
|def|NeutralizerDefiner#1#2#3#4[Y
|gdef#1##1%#2#2#2#2\end{macrocode#4}[##1%#2#2#2#2\end{#3acrocode#4}]Y
]Y
|catcode`|m =12Y
|catcode`| =|active
|@ifdefinable|NeutralizeOneUnstarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneUnstarredEndMacrocode][ ][m][]Y
]Y
|catcode`| =12Y
|@ifdefinable|NeutralizeOneStarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneStarredEndMacrocode][ ][m][*]Y
]Y
|endgroup
%=======================================================================
% \NeutralizeInstancesOfUnstarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeInstancesOfStarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode*} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
\newcommand\NeutralizeInstancesOfUnstarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneUnstarredEndMacrocode}%
}%
\newcommand\NeutralizeInstancesOfStarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneStarredEndMacrocode}%
}%
%=======================================================================
% Patch the environments macrocode and macrocode* of the package doc
% so that by redefining the macro \SkipMacrocodeEndings accordingly
% you can have these environments ignore as many instances of the
% ending phrase of the environment in question as denoted by
% \SkipMacrocodeEndings while scanning for the end of that environment.
\def\SkipMacrocodeEndings{0}%
\@namedef{macrocode*}{%
\***@code
\NeutralizeInstancesOfStarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\def\macrocode{%
\***@code
\frenchspacing\@vobeyspaces
\NeutralizeInstancesOfUnstarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\makeatother

\EnableCrossrefs
\CodelineIndex

\begin{document}

\DocInput{myfile.dtx}

% Index: makeindex -s gind.ist -o mytest.ind mytest.idx
% Change-history: makeindex -s gglo.ist -o mytest.gls mytest.glo
\PrintIndex

\end{document}
-----[Snap]-End of file mytest.tex--------------------------------------


Here you can see an image of the output I get on my system
when compiling the example above:
<Loading Image...>

Sincerely

Ulrich
Peter Flynn
2024-02-16 09:43:53 UTC
Permalink
[...]
Post by Ulrich D i e z
Is there a way to configure doc/dox to recognise the end of the environment only when the '%    \end{macrocode}' occurs at the beginning of a line?
I don't know dox.
As far as I know, the package doc does not provide facilities for
configuring such behavior.
How about patching the environments macrocode and macrocode* of the
package doc so that you can specify the amount of ending-phrases of
these environments that should be ignored when scanning for the end
of an instance of such an environment.
Thank you for the code, very useful and interesting. In fact there is
another solution, and that's to change the XSLT code so that it outputs
percent and four spaces in one xsl:text, and '{macrocode}' in another.
The result is the same, but it means there is no chance of the code
being misinterpreted.

Peter
"When in doubt, change the data"

Ulrich D i e z
2024-02-05 19:19:45 UTC
Permalink
[I just realized that the code for macrocode* lacks \relax, so let's fix this:]
I'm using doc and dox to document a package which includes some XSLT code which generates a .dtx file, and therefore includes the strings
'% \begin{macrocode}' and '% \end{macrocode}' inside the code to be documented, eg
% \begin{macrocode}
<xsl:text>% \begin{macrocode}&#xa;</xsl:text>
<xsl:if test="db:constraintdef[db:cmdsynopsis[db:command]]">
<xsl:for-each select="db:constraintdef/db:cmdsynopsis/db:command">
<xsl:value-of select="."/>
<xsl:text>&#xa;</xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text>% \end{macrocode}&#xa;</xsl:text>
% \end{macrocode}
! Misplaced alignment tab character &.
l.15885 ... <xsl:text>% \end{macrocode}&
#xa;</xsl:text>
I can't figure out why you would want to use a tab mark
Is there a way to configure doc/dox to recognise the end of the environment only when the '% \end{macrocode}' occurs at the beginning of a line?
I don't know dox.

As far as I know, the package doc does not provide facilities for
configuring such behavior.

How about patching the environments macrocode and macrocode* of the
package doc so that you can specify the amount of ending-phrases
of these environments that should be ignored when scanning for the end
of an instance of such an environment.

However, patching these environments is a crucial action as with the
development of the package doc the internals of these environments
may be subject to change so that patching needs to be adapted to those
changes.

I assume that the doc package version number v3.0m dated 2022/11/13
is in use (currently - February 5, 2024 - the most recent one) and
wrote a patch so that by (re)defining the macro \SkipMacrocodeEndings
accordingly you can have these environments ignore as many instances
of the ending phrase of the environment in question as denoted by
\SkipMacrocodeEndings while scanning for the end of that environment.

Internally this is done by scanning for delimiters
% \end{macrocode}
respective
% \end{macrocode*}
(tokenized in verbatim catciode-régime with categories of
spaces and backslashes as determined by the environments)
and replacing m of category 11(letter) by m of category 12(other)
so that the delimiter-matching of the mechanism that scans for the
end of the environment won't match.

With this patch you can do things like

% \begingroup
% \def\SkipMacrocodeEndings{3}
% \begin{macrocode}
something
% \end{macrocode} % 1st ending phrase not considered the end.
% \end{macrocode} % 2nd ending phrase not considered the end.
% \end{macrocode} % 3rd ending phrase not considered the end.
% \end{macrocode} % this ending-phrase is considered the end.
% \endgroup

I **think** this patch does not interfere with the indexing-
and glossary-machineries of the package doc, but be picky anyway
when checking whether the output is as desired.



-----[Snip]-Begin of file mytest.tex------------------------------------
%\errorcontextlines=10000

% Let's create a file myfile.dtx:
\begin{filecontents*}{myfile.dtx}
% \begingroup
% \def\SkipMacrocodeEndings{1}%
% \begin{macrocode}
<xsl:text>% \begin{macrocode}&#xa;</xsl:text>
<xsl:if test="db:constraintdef[db:cmdsynopsis[db:command]]">
<xsl:for-each select="db:constraintdef/db:cmdsynopsis/db:command">
<xsl:value-of select="."/>
<xsl:text>&#xa;</xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text>% \end{macrocode}&#xa;</xsl:text>
% \end{macrocode}
% \endgroup
\end{filecontents*}

\documentclass[a4paper]{article}
\usepackage{doc}

\makeatletter
%=======================================================================
% \MyReplicate{<amount>}{<tokens>}
% After triggering two expansion-steps <tokens> are appended to the
% token stream <amount> times.
% E.g., \MyReplicate{10}{X} yields XXXXXXXXXX
%-----------------------------------------------------------------------
% Define a TeX-number-quantity of non-positive value
\@ifdefinable\MyStopromannumeral{\chardef\MyStopromannumeral=`\^^00}%
%-----------------------------------------------------------------------
% Define Paraphernalia:
\newcommand\Myfot[2]{#1}%
\newcommand\Mysot[2]{#2}%
\newcommand\Myexchg[2]{#2#1}%
%-----------------------------------------------------------------------
% Define the loop:
\newcommand\MyReplicate[2]{%
% #1 amount of replications
% #2 tokens to replicate
\romannumeral\expandafter\Myexchg
\expandafter{\romannumeral\number\number#1 000\relax}%
{\MyReplicateloop{#2}{}}%
}%
\newcommand\MyReplicateloop[3]{%
% #1 tokens to replicate
% #2 replications gathered so far
% #3 lowercase letter m or \relax
\ifx#3\relax\expandafter\Mysot\else\expandafter\Myfot\fi
{\MyReplicateloop{#1}{#2#1}}%
{\MyStopromannumeral#2}%
}%
%=======================================================================
% \NeutralizeOneUnstarredEndMacrocode replaces the delimiter
% % \end{macrocode} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeOneStarredEndMacrocode replaces the delimiter
% % \end{macrocode*} by the same but with m of catcode 11 replaced
% by m of catcode 12.
%-----------------------------------------------------------------------
\begingroup
\catcode`\|=0
\catcode`\[=1
\catcode`\]=2
\catcode`\{=12
\catcode`\}=12
\catcode`\%=12
\catcode`\Y=14
\catcode`\\=\active
|def|NeutralizerDefiner#1#2#3#4[Y
|gdef#1##1%#2#2#2#2\end{macrocode#4}[##1%#2#2#2#2\end{#3acrocode#4}]Y
]Y
|catcode`|m =12|relaxY
|catcode`| =|activeY
|@ifdefinable|NeutralizeOneUnstarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneUnstarredEndMacrocode][ ][m][]Y
]Y
|catcode`| =12|relaxY
|@ifdefinable|NeutralizeOneStarredEndMacrocode[Y
|NeutralizerDefiner[|NeutralizeOneStarredEndMacrocode][ ][m][*]Y
]Y
|endgroup
%=======================================================================
% \NeutralizeInstancesOfUnstarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
% \NeutralizeInstancesOfStarredEndMacrocode{<amount>} replaces
% <amount> instances of the delimiter % \end{macrocode*} by the same
% but with m of catcode 11 replaced by m of catcode 12.
%-----------------------------------------------------------------------
\newcommand\NeutralizeInstancesOfUnstarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneUnstarredEndMacrocode}%
}%
\newcommand\NeutralizeInstancesOfStarredEndMacrocode[1]{%
\MyReplicate{#1}{\NeutralizeOneStarredEndMacrocode}%
}%
%=======================================================================
% Patch the environments macrocode and macrocode* of the package doc
% so that by redefining the macro \SkipMacrocodeEndings accordingly
% you can have these environments ignore as many instances of the
% ending phrase of the environment in question as denoted by
% \SkipMacrocodeEndings while scanning for the end of that environment.
\def\SkipMacrocodeEndings{0}%
\@namedef{macrocode*}{%
\***@code
\NeutralizeInstancesOfStarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\def\macrocode{%
\***@code
\frenchspacing\@vobeyspaces
\NeutralizeInstancesOfUnstarredEndMacrocode\SkipMacrocodeEndings
\***@code
}%
\makeatother

\EnableCrossrefs
\CodelineIndex

\begin{document}

\DocInput{myfile.dtx}

% Index: makeindex -s gind.ist -o mytest.ind mytest.idx
% Change-history: makeindex -s gglo.ist -o mytest.gls mytest.glo
\PrintIndex

\end{document}
-----[Snap]-End of file mytest.tex--------------------------------------


Here you can see an image of the output I get on my system
when compiling the example above:
<https://i.stack.imgur.com/azQEv.png>

Sincerely

Ulrich
Loading...