% \iffalse % %% File l3dosctrip.dtx % % Copyright (C) 2012,2014-2020 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 % % https://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 development version of the bundle can be found at % % https://github.com/latex3/latex3 % % for those people who are interested. % %<*driver|program> % %<*driver> % The same approach as used in \textsf{DocStrip}: if \cs{documentclass} % is undefined then skip the driver, allowing the file to be used to extract % \texttt{l3docstrip.tex} from \texttt{l3docstrip.dtx} directly. This works % as the \cs{fi} is only seen if \LaTeX{} is not in use. The odd \cs{jobname} % business allows the extraction to work with \LaTeX{} provided an appropriate % \texttt{.ins} file is set up. %<*gobble> \ifx\jobname\relax\let\documentclass\undefined\fi \ifx\documentclass\undefined \else \csname fi\endcsname % \def\filename{docstrip.dtx} \documentclass[full,kernel]{l3doc} \ExplSyntaxOn \cs_set_eq:NN \__codedoc_replace_at_at:N \use_none:n \ExplSyntaxOff \begin{document} \DocInput{\jobname.dtx} \end{document} %<*gobble> \fi % % % \fi % % \title{^^A % The \pkg{l3docstrip} package\\ Code extraction and manipulation^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released 2020-06-18} % % \maketitle % % \begin{documentation} % % \section{Extending \textsf{DocStrip}} % % The \pkg{l3docstrip} module adds \LaTeX3 extensions to the \textsf{DocStrip} % program for extracting code from \texttt{.dtx}. As such, this documentation % should be read along with that for \textsf{DocStrip}. % % \section{Internal functions and variables} % % An important consideration for \LaTeX3 development is separating out public % and internal functions. Functions and variables which are private to one % module should not be used or modified by any other module. As \TeX{} does % not have any formal namespacing system, this requires a convention for % indicating which functions in a code-level module are public and which are % private. % % Using \pkg{l3docstrip} allows internal functions to be indicated using a % \enquote{two part} system. Within the \texttt{.dtx} file, internal functions % may be indicated using |@@| in place of the module name, for example % \begin{verbatim} % \cs_new_protected:Npn \@@_some_function:nn #1#2 % { % % Some code here % } % \tl_new:N \l_@@_internal_tl % \end{verbatim} % % To extract the code using \pkg{l3docstrip}, the \enquote{guard} concept % used by \textsf{DocStrip} is extended by introduction of the syntax % \texttt{\%<@@=\meta{module}>}. The \meta{module} name then replaces % the |@@| when the code is extracted, so that % \begin{verbatim} % %<*package> % %<@@=foo> % \cs_new_protected:Npn \@@_some_function:nn #1#2 % { % % Some code here % } % \tl_new:N \l_@@_internal_tl % % % \end{verbatim} % is extracted as % \begin{verbatim} % \cs_new_protected:Npn \__foo_some_function:nn #1#2 % { % % Some code here % } % \tl_new:N \l__foo_internal_tl % \end{verbatim} % where the |__| indicates that the functions and variables are internal % to the \texttt{foo} module. % % Use |@@@@| to obtain |@@| in the output (|@@@@@| to get |@@@|). For % longer pieces of code the replacement can be completely suppressed by % giving an empty module name, namely using the syntax \texttt{\%<@@=>}. % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3docstrip} implementation} % % \begin{macrocode} %<*program> % \end{macrocode} % % We start by loading the existing \textsf{DocStrip} code using the \TeX{} % input convention. % \begin{macrocode} \input docstrip % % \end{macrocode} % % \begin{macro}{\checkOption} % The \cs{checkOption} macro is defined by \textsf{DocStrip} and is redefined % here to accommodate the new \texttt{\%<@} syntax. % % When the macros that process a line have found that the line starts with % \enquote{\texttt{\%<}}, a guard line has been encountered. The first % character of a guard can be an asterisk (\texttt{*}), a slash (\texttt{/}), % a plus (\texttt{+}), a minus (\texttt{-}), a less-than sign (\texttt{<}) % starting verbatim mode, a commercial at (\texttt{@}) or any other character % that can be found in an option name. This means that we have to peek at the % next token and decide what kind of guard we have. We reinsert |#1| as it % may be needed by \cs{doOption}. % \begin{macrocode} \def\checkOption<#1{% \ifcase \ifx*#10\else \ifx/#11\else \ifx+#12\else \ifx-#13\else \ifx<#14\else \ifx @#15\else 6\fi\fi\fi\fi\fi\fi\relax \expandafter\starOption\or \expandafter\slashOption\or \expandafter\plusOption\or \expandafter\minusOption\or \expandafter\verbOption\or \expandafter\moduleOption\or \expandafter\doOption\fi #1% } % \end{macrocode} % \end{macro} % % \begin{macro}{\moduleOption} % In the case where the line starts |%<@|: the defined syntax requires that % this continues to |%<@@=|. At the moment, we assume that the syntax is % correct and |#1| here is the module name for substitution into any % internal functions in the extracted material. % \begin{macrocode} \def\moduleOption @@=#1>#2\endLine{% \maybeMsg{<@@=#1>}% \prepareActiveModule{#1}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\prepareActiveModule} % \begin{macro}{\replaceModuleInLine} % Here, we set up to do the search-and-replace when doing the extraction. % The argument (|#1|) is the replacement text to use, or if empty an % indicator that no replacement should be done. The search material is % one of |__@@|, |_@@| or |@@|, done in order such that all three end % up the same in the output. The string |@@@@| is hidden from these % replacements by temporarily turning it into a pair of letters with % different category codes, not produced by \pkg{docstrip}; this allows to % get |@@| in the output. The replacement function is initialised as a % do-nothing for the case where |%<@@=| is never seen. % \begin{macrocode} \begingroup \catcode`\_ = 12 % \long\gdef\prepareActiveModule#1{% \ifx\relax#1\relax \let\replaceModuleInLine\empty \else \edef\replaceModuleInLine{% \noexpand\replaceAllIn\noexpand\inLine{@@@@}{\string aa}% \noexpand\replaceAllIn\noexpand\inLine{__@@}{__#1}% \noexpand\replaceAllIn\noexpand\inLine{_@@}{__#1}% \noexpand\replaceAllIn\noexpand\inLine{@@}{__#1}% \noexpand\replaceAllIn\noexpand\inLine{\string aa}{@@}% }% \fi } \endgroup \let\replaceModuleInLine\empty % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\replaceAllIn} % \begin{macro}{\replaceAllInAuxI} % \begin{macro}{\replaceAllInAuxII} % \begin{macro}{\replaceAllInAuxIII} % The code here is a simple search-and-replace routine for a macro |#1|, % replacing |#2| by |#3|. As set up here, there is an assumption that nothing % is going to be expandable, which is reasonable as \pkg{l3docstrip} deals % with \enquote{string} material. % \begin{macrocode} \long\def\replaceAllIn#1#2#3{% \long\def\tempa##1##2#2{% ##2\qMark\replaceAllInAuxIII#3##1% }% \edef#1{\expandafter\replaceAllInAuxI#1\qMark#2\qStop}% } \def\replaceAllInAuxI{% \expandafter\replaceAllInAuxII\tempa\replaceAllInAuxI\empty } \long\def\replaceAllInAuxII#1\qMark#2{#1} \long\def\replaceAllInAuxIII#1\qStop{} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\normalLine} % The \cs{normalLine} macro is present in \textsf{DocStrip} but is modified % here to include the search-and-replace macro \cs{replaceModuleInLine}. The % macro \cs{normalLine} writes its argument (which has to be delimited with % |\endLine|) on all active output files, i.e.~those with off-counters equal % to zero. The counter \cs{codeLinesPassed} is incremented by~$1$ for % statistics (the guards for this used in \textsf{DocStrip} are retained). % \begin{macrocode} \def\normalLine#1\endLine{% %<*stats> \advance\codeLinesPassed\@ne % \maybeMsg{.}% \def\inLine{#1}% \replaceModuleInLine \let\do\putline@do \activefiles } % \end{macrocode} % \end{macro} % % \begin{macro}{\doOption} % As \textsf{DocStrip} processes each line, a line starting with |%<| triggers (via \cs{checkOption} above) a look-ahead to establish the type of guard encountered. % Of the branching possibilities, if we ignore the deprecated |+| and |-| and choose to do no replacement for the special verbatim mode, the only branch that we need to alter is that for a single-line guard such as\\ | % ...stats-only code to include...|. % The original definition of \cs{doOption} did not use \cs{inLine} but I believe we're safe to do so. % \begin{macrocode} \def\doOption#1>#2\endLine{% \maybeMsg{<#1 . >}% \Evaluate{#1}% \def\do##1##2##3{% \if1\Expr{##2}% \def\inLine{#2}% \replaceModuleInLine \StreamPut##1{\inLine}% \fi }% \activefiles } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintIndex