From 6ac3dbed4b71022bd6bb0cc25e8fc3df81198498 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Wed, 1 May 2024 03:00:54 +0000 Subject: CTAN sync 202405010300 --- macros/latex/contrib/l3kernel/l3quark.dtx | 1008 ----------------------------- 1 file changed, 1008 deletions(-) delete mode 100644 macros/latex/contrib/l3kernel/l3quark.dtx (limited to 'macros/latex/contrib/l3kernel/l3quark.dtx') diff --git a/macros/latex/contrib/l3kernel/l3quark.dtx b/macros/latex/contrib/l3kernel/l3quark.dtx deleted file mode 100644 index 000063bc00..0000000000 --- a/macros/latex/contrib/l3kernel/l3quark.dtx +++ /dev/null @@ -1,1008 +0,0 @@ -% \iffalse meta-comment -% -%% File: l3quark.dtx -% -% Copyright (C) 1990-2024 The LaTeX 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> -\documentclass[full,kernel]{l3doc} -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -% -% \fi -% -% \title{^^A -% The \pkg{l3quark} module\\ Quarks and scan marks^^A -% } -% -% \author{^^A -% The \LaTeX{} Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } -% -% \date{Released 2024-03-14} -% -% \maketitle -% -% \begin{documentation} -% -% Two special types of constants in \LaTeX3 are \enquote{quarks} and -% \enquote{scan marks}. By convention all constants of type quark -% start out with |\q_|, and scan marks start with |\s_|. -% -% \section{Quarks} -% -% Quarks are control sequences (and in fact, token lists) that expand -% to themselves and should -% therefore \emph{never} be executed directly in the code. -% This would result in an endless loop! -% -% They are meant to be used as delimiter in weird functions, the most -% common use case being the `stop token' (\emph{i.e.}~\cs{q_stop}). -% For example, when writing a macro to parse a user-defined date -% \begin{verbatim} -% \date_parse:n {19/June/1981} -% \end{verbatim} -% one might write a command such as -% \begin{verbatim} -% \cs_new:Npn \date_parse:n #1 { \date_parse_aux:w #1 \q_stop } -% \cs_new:Npn \date_parse_aux:w #1 / #2 / #3 \q_stop -% { } -% \end{verbatim} -% -% Quarks are sometimes also used as error return values for functions -% that receive erroneous input. -% For example, in the function \cs{prop_get:NnN} to retrieve a value stored -% in some key of a property list, if the key does not exist then the return value -% is the quark \cs{q_no_value}. -% As mentioned above, such quarks are extremely fragile and it is imperative -% when using such functions that code is carefully written to check for -% pathological cases to avoid leakage of a quark into an uncontrolled -% environment. -% -% Quarks also permit the -% following ingenious trick when parsing tokens: -% when you pick up a token in a temporary variable -% and you want to know whether you have picked up a particular quark, -% all you have to do is compare the temporary variable to the quark using -% \cs{tl_if_eq:NNTF}. A set of special quark testing functions is set up -% below. All the quark testing functions are expandable although the -% ones testing only single tokens are much faster. -% -% \section{Defining quarks} -% -% \begin{function}{\quark_new:N} -% \begin{syntax} -% \cs{quark_new:N} \meta{quark} -% \end{syntax} -% Creates a new \meta{quark} which expands only to \meta{quark}. -% The \meta{quark} is defined globally, and an error message -% is raised if the name was already taken. -% \end{function} -% -% \begin{variable}{\q_stop} -% Used as a marker for delimited arguments, such as -% \begin{verbatim} -% \cs_set:Npn \tmp:w #1#2 \q_stop {#1} -% \end{verbatim} -% \end{variable} -% -% \begin{variable}{\q_mark} -% Used as a marker for delimited arguments when \cs{q_stop} is -% already in use. -% \end{variable} -% -% \begin{variable}{\q_nil} -% Quark to mark a null value in structured variables or functions. Used -% as an end delimiter when this may itself need to be tested -% (in contrast to \cs{q_stop}, which is only ever used as a delimiter). -% \end{variable} -% -% \begin{variable}{\q_no_value} -% A canonical value for a missing value, when one is requested from -% a data structure. This is therefore used as a \enquote{return} value -% by functions such as \cs{prop_get:NnN} if there is no data to -% return. -% \end{variable} -% -% \section{Quark tests} -% -% The method used to define quarks means that the single token (\texttt{N}) -% tests are faster than the multi-token (\texttt{n}) tests. The latter -% should therefore only be used when the argument can definitely take -% more than a single token. -% -% \begin{function}[EXP,pTF]{\quark_if_nil:N} -% \begin{syntax} -% \cs{quark_if_nil_p:N} \meta{token} -% \cs{quark_if_nil:NTF} \meta{token} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{token} is equal to \cs{q_nil}. -% \end{function} -% -% \begin{function}[EXP,pTF]{\quark_if_nil:n, \quark_if_nil:o, \quark_if_nil:V} -% \begin{syntax} -% \cs{quark_if_nil_p:n} \Arg{token list} \\ -% \cs{quark_if_nil:nTF} \Arg{token list} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{token list} contains only \cs{q_nil} (distinct -% from \meta{token list} being empty or containing \cs{q_nil} plus one -% or more other tokens). -% \end{function} -% -% \begin{function}[EXP,pTF]{\quark_if_no_value:N, \quark_if_no_value:c} -% \begin{syntax} -% \cs{quark_if_no_value_p:N} \meta{token} \\ -% \cs{quark_if_no_value:NTF} \meta{token} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{token} is equal to \cs{q_no_value}. -% \end{function} -% -% \begin{function}[EXP,pTF]{\quark_if_no_value:n} -% \begin{syntax} -% \cs{quark_if_no_value_p:n} \Arg{token list} \\ -% \cs{quark_if_no_value:nTF} \Arg{token list} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{token list} contains only \cs{q_no_value} -% (distinct from \meta{token list} being empty or containing -% \cs{q_no_value} plus one or more other tokens). -% \end{function} -% -% \section{Recursion} -% -% This module provides a uniform interface to intercepting and -% terminating loops as when one is doing tail recursion. The building -% blocks follow below and an example is shown in -% Section~\ref{sec:l3quark:quark-example}. -% -% \begin{variable}{\q_recursion_tail} -% This quark is appended to the data structure in question and -% appears as a real element there. This means it gets any list -% separators around it. -% \end{variable} -% -% \begin{variable}{\q_recursion_stop} -% This quark is added \emph{after} the data structure. Its purpose -% is to make it possible to terminate the recursion at any point -% easily. -% \end{variable} -% -% \begin{function}[EXP]{\quark_if_recursion_tail_stop:N} -% \begin{syntax} -% \cs{quark_if_recursion_tail_stop:N} \meta{token} -% \end{syntax} -% Tests if \meta{token} contains only the marker -% \cs{q_recursion_tail}, and if so uses -% \cs{use_none_delimit_by_q_recursion_stop:w} to terminate the -% recursion that this belongs to. The -% recursion input must include the marker tokens \cs{q_recursion_tail} -% and \cs{q_recursion_stop} as the last two items. -% \end{function} -% -% \begin{function}[EXP,updated = 2011-09-06] -% {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o} -% \begin{syntax} -% \cs{quark_if_recursion_tail_stop:n} \Arg{token list} -% \end{syntax} -% Tests if the \meta{token list} contains only -% \cs{q_recursion_tail}, and if so uses -% \cs{use_none_delimit_by_q_recursion_stop:w} to terminate the -% recursion that this belongs to. The -% recursion input must include the marker tokens \cs{q_recursion_tail} -% and \cs{q_recursion_stop} as the last two items. -% \end{function} -% -% \begin{function}[EXP]{\quark_if_recursion_tail_stop_do:Nn} -% \begin{syntax} -% \cs{quark_if_recursion_tail_stop_do:Nn} \meta{token} \Arg{insertion} -% \end{syntax} -% Tests if \meta{token} contains only the marker -% \cs{q_recursion_tail}, and if so uses -% \cs{use_i_delimit_by_q_recursion_stop:w} to terminate the -% recursion that this belongs to. The -% recursion input must include the marker tokens \cs{q_recursion_tail} -% and \cs{q_recursion_stop} as the last two items. The \meta{insertion} -% code is then added to the input stream after the recursion has -% ended. -% \end{function} -% -% \begin{function}[EXP,updated = 2011-09-06] -% {\quark_if_recursion_tail_stop_do:nn, \quark_if_recursion_tail_stop_do:on} -% \begin{syntax} -% \cs{quark_if_recursion_tail_stop_do:nn} \Arg{token list} \Arg{insertion} -% \end{syntax} -% Tests if the \meta{token list} contains only -% \cs{q_recursion_tail}, and if so uses -% \cs{use_i_delimit_by_q_recursion_stop:w} to terminate the -% recursion that this belongs to. The -% recursion input must include the marker tokens \cs{q_recursion_tail} -% and \cs{q_recursion_stop} as the last two items. The \meta{insertion} -% code is then added to the input stream after the recursion has -% ended. -% \end{function} -% -% -% \begin{function}[EXP,added = 2018-04-10] -% { -% \quark_if_recursion_tail_break:NN, -% \quark_if_recursion_tail_break:nN -% } -% \begin{syntax} -% \cs{quark_if_recursion_tail_break:nN} \Arg{token list} \cs[no-index]{\meta{type}_map_break:} -% \end{syntax} -% Tests if \meta{token list} contains only \cs{q_recursion_tail}, and -% if so terminates the recursion using \cs[no-index]{\meta{type}_map_break:}. -% The recursion end should be marked by \cs{prg_break_point:Nn} -% \cs[no-index]{\meta{type}_map_break:}. -% \end{function} -% -% \subsection{An example of recursion with quarks} -% \label{sec:l3quark:quark-example} -% -% Quarks are mainly used internally in the \pkg{expl3} code to define -% recursion functions such as \cs{tl_map_inline:nn} and so on. -% Here is a small example to demonstrate how to use quarks in this fashion. -% We shall define a command called |\my_map_dbl:nn| which takes a token list -% and applies an operation to every \emph{pair} of tokens. -% For example, |\my_map_dbl:nn {abcd} {[--#1--#2--]~}| would produce -% \enquote{\ttfamily [--a--b--]~[--c--d--]~}. -% Using quarks to define such functions simplifies their logic and ensures -% robustness in many cases. -% -% -% Here's the definition of |\my_map_dbl:nn|. -% First of all, define the function that does the processing based on the -% inline function argument |#2|. -% Then initiate the recursion using an internal function. -% The token list |#1| is terminated using \cs{q_recursion_tail}, with -% delimiters according to the type of recursion (here a pair of -% \cs{q_recursion_tail}), concluding with \cs{q_recursion_stop}. -% These quarks are used to mark the end of the token list being operated upon. -%\begin{verbatim} -% \cs_new:Npn \my_map_dbl:nn #1#2 -% { -% \cs_set:Npn \__my_map_dbl_fn:nn ##1 ##2 {#2} -% \__my_map_dbl:nn #1 \q_recursion_tail \q_recursion_tail -% \q_recursion_stop -% } -%\end{verbatim} -% -% The definition of the internal recursion function follows. -% First check if either of the input tokens are the termination quarks. -% Then, if not, apply the inline function to the two arguments. -%\begin{verbatim} -% \cs_new:Nn \__my_map_dbl:nn -% { -% \quark_if_recursion_tail_stop:n {#1} -% \quark_if_recursion_tail_stop:n {#2} -% \__my_map_dbl_fn:nn {#1} {#2} -%\end{verbatim} -% Finally, recurse: -%\begin{verbatim} -% \__my_map_dbl:nn -% } -%\end{verbatim} -% Note that contrarily to \LaTeX3 built-in mapping functions, this -% mapping function cannot be nested, since the second map would overwrite -% the definition of |\__my_map_dbl_fn:nn|. -% -% \section{Scan marks} -% -% Scan marks are control sequences set equal to \cs{scan_stop:}, -% hence never expand in an expansion context and are (largely) -% invisible if they are encountered in a typesetting context. -% -% Like quarks, they can be used as delimiters in weird functions -% and are often safer to use for this purpose. -% Since they are harmless when executed by \TeX{} in non-expandable -% contexts, they can be used to mark the end of a set of instructions. -% This allows to skip to that point if the end of the instructions -% should not be performed (see \pkg{l3regex}). -% -% \begin{function}[added = 2018-04-01]{\scan_new:N} -% \begin{syntax} -% \cs{scan_new:N} \meta{scan mark} -% \end{syntax} -% Creates a new \meta{scan mark} which is set equal to \cs{scan_stop:}. -% The \meta{scan mark} is defined globally, and an error message -% is raised if the name was already taken by another scan mark. -% \end{function} -% -% \begin{variable}[added = 2018-04-01]{\s_stop} -% Used at the end of a set of instructions, as a marker -% that can be jumped to using \cs{use_none_delimit_by_s_stop:w}. -% \end{variable} -% -% \begin{function}[EXP,added = 2018-04-01]{\use_none_delimit_by_s_stop:w} -% \begin{syntax} -% \cs{use_none_delimit_by_s_stop:w} \meta{tokens} \cs{s_stop} -% \end{syntax} -% Removes the \meta{tokens} and \cs{s_stop} from the input stream. -% This leads to a low-level \TeX{} error if \cs{s_stop} is absent. -% \end{function} -% -% \end{documentation} -% -% \begin{implementation} -% -% \section{\pkg{l3quark} implementation} -% -% \TestFiles{m3quark001.lvt} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% \subsection{Quarks} -% -% \begin{macrocode} -%<@@=quark> -% \end{macrocode} -% -% \begin{macro}{\quark_new:N} -% \UnitTested -% Allocate a new quark. -% \begin{macrocode} -\cs_new_protected:Npn \quark_new:N #1 - { - \__kernel_chk_if_free_cs:N #1 - \cs_gset_nopar:Npn #1 {#1} - } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\q_nil, \q_mark, \q_no_value, \q_stop} -% Some \enquote{public} quarks. \cs{q_stop} is an \enquote{end of -% argument} marker, \cs{q_nil} is a empty value and \cs{q_no_value} -% marks an empty argument. -% \begin{macrocode} -\quark_new:N \q_nil -\quark_new:N \q_mark -\quark_new:N \q_no_value -\quark_new:N \q_stop -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\q_recursion_tail, \q_recursion_stop} -% Quarks for ending recursions. Only ever used there! -% \cs{q_recursion_tail} is appended to whatever list structure we are -% doing recursion on, meaning it is added as a proper list item with -% whatever list separator is in use. \cs{q_recursion_stop} is placed -% directly after the list. -% \begin{macrocode} -\quark_new:N \q_recursion_tail -\quark_new:N \q_recursion_stop -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\s_@@} -% Private scan mark used in \pkg{l3quark}. We don't have \pkg{l3scan} -% yet, so we declare the scan mark here and add it to the scan mark pool -% later. -% \begin{macrocode} -\cs_new_eq:NN \s_@@ \scan_stop: -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\q_@@_nil} -% Private quark use for some tests. -% \begin{macrocode} -\quark_new:N \q_@@_nil -% \end{macrocode} -% \end{variable} -% -% \begin{macro}[EXP]{\quark_if_recursion_tail_stop:N} -% \UnitTested -% \begin{macro}[EXP]{\quark_if_recursion_tail_stop_do:Nn} -% \UnitTested -% When doing recursions, it is easy to spend a lot of time testing if the -% end marker has been found. To avoid this, a dedicated end marker is used -% each time a recursion is set up. Thus if the marker is found everything -% can be wrapper up and finished off. The simple case is when the test -% can guarantee that only a single token is being tested. In this case, -% there is just a dedicated copy of the standard quark test. Both a gobbling -% version and one inserting end code are provided. -% \begin{macrocode} -\cs_new:Npn \quark_if_recursion_tail_stop:N #1 - { - \if_meaning:w \q_recursion_tail #1 - \exp_after:wN \use_none_delimit_by_q_recursion_stop:w - \fi: - } -\cs_new:Npn \quark_if_recursion_tail_stop_do:Nn #1 - { - \if_meaning:w \q_recursion_tail #1 - \exp_after:wN \use_i_delimit_by_q_recursion_stop:nw - \else: - \exp_after:wN \use_none:n - \fi: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP] -% {\quark_if_recursion_tail_stop:n, \quark_if_recursion_tail_stop:o} -% \UnitTested -% \begin{macro}[EXP] -% {\quark_if_recursion_tail_stop_do:nn, \quark_if_recursion_tail_stop_do:on} -% \UnitTested -% \begin{macro}[EXP]{\@@_if_recursion_tail:w} -% See \cs{quark_if_nil:nTF} for the details. Expanding -% \cs{@@_if_recursion_tail:w} once in front of the tokens chosen here -% gives an empty result if and only if |#1|~is exactly -% \cs{q_recursion_tail}. -% \begin{macrocode} -\cs_new:Npn \quark_if_recursion_tail_stop:n #1 - { - \tl_if_empty:oTF - { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! } - { \use_none_delimit_by_q_recursion_stop:w } - { } - } -\cs_new:Npn \quark_if_recursion_tail_stop_do:nn #1 - { - \tl_if_empty:oTF - { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! } - { \use_i_delimit_by_q_recursion_stop:nw } - { \use_none:n } - } -\cs_new:Npn \@@_if_recursion_tail:w - #1 \q_recursion_tail #2 ? #3 ?! { #1 #2 } -\cs_generate_variant:Nn \quark_if_recursion_tail_stop:n { o } -\cs_generate_variant:Nn \quark_if_recursion_tail_stop_do:nn { o } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\quark_if_recursion_tail_break:NN} -% \begin{macro}[EXP]{\quark_if_recursion_tail_break:nN} -% Analogues of the \cs[index=quark_if_recursion_tail_stop:n] -% {quark_if_recursion_tail_stop\ldots{}} functions. -% Break the mapping using |#2|. -% \begin{macrocode} -\cs_new:Npn \quark_if_recursion_tail_break:NN #1#2 - { - \if_meaning:w \q_recursion_tail #1 - \exp_after:wN #2 - \fi: - } -\cs_new:Npn \quark_if_recursion_tail_break:nN #1#2 - { - \tl_if_empty:oT - { \@@_if_recursion_tail:w {} #1 {} ?! \q_recursion_tail ??! } - {#2} - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[pTF]{\quark_if_nil:N} -% \UnitTested -% \begin{macro}[pTF]{\quark_if_no_value:N, \quark_if_no_value:c} -% \UnitTested -% Here we test if we found a special quark as the first argument. -% We better start with \cs{q_no_value} as the first argument since -% the whole thing may otherwise loop if |#1| is wrongly given -% a string like |aabc| instead of a single token.\footnote{It may -% still loop in special circumstances however!} -% \begin{macrocode} -\prg_new_conditional:Npnn \quark_if_nil:N #1 { p, T , F , TF } - { - \if_meaning:w \q_nil #1 - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -\prg_new_conditional:Npnn \quark_if_no_value:N #1 { p, T , F , TF } - { - \if_meaning:w \q_no_value #1 - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -\prg_generate_conditional_variant:Nnn \quark_if_no_value:N - { c } { p , T , F , TF } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[pTF]{\quark_if_nil:n, \quark_if_nil:V, \quark_if_nil:o} -% \UnitTested -% \begin{macro}[pTF]{\quark_if_no_value:n} -% \UnitTested -% \begin{macro}{\@@_if_nil:w, \@@_if_no_value:w} -% \begin{macro}[EXP]{\@@_if_empty_if:o} -% Let us explain \cs{quark_if_nil:nTF}. Expanding \cs{@@_if_nil:w} -% once is safe thanks to the trailing \cs{q_nil} |??!|. The result of -% expanding once is empty if and only if both delimited arguments |#1| -% and~|#2| are empty and |#3|~is delimited by the last tokens~|?!|. -% Thanks to the leading~|{}|, the argument~|#1| is empty if and only -% if the argument of \cs{quark_if_nil:n} starts with \cs{q_nil}. The -% argument~|#2| is empty if and only if this \cs{q_nil} is followed -% immediately by~|?| or by~|{}?|, coming either from the trailing -% tokens in the definition of \cs{quark_if_nil:n}, or from its -% argument. In the first case, \cs{@@_if_nil:w} is followed by -% |{}\q_nil| |{}?| |!\q_nil|~|??!|, hence |#3|~is delimited by the -% final~|?!|, and the test returns \texttt{true} as wanted. In the -% second case, the result is not empty since the first~|?!| in the -% definition of \cs{quark_if_nil:n} stop~|#3|. The auxiliary here -% is the same as \cs{__tl_if_empty_if:o}, with the same comments -% applying. -% \begin{macrocode} -\prg_new_conditional:Npnn \quark_if_nil:n #1 { p, T , F , TF } - { - \@@_if_empty_if:o - { \@@_if_nil:w {} #1 {} ? ! \q_nil ? ? ! } - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -\cs_new:Npn \@@_if_nil:w #1 \q_nil #2 ? #3 ? ! { #1 #2 } -\prg_new_conditional:Npnn \quark_if_no_value:n #1 { p, T , F , TF } - { - \@@_if_empty_if:o - { \@@_if_no_value:w {} #1 {} ? ! \q_no_value ? ? ! } - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -\cs_new:Npn \@@_if_no_value:w #1 \q_no_value #2 ? #3 ? ! { #1 #2 } -\prg_generate_conditional_variant:Nnn \quark_if_nil:n - { V , o } { p , TF , T , F } -\cs_new:Npn \@@_if_empty_if:o #1 - { - \exp_after:wN \if_meaning:w \exp_after:wN \q_nil - \__kernel_tl_to_str:w \exp_after:wN {#1} \q_nil - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\__kernel_quark_new_test:N} -% The function \cs{__kernel_quark_new_test:N} defines |#1| in a -% similar way as \cs[no-index]{quark_if_recursion_tail_...} functions -% (as described below), using -% \cs[no-index]{q__\meta{namespace}_recursion_tail} as the test quark -% and \cs[no-index]{q__\meta{namespace}_recursion_stop} as the -% delimiter quark, where the \meta{namespace} is determined as the -% first |_|-delimited part in~|#1|. -% -% There are six possible function types which this function can define, -% and which is defined depends on the signature of the function being -% defined: -% \begin{description} -% \def\makelabel#1{\texttt{:#1}~} -% \item[n] gives an analogue of \cs{quark_if_recursion_tail_stop:n} -% \item[nn] gives an analogue of \cs{quark_if_recursion_tail_stop_do:nn} -% \item[nN] gives an analogue of \cs{quark_if_recursion_tail_break:nN} -% \item[N] gives an analogue of \cs{quark_if_recursion_tail_stop:N} -% \item[Nn] gives an analogue of \cs{quark_if_recursion_tail_stop_do:Nn} -% \item[NN] gives an analogue of \cs{quark_if_recursion_tail_break:NN} -% \end{description} -% Any other signature causes an error, as does a function without signature. -% -% \begin{macro}{\__kernel_quark_new_conditional:Nn} -% Similar to \cs{__kernel_quark_new_test:N}, but defines quark -% branching conditionals like \cs{quark_if_nil:nTF} that test for the -% quark \cs[no-index]{q__\meta{namespace}_\meta{name}}. -% The \meta{namespace} and \meta{name} are determined from the -% conditional~|#1|, which must take the rather rigid form -% \cs[no-index]{__\meta{namespace}_quark_if_\meta{name}:\meta{arg spec}}. -% There are only two cases for the \meta{arg spec} here: -% \begin{description} -% \def\makelabel#1{\texttt{:#1}~} -% \item[n] gives an analogue of \cs{quark_if_nil:nTF} -% \item[N] gives an analogue of \cs{quark_if_nil:NTF} -% \end{description} -% Any other signature causes an error, as does a function without signature. -% We use low-level emptiness tests as \pkg{l3tl} is not available yet when these -% functions are used; thankfully we only care about whether strings -% are empty so a simple \cs{if_meaning:w} \cs{q_nil} \meta{string} -% \cs{q_nil} suffices. -% -% \begin{macro}{\@@_new_test:NNNn, \@@_new_test:Nccn, -% \@@_new_test_aux:nnNNnnnn} -% \begin{macro}{\@@_new_conditional:Nnnn, \@@_new_conditional:Neen} -% \begin{macrocode} -\cs_new_protected:Npn \__kernel_quark_new_test:N #1 - { \@@_new_test_aux:Ne #1 { \@@_module_name:N #1 } } -\cs_new_protected:Npn \@@_new_test_aux:Nn #1 #2 - { - \if_meaning:w \q_nil #2 \q_nil - \msg_error:nne { quark } { invalid-function } - { \token_to_str:N #1 } - \else: - \@@_new_test:Nccn #1 - { q__#2_recursion_tail } { q__#2_recursion_stop } { __#2 } - \fi: - } -\cs_generate_variant:Nn \@@_new_test_aux:Nn { Ne } -\cs_new_protected:Npn \@@_new_test:NNNn #1 - { - \exp_last_unbraced:Nf \@@_new_test_aux:nnNNnnnn - { \cs_split_function:N #1 } - #1 { test } - } -\cs_generate_variant:Nn \@@_new_test:NNNn { Ncc } -\cs_new_protected:Npn \__kernel_quark_new_conditional:Nn #1 - { - \@@_new_conditional:Neen #1 - { \@@_quark_conditional_name:N #1 } - { \@@_module_name:N #1 } - } -\cs_new_protected:Npn \@@_new_conditional:Nnnn #1#2#3#4 - { - \if_meaning:w \q_nil #2 \q_nil - \msg_error:nne { quark } { invalid-function } - { \token_to_str:N #1 } - \else: - \if_meaning:w \q_nil #3 \q_nil - \msg_error:nne { quark } { invalid-function } - { \token_to_str:N #1 } - \else: - \exp_last_unbraced:Nf \@@_new_test_aux:nnNNnnnn - { \cs_split_function:N #1 } - #1 { conditional } - {#2} {#3} {#4} - \fi: - \fi: - } -\cs_generate_variant:Nn \@@_new_conditional:Nnnn { Nee } -\cs_new_protected:Npn \@@_new_test_aux:nnNNnnnn #1 #2 #3 #4 #5 - { - \cs_if_exist_use:cTF { @@_new_#5_#2:Nnnn } { #4 } - { - \msg_error:nnee { quark } { invalid-function } - { \token_to_str:N #4 } {#2} - \use_none:nnn - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{ -% \@@_new_test_n:Nnnn, \@@_new_test_nn:Nnnn, -% \@@_new_test_N:Nnnn, \@@_new_test_Nn:Nnnn, -% \@@_new_test_NN:Nnnn, \@@_new_test_NN:Nnnn, -% } -% These macros implement the six possibilities mentioned above, passing -% the right arguments to \cs{@@_new_test_aux_do:nNNnnnnNNn}, -% which defines some auxiliaries, and then to -% \cs{@@_new_test_define_tl:nNnNNn} (|:n(n)| variants) or to -% \cs{@@_new_test_define_ifx:nNnNNn} (|:N(n)|) which define the -% main conditionals. -% \begin{macrocode} -\cs_new_protected:Npn \@@_new_test_n:Nnnn #1 #2 #3 #4 - { - \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { none } { } { } { } - \@@_new_test_define_tl:nNnNNn #1 { } - } -\cs_new_protected:Npn \@@_new_test_nn:Nnnn #1 #2 #3 #4 - { - \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2} - \@@_new_test_define_tl:nNnNNn #1 { \use_none:n } - } -\cs_new_protected:Npn \@@_new_test_nN:Nnnn #1 #2 #3 #4 - { - \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2} - \@@_new_test_define_break_tl:nNNNNn #1 { } - } -\cs_new_protected:Npn \@@_new_test_N:Nnnn #1 #2 #3 #4 - { - \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { none } { } { } { } - \@@_new_test_define_ifx:nNnNNn #1 { } - } -\cs_new_protected:Npn \@@_new_test_Nn:Nnnn #1 #2 #3 #4 - { - \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2} - \@@_new_test_define_ifx:nNnNNn #1 - { \else: \exp_after:wN \use_none:n } - } -\cs_new_protected:Npn \@@_new_test_NN:Nnnn #1 #2 #3 #4 - { - \@@_new_test_aux_do:nNNnnnnNNn {#4} #2 #3 { i } { n } {##1} {##2} - \@@_new_test_define_break_ifx:nNNNNn #1 { } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{ -% \@@_new_test_aux_do:nNNnnnnNNn, -% \@@_test_define_aux:NNNNnnNNn -% } -% \cs{@@_new_test_aux_do:nNNnnnnNNn} makes the control sequence names -% which will be used by \cs{@@_test_define_aux:NNNNnnNNn}, and then later -% by \cs{@@_new_test_define_tl:nNnNNn} or -% \cs{@@_new_test_define_ifx:nNnNNn}. The control sequences defined -% here are analogous to \cs{@@_if_recursion_tail:w} and to -% \cs[no-index]{use_(none|i)_delimit_by_q_recursion_stop:(|n)w}. -% -% The name is composed by the name-space and the name of the quarks. -% Suppose \cs{__kernel_quark_new_test:N} was used with: -% \begin{verbatim} -% \__kernel_quark_new_test:N \__test_quark_tail:n -% \end{verbatim} -% then the first auxiliary will be \cs[no-index]{__test_quark_recursion_tail:w}, -% and the second one will be -% \cs[no-index]{__test_use_none_delimit_by_q_recursion_stop:w}. -% -% Note that the actual quarks are \emph{not} defined here. They should -% be defined separately using \cs{quark_new:N}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_new_test_aux_do:nNNnnnnNNn #1 #2 #3 #4 #5 - { - \exp_args:Ncc \@@_test_define_aux:NNNNnnNNn - { #1 _quark_recursion_tail:w } - { #1 _use_ #4 _delimit_by_q_recursion_stop: #5 w } - #2 #3 - } -\cs_new_protected:Npn \@@_test_define_aux:NNNNnnNNn #1 #2 #3 #4 #5 #6 #7 - { - \cs_gset:Npn #1 ##1 #3 ##2 ? ##3 ?! { ##1 ##2 } - \cs_gset:Npn #2 ##1 #6 #4 {#5} - #7 {##1} #1 #2 #3 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{ -% \@@_new_test_define_tl:nNnNNn, -% \@@_new_test_define_ifx:nNnNNn -% } -% \begin{macro}{ -% \@@_new_test_define_break_tl:nNNNNn, -% \@@_new_test_define_break_ifx:nNNNNn -% } -% Finally, these two macros define the main conditional function using -% what's been set up before. -% \begin{macrocode} -\cs_new_protected:Npn \@@_new_test_define_tl:nNnNNn #1 #2 #3 #4 #5 #6 - { - \cs_new:Npn #5 #1 - { - \tl_if_empty:oTF - { #2 {} ##1 {} ?! #4 ??! } - {#3} {#6} - } - } -\cs_new_protected:Npn \@@_new_test_define_ifx:nNnNNn #1 #2 #3 #4 #5 #6 - { - \cs_new:Npn #5 #1 - { - \if_meaning:w #4 ##1 - \exp_after:wN #3 - #6 - \fi: - } - } -\cs_new_protected:Npn \@@_new_test_define_break_tl:nNNNNn #1 #2 #3 - { \@@_new_test_define_tl:nNnNNn {##1##2} #2 {##2} } -\cs_new_protected:Npn \@@_new_test_define_break_ifx:nNNNNn #1 #2 #3 - { \@@_new_test_define_ifx:nNnNNn {##1##2} #2 {##2} } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{ -% \@@_new_conditional_n:Nnnn, -% \@@_new_conditional_N:Nnnn, -% \@@_new_conditional_n_aux:NNNn, -% \@@_new_conditional_N_aux:NNNn -% } -% These macros implement the two possibilities for branching quark -% conditionals. To avoid constructing without defining the -% \cs[no-index]{__\meta{type}_if_quark_\meta{name}:w} helper, -% \texttt{N}-type function accepts a \cs{prg_do_nothing:} as -% a placeholder. -% \begin{macrocode} -\cs_new_protected:Npn \@@_new_conditional_n:Nnnn #1 #2 #3 - { - \exp_args:Ncc \@@_new_conditional_n_aux:NNNn - { __ #3 _if_quark_ #2 :w } { q__ #3 _ #2 } #1 - } -\cs_new_protected:Npn \@@_new_conditional_N:Nnnn #1 #2 #3 - { - \exp_args:NNc \@@_new_conditional_N_aux:NNNn - \prg_do_nothing: { q__ #3 _ #2 } #1 - } -\cs_new_protected:Npn \@@_new_conditional_n_aux:NNNn #1 #2 #3 #4 - { - \cs_gset:Npn #1 ##1 #2 ##2 ? ##3 ?! { ##1##2 } - \prg_new_conditional:Npnn #3 ##1 {#4} - { - \@@_if_empty_if:o { #1 {} ##1 {} ?! #2 ??! } - \prg_return_true: - \else: - \prg_return_false: - \fi: - } - } -\cs_new_protected:Npn \@@_new_conditional_N_aux:NNNn #1 #2 #3 #4 - { - \prg_new_conditional:Npnn #3 ##1 {#4} - { - \if_meaning:w #2 ##1 - \prg_return_true: - \else: - \prg_return_false: - \fi: - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_module_name:N} -% \begin{macro}[EXP]{ -% \@@_module_name:w, -% \@@_module_name_loop:w, -% \@@_module_name_end:w -% } -% \cs{@@_module_name:N} takes a control sequence and returns its -% \meta{module} name, determined as the first non-empty -% non-single-character word, separated by |_| or~|:|. These rules -% give the correct result for public functions -% \cs[no-index]{\meta{module}_\ldots{}}, private functions -% \cs[no-index]{__\meta{module}_\ldots{}}, and variables such as -% \cs[no-index]{l_\meta{module}_\ldots{}}. If no valid module is -% found the result is an empty string. The approach is to first cut -% off everything after the (first) |:| if any is present, then -% repeatedly grab |_|-delimited words until finding one of length at -% least~$2$ (we use low-level tests as \pkg{l3tl} is not fully -% available when \cs{__kernel_quark_new_test:N} is first used. -% If no \meta{module} is found (such as in \cs{::n}) we -% get the trailing marker \cs{use_none:n} |{}|, which expands to -% nothing. -% \begin{macrocode} -\cs_set:Npn \@@_tmp:w #1#2 - { - \cs_new:Npn \@@_module_name:N ##1 - { - \exp_last_unbraced:Nf \@@_module_name:w - { \cs_to_str:N ##1 } #1 \s_@@ - } - \cs_new:Npn \@@_module_name:w ##1 #1 ##2 \s_@@ - { \@@_module_name_loop:w ##1 #2 \use_none:n { } #2 \s_@@ } - \cs_new:Npn \@@_module_name_loop:w ##1 #2 - { - \use_i_ii:nnn \if_meaning:w \prg_do_nothing: - ##1 \prg_do_nothing: \prg_do_nothing: - \exp_after:wN \@@_module_name_loop:w - \else: - \@@_module_name_end:w ##1 - \fi: - } - \cs_new:Npn \@@_module_name_end:w - ##1 \fi: ##2 \s_@@ { \fi: ##1 } - } -\exp_after:wN \@@_tmp:w \tl_to_str:n { : _ } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_quark_conditional_name:N, \@@_quark_conditional_name:w} -% \cs{@@_quark_conditional_name:N} determines the quark name that the quark -% conditional function~|##1| queries, as the part of the function name -% between |_quark_if_| and the trailing~|:|. Again we define it -% through \cs{@@_tmp:w}, which receives |:| as |#1| and |_quark_if_| -% as |#2|. The auxiliary \cs{@@_quark_conditional_name:w} returns the part -% between the first |_quark_if_| and the next~|:|, and we apply this -% auxiliary to the function name followed by |:| (in case the function -% name is lacking a signature), and |_quark_if_:| so that -% \cs{@@_quark_conditional_name:N} returns an empty string if |_quark_if_| is -% not present. -% \begin{macrocode} -\cs_set:Npn \@@_tmp:w #1 #2 \s_@@ - { - \cs_new:Npn \@@_quark_conditional_name:N ##1 - { - \exp_last_unbraced:Nf \@@_quark_conditional_name:w - { \cs_to_str:N ##1 } #1 #2 #1 \s_@@ - } - \cs_new:Npn \@@_quark_conditional_name:w - ##1 #2 ##2 #1 ##3 \s_@@ {##2} - } -\exp_after:wN \@@_tmp:w \tl_to_str:n { : _quark_if_ } \s_@@ -% \end{macrocode} -% \end{macro} -% -% \subsection{Scan marks} -% -% \begin{macrocode} -%<@@=scan> -% \end{macrocode} -% -% \begin{macro}{\scan_new:N} -% \UnitTested -% Check whether the variable is already a scan mark, -% then declare it to be equal to \cs{scan_stop:} globally. -% \begin{macrocode} -\cs_new_protected:Npn \scan_new:N #1 - { - \tl_if_in:NnTF \g_@@_marks_tl { #1 } - { - \msg_error:nne { scanmark } { already-defined } - { \token_to_str:N #1 } - } - { - \tl_gput_right:Nn \g_@@_marks_tl {#1} - \cs_new_eq:NN #1 \scan_stop: - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\s_stop} -% \begin{variable}{\g_@@_marks_tl} -% \UnitTested -% We only declare one scan mark here, more can be defined -% by specific modules. -% Can't use \cs{scan_new:N} yet because \pkg{l3tl} isn't loaded, -% so define \cs{s_stop} by hand and add it to \cs{g_@@_marks_tl}. -% We also add the scan marks declared earlier to the pool here. -% Since they lives in a different namespace, a little \pkg{DocStrip} -% cheating is necessary. -% \begin{macrocode} -\cs_new_eq:NN \s_stop \scan_stop: -\cs_gset_nopar:Npn \g_@@_marks_tl - { - \s_stop -%<@@=quark> - \s_@@ -%<@@=cs> - \s_@@_mark - \s_@@_stop -%<@@=scan> - } -% \end{macrocode} -% \end{variable} -% \end{variable} -% -% \begin{macro}[EXP]{\use_none_delimit_by_s_stop:w} -% \UnitTested -% Similar to \cs{use_none_delimit_by_q_stop:w}. -% \begin{macrocode} -\cs_new:Npn \use_none_delimit_by_s_stop:w #1 \s_stop { } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -% -% \end{macrocode} -% -% \end{implementation} -% -% \PrintIndex -- cgit v1.2.3