% \iffalse
%% File: l3doc.dtx Copyright (C) 1990-2009 LaTeX3 project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the ``expl3 bundle'' (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%<*driver>
\def\nameofplainTeX{plain}
\ifx\fmtname\nameofplainTeX\else
  \expandafter\begingroup
\fi
\input docstrip.tex
\askforoverwritefalse
\preamble


EXPERIMENTAL CODE

Do not distribute this file without also distributing the
source files specified above.

Do not distribute a modified version of this file.


\endpreamble
% stop docstrip adding \endinput
\postamble
\endpostamble
\generate{\file{l3doc.cls}{\from{l3doc.dtx}{class}}}
\generate{\file{l3doc.ist}{\from{l3doc.dtx}{docist}}}
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</driver>
%
%<*driver|class>
\RequirePackage{l3names}
%</driver|class>
%
% Need to protect the file metadata for any modules that load l3doc.
% This is restored after "\ProvideExplClass" below.
%    \begin{macrocode}
%<class>\let        \filenameOld        \filename
%<class>\let     \filenameextOld     \filenameext
%<class>\let        \filedateOld        \filedate
%<class>\let     \fileversionOld     \fileversion
%<class>\let \filedescriptionOld \filedescription
%    \end{macrocode}
%
%<*driver|class>
\GetIdInfo$Id: l3doc.dtx 2180 2011-03-06 10:38:35Z will $
          {L3 Experimental documentation class}
%</driver|class>
%
%<*driver>
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
\documentclass{l3doc}
\begin{document}
\DocInput{l3doc.dtx}
\end{document}
%</driver>
%
% This isn't included in the typeset documentation because it's a bit ugly:
%<*class>
\ProvidesExplClass
  {\filename}{\filedate}{\fileversion}{\filedescription}
\RequirePackage{expl3,xparse}
\let        \filename        \filenameOld
\let     \filenameext     \filenameextOld
\let        \filedate        \filedateOld
\let     \fileversion     \fileversionOld
\let \filedescription \filedescriptionOld
%</class>
% \fi
%
% \title{The \pkg{l3doc} class\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}}
% \author{\Team}
% \date{\filedate}
% \maketitle
% \tableofcontents
%
% \begin{documentation}
%
% \section{Introduction}
%
% This is an ad-hoc class for documenting the \pkg{expl3} bundle,
% a collection of modules or packages that make up \LaTeX3's programming
% environment. Eventually it will replace the "ltxdoc" class for \LaTeX3,
% but not before the good ideas in \pkg{hypdoc}, \cls{xdoc2}, \pkg{docmfp}, and
% \cls{gmdoc} are incorporated.
%
% \textbf{It is even less stable than the main \pkg{expl3} packages. Use at own risk!}
%
% It is written as a `self-contained' docstrip file: executing
% "latex l3doc.dtx"
% will generate the "l3doc.cls" file and typeset this
% documentation; execute "tex l3doc.dtx" to only generate the ".cls" file.
%
% \section{Features of other packages}
%
% This class builds on the \pkg{ltxdoc} class and the \pkg{doc} package, but
% in the time since they were originally written some
% improvements and replacements have appeared that we would like to use as
% inspiration.
%
% These packages or classes are \pkg{hypdoc}, \pkg{docmfp}, \pkg{gmdoc},
% and \pkg{xdoc}. I have summarised them below in order to work out what
% sort of features we should aim at a minimum for \pkg{l3doc}.
%
% \subsection{The \pkg{hypdoc} package}
%
% This package provides hyperlink support for the \pkg{doc} package. I have
% included it in this list to remind me that cross-referencing between
% documentation and implementation of methods is not very good. (E.g., it
% would be nice to be able to automatically hyperlink the documentation for
% a function from its implementation and vice-versa.)
%
% \subsection{The \pkg{docmfp} package}
%
% \begin{itemize}
% \item Provides "\DescribeRoutine" and the "routine" environment (etc.)
%       for  MetaFont and MetaPost code.
% \item Provides "\DescribeVariable" and the "variable" environment (etc.)
%       for more general code.
% \item Provides "\Describe" and the "Code" environment (etc.) as a
%       generalisation of the above two instantiations.
% \item Small tweaks to the DocStrip system to aid non-\LaTeX\ use.
% \end{itemize}
%
% \subsection{The \pkg{xdoc2} package}
%
% \begin{itemize}
% \item Two-sided printing.
% \item "\NewMacroEnvironment", "\NewDescribeEnvironment"; similar idea
%       to \pkg{docmfp} but more comprehensive.
% \item Tons of small improvements.
% \end{itemize}
%
% \subsection{The \pkg{gmdoc} package}
%
% Radical re-implementation of \pkg{doc} as a package or class.
% \begin{itemize}
% \item Requires no "\begin{macrocode}" blocks!
% \item Automatically inserts "\begin{macro}" blocks!
% \item And a whole bunch of other little things.
% \end{itemize}
%
% \section{Problems \& Todo}
%
% Problems at the moment: (1)~not flexible in the types of things that can be documented; (2)~very nonstandard markup (e.g., the odd `"/ (...)"' tags; (3)~no obvious link between the "\begin{function}" environment for documenting things to the "\begin{macro}" function that's used analogously in the implementation.
%
% The "macro" should probably be renamed to "function" when it is used within
% an implementation section. But they should have the same syntax before that happens!
%
% Furthermore, we need another `layer' of documentation commands to
% account for `user-macro' as opposed to `code-functions'; the \pkg{expl3}
% functions should be documented differently, probably, to the \pkg{xparse}
% user macros (at least in terms of indexing).
%
% In no particular order, a list of things to do:
% \begin{itemize}
% \item Rename \env{function}/\env{macro} environments to better describe
%       their use.
% \item Generalise \env{function}/\env{macro} for documenting `other things',
%       such as environment names, package options, even keyval options.
% \item Use \pkg{xparse}.
% \item New function like "\part" but for files (remove awkward `File' as "\partname").
% \item Something better to replace "\StopEventually"; I'm thinking two
%       environments \env{documentation} and \env{implementation} that can
%       conditionally typeset/ignore their material.
%       (This has been implemented but needs further consideration.)
% \item Hyperlink documentation and implementation of macros (see
%       the \textsc{dtx} file of \pkg{svn-multi} v2 as an example).
% \end{itemize}
%
% \section{Bugs}
%
% \begin{itemize}
% \item Spaces are ignored entirely within \env{function} and \env{macro}
%       arguments. This is just waiting for a convenient space-trimming
%       macro in \pkg{expl3}.
% \end{itemize}
%
% \section{Documentation}
%
% \subsection{Configuration}
%
% Before class options are processed, \pkg{l3doc} loads a configuration
% file "l3doc.cfg" if it exists, allowing you to customise the behaviour of
% the class without having to change the documentation source files.
%
% For example, to produce documentation on letter-sized paper instead of the
% default A4 size, create |l3doc.cfg| and include the line
% \begin{verbatim}
% \PassOptionsToClass{letterpaper}{l3doc}
% \end{verbatim}
%
% By default, \pkg{l3doc} selects the |T1| font encoding and loads the
% Latin Modern fonts.
% To prevent this, use the class option |cm-default|.
%
% \subsection{Partitioning documentation and implementation}
%
% \pkg{doc} uses the "\OnlyDocumentation"/"\AlsoImplementation" macros
% to guide the use of "\StopEventually{}", which is intended to be placed
% to partition the documentation and implementation within a single DTX file.
% 
% This isn't very flexible, since it assumes that we \emph{always} want
% to print the documentation. For the \pkg{expl3} sources, I wanted to be
% be able to input DTX files in two modes: only displaying the documentation,
% and only displaying the implementation. For example:
%
% \begin{verbatim}
% \DisableImplementation
% \DocInput{l3basics,l3prg,...}
% \EnableImplementation
% \DisableDocumentation
% \DocInputAgain
% \end{verbatim}
%
% The idea being that the entire \pkg{expl3} bundle can be documented,
% with the implementation included at the back. Now, this isn't perfect,
% but it's a start.
%
% Use "\begin{documentation}...\end{documentation}" around the documentation,
% and "\begin{implementation}...\end{implementation}" around the implementation.
% The "\EnableDocumentation"/"\EnableImplementation" will cause them to be typeset
% when the DTX file is "\DocInput"; use "\DisableDocumentation"/"\DisableImplementation"
% to omit the contents of those environments.
%
% Note that \cmd\DocInput\ now takes comma-separated arguments, and \cmd\DocInputAgain\
% can be used to re-input all DTX files previously input in this way.
%
% \subsection{Describing functions in the documentation}
%
% \DescribeEnv{function}
% \DescribeEnv{syntax}
% Two heavily-used environments are defined to describe the syntax
% of \textsf{expl3} functions and variables.
% \begin{verbatim}
% \begin{function}{ list_of , functions }
%   \begin{syntax}
%     "\foo_bar:" \Arg{meta} <test1>
%   \end{syntax}
% <description>
% \end{function}
% \end{verbatim}
%
% \begin{function}{ list_of , functions }
%   \begin{syntax}
%     "\foo_bar:" \Arg{meta} <test1>
%   \end{syntax}
% <description>
% \end{function}
%
% Functions may be suffixed by an optional flag or two to indicate whether it is
% expandable or defined in conditional forms. Use "/" to separate the function name
% from the flag(s) and then add any of "(EXP)", "(TF)", or "(pTF)" for this.
% Note that "(pTF)" implies "(EXP)" since predicates must always be expandable.
%
% Note that the list of functions used to use "|" as a separator instead, and this syntax is still supported.
%
% \DescribeEnv{function}
% If you are documenting a variable instead of a function, use the "variable" environment instead; it behaves identically to the "function" environment above.
%
% \subsection{Describing functions in the implementation}
%
% \DescribeEnv{macro}
% The well-used environment from \LaTeXe\ for marking up the implementation
% of macros/functions remains the \env{macro} environment.
% One change in \pkg{l3doc}: it now accepts comma-separated lists
% of functions, to avoid a very large number of consecutive "\end{macro}"
% statements.
% \begin{verbatim}
% % \begin{macro}{\foo:N,\foo:c}
% %   \begin{macrocode}
% ... code for \foo:N and \foo:c ...
% %   \end{macrocode}
% % \end{macro}
% \end{verbatim}
% If you are documenting an auxiliary macro, it's generally not necessary
% to highlight it as much and you also don't need to check it for, say,
% having a test function and having a documentation chunk earlier in a "function"
% environment. In this case, write "\begin[aux]{macro}" and it will be
% marked as such; its margin call-out will be printed in grey.
%
% For documenting \pkg{expl3}-type conditionals, you may also pass this
% environment a "TF" option (and omit it from the function name) to denote that
% the function is provided with "T", "F", and "TF" suffixes.
% A similar "pTF" option will print both "TF" and "_p" predicate forms.
%
% \DescribeMacro{\testfile}
% Within a "macro" environment, it is a good idea to mark whether a unit test has
% been created for the commands it defines. This is indicated by writing \cs{testfile}\marg{filename}
% anywhere within "\begin{macro}" \dots "\end{macro}".
% The first time a test file is referred to its filename will be printed in the documentation;
% subsequent referals will be noted by \textsf{l3doc} but not printed.
%
% If the class option "checktest" is enabled, then it is an \emph{error} to have a
% "macro" environment without a \cs{testfile} file. This is intended for large packages such
% as \pkg{expl3} that should have absolutely comprehensive tests suites and whose authors
% may not always be as sharp at adding new tests with new code as they should be.
%
% \DescribeEnv{variable}
% When documenting variable definitions, use the "variable" environment instead.
% It will, here, behave identically to the "macro" environment, except that if the class
% option "checktest" is enabled, variables will not be required to have a test file.
%
% \DescribeEnv{arguments}
% Within a \env{macro} environment, you may use the \env{arguments} environment
% to describe the arguments taken by the function(s). It behaves
% like a modified enumerate environment.
% \begin{verbatim}
% % \begin{macro}{\foo:nn,\foo:VV}
% % \begin{arguments}
% %   \item Name of froozle to be frazzled
% %   \item Name of muble to be jubled
% % \end{arguments}
% %   \begin{macrocode}
% ... code for \foo:nn and \foo:VV ...
% %   \end{macrocode}
% % \end{macro}
% \end{verbatim}
%
% \bigskip
% \textbf{OPTIONS FOR THE FUTURE}\qquad Any improvements to the markup
% for the \env{function} environment would be good to mirror in \env{macro}.
%
% Perhaps this would be a better syntax for describing arguments?
% \begin{verbatim}
% \begin{macro}{\foo:nn,foo:VV}
% \dArg{Name of froozle to be frazzled}
% \dArg{Name of mumble to be jumbled}
% ...
% \end{verbatim}
% I.e., get rid of the environment and do things like in, say, \pkg{fontspec}.
%
% \subsection{Keeping things consistent}
%
% Whenever a function is either documented or defined with \env{function}
% and \env{macro} respectively, its name is stored in a sequence for later
% processing.
%
% At the end of the document (i.e., after the \textsc{dtx} file has finished
% processing), the list of names is analysed to check whether all defined
% functions have been documented and vice versa. The results are printed
% in the console output.
%
% If you need to do more serious work with these lists of names, take a
% look at the implementation for the data structures and methods used to
% store and access them directly.
%
% \subsection{Documenting templates}
%
% The following macros are provided for documenting templates; might
% end up being something completely different but who knows.
% \begin{quote}\parskip=0pt\obeylines
% "\begin{TemplateInterfaceDescription}" \Arg{template type name}
% "  \TemplateArgument{none}{---}"
% \textsc{or one or more of these:}
% "  \TemplateArgument" \Arg{arg no} \Arg{meaning}
% \textsc{and}
% "\TemplateSemantics"
% "  " \meta{text describing the template type semantics}
% "\end{TemplateInterfaceDescription}"
% \end{quote}
%
% \begin{quote}\parskip=0pt\obeylines
% "\begin{TemplateDescription}" \Arg{template type name} \Arg{name}
% \textsc{one or more of these:}
% "  \TemplateKey" \marg{key name} \marg{type of key}
% "    "\marg{textual description of meaning}
% "    "\marg{default value if any}
% \textsc{and}
% "\TemplateSemantics"
% "  " \meta{text describing special additional semantics of the template}
% "\end{TemplateDescription}"
% \end{quote}
%
% \begin{quote}\parskip=0pt\obeylines
% "\begin{InstanceDescription}" \oarg{text to specify key column width (optional)}
% \hfill\marg{template type name}\marg{instance name}\marg{template name}
% \textsc{one or more of these:}
% "  \InstanceKey" \marg{key name} \marg{value}
% \textsc{and}
% "\InstanceSemantics"
% "  " \meta{text describing the result of this instance}
% "\end{InstanceDescription}"
% \end{quote}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3doc} implementation}
%
%    \begin{macrocode}
%<*class>
%    \end{macrocode}
%
% The Guilty Parties.
%    \begin{macrocode}
\cs_new_nopar:Npn\Team{%
  The~\LaTeX3~Project\thanks{%
  Frank~Mittelbach,~Denys~Duchier,~Chris~Rowley,~
  Rainer~Sch\"opf,~Johannes~Braams,~Michael~Downes,~
  David~Carlisle,~Alan~Jeffrey,~Morten~H\o{}gholm,~Thomas~Lotze,~
  Javier~Bezos,~Will~Robertson,~Joseph~Wright}}
%    \end{macrocode}
%
% \subsection{Options and configuration}
%
%    \begin{macrocode}
\DeclareOption{a5paper}{\@latexerr{Option not supported}{}}
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N \g_doc_full_bool
\bool_new:N \g_doc_lmodern_bool
\bool_new:N \g_doc_checkfunc_bool
\bool_new:N \g_doc_checktest_bool
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption{full}{ \bool_set_true:N \g_doc_full_bool }
\DeclareOption{onlydoc}{ \bool_set_false:N \g_doc_full_bool }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption{check}{ \bool_set_true:N \g_doc_checkfunc_bool }
\DeclareOption{nocheck}{ \bool_set_false:N \g_doc_checkfunc_bool }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption{checktest}{ \bool_set_true:N \g_doc_checktest_bool }
\DeclareOption{nochecktest}{ \bool_set_false:N \g_doc_checktest_bool }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption{cm-default}{ \bool_set_false:N \g_doc_lmodern_bool }
\DeclareOption{lm-default}{ \bool_set_true:N \g_doc_lmodern_bool }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ExecuteOptions{full,a4paper,nocheck,nochecktest,lm-default}
%    \end{macrocode}
%
% Input a local configuration file, if it exists.
%
%    \begin{macrocode}
\InputIfFileExists{l3doc.cfg}
  {
    \typeout{*************************************^^J
             *~Local~config~file~l3doc.cfg~used   ^^J
             *************************************}
  }
  { \@input{l3doc.ltx} }
%    \end{macrocode}
%
%    \begin{macrocode}
\ProcessOptions
%    \end{macrocode}
%
%
% \subsection{Class and package loading}
%
%    \begin{macrocode}
\LoadClass{article}
\RequirePackage{doc}
\RequirePackage{array,alphalph,booktabs,color,fixltx2e,enumitem,textcomp,trace,underscore}
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_if:NT \g_doc_lmodern_bool {
  \RequirePackage[T1]{fontenc}
  \RequirePackage{lmodern}
}
%    \end{macrocode}
%
%    \begin{macrocode}
\RequirePackage{hypdoc}
%    \end{macrocode}
% Just want the "comment" environment from \pkg{verbatim}:
%    \begin{macrocode}
\let\doc@verbatim\verbatim
\let\enddoc@verbatim\endverbatim
\let\doc@@verbatim\@verbatim
\RequirePackage{verbatim}
\AtBeginDocument{%
  \let\verbatim\doc@verbatim
  \let\endverbatim\enddoc@verbatim
  \let\@verbatim\doc@@verbatim
}
%    \end{macrocode}
%
% \subsection{Configuration}
%
% \begin{macro}{\MakePrivateLetters}
%    \begin{macrocode}
\cs_set_nopar:Npn \MakePrivateLetters {
  \char_make_letter:N \@
  \char_make_letter:N \_
  \char_make_letter:N \:
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\setcounter{StandardModuleDepth}{1}
\@addtoreset{CodelineNo}{part}
\cs_set_nopar:Npn \theCodelineNo {
  \textcolor[gray]{0.5}{ \sffamily\tiny\arabic{CodelineNo} }
}
%    \end{macrocode}
%
%
%
% \subsection{Design}
%
% Increase the text width slightly so that width the standard fonts
% 72 columns of code may appear in a |macrocode| environment.
% Increase the marginpar width slightly, for long command names.
% And increase the left margin by a similar amount.
%    \begin{macrocode}
\setlength   \textwidth      { 385pt }
\addtolength \marginparwidth {  30pt }
\addtolength \oddsidemargin  {  20pt }
\addtolength \evensidemargin {  20pt }
%    \end{macrocode}
% (These were introduced when "article" was the documentclass, but
%  I've left them here for now to remind me to do something about them
%  later; we still have the problem of \emph{very long} command names.)
%
% Customise lists:
%    \begin{macrocode}
\cs_set_eq:NN \@@oldlist\list
\cs_set_nopar:Npn \list#1#2{\@@oldlist{#1}{#2\listparindent\z@}}
\setlength \parindent  { 0pt }
\setlength \itemindent { 0pt }
\setlength \parskip    { \medskipamount }
%    \end{macrocode}
%
% \subsection{Text markup}
%
%    Make "|" and |"| be `short verb' characters, but not in
%    the document preamble, where an active character may interfere
%    with packages that are loaded.
%    \begin{macrocode}
\AtBeginDocument {
  \MakeShortVerb \"
  \MakeShortVerb \|
}
%    \end{macrocode}
%
%    \begin{macrocode}
\providecommand*\eTeX{
  \if b\expandafter\@car\f@series\@nil\boldmath\fi
  $\m@th\varepsilon$-\TeX
}
\providecommand*\IniTeX{Ini\TeX}
\providecommand*\Lua{Lua}
\providecommand*\LuaTeX{\Lua\TeX}
\providecommand*\pdfTeX{pdf\TeX}
\RequirePackage{graphicx}
\cs_if_free:NT \XeTeX {
  \cs_new_protected_nopar:Npn \XeTeX
    {X\kern-.125em\lower.5ex\hbox{\reflectbox{E}}\kern-.1667em\TeX}
}
%    \end{macrocode}
%
% \begin{macro}{\cmd,\cs}
% |\cmd{\foo}| Prints |\foo| verbatim. It may be used inside moving
% arguments. |\cs{foo}| also prints |\foo|, for those who prefer that
% syntax.
%    \begin{macrocode}
\cs_set_nopar:Npn \cmd #1 { \cs{\expandafter\cmd@to@cs\string#1} }
\cs_set_nopar:Npn \cmd@to@cs #1#2 { \char\number`#2\relax }
\DeclareRobustCommand \cs [1] { \texttt { \char`\\ #1 } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\marg,\oarg,\parg}
%    |\marg{text}| prints \marg{text}, `mandatory argument'.\\
%    |\oarg{text}| prints \oarg{text}, `optional argument'.\\
%    |\parg{te,xt}| prints \parg{te,xt}, `picture mode argument'.
%    \begin{macrocode}
\providecommand\marg[1]{ \texttt{\char`\{} \meta{#1} \texttt{\char`\}} }
\providecommand\oarg[1]{ \texttt[ \meta{#1} \texttt] }
\providecommand\parg[1]{ \texttt( \meta{#1} \texttt) }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\m,\file,\env,\pkg,\cls}
% This list may change\dots this is just my preference for markup.
%    \begin{macrocode}
\cs_set_eq:NN \m    \meta
\cs_set_eq:NN \file \nolinkurl
\DeclareRobustCommand \env {\texttt}
\DeclareRobustCommand \pkg {\textsf}
\DeclareRobustCommand \cls {\textsf}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{texnote}
%    \begin{macrocode}
\newenvironment{texnote}{
  \endgraf
  \vspace{3mm}
  \small\textbf{\TeX~hackers~note:}
}{
  \vspace{3mm}
}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\tn}
% As \cs{cs}. Use this to mark up all \TeX\ and \LaTeXe\ commands; they 
% then end up together in the index. TODO: hyperlinks in the index entries.
%    \begin{macrocode}
\newcommand\tn[1]{
  \texttt{\bslash #1}
  \index{TeX~and~LaTeX2e~commands\actualchar
          \string\TeX{}~and~\string\LaTeXe{}~commands:\levelchar
          #1\actualchar{\string\ttfamily\string\bslash{}#1}}}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{documentation}
% \begin{environment}{implementation}
% \begin{macro}{\EnableDocumentation,\EnableImplementation}
% \begin{macro}{\DisableDocumentation,\DisableImplementation}
%    \begin{macrocode}
\cs_new:Npn \doc_implementation: {
  \cs_set:Npn \variable {\macro[var]}
}
\cs_new:Npn \doc_docu: {
  \cs_set_eq:NN \variable \variabledoc
}
\AtEndOfPackage{\doc_docu:}
\newenvironment{documentation}{\doc_docu:}{}
\newenvironment{implementation}{\doc_implementation:}{}
\newcommand\EnableDocumentation{%
  \renewenvironment{documentation}{\doc_docu:}{}%
}
\newcommand\EnableImplementation{%
  \renewenvironment{implementation}{\doc_implementation:}{}%
}
\newcommand\DisableDocumentation{%
  \cs_set_eq:NN \documentation \comment
  \cs_set_eq:NN \enddocumentation \endcomment
}
\newcommand\DisableImplementation{%
  \cs_set_eq:NN \implementation \comment
  \cs_set_eq:NN \endimplementation \endcomment
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{environment}
% \end{environment}
%
% \begin{environment}{arguments}
% This environment is designed to be used within a \env{macro} environment
% to describe the arguments of the macro/function.
%    \begin{macrocode}
\newenvironment{arguments}{
  \enumerate[
    nolistsep,
    label=\texttt{\#\arabic*}~:,
    labelsep=*,
  ]
}{
  \endenumerate
}
%    \end{macrocode}
% \end{environment}
%
% \begin{environment}{function}
% \begin{environment}{variabledoc}
% Environment for documenting function(s).
% Stick the function names in a box. Use a "|" as delimiter and
% allow |<...>| to be used as markup for |\meta{...}|.
% Ignore spaces and sanitize with catcodes before reading argument.
%    \begin{macrocode}
\group_begin:
\char_make_active:N \<
\cs_new_nopar:Npn \function {
  \phantomsection
  \char_make_active:N \<
  \cs_set_eq:NN < \doc_open_meta:n
  \group_begin:
    \MakePrivateLetters
    \char_make_other:N \|
    \char_make_other:N \\
    \char_make_space:N \~
    \char_make_ignore:N \ % space
    \char_make_ignore:N \^^M
    \char_make_ignore:N \^^I
    \function_aux:n
}
\group_end:
\cs_set_eq:NN \variabledoc \function
%    \end{macrocode}
%
% \begin{macro}{\function_aux:n}
% \begin{arguments}
% \item Vertical bar--separated list of functions with optional metadata;
%       input has already been sanitised by catcode changes before reading
%       the argument.
% \end{arguments}
% Because vertical bars are odd delimiters to choose, we also now iterate over commas!
%    \begin{macrocode}
\group_begin:
\char_make_other:N \|
\cs_gset_nopar:Npn \function_aux:n #1 {
    \cs_set_nopar:Npn \nextnewline{\cs_gset_nopar:Npn\nextnewline{\\}}
    \tl_gset_eq:NN \g_doc_macro_tl \c_empty_tl
    \bigskip\endgraf\noindent\ttfamily
    \tabular[b]{ | l @{} c | }
      \hline
      \clist_map_inline:nn {#1} {\doc_showmacro:w ##1 | \q_stop} \\
      \hline
    \endtabular
  \group_end:
}
\group_end:
%    \end{macrocode}
% \end{macro}
% \end{environment}
% \end{environment}
%
% \begin{macro}{\doc_showmacro:w}
% This function reads in a "|"-separated list, passing each item to
% the auxiliary function "\doc_showmacro_aux:w".
%    \begin{macrocode}
\group_begin:
\char_make_other:N \|
\cs_gset_nopar:Npn \doc_showmacro:w #1 | {
  \tl_if_blank:nTF {#1} {
    \use_none:n
  }{
    \doc_showmacro_aux:w #1 / \q_stop
    \peek_meaning:NTF \q_stop { \use_none:n } { \doc_showmacro:w }
  }
}
\group_end:
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\bool_new:N \l_doc_meta_TF_bool
\bool_new:N \l_doc_meta_pTF_bool
\bool_new:N \l_doc_meta_EXP_bool
%    \end{macrocode}
%
% \begin{macro}{\doc_showmacro_aux:w}
% This macro is passed one of:
% \begin{quote}
%   "\abc:cnx / (EXP) / \q_stop" \\
%   "\abc:cnx / \q_stop" \\
% \end{quote}
% We also have some code here to print out every documented macro at the end
% of the document.
% \begin{arguments}
% \item Function/macro/variable name \item Metadata tags (if any)
% \end{arguments}
%    \begin{macrocode}
\cs_new_nopar:Npn \doc_showmacro_aux:w #1 / #2 \q_stop {

  \tl_if_in:nnTF {#2} { (TF)  } {
    \bool_gset_true:N \l_doc_meta_TF_bool
  }{
    \bool_gset_false:N \l_doc_meta_TF_bool
  }
  \tl_if_in:nnTF {#2} { (EXP) } {
    \bool_gset_true:N \l_doc_meta_EXP_bool
  }{
    \bool_gset_false:N \l_doc_meta_EXP_bool
  }
  \tl_if_in:nnTF {#2} { (pTF)  } {
    \bool_gset_true:N \l_doc_meta_TF_bool
    \bool_gset_true:N \l_doc_meta_pTF_bool
    \bool_gset_true:N \l_doc_meta_EXP_bool
    \tl_set:Nx \l_doc_pTF_name_tl { \doc_predicate_from_base:w #1 \q_nil }
  }{
    \bool_gset_false:N \l_doc_meta_pTF_bool
  }

  \bool_if:NT \l_doc_meta_pTF_bool {
    \doc_special_main_index:o { \l_doc_pTF_name_tl }
    \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:N \l_doc_pTF_name_tl }
  }

  \bool_if:NTF \l_doc_meta_TF_bool {
    \doc_special_main_index:o { #1 TF }
    \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1 TF } }
    \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1 T  } }
    \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1  F } }
  }{
    \doc_special_main_index:o { #1 }
    \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1    } }
  }

  \bool_if:NTF \l_doc_meta_pTF_bool {
    \bool_gset_false:N \l_doc_meta_TF_bool
    \exp_after:wN \doc_showmacro_aux_ii:w \l_doc_pTF_name_tl ::\q_stop
    \bool_gset_true:N \l_doc_meta_TF_bool
    \doc_showmacro_aux_ii:w #1::\q_stop
  }{
    \doc_showmacro_aux_ii:w #1::\q_stop
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\doc_showmacro_aux_ii:w}
% This macro is passed arguments in the following ways:
% \begin{quote}
%   "\doc_showmacro_aux_ii:w "^^A
%    \makebox[\widthof{\texttt{123456}}]{\meta{name}}^^A
%                        " ::\q_stop" \\
%   "\doc_showmacro_aux_ii:w \foo   ::\q_stop" \\
%   "\doc_showmacro_aux_ii:w \foo:  ::\q_stop" \\
%   "\doc_showmacro_aux_ii:w \foo:Z ::\q_stop" \\
% \end{quote}
% Notice that for "\foo", "#2" and "#3" are empty,\\
% for "\foo:", "#2" is empty, and "#3" is `":"'\\
% for "\foo:Z", "#2" is `"Z"' and "#3" is `":"' .
% \begin{arguments}
% \item Function name \item Possible arg.\ spec. \item Possible colon
% \end{arguments}
%    \begin{macrocode}
\cs_set_nopar:Npn \doc_showmacro_aux_ii:w #1:#2:#3 \q_stop {
  \nextnewline
  \str_if_eq:xxTF {#1} {\g_doc_macro_tl} {
    \doc_typeset_aux:n
  }{
    \tl_gset:Nn \g_doc_macro_tl {#1}
    \use:n
  }
  { \g_doc_macro_tl }
  #3
  #2
  \bool_if:NT \l_doc_meta_TF_bool { \doc_typeset_TF: }
  &
  \bool_if:NT \l_doc_meta_EXP_bool {
    \hspace{\tabcolsep}
    $\star$
  }
  \tl_set:Nx \g_doc_macro_tl { \tl_to_str:N \g_doc_macro_tl }
  \exp_args:NNf \tl_replace_all_in:Nnn \g_doc_macro_tl {\token_to_str:N _} {/}
  \exp_args:NNf \tl_replace_all_in:Nnn \g_doc_macro_tl {\@backslashchar} {}
  \bool_if:NT \g_doc_full_bool {
    \exp_args:Nf\label{doc/function/\g_doc_macro_tl#3#2}
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{syntax}
% Syntax block placed next to the list of functions to illustrate their use.
%    \begin{macrocode}
\dim_new:N \g_doc_syntax_dim
\dim_set:Nn \g_doc_syntax_dim {0.7\textwidth}
\newenvironment{syntax}{
  \minipage[b]{\g_doc_syntax_dim}
    \cs_set_nopar:Npn \meta@font@select{\rmfamily\itshape} % (Will: I HATE italic cmtt!)
    \small\ttfamily\raggedright
    \obeyspaces\obeylines
}{
  \endminipage
  \hfil\break
  \global\@ignoretrue
}
%    \end{macrocode}
% \end{environment}
%
% Perhaps these belong in \file{l3token}?
%    \begin{macrocode}
\tl_map_inline:nn {0123456789} { \cs_gset_eq:cN {char_other_#1} #1 }
%    \end{macrocode}
%
% \begin{macro}{\doc_open_meta:n,\doc_close_meta:n}
% This code turns all numbers within "<...>" markup to be set as subscripts.
% You can use escaped numbers to get the real thing (e.g., "\1" = `1').
%    \begin{macrocode}
\group_begin:
  \tl_map_inline:nn {0123456789} { \char_make_active:N #1 }
  \cs_new:Npn \doc_open_meta:n {
    \group_begin:
      \tl_map_function:nN {0123456789} \doc_assign_num:n
      \doc_close_meta:w
  }
  \cs_new:Npn \Arg {
    \texttt{ \char`\{ }
    \group_begin:
      \tl_map_function:nN {0123456789} \doc_assign_num:n
      \doc_close_Arg:n
  }
\group_end:
\cs_new_nopar:Npn \doc_close_meta:w #1> { \meta {#1} \group_end: }
\cs_new_nopar:Npn \doc_close_Arg:n #1 {
  \meta {#1}
  \group_end:
  \texttt{ \char`\} }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\doc_assign_num:n}
% This function takes a numeral (`0'), defines its escaped self to be equal
% to itself ("\0" $\to$ `0'), makes it active, and turns itself into a subscript
% instead (`0' $\to$ `${}_0$').
%    \begin{macrocode}
\cs_new_nopar:Npn \doc_assign_num:n #1 {
  \cs_set_eq:cc { \string #1 } { char_other_\string #1 }
  \char_make_active:N #1
  \cs_set_nopar:Npn #1 { \unskip \, $ {} \sb { \use:c { char_other_\string #1 } } $ }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{macro}
% We want to extend the old definition to allow comma-separated lists of
% macros, rather than one at a time. keyval processing is very rudimentary;
% awaiting a more robust solution.
%    \begin{macrocode}
\renewcommand \macro [1][] {

  \int_compare:nNnTF \currentgrouplevel=2
    { \int_gzero:N \g_doc_nested_macro_int }
    { \int_incr:N  \g_doc_nested_macro_int }

  \bool_set_false:N \l_doc_macro_aux_bool
  \bool_set_false:N \l_doc_macro_TF_bool
  \bool_set_false:N \l_doc_macro_pTF_bool
  \bool_set_false:N \l_doc_macro_var_bool
  \bool_set_false:N \l_doc_tested_bool
  
  \cs_set_eq:NN \doc_macroname_prefix:n \use:n
  \cs_set_eq:NN \doc_macroname_suffix: \c_empty_tl
  
  \cs_set_nopar:Npn \KV_key_no_value_elt:n ##1 { \use:c {doc_macro_opt_##1:} }
  \KV_parse_space_removal_sanitize:n {#1}
  
  \cs_set_eq:NN \testfile \doc_print_testfile:n

  \group_begin:
    \MakePrivateLetters
    \char_make_letter:N \\
    \char_make_ignore:N \ % space
    \char_make_ignore:N \^^M
    \char_make_ignore:N \^^I
    \doc_macro_aux:n
}
%    \end{macrocode}
% After changing the catcodes, parse the arguments:
%    \begin{macrocode}
\cs_new_nopar:Npn \doc_macro_aux:n #1 {
  \group_end:
  \cs_set:Npn \l_doc_macro_input_clist {#1}
  \bool_if:NTF \l_doc_macro_pTF_bool
  {
    \clist_map_inline:nn {#1}
    {
      \exp_args:Nf \doc_macro_single
        { \doc_predicate_from_base:w ##1 \q_nil }
    }
    \bool_set_true:N \l_doc_macro_TF_bool
    \clist_map_inline:nn {#1} { \doc_macro_single {##1} }
    \bool_set_false:N \l_doc_macro_TF_bool
  }
  {
    \clist_map_inline:nn {#1} { \doc_macro_single {##1} }
  }
}
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N \l_doc_macro_aux_bool
\bool_new:N \l_doc_macro_TF_bool
\bool_new:N \l_doc_macro_pTF_bool
\bool_new:N \l_doc_macro_var_bool
\cs_set_nopar:Npn \doc_macro_opt_aux: { \bool_set_true:N \l_doc_macro_aux_bool }
\cs_set_nopar:Npn \doc_macro_opt_TF:  { \bool_set_true:N \l_doc_macro_TF_bool  }
\cs_set_nopar:Npn \doc_macro_opt_pTF: { \bool_set_true:N \l_doc_macro_pTF_bool }
\cs_set_nopar:Npn \doc_macro_opt_var: { \bool_set_true:N \l_doc_macro_var_bool }
%    \end{macrocode}
% \end{environment}
%
%    \begin{macrocode}
\cs_set:Npn \doc_predicate_from_base:w #1:#2 \q_nil {#1_p:#2}
%    \end{macrocode}
%
% \begin{environment}{doc_macro_single}
% Let's start to mess around with "doc"'s "macro" environment. See \file{doc.dtx}
% for a full explanation of the original environment. It's
% rather \emph{enthusiastically} commented.
% \begin{arguments}
% \item Macro/function/whatever name; input has already been sanitised.
% \end{arguments}
%    \begin{macrocode}
\int_new:N \l_doc_macro_int
\cs_set_nopar:Npn \doc_macro_single #1 {
  \int_incr:N \l_doc_macro_int
  \tl_set:Nx \saved@macroname { \token_to_str:N #1 }
  \topsep\MacroTopsep
  \trivlist
  \cs_set_nopar:Npn \makelabel ##1 { \llap{##1} }
  \if@inlabel
    \cs_set_eq:NN \@tempa \@empty
    \count@ \macro@cnt
    \loop \ifnum\count@>\z@
      \cs_set_nopar:Npx \@tempa{\@tempa\hbox{\strut}}
      \advance\count@\m@ne
    \repeat
    \cs_set_nopar:Npx \makelabel ##1 {
      \llap{\vtop to\baselineskip {\@tempa\hbox{##1}\vss}}
    }
    \advance \macro@cnt \@ne
  \else
    \macro@cnt \@ne
  \fi

  \bool_if:NT \l_doc_macro_aux_bool {
    \cs_set_eq:NN \doc_macroname_prefix:n \doc_typeset_aux:n
  }
  \bool_if:NT \l_doc_macro_TF_bool {
    \cs_set_eq:NN \doc_macroname_suffix: \doc_typeset_TF:
  }
  
  \bool_if:NF \l_doc_macro_aux_bool {
    \tl_gset:Nx \l_doc_macro_tl { \tl_to_str:n {#1} }
    \exp_args:NNf \tl_greplace_all_in:Nnn \l_doc_macro_tl {\token_to_str:N _} {/}
    \exp_args:NNf \tl_greplace_all_in:Nnn \l_doc_macro_tl {\@backslashchar} {}
  }

  \use:x {
    \exp_not:N \item [ \exp_not:N \doc_print_macroname:n {
      \tl_to_str:n {#1}
    }]
  }
  \global\advance \c@CodelineNo \@ne

  \bool_if:NF \l_doc_macro_aux_bool {
    \bool_if:NTF \l_doc_macro_TF_bool {
      \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 TF } }
      \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 T  } }
      \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 F  } }
    }{
      \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n {#1} }
    }
  }
  \bool_if:NTF \l_doc_macro_TF_bool {
    \SpecialMainIndex{#1 TF}\nobreak
    \DoNotIndex{#1 TF}
  }{
    \SpecialMainIndex{#1}\nobreak
    \DoNotIndex{#1}
  }
  
  \global\advance \c@CodelineNo \m@ne
  \ignorespaces
}
%    \end{macrocode}
%
% \begin{macro}{\doc_print_macroname:n}
%    \begin{macrocode}
\tl_clear:N \l_doc_macro_tl
\cs_set_nopar:Npn \doc_print_macroname:n #1 {
  \strut
  \int_compare:nTF { \tl_elt_count:n {#1} <= 28 }
    { \MacroFont } { \MacroLongFont }

  % INEFFICIENT: (!)
  \exp_args:NNx \seq_if_in:NnTF \g_doc_functions_seq
  { #1 \bool_if:NT \l_doc_macro_TF_bool { \tl_to_str:n {TF} } }
  {
    \hyperref [doc/function/\l_doc_macro_tl]
  }
  { \use:n }
  {
    \doc_macroname_prefix:n {#1} \doc_macroname_suffix: \ % space!
  }
}
%    \end{macrocode}
% \end{macro}
% \end{environment}
%
% \begin{macro}{\MacroLongFont}
%    \begin{macrocode}
\providecommand \MacroLongFont {
  \fontfamily{lmtt}\fontseries{lc}\small
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\doc_typeset_TF:,\doc_typeset_aux:n}
% Used by \cs{doc_macro_single} and \cs{doc_showmacro_aux_ii:w} to typeset
% conditionals and auxiliary functions.
%    \begin{macrocode}
\cs_set_nopar:Npn \doc_typeset_TF: {
  \itshape TF%
  \makebox[0pt][r]{%
    \color[gray]{0.5}
    \underline { \phantom{\itshape TF} \kern-0.1em }
  }
}
\cs_set_nopar:Npn \doc_typeset_aux:n #1 {
  {\color[gray]{0.5} #1}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\doc_print_testfile:n}
% Used to show that a macro has a test, somewhere.
%    \begin{macrocode}
\DeclareDocumentCommand \doc_print_testfile:n {m} {
  \bool_set_true:N \l_doc_tested_bool
  \tl_if_eq:nnF {#1} {*} {
    \seq_if_in:NnF \g_doc_testfiles_seq {#1}
    {
      \par{\footnotesize(\textit{
        The~ test~ suite~ for~ this~ command,~ and~ others~ in~ this~ file,~ is~ \textsf{#1}}.
      )\par}
      \seq_gput_right:Nn \g_doc_testfiles_seq {#1}
    }
  }
}
\seq_new:N \g_doc_testfiles_seq
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\TestFiles}
%    \begin{macrocode}
\DeclareDocumentCommand \TestFiles {m} {
  \par
  {\itshape
    The~ following~ test~ files~ are~ used~ for~ this~ code:~ \textsf{#1}.
  }
  \par\ignorespaces
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\UnitTested}
%    \begin{macrocode}
\DeclareDocumentCommand \UnitTested {} {
  \testfile*
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\TestMissing}
%    \begin{macrocode}
\cs_generate_variant:Nn \prop_gput:Nnn {NVx}
\prop_new:N \g_doc_missing_tests_prop
\DeclareDocumentCommand \TestMissing {m} {
  \prop_if_in:NVTF \g_doc_missing_tests_prop \l_doc_macro_input_clist
  {
    \prop_get:NVN \g_doc_missing_tests_prop \l_doc_macro_input_clist \l_tmpa_tl
    \prop_gput:NVx \g_doc_missing_tests_prop \l_doc_macro_input_clist
    {
      *~ \l_tmpa_tl
      ^^J \exp_not:n {\space\space\space\space\space\space}
      *~ #1
    }
  }
  { \prop_gput:NVn \g_doc_missing_tests_prop \l_doc_macro_input_clist {#1} }
}
%    \end{macrocode}
% \end{macro}
%
% Delete these when they're finally available:
%    \begin{macrocode}
\cs_set_nopar:Npn \clist_length:N #1 {
  \tex_number:D \etex_numexpr:D
    0
    \clist_map_function:NN #1 \tl_elt_count_aux:n
  \scan_stop:
}
\cs_set_nopar:Npn \clist_length:n #1 {
  \tex_number:D \etex_numexpr:D
    0
    \clist_map_function:nN {#1} \tl_elt_count_aux:n
  \scan_stop:
}
\cs_set_nopar:Npn \clist_item:Nn #1#2 {
  \exp_args:No \clist_item:nn {#1} {#2}
}
\cs_generate_variant:Nn \clist_item:Nn { c }
\cs_set:Npn \clist_item:nn #1#2 {
  \int_compare:nNnTF {#2} < { 0 }
    {
      \exp_args:Nf \clist_item_aux:nw 
        { \clist_length:n {#1} + #2 }
        #1 , \q_recursion_tail \q_recursion_stop
    }
    {
      \clist_item_aux:nw {#2} #1 
        , \q_recursion_tail \q_recursion_stop
    }
}
\cs_set:Npn \clist_item_aux:nw #1#2 , #3 {
  \int_compare:nNnTF {#1} = { 0 }
    { \use_i_delimit_by_q_recursion_stop:nw {#2} }
    {
      \quark_if_recursion_tail_stop:n {#3}
      \clist_item_aux:nw { #1 - 1 } #3
    }
}
%    \end{macrocode}
%
% \begin{macro}{\endmacro}
%    \begin{macrocode}
\int_new:N \g_doc_nested_macro_int
\cs_set:Nn \doc_texttt_comma:n {\,,~\texttt{#1}}
\cs_set:Npn \endmacro {
  \int_compare:nT {\g_doc_nested_macro_int<1}
  {
  \par\nobreak{\footnotesize(\emph{
    End~ definition~ for~
    \prg_case_int:nnn { \clist_length:N \l_doc_macro_input_clist }
    {
      {1} { \texttt{ \clist_use:N \l_doc_macro_input_clist }. }
      {2}
      {
        \tl_set:Nx \l_clist_first_tl { \clist_item:Nn \l_doc_macro_input_clist {0} }
        \tl_set:Nx \l_clist_last_tl { \clist_item:Nn \l_doc_macro_input_clist {1} }
        \texttt{\l_clist_first_tl}\,~ and~ \texttt{\l_clist_last_tl}\,.
      }
      {3}
      {
        \tl_set:Nx \l_clist_first_tl { \clist_item:Nn \l_doc_macro_input_clist {0} }
        \tl_set:Nx \l_clist_mid_tl   { \clist_item:Nn \l_doc_macro_input_clist {1} }
        \tl_set:Nx \l_clist_last_tl  { \clist_item:Nn \l_doc_macro_input_clist {2} }
        \texttt{\l_clist_first_tl}\,,~
        \texttt{\l_clist_mid_tl}\,,~
        and~ \texttt{\l_clist_last_tl}\,.
      }
    }
    {
      \tl_set:Nx \l_clist_first_tl { \clist_item:Nn \l_doc_macro_input_clist {0} }
      \texttt{\l_clist_first_tl}\,~and~others.
    }
    \bool_if:nT {
      !\l_doc_macro_aux_bool &&
      \int_compare_p:n {\g_doc_nested_macro_int<1}
    }
    {
        \int_compare:nNnTF \l_doc_macro_int=1 {~This~} {~These~}
        \bool_if:NTF \l_doc_macro_var_bool{variable}{function}
        \int_compare:nNnTF \l_doc_macro_int=1 {~is~}{s~are~}
        documented~on~page~
        \exp_args:Nx\pageref{doc/function/\l_doc_macro_tl}.
    }
  })\par}
  }
  \bool_if:nT
  { \g_doc_checktest_bool &&
    !( \l_doc_macro_aux_bool || \l_doc_macro_var_bool ) &&
    !\l_doc_tested_bool
  }
  {
    \seq_gput_right:Nx \g_doc_not_tested_seq
    {
      \l_doc_macro_input_clist
      \bool_if:NT \l_doc_macro_pTF_bool {~(pTF)}
      \bool_if:NT \l_doc_macro_TF_bool {~(TF)}
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DescribeOption}
% For describing package options. Due to Joseph Wright.
% Name/usage might change soon.
%    \begin{macrocode}
\newcommand*{\DescribeOption}{
 \leavevmode
 \@bsphack
 \begingroup
   \MakePrivateLetters
   \Describe@Option
}
\newcommand*{\Describe@Option}[1]{
 \endgroup
 \marginpar{
   \raggedleft
   \PrintDescribeEnv{#1}
 }
 \SpecialOptionIndex{#1}
 \@esphack
 \ignorespaces
}
\newcommand*{\SpecialOptionIndex}[1]{
 \@bsphack
 \begingroup
   \HD@target
   \let\HDorg@encapchar\encapchar
   \edef\encapchar usage{
     \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage}
   }
   \index{
     #1\actualchar{\protect\ttfamily#1}~(option)
     \encapchar usage
   }
   \index{
     options:\levelchar#1\actualchar{\protect\ttfamily#1}
     \encapchar usage
   }
 \endgroup
 \@esphack
}
%    \end{macrocode}
% \end{macro}
%
% Here are some definitions for additional markup that will help to
% structure your documentation.
%
% \begin{environment}{danger}
% \begin{environment}{ddanger}
% \begin{syntax}
% |\begin{[d]danger}|\\
% dangerous code\\
% |\end{[d]danger}|
% \end{syntax}
%
% \begin{danger}
%   Provides a danger bend, as known from the \TeX{}book.
% \end{danger}
% The actual character from the font |manfnt|:
%    \begin{macrocode}
\font\manual=manfnt
\cs_set_nopar:Npn \dbend { {\manual\char127} }
%    \end{macrocode}
%
% Defines the single danger bend. Use it whenever there is a feature in your
% package that might be tricky to use.
% FIXME: Has to be fixed when in combination with a macro-definition.
%    \begin{macrocode}
\newenvironment {danger} {
  \begin{trivlist}\item[]\noindent
  \begingroup\hangindent=2pc\hangafter=-2
  \cs_set_nopar:Npn \par{\endgraf\endgroup}
  \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces
}{
  \par\end{trivlist}
}
%    \end{macrocode}
%
% \begin{ddanger}
%   Use the double danger bend if there is something which could cause serious
%   problems when used in a wrong way. Better the normal user does not know
%   about such things.
% \end{ddanger}
%    \begin{macrocode}
\newenvironment {ddanger} {
  \begin{trivlist}\item[]\noindent
  \begingroup\hangindent=3.5pc\hangafter=-2
  \cs_set_nopar:Npn \par{\endgraf\endgroup}
  \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\ignorespaces
}{
  \par\end{trivlist}
}
%    \end{macrocode}
% \end{environment}
% \end{environment}
%
% \subsection{Documenting templates}
%
%    \begin{macrocode}
\newenvironment{TemplateInterfaceDescription}[1]
  {\subsection{The~object~type~`#1'}%
   \begingroup
   \@beginparpenalty\@M
   \description
   \def\TemplateArgument##1##2{\item[Arg:~##1]##2\par}%
   \def\TemplateSemantics{\enddescription\endgroup
       \subsubsection*{Semantics:}}%
  }
  {\par\bigskip}
%    \end{macrocode}
%
%    \begin{macrocode}
\newenvironment{TemplateDescription}[2]
  {\subsection{The~template~`#2'~(object~type~#1)}%
   \subsubsection*{Attributes:}%
   \begingroup
   \@beginparpenalty\@M
   \description
   \def\TemplateKey##1##2##3##4{\item[##1~(##2)]##3%
     \ifx\TemplateKey##4\TemplateKey\else
%         \hskip0ptplus3em\penalty-500\hskip 0pt plus 1filll Default:~##4%
         \hfill\penalty500\hbox{}\hfill Default:~##4%
         \nobreak\hskip-\parfillskip\hskip0pt\relax
     \fi
     \par}%
   \def\TemplateSemantics{\enddescription\endgroup
       \subsubsection*{Semantics~\&~Comments:}}%
  }
  {\par\bigskip}
%    \end{macrocode}
%
%    \begin{macrocode}
\newenvironment{InstanceDescription}[4][xxxxxxxxxxxxxxx]
  {\subsubsection{The~instance~`#3'~(template~#2/#4)}%
   \subsubsection*{Attribute~values:}%
   \begingroup
   \@beginparpenalty\@M
   \def\InstanceKey##1##2{\>\textbf{##1}\>##2\\}%
   \def\InstanceSemantics{\endtabbing\endgroup
       \vskip-30pt\vskip0pt
       \subsubsection*{Layout~description~\&~Comments:}}%
   \tabbing
   xxxx\=#1\=\kill
  }
  {\par\bigskip}
%    \end{macrocode}
%
% \subsection{Inheriting doc}
%
% Code here is taken from \pkg{doc}, stripped of comments and translated
% into \pkg{expl3} syntax. New features are added in various places.
%
% \begin{macro}{\StopEventually,\Finale,\AlsoImplementation,\OnlyDescription}
%    \begin{macrocode}
\bool_new:N \g_doc_implementation_bool
\cs_set_nopar:Npn \AlsoImplementation {
  \bool_set_true:N \g_doc_implementation_bool
  \cs_set:Npn \StopEventually ##1 {
    \@bsphack
    \cs_gset_nopar:Npn \Finale { ##1 \check@checksum }
    \init@checksum
    \@esphack
  }
}
\AlsoImplementation
\cs_set_nopar:Npn \OnlyDescription {
  \@bsphack
  \bool_set_false:N \g_doc_implementation_bool
  \cs_set:Npn \StopEventually ##1 { ##1 \endinput }
  \@esphack
}
\cs_set_eq:NN \Finale \relax
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\cs_set_nopar:Npn \partname{File}
%    \end{macrocode}
%
% \begin{macro}{\DocInput}
% From \pkg{doc}. Now accepts comma-list input (who has commas in filenames?).
%    \begin{macrocode}
\clist_new:N \g_docinput_clist
\cs_set:Npn \DocInput #1 {
  \clist_map_inline:nn {#1} {
    \clist_put_right:Nn \g_docinput_clist {##1}
    \MakePercentIgnore
    \input{##1}
    \MakePercentComment
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DocInputAgain}
% Uses "\g_docinput_clist" to re-input whatever's already been "\DocInput"-ed until now.
% May be used multiple times.
%    \begin{macrocode}
\cs_set:Npn \DocInputAgain {
  \clist_map_inline:Nn \g_docinput_clist {
    \MakePercentIgnore
    \input{##1}
    \MakePercentComment
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DocInclude}
% More or less exactly the same as |\include|, but uses |\DocInput|
% on a |dtx| file, not |\input| on a |tex| file.
%    \begin{macrocode}
\cs_set_nopar:Npn \partname{File}
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand*{\DocInclude}[1]{%
  \relax\clearpage
  \docincludeaux
  \IfFileExists{#1.fdd}{
    \cs_set_nopar:Npn \currentfile{#1.fdd}
  }{
    \cs_set_nopar:Npn \currentfile{#1.dtx}
  }
  \ifnum\@auxout=\@partaux
    \@latexerr{\string\include\space cannot~be~nested}\@eha
  \else
    \@docinclude #1
  \fi
}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set_nopar:Npn \@docinclude #1 {
  \clearpage
  \immediate\write\@mainaux{\string\@input{#1.aux}}
  \@tempswatrue
  \if@partsw
    \@tempswafalse
    \cs_set_nopar:Npx \@tempb{#1}
    \@for\@tempa:=\@partlist\do{
      \ifx\@tempa\@tempb\@tempswatrue\fi
    }
  \fi
  \if@tempswa
    \cs_set_eq:NN \@auxout\@partaux
    \immediate\openout\@partaux #1.aux
    \immediate\write\@partaux{\relax}
    \cs_set_eq:NN \@ltxdoc@PrintIndex\PrintIndex
    \cs_set_eq:NN \PrintIndex\relax
    \cs_set_eq:NN \@ltxdoc@PrintChanges\PrintChanges
    \cs_set_eq:NN \PrintChanges\relax
    \cs_set_eq:NN \@ltxdoc@theglossary\theglossary
    \cs_set_eq:NN \@ltxdoc@endtheglossary\endtheglossary
    \part{\currentfile}
    {
      \cs_set_eq:NN \ttfamily\relax
      \cs_gset_nopar:Npx \filekey{\filekey, \thepart={\ttfamily\currentfile}}
    }
    \DocInput{\currentfile}
    \cs_set_eq:NN \PrintIndex\@ltxdoc@PrintIndex
    \cs_set_eq:NN \PrintChanges\@ltxdoc@PrintChanges
    \cs_set_eq:NN \theglossary\@ltxdoc@theglossary
    \cs_set_eq:NN \endtheglossary\@ltxdoc@endtheglossary
    \clearpage
    \@writeckpt{#1}
    \immediate\closeout\@partaux
  \else
    \@nameuse{cp@#1}
  \fi
  \cs_set_eq:NN \@auxout\@mainaux
}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_gset_nopar:Npn \codeline@wrindex #1 {
  \immediate\write\@indexfile {
    \string\indexentry{#1}
    {\filesep\number\c@CodelineNo}
  }
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\cs_set_eq:NN \filesep \@empty
%    \end{macrocode}
%
% \begin{macro}{\docincludeaux}
%    \begin{macrocode}
\cs_set_nopar:Npn \docincludeaux {
  \cs_set_nopar:Npn \thepart {\alphalph{part}}
  \cs_set_nopar:Npn \filesep {\thepart-}
  \cs_set_eq:NN \filekey\@gobble
  \g@addto@macro\index@prologue{
    \cs_gset_nopar:Npn\@oddfoot{
      \parbox{\textwidth}{
        \strut\footnotesize
        \raggedright{\bfseries File~Key:}~\filekey
      }
    }
    \cs_set_eq:NN \@evenfoot\@oddfoot
  }
  \cs_gset_eq:NN \docincludeaux\relax
  \cs_gset_nopar:Npn\@oddfoot{
    \expandafter\ifx\csname ver@\currentfile\endcsname\relax
      File~\thepart :~{\ttfamily\currentfile}~
    \else
      \GetFileInfo{\currentfile}
      File~\thepart :~{\ttfamily\filename}~
      Date:~\filedate\ % space
      Version~\fileversion
    \fi
    \hfill\thepage
  }
  \cs_set_eq:NN \@evenfoot \@oddfoot
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{At end document}
%
% Print all defined and documented macros/functions.
%
%    \begin{macrocode}
\seq_new:N \g_doc_functions_seq
\seq_new:N \g_doc_macros_seq
\seq_new:N \g_doc_not_tested_seq
%    \end{macrocode}
%
%    \begin{macrocode}
\iow_open:Nn \g_write_func_stream { \jobname.cmds }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new_nopar:Npn \doc_show_functions_defined: {
  \bool_if:nT { \g_doc_implementation_bool && \g_doc_checkfunc_bool } {
    \typeout{ ======================================== ^^J }

    \tl_clear:N \l_tmpa_tl
    \seq_map_inline:Nn \g_doc_functions_seq {
      \seq_if_in:NnT \g_doc_macros_seq {##1} {
        \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J }
        \iow_now:Nn \g_write_func_stream { ##1 }
      }
    }
    \iow_close:N \g_write_func_stream
    \doc_functions_typeout:n {
      Functions~both~documented~and~defined:^^J (In~order~of~being~documented)
    }

    \seq_map_inline:Nn \g_doc_functions_seq {
      \seq_if_in:NnF \g_doc_macros_seq {##1} {
        \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J }
      }
    }
    \doc_functions_typeout:n { Functions~documented~but~not~defined: }

    \seq_map_inline:Nn \g_doc_macros_seq {
      \seq_if_in:NnF \g_doc_functions_seq {##1} {
        \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J }
      }
    }
    \doc_functions_typeout:n { Functions~defined~but~not~documented: }

    \typeout{ ======================================== }
  }
}
\AtEndDocument{ \doc_show_functions_defined: }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set_nopar:Npn \doc_functions_typeout:n #1 {
  \tl_if_empty:NF \l_tmpa_tl {
    \typeout{
      -------------------------------------- ^^J #1 ^^J
      -------------------------------------- ^^J \l_tmpa_tl
    }
    \tl_clear:N \l_tmpa_tl
  }
}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Npn \doc_show_not_tested: {
  \bool_if:NT \g_doc_checktest_bool
  {
    \bool_if:nT { !(\seq_if_empty_p:N  \g_doc_not_tested_seq) ||
                  !(\prop_if_empty_p:N \g_doc_missing_tests_prop) }
    {
      \tl_clear:N \l_tmpa_tl
      \prop_if_empty:NF \g_doc_missing_tests_prop
      {
        \tl_put_right:Nn \l_tmpa_tl
        {
          ^^J^^JThe~ following~ macro(s)~ have~ incomplete~ tests:^^J
        }
        \prop_map_inline:Nn \g_doc_missing_tests_prop
        {
          \tl_put_right:Nn \l_tmpa_tl
          {^^J\space\space\space\space ##1
           ^^J\space\space\space\space\space\space ##2} 
        }
      }
      \seq_if_empty:NF \g_doc_not_tested_seq
      {
        \tl_put_right:Nn \l_tmpa_tl
        {
          ^^J^^J
          The~ following~ macro(s)~ do~ not~ have~ any~ tests:^^J
        }
        \seq_map_inline:Nn \g_doc_not_tested_seq
        {
          \clist_map_inline:nn {##1}
          {
            \tl_put_right:Nn \l_tmpa_tl {^^J\space\space\space\space ####1}
          }
        }
        \int_set:Nn \l_tmpa_int {\etex_interactionmode:D}
        \errorstopmode
        \ClassError{l3doc}{\l_tmpa_tl}{}
        \int_set:Nn \etex_interactionmode:D {\l_tmpa_int}
      }
    }
  }
}
\AtEndDocument{ \doc_show_not_tested: }
%    \end{macrocode}
%
% \subsection{Indexing}
%
% Fix index (for now):
%    \begin{macrocode}
\g@addto@macro\theindex{\MakePrivateLetters}
\cs_set:Npn \verbatimchar {&}
%    \end{macrocode}
%
%    \begin{macrocode}
\setcounter{IndexColumns}{2}
%    \end{macrocode}
%
% Set up the Index to use "\part"
%    \begin{macrocode}
\IndexPrologue{
  \part*{Index}
  \markboth{Index}{Index}
  \addcontentsline{toc}{part}{Index}
  The~italic~numbers~denote~the~pages~where~the~
  corresponding~entry~is~described,~
  numbers~underlined~point~to~the~definition,~
  all~others~indicate~the~places~where~it~is~used.
}
%    \end{macrocode}
%
%
% \begin{macro}{\doc_special_main_index:n,\doc_special_main_index:o,\hdpgindex}
% Heiko's replacement to play nicely with |hypdoc|:
%    \begin{macrocode}

\cs_set_nopar:Npn \doc_special_main_index:n #1 {
  \index{
    \@gobble#1
    \actualchar
    \string\verb\quotechar*\verbatimchar#1\verbatimchar
    \encapchar
    hdpgindex{\thepage}{usage}
  }
}
\cs_set_nopar:Npn \doc_special_main_index:o { \exp_args:No \doc_special_main_index:n }
%    \end{macrocode}
%    \begin{macrocode}
\cs_set_nopar:Npn \hdpgindex #1#2#3 {
  \csname\ifx\\#2\\relax\else#2\fi\endcsname{
    \hyperlink{page.#1}{#3}
  }
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\g@addto@macro \PrintIndex { \AtEndDocument{ \typeout{^^J
  ========================================^^J
  Generate~the~index~by~executing^^J
  \c_space_tl \c_space_tl \c_space_tl \c_space_tl
  makeindex~-s~l3doc.ist~-o~\jobname.ind~\jobname.idx^^J
  ========================================^^J
  }}
}
%    \end{macrocode}
%
% \subsection{Change history}
%
% Set the change history to use "\part".
% Allow control names to be hyphenated in here...
%    \begin{macrocode}
\GlossaryPrologue{
  \part*{Change~History}
  {\GlossaryParms\ttfamily\hyphenchar\font=`\-}
  \markboth{Change~History}{Change~History}
  \addcontentsline{toc}{part}{Change~History}
}
%    \end{macrocode}
%
%    \begin{macrocode}
\g@addto@macro \PrintChanges { \AtEndDocument{ \typeout{^^J
  ========================================^^J
  Generate~the~change~list~by~executing^^J
  \c_space_tl \c_space_tl \c_space_tl \c_space_tl
   makeindex~-s~gglo.ist~~-o~\jobname.gls~\jobname.glo^^J
  ========================================^^J
  }}
}
%    \end{macrocode}
%
%^^A The standard \changes command modified slightly to better cope with
%^^A this multiple file document.
%^^A\def\changes@#1#2#3{%
%^^A  \let\protect\@unexpandable@protect
%^^A  \edef\@tempa{\noexpand\glossary{#2\space\currentfile\space#1\levelchar
%^^A                                 \ifx\saved@macroname\@empty
%^^A                                   \space
%^^A                                   \actualchar
%^^A                                   \generalname
%^^A                                 \else
%^^A                                   \expandafter\@gobble
%^^A                                   \saved@macroname
%^^A                                   \actualchar
%^^A                                   \string\verb\quotechar*%
%^^A                                   \verbatimchar\saved@macroname
%^^A                                   \verbatimchar
%^^A                                 \fi
%^^A                                 :\levelchar #3}}%
%^^A  \@tempa\endgroup\@esphack}
%
% \subsection{cfg}
%
%    \begin{macrocode}
\bool_if:NTF \g_doc_full_bool {
  \RecordChanges
  \CodelineIndex
  \EnableCrossrefs
  \AlsoImplementation
}{
  \CodelineNumbered
  \DisableCrossrefs
  \OnlyDescription
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
%</class>
%    \end{macrocode}
%
%
% \subsection{Makeindex configuration}
%
% The makeindex style "l3doc.ist" is used in place of the usual
% "gind.ist" to ensure that I is used in the sequence I J K
% not I II II, which would be the default makeindex behaviour.
%
% Will: Do we need this?
%
%    \begin{macrocode}
%<*docist>
actual '='
quote '!'
level '#'
preamble
"\n \\begin{theindex} \n \\makeatletter\\scan@allowedfalse\n"
postamble
"\n\n \\end{theindex}\n"
item_x1   "\\efill \n \\subitem "
item_x2   "\\efill \n \\subsubitem "
delim_0   "\\pfill "
delim_1   "\\pfill "
delim_2   "\\pfill "
% The next lines will produce some warnings when
% running Makeindex as they try to cover two different
% versions of the program:
lethead_prefix   "{\\bfseries\\hfil "
lethead_suffix   "\\hfil}\\nopagebreak\n"
lethead_flag       1
heading_prefix   "{\\bfseries\\hfil "
heading_suffix   "\\hfil}\\nopagebreak\n"
headings_flag       1

% and just for source3:
% Remove R so I is treated in sequence I J K not I II III
page_precedence "rnaA"
%</docist>
%    \end{macrocode}
%
% \section{Testing}
%\ExplSyntaxOn 
%\cs_set_eq:NN\g_saved_doc_functions_seq\g_doc_functions_seq
%\cs_set_eq:NN\g_saved_doc_macros_seq\g_doc_macros_seq
%\ExplSyntaxOff
%
% \begin{function}{\example_foo:N|\example_foo:c}
% \begin{syntax}
%   "\example_foo:N" <arg1>
% \end{syntax}
% <0123456789> <\0\1\2\3\4\5\6\7\8\9>  \Arg{arg1} ":("
% \end{function}
%
% \begin{function}{ \foo | \foo: | \foo:x | \barrz: }
% \begin{syntax}
%   "\example_foo:N" <arg1>
% \end{syntax}
% <0123456789> <\0\1\2\3\4\5\6\7\8\9>
% \end{function}
%
% \begin{function}{\foo:N / (TF) | \foo_if:c / (TF) (EXP)}
% Test.
% \end{function}
%
% \begin{function}{ \bar / (EXP) | \bar: / (EXP)  | \bar:x / (EXP)  | }
% \begin{syntax}
%   "\example_foo:N" <arg1>
% \end{syntax}
% <0123456789> <\0\1\2\3\4\5\6\7\8\9>
% \end{function}
%
% \begin{macro}{ \foo , \foo: , \foo:x }
% Testing.
% \end{macro}
%
% \bigskip\bigskip
%
% \begin{macro}[aux]{ \foo_aux: }
% Testing.
% \end{macro}
%
% \bigskip\bigskip
%
% \begin{macro}[TF]{ \foo_if:c }
% Testing.
% \end{macro}
%
% \bigskip\bigskip
%
% \begin{macro}{\aaaa_bbbb_cccc_dddd_eeee_ffff_gggg_hhhh}
% Long macro names need to be printed in a shorter font.
%    \begin{macrocode}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\c_minus_one,
% \c_zero,
% \c_one,
% \c_two,
% \c_three,
% \c_four,
% \c_five,
% \c_six,
% \c_seven,
% \c_eight,
% \c_nine,
% \c_ten,
% \c_eleven,
% \c_sixteen,
% \c_thirty_two,
% \c_hundred_one,
% \c_twohundred_fifty_five,
% \c_twohundred_fifty_six,
% \c_thousand,
% \c_ten_thousand,
% \c_ten_thousand_one}
% \begin{arguments}
% \item name
% \item parameters
% \end{arguments}
% Another test.
% \end{macro}
%
%  
%\ExplSyntaxOn 
%\cs_set_eq:NN\g_doc_functions_seq\g_saved_doc_functions_seq
%\cs_set_eq:NN\g_doc_macros_seq\g_saved_doc_macros_seq
%\ExplSyntaxOff
%
%
% \subsection{Macros}
% \raggedright
% \ExplSyntaxOn
% \seq_map_inline:Nn \g_doc_macros_seq { `\texttt{#1}' \quad }
% \ExplSyntaxOff
%
% \subsection{Functions}
% \ExplSyntaxOn
% \seq_map_inline:Nn \g_doc_functions_seq { `\texttt{#1}' \quad }
% \ExplSyntaxOff
%
% \end{implementation}
%
% \PrintIndex
%
% \endinput
