% \iffalse meta-comment % %% File: l3doc.dtx Copyright (C) 1990-2011 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 "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 LaTeX3 Project. %% %% ----------------------------------------------------------------------- % %<*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|class> \RequirePackage{l3names} % % % 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> \GetIdInfo$Id: l3doc.dtx 2601 2011-08-16 23:20:27Z bruno $ {L3 Experimental documentation class} % % %<*driver> \ProvidesFile{\ExplFileName.dtx} [\ExplFileDate\space v\ExplFileVersion\space\ExplFileDescription] \documentclass{l3doc} \usepackage{framed} \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} \RequirePackage{expl3,xparse} \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 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{framed} % \vspace{-\baselineskip} % \begin{verbatim} % \begin{function}{ list_of , functions } % \begin{syntax} % "\foo_bar:" \Arg{meta} % \end{syntax} % % \end{function} % \end{verbatim} % \vspace{-2\baselineskip} % \hrulefill % \begin{function}{ list_of , functions } % \begin{syntax} % "\foo_bar:" \Arg{meta} % \end{syntax} % % \end{function} % \end{framed} % % Function environments take an optional argument to indicate whether the function(s) it % describes are expandable or defined in conditional forms. Use "EXP", "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} % \vspace{-2\baselineskip} % \hrulefill % \begin{function}[pTF]{ \cs_if_exist:N } % \begin{syntax} % "\cs_if_exist_p:N" % \end{syntax} % % \end{function} % \end{framed} % % Note that the list of functions used to use "|" as a separator instead, % and this syntax is still supported. % % In the old syntax, individual functions could be suffixed by an optional flag or % two to indicate the same information given in the optional argument. % This is still supported; use "/" to separate the function name % from the flag(s) and then add any of "(EXP)", "(TF)", or "(pTF)". % % \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} % % \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,csquotes} % \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 \expandafter\let\csname doc@verbatim*\expandafter\endcsname \csname verbatim*\endcsname \expandafter\let\csname enddoc@verbatim*\expandafter\endcsname \csname endverbatim*\endcsname \expandafter\let\csname doc@@verbatim*\expandafter\endcsname \csname @verbatim*\endcsname \RequirePackage{verbatim} \AtBeginDocument{% \let\verbatim\doc@verbatim \let\endverbatim\enddoc@verbatim \let\@verbatim\doc@@verbatim \expandafter\let\csname verbatim*\expandafter\endcsname \csname doc@verbatim*\endcsname \expandafter\let\csname endverbatim*\expandafter\endcsname \csname enddoc@verbatim*\endcsname \expandafter\let\csname @verbatim*\expandafter\endcsname \csname doc@@verbatim*\endcsname } % \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} \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} \char_set_catcode_active:N \< \DeclareDocumentCommand \function { O{} } { \phantomsection \bool_gset_false:N \l_doc_meta_TF_bool \bool_gset_false:N \l_doc_meta_pTF_bool \bool_gset_false:N \l_doc_meta_EXP_bool \cs_set_nopar:Npn \KV_key_no_value_elt:n ##1 { \use:c {doc_meta_opt_##1:} } \keyval_parse:NNn \KV_key_no_value_elt:n \use_none:nn {#1} \char_set_catcode_active:N \< \cs_set_eq:NN < \doc_open_meta:n \group_begin: \MakePrivateLetters \char_set_catcode_other:N \| \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 \function_aux:n } \char_set_catcode_other:N \< \cs_set_eq:NN \variabledoc \function % \end{macrocode} % % \begin{macrocode} \cs_set:Nn \doc_meta_opt_TF: { \bool_gset_true:N \l_doc_meta_TF_bool } \cs_set:Nn \doc_meta_opt_EXP: { \bool_gset_true:N \l_doc_meta_EXP_bool } \cs_set:Nn \doc_meta_opt_pTF: { \bool_gset_true:N \l_doc_meta_pTF_bool \bool_gset_true:N \l_doc_meta_TF_bool \bool_gset_true:N \l_doc_meta_EXP_bool } % \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_set_catcode_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_set_catcode_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:nnT {#2} { (TF) } { \bool_gset_true:N \l_doc_meta_TF_bool } \tl_if_in:nnT {#2} { (EXP) } { \bool_gset_true:N \l_doc_meta_EXP_bool } \tl_if_in:nnT {#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 } \bool_if:NT \l_doc_meta_pTF_bool { \tl_set:Nx \l_doc_pTF_name_tl { \doc_predicate_from_base:w #1 \q_nil } \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:Nnn \g_doc_macro_tl {\token_to_str:N _} {/} \exp_args:NNf \tl_replace_all: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_set_catcode_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_set_catcode_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_internal_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:} } \keyval_parse:NNn \KV_key_no_value_elt:n \use_none:nn {#1} \cs_set_eq:NN \testfile \doc_print_testfile:n \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 \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} { \tl_if_blank:nF {##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} { \tl_if_blank:nF {##1} { \doc_macro_single {##1} } } \bool_set_false:N \l_doc_macro_TF_bool } { \clist_map_inline:nn {#1} { \tl_if_blank:nF {##1} { \doc_macro_single {##1} } } } } % \end{macrocode} % % \begin{macrocode} \bool_new:N \l_doc_macro_internal_bool \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_internal: { \bool_set_true:N \l_doc_macro_internal_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:Nnn \l_doc_macro_tl {\token_to_str:N _} {/} \exp_args:NNf \tl_greplace_all: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} % % \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 && !\l_doc_macro_internal_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:~\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} \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} % % \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} %\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" % \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" % \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}[EXP]{\fffoo:N} % Test. % \end{function} % \begin{function}[TF]{\ffffoo:N} % Test. % \end{function} % \begin{function}[pTF]{\ffoo:N} % Test. % \end{function} % % \begin{function}{ \bar / (EXP) | \bar: / (EXP) | \bar:x / (EXP) | } % \begin{syntax} % "\example_foo:N" % \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} % % \begin{macro}[internal]{ \foo_if:d } % 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