diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3basics.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3basics.dtx | 3950 |
1 files changed, 2204 insertions, 1746 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3basics.dtx b/Master/texmf-dist/source/latex/expl3/l3basics.dtx index e34e42f2732..ecbafc5d6b9 100644 --- a/Master/texmf-dist/source/latex/expl3/l3basics.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3basics.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3basics.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3basics.dtx Copyright (C) 1990-2008 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 @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -35,7 +35,7 @@ \RequirePackage{l3names} %</driver|package> %\fi -\GetIdInfo$Id: l3basics.dtx 702 2007-11-27 14:21:49Z morten $ +\GetIdInfo$Id: l3basics.dtx 1365 2009-05-31 17:26:17Z mittelba $ {L3 Experimental basic definitions} %\iffalse %<*driver> @@ -43,9 +43,9 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3basics.dtx} \end{document} %</driver> % \fi @@ -59,41 +59,116 @@ % \date{\filedate} % \maketitle % +% \begin{documentation} % % As the name suggest this package holds some basic definitions which % are needed by most or all other packages in this set. % -% \section{Basics} -% -% Here we describe those functions that used all over the place. With +% Here we describe those functions that are used all over the place. With % that we mean functions dealing with the construction and testing of % control sequences. Furthermore the basic parts of conditional % processing are covered; conditional processing dealing with specific % data types is described in the modules specific for the respective % data types. % -% \subsection{Predicates and conditionals} +% \section{Predicates and conditionals} +% \label{sec:predicates} +% +% \LaTeX3 has three concepts for conditional flow processing: +% \begin{description} +% +% \item[Branching conditionals] +% Functions that carry out a test and then execute, depending on its +% result, either the code supplied in the \m{true arg} or the \m{false +% arg}. +% These arguments are denoted with "T" and "F" repectively. An +% example would be +% \begin{quote} +% "\cs_if_free:cTF{abc}" \Arg{true code} \Arg{false code} +% \end{quote} +% a function that will turn the first argument into a control sequence +% (since it's marked as "c") then checks whether this control sequence +% is still free and then depending on the result carry out the code in +% the second argument (true case) or in the third argument (false +% case). +% +% These type of functions are known as `conditionals'; whenever a "TF" +% function is defined it will usually be accompanied by "T" and "F" +% functions as well. These are provided for convenience when the +% branch only needs to go a single way. Package writers are free to +% choose which types to define but the kernel definitions will always +% provide all three versions. +% +% Important to note is that these branching conditionals with \m{true +% code} and/or \m{false code} are always defined in a way that the +% code of the chosen alternative can operate on following tokens in +% the input stream. +% +% These conditional functions may or may not be fully expandable, but if they +% are expandable they will be accompanied by a `predicate' for the same test +% as described below. +% +% \item[Predicates] +% `Predicates' are functions that return a special type of boolean +% value which can be tested by the function "\if_predicate:w" +% or in the boolean expression parser. All functions of this type +% are expandable and have names that end with "_p" in the +% description part. For example, +% \begin{quote} +% "\cs_if_free_p:N" +% \end{quote} +% would be a predicate function for the same type of test as the +% conditional described above. It would return `true' if its argument (a +% single token denoted by "N") is still free for definition. It would be used +% in constructions like +% \begin{quote} +% "\if_predicate:w \cs_if_free_p:N \l_tmpz_tl" \m{true code} "\else:" +% \m{false code} "\fi:" +% \end{quote} +% or in expressions utilizing the boolean logic parser: +% \begin{quote} +% "\bool_if:nTF {" \\ +% " \cs_if_free_p:N \l_tmpz_tl || \cs_if_free_p:N \g_tmpz_tl " \\ +% "}" +% \Arg{true code} \Arg{false code} +% \end{quote} % -% \subsubsection{Primitive conditionals} +% Like their branching cousins, predicate functions ensure that all +% underlying primitive "\else:" or "\fi:" have been removed before +% returning the boolean true or false values.\footnote{If defined +% using the interface provided.} +% +% For each predicate defined, a `predicate conditional' will also exist that +% behaves like a conditional described above. +% +% \item[Primitive conditionals] +% There is a third variety of conditional, which is the original concept used in +% plain \TeX{} and \LaTeX. Their use is discouraged in \pkg{expl3} (although +% still used in low-level definitions) because they are more fragile and +% in many cases require more expansion control (hence more code) than the two +% types of conditionals described above. +% \end{description} +% +% +% \subsection{Primitive conditionals} % % The \eTeX\ engine itself provides many different conditionals. Some % expand whatever comes after them and others don't. Hence the names % for these underlying functions will often contain a |:w| part but % higher level functions are often available. See for instance -% |\int_compare_p:nNn| which is a wrapper for |\if_num:w|. +% |\intexpr_compare_p:nNn| which is a wrapper for |\if_num:w|. % % Certain conditionals deal with specific data types like boxes and % fonts and are described there. The ones described below are either % the universal conditionals or deal with control sequences. We will % prefix primitive conditionals with |\if_|. % -% \begin{function}{% -% \if_true: | -% \if_false: | -% \else: | -% \fi: | -% \reverse_if:N | -% } +% \begin{function}{ \if_true: / (EXP) | +% \if_false: / (EXP) | +% \or: / (EXP) | +% \else: / (EXP) | +% \fi: / (EXP) | +% \reverse_if:N / (EXP) } % \begin{syntax} % "\if_true:" <true code> "\else:" <false code> "\fi:" \\ % "\if_false:" <true code> "\else:" <false code> "\fi:" \\ @@ -101,37 +176,31 @@ % \end{syntax} % "\if_true:" always executes <true code>, while "\if_false:" always % executes <false code>. "\reverse_if:N" reverses any two-way primitive -% conditional. "\else:" and "\fi:" delimit the branches of the conditional. +% conditional. "\else:" and "\fi:" delimit the branches of the +% conditional. "\or:" is used in case switches, see \pkg{l3intexpr} +% for more. +% \begin{texnote} +% These are equivalent to their corresponding \TeX\ primitive +% conditionals; |\reverse_if:N| is \eTeX's |\unless|. +% \end{texnote} % \end{function} % -% \begin{function}{% -% \if_meaning:NN | -% \if_cs_meaning_eq:NN | -% \if_token_eq:NN | -% } +% \begin{function}{ \if_meaning:w / (EXP) } % \begin{syntax} -% "\if_meaning:NN" <cs1> <cs2> <true code> "\else:" <false code> -% "\fi:" \\ -% "\if_cs_meaning_eq:NN" <cs1> <cs2> <true code> "\else:" -% <false code> "\fi:" \\ -% "\if_token_eq:NN" <token1> <token2> <true code> "\else:" <false -% code> "\fi:" +% "\if_meaning:w" <arg1> <arg2> <true code> "\else:" <false code> "\fi:" % \end{syntax} -% "\if_meaning:NN" executes <true code> when the replacement text, -% i.e., the expansion of <cs1> and <cs2> are the same, otherwise it -% executes <false code>. However this name isn't really that -% good. What the \TeX\ primitive does is compare two tokens to see if -% they are equal. Hence this is actually a "token" functions. A -% similar argument applies to the situation where it is used to -% compare control sequences, where it is the meaning being compared. -% Something to be cleaned up at some point. +% "\if_meaning:w" executes <true code> when <arg1> and <arg2> are the same, +% otherwise it executes <false code>. +% <arg1> and <arg2> could be functions, variables, tokens; in all cases the +% \emph{unexpanded} definitions are compared. +% \begin{texnote} +% This is \TeX's |\ifx|. +% \end{texnote} % \end{function} % -% \begin{function}{% -% \if:w | -% \if_charcode:w | -% \if_catcode:w -% } +% \begin{function}{ \if:w / (EXP) | +% \if_charcode:w / (EXP) | +% \if_catcode:w / (EXP) } % \begin{syntax} % "\if:w" <token1> <token2> <true code> "\else:" <false code> "\fi:" \\ % "\if_catcode:w" <token1> <token2> <true code> "\else:" <false @@ -145,10 +214,30 @@ % identical. "\if_charcode:w" is an alternative name for "\if:w". % \end{function} % -% \begin{function}{% -% \if_cs_exist:N | -% \if_cs_exist:w -% } +% +% \begin{function}{\if_predicate:w / (EXP)} +% \begin{syntax} +% "\if_predicate:w" <predicate> <true code> "\else:" <false code> "\fi:" +% \end{syntax} +% This function takes a predicate function and +% branches according to the result. (In practice this function would also +% accept a single boolean variable in place of the <predicate> but to make the +% coding clearer this should be done through "\if_bool:N".) +% \end{function} +% +% +% +% \begin{function}{\if_bool:N / (EXP)} +% \begin{syntax} +% "\if_bool:N" <boolean> <true code> "\else:" <false code> "\fi:" +% \end{syntax} +% This function takes a boolean variable and +% branches according to the result. +% \end{function} +% +% +% \begin{function}{ \if_cs_exist:N / (EXP) | +% \if_cs_exist:w / (EXP) } % \begin{syntax} % "\if_cs_exist:N" <cs> <true code> "\else:" <false code> "\fi:" \\ % "\if_cs_exist:w" <tokens> "\cs_end:" <true code> "\else:" <false @@ -162,357 +251,388 @@ % \end{function} % % \begin{function}{ -% \if_mode_horizontal: | -% \if_mode_vertical: | -% \if_mode_math: | -% \if_mode_inner: -% } +% \if_mode_horizontal: / (EXP) | +% \if_mode_vertical: / (EXP) | +% \if_mode_math: / (EXP) | +% \if_mode_inner: / (EXP) } % \begin{syntax} -% "\if_horizontal_mode:" <true code> "\else:" <false code> "\fi:" +% "\if_mode_horizontal:" <true code> "\else:" <false code> "\fi:" % \end{syntax} % Execute <true code> if currently in horizontal mode, otherwise % execute <false code>. Similar for the other functions. % \end{function} % -% \subsubsection{Non-primitive conditionals} +% \subsection{Non-primitive conditionals} % -% \begin{function}{% -% \cs_if_eq_p:NN -% } +% \begin{function}{ \cs_if_eq_name_p:NN } % \begin{syntax} -% "\cs_if_eq_p:NN" <cs1> <cs2> +% "\cs_if_eq_name_p:NN" <cs1> <cs2> % \end{syntax} % Returns `true' if <cs1> and <cs2> are textually the same, i.e.\ have % the same name, otherwise it returns `false'. % \end{function} % -% \begin{function}{% -% \cs_if_eq:NNTF | -% \cs_if_eq:NNT | -% \cs_if_eq:NNF | -% \cs_if_eq:cNTF | -% \cs_if_eq:cNT | -% \cs_if_eq:cNF | -% \cs_if_eq:NcTF | -% \cs_if_eq:NcT | -% \cs_if_eq:NcF | -% \cs_if_eq:ccTF | -% \cs_if_eq:ccT | -% \cs_if_eq:ccF -% } +% \begin{function}{ \cs_if_eq_p:NN / (EXP) | +% \cs_if_eq_p:cN / (EXP) | +% \cs_if_eq_p:Nc / (EXP) | +% \cs_if_eq_p:cc / (EXP) | +% \cs_if_eq:NN / (TF)(EXP) | +% \cs_if_eq:cN / (TF)(EXP) | +% \cs_if_eq:Nc / (TF)(EXP) | +% \cs_if_eq:cc / (TF)(EXP) } % \begin{syntax} -% "\cs_if_eq:NNTF" <cs1> <cs2> "{"<true code>"}{"<false code>"}" +% "\cs_if_eq_p:NNTF" <cs1> <cs2> +% "\cs_if_eq:NNTF" <cs1> <cs2> \Arg{true code} \Arg{false code} % \end{syntax} -% These functions check if <cs1> and <cs2> have same meaning and then -% execute either <true code> or <false code>. +% These functions check if <cs1> and <cs2> have same meaning. % \end{function} % % -% \begin{function}{% -% \cs_if_free_p:N -% } +% \begin{function}{ \cs_if_free_p:N / (EXP) | +% \cs_if_free_p:c / (EXP) | +% \cs_if_free:N / (TF)(EXP) | +% \cs_if_free:c / (TF)(EXP) } % \begin{syntax} % "\cs_if_free_p:N" <cs> +% "\cs_if_free:NTF" <cs> \Arg{true code} \Arg{false code} % \end{syntax} -% Returns `true' if <cs> is either undefined or equal to "\scan_stop:". -% However, it returns `false' if <cs> is textually "\c_undefined" (the -% constantly undefined function), or textually "\scan_stop:". +% Returns `true' if <cs> is either undefined or equal to +% "\tex_relax:D" (the function that is assigned to newly created +% control sequences by \TeX{} when "\cs:w" "..." "\cs_end:" is +% used). In addition to this, `true' is only returned if <cs> does not +% have a signature equal to "D", i.e., `do not use' functions are not +% free to be redefined. % \end{function} % -% \begin{function}{% -% \cs_if_free:NTF | -% \cs_if_free:NT | -% \cs_if_free:NF | -% \cs_if_free:cTF | -% \cs_if_free:cT | -% \cs_if_free:cF -% } +% \begin{function}{ \cs_if_exist_p:N / (EXP) | +% \cs_if_exist_p:c / (EXP) | +% \cs_if_exist:N / (TF)(EXP) | +% \cs_if_exist:c / (TF)(EXP) } % \begin{syntax} -% "\cs_if_free:NTF" <cs> "{"<true code>"}{"<false code>"}" +% "\cs_if_exist_p:N" <cs> +% "\cs_if_exist:NTF" <cs> \Arg{true code} \Arg{false code} % \end{syntax} -% These functions check if <cs> is free and then execute either <true -% code> or <false code>. -% \begin{texnote} -% The conditional "\cs_if_free:cTF" is the \LaTeX3 implementation of -% the \LaTeX2 function \tn{@ifundefined}. The other functions -% haven't been around before. -% \end{texnote} +% These functions check if <cs> exists, i.e., if <cs> is present in +% the hash table and is not the primitive "\tex_relax:D". % \end{function} % -% \begin{function}{% -% \cs_if_really_free:cTF | -% \cs_if_really_free:cF | -% \cs_if_really_free:cT -% } +% \begin{function}{ \cs_if_do_not_use_p:N / (EXP) } % \begin{syntax} -% "\cs_if_really_free:cTF" "{"<tokens>"}" "{"<true code>"} {"<false -% code>"}" +% "\cs_if_do_not_use_p:N" <cs> % \end{syntax} -% Similar to "\cs_if_free:cTF" but does not put anything previously -% undefined into the hash table. Useful for special control sequences -% like "\foo/bar" which cannot be entered as one token. +% These functions check if <cs> has the arg spec "D" for `\emph{do not use}'. +% There are no "TF"-type conditionals for this function as it is only used +% internally and not expected to be widely used. (For now, anyway.) % \end{function} % -% \begin{function}{% -% \cs_if_exist_p:N -% } +% \begin{function}{ \chk_if_free_cs:N } % \begin{syntax} -% "\cs_if_exist_p:N" <cs> +% "\chk_if_free_cs:N" <cs> % \end{syntax} -% This function does the opposite of "\cs_if_free_p:N". +% This function checks that <cs> is \m{free} according to the criteria +% for "\cs_if_free_p:N" above. If not, an error is generated. % \end{function} % -% \begin{function}{% -% \cs_if_exist:NTF | -% \cs_if_exist:NT | -% \cs_if_exist:NF | -% \cs_if_exist:cTF | -% \cs_if_exist:cT | -% \cs_if_exist:cF -% } +% \begin{function}{ \chk_if_exist_cs:N | +% \chk_if_exist_cs:c } % \begin{syntax} -% "\cs_if_exist:NTF" <cs> "{"<true code>"}{"<false code>"}" +% "\chk_if_exist_cs:N" <cs> % \end{syntax} -% These functions check if <cs> exists and then execute either <true -% code> or <false code>. Exactly the opposite of "\cs_if_free:NTF". +% This function checks that <cs> is defined. If it is not an error +% is generated. % \end{function} % -% \begin{function}{% -% \cs_if_really_exist:cTF | -% \cs_if_really_exist:cF | -% \cs_if_really_exist:cT -% } +% \begin{variable}{ \c_true_bool | \c_false_bool } % \begin{syntax} -% "\cs_if_really_exist:cTF" "{"<tokens>"}" "{"<true code>"} {"<false -% code>"}" % \end{syntax} -% The opposite of "\cs_if_really_free:cTF". -% \end{function} +% Constants that represent `true' or `false', respectively. Used to +% implement predicates. +% \end{variable} % +% \subsection{Applications} % -% \begin{function}{% -% \chk_new_cs:N | -% } +% \begin{function}{ \str_if_eq_p:nn / (EXP) } % \begin{syntax} -% "\chk_new_cs:N" <cs> +% "\str_if_eq_p:nn" \Arg{string1} \Arg{string2} % \end{syntax} -% This function checks that <cs> is so far either undefined or equals -% "\scan_stop:" (the function that is assigned to newly created -% control sequences by \TeX{} when "\cs:w" "..." "\cs_end:" is -% used). +% Expands to `true' if <string1> is the same as <string2>, +% otherwise `false'. Ignores spaces within the strings. % \end{function} % -% \begin{function}{% -% \chk_exist_cs:N | -% \chk_exist_cs:c -% } +% \begin{function}{ \str_if_eq_var_p:nf / (EXP) } % \begin{syntax} -% "\chk_exist_cs:N" <cs> +% "\str_if_eq_var_p:nf" \Arg{string1} \Arg{string2} % \end{syntax} -% This function checks that <cs> is defined. If it is not an error -% is generated. +% A variant of "\str_if_eq_p:nn" which has the advantage of +% obeying spaces in at least the second argument. % \end{function} % % -% \begin{variable}{% -% \c_true | -% \c_false -% } +% \section{Control sequences} +% +% \begin{function}{ \cs:w / (EXP) | \cs_end: / (EXP) } % \begin{syntax} +% "\cs:w" <tokens> "\cs_end:" % \end{syntax} -% Constants that represent `true' or `false', respectively. Used to -% implement predicates. -% \end{variable} +% This is the \TeX{} internal way of generating a control sequence from +% some token list. <tokens> get expanded and must ultimately result in a +% sequence of characters. +% \begin{texnote} +% These functions are the primitives \tn{csname} and \tn{endcsname}. +% "\cs:w" is considered weird because it expands tokens until it reaches +% "\cs_end:". +% \end{texnote} +% \end{function} % +% \begin{function}{ \cs_show:N | +% \cs_show:c } +% \begin{syntax} +% "\cs_show:N" <cs> +% "\cs_show:c" \Arg{arg} +% \end{syntax} +% This function shows in the console output the \emph{meaning} of the control +% sequence <cs> or that created by <arg>. +% \begin{texnote} +% This is \TeX's |\show| and associated csname version of it. +% \end{texnote} +% \end{function} % +% \begin{function}{ \cs_meaning:N / (EXP) | +% \cs_meaning:c / (EXP) } +% \begin{syntax} +% "\cs_meaning:N" <cs> +% "\cs_meaning:c" \Arg{arg} +% \end{syntax} +% This function expands to the \emph{meaning} of the control sequence <cs> or +% that created by <arg>. +% \begin{texnote} +% This is \TeX's |\meaning| and associated csname version of it. +% \end{texnote} +% \end{function} % -% \subsection{Selecting and discarding tokens from the input stream} +% \section{Selecting and discarding tokens from the input stream} % -% The conditional processing could not have been implemented without +% The conditional processing cannot be implemented without % being able to gobble and select which tokens to use from the input % stream. +% % -% \begin{function}{% -% \use_none:n | -% \use_none:nn | -% \use_none:nnn | -% \use_none:nnnn | -% \use_none:nnnnn | -% \use_none:nnnnnn | -% \use_none:nnnnnnn | -% \use_none:nnnnnnnn | -% \use_none:nnnnnnnnn | -% } +% \begin{function}{ \use:n / (EXP) | +% \use:nn / (EXP) | +% \use:nnn / (EXP) | +% \use:nnnn / (EXP) } % \begin{syntax} -% "\use_none:n" "{"<arg1>"}"\\ -% "\use_none:nn" "{"<arg1>"}{"<arg2>"}" +% "\use:n" \Arg{arg} % \end{syntax} -% These functions gobble the tokens or brace groups from the input -% stream. +% Functions that returns all of their arguments to the input stream after +% removing the surrounding braces around each argument. +% \begin{texnote} +% "\use:n" is \LaTeXe's "\@firstofone"/"\@iden". +% \end{texnote} % \end{function} % +% \begin{function}{ \use:c / (EXP) } +% \begin{syntax} +% "\use:c" \Arg{cs} +% \end{syntax} +% Function that returns to the input stream the control sequence created from +% its argument. Requires two expansions before a control sequence is returned. +% \begin{texnote} +% "\use:c" is \LaTeXe's "\@nameuse". +% \end{texnote} +% \end{function} % -% \begin{function}{\use_arg_i:n} +% \begin{function}{ \use_none:n / (EXP) | +% \use_none:nn / (EXP) | +% \use_none:nnn / (EXP) | +% \use_none:nnnn / (EXP) | +% \use_none:nnnnn / (EXP) | +% \use_none:nnnnnn / (EXP) | +% \use_none:nnnnnnn / (EXP) | +% \use_none:nnnnnnnn / (EXP) | +% \use_none:nnnnnnnnn / (EXP) } % \begin{syntax} -% "\use_arg_i:n" "{" <code1> "}" +% "\use_none:n" \Arg{arg1}\\ +% "\use_none:nn" \Arg{arg1} \Arg{arg2} % \end{syntax} -% Function that executes the next argument after removing the -% surrounding braces. Used to implement conditionals. +% These functions gobble the tokens or brace groups from the input +% stream. +% \begin{texnote} +% "\use_none:n", "\use_none:nn", "\use_none:nnnn" are \LaTeXe's +% "\@gobble", "\@gobbletwo", and "\@gobblefour". +% \end{texnote} % \end{function} % -% \begin{function}{% -% \use_arg_i:nn | -% \use_arg_ii:nn | -% } +% \begin{function}{ \use_i:nn / (EXP) | +% \use_ii:nn / (EXP) } % \begin{syntax} -% "\use_arg_i:nn" "{" <code1> "}{" <code2> "}" +% "\use_i:nn" \Arg{code1} \Arg{code2} % \end{syntax} % Functions that execute the first or second argument respectively, % after removing the surrounding braces. Primarily used to implement % conditionals. +% \begin{texnote} +% These are \LaTeXe's "\@firstoftwo" and "\@secondoftwo", respectively. +% \end{texnote} % \end{function} % -% \begin{function}{% -% \use_arg_i:nnn | -% \use_arg_ii:nnn | -% \use_arg_iii:nnn | -% } +% \begin{function}{ \use_i:nnn / (EXP) | +% \use_ii:nnn / (EXP) | +% \use_iii:nnn / (EXP) } % \begin{syntax} -% "\use_arg_i:nnn" "{" <arg1> "}{" <arg2> "}{" <arg3> "}" +% "\use_i:nnn" \Arg{arg1} \Arg{arg2} \Arg{arg3} % \end{syntax} % Functions that pick up one of three arguments and execute them after -% removing the surrounding braces. Should be described somewhere else. +% removing the surrounding braces. +% \begin{texnote} +% \LaTeXe\ has only "\@thirdofthree". +% \end{texnote} % \end{function} % -% \begin{function}{% -% \use_arg_i:nnnn | -% \use_arg_ii:nnnn | -% \use_arg_iii:nnnn | -% \use_arg_iv:nnnn | -% } +% \begin{function}{ \use_i:nnnn / (EXP) | +% \use_ii:nnnn / (EXP) | +% \use_iii:nnnn / (EXP) | +% \use_iv:nnnn / (EXP) } % \begin{syntax} -% "\use_arg_i:nnnn" "{" <arg1> "}{" <arg2> "}{" <arg3> "}{" <arg4> "}" +% "\use_i:nnnn" \Arg{arg1} \Arg{arg2} \Arg{arg3} \Arg{arg4} % \end{syntax} % Functions that pick up one of four arguments and execute them after % removing the surrounding braces. % \end{function} % -% A different kind of functions for selecting tokens from the token -% stream are those that use delimited arguments. +% \subsection{Extending the interface} % -% \begin{function}{% -% \use_none_delimit_by_q_nil:w | -% \use_none_delimit_by_q_stop:w | -% } +% \begin{function}{ \use_i_ii:nnn / (EXP) } +% \begin{syntax} +% "\use_i_ii:nnn" \Arg{arg1} \Arg{arg2} \Arg{arg3} +% \end{syntax} +% This function used in the expansion module reads three arguments and +% returns (without braces) the first and second argument while +% discarding the third argument. +% +% If you wish to select multiple arguments while discarding others, +% use a syntax like this. Its definition is +% \begin{verbatim} +% \cs_set:Npn \use_i_ii:nnn #1#2#3 {#1#2} +% \end{verbatim} +% \end{function} +% +% \subsection{Selecting tokens from delimited arguments} +% +% A different kind of function for selecting tokens from the token +% stream are those that use delimited arguments. +% +% \begin{function}{ \use_none_delimit_by_q_nil:w / (EXP) | +% \use_none_delimit_by_q_stop:w / (EXP) | +% \use_none_delimit_by_q_recursion_stop:w / (EXP) } % \begin{syntax} % "\use_none_delimit_by_q_nil:w" <balanced text> "\q_nil" % \end{syntax} % Gobbles <balanced text>. Useful in gobbling the remainder in a list -% structure. +% structure or terminating recursion. % \end{function} % -% \begin{function}{% -% \use_arg_i_delimit_by_q_nil:nw | -% \use_arg_i_delimit_by_q_stop:nw | -% } +% \begin{function}{ \use_i_delimit_by_q_nil:nw / (EXP) | +% \use_i_delimit_by_q_stop:nw / (EXP) | +% \use_i_delimit_by_q_recursion_stop:nw / (EXP) } % \begin{syntax} -% "\use_arg_i_delimit_by_q_nil:nw" "{"<arg>"}" <balanced text> "\q_nil" +% "\use_i_delimit_by_q_nil:nw" \Arg{arg} <balanced text> "\q_nil" % \end{syntax} % Gobbles <balanced text> and executes <arg> afterwards. This can also % be used to get the first item in a token list. % \end{function} % % -% \begin{function}{% -% \use_arg_i_after_fi:nw | -% \use_arg_i_after_else:nw | -% \use_arg_i_after_or:nw | -% \use_arg_i_after_orelse:nw -% } +% \begin{function}{ \use_i_after_fi:nw / (EXP) | +% \use_i_after_else:nw / (EXP) | +% \use_i_after_or:nw / (EXP) | +% \use_i_after_orelse:nw / (EXP) } % \begin{syntax} -% "\use_arg_i_after_fi:nw" "{"<arg>"}" "\fi:" -% "\use_arg_i_after_else:nw" "{"<arg>"}" "\else:" <balanced text> "\fi:" -% "\use_arg_i_after_or:nw" "{"<arg>"}" "\or:" <balanced text> "\fi:" -% "\use_arg_i_after_orelse:nw" "{"<arg>"}" "\or:/\else:" <balanced text> "\fi:" +% "\use_i_after_fi:nw" \Arg{arg} "\fi:" +% "\use_i_after_else:nw" \Arg{arg} "\else:" <balanced text> "\fi:" +% "\use_i_after_or:nw" \Arg{arg} "\or:" <balanced text> "\fi:" +% "\use_i_after_orelse:nw" \Arg{arg} "\or:/\else:" <balanced text> "\fi:" % \end{syntax} % Executes <arg> after executing closing out -% "\fi:". "\use_arg_i_after_orelse:nw" can be used anywhere where -% "\use_arg_i_after_else:nw" or "\use_arg_i_after_or:nw" are used. +% "\fi:". "\use_i_after_orelse:nw" can be used anywhere where +% "\use_i_after_else:nw" or "\use_i_after_or:nw" are used. % \end{function} % -% \subsection{Internal functions} % -% \begin{function}{% -% \cs:w | -% \cs_end: -% } +% \section{That which belongs in other modules but needs to be defined earlier} +% +% \begin{function}{ \exp_after:wN / (EXP) } % \begin{syntax} -% "\cs:w" <tokens> "\cs_end:" +% "\exp_after:wN" <token1> <token2> % \end{syntax} -% This is the \TeX{} internal way of generating a control sequence from -% some token list. <tokens> get expanded and must ultimately result in a -% sequence of characters. +% Expands <token2> once and then continues processing from <token1>. % \begin{texnote} -% These functions are the primitives \tn{csname} and \tn{endcsname}. -% "\cs:w" is considered weird because it expands tokens until it reaches -% "\cs_end:". -% \end{texnote} +% This is \TeX's \tn{expandafter}. +% \end{texnote} % \end{function} % -% \begin{function}{\pref_global:D | -% \pref_long:D | -% \pref_protected:D | -% } +% \begin{function}{ \exp_not:N / (EXP) | \exp_not:n / (EXP) } % \begin{syntax} -% "\pref_global:D" "\def:Npn" +% "\exp_not:N" <token> +% "\exp_not:n" \Arg{tokens} % \end{syntax} -% Prefix functions that can be used in front of some definition -% functions (namely \ldots). The result of prefixing a function -% definition with "\pref_global:D" makes the definition global, -% "\pref_long:D" change the argument scanning mechanism so that it -% allows "\par" tokens in the argument of the prefixed function, -% and "\pref_protected:D" makes the definition robust in "\write"s etc. -% -% -% None of these internal functions should be used by a programmer since -% the necessary combinations are all available as separate function, -% e.g., "\def_long:Npn" is internally implemented as "\pref_long:D" -% "\def:Npn". +% In an expanding context, this function prevents <token> or <tokens> from +% expanding. % \begin{texnote} -% These prefixes are the primitives \tn{global}, \tn{long}, and -% \tn{protected}. The \tn{outer} isn't used at all within \LaTeX3 -% because \ldots +% These are \TeX's \tn{noexpand} and \eTeX's \tn{unexpanded}, respectively. % \end{texnote} % \end{function} % +% \begin{function}{ \prg_do_nothing: / (EXP) } +% This is as close as we get to a null operation or no-op. +% \begin{texnote} +% Definition as in \LaTeX's \tn{\@empty} but not used for the same thing. +% \end{texnote} +% \end{function} % -% -% \begin{function}{\io_put_log:x | -% \io_put_term:x | -% \io_put_deferred:Nx | -% } +% \begin{function}{ \iow_log:x | +% \iow_term:x | +% \iow_shipout_x:Nn } % \begin{syntax} -% "\io_put_log:x" "{"<message>"}" -% "\io_put_deferred:Nx" <write_stream> "{"<message>"}" +% "\iow_log:x" \Arg{message} +% "\iow_shipout_x:Nn" <write_stream> \Arg{message} % \end{syntax} % Writes <message> to either to log or the terminal. % \end{function} % -% \subsection{Defining functions} +% \begin{function}{ \msg_kernel_bug:x } +% \begin{syntax} +% "\msg_kernel_bug:x" \Arg{message} +% \end{syntax} +% Internal function for calling errors in our code. +% \end{function} +% +% \begin{function}{ \cs_record_meaning:N } +% Placeholder for a function to be defined by \file{l3chk}. +% \end{function} +% +% \begin{variable}{ \c_minus_one | \c_zero | \c_sixteen } +% Numeric constants. +% \end{variable} +% +% +% +% \section{Defining functions} % % % There are two types of function definitions in \LaTeX3: versions % that check if the function name is still unused, and versions that -% simply make the definition. The later are used for internal scratch +% simply make the definition. The latter are used for internal scratch % functions that get new meanings all over the place. % % For each type there is an additional choice to be made: Does the % function to be defined contain delimited arguments? The answer in -% 99\% of the cases is no, so in most cases the programmer just want -% to input the number of arguments, which is basically how -% \cs{newcommand} in \LaTeXe{} works. Therefore we provide functions -% that expect a number as the primary type and later on in this module -% you can find the ones with the more primitive syntax. +% 99\% of the cases is no. For this type the programmer will know the +% number of arguments and in most cases use the argument signature to +% signal this, e.g., "\foo_bar:nnn" presumably takes three +% arguments. We therefore also provide functions that automatically +% detect how many arguments are required and construct the parameter +% text on the fly. % % A definition of a new function can be done locally and globally. Currently % nearly all function definitions are done locally on top level, in @@ -528,104 +648,126 @@ % as individual functions. % \end{texnote} % -% -% \subsubsection{Defining new functions} -% -% Firstly comes to variants most used namely those taking a number to -% denote the number of arguments. -% -% \begin{function}{\def_new:NNn | -% \def_new:NNx | -% \def_new:cNn | -% \def_new:cNx +% A slew of functions are defined in the following sections for defining +% new functions. Here's a quick summary to get an idea of what's available: +% {\centering +% "\cs_"("g")("new"/"set")("_protected")("_nopar")":"("N"/"c")("p")("n"/"x") +% \par} +% That stands for, respectively, the following variations: +% \begin{description} +% \item[\texttt g] Global or local; +% \item[\texttt{new}/\texttt{set}] +% Define a new function or re-define an existing one; +% \item[\texttt{protected}] +% Prevent expansion of the function in "x" arguments; +% \item[\texttt{nopar}] Restrict the argument(s) from containing "\par"; +% \item[\texttt N/\texttt c] Either a control sequence or a `csname'; +% \item[\texttt p] +% Either the a primitive \TeX\ argument or the number of arguments +% is detected from the argument signature, i.e., |\foo:nnn| is +% assumed to have three arguments |#1#2#3|; +% \item[\texttt n/\texttt x] Either an unexpanded or an expanded definition. +% \end{description} +% That adds up to 128 variations (!). However, the system is very +% logical and only a handful will usually be required often. +% +% +% +% \subsection{Defining new functions using primitive parameter text} +% +% +% \begin{function}{\cs_new:Npn | +% \cs_new:Npx | +% \cs_new:cpn | +% \cs_new:cpx % } % \begin{syntax} -% "\def_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_new:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Defines a new function, making sure that <cs> is unused so far. -% <num> is the number of arguments which is in the interval $[0,9]$ -% otherwise an error is raised. It is under the responsibility of the -% programmer to name the new function according to the rules laid out -% in the previous section. <code> is either passed literally or may -% be subject to expansion (under the "x" variants). +% Defines a function that may contain "\par" tokens in the argument(s) +% when called. This is not allowed for normal functions. % \end{function} % -% \begin{function}{\gdef_new:NNn | -% \gdef_new:cNn | -% \gdef_new:NNx | -% \gdef_new:cNx +% \begin{function}{\cs_gnew:Npn | +% \cs_gnew:Npx | +% \cs_gnew:cpn | +% \cs_gnew:cpx % } % \begin{syntax} -% "\gdef_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_gnew:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Like "\def_new:NNn" but defines the new function globally. +% Global versions of the above functions. % \end{function} % -% \begin{function}{\def_long_new:NNn | -% \def_long_new:NNx | -% \def_long_new:cNn | -% \def_long_new:cNx +% \begin{function}{\cs_new_nopar:Npn | +% \cs_new_nopar:Npx | +% \cs_new_nopar:cpn | +% \cs_new_nopar:cpx % } % \begin{syntax} -% "\def_long_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_new_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Defines a function that may contain "\par" tokens in the argument(s) -% when called. This is not allowed for normal functions. +% Defines a new function, making sure that <cs> is unused so far. +% <parms> may consist of arbitrary parameter specification in \TeX{} +% syntax. It is under the responsibility of the programmer to name the +% new function according to the rules laid out in the previous section. +% <code> is either passed literally or may be subject to expansion +% (under the "x" variants). % \end{function} % -% \begin{function}{\gdef_long_new:NNn | -% \gdef_long_new:NNx | -% \gdef_long_new:cNn | -% \gdef_long_new:cNx +% \begin{function}{\cs_gnew_nopar:Npn | +% \cs_gnew_nopar:Npx | +% \cs_gnew_nopar:cpn | +% \cs_gnew_nopar:cpx % } % \begin{syntax} -% "\gdef_long_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_gnew_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Global versions of the above functions. +% Like "\cs_new_nopar:Npn" but defines the new function globally. See +% comments above. % \end{function} % -% \begin{function}{\def_protected_new:NNn | -% \def_protected_new:NNx | -% \def_protected_new:cNn | -% \def_protected_new:cNx +% \begin{function}{\cs_new_protected:Npn | +% \cs_new_protected:Npx | +% \cs_new_protected:cpn | +% \cs_new_protected:cpx % } % \begin{syntax} -% "\def_protected_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_new_protected:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Defines a function that does not expand when inside an |x| type -% expansion. +% Defines a function that is both robust and may contain "\par" tokens +% in the argument(s) when called. % \end{function} % -% \begin{function}{\gdef_protected_new:NNn | -% \gdef_protected_new:NNx | -% \gdef_protected_new:cNn | -% \gdef_protected_new:cNx -% } +% \begin{function}{ \cs_gnew_protected:Npn | +% \cs_gnew_protected:Npx | +% \cs_gnew_protected:cpn | +% \cs_gnew_protected:cpx } % \begin{syntax} -% "\gdef_protected_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_gnew_protected:Npn" <cs> <parms> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long_new:NNn | -% \def_protected_long_new:NNx | -% \def_protected_long_new:cNn | -% \def_protected_long_new:cNx +% \begin{function}{\cs_new_protected_nopar:Npn | +% \cs_new_protected_nopar:Npx | +% \cs_new_protected_nopar:cpn | +% \cs_new_protected_nopar:cpx % } % \begin{syntax} -% "\def_protected_long_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_new_protected_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Defines a function that is both robust and may contain "\par" tokens -% in the argument(s) when called. +% Defines a function that does not expand when inside an |x| type +% expansion. % \end{function} % -% \begin{function}{\gdef_protected_long_new:NNn | -% \gdef_protected_long_new:NNx | -% \gdef_protected_long_new:cNn | -% \gdef_protected_long_new:cNx +% \begin{function}{\cs_gnew_protected_nopar:Npn | +% \cs_gnew_protected_nopar:Npx | +% \cs_gnew_protected_nopar:cpn | +% \cs_gnew_protected_nopar:cpx % } % \begin{syntax} -% "\gdef_protected_long_new:NNn" <cs> <num> "{" <code> "}" +% "\cs_gnew_protected_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} @@ -634,367 +776,385 @@ % % % -% Secondly comes the ones where the programmer can use delimited -% arguments. Rarely needed outside the kernel. % % -% \begin{function}{\def_new:Npn | -% \def_new:Npx | -% \def_new:cpn | -% \def_new:cpx -% } -% \begin{syntax} -% "\def_new:Npn" <cs> <parms> "{" <code> "}" -% \end{syntax} -% Defines a new function, making sure that <cs> is unused so far. -% <parms> may consist of arbitrary parameter specification in \TeX{} -% syntax. It is under the responsibility of the programmer to name the -% new function according to the rules laid out in the previous section. -% <code> is either passed literally or may be subject to expansion -% (under the "x" variants). -% \end{function} % -% \begin{function}{\gdef_new:Npn | -% \gdef_new:cpn | -% \gdef_new:Npx | -% \gdef_new:cpx -% } -% \begin{syntax} -% "\gdef_new:Npn" <cs> <parms> "{" <code> "}" -% \end{syntax} -% Like "\def_new:Npn" but defines the new function globally. See -% comments above. -% \end{function} % -% \begin{function}{\def_long_new:Npn | -% \def_long_new:Npx | -% \def_long_new:cpn | -% \def_long_new:cpx +% \subsection{Defining new functions using the signature} +% +% +% \begin{function}{\cs_new:Nn | +% \cs_new:Nx | +% \cs_new:cn | +% \cs_new:cx % } % \begin{syntax} -% "\def_long_new:Npn" <cs> <parms> "{" <code> "}" +% "\cs_new:Nn" <cs> \Arg{code} % \end{syntax} -% Defines a function that may contain "\par" tokens in the argument(s) -% when called. This is not allowed for normal functions. +% Defines a new function, making sure that <cs> is unused so far. The +% parameter text is automatically detected from the length of the +% function signature. If <cs> is missing a colon in its name, an error +% is raised. It is under the responsibility of the programmer to name +% the new function according to the rules laid out in the previous +% section. <code> is either passed literally or may be subject to +% expansion (under the "x" variants). +% \begin{texnote} +% Internally, these use \TeX's "\long". These forms are +% recommended for low-level definitions as experience has shown that "\par" +% tokens often turn up in programming situations that wouldn't have been +% expected. +% \end{texnote} % \end{function} % -% \begin{function}{\gdef_long_new:Npn | -% \gdef_long_new:Npx | -% \gdef_long_new:cpn | -% \gdef_long_new:cpx +% \begin{function}{\cs_gnew:Nn | +% \cs_gnew:Nx | +% \cs_gnew:cn | +% \cs_gnew:cx % } % \begin{syntax} -% "\gdef_long_new:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gnew:Nn" <cs> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_new:Npn | -% \def_protected_new:Npx | -% \def_protected_new:cpn | -% \def_protected_new:cpx +% \begin{function}{\cs_new_nopar:Nn | +% \cs_new_nopar:Nx | +% \cs_new_nopar:cn | +% \cs_new_nopar:cx % } % \begin{syntax} -% "\def_protected_new:Npn" <cs> <parms> "{" <code> "}" +% "\cs_new_nopar:Nn" <cs> \Arg{code} % \end{syntax} -% Defines a function that does not expand when inside an |x| type -% expansion. +% Version of the above in which "\par" is not allowed to appear within the +% argument(s) of the defined functions. % \end{function} % -% \begin{function}{\gdef_protected_new:Npn | -% \gdef_protected_new:Npx | -% \gdef_protected_new:cpn | -% \gdef_protected_new:cpx +% \begin{function}{\cs_gnew_nopar:Nn | +% \cs_gnew_nopar:Nx | +% \cs_gnew_nopar:cn | +% \cs_gnew_nopar:cx % } % \begin{syntax} -% "\gdef_protected_new:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gnew_nopar:Nn" <cs> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long_new:Npn | -% \def_protected_long_new:Npx | -% \def_protected_long_new:cpn | -% \def_protected_long_new:cpx +% \begin{function}{\cs_new_protected:Nn | +% \cs_new_protected:Nx | +% \cs_new_protected:cn | +% \cs_new_protected:cx % } % \begin{syntax} -% "\def_protected_long_new:Npn" <cs> <parms> "{" <code> "}" +% "\cs_new_protected:Nn" <cs> \Arg{code} % \end{syntax} % Defines a function that is both robust and may contain "\par" tokens % in the argument(s) when called. % \end{function} % -% \begin{function}{\gdef_protected_long_new:Npn | -% \gdef_protected_long_new:Npx | -% \gdef_protected_long_new:cpn | -% \gdef_protected_long_new:cpx +% \begin{function}{\cs_gnew_protected:Nn | +% \cs_gnew_protected:Nx | +% \cs_gnew_protected:cn | +% \cs_gnew_protected:cx % } % \begin{syntax} -% "\gdef_protected_long_new:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gnew_protected:Nn" <cs> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\let_new:NN | -% \let_new:cN | -% \let_new:Nc | -% \let_new:cc | -% \glet_new:NN| -% \glet_new:cN| -% \glet_new:Nc| -% \glet_new:cc } +% \begin{function}{\cs_new_protected_nopar:Nn | +% \cs_new_protected_nopar:Nx | +% \cs_new_protected_nopar:cn | +% \cs_new_protected_nopar:cx +% } % \begin{syntax} -% "\let_new:NN" <cs1> <cs2> +% "\cs_new_protected_nopar:Nn" <cs> \Arg{code} % \end{syntax} -% Gives the function <cs1> the current meaning of <cs2>. Again, we may -% do this always globally. +% Defines a function that does not expand when inside an |x| type +% expansion. "\par" is not allowed in the argument(s) of the defined function. % \end{function} % -% -% -% \subsubsection{Undefining functions} -% -% \begin{function}{ \cs_gundefine:N +% \begin{function}{\cs_gnew_protected_nopar:Nn | +% \cs_gnew_protected_nopar:Nx | +% \cs_gnew_protected_nopar:cn | +% \cs_gnew_protected_nopar:cx % } % \begin{syntax} -% "\cs_gundefine:N" <cs> +% "\cs_gnew_protected_nopar:Nn" <cs> \Arg{code} % \end{syntax} -% Undefines the control sequence. +% Global versions of the above functions. % \end{function} % -% \subsubsection{Defining internal functions (no checks)} +% +% +% \subsection{Defining functions using primitive parameter text} +% % % Besides the function definitions that check whether or not their % argument is an unused function we need function definitions that % overwrite currently used definitions. The following functions are % provided for this purpose. % -% First comes the versions expecting a number to denote the number of -% arguments. -% -% \begin{function}{\def:NNn | -% \def:NNx | -% \def:cNn | -% \def:cNx | +% \begin{function}{\cs_set:Npn | +% \cs_set:Npx | +% \cs_set:cpn | +% \cs_set:cpx | % } % \begin{syntax} -% "\def:NNn" <cs> <num> "{" <code> "}" +% "\cs_set:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Like "\def_new:NNn" etc.\ but does not check the <cs> name. +% Like "\cs_set_nopar:Npn" but allows "\par" tokens in the arguments of the +% function being defined. +% \begin{texnote} +% These are equivalent to \TeX's "\long\def" and so on. These forms are +% recommended for low-level definitions as experience has shown that "\par" +% tokens often turn up in programming situations that wouldn't have been +% expected. +% \end{texnote} % \end{function} % -% \begin{function}{\gdef:NNn | -% \gdef:NNx | -% \gdef:cNn | -% \gdef:cNx | +% \begin{function}{\cs_gset:Npn | +% \cs_gset:Npx | +% \cs_gset:cpn | +% \cs_gset:cpx | % } % \begin{syntax} -% "\gdef:NNn" <cs> <num> "{" <code> "}" +% "\cs_gset:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Like "\def:NNn" but defines the <cs> globally. +% Global variant of "\cs_set:Npn". % \end{function} % -% -% \begin{function}{\def_long:NNn | -% \def_long:NNx | -% \def_long:cNn | -% \def_long:cNx | +% \begin{function}{\cs_set_nopar:Npn | +% \cs_set_nopar:Npx | +% \cs_set_nopar:cpn | +% \cs_set_nopar:cpx | % } % \begin{syntax} -% "\def_long:NNn" <cs> <num> "{" <code> "}" +% "\cs_set_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Like "\def:NNn" but allows "\par" tokens in the arguments of the -% function being defined. +% Like "\cs_new_nopar:Npn" etc.\ but does not check the <cs> name. +% \begin{texnote} +% "\cs_set_nopar:Npn" is the \LaTeX3 name for \TeX{}'s \tn{def} and +% "\cs_set_nopar:Npx" corresponds to the primitive \tn{edef}. The +% "\cs_set_nopar:cpn" function was known in \LaTeX2 as \tn{@namedef}. +% "\cs_set_nopar:cpx" has no equivalent. +% \end{texnote} % \end{function} % -% \begin{function}{\gdef_long:NNn | -% \gdef_long:NNx | -% \gdef_long:cNn | -% \gdef_long:cNx | +% \begin{function}{\cs_gset_nopar:Npn | +% \cs_gset_nopar:Npx | +% \cs_gset_nopar:cpn | +% \cs_gset_nopar:cpx | % } % \begin{syntax} -% "\gdef_long:NNn" <cs> <num> "{" <code> "}" +% "\cs_gset_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} -% Global variant of "\def_long:NNn". +% Like "\cs_set_nopar:Npn" but defines the <cs> globally. +% \begin{texnote} +% "\cs_gset_nopar:Npn" and "\cs_gset_nopar:Npx" +% are \TeX's \tn{gdef} and \tn{xdef}. +% \end{texnote} % \end{function} % -% \begin{function}{\def_protected:NNn | -% \def_protected:cNn | -% \def_protected:NNx | -% \def_protected:cNx | +% +% \begin{function}{\cs_set_protected:Npn | +% \cs_set_protected:Npx | +% \cs_set_protected:cpn | +% \cs_set_protected:cpx | % } % \begin{syntax} -% "\def_protected:NNn" <cs> <num> "{" <code> "}" +% "\cs_set_protected:Npn" <cs> <parms> \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% This also comes as a |long| version. If you for some reason want to -% expand it inside an |x| type expansion, prefix it with -% |\exp_after:NN \use_noop:|. +% These varieties allow |\par| tokens in the arguments of the +% function being defined. % \end{function} % -% \begin{function}{\gdef_protected:NNn | -% \gdef_protected:cNn | -% \gdef_protected:NNx | -% \gdef_protected:cNx | +% \begin{function}{\cs_gset_protected:Npn | +% \cs_gset_protected:Npx | +% \cs_gset_protected:cpn | +% \cs_gset_protected:cpx | % } % \begin{syntax} -% "\gdef_protected:NNn" <cs> <num> "{" <code> "}" +% "\cs_gset_protected:Npn" <cs> <parms> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long:NNn | -% \def_protected_long:cNn | -% \def_protected_long:NNx | -% \def_protected_long:cNx | +% \begin{function}{\cs_set_protected_nopar:Npn | +% \cs_set_protected_nopar:Npx | +% \cs_set_protected_nopar:cpn | +% \cs_set_protected_nopar:cpx | % } % \begin{syntax} -% "\def_protected_long:NNn" <cs> <num> "{" <code> "}" +% "\cs_set_protected_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% These varieties also allow |\par| tokens in the arguments of the -% function being defined. +% If you want for some reason to expand it inside an |x| type expansion, +% prefix it with |\exp_after:wN \prg_do_nothing:|. % \end{function} % -% \begin{function}{\gdef_protected_long:NNn | -% \gdef_protected_long:cNn | -% \gdef_protected_long:NNx | -% \gdef_protected_long:cNx | +% \begin{function}{\cs_gset_protected_nopar:Npn | +% \cs_gset_protected_nopar:Npx | +% \cs_gset_protected_nopar:cpn | +% \cs_gset_protected_nopar:cpx | % } % \begin{syntax} -% "\gdef_protected_long:NNn" <cs> <num> "{" <code> "}" +% "\cs_gset_protected_nopar:Npn" <cs> <parms> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% Secondly the ones that use the primitive parameter build-up: % -% \begin{function}{\def:Npn | -% \def:Npx | -% \def:cpn | -% \def:cpx | +% \subsection{Defining functions using the signature (no checks)} +% +% As above but now detecting the parameter text from inspecting the +% signature. +% +% \begin{function}{\cs_set:Nn | +% \cs_set:Nx | +% \cs_set:cn | +% \cs_set:cx | % } % \begin{syntax} -% "\def:Npn" <cs> <parms> "{" <code> "}" +% "\cs_set:Nn" <cs> \Arg{code} % \end{syntax} -% Like "\def_new:Npn" etc.\ but does not check the <cs> name. -% \begin{texnote} -% "\def:Npn" is the \LaTeX3 name for \TeX{}'s \tn{def} and "\def:Npx" -% corresponds to the primitive \tn{edef}. The "\def:cpn" function was -% known in \LaTeX2 as \tn{@namedef}. "\def:cpx" has no equivalent. -% \end{texnote} +% Like "\cs_set_nopar:Nn" but allows "\par" tokens in the arguments of the +% function being defined. % \end{function} % -% \begin{function}{\gdef:Npn | -% \gdef:Npx | -% \gdef:cpn | -% \gdef:cpx | +% \begin{function}{\cs_gset:Nn | +% \cs_gset:Nx | +% \cs_gset:cn | +% \cs_gset:cx | % } % \begin{syntax} -% "\gdef:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gset:Nn" <cs> \Arg{code} % \end{syntax} -% Like "\def:Npn" but defines the <cs> globally. -% \begin{texnote} -% "\gdef:Npn" and "\gdef:Npx" are known to \TeX{}hackers as \tn{gdef} -% and \tn{xdef}. -% \end{texnote} +% Global variant of "\cs_set:Nn". % \end{function} % -% -% \begin{function}{\def_long:Npn | -% \def_long:Npx | -% \def_long:cpn | -% \def_long:cpx | +% \begin{function}{\cs_set_nopar:Nn | +% \cs_set_nopar:Nx | +% \cs_set_nopar:cn | +% \cs_set_nopar:cx | % } % \begin{syntax} -% "\def_long:Npn" <cs> <parms> "{" <code> "}" +% "\cs_set_nopar:Nn" <cs> \Arg{code} % \end{syntax} -% Like "\def:Npn" but allows "\par" tokens in the arguments of the -% function being defined. +% Like "\cs_new_nopar:Nn" etc.\ but does not check the <cs> name. % \end{function} % -% \begin{function}{\gdef_long:Npn | -% \gdef_long:Npx | -% \gdef_long:cpn | -% \gdef_long:cpx | +% \begin{function}{\cs_gset_nopar:Nn | +% \cs_gset_nopar:Nx | +% \cs_gset_nopar:cn | +% \cs_gset_nopar:cx | % } % \begin{syntax} -% "\gdef_long:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gset_nopar:Nn" <cs> \Arg{code} % \end{syntax} -% Global variant of "\def_long:Npn". +% Like "\cs_set_nopar:Nn" but defines the <cs> globally. % \end{function} % -% \begin{function}{\def_protected:Npn | -% \def_protected:cpn | -% \def_protected:Npx | -% \def_protected:cpx | +% \begin{function}{\cs_set_protected:Nn | +% \cs_set_protected:cn | +% \cs_set_protected:Nx | +% \cs_set_protected:cx | % } % \begin{syntax} -% "\def_protected:Npn" <cs> <parms> "{" <code> "}" +% "\cs_set_protected:Nn" <cs> \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% This also comes as a |long| version. If you for some reason want to -% expand it inside an |x| type expansion, prefix it with -% |\exp_after:NN \use_noop:|. +% These varieties also allow |\par| tokens in the arguments of the +% function being defined. % \end{function} % -% \begin{function}{\gdef_protected:Npn | -% \gdef_protected:cpn | -% \gdef_protected:Npx | -% \gdef_protected:cpx | +% \begin{function}{\cs_gset_protected:Nn | +% \cs_gset_protected:cn | +% \cs_gset_protected:Nx | +% \cs_gset_protected:cx | % } % \begin{syntax} -% "\gdef_protected:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gset_protected:Nn" <cs> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long:Npn | -% \def_protected_long:cpn | -% \def_protected_long:Npx | -% \def_protected_long:cpx | +% \begin{function}{\cs_set_protected_nopar:Nn | +% \cs_set_protected_nopar:cn | +% \cs_set_protected_nopar:Nx | +% \cs_set_protected_nopar:cx | % } % \begin{syntax} -% "\def_protected_long:Npn" <cs> <parms> "{" <code> "}" +% "\cs_set_protected_nopar:Nn" <cs> \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% These varieties also allow |\par| tokens in the arguments of the -% function being defined. +% This also comes as a |long| version. If you for some reason want to +% expand it inside an |x| type expansion, prefix it with +% |\exp_after:wN \prg_do_nothing:|. % \end{function} % -% \begin{function}{\gdef_protected_long:Npn | -% \gdef_protected_long:cpn | -% \gdef_protected_long:Npx | -% \gdef_protected_long:cpx | +% \begin{function}{\cs_gset_protected_nopar:Nn | +% \cs_gset_protected_nopar:cn | +% \cs_gset_protected_nopar:Nx | +% \cs_gset_protected_nopar:cx | % } % \begin{syntax} -% "\gdef_protected_long:Npn" <cs> <parms> "{" <code> "}" +% "\cs_gset_protected_nopar:Nn" <cs> \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % % -% \begin{function}{\let:NN | -% \let:cN | -% \let:Nc | -% \let:cc | -% \glet:NN | -% \glet:cN | -% \glet:Nc | -% \glet:cc -% } +% \subsection{Undefining functions} +% +% \begin{function}{ \cs_gundefine:N } +% \begin{syntax} +% "\cs_gundefine:N" <cs> +% \end{syntax} +% Undefines the control sequence globally. +% \end{function} +% +% +% \subsection{Copying function definitions} +% +% \begin{function}{ \cs_new_eq:NN | +% \cs_new_eq:cN | +% \cs_new_eq:Nc | +% \cs_new_eq:cc | +% \cs_gnew_eq:NN | +% \cs_gnew_eq:cN | +% \cs_gnew_eq:Nc | +% \cs_gnew_eq:cc } +% \begin{syntax} +% "\cs_new_eq:NN" <cs1> <cs2> +% \end{syntax} +% Gives the function <cs1> locally or globally the current meaning of <cs2>. +% If <cs1> already exists then an error is called. +% \end{function} +% +% +% \begin{function}{\cs_set_eq:NN | +% \cs_set_eq:cN | +% \cs_set_eq:Nc | +% \cs_set_eq:cc | +% \cs_gset_eq:NN | +% \cs_gset_eq:cN | +% \cs_gset_eq:Nc | +% \cs_gset_eq:cc } % \begin{syntax} -% "\let:cN" <cs1> <cs2> +% "\cs_set_eq:cN" <cs1> <cs2> % \end{syntax} % Gives the function <cs1> the current meaning of <cs2>. Again, we may % always do this globally. % \end{function} % -% \begin{function}{\let:NwN} +% \begin{function}{\cs_set_eq:NwN} % \begin{syntax} -% "\let:NwN" <cs1> <cs2> -% "\let:NwN" <cs1> "=" <cs2> +% "\cs_set_eq:NwN" <cs1> <cs2> +% "\cs_set_eq:NwN" <cs1> "=" <cs2> % \end{syntax} % These functions assign the meaning of <cs2> locally or globally to the % function <cs1>. Because the \TeX{} primitive operation is being used @@ -1002,67 +1162,109 @@ % <cs1> and <cs2> the name contains a "w". (Not happy about this % convention!). % \begin{texnote} -% "\let:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. +% "\cs_set_eq:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. % \end{texnote} % \end{function} % +% \subsection{Internal functions} % -% \subsection{Defining test functions} % +% \begin{function}{ \pref_global:D | +% \pref_long:D | +% \pref_protected:D } +% \begin{syntax} +% "\pref_global:D" "\cs_set_nopar:Npn" +% \end{syntax} +% Prefix functions that can be used in front of some definition +% functions (namely \ldots). The result of prefixing a function +% definition with "\pref_global:D" makes the definition global, +% "\pref_long:D" change the argument scanning mechanism so that it +% allows "\par" tokens in the argument of the prefixed function, +% and "\pref_protected:D" makes the definition robust in "\write"s etc. % -% \begin{function}{ -% \def_test_function:npn | -% \def_long_test_function:npn | -% \def_test_function_new:npn | -% \def_long_test_function_new:npn | -% } -% \begin{syntax} -% "\def_test_function_new:npn" "{"name"}" <parms> "{"<test>"}" -% \end{syntax} -% Define all the common test cases for a simple test to reduce the -% risk of typos. As an example here's how we defined the functions -% "\cs_free:cTF", "\cs_free:cT" and "\cs_free:cF". You just have to -% fill in the test. -% \begin{verbatim} -% \def_test_function:npn{cs_free:c} #1 { -% \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} -% \end{verbatim} -% Be careful not to use this function inside some primitive -% conditional as \TeX\ will most likely get confused because of the -% unmatched conditionals. +% None of these internal functions should be used by a programmer since +% the necessary combinations are all available as separate function, +% e.g., "\cs_set:Npn" is internally implemented as "\pref_long:D" +% "\cs_set_nopar:Npn". +% \begin{texnote} +% These prefixes are the primitives \tn{global}, \tn{long}, and +% \tn{protected}. The \tn{outer} prefix isn't used at all within \LaTeX3 +% because \ldots (it causes more hassle than it's worth? It's nevery proved +% useful in any meaningful way?) +% \end{texnote} % \end{function} % +% \section{The innards of a function} % -% \subsection{The innards of a function} -% -% \begin{function}{\cs_to_str:N} +% \begin{function}{\cs_to_str:N / (EXP)} % \begin{syntax} % "\cs_to_str:N" <cs> % \end{syntax} -% This function return the name of <cs> as a sequence of letters with +% This function returns the name of <cs> as a sequence of letters with % the escape character removed. % \end{function} % -% \begin{function}{\token_to_string:N} +% \begin{function}{\token_to_str:N / (EXP) | \token_to_str:c / (EXP)} % \begin{syntax} -% "\token_to_string:N" <arg> +% "\token_to_str:N" <arg> % \end{syntax} % This function return the name of <arg> as a sequence of letters % including the escape character. +% \begin{texnote} +% This is \TeX's \tn{string}. +% \end{texnote} % \end{function} % -% \begin{function}{\token_to_meaning:N} +% \begin{function}{\token_to_meaning:N / (EXP)} % \begin{syntax} % "\token_to_meaning:N" <arg> % \end{syntax} % This function returns the type and definition of <arg> as a sequence % of letters. +% \begin{texnote} +% This is \TeX's \tn{meaning}. +% \end{texnote} +% \end{function} +% +% +% \begin{function}{\cs_get_function_name:N / (EXP) | +% \cs_get_function_signature:N / (EXP)} +% \begin{syntax} +% "\cs_get_function_name:N" "\"<fn>":"<args> +% \end{syntax} +% The "name" variant strips off the leading escape character and the +% trailing argument specification (including the colon) to return +% <fn>. The "signature" variants does the same but returns the +% signature <args> instead. % \end{function} % +% +% \begin{function}{\cs_split_function:NN / (EXP)} +% \begin{syntax} +% "\cs_split_function:NN" "\"<fn>":"<args> <post process> +% \end{syntax} +% Strips off the leading escape character, splits off the signature +% without the colon, informs whether or not a colon was present and +% then prefixes these results with <post process>, i.e., <post +% process>\Arg{name}\Arg{signature}\meta{true}/\meta{false}. For +% example, "\cs_get_function_name:N" is nothing more than +% "\cs_split_function:NN" "\"<fn>":"<args> "\use_i:nnn". +% \end{function} +% +% +% \begin{function}{\cs_get_arg_count_from_signature:N / (EXP)} +% \begin{syntax} +% "\cs_get_arg_count_from_signature:N" "\"<fn>":"<args> +% \end{syntax} +% Returns the number of chars in <args>, signifying the number of arguments +% that the function uses. +% \end{function} +% +% % Other functions regarding arbitrary tokens can be found in the % \textsf{l3token} module. % -% \subsection{Grouping and scanning} +% \section{Grouping and scanning} % % \begin{function}{\scan_stop:} % \begin{syntax} @@ -1087,32 +1289,52 @@ % \end{texnote} % \end{function} % +% \begin{function}{\group_execute_after:N} +% \begin{syntax} +% "\group_execute_after:N" <token> +% \end{syntax} +% Adds <token> to the list of tokens to be inserted after the +% current group ends (through an explicit or implicit "\group_end:"). +% \begin{texnote} +% This is \TeX's \tn{aftergroup}. +% \end{texnote} +% \end{function} +% % -% \subsection{Engine specific definitions} +% \section{Checking the engine} +% +% \begin{function}{\xetex_if_engine: / (TF)(EXP)} +% \begin{syntax} +% "\xetex_if_engine:TF" \Arg{true code} \Arg{false code} +% \end{syntax} +% This function detects if we're running a Xe\TeX-based format. +% \end{function} % -% \begin{function}{\engine_if_aleph:TF} +% \begin{function}{\luatex_if_engine: / (TF)(EXP)} % \begin{syntax} -% "\engine_if_aleph:TF" "{"<true code>"}" "{"<false code>"}" +% "\luatex_if_engine:TF" \Arg{true code} \Arg{false code} % \end{syntax} -% This function detects if we're running an Aleph based format. This -% is particularly useful when allocating registers. +% This function detects if we're running a Lua\TeX-based format. % \end{function} % +% \begin{variable}{\c_xetex_is_engine_bool|\c_luatex_is_engine_bool} +% Boolean variables used for the above functions. +% \end{variable} % +% \end{documentation} % -% \StopEventually{} +% \begin{implementation} % +% \section{\pkg{l3basics} implementation} % -% \subsection{The Implementation} -% We start by ensuring that the required packages are loaded. We need -% \textsf{l3names} to get things going but we actually need it very -% early on, so it is loaded at the very top of this file. Also, most -% of the code below won't run until \textsf{l3expan} has been +% We need \textsf{l3names} to get things going but we actually need it very +% early on, so it is loaded at the very top of the file \file{l3basics.dtx}. +% Also, most of the code below won't run until \textsf{l3expan} has been % loaded. % -% \subsubsection{Renaming some \TeX{} primitives (again)} +% \subsection{Renaming some \TeX{} primitives (again)} % -% \begin{macro}{\let:NwN} +% \begin{macro}{\cs_set_eq:NwN} % Having given all the tex primitives a consistent name, we need to % give sensible names to the ones we actually want to use. % These will be defined as needed in the appropriate modules, but @@ -1120,30 +1342,39 @@ % in terms of csname usage, an alternative scheme would be to just use % the ``tex\ldots D'' name in the cases where no good alternative exists.} % \begin{macrocode} -%<package>\ProvidesExplPackage -%<package> {\filename}{\filedate}{\fileversion}{\filedescription} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +%</package> %<*initex|package> -\tex_let:D \let:NwN \tex_let:D +\tex_let:D \cs_set_eq:NwN \tex_let:D % \end{macrocode} % \end{macro} % \begin{macro}{\if_true:} % \begin{macro}{\if_false:} +% \begin{macro}{\or:} % \begin{macro}{\else:} % \begin{macro}{\fi:} % \begin{macro}{\reverse_if:N} % \begin{macro}{\if:w} +% \begin{macro}{\if_bool:N} +% \begin{macro}{\if_predicate:w} % \begin{macro}{\if_charcode:w} % \begin{macro}{\if_catcode:w} % Then some conditionals. % \begin{macrocode} -\let:NwN \if_true: \tex_iftrue:D -\let:NwN \if_false: \tex_iffalse:D -\let:NwN \else: \tex_else:D -\let:NwN \fi: \tex_fi:D -\let:NwN \reverse_if:N \etex_unless:D -\let:NwN \if:w \tex_if:D -\let:NwN \if_charcode:w \tex_if:D -\let:NwN \if_catcode:w \tex_ifcat:D +\cs_set_eq:NwN \if_true: \tex_iftrue:D +\cs_set_eq:NwN \if_false: \tex_iffalse:D +\cs_set_eq:NwN \or: \tex_or:D +\cs_set_eq:NwN \else: \tex_else:D +\cs_set_eq:NwN \fi: \tex_fi:D +\cs_set_eq:NwN \reverse_if:N \etex_unless:D +\cs_set_eq:NwN \if:w \tex_if:D +\cs_set_eq:NwN \if_bool:N \tex_ifodd:D +\cs_set_eq:NwN \if_predicate:w \tex_ifodd:D +\cs_set_eq:NwN \if_charcode:w \tex_if:D +\cs_set_eq:NwN \if_catcode:w \tex_ifcat:D % \end{macrocode} % \end{macro} % \end{macro} @@ -1153,28 +1384,26 @@ % \end{macro} % \end{macro} % \end{macro} -% \begin{macro}{\if_meaning:NN} -% \begin{macro}{\if_token_eq:NN} -% \begin{macro}{\if_cs_meaning_eq:NN} -% Some different names for |\ifx|.\footnote{MH: Clean up at some point} -% \begin{macrocode} -\let:NwN \if_meaning:NN \tex_ifx:D -\let:NwN \if_token_eq:NN \tex_ifx:D -\let:NwN \if_cs_meaning_eq:NN\tex_ifx:D -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% +% \begin{macro}{\if_meaning:w} +% \begin{macrocode} +\cs_set_eq:NwN \if_meaning:w \tex_ifx:D +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\if_mode_math:} % \begin{macro}{\if_mode_horizontal:} % \begin{macro}{\if_mode_vertical:} % \begin{macro}{\if_mode_inner:} % \TeX{} lets us detect some if its modes. % \begin{macrocode} -\let:NwN \if_mode_math: \tex_ifmmode:D -\let:NwN \if_mode_horizontal:\tex_ifhmode:D -\let:NwN \if_mode_vertical: \tex_ifvmode:D -\let:NwN \if_mode_inner: \tex_ifinner:D +\cs_set_eq:NwN \if_mode_math: \tex_ifmmode:D +\cs_set_eq:NwN \if_mode_horizontal: \tex_ifhmode:D +\cs_set_eq:NwN \if_mode_vertical: \tex_ifvmode:D +\cs_set_eq:NwN \if_mode_inner: \tex_ifinner:D % \end{macrocode} % \end{macro} % \end{macro} @@ -1183,29 +1412,30 @@ % \begin{macro}{\if_cs_exist:N} % \begin{macro}{\if_cs_exist:w} % \begin{macrocode} -\let:NwN \if_cs_exist:N \etex_ifdefined:D -\let:NwN \if_cs_exist:w \etex_ifcsname:D +\cs_set_eq:NwN \if_cs_exist:N \etex_ifdefined:D +\cs_set_eq:NwN \if_cs_exist:w \etex_ifcsname:D % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\exp_after:NN} +% \begin{macro}{\exp_after:wN} % \begin{macro}{\exp_not:N} % \begin{macro}{\exp_not:n} % The three |\exp_| functions are used in the \textsf{l3expan} module % where they are described. % \begin{macrocode} -\let:NwN \exp_after:NN \tex_expandafter:D -\let:NwN \exp_not:N \tex_noexpand:D -\let:NwN \exp_not:n \etex_unexpanded:D +\cs_set_eq:NwN \exp_after:wN \tex_expandafter:D +\cs_set_eq:NwN \exp_not:N \tex_noexpand:D +\cs_set_eq:NwN \exp_not:n \etex_unexpanded:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\io_put_deferred:Nx} +% \begin{macro}{\iow_shipout_x:Nn} % \begin{macro}{\token_to_meaning:N} -% \begin{macro}{\token_to_string:N} +% \begin{macro}{\token_to_str:N} +% \begin{macro}{\token_to_str:c} % \begin{macro}{\cs:w} % \begin{macro}{\cs_end:} % \begin{macro}{\cs_meaning:N} @@ -1213,15 +1443,16 @@ % \begin{macro}{\cs_show:N} % \begin{macro}{\cs_show:c} % \begin{macrocode} -\let:NwN \io_put_deferred:Nx \tex_write:D -\let:NwN \token_to_meaning:N \tex_meaning:D -\let:NwN \token_to_string:N \tex_string:D -\let:NwN \cs:w \tex_csname:D -\let:NwN \cs_end: \tex_endcsname:D -\let:NwN \cs_meaning:N \tex_meaning:D -\tex_def:D \cs_meaning:c #1{\exp_after:NN\cs_meaning:N\cs:w #1\cs_end:} -\let:NwN \cs_show:N \tex_show:D -\tex_def:D \cs_show:c #1{\exp_after:NN\cs_show:N\cs:w #1\cs_end:} +\cs_set_eq:NwN \iow_shipout_x:Nn \tex_write:D +\cs_set_eq:NwN \token_to_meaning:N \tex_meaning:D +\cs_set_eq:NwN \token_to_str:N \tex_string:D +\cs_set_eq:NwN \cs:w \tex_csname:D +\cs_set_eq:NwN \cs_end: \tex_endcsname:D +\cs_set_eq:NwN \cs_meaning:N \tex_meaning:D +\tex_def:D \cs_meaning:c {\exp_args:Nc\cs_meaning:N} +\cs_set_eq:NwN \cs_show:N \tex_show:D +\tex_def:D \cs_show:c {\exp_args:Nc\cs_show:N} +\tex_def:D \token_to_str:c {\exp_args:Nc\token_to_str:N} % \end{macrocode} % \end{macro} % \end{macro} @@ -1232,6 +1463,8 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% % \begin{macro}{\scan_stop:} % \begin{macro}{\group_begin:} % \begin{macro}{\group_end:} @@ -1239,70 +1472,69 @@ % versions that are safe inside alignments. These safe versions are % defined in the \textsf{l3prg} module. % \begin{macrocode} -\let:NwN \scan_stop: \tex_relax:D -\let:NwN \group_begin: \tex_begingroup:D -\let:NwN \group_end: \tex_endgroup:D +\cs_set_eq:NwN \scan_stop: \tex_relax:D +\cs_set_eq:NwN \group_begin: \tex_begingroup:D +\cs_set_eq:NwN \group_end: \tex_endgroup:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\group_execute_after:N} % \begin{macrocode} -\let:NwN \group_execute_after:N \tex_aftergroup:D +\cs_set_eq:NwN \group_execute_after:N \tex_aftergroup:D % \end{macrocode} % \end{macro} -% \begin{macro}{\the_internal:D} % \begin{macro}{\pref_global:D} % \begin{macro}{\pref_long:D} % \begin{macro}{\pref_protected:D} -% These following names are temporary and should be removed as soon -% as possible (April 1998). -% \begin{macrocode} -\let:NwN \the_internal:D \tex_the:D -\let:NwN \pref_global:D \tex_global:D -% \end{macrocode} -% "\pref_long:D" has been documented for years but didn't exist\dots{} -% Added it and the robustness prefix. % \begin{macrocode} -\let:NwN \pref_long:D \tex_long:D -\let:NwN \pref_protected:D \etex_protected:D +\cs_set_eq:NwN \pref_global:D \tex_global:D +\cs_set_eq:NwN \pref_long:D \tex_long:D +\cs_set_eq:NwN \pref_protected:D \etex_protected:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % % -% \subsubsection {Defining functions} +% \subsection {Defining functions} % % % We start by providing functions for the typical definition % functions. First the local ones. % -% \begin{macro}{\def:Npn} -% \begin{macro}{\def:Npx} -% \begin{macro}{\def_long:Npn} -% \begin{macro}{\def_long:Npx} -% \begin{macro}{\def_protected:Npn} -% \begin{macro}{\def_protected:Npx} -% \begin{macro}{\def_protected_long:Npn} -% \begin{macro}{\def_protected_long:Npx} +% \begin{macro}{\cs_set_nopar:Npn} +% \begin{macro}{\cs_set_nopar:Npx} +% \begin{macro}{\cs_set:Npn} +% \begin{macro}{\cs_set:Npx} +% \begin{macro}{\cs_set_protected_nopar:Npn} +% \begin{macro}{\cs_set_protected_nopar:Npx} +% \begin{macro}{\cs_set_protected:Npn} +% \begin{macro}{\cs_set_protected:Npx} % All assignment functions in \LaTeX3 should be naturally robust; % after all, the \TeX\ primitives for assignments are and it can be % a cause of problems if others aren't. % \begin{macrocode} -\let:NwN \def:Npn \tex_def:D -\let:NwN \def:Npx \tex_edef:D -\pref_protected:D \def:Npn \def_long:Npn {\pref_long:D \def:Npn} -\pref_protected:D \def:Npn \def_long:Npx {\pref_long:D \def:Npx} -\pref_protected:D \def:Npn \def_protected:Npn {\pref_protected:D \def:Npn} -\pref_protected:D \def:Npn \def_protected:Npx {\pref_protected:D \def:Npx} -\def_protected:Npn \def_protected_long:Npn { - \pref_protected:D \pref_long:D \def:Npn +\cs_set_eq:NwN \cs_set_nopar:Npn \tex_def:D +\cs_set_eq:NwN \cs_set_nopar:Npx \tex_edef:D +\pref_protected:D \cs_set_nopar:Npn \cs_set:Npn { + \pref_long:D \cs_set_nopar:Npn +} +\pref_protected:D \cs_set_nopar:Npn \cs_set:Npx { + \pref_long:D \cs_set_nopar:Npx +} +\pref_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npn { + \pref_protected:D \cs_set_nopar:Npn +} +\pref_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npx { + \pref_protected:D \cs_set_nopar:Npx +} +\cs_set_protected_nopar:Npn \cs_set_protected:Npn { + \pref_protected:D \pref_long:D \cs_set_nopar:Npn } -\def_protected:Npn \def_protected_long:Npx { - \pref_protected:D \pref_long:D \def:Npx +\cs_set_protected_nopar:Npn \cs_set_protected:Npx { + \pref_protected:D \pref_long:D \cs_set_nopar:Npx } % \end{macrocode} % \end{macro} @@ -1314,27 +1546,35 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\gdef:Npn} -% \begin{macro}{\gdef:Npx} -% \begin{macro}{\gdef_long:Npn} -% \begin{macro}{\gdef_long:Npx} -% \begin{macro}{\gdef_protected:Npn} -% \begin{macro}{\gdef_protected:Npx} -% \begin{macro}{\gdef_protected_long:Npn} -% \begin{macro}{\gdef_protected_long:Npx} +% \begin{macro}{\cs_gset_nopar:Npn} +% \begin{macro}{\cs_gset_nopar:Npx} +% \begin{macro}{\cs_gset:Npn} +% \begin{macro}{\cs_gset:Npx} +% \begin{macro}{\cs_gset_protected_nopar:Npn} +% \begin{macro}{\cs_gset_protected_nopar:Npx} +% \begin{macro}{\cs_gset_protected:Npn} +% \begin{macro}{\cs_gset_protected:Npx} % Global versions of the above functions. % \begin{macrocode} -\let:NwN \gdef:Npn \tex_gdef:D -\let:NwN \gdef:Npx \tex_xdef:D -\def_protected:Npn \gdef_long:Npn {\pref_long:D \gdef:Npn} -\def_protected:Npn \gdef_long:Npx {\pref_long:D \gdef:Npx} -\def_protected:Npn \gdef_protected:Npn {\pref_protected:D \gdef:Npn} -\def_protected:Npn \gdef_protected:Npx {\pref_protected:D \gdef:Npx} -\def_protected:Npn \gdef_protected_long:Npn { - \pref_protected:D \pref_long:D \gdef:Npn +\cs_set_eq:NwN \cs_gset_nopar:Npn \tex_gdef:D +\cs_set_eq:NwN \cs_gset_nopar:Npx \tex_xdef:D +\cs_set_protected_nopar:Npn \cs_gset:Npn { + \pref_long:D \cs_gset_nopar:Npn } -\def_protected:Npn \gdef_protected_long:Npx { - \pref_protected:D \pref_long:D \gdef:Npx +\cs_set_protected_nopar:Npn \cs_gset:Npx { + \pref_long:D \cs_gset_nopar:Npx +} +\cs_set_protected_nopar:Npn \cs_gset_protected_nopar:Npn { + \pref_protected:D \cs_gset_nopar:Npn +} +\cs_set_protected_nopar:Npn \cs_gset_protected_nopar:Npx { + \pref_protected:D \cs_gset_nopar:Npx +} +\cs_set_protected_nopar:Npn \cs_gset_protected:Npn { + \pref_protected:D \pref_long:D \cs_gset_nopar:Npn +} +\cs_set_protected_nopar:Npn \cs_gset_protected:Npx { + \pref_protected:D \pref_long:D \cs_gset_nopar:Npx } % \end{macrocode} % \end{macro} @@ -1346,34 +1586,666 @@ % \end{macro} % \end{macro} % -% \subsubsection{Predicate implementation} % +% +% \subsection{Selecting tokens} +% +% \begin{macro}{\use:c} +% This macro grabs its argument and returns a csname from it. +% \begin{macrocode} +\cs_set:Npn \use:c #1 { \cs:w#1\cs_end: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\use:n} +% \begin{macro}{\use:nn} +% \begin{macro}{\use:nnn} +% \begin{macro}{\use:nnnn} +% These macro grabs its arguments and returns it back to the input +% (with outer braces removed). "\use:n" is defined earlier for bootstrapping. +% \begin{macrocode} +\cs_set:Npn \use:n #1 {#1} +\cs_set:Npn \use:nn #1#2 {#1#2} +\cs_set:Npn \use:nnn #1#2#3 {#1#2#3} +\cs_set:Npn \use:nnnn #1#2#3#4 {#1#2#3#4} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\use_i:nn} +% \begin{macro}{\use_ii:nn} +% These macros are needed to provide functions with true and false +% cases, as introduced by Michael some time ago. By using +% |\exp_after:wN| |\use_i:nn | |\else:| constructions it +% is possible to write code where the true or false case is able to +% access the following tokens from the input stream, which is not +% possible if the |\c_true_bool| syntax is used. +% \begin{macrocode} +\cs_set:Npn \use_i:nn #1#2 {#1} +\cs_set:Npn \use_ii:nn #1#2 {#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% \begin{macro}{\use_i:nnn} +% \begin{macro}{\use_ii:nnn} +% \begin{macro}{\use_iii:nnn} +% \begin{macro}{\use_i:nnnn} +% \begin{macro}{\use_ii:nnnn} +% \begin{macro}{\use_iii:nnnn} +% \begin{macro}{\use_iv:nnnn} +% \begin{macro}{\use_i_ii:nnn} +% We also need something for picking up arguments from a longer +% list. +% \begin{macrocode} +\cs_set:Npn \use_i:nnn #1#2#3{#1} +\cs_set:Npn \use_ii:nnn #1#2#3{#2} +\cs_set:Npn \use_iii:nnn #1#2#3{#3} +\cs_set:Npn \use_i:nnnn #1#2#3#4{#1} +\cs_set:Npn \use_ii:nnnn #1#2#3#4{#2} +\cs_set:Npn \use_iii:nnnn #1#2#3#4{#3} +\cs_set:Npn \use_iv:nnnn #1#2#3#4{#4} +\cs_set:Npn \use_i_ii:nnn #1#2#3{#1#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\use_none_delimit_by_q_nil:w} +% \begin{macro}{\use_none_delimit_by_q_stop:w} +% \begin{macro}{\use_none_delimit_by_q_recursion_stop:w} +% Functions that gobble everything until they see either |\q_nil| or +% |\q_stop| resp. +% \begin{macrocode} +\cs_set:Npn \use_none_delimit_by_q_nil:w #1\q_nil{} +\cs_set:Npn \use_none_delimit_by_q_stop:w #1\q_stop{} +\cs_set:Npn \use_none_delimit_by_q_recursion_stop:w #1 \q_recursion_stop {} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\use_i_delimit_by_q_nil:nw} +% \begin{macro}{\use_i_delimit_by_q_stop:nw} +% \begin{macro}{\use_i_delimit_by_q_recursion_stop:nw} +% Same as above but execute first argument after gobbling. Very +% useful when you need to skip the rest of a mapping sequence but +% want an easy way to control what should be expanded next. +% \begin{macrocode} +\cs_set:Npn \use_i_delimit_by_q_nil:nw #1#2\q_nil{#1} +\cs_set:Npn \use_i_delimit_by_q_stop:nw #1#2\q_stop{#1} +\cs_set:Npn \use_i_delimit_by_q_recursion_stop:nw #1#2 \q_recursion_stop {#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\use_i_after_fi:nw} +% \begin{macro}{\use_i_after_else:nw} +% \begin{macro}{\use_i_after_or:nw} +% \begin{macro}{\use_i_after_orelse:nw} +% Returns the first argument after ending the conditional. +% \begin{macrocode} +\cs_set:Npn \use_i_after_fi:nw #1\fi:{\fi: #1} +\cs_set:Npn \use_i_after_else:nw #1\else:#2\fi:{\fi: #1} +\cs_set:Npn \use_i_after_or:nw #1\or: #2\fi: {\fi:#1} +\cs_set:Npn \use_i_after_orelse:nw #1 #2#3\fi: {\fi:#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Gobbling tokens from input} +% +% \begin{macro}{\use_none:n} +% \begin{macro}{\use_none:nn} +% \begin{macro}{\use_none:nnn} +% \begin{macro}{\use_none:nnnn} +% \begin{macro}{\use_none:nnnnn} +% \begin{macro}{\use_none:nnnnnn} +% \begin{macro}{\use_none:nnnnnnn} +% \begin{macro}{\use_none:nnnnnnnn} +% \begin{macro}{\use_none:nnnnnnnnn} +% To gobble tokens from the input we use a standard naming +% convention: the number of tokens gobbled is given by the number of +% |n|'s following the |:| in the name. Although defining +% |\use_none:nnn| and above as separate calls of |\use_none:n| and +% |\use_none:nn| is slightly faster, this is very non-intuitive to +% the programmer who will assume that expanding such a function once +% will take care of gobbling all the tokens in one go. +% \begin{macrocode} +\cs_set:Npn \use_none:n #1{} +\cs_set:Npn \use_none:nn #1#2{} +\cs_set:Npn \use_none:nnn #1#2#3{} +\cs_set:Npn \use_none:nnnn #1#2#3#4{} +\cs_set:Npn \use_none:nnnnn #1#2#3#4#5{} +\cs_set:Npn \use_none:nnnnnn #1#2#3#4#5#6{} +\cs_set:Npn \use_none:nnnnnnn #1#2#3#4#5#6#7{} +\cs_set:Npn \use_none:nnnnnnnn #1#2#3#4#5#6#7#8{} +\cs_set:Npn \use_none:nnnnnnnnn #1#2#3#4#5#6#7#8#9{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Expansion control from l3expan} +% +% \begin{macro}{\exp_args:Nc} +% Moved here for now as it is going to be used right away. +% \begin{macrocode} +\cs_set:Npn \exp_args:Nc #1#2{\exp_after:wN#1\cs:w#2\cs_end:} +% \end{macrocode} +% \end{macro} +% +% \subsection{Conditional processing and definitions} +% +% Underneath any predicate function (|_p|) or other conditional forms +% (|TF|, etc.) is a built-in logic saying that it after all of the +% testing and processing must return the \meta{state} this leaves +% \TeX\ in. Therefore, a simple user interface could be something like +% \begin{verbatim} +% \if_meaning:w #1#2 \prg_return_true: \else: +% \if_meaning:w #1#3 \prg_return_true: \else: +% \prg_return_false: +% \fi: \fi: +% \end{verbatim} +% Usually, a \TeX\ programmer would have to insert a number of +% |\exp_after:wN|s to ensure the state value is returned at exactly +% the point where the last conditional is finished. However, that +% obscures the code and forces the \TeX\ programmer to prove that +% he/she knows the $2^{n}-1$ table. We therefore provide the simpler +% interface. +% +% \begin{macro}{\prg_return_true:} +% \begin{macro}{\prg_return_false:} +% These break statements put \TeX\ in a \m{true} or \m{false} state. +% The idea is that the expansion of |\tex_romannumeral:D \c_zero| is +% \m{null} so we set off a |\tex_romannumeral:D|. It will on its +% way expand any |\else:| or |\fi:| that are waiting to be discarded +% anyway before finally arriving at the |\c_zero| we will place +% right after the conditional. After this expansion has terminated, +% we issue either |\if_true:| or |\if_false:| to put \TeX\ in the +% correct state. +% \begin{macrocode} +\cs_set:Npn \prg_return_true: { \exp_after:wN\if_true:\tex_romannumeral:D } +\cs_set:Npn \prg_return_false: {\exp_after:wN\if_false:\tex_romannumeral:D } +% \end{macrocode} +% An extended state space could instead utilize |\tex_ifcase:D|: +% \begin{verbatim} +% \cs_set:Npn \prg_return_true: { +% \exp_after:wN\tex_ifcase:D \exp_after:wN \c_zero \tex_romannumeral:D +% } +% \cs_set:Npn \prg_return_false: { +% \exp_after:wN\tex_ifcase:D \exp_after:wN \c_one \tex_romannumeral:D +% } +% \cs_set:Npn \prg_return_error: { +% \exp_after:wN\tex_ifcase:D \exp_after:wN \c_two \tex_romannumeral:D +% } +% \end{verbatim} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\prg_set_conditional:Npnn,\prg_new_conditional:Npnn, +% \prg_set_protected_conditional:Npnn,\prg_new_protected_conditional:Npnn} +% The user functions for the types using parameter text from the +% programmer. Call aux function to grab parameters, split the base +% function into name and signature and then use, e.g., |\cs_set:Npn| +% to define it with. +% \begin{macrocode} +\cs_set:Npn \prg_set_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set:Npn {parm} + } +} +\cs_set:Npn \prg_new_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new:Npn {parm} + } +} +\cs_set:Npn \prg_set_protected_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set_protected:Npn {parm} + } +} +\cs_set:Npn \prg_new_protected_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new_protected:Npn {parm} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prg_set_conditional:Nnn,\prg_new_conditional:Nnn, +% \prg_set_protected_conditional:Nnn,\prg_new_protected_conditional:Nnn} +% The user functions for the types automatically inserting the +% correct parameter text based on the signature. Call aux function +% after calculating number of arguments, split the base function +% into name and signature and then use, e.g., |\cs_set:Npn| to +% define it with. +% \begin{macrocode} +\cs_set:Npn \prg_set_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} +\cs_set:Npn \prg_new_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} + +\cs_set:Npn \prg_set_protected_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set_protected:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} + +\cs_set:Npn \prg_new_protected_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new_protected:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\prg_get_parm_aux:nw,\prg_get_count_aux:nn} +% For the "Npnn" type we must grab the parameter text before +% continuing. We make this a very generic function that takes one +% argument before reading everything up to a left brace. Something +% similar for the "Nnn" type. +% \begin{macrocode} +\cs_set:Npn \prg_get_count_aux:nn #1#2 {#1{#2}} +\cs_set:Npn \prg_get_parm_aux:nw #1#2#{#1{#2}} +% \end{macrocode} +% \end{macro} +% \begin{macro}[aux]{\prg_generate_conditional_parm_aux:nnNNnnnn, +% \prg_generate_conditional_parm_aux:nw} +% +% The workhorse here is going through a list of desired forms, i.e., +% p, TF, T and F. The first three arguments come from splitting up +% the base form of the conditional, which gives the name, signature +% and a boolean to signal whether or not there was a colon in the +% name. For the time being, we do not use this piece of information +% but could well throw an error. The fourth argument is how to +% define this function, the fifth is the text "parm" or "count" for +% which version to use to define the functions, the sixth is the +% parameters to use (possibly empty) or number of arguments, the +% seventh is the list of forms to define, the eight is the +% replacement text which we will augment when defining the forms. +% \begin{macrocode} +\cs_set:Npn \prg_generate_conditional_aux:nnNNnnnn #1#2#3#4#5#6#7#8{ + \prg_generate_conditional_aux:nnw{#5}{ + #4{#1}{#2}{#6}{#8} + }#7,?, \q_recursion_stop +} +% \end{macrocode} +% Looping through the list of desired forms. First is the text "parm" +% or "count", second is five arguments packed together and third is +% the form. Use text and form to call the correct type. +% \begin{macrocode} +\cs_set:Npn \prg_generate_conditional_aux:nnw #1#2#3,{ + \if:w ?#3 + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + \use:c{prg_generate_#3_form_#1:Nnnnn} #2 + \prg_generate_conditional_aux:nnw{#1}{#2} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\prg_generate_p_form_parm:Nnnnn, +% \prg_generate_TF_form_parm:Nnnnn, +% \prg_generate_T_form_parm:Nnnnn, +% \prg_generate_F_form_parm:Nnnnn +% } +% How to generate the various forms. The "parm" types here takes the +% following arguments: 1: how to define (an N-type), 2: name, 3: +% signature, 4: parameter text (or empty), 5: replacement. +% \begin{macrocode} +\cs_set:Npn \prg_generate_p_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc #1 {#2_p:#3}#4{#5 \c_zero + \exp_after:wN\c_true_bool\else:\exp_after:wN\c_false_bool\fi: + } +} +\cs_set:Npn \prg_generate_TF_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc#1 {#2:#3TF}#4{#5 \c_zero + \exp_after:wN \use_i:nn \else: \exp_after:wN \use_ii:nn \fi: + } +} +\cs_set:Npn \prg_generate_T_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc#1 {#2:#3T}#4{#5 \c_zero + \else:\exp_after:wN\use_none:nn\fi:\use:n + } +} +\cs_set:Npn \prg_generate_F_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc#1 {#2:#3F}#4{#5 \c_zero + \exp_after:wN\use_none:nn\fi:\use:n + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\prg_generate_p_form_count:Nnnnn, +% \prg_generate_TF_form_count:Nnnnn, +% \prg_generate_T_form_count:Nnnnn, +% \prg_generate_F_form_count:Nnnnn +% } +% How to generate the various forms. The "count" types here use a +% number to insert the correct parameter text, otherwise like the +% "parm" functions above. +% \begin{macrocode} +\cs_set:Npn \prg_generate_p_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2_p:#3} #1 {#4}{#5 \c_zero + \exp_after:wN\c_true_bool\else:\exp_after:wN\c_false_bool\fi: + } +} +\cs_set:Npn \prg_generate_TF_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2:#3TF} #1 {#4}{#5 \c_zero + \exp_after:wN\use_i:nn\else:\exp_after:wN\use_ii:nn\fi: + } +} +\cs_set:Npn \prg_generate_T_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2:#3T} #1 {#4}{#5 \c_zero + \else:\exp_after:wN\use_none:nn\fi:\use:n + } +} +\cs_set:Npn \prg_generate_F_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2:#3F} #1 {#4}{#5 \c_zero + \exp_after:wN\use_none:nn\fi:\use:n + } +} +% \end{macrocode} +% \end{macro} +% +% All that is left is to define the canonical boolean true and false. % I think Michael originated the idea of expandable boolean tests. At % first these were supposed to expand into either \texttt{TT} or % \texttt{TF} to be tested using |\if:w| but this was later changed to -% \texttt{00} and \texttt{01}, so they can be used in logical -% operations (see the \textsf{l3prg} module). We need this from the -% get-go. +% \texttt{00} and \texttt{01}, so they could be used in logical +% operations. Later again they were changed to being numerical +% constants with values of $1$ for true and $0$ for false. We need +% this from the get-go. % -% \begin{macro}{\c_true} -% \begin{macro}{\c_false} +% \begin{macro}{\c_true_bool} +% \begin{macro}{\c_false_bool} % Here are the canonical boolean values. % \begin{macrocode} -\def:Npn \c_true {00} -\def:Npn \c_false {01} +\tex_chardef:D \c_true_bool = 1~ +\tex_chardef:D \c_false_bool = 0~ % \end{macrocode} % \end{macro} % \end{macro} % -% \subsubsection {Defining and checking (new) functions} +% +% \subsection{Dissecting a control sequence} +% +% \begin{macro}{\cs_to_str:N} +% \begin{macro}[aux]{\cs_to_str_aux:w} +% This converts a control sequence into the character string of its +% name, removing the leading escape character. This turns out to be +% a non-trivial matter as there a different cases: +% \begin{itemize} +% \item The usual case of a printable escape character; +% \item the case of a non-printable escape characters, e.g., when +% the value of |\tex_escapechar:D| is negative; +% \item when the escape character is a space. +% \end{itemize} +% The route chosen is this: If |\token_to_str:N \a| produces a +% non-space escape char, then this will produce two tokens. If the +% escape char is non-printable, only one token is produced. If the +% escape char is a space, then a space token plus one token +% character token is produced. If we augment the result of this +% expansion with the letters |ax| we get the following three +% scenarios (with \meta{X} being a printable non-space escape +% character): +% \begin{itemize} +% \item \meta{X}"aax" +% \item "aax" +% \item " aax" +% \end{itemize} +% In the second and third case, putting an auxiliary function in front +% reading undelimited arguments will treat them the same, removing the +% space token for us automatically. Therefore, if we test the second +% and third argument of what such a function reads, in case 1 we will +% get true and in cases 2 and 3 we will get false. If we choose to +% optimize for the usual case of a printable escape char, we can do it +% like this (again getting TeX to remove the leading space for us): +% \begin{macrocode} +\cs_set_nopar:Npn \cs_to_str:N { + \if:w \exp_after:wN \cs_str_aux:w\token_to_str:N \a ax\q_nil + \else: + \exp_after:wN \exp_after:wN\exp_after:wN \use_ii:nn + \fi: + \exp_after:wN \use_none:n \token_to_str:N +} +\cs_set:Npn \cs_str_aux:w #1#2#3#4\q_nil{#2#3} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\cs_split_function:NN} +% \begin{macro}[aux]{\cs_split_function_aux:w} +% \begin{macro}[aux]{\cs_split_function_auxii:w} +% This function takes a function name and splits it into name with +% the escape char removed and argument specification. In addition to +% this, a third argument, a boolean \m{true} or \m{false} is +% returned with \m{true} for when there is a colon in the function +% and \m{false} if there is not. Lastly, the second argument of +% |\cs_split_function:NN| is supposed to be a function +% taking three variables, one for name, one for signature, and one +% for the boolean. For example, +% "\cs_split_function:NN\foo_bar:cnx\use_i:nnn" as input +% becomes "\use_i:nnn {foo_bar}{cnx}\c_true_bool". +% +% Can't use a literal ":" because it has the wrong catcode here, so +% it's transformed from "@" with "\tex_lowercase:D". +% \begin{macrocode} +\group_begin: + \tex_lccode:D `\@ = `\: \scan_stop: + \tex_catcode:D `\@ = 12~ +\tex_lowercase:D { + \group_end: +% \end{macrocode} +% First ensure that we actually get a properly evaluated str as we +% don't know how many expansions |\cs_to_str:N| requires. Insert +% extra colon to catch the error cases. +% \begin{macrocode} +\cs_set:Npn \cs_split_function:NN #1#2{ + \exp_after:wN \cs_split_function_aux:w + \tex_romannumeral:D -`\q \cs_to_str:N #1 @a \q_nil #2 +} +% \end{macrocode} +% If no colon in the name, |#2| is |a| with catcode 11 and |#3| is +% empty. If colon in the name, then either |#2| is a colon or the +% first letter of the signature. The letters here have catcode 12. +% If a colon was given we need to a) split off the colon and quark at +% the end and b) ensure we return the name, signature and boolean true +% We can't use |\quark_if_no_value:NTF| yet but this is very safe +% anyway as all tokens have catcode~12. +% \begin{macrocode} +\cs_set:Npn \cs_split_function_aux:w #1@#2#3\q_nil#4{ + \if_meaning:w a#2 + \exp_after:wN \use_i:nn + \else: + \exp_after:wN\use_ii:nn + \fi: + {#4{#1}{}\c_false_bool} + {\cs_split_function_auxii:w#2#3\q_nil #4{#1}} +} +\cs_set:Npn \cs_split_function_auxii:w #1@a\q_nil#2#3{ + #2{#3}{#1}\c_true_bool +} +% \end{macrocode} +% End of lowercase +% \begin{macrocode} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\cs_get_function_name:N, \cs_get_function_signature:N } +% Now returning the name is trivial: just discard the last two +% arguments. Similar for signature. +% \begin{macrocode} +\cs_set:Npn \cs_get_function_name:N #1 { + \cs_split_function:NN #1\use_i:nnn +} +\cs_set:Npn \cs_get_function_signature:N #1 { + \cs_split_function:NN #1\use_ii:nnn +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Exist or free} +% +% A control sequence is said to \emph{exist} (to be used) if has an entry in +% the hash table and its meaning is different from the primitive +% "\tex_relax:D" token. A control sequence is said to be \emph{free} +% (to be defined) if it does not already exist and also meets the +% requirement that it does not contain a "D" signature. The reasoning +% behind this is that most of the time, a check for a free control +% sequence is when we wish to make a new control sequence and we do +% not want to let the user define a new ``do not use'' control +% sequence. +% +% \begin{macro}{\cs_if_exist_p:N,\cs_if_exist_p:c} +% \begin{macro}[TF]{\cs_if_exist:N,\cs_if_exist:c} +% Two versions for checking existence. For the "N" form we firstly +% check for "\tex_relax:D" and then if it is in the hash +% table. There is no problem when inputting something like "\else:" +% or "\fi:" as \TeX\ will only ever skip input in case the token +% tested against is "\tex_relax:D". +% \begin{macrocode} +\prg_set_conditional:Npnn \cs_if_exist:N #1 {p,TF,T,F}{ + \if_meaning:w #1\tex_relax:D + \prg_return_false: + \else: + \if_cs_exist:N #1 + \prg_return_true: + \else: + \prg_return_false: + \fi: + \fi: +} +% \end{macrocode} +% For the "c" form we firstly check if it is in the hash table and +% then for "\tex_relax:D" so that we do not add it to the hash table +% unless it was already there. Here we have to be careful as the text +% to be skipped if the first test is false may contain tokens that +% disturb the scanner. Therefore, we ensure that the second test is +% performed after the first one has concluded completely. +% \begin{macrocode} +\prg_set_conditional:Npnn \cs_if_exist:c #1 {p,TF,T,F}{ + \if_cs_exist:w #1 \cs_end: + \exp_after:wN \use_i:nn + \else: + \exp_after:wN \use_ii:nn + \fi: + { + \exp_after:wN \if_meaning:w \cs:w #1\cs_end: \tex_relax:D + \prg_return_false: + \else: + \prg_return_true: + \fi: + } + \prg_return_false: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\cs_if_do_not_use_p:N} +% \begin{macro}[aux]{\cs_if_do_not_use_aux:nnN} +% \begin{macrocode} +\cs_set:Npn \cs_if_do_not_use_p:N #1{ + \cs_split_function:NN #1 \cs_if_do_not_use_aux:nnN +} +\cs_set:Npn \cs_if_do_not_use_aux:nnN #1#2#3{ + \exp_after:wN\str_if_eq_p:nn \token_to_str:N D {#2} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\cs_if_free_p:N,\cs_if_free_p:c} +% \begin{macro}[TF]{\cs_if_free:N,\cs_if_free:c} +% The simple implementation is one using the boolean expression +% parser: If it is exists or is do not use, then return false. +% \begin{verbatim} +% \prg_set_conditional:Npnn \cs_if_free:N #1{p,TF,T,F}{ +% \bool_if:nTF {\cs_if_exist_p:N #1 || \cs_if_do_not_use_p:N #1} +% {\prg_return_false:}{\prg_return_true:} +% } +% \end{verbatim} +% However, this functionality may not be available this early on. We +% do something similar: The numerical values of true and false is one +% and zero respectively, which we can use. The problem again here is +% that the token we are checking may in fact be something that can +% disturb the scanner, so we have to be careful. We would like to do +% minimal evaluation so we ensure this. +% \begin{macrocode} +\prg_set_conditional:Npnn \cs_if_free:N #1{p,TF,T,F}{ + \tex_ifnum:D \cs_if_exist_p:N #1 =\c_zero + \exp_after:wN \use_i:nn + \else: + \exp_after:wN \use_ii:nn + \fi: + { + \tex_ifnum:D \cs_if_do_not_use_p:N #1 =\c_zero + \prg_return_true: + \else: + \prg_return_false: + \fi: + } + \prg_return_false: +} +\cs_set_nopar:Npn \cs_if_free_p:c{\exp_args:Nc\cs_if_free_p:N} +\cs_set_nopar:Npn \cs_if_free:cTF{\exp_args:Nc\cs_if_free:NTF} +\cs_set_nopar:Npn \cs_if_free:cT{\exp_args:Nc\cs_if_free:NT} +\cs_set_nopar:Npn \cs_if_free:cF{\exp_args:Nc\cs_if_free:NF} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsection{Defining and checking (new) functions} % % \begin{macro}{\c_minus_one} +% \begin{macro}{\c_zero} % \begin{macro}{\c_sixteen} % We need the constants |\c_minus_one| and |\c_sixteen| now for -% writing information to the log and the terminal but the -% rest are defined in the \textsf{l3num} module -- at least for the +% writing information to the log and the terminal and |\c_zero| +% which is used by some functions in the \textsf{l3num}module. The +% rest are defined in the \textsf{l3int} module -- at least for the % ones that can be defined with |\tex_chardef:D| or -% |\tex_mathchardef:D|. Otherwise the \textsf{l3int} module is +% |\tex_mathchardef:D|. For other constants the \textsf{l3int} module is % required but it can't be used until the allocation has been set % up properly! The actual allocation mechanism is in % \textsf{l3alloc} and as \TeX{} wants to reserve count registers @@ -1381,16 +2253,18 @@ % |\c_minus_one|. % \begin{macrocode} %<*!initex> -\let:NwN \c_minus_one\m@ne +\cs_set_eq:NwN \c_minus_one\m@ne %</!initex> %<*!package> -\tex_countdef:D \c_minus_one = 10 \scan_stop: -\c_minus_one = -1 \scan_stop: +\tex_countdef:D \c_minus_one = 10 ~ +\c_minus_one = -1 ~ %</!package> -\tex_chardef:D \c_sixteen = 16\scan_stop: +\tex_chardef:D \c_sixteen = 16~ +\tex_chardef:D \c_zero = 0~ % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % We provide two kinds of functions that can be used to define % control sequences. On the one hand we have functions that check @@ -1402,25 +2276,29 @@ % allow us to generate error messages. The definitions here are % only temporary, they will be redefined later on. % -% \begin{macro}{\io_put_log:x} -% \begin{macro}{\io_put_term:x} +% \begin{macro}{\iow_log:x} +% \begin{macro}{\iow_term:x} % We define a routine to write only to the log file. And a % similar one for writing to both the log file and the terminal. % % \begin{macrocode} -\def:Npn \io_put_log:x{ - \tex_immediate:D\io_put_deferred:Nx \c_minus_one } -\def:Npn \io_put_term:x{ - \tex_immediate:D\io_put_deferred:Nx \c_sixteen } +\cs_set_nopar:Npn \iow_log:x { + \tex_immediate:D \iow_shipout_x:Nn \c_minus_one +} +\cs_set_nopar:Npn \iow_term:x { + \tex_immediate:D \iow_shipout_x:Nn \c_sixteen +} % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\err_latex_bug:x} +% \begin{macro}{\msg_kernel_bug:x} % This will show internal errors. % \begin{macrocode} -\def:Npn\err_latex_bug:x#1{ - \io_put_term:x{This~is~a~LaTeX~bug!~Check~coding!}\tex_errmessage:D{#1}} +\cs_set_nopar:Npn \msg_kernel_bug:x #1 { + \iow_term:x { This~is~a~LaTeX~bug:~check~coding! } + \tex_errmessage:D {#1} +} % \end{macrocode} % \end{macro} % @@ -1430,123 +2308,72 @@ % definition here. % \begin{macrocode} %<*trace> -\def:Npn \cs_record_meaning:N#1{} +\cs_set:Npn \cs_record_meaning:N #1{} %</trace> % \end{macrocode} % \end{macro} % -% We need these two to make |\chk_new_cs:N| bulletproof. -% \begin{macrocode} -\def_long:Npn \use_none:n #1{} -\def_long:Npn \use_arg_i:n #1{#1} -% \end{macrocode} -% \begin{macro}{\chk_new_cs:N} -% This command is called by |\def_new:Npn| and |\let_new:NN| etc.\ +% \begin{macro}{\chk_if_free_cs:N} +% This command is called by |\cs_new_nopar:Npn| and |\cs_new_eq:NN| etc.\ % to make sure that the argument sequence is not already in use. If % it is, an error is signalled. It checks if \m{csname} is % undefined or |\scan_stop:|. Otherwise an error message is % issued. We have to make sure we don't put the argument into the % conditional processing since it may be an |\if...| type function! % \begin {macrocode} -\def:Npn \chk_new_cs:N #1{ - \if:w \cs_if_free_p:N #1 - \exp_after:NN \use_none:n - \else: - \exp_after:NN \use_arg_i:n - \fi: +\cs_set_nopar:Npn \chk_if_free_cs:N #1{ + \cs_if_free:NF #1 { - \err_latex_bug:x {Command~name~`\token_to_string:N #1'~ + \msg_kernel_bug:x {Command~name~`\token_to_str:N #1'~ already~defined!~ Current~meaning:~\token_to_meaning:N #1 } } %<*trace> \cs_record_meaning:N#1 -% \io_put_term:x{Defining~\token_to_string:N #1~on~%} - \io_put_log:x{Defining~\token_to_string:N #1~on~ +% \iow_term:x{Defining~\token_to_str:N #1~on~%} + \iow_log:x{Defining~\token_to_str:N #1~on~ line~\tex_the:D \tex_inputlineno:D} %</trace> } % \end{macrocode} % \end{macro} % -% On 2005/11/20 Morten said: I think names for testing if a certain -% condition is true or false should always contain |if| to avoid -% confusion. This is what we do for lots of other types of test -% functions. For now I have defined both names for the functions -% checking names of control sequences. -% -% \begin{macro}{\cs_if_exist_p:N} -% Expands into |\c_true| if the control sequence given as its -% argument \emph{is} in use. -% \begin{macrocode} -\def:Npn \cs_if_exist_p:N #1{ - \if:w \cs_if_free_p:N #1 - \c_false - \else: - \c_true \fi:} -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\chk_if_exist_cs:N } % \begin{macro}{\chk_if_exist_cs:c } % This function issues a warning message when the control sequence % in its argument does not exist. % \begin{macrocode} -\def:Npn \chk_if_exist_cs:N #1 { - \if:w \cs_if_exist_p:N #1 - \else: - \err_latex_bug:x{Command~ `\token_to_string:N #1'~ +\cs_set_nopar:Npn \chk_if_exist_cs:N #1 { + \cs_if_exist:NF #1 + { + \msg_kernel_bug:x {Command~ `\token_to_str:N #1'~ not~ yet~ defined!} - \fi:} -\def:Npn \chk_if_exist_cs:c #1 { - \exp_after:NN \chk_if_exist_cs:N \cs:w #1\cs_end: } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\cs_if_free_p:N} -% Expands into |\c_true| if the control sequence given as its -% argument is not yet in use. Note that we make sure to expand -% into |\c_false| if the control sequence is textually -% |\c_undefined| or |\scan_stop:|, so that we don't end up -% (re)defining them. -% \begin{macrocode} -\def:Npn \cs_if_free_p:N #1{ - \if_cs_exist:N #1 - \if_meaning:NN#1\scan_stop: - \if:w\cs_if_eq_name_p:NN #1\scan_stop: - \c_false \else: \c_true \fi: - \else: - \c_false - \fi: - \else: - \if:w \cs_if_eq_name_p:NN #1\c_undefined - \c_false \else: \c_true \fi: - \fi: + } } -\let:NwN \cs_free_p:N \cs_if_free_p:N +\cs_set_nopar:Npn \chk_if_exist_cs:c {\exp_args:Nc \chk_if_exist_cs:N } % \end{macrocode} % \end{macro} +% \end{macro} % % % \begin{macro}{\str_if_eq_p:nn} -% \begin{macro}{\str_if_eq_p_aux:w} +% \begin{macro}[aux]{\str_if_eq_p_aux:w} % Takes 2 lists of characters as arguments and expands into -% |\c_true| if they are equal, and |\c_false| otherwise. Note that +% |\c_true_bool| if they are equal, and |\c_false_bool| otherwise. Note that % in the current implementation spaces in these strings are % ignored.\footnote{This is a function which could use % \cs{tlist_compare:xx}.} % \begin{macrocode} -\def:Npn \str_if_eq_p:nn #1#2{ +\prg_set_conditional:Npnn \str_if_eq:nn #1#2{p}{ \str_if_eq_p_aux:w #1\scan_stop:\\#2\scan_stop:\\ } -\def:Npn \str_if_eq_p_aux:w #1#2\\#3#4\\{ - \if_meaning:NN#1#3 - \if_meaning:NN#1\scan_stop:\c_true \else: - \if_meaning:NN#3\scan_stop:\c_false \else: +\cs_set_nopar:Npn \str_if_eq_p_aux:w #1#2\\#3#4\\{ + \if_meaning:w#1#3 + \if_meaning:w#1\scan_stop:\prg_return_true: \else: + \if_meaning:w#3\scan_stop:\prg_return_false: \else: \str_if_eq_p_aux:w #2\\#4\\\fi:\fi: - \else:\c_false \fi:} + \else:\prg_return_false: \fi:} % \end{macrocode} % \end{macro} % \end{macro} @@ -1557,21 +2384,21 @@ % arguments and expands into true iff they have the same name. % We make it long in case one of them is |\par|! % \begin{macrocode} -\def_long:Npn \cs_if_eq_name_p:NN #1#2{ - \exp_after:NN\exp_after:NN - \exp_after:NN\str_if_eq_p_aux:w - \exp_after:NN\token_to_string:N - \exp_after:NN#1 - \exp_after:NN\scan_stop: - \exp_after:NN\\ - \token_to_string:N#2\scan_stop:\\} +\prg_set_conditional:Npnn \cs_if_eq_name:NN #1#2{p}{ + \exp_after:wN\exp_after:wN + \exp_after:wN\str_if_eq_p_aux:w + \exp_after:wN\token_to_str:N + \exp_after:wN#1 + \exp_after:wN\scan_stop: + \exp_after:wN\\ + \token_to_str:N#2\scan_stop:\\} % \end{macrocode} % \end{macro} % % % \begin{macro}{\str_if_eq_var_p:nf} -% \begin{macro}{\str_if_eq_var_start:nnN} -% \begin{macro}{\str_if_eq_var_stop:w} +% \begin{macro}[aux]{\str_if_eq_var_start:nnN} +% \begin{macro}[aux]{\str_if_eq_var_stop:w} % A variant of |\str_if_eq_p:nn| which has the advantage of obeying % spaces in at least the second argument. See \textsf{l3quark} for % an application. From the hand of David Kastrup with slight @@ -1591,19 +2418,19 @@ % octal notation so |\tex_number:D| returns |11|. If one test % returns false the |'| is never seen and then we get just |13|. We % wrap the whole process in an external |\if:w| in order to make it -% return either |\c_true| or |\c_false| since some parts of +% return either |\c_true_bool| or |\c_false_bool| since some parts of % \textsf{l3prg} expect a predicate to return one of these two % tokens. % \begin{macrocode} -\def:Npn \str_if_eq_var_p:nf#1{ - \if:w \tex_number:D\str_if_eq_var_start:nnN{}{}#1\scan_stop: +\prg_set_conditional:Npnn \str_if_eq_var:nf #1#2 {p} { + \if:w \tex_number:D\str_if_eq_var_start:nnN{}{}#1\scan_stop:{#2} } -\def:Npn\str_if_eq_var_start:nnN#1#2#3{ - \if:w#3\scan_stop:\exp_after:NN\str_if_eq_var_stop:w\fi: +\cs_set_nopar:Npn\str_if_eq_var_start:nnN#1#2#3{ + \if:w#3\scan_stop:\exp_after:wN\str_if_eq_var_stop:w\fi: \str_if_eq_var_start:nnN{\if:w#3#1}{#2\fi:} } -\def:Npn\str_if_eq_var_stop:w\str_if_eq_var_start:nnN#1#2#3{ - #1#3\scan_stop:'#213~\c_true\else:\c_false\fi: +\cs_set:Npn\str_if_eq_var_stop:w\str_if_eq_var_start:nnN#1#2#3{ + #1#3\scan_stop:'#213~\prg_return_true:\else:\prg_return_false:\fi: } % \end{macrocode} % \end{macro} @@ -1613,39 +2440,37 @@ % % % -% \subsubsection{More new definitions} +% \subsection{More new definitions} % % % -% \begin{macro}{\def_new:Npn} -% \begin{macro}{\def_new:Npx} -% \begin{macro}{\def_long_new:Npn} -% \begin{macro}{\def_long_new:Npx} -% \begin{macro}{\def_protected_new:Npn} -% \begin{macro}{\def_protected_new:Npx} -% \begin{macro}{\def_protected_long_new:Npn} -% \begin{macro}{\def_protected_long_new:Npx} -% These are like |\def:Npn| and |\let:NN|, but they first check that -% the argument command is not already in use. You may use -% |\pref_global:D|, |\pref_long:D|, |\pref_protected:D|, and +% \begin{macro}{\cs_new_nopar:Npn} +% \begin{macro}{\cs_new_nopar:Npx} +% \begin{macro}{\cs_new:Npn} +% \begin{macro}{\cs_new:Npx} +% \begin{macro}{\cs_new_protected_nopar:Npn} +% \begin{macro}{\cs_new_protected_nopar:Npx} +% \begin{macro}{\cs_new_protected:Npn} +% \begin{macro}{\cs_new_protected:Npx} +% These are like |\cs_set_nopar:Npn| and |\cs_set_eq:NN|, but they +% first check that the argument command is not already in use. You +% may use |\pref_global:D|, |\pref_long:D|, |\pref_protected:D|, and % |\tex_outer:D| as prefixes. % \begin {macrocode} -\def_protected:Npn \def_new:Npn #1{\chk_new_cs:N #1 - \def:Npn #1} -\def_protected:Npn \def_new:Npx #1{\chk_new_cs:N #1 - \def:Npx #1} -\def_protected:Npn \def_long_new:Npn #1{\chk_new_cs:N #1 - \def_long:Npn #1} -\def_protected:Npn \def_long_new:Npx #1{\chk_new_cs:N #1 - \def_long:Npx #1} -\def_protected:Npn \def_protected_new:Npn #1{\chk_new_cs:N #1 - \def_protected:Npn #1} -\def_protected:Npn \def_protected_new:Npx #1{\chk_new_cs:N #1 - \def_protected:Npx #1} -\def_protected:Npn \def_protected_long_new:Npn #1{\chk_new_cs:N #1 - \def_protected_long:Npn #1} -\def_protected:Npn \def_protected_long_new:Npx #1{\chk_new_cs:N #1 - \def_protected_long:Npx #1} +\cs_set:Npn \cs_tmp:w #1#2{ + \cs_set_protected_nopar:Npn #1 ##1 { + \chk_if_free_cs:N ##1 + #2 ##1 + } +} +\cs_tmp:w \cs_new_nopar:Npn \cs_set_nopar:Npn +\cs_tmp:w \cs_new_nopar:Npx\cs_set_nopar:Npx +\cs_tmp:w \cs_new:Npn \cs_set:Npn +\cs_tmp:w \cs_new:Npx\cs_set:Npx +\cs_tmp:w \cs_new_protected_nopar:Npn \cs_set_protected_nopar:Npn +\cs_tmp:w \cs_new_protected_nopar:Npx\cs_set_protected_nopar:Npx +\cs_tmp:w \cs_new_protected:Npn \cs_set_protected:Npn +\cs_tmp:w \cs_new_protected:Npx\cs_set_protected:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -1656,32 +2481,24 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\gdef_new:Npn} -% \begin{macro}{\gdef_new:Npx} -% \begin{macro}{\gdef_long_new:Npn} -% \begin{macro}{\gdef_long_new:Npx} -% \begin{macro}{\gdef_protected_new:Npn} -% \begin{macro}{\gdef_protected_new:Npx} -% \begin{macro}{\gdef_protected_long_new:Npn} -% \begin{macro}{\gdef_protected_long_new:Npx} +% \begin{macro}{\cs_gnew_nopar:Npn} +% \begin{macro}{\cs_gnew_nopar:Npx} +% \begin{macro}{\cs_gnew:Npn} +% \begin{macro}{\cs_gnew:Npx} +% \begin{macro}{\cs_gnew_protected_nopar:Npn} +% \begin{macro}{\cs_gnew_protected_nopar:Npx} +% \begin{macro}{\cs_gnew_protected:Npn} +% \begin{macro}{\cs_gnew_protected:Npx} % Global versions of the above functions. % \begin {macrocode} -\def_protected_new:Npn \gdef_new:Npn #1{\chk_new_cs:N #1 - \gdef:Npn #1} -\def_protected_new:Npn \gdef_new:Npx #1{\chk_new_cs:N #1 - \gdef:Npx #1} -\def_protected_new:Npn \gdef_long_new:Npn #1{\chk_new_cs:N #1 - \gdef_long:Npn #1} -\def_protected_new:Npn \gdef_long_new:Npx #1{\chk_new_cs:N #1 - \gdef_long:Npx #1} -\def_protected_new:Npn \gdef_protected_new:Npn #1{\chk_new_cs:N #1 - \gdef_protected:Npn #1} -\def_protected_new:Npn \gdef_protected_new:Npx #1{\chk_new_cs:N #1 - \gdef_protected:Npx #1} -\def_protected_new:Npn \gdef_protected_long_new:Npn #1{\chk_new_cs:N #1 - \gdef_protected_long:Npn #1} -\def_protected_new:Npn \gdef_protected_long_new:Npx #1{\chk_new_cs:N #1 - \gdef_protected_long:Npx #1} +\cs_tmp:w \cs_gnew_nopar:Npn \cs_gset_nopar:Npn +\cs_tmp:w \cs_gnew_nopar:Npx \cs_gset_nopar:Npx +\cs_tmp:w \cs_gnew:Npn \cs_gset:Npn +\cs_tmp:w \cs_gnew:Npx \cs_gset:Npx +\cs_tmp:w \cs_gnew_protected_nopar:Npn \cs_gset_protected_nopar:Npn +\cs_tmp:w \cs_gnew_protected_nopar:Npx \cs_gset_protected_nopar:Npx +\cs_tmp:w \cs_gnew_protected:Npn \cs_gset_protected:Npn +\cs_tmp:w \cs_gnew_protected:Npx \cs_gset_protected:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -1693,33 +2510,36 @@ % \end{macro} % % -% \begin{macro}{\def:cpn} -% \begin{macro}{\def:cpx} -% \begin{macro}{\gdef:cpn} -% \begin{macro}{\gdef:cpx} -% \begin{macro}{\def_new:cpn} -% \begin{macro}{\def_new:cpx} -% \begin{macro}{\gdef_new:cpn} -% \begin{macro}{\gdef_new:cpx} -% Like |\def:Npn| and |\def_new:Npn|, except that the first argument -% consists of the sequence of characters that should be used to form -% the name of the desired control sequence (the |c| stands for -% csname argument, see the expansion module.). Global versions are -% also provided. +% \begin{macro}{\cs_set_nopar:cpn} +% \begin{macro}{\cs_set_nopar:cpx} +% \begin{macro}{\cs_gset_nopar:cpn} +% \begin{macro}{\cs_gset_nopar:cpx} +% \begin{macro}{\cs_new_nopar:cpn} +% \begin{macro}{\cs_new_nopar:cpx} +% \begin{macro}{\cs_gnew_nopar:cpn} +% \begin{macro}{\cs_gnew_nopar:cpx} +% Like |\cs_set_nopar:Npn| and |\cs_new_nopar:Npn|, except that the +% first argument consists of the sequence of characters that should +% be used to form the name of the desired control sequence (the |c| +% stands for csname argument, see the expansion module). Global +% versions are also provided. % -% |\def:cpn|\m{string}\m{rep-text} will turn \m{string} into a -% csname and then assign \m {rep-text} to it by using |\def:Npn|. -% This means that there might be a parameter string between the two -% arguments. +% |\cs_set_nopar:cpn|\m{string}\m{rep-text} will turn \m{string} +% into a csname and then assign \m {rep-text} to it by using +% |\cs_set_nopar:Npn|. This means that there might be a parameter +% string between the two arguments. % \begin{macrocode} -\def_new:Npn \def:cpn #1{\exp_after:NN \def:Npn \cs:w #1\cs_end:} -\def_new:Npn \def:cpx #1{\exp_after:NN \def:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef:cpn #1{\exp_after:NN \gdef:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef:cpx #1{\exp_after:NN \gdef:Npx \cs:w #1\cs_end:} -\def_new:Npn \def_new:cpn #1{\exp_after:NN \def_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_new:cpx #1{\exp_after:NN \def_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_new:cpn #1{\exp_after:NN \gdef_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_new:cpx #1{\exp_after:NN \gdef_new:Npx \cs:w #1\cs_end:} +\cs_set:Npn \cs_tmp:w #1#2{ + \cs_new_nopar:Npn #1 { \exp_args:Nc #2 } +} +\cs_tmp:w \cs_set_nopar:cpn \cs_set_nopar:Npn +\cs_tmp:w \cs_set_nopar:cpx \cs_set_nopar:Npx +\cs_tmp:w \cs_gset_nopar:cpn \cs_gset_nopar:Npn +\cs_tmp:w \cs_gset_nopar:cpx \cs_gset_nopar:Npx +\cs_tmp:w \cs_new_nopar:cpn \cs_new_nopar:Npn +\cs_tmp:w \cs_new_nopar:cpx \cs_new_nopar:Npx +\cs_tmp:w \cs_gnew_nopar:cpn \cs_gnew_nopar:Npn +\cs_tmp:w \cs_gnew_nopar:cpx \cs_gnew_nopar:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -1732,32 +2552,25 @@ % % % -% \begin{macro}{\def_long:cpn} -% \begin{macro}{\def_long:cpx} -% \begin{macro}{\gdef_long:cpn} -% \begin{macro}{\gdef_long:cpx} -% \begin{macro}{\def_long_new:cpn} -% \begin{macro}{\def_long_new:cpx} -% \begin{macro}{\gdef_long_new:cpn} -% \begin{macro}{\gdef_long_new:cpx} -% Variants of the |\def_long:Npn| versions which make a csname out +% \begin{macro}{\cs_set:cpn} +% \begin{macro}{\cs_set:cpx} +% \begin{macro}{\cs_gset:cpn} +% \begin{macro}{\cs_gset:cpx} +% \begin{macro}{\cs_new:cpn} +% \begin{macro}{\cs_new:cpx} +% \begin{macro}{\cs_gnew:cpn} +% \begin{macro}{\cs_gnew:cpx} +% Variants of the |\cs_set:Npn| versions which make a csname out % of the first arguments. We may also do this globally. % \begin{macrocode} -\def_new:Npn \def_long:cpn #1{\exp_after:NN \def_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_long:cpx #1{ - \exp_after:NN\def_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \gdef_long:cpn #1{ - \exp_after:NN \gdef_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_long:cpx #1{ - \exp_after:NN\gdef_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \def_long_new:cpn #1{ - \exp_after:NN \def_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_long_new:cpx #1{ - \exp_after:NN \def_long_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_long_new:cpn #1{ - \exp_after:NN \gdef_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_long_new:cpx #1{ - \exp_after:NN \gdef_long_new:Npx \cs:w #1\cs_end:} +\cs_tmp:w \cs_set:cpn \cs_set:Npn +\cs_tmp:w \cs_set:cpx \cs_set:Npx +\cs_tmp:w \cs_gset:cpn \cs_gset:Npn +\cs_tmp:w \cs_gset:cpx \cs_gset:Npx +\cs_tmp:w \cs_new:cpn \cs_new:Npn +\cs_tmp:w \cs_new:cpx \cs_new:Npx +\cs_tmp:w \cs_gnew:cpn \cs_gnew:Npn +\cs_tmp:w \cs_gnew:cpx \cs_gnew:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -1768,33 +2581,25 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\def_protected:cpn} -% \begin{macro}{\def_protected:cpx} -% \begin{macro}{\gdef_protected:cpn} -% \begin{macro}{\gdef_protected:cpx} -% \begin{macro}{\def_protected_new:cpn} -% \begin{macro}{\def_protected_new:cpx} -% \begin{macro}{\gdef_protected_new:cpn} -% \begin{macro}{\gdef_protected_new:cpx} -% Variants of the |\def_protected:Npn| versions which make a csname +% \begin{macro}{\cs_set_protected_nopar:cpn} +% \begin{macro}{\cs_set_protected_nopar:cpx} +% \begin{macro}{\cs_gset_protected_nopar:cpn} +% \begin{macro}{\cs_gset_protected_nopar:cpx} +% \begin{macro}{\cs_new_protected_nopar:cpn} +% \begin{macro}{\cs_new_protected_nopar:cpx} +% \begin{macro}{\cs_gnew_protected_nopar:cpn} +% \begin{macro}{\cs_gnew_protected_nopar:cpx} +% Variants of the |\cs_set_protected_nopar:Npn| versions which make a csname % out of the first arguments. We may also do this globally. % \begin{macrocode} -\def_new:Npn \def_protected:cpn #1{ - \exp_after:NN \def_protected:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected:cpx #1{ - \exp_after:NN\def_protected:Npx\cs:w #1\cs_end:} -\def_new:Npn \gdef_protected:cpn #1{ - \exp_after:NN \gdef_protected:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected:cpx #1{ - \exp_after:NN\gdef_protected:Npx\cs:w #1\cs_end:} -\def_new:Npn \def_protected_new:cpn #1{ - \exp_after:NN \def_protected_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected_new:cpx #1{ - \exp_after:NN \def_protected_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_new:cpn #1{ - \exp_after:NN \gdef_protected_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_new:cpx #1{ - \exp_after:NN \gdef_protected_new:Npx \cs:w #1\cs_end:} +\cs_tmp:w \cs_set_protected_nopar:cpn \cs_set_protected_nopar:Npn +\cs_tmp:w \cs_set_protected_nopar:cpx \cs_set_protected_nopar:Npx +\cs_tmp:w \cs_gset_protected_nopar:cpn \cs_gset_protected_nopar:Npn +\cs_tmp:w \cs_gset_protected_nopar:cpx \cs_gset_protected_nopar:Npx +\cs_tmp:w \cs_new_protected_nopar:cpn \cs_new_protected_nopar:Npn +\cs_tmp:w \cs_new_protected_nopar:cpx \cs_new_protected_nopar:Npx +\cs_tmp:w \cs_gnew_protected_nopar:cpn \cs_gnew_protected_nopar:Npn +\cs_tmp:w \cs_gnew_protected_nopar:cpx \cs_gnew_protected_nopar:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -1805,33 +2610,25 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\def_protected_long:cpn} -% \begin{macro}{\def_protected_long:cpx} -% \begin{macro}{\gdef_protected_long:cpn} -% \begin{macro}{\gdef_protected_long:cpx} -% \begin{macro}{\def_protected_long_new:cpn} -% \begin{macro}{\def_protected_long_new:cpx} -% \begin{macro}{\gdef_protected_long_new:cpn} -% \begin{macro}{\gdef_protected_long_new:cpx} -% Variants of the |\def_protected_long:Npn| versions which make a csname +% \begin{macro}{\cs_set_protected:cpn} +% \begin{macro}{\cs_set_protected:cpx} +% \begin{macro}{\cs_gset_protected:cpn} +% \begin{macro}{\cs_gset_protected:cpx} +% \begin{macro}{\cs_new_protected:cpn} +% \begin{macro}{\cs_new_protected:cpx} +% \begin{macro}{\cs_gnew_protected:cpn} +% \begin{macro}{\cs_gnew_protected:cpx} +% Variants of the |\cs_set_protected:Npn| versions which make a csname % out of the first arguments. We may also do this globally. % \begin{macrocode} -\def_new:Npn \def_protected_long:cpn #1{ - \exp_after:NN \def_protected_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected_long:cpx #1{ - \exp_after:NN\def_protected_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long:cpn #1{ - \exp_after:NN \gdef_protected_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long:cpx #1{ - \exp_after:NN\gdef_protected_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \def_protected_long_new:cpn #1{ - \exp_after:NN \def_protected_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected_long_new:cpx #1{ - \exp_after:NN \def_protected_long_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long_new:cpn #1{ - \exp_after:NN \gdef_protected_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long_new:cpx #1{ - \exp_after:NN \gdef_protected_long_new:Npx \cs:w #1\cs_end:} +\cs_tmp:w \cs_set_protected:cpn \cs_set_protected:Npn +\cs_tmp:w \cs_set_protected:cpx \cs_set_protected:Npx +\cs_tmp:w \cs_gset_protected:cpn \cs_gset_protected:Npn +\cs_tmp:w \cs_gset_protected:cpx \cs_gset_protected:Npx +\cs_tmp:w \cs_new_protected:cpn \cs_new_protected:Npn +\cs_tmp:w \cs_new_protected:cpx \cs_new_protected:Npx +\cs_tmp:w \cs_gnew_protected:cpn \cs_gnew_protected:Npn +\cs_tmp:w \cs_gnew_protected:cpx \cs_gnew_protected:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -1843,56 +2640,31 @@ % \end{macro} % % -% \begin{macro}{\def_aux_0:NNn} -% \begin{macro}{\def_aux_1:NNn} -% \begin{macro}{\def_aux_2:NNn} -% \begin{macro}{\def_aux_3:NNn} -% \begin{macro}{\def_aux_4:NNn} -% \begin{macro}{\def_aux_5:NNn} -% \begin{macro}{\def_aux_6:NNn} -% \begin{macro}{\def_aux_7:NNn} -% \begin{macro}{\def_aux_8:NNn} -% \begin{macro}{\def_aux_9:NNn} -% \begin{macro}{\def_aux:NNnn} -% \begin{macro}{\def_aux:Ncnn} -% \begin{macro}{\def_arg_number_error_msg:Nn} -% Defining a function with $n$ arguments. First some helper functions. -% \begin{macrocode} -\def_new:cpn {def_aux_0:NNn} #1#2 {#1 #2 } -\def_new:cpn {def_aux_1:NNn} #1#2 {#1 #2 ##1 } -\def_new:cpn {def_aux_2:NNn} #1#2 {#1 #2 ##1##2 } -\def_new:cpn {def_aux_3:NNn} #1#2 {#1 #2 ##1##2##3 } -\def_new:cpn {def_aux_4:NNn} #1#2 {#1 #2 ##1##2##3##4 } -\def_new:cpn {def_aux_5:NNn} #1#2 {#1 #2 ##1##2##3##4##5 } -\def_new:cpn {def_aux_6:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6 } -\def_new:cpn {def_aux_7:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7 } -\def_new:cpn {def_aux_8:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7##8 } -\def_new:cpn {def_aux_9:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7##8##9 } -% \end{macrocode} -% Then the function itself which checks for the existance of such a -% helper function. If it doesn't exist, return an error. Otherwise -% call it to define \verb|#2| with the correct number of arguments. +% \begin{macro}[aux]{\use_0_parameter:} +% \begin{macro}[aux]{\use_1_parameter:} +% \begin{macro}[aux]{\use_2_parameter:} +% \begin{macro}[aux]{\use_3_parameter:} +% \begin{macro}[aux]{\use_4_parameter:} +% \begin{macro}[aux]{\use_5_parameter:} +% \begin{macro}[aux]{\use_6_parameter:} +% \begin{macro}[aux]{\use_7_parameter:} +% \begin{macro}[aux]{\use_8_parameter:} +% \begin{macro}[aux]{\use_9_parameter:} +% For using parameters, i.e., when you need to define a function to +% process three parameters. See \textsf{xparse} for an application. % \begin{macrocode} -\def_protected_long_new:Npn \def_aux:NNnn #1#2#3#4 { - \cs_if_really_exist:cTF {def_aux_\tex_the:D\etex_numexpr:D #3 :NNn} - { - \cs_use:c {def_aux_\tex_the:D\etex_numexpr:D #3 :NNn} #1 #2 {#4} - } - { \def_arg_number_error_msg:Nn #2{#3} } -} -\def_new:Npn \def_aux:Ncnn #1#2{ - \exp_after:NN \def_aux:NNnn \exp_after:NN #1 \cs:w #2\cs_end:} -% \end{macrocode} -% The error message. -% \begin{macrocode} -\def_new:Npn \def_arg_number_error_msg:Nn #1#2 { - \err_latex_bug:x{ - You're~ trying~ to~ define~ the~ command~ `\token_to_string:N #1'~ - with~ \use_arg_i:n{\tex_the:D\etex_numexpr:D #2\scan_stop:} ~ - arguments~ but~ I~ only~ allow~ 0-9~ arguments.~ I~ can~ probably~ - not~ help~ you~ here - } -} +\cs_set_nopar:cpn{use_0_parameter:}{} +\cs_set_nopar:cpn{use_1_parameter:}{{##1}} +\cs_set_nopar:cpn{use_2_parameter:}{{##1}{##2}} +\cs_set_nopar:cpn{use_3_parameter:}{{##1}{##2}{##3}} +\cs_set_nopar:cpn{use_4_parameter:}{{##1}{##2}{##3}{##4}} +\cs_set_nopar:cpn{use_5_parameter:}{{##1}{##2}{##3}{##4}{##5}} +\cs_set_nopar:cpn{use_6_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}} +\cs_set_nopar:cpn{use_7_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}} +\cs_set_nopar:cpn{use_8_parameter:}{ + {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}} +\cs_set_nopar:cpn{use_9_parameter:}{ + {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}} % \end{macrocode} % \end{macro} % \end{macro} @@ -1904,409 +2676,332 @@ % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_aux_use_0_parameter:} -% \begin{macro}{\def_aux_use_1_parameter:} -% \begin{macro}{\def_aux_use_2_parameter:} -% \begin{macro}{\def_aux_use_3_parameter:} -% \begin{macro}{\def_aux_use_4_parameter:} -% \begin{macro}{\def_aux_use_5_parameter:} -% \begin{macro}{\def_aux_use_6_parameter:} -% \begin{macro}{\def_aux_use_7_parameter:} -% \begin{macro}{\def_aux_use_8_parameter:} -% \begin{macro}{\def_aux_use_9_parameter:} -% Something similar to |\def_aux_9:NNn| but for using the -% parameters. +% \subsection{Copying definitions} +% +% \begin{macro}{\cs_set_eq:NN} +% \begin{macro}{\cs_set_eq:cN} +% \begin{macro}{\cs_set_eq:Nc} +% \begin{macro}{\cs_set_eq:cc} +% These macros allow us to copy the definition of a control sequence +% to another control sequence. +% +% The |=| sign allows us to define funny char tokens like |=| +% itself or \verb*= = with this function. For the definition of +% |\c_space_chartok{~}| to work we need the |~| after the |=|. +% +% |\cs_set_eq:NN| is long to avoid problems with a literal argument +% of |\par|. While |\cs_new_eq:NN| will probably never be correct +% with a first argument of |\par|, define it long in order to throw +% an `already defined' error rather than `runaway argument'. +% +% The |c| variants are not protected in order for their arguments to +% be constructed in the correct context. +% % \begin{macrocode} -\def:cpn{def_aux_use_0_parameter:}{} -\def:cpn{def_aux_use_1_parameter:}{{##1}} -\def:cpn{def_aux_use_2_parameter:}{{##1}{##2}} -\def:cpn{def_aux_use_3_parameter:}{{##1}{##2}{##3}} -\def:cpn{def_aux_use_4_parameter:}{{##1}{##2}{##3}{##4}} -\def:cpn{def_aux_use_5_parameter:}{{##1}{##2}{##3}{##4}{##5}} -\def:cpn{def_aux_use_6_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}} -\def:cpn{def_aux_use_7_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}} -\def:cpn{def_aux_use_8_parameter:}{ - {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}} -\def:cpn{def_aux_use_9_parameter:}{ - {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}} +\cs_set_protected:Npn \cs_set_eq:NN #1 { \cs_set_eq:NwN #1=~ } +\cs_set_nopar:Npn \cs_set_eq:cN { \exp_args:Nc \cs_set_eq:NN } +\cs_set_nopar:Npn \cs_set_eq:Nc { \exp_args:NNc \cs_set_eq:NN } +\cs_set_nopar:Npn \cs_set_eq:cc { \exp_args:Ncc \cs_set_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def:NNn} -% \begin{macro}{\def:NNx} -% \begin{macro}{\def:cNn} -% \begin{macro}{\def:cNx} -% \begin{macro}{\gdef:NNn} -% \begin{macro}{\gdef:NNx} -% \begin{macro}{\gdef:cNn} -% \begin{macro}{\gdef:cNx} -% \begin{macro}{\def_new:NNn} -% \begin{macro}{\def_new:NNx} -% \begin{macro}{\def_new:cNn} -% \begin{macro}{\def_new:cNx} -% \begin{macro}{\gdef_new:NNn} -% \begin{macro}{\gdef_new:NNx} -% \begin{macro}{\gdef_new:cNn} -% \begin{macro}{\gdef_new:cNx} -% Defining macros without delimited arguments is now relatively -% easy. First local and global versions of the usual |\def:Npn| -% operation. +% \begin{macro}{\cs_new_eq:NN} +% \begin{macro}{\cs_new_eq:cN} +% \begin{macro}{\cs_new_eq:Nc} +% \begin{macro}{\cs_new_eq:cc} % \begin{macrocode} -\def_new:Npn \def:NNn { \def_aux:NNnn \def:Npn } -\def_new:Npn \def:NNx { \def_aux:NNnn \def:Npx } -\def_new:Npn \def:cNn { \def_aux:Ncnn \def:Npn } -\def_new:Npn \def:cNx { \def_aux:Ncnn \def:Npx } -\def_new:Npn \gdef:NNn { \def_aux:NNnn \gdef:Npn } -\def_new:Npn \gdef:NNx { \def_aux:NNnn \gdef:Npx } -\def_new:Npn \gdef:cNn { \def_aux:Ncnn \gdef:Npn } -\def_new:Npn \gdef:cNx { \def_aux:Ncnn \gdef:Npx } -\def_new:Npn \def_new:NNn { \def_aux:NNnn \def_new:Npn } -\def_new:Npn \def_new:NNx { \def_aux:NNnn \def_new:Npx } -\def_new:Npn \def_new:cNn { \def_aux:Ncnn \def_new:Npn } -\def_new:Npn \def_new:cNx { \def_aux:Ncnn \def_new:Npx } -\def_new:Npn \gdef_new:NNn { \def_aux:NNnn \gdef_new:Npn } -\def_new:Npn \gdef_new:NNx { \def_aux:NNnn \gdef_new:Npx } -\def_new:Npn \gdef_new:cNn { \def_aux:Ncnn \gdef_new:Npn } -\def_new:Npn \gdef_new:cNx { \def_aux:Ncnn \gdef_new:Npx } +\cs_new_protected:Npn \cs_new_eq:NN #1 { + \chk_if_free_cs:N #1 + \cs_set_eq:NN #1 +} +\cs_new_nopar:Npn \cs_new_eq:cN { \exp_args:Nc \cs_new_eq:NN } +\cs_new_nopar:Npn \cs_new_eq:Nc { \exp_args:NNc \cs_new_eq:NN } +\cs_new_nopar:Npn \cs_new_eq:cc { \exp_args:Ncc \cs_new_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_long:NNn} -% \begin{macro}{\def_long:NNx} -% \begin{macro}{\def_long:cNn} -% \begin{macro}{\def_long:cNx} -% \begin{macro}{\gdef_long:NNn} -% \begin{macro}{\gdef_long:NNx} -% \begin{macro}{\gdef_long:cNn} -% \begin{macro}{\gdef_long:cNx} -% \begin{macro}{\def_long_new:NNn} -% \begin{macro}{\def_long_new:NNx} -% \begin{macro}{\def_long_new:cNn} -% \begin{macro}{\def_long_new:cNx} -% \begin{macro}{\gdef_long_new:NNn} -% \begin{macro}{\gdef_long_new:NNx} -% \begin{macro}{\gdef_long_new:cNn} -% \begin{macro}{\gdef_long_new:cNx} -% Long versions of the above. +% \begin{macro}{\cs_gset_eq:NN} +% \begin{macro}{\cs_gset_eq:cN} +% \begin{macro}{\cs_gset_eq:Nc} +% \begin{macro}{\cs_gset_eq:cc} % \begin{macrocode} -\def_new:Npn \def_long:NNn { \def_aux:NNnn \def_long:Npn } -\def_new:Npn \def_long:NNx { \def_aux:NNnn \def_long:Npx } -\def_new:Npn \def_long:cNn { \def_aux:Ncnn \def_long:Npn } -\def_new:Npn \def_long:cNx { \def_aux:Ncnn \def_long:Npx } -\def_new:Npn \gdef_long:NNn { \def_aux:NNnn \gdef_long:Npn } -\def_new:Npn \gdef_long:NNx { \def_aux:NNnn \gdef_long:Npx } -\def_new:Npn \gdef_long:cNn { \def_aux:Ncnn \gdef_long:Npn } -\def_new:Npn \gdef_long:cNx { \def_aux:Ncnn \gdef_long:Npx } -\def_new:Npn \def_long_new:NNn { \def_aux:NNnn \def_long_new:Npn } -\def_new:Npn \def_long_new:NNx { \def_aux:NNnn \def_long_new:Npx } -\def_new:Npn \def_long_new:cNn { \def_aux:Ncnn \def_long_new:Npn } -\def_new:Npn \def_long_new:cNx { \def_aux:Ncnn \def_long_new:Npx } -\def_new:Npn \gdef_long_new:NNn { \def_aux:NNnn \gdef_long_new:Npn } -\def_new:Npn \gdef_long_new:NNx { \def_aux:NNnn \gdef_long_new:Npx } -\def_new:Npn \gdef_long_new:cNn { \def_aux:Ncnn \gdef_long_new:Npn } -\def_new:Npn \gdef_long_new:cNx { \def_aux:Ncnn \gdef_long_new:Npx } +\cs_new_protected:Npn \cs_gset_eq:NN { \pref_global:D \cs_set_eq:NN } +\cs_new_nopar:Npn \cs_gset_eq:Nc { \exp_args:NNc \cs_gset_eq:NN } +\cs_new_nopar:Npn \cs_gset_eq:cN { \exp_args:Nc \cs_gset_eq:NN } +\cs_new_nopar:Npn \cs_gset_eq:cc { \exp_args:Ncc \cs_gset_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% % -% \begin{macro}{\def_protected:NNn} -% \begin{macro}{\def_protected:NNx} -% \begin{macro}{\def_protected:cNn} -% \begin{macro}{\def_protected:cNx} -% \begin{macro}{\gdef_protected:NNn} -% \begin{macro}{\gdef_protected:NNx} -% \begin{macro}{\gdef_protected:cNn} -% \begin{macro}{\gdef_protected:cNx} -% \begin{macro}{\def_protected_new:NNn} -% \begin{macro}{\def_protected_new:NNx} -% \begin{macro}{\def_protected_new:cNn} -% \begin{macro}{\def_protected_new:cNx} -% \begin{macro}{\gdef_protected_new:NNn} -% \begin{macro}{\gdef_protected_new:NNx} -% \begin{macro}{\gdef_protected_new:cNn} -% \begin{macro}{\gdef_protected_new:cNx} -% Protected versions of the above. +% \begin{macro}{\cs_gnew_eq:NN} +% \begin{macro}{\cs_gnew_eq:cN} +% \begin{macro}{\cs_gnew_eq:Nc} +% \begin{macro}{\cs_gnew_eq:cc} % \begin{macrocode} -\def_new:Npn \def_protected:NNn { \def_aux:NNnn \def_protected:Npn } -\def_new:Npn \def_protected:NNx { \def_aux:NNnn \def_protected:Npx } -\def_new:Npn \def_protected:cNn { \def_aux:Ncnn \def_protected:Npn } -\def_new:Npn \def_protected:cNx { \def_aux:Ncnn \def_protected:Npx } -\def_new:Npn \gdef_protected:NNn { \def_aux:NNnn \gdef_protected:Npn } -\def_new:Npn \gdef_protected:NNx { \def_aux:NNnn \gdef_protected:Npx } -\def_new:Npn \gdef_protected:cNn { \def_aux:Ncnn \gdef_protected:Npn } -\def_new:Npn \gdef_protected:cNx { \def_aux:Ncnn \gdef_protected:Npx } -\def_new:Npn \def_protected_new:NNn { \def_aux:NNnn \def_protected_new:Npn } -\def_new:Npn \def_protected_new:NNx { \def_aux:NNnn \def_protected_new:Npx } -\def_new:Npn \def_protected_new:cNn { \def_aux:Ncnn \def_protected_new:Npn } -\def_new:Npn \def_protected_new:cNx { \def_aux:Ncnn \def_protected_new:Npx } -\def_new:Npn \gdef_protected_new:NNn { \def_aux:NNnn \gdef_protected_new:Npn } -\def_new:Npn \gdef_protected_new:NNx { \def_aux:NNnn \gdef_protected_new:Npx } -\def_new:Npn \gdef_protected_new:cNn { \def_aux:Ncnn \gdef_protected_new:Npn } -\def_new:Npn \gdef_protected_new:cNx { \def_aux:Ncnn \gdef_protected_new:Npx } +\cs_new_protected:Npn \cs_gnew_eq:NN #1 { + \chk_if_free_cs:N #1 + \pref_global:D \cs_set_eq:NN #1 +} +\cs_new_nopar:Npn \cs_gnew_eq:cN { \exp_args:Nc \cs_gnew_eq:NN } +\cs_new_nopar:Npn \cs_gnew_eq:Nc { \exp_args:NNc \cs_gnew_eq:NN } +\cs_new_nopar:Npn \cs_gnew_eq:cc { \exp_args:Ncc \cs_gnew_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_protected_long:NNn} -% \begin{macro}{\def_protected_long:NNx} -% \begin{macro}{\def_protected_long:cNn} -% \begin{macro}{\def_protected_long:cNx} -% \begin{macro}{\gdef_protected_long:NNn} -% \begin{macro}{\gdef_protected_long:NNx} -% \begin{macro}{\gdef_protected_long:cNn} -% \begin{macro}{\gdef_protected_long:cNx} -% \begin{macro}{\def_protected_long_new:NNn} -% \begin{macro}{\def_protected_long_new:NNx} -% \begin{macro}{\def_protected_long_new:cNn} -% \begin{macro}{\def_protected_long_new:cNx} -% \begin{macro}{\gdef_protected_long_new:NNn} -% \begin{macro}{\gdef_protected_long_new:NNx} -% \begin{macro}{\gdef_protected_long_new:cNn} -% \begin{macro}{\gdef_protected_long_new:cNx} -% And finally both long and protected. +% +% \subsection{Undefining functions} +% +% \begin{macro}{\cs_gundefine:N } +% The following function is used to free the main memory from the +% definition of some function that isn't in use any longer. % \begin{macrocode} -\def_new:Npn \def_protected_long:NNn { \def_aux:NNnn \def_protected_long:Npn } -\def_new:Npn \def_protected_long:NNx { \def_aux:NNnn \def_protected_long:Npx } -\def_new:Npn \def_protected_long:cNn { \def_aux:Ncnn \def_protected_long:Npn } -\def_new:Npn \def_protected_long:cNx { \def_aux:Ncnn \def_protected_long:Npx } -\def_new:Npn \gdef_protected_long:NNn { \def_aux:NNnn \gdef_protected_long:Npn } -\def_new:Npn \gdef_protected_long:NNx { \def_aux:NNnn \gdef_protected_long:Npx } -\def_new:Npn \gdef_protected_long:cNn { \def_aux:Ncnn \gdef_protected_long:Npn } -\def_new:Npn \gdef_protected_long:cNx { \def_aux:Ncnn \gdef_protected_long:Npx } -\def_new:Npn \def_protected_long_new:NNn { - \def_aux:NNnn \def_protected_long_new:Npn } -\def_new:Npn \def_protected_long_new:NNx { - \def_aux:NNnn \def_protected_long_new:Npx } -\def_new:Npn \def_protected_long_new:cNn { - \def_aux:Ncnn \def_protected_long_new:Npn } -\def_new:Npn \def_protected_long_new:cNx { - \def_aux:Ncnn \def_protected_long_new:Npx } -\def_new:Npn \gdef_protected_long_new:NNn { - \def_aux:NNnn \gdef_protected_long_new:Npn } -\def_new:Npn \gdef_protected_long_new:NNx { - \def_aux:NNnn \gdef_protected_long_new:Npx } -\def_new:Npn \gdef_protected_long_new:cNn { - \def_aux:Ncnn \gdef_protected_long_new:Npn } -\def_new:Npn \gdef_protected_long_new:cNx { - \def_aux:Ncnn \gdef_protected_long_new:Npx } +\cs_new_nopar:Npn \cs_gundefine:N #1{\cs_gset_eq:NN #1\c_undefined:D} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\let:NN} -% \begin{macro}{\let:cN} -% \begin{macro}{\let:Nc} -% \begin{macro}{\let:cc} -% \begin{macro}{\let_new:NN} -% \begin{macro}{\let_new:cN} -% \begin{macro}{\let_new:Nc} -% \begin{macro}{\let_new:cc} -% These macros allow us to copy the definition of a control sequence -% to another control sequence. -% \begin{macrocode} -\def_protected_long_new:Npn \let:NN #1{ +% \subsection{Engine specific definitions} +% +% \begin{macro}{\c_xetex_is_engine_bool,\c_luatex_is_engine_bool} +% \begin{macro}[TF]{\xetex_if_engine:,\luatex_if_engine:} +% In some cases it will be useful to know which engine we're running. +% Don't provide a "_p" predicate because the "_bool" is used for the +% same thing. +% \begin{macrocode} +\if_cs_exist:N \xetex_version:D + \cs_new_eq:NN \c_xetex_is_engine_bool \c_true_bool +\else: + \cs_new_eq:NN \c_xetex_is_engine_bool \c_false_bool +\fi: +\prg_new_conditional:Npnn \xetex_if_engine: {TF,T,F} { + \if_bool:N \c_xetex_is_engine_bool + \prg_return_true: \else: \prg_return_false: \fi: +} % \end{macrocode} -% The |=| sign allows us to define funny char tokens like .|=| -% itself or \verb*= = with this function. For the definition of -% |\c_space_chartok{~}| to work we need the |~| after the |=| +% % \begin{macrocode} - \let:NwN #1=~} -\def_new:Npn\let:cN #1 {\exp_after:NN\let:NN\cs:w#1\cs_end:} -\def_new:Npn\let:Nc{\exp_args:NNc\let:NN} -\def_new:Npn\let:cc{\exp_args:Ncc\let:NN} -\def_new:Npn \let_new:NN #1{\chk_new_cs:N #1 - \let:NN #1} -\def_new:Npn \let_new:cN {\exp_args:Nc \let_new:NN} -\def_new:Npn \let_new:Nc {\exp_args:NNc \let_new:NN} -\def_new:Npn \let_new:cc {\exp_args:Ncc \let_new:NN} +\if_cs_exist:N \luatex_directlua:D + \cs_new_eq:NN \c_luatex_is_engine_bool \c_true_bool +\else: + \cs_new_eq:NN \c_luatex_is_engine_bool \c_false_bool +\fi: +\prg_set_conditional:Npnn \xetex_if_engine: {TF,T,F}{ + \if_bool:N \c_xetex_is_engine_bool \prg_return_true: + \else: \prg_return_false: \fi: +} +\prg_set_conditional:Npnn \luatex_if_engine: {TF,T,F}{ + \if_bool:N \c_luatex_is_engine_bool \prg_return_true: + \else: \prg_return_false: \fi: +} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\glet:NN} -% \begin{macro}{\glet:cN} -% \begin{macro}{\glet:Nc} -% \begin{macro}{\glet:cc} -% \begin{macro}{\glet_new:NN} -% \begin{macro}{\glet_new:cN} -% \begin{macro}{\glet_new:Nc} -% \begin{macro}{\glet_new:cc} -% These are global versions of some of the previously defined functions. +% +% +% +% \subsection{Scratch functions} +% +% \begin{macro}{\prg_do_nothing:} +% I don't think this function belongs here, but one place is as +% good as any other. I want to use this function when I want to +% express `no operation'. It is for example used in templates where +% depending on the users settings we have to either select an function that +% does something, or one that does nothing. % \begin{macrocode} -\def_protected_new:Npn \glet:NN {\pref_global:D \let:NN} -\def_protected_new:Npn \glet:Nc {\exp_args:NNc \glet:NN} -\def_protected_new:Npn \glet:cN {\exp_args:Nc \glet:NN} -\def_new:Npn \glet:cc {\exp_args:Ncc \glet:NN} -\def_new:Npn \glet_new:NN #1{\chk_new_cs:N #1 - \tex_global:D\let:NN #1} -\def_new:Npn \glet_new:cN {\exp_args:Nc \glet_new:NN} -\def_new:Npn \glet_new:Nc {\exp_args:NNc \glet_new:NN} -\def_new:Npn \glet_new:cc {\exp_args:Ncc \glet_new:NN} +\cs_new_nopar:Npn \prg_do_nothing: {} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\def:No} -% \begin{macro}{\gdef:No} -% |\def:No| expands its second argument one time before making -% the definition. +% \subsection{Defining functions from a given number of arguments} +% +% \begin{macro}{\cs_get_arg_count_from_signature:N} +% \begin{macro}[aux]{\cs_get_arg_count_from_signature_aux:nnN} +% \begin{macro}[aux]{\cs_get_arg_count_from_signature_auxii:w} +% Counting the number of tokens in the signature, i.e., the number +% of arguments the function should take. If there is no signature, +% we return that there is $-1$ arguments to signal an error. +% Otherwise we insert the string |9876543210| after the signature. +% If the signature is empty, the number we want is $0$ so we remove +% the first nine tokens and return the tenth. Similarly, if the +% signature is |nnn| we want to remove the nine tokens |nnn987654| +% and return $3$. Therefore, we simply remove the first nine tokens +% and then return the tenth. +% \begin{macrocode} +\cs_set:Npn \cs_get_arg_count_from_signature:N #1{ + \cs_split_function:NN #1 \cs_get_arg_count_from_signature_aux:nnN +} +\cs_set:Npn \cs_get_arg_count_from_signature_aux:nnN #1#2#3{ + \if_predicate:w #3 % \bool_if:NTF here + \exp_after:wN \use_i:nn + \else: + \exp_after:wN\use_ii:nn + \fi: + { + \exp_after:wN \cs_get_arg_count_from_signature_auxii:w + \use_none:nnnnnnnnn #2 9876543210\q_nil + } + {-1} +} +\cs_set:Npn \cs_get_arg_count_from_signature_auxii:w #1#2\q_nil{#1} +% \end{macrocode} +% A variant form we need right away. % \begin{macrocode} -\def_new:Npn \def:No{\exp_args:NNo\def:Npn} -\def_new:Npn \gdef:No {\exp_args:NNo\gdef:Npn} +\cs_set_nopar:Npn \cs_get_arg_count_from_signature:c { + \exp_args:Nc \cs_get_arg_count_from_signature:N +} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\def_test_function_aux:Nnnn} -% \begin{macro}{\def_test_function_aux:Nnnx} -% \begin{macro}{\def_test_function:npn} -% \begin{macro}{\def_test_function:npx} -% \begin{macro}{\def_long_test_function:npn} -% \begin{macro}{\def_long_test_function:npx} -% \begin{macro}{\def_test_function_new:npn} -% \begin{macro}{\def_test_function_new:npx} -% \begin{macro}{\def_long_test_function_new:npn} -% \begin{macro}{\def_long_test_function_new:npx} -% We will often be defining several almost identical TF, T and F -% type functions so it makes sense for us to define a small function -% that will do this for us so that we are less likely to introduce -% typos (it does tend to happen). By doing it in two steps as below -% we can still retain a simple interface where you write the \TeX\ -% parameters as usual. Just don't do it when you're already within a -% conditional! % -% I think the ways of exiting conditionals below are as fast as they -% get. Using |\reverse_if:N| instead of |\else:| didn't give any -% difference I could measure. +% +% +% \begin{macro}[aux]{\cs_generate_from_arg_count:NNnn} +% \begin{macro}[aux]{\cs_generate_from_arg_count_error_msg:Nn} +% We provide a constructor function for defining functions with a +% given number of arguments. For this we need to choose the correct +% parameter text and then use that when defining. Since \TeX\ +% supports from zero to nine arguments, we use a simple switch to +% choose the correct parameter text, ensuring the result is returned +% after finishing the conditional. If it is not between zero and +% nine, we throw an error. +% +% 1: function to define, 2: with what to define it, 3: the number of +% args it requires and 4: the replacement text % \begin{macrocode} -\def_long_new:Npn \def_test_function_aux:Nnnn #1#2#3#4{ - #1 {#2TF} #3 {#4 - \exp_after:NN\use_arg_i:nn\else:\exp_after:NN\use_arg_ii:nn\fi:} - #1 {#2FT} #3 {#4 - \exp_after:NN\use_arg_ii:nn\else:\exp_after:NN\use_arg_i:nn\fi:} - #1 {#2T} #3 {#4 - \else:\exp_after:NN\use_none:nn\fi:\use_arg_i:n} - #1 {#2F} #3 {#4 - \exp_after:NN\use_none:nn\fi:\use_arg_i:n}} -\def_long_new:Npn \def_test_function_aux:Nnnx #1#2#3#4{ - #1 {#2TF} #3 {#4 - \exp_not:n{\exp_after:NN\use_arg_i:nn\else:\exp_after:NN\use_arg_ii:nn\fi:}} - #1 {#2FT} #3 {#4 - \exp_not:n{\exp_after:NN\use_arg_ii:nn\else:\exp_after:NN\use_arg_i:nn\fi:}} - #1 {#2T} #3 {#4 - \exp_not:n{\else:\exp_after:NN\use_none:nn\fi:\use_arg_i:n}} - #1 {#2F} #3 {#4 - \exp_not:n{\exp_after:NN\use_none:nn\fi:\use_arg_i:n}}} -\def_long_new:Npn \def_test_function:npn #1#2#{ - \def_test_function_aux:Nnnn \def:cpn {#1}{#2} -} -\def_long_new:Npn \def_test_function:npx #1#2#{ - \def_test_function_aux:Nnnx \def:cpx {#1}{#2} -} -\def_long_new:Npn \def_long_test_function:npn #1#2#{ - \def_test_function_aux:Nnnn \def_long:cpn {#1}{#2} -} -\def_long_new:Npn \def_long_test_function:npx #1#2#{ - \def_test_function_aux:Nnnx \def_long:cpx {#1}{#2} -} -\def_long_new:Npn \def_test_function_new:npn #1#2#{ - \def_test_function_aux:Nnnn \def_new:cpn {#1}{#2} +\cs_set:Npn \cs_generate_from_arg_count:NNnn #1#2#3#4{ + \tex_ifcase:D \etex_numexpr:D #3\tex_relax:D + \use_i_after_orelse:nw{#2#1} + \or: + \use_i_after_orelse:nw{#2#1 ##1} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6##7} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6##7##8} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6##7##8##9} + \else: + \use_i_after_fi:nw{ + \cs_generate_from_arg_count_error_msg:Nn#1{#3} + \use_none:n % to remove replacement text + } + \fi: + {#4} } -\def_long_new:Npn \def_long_test_function_new:npn #1#2#{ - \def_test_function_aux:Nnnn \def_long_new:cpn {#1}{#2} +% \end{macrocode} +% A variant form we need right away. +% \begin{macrocode} +\cs_set_nopar:Npn \cs_generate_from_arg_count:cNnn { + \exp_args:Nc \cs_generate_from_arg_count:NNnn } -\def_long_new:Npn \def_test_function_new:npx #1#2#{ - \def_test_function_aux:Nnnx \def_new:cpx {#1}{#2} +% \end{macrocode} +% The error message. Elsewhere we use the value of $-1$ to signal a +% missing colon in a function, so provide a hint for help on this. +% \begin{macrocode} +\cs_set:Npn \cs_generate_from_arg_count_error_msg:Nn #1#2 { + \msg_kernel_bug:x { + You're~ trying~ to~ define~ the~ command~ `\token_to_str:N #1'~ + with~ \use:n{\tex_the:D\etex_numexpr:D #2\tex_relax:D} ~ + arguments~ but~ I~ only~ allow~ 0-9~arguments.~Perhaps~you~ + forgot~to~use~a~colon~in~the~function~name?~ + I~ can~ probably~ not~ help~ you~ here + } } -\def_long_new:Npn \def_long_test_function_new:npx #1#2#{ - \def_test_function_aux:Nnnx \def_long_new:cpx {#1}{#2} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% +% \subsection{Using the signature to define functions} +% +% We can now combine some of the tools we have to provide a simple +% interface for defining functions. We define some simpler functions +% with user interface |\cs_set:Nn \foo_bar:nn {#1,#2}|, i.e., the +% number of arguments is read from the signature. +% +% +% \begin{macro}{\cs_set:Nn} +% \begin{macro}{\cs_set:Nx} +% \begin{macro}{\cs_set_nopar:Nn} +% \begin{macro}{\cs_set_nopar:Nx} +% \begin{macro}{\cs_set_protected:Nn} +% \begin{macro}{\cs_set_protected:Nx} +% \begin{macro}{\cs_set_protected_nopar:Nn} +% \begin{macro}{\cs_set_protected_nopar:Nx} +% \begin{macro}{\cs_gset:Nn} +% \begin{macro}{\cs_gset:Nx} +% \begin{macro}{\cs_gset_nopar:Nn} +% \begin{macro}{\cs_gset_nopar:Nx} +% \begin{macro}{\cs_gset_protected:Nn} +% \begin{macro}{\cs_gset_protected:Nx} +% \begin{macro}{\cs_gset_protected_nopar:Nn} +% \begin{macro}{\cs_gset_protected_nopar:Nx} +% We want to define |\cs_set:Nn| as +% \begin{verbatim} +% \cs_set_protected:Npn \cs_set:Nn #1#2{ +% \cs_generate_from_arg_count:NNnn #1\cs_set:Npn +% {\cs_get_arg_count_from_signature:N #1}{#2} +% } +% \end{verbatim} +% In short, to define |\cs_set:Nn| we need just use |\cs_set:Npn|, +% everything else is the same for each variant. Therefore, we can +% make it simpler by temporarily defining a function to do this for +% us. +% \begin{macrocode} +\cs_set:Npn \cs_tmp:w #1#2#3{ + \cs_set_protected:cpx {cs_#1:#2}##1##2{ + \exp_not:N \cs_generate_from_arg_count:NNnn ##1 + \exp_after:wN \exp_not:N \cs:w cs_#1:#3 \cs_end: + {\exp_not:N\cs_get_arg_count_from_signature:N ##1}{##2} + } } % \end{macrocode} +% Then we define the 32 variants beginning with |N|. +% \begin{macrocode} +\cs_tmp:w {set}{Nn}{Npn} +\cs_tmp:w {set}{Nx}{Npx} +\cs_tmp:w {set_nopar}{Nn}{Npn} +\cs_tmp:w {set_nopar}{Nx}{Npx} +\cs_tmp:w {set_protected}{Nn}{Npn} +\cs_tmp:w {set_protected}{Nx}{Npx} +\cs_tmp:w {set_protected_nopar}{Nn}{Npn} +\cs_tmp:w {set_protected_nopar}{Nx}{Npx} +\cs_tmp:w {gset}{Nn}{Npn} +\cs_tmp:w {gset}{Nx}{Npx} +\cs_tmp:w {gset_nopar}{Nn}{Npn} +\cs_tmp:w {gset_nopar}{Nx}{Npx} +\cs_tmp:w {gset_protected}{Nn}{Npn} +\cs_tmp:w {gset_protected}{Nx}{Npx} +\cs_tmp:w {gset_protected_nopar}{Nn}{Npn} +\cs_tmp:w {gset_protected_nopar}{Nx}{Npx} +% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} @@ -2317,86 +3012,50 @@ % \end{macro} % \end{macro} % \end{macro} -% -% -% \subsubsection{Further checking} -% -% \begin{macro}{\cs_if_free:NTF} -% \begin{macro}{\cs_if_free:NT} -% \begin{macro}{\cs_if_free:NF} -% The old |\@ifundefined| of \LaTeX{} 2.09 is re-implemented in the -% function |\cs_free:cTF|, again in a way that |\else:| and |\fi:| -% are removed. In this implementation this is absolutely -% necessary because functions inside the conditional parts expect -% to read further input from outside the conditional. Actually, -% the first part of the code below is more general, since it checks -% \m{csnames} directly and therefore allows both |\scan_stop:| and -% |\c_undefined|. -% \begin{macrocode} -\def_long_test_function_new:npn {cs_if_free:N}#1{\if:w\cs_if_free_p:N #1} -\let:NN \cs_free:NTF \cs_if_free:NTF -\let:NN \cs_free:NT \cs_if_free:NT -\let:NN \cs_free:NF \cs_if_free:NF -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\cs_if_free:cTF} -% \begin{macro}{\cs_if_free:cT} -% \begin{macro}{\cs_if_free:cF} -% We have to implement the |c| variants `by hand' because a different -% test is necessary and I don't want the overhead for the test with -% |\if:w|. What a mistake Don made by making this a -% feature of |\cs:w|. If I'm not totally mistaken this -% feature alone has cost him more than 600\$ for bug-checks. -% \begin{macrocode} -\def_long_test_function_new:npn {cs_if_free:c}#1{ - \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} -\let:NN \cs_free:cTF \cs_if_free:cTF -\let:NN \cs_free:cT \cs_if_free:cT -\let:NN \cs_free:cF \cs_if_free:cF -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\cs_if_really_free:cTF} -% \begin{macro}{\cs_if_really_free:cT} -% \begin{macro}{\cs_if_really_free:cF} -% These versions are for special control sequences that can only be -% formed through |\cs:w ... \cs_end:|. They do not turn the control -% sequence formed into |\scan_stop:|. +% \begin{macro}{\cs_new:Nn} +% \begin{macro}{\cs_new:Nx} +% \begin{macro}{\cs_new_nopar:Nn} +% \begin{macro}{\cs_new_nopar:Nx} +% \begin{macro}{\cs_new_protected:Nn} +% \begin{macro}{\cs_new_protected:Nx} +% \begin{macro}{\cs_new_protected_nopar:Nn} +% \begin{macro}{\cs_new_protected_nopar:Nx} +% \begin{macro}{\cs_gnew:Nn} +% \begin{macro}{\cs_gnew:Nx} +% \begin{macro}{\cs_gnew_nopar:Nn} +% \begin{macro}{\cs_gnew_nopar:Nx} +% \begin{macro}{\cs_gnew_protected:Nn} +% \begin{macro}{\cs_gnew_protected:Nx} +% \begin{macro}{\cs_gnew_protected_nopar:Nn} +% \begin{macro}{\cs_gnew_protected_nopar:Nx} % \begin{macrocode} -\def_long_test_function_new:npn {cs_if_really_free:c}#1{ - \reverse_if:N\if_cs_exist:w #1\cs_end:} -\let:NN \cs_really_free:cTF \cs_if_really_free:cTF -\let:NN \cs_really_free:cT \cs_if_really_free:cT -\let:NN \cs_really_free:cF \cs_if_really_free:cF +\cs_tmp:w {new}{Nn}{Npn} +\cs_tmp:w {new}{Nx}{Npx} +\cs_tmp:w {new_nopar}{Nn}{Npn} +\cs_tmp:w {new_nopar}{Nx}{Npx} +\cs_tmp:w {new_protected}{Nn}{Npn} +\cs_tmp:w {new_protected}{Nx}{Npx} +\cs_tmp:w {new_protected_nopar}{Nn}{Npn} +\cs_tmp:w {new_protected_nopar}{Nx}{Npx} +\cs_tmp:w {gnew}{Nn}{Npn} +\cs_tmp:w {gnew}{Nx}{Npx} +\cs_tmp:w {gnew_nopar}{Nn}{Npn} +\cs_tmp:w {gnew_nopar}{Nx}{Npx} +\cs_tmp:w {gnew_protected}{Nn}{Npn} +\cs_tmp:w {gnew_protected}{Nx}{Npx} +\cs_tmp:w {gnew_protected_nopar}{Nn}{Npn} +\cs_tmp:w {gnew_protected_nopar}{Nx}{Npx} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\cs_if_exist:NTF} -% \begin{macro}{\cs_if_exist:NT} -% \begin{macro}{\cs_if_exist:NF} -% \begin{macro}{\cs_if_exist:cTF} -% \begin{macro}{\cs_if_exist:cT} -% \begin{macro}{\cs_if_exist:cF} -% \begin{macro}{\cs_if_really_exist:cTF} -% \begin{macro}{\cs_if_really_exist:cT} -% \begin{macro}{\cs_if_really_exist:cF} -% Now the same functions but with reverse logic: test if the control -% sequence exists. -% \begin{macrocode} -\def_long_test_function_new:npn {cs_if_exist:N}#1{\if:w\cs_if_exist_p:N #1} -\def_long_test_function_new:npn {cs_if_exist:c}#1{ - \exp_after:NN\reverse_if:N - \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} -\def_long_test_function_new:npn {cs_if_really_exist:c}#1{ - \if_cs_exist:w #1\cs_end:} -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} @@ -2406,93 +3065,67 @@ % \end{macro} % \end{macro} % \end{macro} -% -% -% \subsubsection{Freeing memory} -% -% \begin{macro}{\cs_gundefine:N } -% The following function is used to free the main memory from the -% definition of some function that isn't in use any longer. -% \begin{macrocode} -\def_new:Npn \cs_gundefine:N #1{\glet:NN #1\c_undefined} -% \end{macrocode} % \end{macro} -% -% -% \subsubsection{Engine specific definitions} -% -% \begin{macro}{\engine_if_aleph:TF} -% In some cases it will be useful to know which engine we're running. -% \begin{macrocode} -\def_test_function_new:npn {engine_if_aleph:}{\if_cs_exist:N \aleph_textdir:D} -% \end{macrocode} % \end{macro} -% -% -% -% \subsubsection{Selecting tokens} -% -% \begin{macro}{\use_arg_i:n} -% This macro grabs its argument and returns it back to the input -% (with outer braces removed). -% \begin{macrocode} -%\def_long_new:Npn \use_arg_i:n #1{#1}% moved earlier -% \end{macrocode} +% \end{macro} % \end{macro} % -% \begin{macro}{\use:c} -% \begin{macro}{\cs_use:c} -% \begin{macro}{\use:cc} -% This macro grabs its argument and returns a csname from it. +% Then something similar for the |c| variants. +% \begin{verbatim} +% \cs_set_protected:Npn \cs_set:cn #1#2{ +% \cs_generate_from_arg_count:cNnn {#1}\cs_set:Npn +% {\cs_get_arg_count_from_signature:c {#1}}{#2} +% } +% \end{verbatim} % \begin{macrocode} -\def_new:Npn \use:c #1{\cs:w #1\cs_end:} -\def_new:Npn \cs_use:c #1 { \cs:w#1\cs_end: } +\cs_set:Npn \cs_tmp:w #1#2#3{ + \cs_set_protected:cpx {cs_#1:#2}##1##2{ + \exp_not:N\cs_generate_from_arg_count:cNnn {##1} + \exp_after:wN \exp_not:N \cs:w cs_#1:#3 \cs_end: + {\exp_not:N\cs_get_arg_count_from_signature:c {##1}}{##2} + } +} % \end{macrocode} -% THE NAME IS COMPLETELY WRONG!!!!! -% Morten says: Perhaps this is really |\exp_args:cc| instead? +% \begin{macro}{\cs_set:cn} +% \begin{macro}{\cs_set:cx} +% \begin{macro}{\cs_set_nopar:cn} +% \begin{macro}{\cs_set_nopar:cx} +% \begin{macro}{\cs_set_protected:cn} +% \begin{macro}{\cs_set_protected:cx} +% \begin{macro}{\cs_set_protected_nopar:cn} +% \begin{macro}{\cs_set_protected_nopar:cx} +% \begin{macro}{\cs_gset:cn} +% \begin{macro}{\cs_gset:cx} +% \begin{macro}{\cs_gset_nopar:cn} +% \begin{macro}{\cs_gset_nopar:cx} +% \begin{macro}{\cs_gset_protected:cn} +% \begin{macro}{\cs_gset_protected:cx} +% \begin{macro}{\cs_gset_protected_nopar:cn} +% \begin{macro}{\cs_gset_protected_nopar:cx} +% The 32 |c| variants. % \begin{macrocode} -\def_new:Npn \use:cc #1#2 - {\cs:w #1\exp_after:NN\cs_end:\cs:w #2\cs_end:} +\cs_tmp:w {set}{cn}{Npn} +\cs_tmp:w {set}{cx}{Npx} +\cs_tmp:w {set_nopar}{cn}{Npn} +\cs_tmp:w {set_nopar}{cx}{Npx} +\cs_tmp:w {set_protected}{cn}{Npn} +\cs_tmp:w {set_protected}{cx}{Npx} +\cs_tmp:w {set_protected_nopar}{cn}{Npn} +\cs_tmp:w {set_protected_nopar}{cx}{Npx} +\cs_tmp:w {gset}{cn}{Npn} +\cs_tmp:w {gset}{cx}{Npx} +\cs_tmp:w {gset_nopar}{cn}{Npn} +\cs_tmp:w {gset_nopar}{cx}{Npx} +\cs_tmp:w {gset_protected}{cn}{Npn} +\cs_tmp:w {gset_protected}{cx}{Npx} +\cs_tmp:w {gset_protected_nopar}{cn}{Npn} +\cs_tmp:w {gset_protected_nopar}{cx}{Npx} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\use_arg_i:nn} -% \begin{macro}{\use_arg_ii:nn} -% These macros are needed to provide functions with true and false -% cases, as introduced by Michael some time ago. By using -% |\exp_after:NN| |\use_arg_i:nn | |\else:| constructions it -% is possible to write code where the true or false case is able to -% access the following tokens from the input stream, which is not -% possible if the |\c_true| syntax is used. -% \begin{macrocode} -\def_long_new:Npn \use_arg_i:nn #1#2{#1} -\def_long_new:Npn \use_arg_ii:nn #1#2{#2} -% \end{macrocode} % \end{macro} % \end{macro} -% -% -% -% \begin{macro}{\use_arg_i:nnn} -% \begin{macro}{\use_arg_ii:nnn} -% \begin{macro}{\use_arg_iii:nnn} -% \begin{macro}{\use_arg_i:nnnn} -% \begin{macro}{\use_arg_ii:nnnn} -% \begin{macro}{\use_arg_iii:nnnn} -% \begin{macro}{\use_arg_iv:nnnn} -% We also need something for picking up arguments from a longer -% list. -% \begin{macrocode} -\def_long_new:NNn \use_arg_i:nnn 3{#1} -\def_long_new:NNn \use_arg_ii:nnn 3{#2} -\def_long_new:NNn \use_arg_iii:nnn 3{#3} -\def_long_new:NNn \use_arg_i:nnnn 4{#1} -\def_long_new:NNn \use_arg_ii:nnnn 4{#2} -\def_long_new:NNn \use_arg_iii:nnnn 4{#3} -\def_long_new:NNn \use_arg_iv:nnnn 4{#4} -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} @@ -2500,84 +3133,49 @@ % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\use_arg_i_ii:nn} -% And a function for grabbing two arguments and returning them -% again. -% \begin{macrocode} -\def_long_new:NNn\use_arg_i_ii:nn 2{#1#2} -% \end{macrocode} % \end{macro} -% -% \begin{macro}{\use_none_delimit_by_q_nil:w} -% \begin{macro}{\use_none_delimit_by_q_stop:w} -% Functions that gobble everything until they see either |\q_nil| or -% |\q_stop| resp. -% \begin{macrocode} -\def_long_new:Npn \use_none_delimit_by_q_nil:w #1\q_nil{} -\def_long_new:Npn \use_none_delimit_by_q_stop:w #1\q_stop{} -% \end{macrocode} % \end{macro} % \end{macro} -% -% \begin{macro}{\use_arg_i_delimit_by_q_nil:nw} -% \begin{macro}{\use_arg_i_delimit_by_q_stop:nw} -% Same as above but execute first argument after gobbling. Very -% useful when you need to skip the rest of a mapping sequence but -% want an easy way to control what should be expanded next. -% \begin{macrocode} -\def_long_new:Npn \use_arg_i_delimit_by_q_nil:nw #1#2\q_nil{#1} -\def_long_new:Npn \use_arg_i_delimit_by_q_stop:nw #1#2\q_stop{#1} -% \end{macrocode} -% \end{macro} % \end{macro} % -% -% \begin{macro}{\use_arg_i_after_fi:nw} -% \begin{macro}{\use_arg_i_after_else:nw} -% \begin{macro}{\use_arg_i_after_or:nw} -% \begin{macro}{\use_arg_i_after_or:nw} -% Returns the first argument after ending the conditional. +% \begin{macro}{\cs_new:cn} +% \begin{macro}{\cs_new:cx} +% \begin{macro}{\cs_new_nopar:cn} +% \begin{macro}{\cs_new_nopar:cx} +% \begin{macro}{\cs_new_protected:cn} +% \begin{macro}{\cs_new_protected:cx} +% \begin{macro}{\cs_new_protected_nopar:cn} +% \begin{macro}{\cs_new_protected_nopar:cx} +% \begin{macro}{\cs_gnew:cn} +% \begin{macro}{\cs_gnew:cx} +% \begin{macro}{\cs_gnew_nopar:cn} +% \begin{macro}{\cs_gnew_nopar:cx} +% \begin{macro}{\cs_gnew_protected:cn} +% \begin{macro}{\cs_gnew_protected:cx} +% \begin{macro}{\cs_gnew_protected_nopar:cn} +% \begin{macro}{\cs_gnew_protected_nopar:cx} % \begin{macrocode} -\def_long_new:Npn \use_arg_i_after_fi:nw #1\fi:{\fi: #1} -\def_long_new:Npn \use_arg_i_after_else:nw #1\else:#2\fi:{\fi: #1} -\def_long_new:Npn \use_arg_i_after_or:nw #1\or: #2\fi: {\fi:#1} -\def_long_new:Npn \use_arg_i_after_orelse:nw #1 #2#3\fi: {\fi:#1} +\cs_tmp:w {new}{cn}{Npn} +\cs_tmp:w {new}{cx}{Npx} +\cs_tmp:w {new_nopar}{cn}{Npn} +\cs_tmp:w {new_nopar}{cx}{Npx} +\cs_tmp:w {new_protected}{cn}{Npn} +\cs_tmp:w {new_protected}{cx}{Npx} +\cs_tmp:w {new_protected_nopar}{cn}{Npn} +\cs_tmp:w {new_protected_nopar}{cx}{Npx} +\cs_tmp:w {gnew}{cn}{Npn} +\cs_tmp:w {gnew}{cx}{Npx} +\cs_tmp:w {gnew_nopar}{cn}{Npn} +\cs_tmp:w {gnew_nopar}{cx}{Npx} +\cs_tmp:w {gnew_protected}{cn}{Npn} +\cs_tmp:w {gnew_protected}{cx}{Npx} +\cs_tmp:w {gnew_protected_nopar}{cn}{Npn} +\cs_tmp:w {gnew_protected_nopar}{cx}{Npx} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% -% \subsubsection{Gobbling tokens from input} -% -% \begin{macro}{\use_none:n} -% \begin{macro}{\use_none:nn} -% \begin{macro}{\use_none:nnn} -% \begin{macro}{\use_none:nnnn} -% \begin{macro}{\use_none:nnnnn} -% \begin{macro}{\use_none:nnnnnn} -% \begin{macro}{\use_none:nnnnnnn} -% \begin{macro}{\use_none:nnnnnnnn} -% \begin{macro}{\use_none:nnnnnnnnn} -% To gobble tokens from the input we use a standard naming -% convention: the number of tokens gobbled is given by the number of -% |n|'s following the |:| in the name. Although defining -% |\use_none:nnn| and above as separate calls of |\use_none:n| and -% |\use_none:nn| is slightly faster, this is very non-intuitive to -% the programmer who will assume that expanding such a function once -% will take care of gobbling all the tokens in one go. -% \begin{macrocode} -%\def_long_new:NNn \use_none:n 1{}% moved earlier -\def_long_new:NNn \use_none:nn 2{} -\def_long_new:NNn \use_none:nnn 3{} -\def_long_new:NNn \use_none:nnnn 4{} -\def_long_new:NNn \use_none:nnnnn 5{} -\def_long_new:NNn \use_none:nnnnnn 6{} -\def_long_new:NNn \use_none:nnnnnnn 7{} -\def_long_new:NNn \use_none:nnnnnnnn 8{} -\def_long_new:NNn \use_none:nnnnnnnnn 9{} -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} @@ -2587,240 +3185,100 @@ % \end{macro} % \end{macro} % \end{macro} -% -% -% \subsubsection{Scratch functions} -% -% \begin{macro}{\gtmp:w} -% This function is for global scratch definitions that are used -% immediately afterwards. It should be used when we need a function -% that operates on input, i.e.\ has arguments. If we want to save -% only some tokens for later use, token-list scratch variables -% should be used. -% \begin{macrocode} -\def_new:Npn \gtmp:w {} -% \end{macrocode} % \end{macro} -% -% \begin{macro}{\tmp:w} -% This is a local version of the previous function. -% \begin{macrocode} -\def_new:Npn \tmp:w {} -% \end{macrocode} % \end{macro} -% -% \begin{macro}{\use_noop:} -% I don't think this function belongs here, but one place is as -% good as any other. I want to use this function when I want to -% express `no operation'. -% \begin{macrocode} -\def_new:Npn \use_noop: {} -% \end{macrocode} % \end{macro} % -% \subsubsection{Strings and input stream token lists} -% -% \begin{macro}{\cs_to_str:N} -% This converts a control sequence into the character string of its -% name, removing the leading escape character. -% \begin{macrocode} -\def_new:Npn \cs_to_str:N {\exp_after:NN\use_none:n \token_to_string:N} -% \end{macrocode} -% \end{macro} % % % % % -% \begin{macro}{\cs_if_eq:NNTF} -% \begin{macro}{\cs_if_eq:NNT} -% \begin{macro}{\cs_if_eq:NNF} -% \begin{macro}{\cs_if_eq:cNTF} -% \begin{macro}{\cs_if_eq:cNT} -% \begin{macro}{\cs_if_eq:cNF} -% \begin{macro}{\cs_if_eq:NcTF} -% \begin{macro}{\cs_if_eq:NcT} -% \begin{macro}{\cs_if_eq:NcF} -% \begin{macro}{\cs_if_eq:ccTF} -% \begin{macro}{\cs_if_eq:ccT} -% \begin{macro}{\cs_if_eq:ccF} +% \begin{macro}{\cs_if_eq_p:NN,\cs_if_eq_p:cN,\cs_if_eq_p:Nc,\cs_if_eq_p:cc} +% \begin{macro}[TF]{\cs_if_eq:NN,\cs_if_eq:cN,\cs_if_eq:Nc,\cs_if_eq:cc} % Check if two control sequences are identical. % \begin{macrocode} -\def_test_function_new:npn {cs_if_eq:NN} #1#2{\if_meaning:NN #1#2} -\def_new:Npn \cs_if_eq:cNTF {\exp_args:Nc \cs_if_eq:NNTF} -\def_new:Npn \cs_if_eq:cNT {\exp_args:Nc \cs_if_eq:NNT} -\def_new:Npn \cs_if_eq:cNF {\exp_args:Nc \cs_if_eq:NNF} -\def_new:Npn \cs_if_eq:NcTF {\exp_args:NNc \cs_if_eq:NNTF} -\def_new:Npn \cs_if_eq:NcT {\exp_args:NNc \cs_if_eq:NNT} -\def_new:Npn \cs_if_eq:NcF {\exp_args:NNc \cs_if_eq:NNF} -\def_new:Npn \cs_if_eq:ccTF {\exp_args:Ncc \cs_if_eq:NNTF} -\def_new:Npn \cs_if_eq:ccT {\exp_args:Ncc \cs_if_eq:NNT} -\def_new:Npn \cs_if_eq:ccF {\exp_args:Ncc \cs_if_eq:NNF} +\prg_set_conditional:Npnn \cs_if_eq:NN #1#2{p,TF,T,F}{ + \if_meaning:w #1#2 + \prg_return_true: \else: \prg_return_false: \fi: +} +\cs_new_nopar:Npn \cs_if_eq_p:cN {\exp_args:Nc \cs_if_eq_p:NN} +\cs_new_nopar:Npn \cs_if_eq:cNTF {\exp_args:Nc \cs_if_eq:NNTF} +\cs_new_nopar:Npn \cs_if_eq:cNT {\exp_args:Nc \cs_if_eq:NNT} +\cs_new_nopar:Npn \cs_if_eq:cNF {\exp_args:Nc \cs_if_eq:NNF} +\cs_new_nopar:Npn \cs_if_eq_p:Nc {\exp_args:NNc \cs_if_eq_p:NN} +\cs_new_nopar:Npn \cs_if_eq:NcTF {\exp_args:NNc \cs_if_eq:NNTF} +\cs_new_nopar:Npn \cs_if_eq:NcT {\exp_args:NNc \cs_if_eq:NNT} +\cs_new_nopar:Npn \cs_if_eq:NcF {\exp_args:NNc \cs_if_eq:NNF} +\cs_new_nopar:Npn \cs_if_eq_p:cc {\exp_args:Ncc \cs_if_eq_p:NN} +\cs_new_nopar:Npn \cs_if_eq:ccTF {\exp_args:Ncc \cs_if_eq:NNTF} +\cs_new_nopar:Npn \cs_if_eq:ccT {\exp_args:Ncc \cs_if_eq:NNT} +\cs_new_nopar:Npn \cs_if_eq:ccF {\exp_args:Ncc \cs_if_eq:NNF} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % Finally some code that is needed as we do not distribute the file % module at the moment (so we simply define the needed function via an % existing \LaTeX{} command) and some other stuff which was set up % elsewhere, in undistributed modules. % \begin{macrocode} -\def_new:Npn\file_not_found:nTF #1#2#3{\IfFileExists{#1}{#3}{#2}} +\cs_new_nopar:Npn\file_not_found:nTF #1#2#3{\IfFileExists{#1}{#3}{#2}} % \end{macrocode} % % -% \subsubsection{Predicates and conditionals} -% \label{sec:predicates} -% -% \LaTeX3 has three concepts for conditional flow processing: -% \begin{enumerate} -% -% \item -% Functions that carry out a test an then execute, depending on its -% result, either the code supplied in the \m{true arg} or the \m{false -% arg}. These arguments are denoted with "T" and "F" repectively. An -% example would be -% \begin{quote} -% "\cs_free:cTF{abc}{...}{...}" -% \end{quote} -% a function that will turn the first argument into a control sequence -% (since its marked as "c") then checks whether this control sequence is -% still free and then depending on the result carry out the code in the -% second argument (true case) or in the third argument (false case). -% -% \item -% Functions that return a special type of boolean value which can be -% tested by the function "\if:w". All functions of this type -% have names that end with "_p" in the description part. For example -% \begin{quote} -% "\cs_free_p:N" -% \end{quote} -% would be a predicate function for the same type of test as the -% function above. It would return `true' if its argument (a single token -% denoted by "N") is still free for definition. It would be used in -% constructions like -% \begin{quote} -% "\if:w \cs_free_p:N \l_foo_bar ... \else: ... \fi:" -% \end{quote} -% -% \item -% Actually there is a third one, namely the original concept used in -% plain \TeX{}. This belongs to the second form but needs further -% thoughts. -% \end{enumerate} -% -% Important to note is that conditionals with \m{true code} and/or -% \m{false code} are always defined in a way that the code of the chosen -% alternative can operate on following tokens in the input stream while -% the predicate implementations always have an "\else:" or "\fi:" -% interfering. This can be important in scanner implementations. % +% \begin{macro}{\prg_set_eq_conditional:NNn,\prg_new_eq_conditional:NNn} +% \begin{macrocode} +\cs_set:Npn \prg_set_eq_conditional:NNn #1#2#3 { + \prg_set_eq_conditional_aux:NNNn \cs_set_eq:cc #1#2 {#3} +} +\cs_set:Npn \prg_new_eq_conditional:NNn #1#2#3 { + \prg_set_eq_conditional_aux:NNNn \cs_new_eq:cc #1#2 {#3} +} +% \end{macrocode} +% \begin{macro}[aux]{\prg_set_eq_conditional_aux:NNNn, +% \prg_set_eq_conditional_aux:NNNw} +% \begin{macrocode} +\cs_set:Npn \prg_set_eq_conditional_aux:NNNn #1#2#3#4 { + \prg_set_eq_conditional_aux:NNNw #1#2#3#4,?,\q_recursion_stop +} +% \end{macrocode} +% Manual clist loop over argument "#4". +% \begin{macrocode} +\cs_set:Npn \prg_set_eq_conditional_aux:NNNw #1#2#3#4, { + \if:w ? #4 \scan_stop: + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + #1 { + \exp_args:NNc \cs_split_function:NN #2 {prg_conditional_form_#4:nnn} + }{ + \exp_args:NNc \cs_split_function:NN #3 {prg_conditional_form_#4:nnn} + } + \prg_set_eq_conditional_aux:NNNw #1{#2}{#3} +} +% \end{macrocode} +% \begin{macrocode} +\cs_set:Npn \prg_conditional_form_p:nnn #1#2#3 {#1_p:#2} +\cs_set:Npn \prg_conditional_form_TF:nnn #1#2#3 {#1:#2TF} +\cs_set:Npn \prg_conditional_form_T:nnn #1#2#3 {#1:#2T} +\cs_set:Npn \prg_conditional_form_F:nnn #1#2#3 {#1:#2F} +% \end{macrocode} +% \end{macro} +% \end{macro} % % \begin{macrocode} %</initex|package> +% \end{macrocode} +% +% \begin{macrocode} %<*showmemory> \showMemUsage %</showmemory> % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.38 2006/08/06 17:05:25 morten -% Make \chk_new_cs:N bulletproof -% -% Revision 1.37 2006/07/30 14:37:47 morten -% Added \str_if_eq_var_p:nf -% -% Revision 1.36 2006/07/23 13:43:21 morten -% Removed extra occurrence of \str_if_eq_p:nn -% -% Revision 1.35 2006/07/17 22:25:31 morten -% Fix logic of \chk_new_cs:N and rename \cs_if_eq_p:NN to -% \cs_if_eq_name_p:NN because it is not their meaning but their names -% which are compared. -% -% Revision 1.34 2006/07/08 22:46:17 morten -% Rearranged some code and added complete set of \use_none:<args> -% functions. -% -% Revision 1.33 2006/07/06 14:53:56 morten -% Added \def:NNn functions, reorganized code and much much more. -% -% Revision 1.32 2006/06/03 17:14:43 morten -% Added more \use_arg_... functions. -% -% Revision 1.31 2006/03/20 18:26:33 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.30 2006/01/22 19:35:46 morten -% Changed \use_none:nnn to gobble all tokens in one go and added -% \use_arg_i_ii:nn for l3keyval. -% -% Revision 1.29 2006/01/16 09:47:49 morten -% Fixed deleted brace -% -% Revision 1.28 2006/01/15 19:08:28 morten -% Fixed typos in some \if names -% -% Revision 1.27 2006/01/04 01:29:36 morten -% Changed "robust" to "protected". +% \end{implementation} % -% Revision 1.26 2005/12/27 09:53:55 morten -% Fixed some names, added a few more \use_... functions, changed RCS -% information retrieval -% -% Revision 1.25 2005/12/23 11:16:15 morten -% *** empty log message *** -% -% Revision 1.24 2005/12/02 15:21:55 morten -% Fixed minor typo -% -% Revision 1.23 2005/11/20 07:10:03 morten -% Added a few missing functions. New function type -% \def_test_function:npn to help define TF-type functions. -% -% Revision 1.22 2005/11/08 04:16:17 morten -% Fixed typo. -% -% Revision 1.21 2005/10/27 22:35:13 morten -% Cleaned up a bit and moved some code to l3num. -% -% Revision 1.20 2005/07/12 16:10:24 morten -% Allow \cs_if_eq_p:NN to accept \par. (Yes, real life experience) -% -% Revision 1.19 2005/04/06 21:34:55 morten -% Added more functions. Moved \engine_aleph:TF from l3prg -% -% Revision 1.18 2005/03/25 23:52:24 braams -% The definition of \next needs to be seen at initex time, -% not at typesetting time -% -% Revision 1.17 2005/03/22 23:28:46 morten -% Moved some code to l3prg, removed obsolete code, cleaned up documentation. -% -% Revision 1.16 2005/03/16 22:31:44 braams -% Changed definition of \c_zero and \c_minus_one -% -% Revision 1.15 2005/03/15 23:16:27 braams -% Some tweaking with the docstrip guards to get the documentation to -% come out right. -% -% Revision 1.14 2005/03/15 22:50:00 braams -% Made loadable by initex as the second file -% -% Revision 1.13 2005/03/11 21:32:21 braams -% Fixed the use of RCS information; -% moved \RequirePackage after \StopEventually +% \PrintIndex % +% \endinput |