% \iffalse meta-comment % %% File: l3doc.dtx Copyright (C) 1990-2012 The 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 "l3kernel 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 LaTeX3 Project. %% %% ----------------------------------------------------------------------- % %<*driver> \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi \input l3docstrip.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,cfg}}} \generate{\file{l3doc.ist}{\from{l3doc.dtx}{docist}}} \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % % % Need to protect the file metadata for any modules that load l3doc. % This is restored after "\ProvideExplClass" below. % \begin{macrocode} %\let \filenameOld \ExplFileName %\let \filedateOld \ExplFileDate %\let \fileversionOld \ExplFileVersion %\let \filedescriptionOld \ExplFileDescription % \end{macrocode} % %<*driver|class> \RequirePackage{expl3,xparse,calc} % % %<*driver|class> \GetIdInfo$Id: l3doc.dtx 4230 2012-09-24 21:44:28Z joseph $ {L3 Experimental documentation class} % % %<*driver> \ProvidesFile{\ExplFileName.dtx} [\ExplFileDate\space v\ExplFileVersion\space\ExplFileDescription] \documentclass{l3doc} \usepackage{framed,lipsum} \begin{document} \DocInput{l3doc.dtx} \end{document} % % % This isn't included in the typeset documentation because it's a bit ugly: %<*class> \ProvidesExplClass {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \let \ExplFileName \filenameOld \let \ExplFileDate \filedateOld \let \ExplFileVersion \fileversionOld \let \ExplFileDescription \filedescriptionOld % % \fi % % \title{The \pkg{l3doc} class\thanks{This file % has version number v\ExplFileVersion, last % revised \ExplFileDate.}} % \author{\Team} % \date{\ExplFileDate} % \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 much 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)~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 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). % This is partially done, now, but should be improved. % \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 "\DocInput" now takes comma-separated arguments, and "\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{framed} % \vspace{-\baselineskip} % \begin{verbatim} % \begin{function}{ \function_one , \function_two: } % \begin{syntax} % "\foo_bar:" \Arg{meta} % \end{syntax} % % \end{function} % \end{verbatim} % \hrulefill % \par % \hspace*{0.25\textwidth} % \begin{minipage}{0.5\textwidth} % \begin{function}{ \function_one: , \function_two: } % \begin{syntax} % "\foo_bar:" \Arg{meta} % \end{syntax} % % \end{function} % \end{minipage} % \end{framed} % % Function environments take an optional argument to indicate whether the function(s) it % describes are expandable or restricted-expandable or defined in conditional forms. Use "EXP", "rEXP", "TF", or "pTF" % for this; note that "pTF" implies "EXP" since predicates must always be expandable. % As an example: % \begin{framed} % \vspace{-\baselineskip} % \begin{verbatim} % \begin{function}[pTF]{ \cs_if_exist:N } % \begin{syntax} % "\cs_if_exist_p:N" % \end{syntax} % % \end{function} % \end{verbatim} % \hrulefill % \par % \hspace*{0.25\textwidth} % \begin{minipage}{0.5\textwidth} % \begin{function}[pTF]{ \cs_if_exist:N } % \begin{syntax} % "\cs_if_exist_p:N" % \end{syntax} % % \end{function} % \end{minipage} % \end{framed} % % \DescribeEnv{variable} % 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. % Some changes 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{macro}[aux]" and it will be % marked as such; its margin call-out will be printed in grey. % % Similarly, an internal package function still requires documentation % but usually will not be documented for users to see; these can be marked % as such with "\begin{macro}[internal]". % % 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{\TestFiles} % \cs{TestFiles}\marg{list of files} is used to indicate which test files % are used for the current code; they will be printed in the documentation. % % \DescribeMacro{\UnitTested} % 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{UnitTested} % anywhere within "\begin{macro}" \dots "\end{macro}". % % 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. % % \DescribeMacro{\TestMissing} % If a function is missing a test, this may be flagged by writing (as many times as needed) % \cs{TestMissing}\marg{explanation of test required}. % These missing tests will be summarised in the listing printed at the end of the % compilation run. % % \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} % % % \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} % % \begin{macrocode} %<@@=codedoc> % \end{macrocode} % % \subsection{Variables} % % \begin{macrocode} \coffin_new:N \l_@@_output_box \coffin_new:N \l_@@_names_coffin \coffin_new:N \l_@@_descr_coffin \coffin_new:N \l_@@_syntax_coffin \box_new:N \g_@@_syntax_box \bool_new:N \l_@@_long_name_bool \bool_new:N \g_@@_implementation_bool \dim_new:N \l_@@_trial_width_dim \tl_new:N \l_@@_macro_tl \int_new:N \l_@@_macro_int \int_new:N \g_@@_nested_macro_int %\int_new:N \c@CodelineNo \prop_new:N \g_@@_missing_tests_prop \clist_new:N \g_docinput_clist \tl_new:N \l_@@_at_replaced_macro_tl % \end{macrocode} % % \begin{macrocode} \seq_new:N \g_@@_testfiles_seq \seq_new:N \g_doc_functions_seq \seq_new:N \g_doc_macros_seq \seq_new:N \g_@@_not_tested_seq % \end{macrocode} % % For function/macro environments: % \begin{macrocode} \bool_new:N \l_@@_meta_TF_bool \bool_new:N \l_@@_meta_pTF_bool \bool_new:N \l_@@_meta_EXP_bool \bool_new:N \l_@@_meta_rEXP_bool \bool_new:N \l_@@_macro_internal_bool \bool_new:N \l_@@_macro_aux_bool \bool_new:N \l_@@_macro_TF_bool \bool_new:N \l_@@_macro_pTF_bool \bool_new:N \l_@@_macro_var_bool % \end{macrocode} % % For package options: % \begin{macrocode} \bool_new:N \g_@@_full_bool \bool_new:N \g_@@_lmodern_bool \bool_new:N \g_@@_checkfunc_bool \bool_new:N \g_@@_checktest_bool % \end{macrocode} % % Temporaries: % \begin{macrocode} \seq_new:N \g_@@_tmpa_seq \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl \int_new:N \l_@@_tmpa_int % \end{macrocode} % % Other: % \begin{macrocode} \bool_new:N \l_@@_tested_bool % \end{macrocode} % % % % \subsection{Options and configuration} % % \begin{macrocode} \DeclareOption{a5paper}{\@latexerr{Option not supported}{}} % \end{macrocode} % % % \begin{macrocode} \DeclareOption{full}{ \bool_set_true:N \g_@@_full_bool } \DeclareOption{onlydoc}{ \bool_set_false:N \g_@@_full_bool } % \end{macrocode} % % \begin{macrocode} \DeclareOption{check}{ \bool_set_true:N \g_@@_checkfunc_bool } \DeclareOption{nocheck}{ \bool_set_false:N \g_@@_checkfunc_bool } % \end{macrocode} % % \begin{macrocode} \DeclareOption{checktest}{ \bool_set_true:N \g_@@_checktest_bool } \DeclareOption{nochecktest}{ \bool_set_false:N \g_@@_checktest_bool } % \end{macrocode} % % \begin{macrocode} \DeclareOption{cm-default}{ \bool_set_false:N \g_@@_lmodern_bool } \DeclareOption{lm-default}{ \bool_set_true:N \g_@@_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, with a message to the console that this has happened. Since we distribute a cfg file with the class, this should usually always be true. Therefore, check for \cs{ExplMakeTitle} (defined in `our' cfg file) and only output the informational message if it's not found. % % \begin{macrocode} \msg_new:nnn {l3doc} {input-cfg} { Local~config~file~l3doc.cfg~loaded. } \file_if_exist:nT {l3doc.cfg} { \file_input:n {l3doc.cfg} \msg_info:nn {l3doc} {input-cfg} } % \end{macrocode} % % \begin{macrocode} \ProcessOptions % \end{macrocode} % % % \subsection{Class and package loading} % % \begin{macrocode} \LoadClass{article} \RequirePackage{doc} \RequirePackage { array, alphalph, amsmath, booktabs, color, colortbl, fixltx2e, hologo, enumitem, pifont, textcomp, trace, underscore, csquotes, fancyvrb, verbatim } \raggedbottom % \end{macrocode} % % % I've never worked out why the verbatim environment adds extra space in dtx documents. % Fix it with fancyvrb: % \begin{macrocode} \fvset{gobble=2} \cs_set_eq:NN \verbatim \Verbatim \cs_set_eq:NN \endverbatim \endVerbatim % \end{macrocode} % % \begin{macrocode} \bool_if:NT \g_@@_lmodern_bool { \RequirePackage[T1]{fontenc} \RequirePackage{lmodern} % \end{macrocode} % Now replace the italic typewriter font with the oblique shape instead; % the former makes my skin crawl. (Will, Aug 2011) % \begin{macrocode} \group_begin: \ttfamily \DeclareFontShape{T1}{lmtt}{m}{it}{<->ec-lmtto10}{} \group_end: } % \end{macrocode} % % Must be last, as usual. % \begin{macrocode} \RequirePackage{hypdoc} % \end{macrocode} % % \subsection{Configuration} % % \begin{macro}{\MakePrivateLetters} % \begin{macrocode} \cs_set_nopar:Npn \MakePrivateLetters { \char_set_catcode_letter:N \@ \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \: } % \end{macrocode} % \end{macro} % % \begin{macrocode} \setcounter{StandardModuleDepth}{1} \@addtoreset{CodelineNo}{part} \tl_replace_once:Nnn \theCodelineNo { \HDorg@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.) % % Customise lists: % \begin{macrocode} \cs_set_eq:NN \@@_oldlist:nn \list \cs_set_nopar:Npn \list #1 #2 { \@@_oldlist:nn {#1} { #2 \listparindent\z@ } } \setlength \parindent { 2em } \setlength \itemindent { 0pt } \setlength \parskip { 0pt plus 3pt minus 0pt } % \end{macrocode} % % Customise TOC (as we have so many sections). Different design and/or % structure is called for ): % \begin{macrocode} \@addtoreset{section}{part} \cs_set_nopar:Npn \l@section #1#2 { \ifnum \c@tocdepth >\z@ \addpenalty\@secpenalty \addvspace{1.0em \@plus\p@} \setlength\@tempdima{2.5em} % was 1.5em \begingroup \parindent \z@ \rightskip \@pnumwidth \parfillskip -\@pnumwidth \leavevmode \bfseries \advance\leftskip\@tempdima \hskip -\leftskip #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par \endgroup \fi } \cs_set_nopar:Npn\l@subsection{\@dottedtocline{2}{2.5em}{2.3em}} % #2 = 1.5em % \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{\hologo{eTeX}} \providecommand*\IniTeX{\hologo{iniTeX}} \providecommand*\Lua{Lua} \providecommand*\LuaTeX{\hologo{LuaTeX}} \providecommand*\pdfTeX{\hologo{pdfTeX}} \providecommand*\XeTeX{\hologo{XeTeX}} % \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. There is a bit of shuffling around to make sure that |_| % has the catcode that \cs{doc_replace_at_at:N} expects, without % rescanning the whole argument. For that we store in % \cs{l_@@_tmpb_tl} a single underscore with the current catcode, % then replace all such underscores by letter underscores in |#1| % (stored in the |tmpa| token list). After calling % \cs{doc_replace_at_at:N}, we replace the underscores back to their % old meaning before using the token list. % \begin{macrocode} \DeclareDocumentCommand \cmd {m} { \@@_cmd:n { #1 } } \DeclareDocumentCommand \cs {m} { \@@_cs:n { #1 } } % \end{macrocode} % % This is |\cmd{\foo}| and |\cs{foo}|: \cmd\foo\ and \cs{foo}. % \begin{macrocode} \cs_new:Npn \@@_cmd:n #1 { \cs{ \expandafter \@@_cmd_to_cs:w \string#1 } } \cs_set_nopar:Npn \@@_cmd_to_cs:w #1#2 { \char\number`#2\relax } % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \@@_cs:n #1 { \tl_set_rescan:Nnn \l_@@_tmpb_tl { } { _ } \tl_set:Nn \l_@@_tmpa_tl {#1} \tl_replace_all:NVn \l_@@_tmpa_tl \l_@@_tmpb_tl { _ } \@@_replace_at_at:N \l_@@_tmpa_tl \tl_replace_all:NnV \l_@@_tmpa_tl { _ } \l_@@_tmpb_tl \texttt { \char`\\ \tl_use:N \l_@@_tmpa_tl} } \cs_generate_variant:Nn \tl_replace_all:Nnn { NV , NnV } % \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}{\file,\env,\pkg,\cls} % This list may change\dots this is just my preference for markup. % \begin{macrocode} \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} \DeclareDocumentCommand \tn {m} { \texttt { \char`\\ #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 \@@_implementation: { \DeclareDocumentCommand {\variable} { O{} } { \@@_macro:n { var , ##1 } } \cs_set_eq:NN \endvariable \endmacro } \cs_new:Npn \@@_docu: { \cs_set_eq:NN \variable \variabledoc \cs_set_eq:NN \endvariable \endvariabledoc } \AtEndOfPackage{\@@_docu:} \newenvironment{documentation}{\@@_docu:}{} \newenvironment{implementation}{\@@_implementation:}{} % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand \EnableDocumentation {} { \renewenvironment{documentation}{\@@_docu:}{} } \NewDocumentCommand \EnableImplementation {} { \renewenvironment{implementation}{\@@_implementation:}{} } \NewDocumentCommand \DisableDocumentation {} { \cs_set_eq:NN \documentation \comment \cs_set_eq:NN \enddocumentation \endcomment } \NewDocumentCommand \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{macrocode} \keys_define:nn { l3doc/function } { TF .code:n = { \bool_gset_true:N \l_@@_meta_TF_bool } , EXP .code:n = { \bool_gset_true:N \l_@@_meta_EXP_bool \bool_gset_false:N \l_@@_meta_rEXP_bool } , rEXP .code:n = { \bool_gset_false:N \l_@@_meta_EXP_bool \bool_gset_true:N \l_@@_meta_rEXP_bool } , pTF .code:n = { \bool_gset_true:N \l_@@_meta_pTF_bool \bool_gset_true:N \l_@@_meta_TF_bool \bool_gset_true:N \l_@@_meta_EXP_bool } , added .tl_set:N = \l_@@_date_added_tl , updated .tl_set:N = \l_@@_date_updated_tl , tested .code:n = { } , } % \end{macrocode} % % % \begin{environment}{function} % \begin{environment}{variabledoc} % Environment for documenting function(s). % Stick the function names in a box. % Allow |<...>| to be used as markup for |\meta{...}|. % Ignore spaces and sanitize with catcodes before reading argument. % \begin{macrocode} \char_set_catcode_active:N \< \DeclareDocumentEnvironment {function} { O{} } { \par\bigskip\noindent \phantomsection \coffin_clear:N \l_@@_descr_coffin \box_gclear:N \g_@@_syntax_box \coffin_clear:N \l_@@_syntax_coffin \coffin_clear:N \l_@@_names_coffin \bool_set_false:N \l_@@_meta_TF_bool \bool_set_false:N \l_@@_meta_pTF_bool \bool_set_false:N \l_@@_meta_EXP_bool \bool_set_false:N \l_@@_meta_rEXP_bool \keys_set:nn { l3doc/function } {#1} \char_set_active_eq:NN < \@@_open_meta:w \group_begin: \MakePrivateLetters \char_set_catcode_other:N \| \char_set_catcode_space:N \~ \char_set_catcode_ignore:N \ % space \char_set_catcode_ignore:N \^^M \char_set_catcode_ignore:N \^^I \exp_after:wN \group_end: \@@_function:n } { \vcoffin_set_end: \hcoffin_set:Nn \l_@@_syntax_coffin { \box_use:N \g_@@_syntax_box } % \end{macrocode} % \cs{g_@@_syntax_box} is defined in the syntax environment. % \begin{macrocode} \bool_if:NTF \l_@@_long_name_bool { \coffin_join:NnnNnnnn \l_@@_output_box {hc} {vc} \l_@@_syntax_coffin {l} {T} {0pt} {0pt} \coffin_join:NnnNnnnn \l_@@_output_box {l} {t} \l_@@_names_coffin {r} {t} {-\marginparsep} {0pt} \coffin_join:NnnNnnnn \l_@@_output_box {l} {b} \l_@@_descr_coffin {l} {t} {0.75\marginparwidth + \marginparsep} {-\medskipamount} \coffin_typeset:Nnnnn \l_@@_output_box {\l_@@_descr_coffin-l} {\l_@@_descr_coffin-t} {0pt} {0pt} } { \coffin_join:NnnNnnnn \l_@@_output_box {hc} {vc} \l_@@_syntax_coffin {l} {t} {0pt} {0pt} \coffin_join:NnnNnnnn \l_@@_output_box {l} {b} \l_@@_descr_coffin {l} {t} {0pt} {-\medskipamount} \coffin_join:NnnNnnnn \l_@@_output_box {l} {t} \l_@@_names_coffin {r} {t} {-\marginparsep} {0pt} \coffin_typeset:Nnnnn \l_@@_output_box {\l_@@_syntax_coffin-l} {\l_@@_syntax_coffin-T} {0pt} {0pt} } \par \allowbreak } \char_set_catcode_other:N \< \cs_set_eq:NN \variabledoc \function \cs_set_eq:NN \endvariabledoc \endfunction % \end{macrocode} % % % \begin{macro}{\@@_function:n} % \begin{arguments} % \item Comma-separated list of functions; % input has already been sanitised by catcode changes before reading % the argument. % \end{arguments} % \begin{macrocode} \cs_set_nopar:Npn \@@_function:n #1 { \tl_set:Nn \l_@@_function_input_tl {#1} \dim_zero:N \l_@@_trial_width_dim \hcoffin_set:Nn \l_@@_names_coffin { \function_typeset:n {#1} } \dim_set:Nn \l_@@_trial_width_dim { \box_wd:N \l_@@_names_coffin } \bool_set:Nn \l_@@_long_name_bool { \dim_compare_p:nNn \l_@@_trial_width_dim > \marginparwidth } \vcoffin_set:Nnw \l_@@_descr_coffin {\textwidth} \noindent\ignorespaces } \cs_gset_nopar:Npn \function_typeset:n #1 %^^A todo: use "\cs_new:Npn" here { \tl_gclear:N \g_@@_macro_tl % populate "\l_@@_functions_block_prop" with info on the functions present: \clist_map_function:nN {#1} \@@_parse_functions:n \small\ttfamily \begin{tabular}{ @{} l @{} r @{} } \toprule \prop_map_function:NN \l_@@_functions_block_prop \@@_typeset_functions:nn \@@_typeset_dates: \bottomrule \end{tabular} \normalfont\normalsize } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_functions:n} % The idea here is to populate "\l_@@_functions_block_prop" with information % about the functions being typeset and their variants. % The property list uses a specific format: the keys contained are the function `names' (stripped of signature) with values specified by a comma-separated list containing two brace groups per item: % \begin{center} % |> {my_function} => {| \Arg{Nargs_1} \Arg{sig_1} |,| \Arg{Nargs_2} \Arg{sig_2} |, ... }| % \end{center} % This somewhat arcane syntax is chosen to distinguish between all variants of control sequence that may be being documented here. (With or without \textsf{expl3} function syntax.) % \begin{macrocode} \prop_new:N \l_@@_functions_block_prop \cs_generate_variant:Nn \prop_put:Nnn {Nxx} \cs_new:Nn \@@_parse_functions:n { \exp_args:Nxx \tl_if_head_eq_charcode:nNTF { \token_to_str:N #1 } {\cs_to_str:N \\} { \tl_gset_eq:NN \l_@@_function_name_prefix_tl \@backslashchar % for the weird functions named "\::N" and so on: \exp_args:Nx \tl_if_head_eq_charcode:nNTF { \cs_to_str:N #1 } { : } { % again, no variants: \prop_put:Nxx \l_@@_functions_block_prop { \cs_to_str:N #1 } { {-1} {} } } { % finally, for regular old csnames: \exp_args:NNf \prop_get:NnNTF \l_@@_functions_block_prop { \__cs_get_function_name:N #1 } \l_@@_tmpb_tl { \prop_put:Nxx \l_@@_functions_block_prop { \__cs_get_function_name:N #1 } { \l_@@_tmpb_tl , {\__cs_count_signature:N #1} {\__cs_get_function_signature:N #1} } } { \prop_put:Nxx \l_@@_functions_block_prop { \__cs_get_function_name:N #1 } { {\__cs_count_signature:N #1} {\__cs_get_function_signature:N #1} } } } } % \end{macrocode} % False branch for keys and things that aren't actually csnames: % \begin{macrocode} { % for now don't bother splitting into variants: \tl_gclear:N \l_@@_function_name_prefix_tl \prop_put:Nxx \l_@@_functions_block_prop { \tl_to_str:n {#1} } { {-1} {} } } } % \end{macrocode} % \end{macro} % \end{environment} % \end{environment} % % % \begin{macro}{\@@_typeset_functions:nn} % \begin{arguments} % \item Function/macro/variable name (stripped of signature in the first case, if any) % \item Comma-list containing information about the signature variants being documented (if any) % \end{arguments} % \begin{macrocode} \cs_new:Nn \@@_typeset_functions:nn { \clist_gset:Nn \l_@@_variants_clist {#2} \clist_gpop:NN \l_@@_variants_clist \l_@@_tmpb_tl \exp_args:Nc \@@_typeset_functions_aux:N { #1 \int_compare:nT { \exp_after:wN \use_i:nn \l_@@_tmpb_tl > -1 } {:} \int_compare:nT { \exp_after:wN \use_i:nn \l_@@_tmpb_tl > 0 } { \exp_after:wN \use_ii:nn \l_@@_tmpb_tl } } \\ } \cs_new_nopar:Nn \@@_typeset_functions_aux:N { \bool_if:NT \l_@@_meta_pTF_bool { \tl_set:Nx \l_@@_pTF_name_tl { \l_@@_function_name_prefix_tl \@@_predicate_from_base:N #1 } \@@_special_main_index:o { \l_@@_pTF_name_tl } \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:N \l_@@_pTF_name_tl } \tl_set:Nx \l_@@_pTF_name_tl { \@@_predicate_from_base:N #1 } } \tl_set:Nx \l_@@_tmpa_tl { \l_@@_function_name_prefix_tl \cs_to_str:N #1 \bool_if:NT \l_@@_meta_TF_bool { \tl_to_str:n {TF} } } \@@_special_main_index:o { \l_@@_tmpa_tl } \seq_gput_right:No \g_doc_functions_seq { \l_@@_tmpa_tl } \bool_if:NTF \l_@@_meta_pTF_bool { \bool_gset_false:N \l_@@_meta_TF_bool \exp_args:Nc \@@_typeset_function_block:N { \l_@@_pTF_name_tl } \bool_gset_true:N \l_@@_meta_TF_bool \\ \@@_typeset_function_block:N #1 } { \exp_args:Nx \tl_if_head_eq_charcode:nNTF { \exp_after:wN \use_none:n \token_to_str:N #1 } {:} { \@@_show_macro_unusual:N #1 } { \@@_typeset_function_block:N #1 } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_typeset_function_block:N} % \begin{macrocode} \cs_set_nopar:Nn \@@_typeset_function_block:N { \tl_gset:Nx \l_@@_function_name_tl { \__cs_get_function_name:N #1 } \tl_gset:Nx \l_@@_function_sig_tl { \__cs_get_function_signature:N #1 } \tl_gset:Nx \g_@@_macro_tl { \l_@@_function_name_prefix_tl \l_@@_function_name_tl } \@@_typeset_function_basename:N #1 \bool_if:NT \l_@@_meta_TF_bool { \@@_typeset_TF: } \@@_typeset_expandability: \clist_if_empty:NF \l_@@_variants_clist { \@@_typeset_variants: } \bool_if:NT \g_@@_full_bool { \@@_label_function:N #1 } } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_typeset_function_basename:N { \l_@@_function_name_prefix_tl \cs_to_str:N #1 } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_typeset_expandability: { & \bool_if:NT \l_@@_meta_EXP_bool { \hspace{\tabcolsep} \hyperlink{expstar} {$\star$} } \bool_if:NT \l_@@_meta_rEXP_bool { \hspace{\tabcolsep} \hyperlink{rexpstar} {\ding{73}} % hollow star } } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_typeset_variants: { \\ \@@_typeset_aux:n \g_@@_macro_tl : \int_compare:nTF { \clist_count:N \l_@@_variants_clist == 1 } { \exp_after:wN \use_ii:nn \l_@@_variants_clist } { \textrm( \clist_pop:NN \l_@@_variants_clist \l_@@_tmpb_tl \exp_after:wN \use_ii:nn \l_@@_tmpb_tl \clist_map_inline:Nn \l_@@_variants_clist {\textrm| \use_ii:nn ##1} \textrm) } \bool_if:NT \l_@@_meta_TF_bool { \@@_typeset_TF: } & \bool_if:NT \l_@@_meta_EXP_bool { \hspace{\tabcolsep} \hyperlink{expstar} {$\star$} } \bool_if:NT \l_@@_meta_rEXP_bool { \hspace{\tabcolsep} \hyperlink{rexpstar} {\ding{73}} % hollow star } } % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \@@_label_function:N { \tl_set:Nx \l_@@_tmpa_tl { \l_@@_function_name_prefix_tl \cs_to_str:N #1 } \exp_args:NNf \tl_replace_all:Nnn \l_@@_tmpa_tl {\token_to_str:N _} {/} \exp_args:NNf \tl_remove_all:Nn \l_@@_tmpa_tl {\@backslashchar} \exp_args:Nx \label {doc/function//\l_@@_tmpa_tl} } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_show_macro_unusual:N} % This is for the case when the function is one of the weird ones like \cs{::N}. % \begin{macrocode} \cs_set_nopar:Nn \@@_show_macro_unusual:N { \tl_gset:Nx \g_@@_macro_tl { \token_to_str:N #1} \token_to_str:N #1 & \exp_args:NNf \tl_replace_all:Nnn \g_@@_macro_tl {\token_to_str:N _} {/} \exp_args:NNf \tl_replace_all:Nnn \g_@@_macro_tl {\@backslashchar} {} \bool_if:NT \g_@@_full_bool { \exp_args:Nx \label { doc/function//\g_@@_macro_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_typeset_dates:} % To display metadata for when functions are added/modified. % \begin{macrocode} \cs_set:Nn \@@_typeset_dates: { \bool_if:nF { \tl_if_empty_p:N \l_@@_date_added_tl && \tl_if_empty_p:N \l_@@_date_updated_tl } { \midrule } \tl_if_empty:NF \l_@@_date_added_tl { \multicolumn{2}{@{}r@{}} { \scriptsize New:\,\l_@@_date_added_tl } \\ } \tl_if_empty:NF \l_@@_date_updated_tl { \multicolumn{2}{@{}r@{}} { \scriptsize Updated:\,\l_@@_date_updated_tl } \\ } } % \end{macrocode} % \end{macro} % % \begin{environment}{syntax} % Syntax block placed next to the list of functions to illustrate their use. % \begin{macrocode} \newenvironment{syntax} { \small\ttfamily \bool_if:NTF \l_@@_long_name_bool { \hbox_gset:Nw \g_@@_syntax_box \arrayrulecolor{white} \begin{tabular}{@{}l@{}} \toprule \begin{minipage} { \textwidth+0.75\marginparwidth-\l_@@_trial_width_dim } } { \hbox_gset:Nw \g_@@_syntax_box \arrayrulecolor{white} \begin{tabular}{@{}l@{}} \toprule \begin{minipage}{ \textwidth } } \raggedright \obeyspaces\obeylines } { \end{minipage} \end{tabular} \arrayrulecolor{black} \hbox_set_end: \ignorespacesafterend } % \end{macrocode} % \end{environment} % % \begin{macro}{\@@_ensuremath_sb:n} % \begin{macrocode} \cs_new:Npn \@@_ensuremath_sb:n #1 { \ensuremath{\sb{#1}} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_open_meta:w,\@@_close_meta:n} % \begin{macrocode} \cs_set_eq:NN \@@_meta:n \meta \cs_set:Npn \meta { \group_begin: \char_set_active_eq:NN _ \@@_ensuremath_sb:n \@@_close_meta:n } \cs_new:Npn \@@_open_meta:w { \group_begin: \char_set_active_eq:NN _ \@@_ensuremath_sb:n \@@_close_meta:w } \cs_new:Npn \Arg { \texttt{ \char`\{ } \group_begin: \char_set_active_eq:NN _ \@@_ensuremath_sb:n \@@_close_Arg:n } \cs_new_nopar:Npn \@@_close_meta:n #1 { \@@_meta:n {#1} \group_end: } \cs_new_nopar:Npn \@@_close_meta:w #1> { \@@_meta:n {#1} \group_end: } \cs_new_nopar:Npn \@@_close_Arg:n #1 { \@@_meta:n {#1} \group_end: \texttt{ \char`\} } } % \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: % \begin{macrocode} \keys_define:nn { l3doc/macro } { aux .code:n = { \bool_set_true:N \l_@@_macro_aux_bool } , internal .code:n = { \bool_set_true:N \l_@@_macro_internal_bool } , int .code:n = { \bool_set_true:N \l_@@_macro_internal_bool } , var .code:n = { \bool_set_true:N \l_@@_macro_var_bool } , TF .code:n = { \bool_set_true:N \l_@@_macro_TF_bool } , pTF .code:n = { \bool_set_true:N \l_@@_macro_pTF_bool } , tested .code:n = { } , EXP .code:n = {} , % TODO rEXP .code:n = {} , % TODO added .code:n = {} , % TODO updated .code:n = {} , % TODO } % \end{macrocode} % % \begin{macrocode} \RenewDocumentCommand { \macro } { O{} } { \@@_macro:n {#1} } \cs_new_protected:Npn \@@_macro:n #1 { \int_compare:nNnTF \currentgrouplevel=2 { \int_gzero:N \g_@@_nested_macro_int } { \int_incr:N \g_@@_nested_macro_int } \bool_gset_false:N \l_@@_macro_aux_bool \bool_gset_false:N \l_@@_macro_internal_bool \bool_gset_false:N \l_@@_macro_TF_bool \bool_gset_false:N \l_@@_macro_pTF_bool \bool_gset_false:N \l_@@_macro_var_bool \bool_gset_false:N \l_@@_tested_bool \cs_set_eq:NN \@@_macroname_prefix:n \use:n \cs_set_eq:NN \@@_macroname_suffix: \c_empty_tl \keys_set:nn { l3doc/macro } {#1} \cs_set_eq:NN \testfile \@@_print_testfile:n \peek_meaning_ignore_spaces:NTF \c_group_begin_token { \group_begin: \MakePrivateLetters \char_set_catcode_letter:N \\ \char_set_catcode_ignore:N \ % space \char_set_catcode_ignore:N \^^M \char_set_catcode_ignore:N \^^I \@@_macro_aux:n } { \@@_macro_verbatim:w } } \NewDocumentCommand {\@@_macro_verbatim:w} {v} { \group_begin: % pretty useless \@@_macro_aux:n {#1} } % \end{macrocode} % After changing the catcodes, parse the arguments: % \begin{macrocode} \clist_new:N \l_@@_macro_input_clist \cs_new_nopar:Npn \@@_macro_aux:n #1 { \group_end: \clist_set:Nn \l_@@_macro_input_clist {#1} \bool_if:NTF \l_@@_macro_pTF_bool { \clist_map_inline:Nn \l_@@_macro_input_clist { \exp_args:Nx \@@_macro_single:n { \@@_predicate_from_base:w ##1 \q_nil } } \bool_set_true:N \l_@@_macro_TF_bool \clist_map_function:NN \l_@@_macro_input_clist \@@_macro_single:n \bool_set_false:N \l_@@_macro_TF_bool } { \clist_map_function:NN \l_@@_macro_input_clist \@@_macro_single:n } } % \end{macrocode} % % \end{environment} % % \begin{macrocode} \cs_set:Nn \@@_predicate_from_base:N { \__cs_get_function_name:N #1 _p: \__cs_get_function_signature:N #1 } \cs_set:Npn \@@_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} % \cs{l_@@_at_replaced_macro_tl} stores the macro name after % replacement of |@@|. % \begin{macrocode} \cs_set_nopar:Npn \@@_macro_single:n #1 { \int_incr:N \l_@@_macro_int \tl_set:Nx \l_@@_at_replaced_macro_tl { \token_to_str:N #1 } \@@_replace_at_at:N \l_@@_at_replaced_macro_tl \tl_set_eq:NN \saved@macroname \l_@@_at_replaced_macro_tl \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_@@_macro_aux_bool { \cs_set_eq:NN \@@_macroname_prefix:n \@@_typeset_aux:n } \bool_if:NT \l_@@_macro_TF_bool { \cs_set_eq:NN \@@_macroname_suffix: \@@_typeset_TF: } \bool_if:NF \l_@@_macro_aux_bool { \tl_gset:Nx \l_@@_macro_tl { \tl_to_str:N \l_@@_at_replaced_macro_tl } \exp_args:NNf \tl_greplace_all:Nnn \l_@@_macro_tl {\token_to_str:N _} {/} \exp_args:NNf \tl_greplace_all:Nnn \l_@@_macro_tl {\@backslashchar} {} } \use:x { \exp_not:N \item [ \exp_not:N \@@_print_macroname:n { \tl_to_str:N \l_@@_at_replaced_macro_tl }] } \int_gincr:N \c@CodelineNo \bool_if:NF \l_@@_macro_aux_bool { \bool_if:NTF \l_@@_macro_TF_bool { \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl \tl_to_str:n {TF} } \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl \tl_to_str:n {T } } \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl \tl_to_str:n { F} } } { \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl } } } \bool_if:NTF \l_@@_macro_TF_bool { \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl TF}\nobreak \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl TF} } { \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl }\nobreak \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl } } \int_gdecr:N \c@CodelineNo \ignorespaces } % \end{macrocode} % % \begin{macro}{\@@_print_macroname:n} % \begin{macrocode} \tl_clear:N \l_@@_macro_tl \cs_set_nopar:Npn \@@_print_macroname:n #1 { \strut \HD@target \int_compare:nTF { \tl_count:n {#1} <= 28 } { \MacroFont } { \MacroLongFont } % INEFFICIENT: (!) \exp_args:NNx \seq_if_in:NnTF \g_doc_functions_seq { #1 \bool_if:NT \l_@@_macro_TF_bool { \tl_to_str:n {TF} } } { \hyperref [doc/function//\l_@@_macro_tl] } { \use:n } { \@@_macroname_prefix:n {#1} \@@_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}{\@@_typeset_TF:,\@@_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 \@@_typeset_TF: { \hyperlink{explTF} { \color{black} \itshape TF \makebox[0pt][r] { \color{red} \underline { \phantom{\itshape TF} \kern-0.1em } } } } \cs_set_nopar:Npn \@@_typeset_aux:n #1 { { \color[gray]{0.7} #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_print_testfile:n} % Used to show that a macro has a test, somewhere. % \begin{macrocode} \DeclareDocumentCommand \@@_print_testfile:n {m} { \bool_set_true:N \l_@@_tested_bool \tl_if_eq:nnF {#1} {*} { \seq_if_in:NnF \g_@@_testfiles_seq {#1} { \seq_gput_right:Nn \g_@@_testfiles_seq {#1} \par \@@_print_testfile_aux:n {#1} } } } % \end{macrocode} % Text for displaying: % \begin{macrocode} \cs_new_protected:Npn \@@_print_testfile_aux:n #1 { \footnotesize ( \textit{ The~ test~ suite~ for~ this~ command,~ and~ others~ in~ this~ file,~ is~ \textsf{#1} }. )\par } % \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} % Note: There \cs{l_@@_macro_input_clist} may contain unconverted |@@|. % \begin{macrocode} \cs_generate_variant:Nn \prop_gput:Nnn {NVx} \DeclareDocumentCommand \TestMissing {m} { \prop_if_in:NVTF \g_@@_missing_tests_prop \l_@@_macro_input_clist { \prop_get:NVN \g_@@_missing_tests_prop \l_@@_macro_input_clist \l_@@_tmpa_tl \prop_gput:NVx \g_@@_missing_tests_prop \l_@@_macro_input_clist { *~ \l_@@_tmpa_tl ^^J \exp_not:n {\space\space\space\space\space\space} *~ #1 } } { \prop_gput:NVn \g_@@_missing_tests_prop \l_@@_macro_input_clist {#1} } } % \end{macrocode} % \end{macro} % % \begin{variable}{\g_@@_module_name_tl} % \begin{macro}[internal]{\@@_replace_at_at:N} % \begin{macrocode} \tl_new:N \g_@@_module_name_tl \cs_new_protected:Npn \@@_replace_at_at:N #1 { \tl_if_empty:NF \g_@@_module_name_tl { \tl_replace_all:Non #1 { \token_to_str:N @ } { @ } \tl_replace_all:Non #1 { \token_to_str:N _ } { _ } % \end{macrocode} % To make the search-and-replace work, in the source of l3doc % itself the \verb|@@| search string needs to be protected from % replacement by l3docstrip! This is easy to do by adding a space. % \begin{macrocode} \tl_replace_all:Nox #1 { _@ @ } { __ \g_@@_module_name_tl } \tl_replace_all:Nox #1 { @ @ } { __ \g_@@_module_name_tl } } } \cs_generate_variant:Nn \tl_replace_all:Nnn { Non, Nox } % \end{macrocode} % \end{macro} % \end{variable} % % \begin{macro}{\endmacro} % The \cs{doc_endmacro_wrap_each:N} puts each item of the sequence |#1| % in \cs{texttt} font and with a trailing TF if needed. This should % go inline in the definition of \cs{endmacro}, but somehow the |#| % doesn't go through some \LaTeXe{} internals. % \begin{macrocode} \cs_new_protected:Nn \@@_endmacro_build_seq:N { \seq_gclear:N #1 \clist_map_inline:Nn \l_@@_macro_input_clist { \tl_set:Nn \l_@@_tmpa_tl {##1} \@@_replace_at_at:N \l_@@_tmpa_tl \seq_gput_right:No #1 { \l_@@_tmpa_tl } } } \cs_set_protected:Nn \@@_endmacro_wrap_each:N { \bool_if:NTF \l_@@_macro_TF_bool { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 TF } } } { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 } } } } \cs_set:Nn \@@_texttt_comma:n {\,,~\texttt{#1}} \cs_set:Npn \endmacro { \int_compare:nT { \g_@@_nested_macro_int < 1 } { \par\nobreak\noindent{\footnotesize(\emph{ End~ definition~ for~ \@@_endmacro_build_seq:N \g_@@_tmpa_seq \@@_endmacro_wrap_each:N \g_@@_tmpa_seq \int_compare:nTF { \seq_count:N \g_@@_tmpa_seq <= 3 } { \seq_use:Nnnn \g_@@_tmpa_seq { \,~and~ } { \,,~ } { \,,~and~ } } { \seq_item:Nn \g_@@_tmpa_seq {1}\,~and~others. } \bool_if:nT { !\l_@@_macro_aux_bool && !\l_@@_macro_internal_bool && \int_compare_p:n {\g_@@_nested_macro_int<1} } { \int_compare:nNnTF \l_@@_macro_int=1 {~This~} {~These~} \bool_if:NTF \l_@@_macro_var_bool{variable}{function} \int_compare:nNnTF \l_@@_macro_int=1 {~is~}{s~are~} documented~on~page~ \exp_args:Nx\pageref{doc/function//\l_@@_macro_tl}. } })\par} } \bool_if:nT { \g_@@_checktest_bool && !( \l_@@_macro_aux_bool || \l_@@_macro_var_bool ) && !\l_@@_tested_bool } { \seq_gput_right:Nx \g_@@_not_tested_seq { \seq_use:Nnnn \g_@@_tmpa_seq { , } { , } { , } \bool_if:NT \l_@@_macro_pTF_bool {~(pTF)} \bool_if:NT \l_@@_macro_TF_bool {~(TF)} } } } % \end{macrocode} % \end{macro} % % \begin{environment}{macrocode} % \begin{macro}[aux]{\@@_xmacro_code:n} % Hook into the \texttt{macrocode} environment in a dirty way: % \cs{xmacro@code} is responsible for grabbing (and tokenizing) the % body of the environment. Redefine it to pass what it grabs to % \cs{doc_xparse_code:n}. This new macro replaces all |@@| by the % appropriate module name. One exceptional case is the % |<@@=|\meta{module}|>| lines themselves, where |@@| should not be % modified. Actually, we search for such lines, to set the module % name automatically. We need to be careful: no |<@@=| should appear % as such in the code below since \pkg{l3doc} is also typeset using % this code. % \begin{macrocode} \group_begin: \char_set_catcode_escape:N \/ \char_set_catcode_other:N \^^A \char_set_catcode_active:N \^^S \char_set_catcode_active:N \^^B \char_set_catcode_other:N \^^L \char_set_catcode_other:N \^^R \char_set_lccode:nn { `\^^A } { `\% } \char_set_lccode:nn { `\^^S } { `\ } \char_set_lccode:nn { `\^^B } { `\\ } \char_set_lccode:nn { `\^^L } { `\{ } \char_set_lccode:nn { `\^^R } { `\} } \tl_to_lowercase:n { \group_end: \cs_set_protected:Npn \xmacro@code #1 ^^A ^^S^^S^^S^^S ^^Bend ^^Lmacrocode^^R { \@@_xmacro_code:n {#1} /end{macrocode} } } \group_begin: \char_set_catcode_active:N \< \char_set_catcode_active:N \> \cs_new_protected:Npn \@@_xmacro_code:n #1 { \tl_if_in:nnTF {#1} { < @ @ = } { \@@_xmacro_code:w #1 \q_stop } { \tl_set:Nn \l_@@_tmpa_tl {#1} \@@_replace_at_at:N \l_@@_tmpa_tl \tl_use:N \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_xmacro_code:w #1 < @ @ = #2 > #3 \q_stop { \tl_set:Nn \l_@@_tmpa_tl {#1} \@@_replace_at_at:N \l_@@_tmpa_tl \tl_gset:Nn \g_@@_module_name_tl {#2} \tl_put_right:Nn \l_@@_tmpa_tl { < @ @ = #2 > } \tl_set:Nn \l_@@_tmpb_tl {#3} \@@_replace_at_at:N \l_@@_tmpb_tl \tl_put_right:No \l_@@_tmpa_tl { \l_@@_tmpb_tl } \tl_use:N \l_@@_tmpa_tl } \group_end: % \end{macrocode} % \end{macro} % \end{environment} % % \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 } % \end{macrocode} % % \begin{macrocode} \newcommand*{\Describe@Option}[1] { \endgroup \marginpar{ \raggedleft \PrintDescribeEnv{#1} } \SpecialOptionIndex{#1} \@esphack \ignorespaces } % \end{macrocode} % % \begin{macrocode} \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} \cs_set_nopar:Npn \AlsoImplementation { \bool_set_true:N \g_@@_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_@@_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} \cs_set:Npn \DocInput #1 { \clist_map_inline:nn {#1} { \clist_put_right:Nn \g_docinput_clist {##1} \tl_gclear:N \g_@@_module_name_tl \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 \tl_gclear:N \g_@@_module_name_tl \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 \int_use:N \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:~\ExplFileDate\ % space Version~\ExplFileVersion \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} \iow_new:N \g_@@_func_iow % \end{macrocode} % % \begin{macrocode} \cs_new_nopar:Npn \@@_show_functions_defined: { \bool_if:nT { \g_@@_implementation_bool && \g_@@_checkfunc_bool } { \typeout{ ======================================== ^^J } \iow_open:Nn \g_@@_func_iow { \c_job_name_tl .cmds } \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_@@_func_iow { > ~ ##1 } } } \@@_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 } \iow_now:Nn \g_@@_func_iow { ! ~ ##1} } } \@@_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 } \iow_now:Nn \g_@@_func_iow { ? ~ ##1} } } \@@_functions_typeout:n { Functions~defined~but~not~documented: } \iow_close:N \g_@@_func_iow \typeout{ ======================================== } } } \AtEndDocument{ \@@_show_functions_defined: } % \end{macrocode} % % \begin{macrocode} \cs_set_nopar:Npn \@@_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 \@@_show_not_tested: { \bool_if:NT \g_@@_checktest_bool { \bool_if:nT { !(\seq_if_empty_p:N \g_@@_not_tested_seq) || !(\prop_if_empty_p:N \g_@@_missing_tests_prop) } { \tl_clear:N \l_@@_tmpa_tl \prop_if_empty:NF \g_@@_missing_tests_prop { \tl_put_right:Nn \l_@@_tmpa_tl { ^^J^^JThe~ following~ macro(s)~ have~ incomplete~ tests:^^J } \prop_map_inline:Nn \g_@@_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_@@_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_@@_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{ \@@_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}{\@@_special_main_index:n,\@@_special_main_index:o, \@@_special_main_index:x} % Heiko's replacement to play nicely with |hypdoc|: % \begin{macrocode} \cs_set_nopar:Npn \@@_special_main_index:n #1 { \HD@target \index { \@gobble#1 \actualchar \string\verb\quotechar*\verbatimchar#1\verbatimchar \encapchar hdclindex{\the\c@HD@hypercount}{usage} } } \cs_generate_variant:Nn \@@_special_main_index:n { o , x } % \end{macrocode} % \end{macro} % % \begin{macrocode} \msg_new:nnn {l3doc} {print-index-howto} { Generate~the~index~by~executing\\ \iow_indent:n { makeindex~-s~l3doc.ist~-o~\c_job_name_tl .ind~\c_job_name_tl .idx } } \tl_gput_right:Nn \PrintIndex { \AtEndDocument{ \msg_info:nn {l3doc} {print-index-howto} } } % \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} \msg_new:nnn {l3doc} {print-changes-howto} { Generate~the~change~list~by~executing\\ \iow_indent:n { makeindex~-s~gglo.ist~-o~\c_job_name_tl .gls~\c_job_name_tl .glo } } \tl_gput_right:Nn \PrintChanges { \AtEndDocument{ \msg_info:nn {l3doc} {print-changes-howto} } } % \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{Default configuration} % % \begin{macrocode} \bool_if:NTF \g_@@_full_bool { \RecordChanges \CodelineIndex \EnableCrossrefs \AlsoImplementation } { \CodelineNumbered \DisableCrossrefs \OnlyDescription } % \end{macrocode} % % % \begin{macrocode} % % \end{macrocode} % % \subsection{Internal macros for \LaTeX3 sources} % % These definitions are only used by the \LaTeX3 documentation; % they are not necessary for third-party users of l3doc. % In time this will be broken into a separate package that is specifically % loaded in the various expl3 modules, etc. % % \begin{macrocode} %<*cfg> % \end{macrocode} % % The Guilty Parties. % \begin{macrocode} \tl_new:N \Team \tl_set:Nn \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,~Bruno~Le~Floch } } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand{\ExplMakeTitle}{mm} { \title { The~\pkg{#1}~package \\ #2 \thanks { This~file~describes~v\ExplFileVersion,~ last~revised~\ExplFileDate. } } \author { The~\LaTeX3~Project\thanks{E-mail:~ \href{mailto:latex-l@listserv.uni-heidelberg.de} {latex-l@listserv.uni-heidelberg.de}} } \date{Released~\ExplFileDate} \maketitle } % \end{macrocode} % % \subsection{Text extras} % % \begin{macrocode} \DeclareDocumentCommand\ie{}{\emph{i.e.}} \DeclareDocumentCommand\eg{}{\emph{e.g.}} \DeclareDocumentCommand\Ie{}{\emph{I.e.}} \DeclareDocumentCommand\Eg{}{\emph{E.g.}} % \end{macrocode} % % \subsection{Math extras} % % For \pkg{l3fp}. % % \begin{macrocode} \AtBeginDocument { \clist_map_inline:nn { asin, acos, atan, acot, asinh, acosh, atanh, acoth, round, floor, ceil } { \exp_args:Nc \DeclareMathOperator{#1}{#1} } } % \end{macrocode} % % \begin{macro}{\nan} % \begin{macrocode} \NewDocumentCommand { \nan } { } { \text { \texttt { nan } } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \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" % % \end{macrocode} % % \section{Testing} % % \begin{function}{foo} % \begin{syntax} % "\foo" \Arg{something_1} % \end{syntax} % Does with % \end{function} % % \begin{function}{.bool_set:N} % blah % \end{function} % % \ExplSyntaxOn \cs_set_eq:NN \c_alignment_token @ \ExplSyntaxOff % \begin{variabledoc} % { % \c_alignment_token, % } % \end{variabledoc} % \ExplSyntaxOn \cs_set_eq:NN \c_alignment_token & \ExplSyntaxOff % % \begin{function}[added=2011-09-06]{\example_foo:N,\example_foo:c} % \begin{syntax} % "\example_foo:N" % "\example_foo:c" \Arg{arg_1} % \end{syntax} % <0123456789> % \end{function} % % \begin{function}[added=2011-09-06]{ \foo , \fooo: , \foooo:n , \foooo:x , \fooooo:n , \fooooo:c , \fooooo:x } % \begin{syntax} % "\example_foo:N" % \end{syntax} % <0123456789> % \end{function} % % \begin{function}[TF]{\foo:N , \foo_if:c } % Test. % \end{function} % \begin{function}[TF,EXP]{\foo:N , \foo_if:c } % Test. % \end{function} % % \begin{function}[added=2011-09-06,EXP]{\fffoo:N} % Test. % \end{function} % \begin{function}[added=2011-09-06,updated=2011-09-07,EXP]{\fffoo:N} % Test. % \end{function} % \begin{function}[updated=2011-09-06,EXP]{\fffoo:N} % Test. % \end{function} % \begin{function}[TF]{\ffffoo:N} % Test. % \end{function} % \begin{function}[pTF]{\ffoo:N} % \lipsum[6] % \end{function} % \begin{function}[pTF]{\ffoo:N,\ffoo:c,\ffoo:V} % \lipsum[6] % \end{function} % \begin{function}[pTF]{\ffoo:N,\ffoo:c} % \lipsum[6] % \end{function} % % % \begin{function}[TF]{\ffffoo_with_very_very_very_long_name:N} % \lipsum[1] % \end{function} % % \begin{function}[TF]{\ffffoo_with_very_very_very_long_name:N,\ffffoo_with_very_very_very_long_name:c,\ffffoo_with_very_very_very_long_name:V} % \lipsum[1] % \end{function} % % \begin{function}[TF]{\ffffoo_with_very_very_very_long_name:N,\ffffoo_with_very_very_very_long_name:c,\ffffoo_with_very_very_very_long_name:V} % \begin{syntax} % this is how you use it % \end{syntax} % \lipsum[1] % \end{function} % % \begin{function}[TF]{\ffffoo_with_very_very_very_long_name:N,\ffffoo_with_very_very_very_long_name:V} % \begin{syntax} % this is how you use it % \end{syntax} % \lipsum[1] % \end{function} % % \bigskip\bigskip % % \begin{macro}[aux]{ \foo_aux: } % Testing `aux' option. % \end{macro} % % \begin{macro}[TF]{ \foo_if:c } % Testing `TF' option. % \end{macro} % \begin{macro}[TF]{ \foo_if:c, \fooo_if:n } % Testing `TF' option. % \end{macro} % % \begin{macro}[pTF]{ \foo_if:d } % Testing `pTF' option. % \end{macro} % % \begin{macro}[internal]{ \test_internal: } % Testing `internal' option. % \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{function}{\::N} % this is (no longer) weird % \end{function} % % \begin{macro}{\::N} % this is (no longer) weird % \end{macro} % % % % \begin{function}[EXP]{\foo}\end{function} % \begin{function}[rEXP]{\foo}\end{function} % % here is some verbatim text: % \begin{verbatim} % a & B # c % \end{verbatim} % without overriding this with fancyvrb there would be extraneous whitespace. % % \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} % % % % % \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