diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel')
51 files changed, 2451 insertions, 1825 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index 3d261943684..f99bca058f2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -23,7 +23,7 @@ % for those people who are interested. % %<*driver|generic|package> -\def\ExplFileDate{2019-02-15}% +\def\ExplFileDate{2019-03-05}% %</driver|generic|package> %<*driver> \documentclass[full]{l3doc} @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -917,6 +917,12 @@ % the option name alone is equivalent to using the option with the % \texttt{true} value. % +% \DescribeOption{undo-recent-deprecations} +% The \texttt{undo-recent-deprecations} option suppresses deprecation +% errors for the first six months after a command is deprecated. It is +% intended as a last resort measure for users of packages that were not +% updated in time. +% % \DescribeOption{check-declarations} % All variables used in \LaTeX3 code should be declared. This is enforced % by \TeX{} for variable types based on \TeX{} registers, but not for those @@ -1190,6 +1196,7 @@ % \begin{macro}[int]{\expl@create@bool@option} % \begin{variable}[int] % { +% \l@expl@undo@recent@deprecations@bool , % \l@expl@check@declarations@bool , % \l@expl@log@functions@bool , % \l@expl@enable@debug@bool @@ -1213,6 +1220,8 @@ \newcommand*#2{}% \chardef #2=0 % }% +\expl@create@bool@option + {undo-recent-deprecations}\l@expl@undo@recent@deprecations@bool \expl@create@bool@option{check-declarations}\l@expl@check@declarations@bool \expl@create@bool@option{log-functions}\l@expl@log@functions@bool \expl@create@bool@option{enable-debug}\l@expl@enable@debug@bool @@ -1242,10 +1251,6 @@ % \end{variable} % \end{macro} % -% \begin{macro}{\GetIdInfo} -% This is implemented right at the start of \texttt{l3bootstrap.dtx}. -% \end{macro} -% % \begin{macro}{\ProvidesExplPackage, \ProvidesExplClass, \ProvidesExplFile} % For other packages and classes building on this one it is convenient % not to need \cs{ExplSyntaxOn} each time. @@ -1282,18 +1287,6 @@ \fi % \end{macrocode} % -% \begin{macro}{\color} -% The \cs{color} macro must be defined for showing coffin poles, so -% a no-op version is provided here. -% \begin{macrocode} -\AtBeginDocument - { - \cs_if_exist:NF \color - { \DeclareRobustCommand \color [2] [ ] { } } - } -% \end{macrocode} -% \end{macro} -% % \begin{variable}{\l__expl_driver_tl} % \begin{variable}{\l__expl_native_drivers_bool} % With the code now loaded, options can be handled using a real key--value @@ -1434,6 +1427,7 @@ % \begin{macrocode} \keys_define:nn { expl } { + undo-recent-deprecations .bool_set:N = \l@expl@undo@recent@deprecations@bool, check-declarations .bool_set:N = \l@expl@check@declarations@bool, log-functions .bool_set:N = \l@expl@log@functions@bool } @@ -1667,6 +1661,7 @@ % % \begin{variable}[int] % { +% \l@expl@undo@recent@deprecations@bool , % \l@expl@check@declarations@bool , % \l@expl@log@functions@bool , % \l@expl@enable@debug@bool @@ -1675,6 +1670,7 @@ % the two variables are defined to do nothing. % Appropriate value before input of the loader. % \begin{macrocode} +\chardef \l@expl@undo@recent@deprecations@bool = 0 % \chardef \l@expl@check@declarations@bool = 0 % \chardef \l@expl@log@functions@bool = 0 % \chardef \l@expl@enable@debug@bool = 0 % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx index c7464dce77b..16e6a459943 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx index 7730ede1e34..06bb1880b17 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -163,7 +163,7 @@ % Create a new function with the \texttt{protected} restriction, % such as \cs{cs_set_protected:Npn}. The parameter may contain % \cs{par} tokens but the function will not expand within an -% \texttt{x}-type expansion. +% \texttt{x}-type or \texttt{e}-type expansion. % \end{description} % % Finally, the functions in @@ -244,7 +244,7 @@ % \emph{etc.}) will be replaced by those absorbed by the function. % When the \meta{function} is used the \meta{parameters} absorbed % cannot contain \cs{par} tokens. The \meta{function} will not -% expand within an \texttt{x}-type argument. The definition is global +% expand within an \texttt{x}-type or \texttt{e}-type argument. The definition is global % and an error results if the \meta{function} is already defined. % \end{function} % @@ -289,7 +289,7 @@ % \emph{etc.}) will be replaced by those absorbed by the function. % The assignment of a meaning to the \meta{function} is restricted to % the current \TeX{} group level. The \meta{function} will -% not expand within an \texttt{x}-type argument. +% not expand within an \texttt{x}-type or \texttt{e}-type argument. % \end{function} % % \begin{function} @@ -307,7 +307,7 @@ % cannot contain \cs{par} tokens. The assignment of a meaning % to the \meta{function} is restricted to the current \TeX{} group % level. The \meta{function} will not expand within an -% \texttt{x}-type argument. +% \texttt{x}-type or \texttt{e}-type argument. % \end{function} % % \begin{function}{\cs_gset:Npn, \cs_gset:cpn, \cs_gset:Npx, \cs_gset:cpx} @@ -353,7 +353,7 @@ % The assignment of a meaning to the \meta{function} is \emph{not} % restricted to the current \TeX{} group level: the assignment is % global. The \meta{function} will not expand within an -% \texttt{x}-type argument. +% \texttt{x}-type or \texttt{e}-type argument. % \end{function} % % \begin{function} @@ -441,7 +441,7 @@ % (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the % function. When the \meta{function} is used the \meta{parameters} % absorbed cannot contain \cs{par} tokens. The \meta{function} will not -% expand within an \texttt{x}-type argument. The definition is global and +% expand within an \texttt{x}-type or \texttt{e}-type argument. The definition is global and % an error results if the \meta{function} is already defined. % \end{function} % @@ -512,7 +512,7 @@ % (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the % function. When the \meta{function} is used the \meta{parameters} % absorbed cannot contain \cs{par} tokens. The \meta{function} will not -% expand within an \texttt{x}-type argument. +% expand within an \texttt{x}-type or \texttt{e}-type argument. % The assignment of a meaning to the \meta{function} is restricted to % the current \TeX{} group level. % \end{function} @@ -581,7 +581,7 @@ % (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the % function. When the \meta{function} is used the \meta{parameters} % absorbed cannot contain \cs{par} tokens. The \meta{function} will not -% expand within an \texttt{x}-type argument. +% expand within an \texttt{x}-type or \texttt{e}-type argument. % The assignment of a meaning to the \meta{function} is global. % \end{function} % @@ -794,7 +794,7 @@ % of category code $10$. The result does \emph{not} include % the current escape token, contrarily to \cs{token_to_str:N}. % Full expansion of this function requires exactly $2$ expansion -% steps, and so an \texttt{x}-type expansion, or two +% steps, and so an \texttt{x}-type or \texttt{e}-type expansion, or two % \texttt{o}-type expansions are required to % convert the \meta{control sequence} to a sequence of characters % in the input stream. In most cases, an \texttt{f}-expansion @@ -802,7 +802,7 @@ % of the result. % \end{function} % -% \section{Analysing control sequence names} +% \section{Analysing control sequences} % % \begin{function}[EXP, added = 2018-04-06]{\cs_split_function:N} % \begin{syntax} @@ -819,6 +819,70 @@ % (other). % \end{function} % +% The next three functions decompose \TeX{} macros into their +% constituent parts: if the \meta{token} passed is not a macro then no +% decomposition can occur. In the latter case, all three functions leave +% \cs{scan_stop:} in the input stream. +% +% \begin{function}[EXP, added = 2019-02-27]{\cs_prefix_spec:N} +% \begin{syntax} +% \cs{cs_prefix_spec:N} \meta{token} +% \end{syntax} +% If the \meta{token} is a macro, this function leaves the applicable +% \TeX{} prefixes in input stream as a string of tokens of category +% code $12$ (with spaces having category code $10$). Thus for example +% \begin{verbatim} +% \cs_set:Npn \next:nn #1#2 { x #1~y #2 } +% \cs_prefix_spec:N \next:nn +% \end{verbatim} +% leaves |\long| in the input stream. If the \meta{token} is +% not a macro then \cs{scan_stop:} is left in the input stream. +% \begin{texnote} +% The prefix can be empty, |\long|, |\protected| or +% |\protected\long| with backslash replaced by the current escape +% character. +% \end{texnote} +% \end{function} +% +% \begin{function}[EXP, added = 2019-02-27]{\cs_argument_spec:N} +% \begin{syntax} +% \cs{cs_argument_spec:N} \meta{token} +% \end{syntax} +% If the \meta{token} is a macro, this function leaves the primitive +% \TeX{} argument specification in input stream as a string of +% character tokens of category code $12$ (with spaces having category +% code $10$). Thus for example +% \begin{verbatim} +% \cs_set:Npn \next:nn #1#2 { x #1 y #2 } +% \cs_argument_spec:N \next:nn +% \end{verbatim} +% leaves |#1#2| in the input stream. If the \meta{token} is +% not a macro then \cs{scan_stop:} is left in the input stream. +% \begin{texnote} +% If the argument specification contains the string |->|, then the +% function produces incorrect results. +% \end{texnote} +% \end{function} +% +% \begin{function}[EXP, added = 2019-02-27]{\cs_replacement_spec:N} +% \begin{syntax} +% \cs{cs_replacement_spec:N} \meta{token} +% \end{syntax} +% If the \meta{token} is a macro, this function leaves the replacement +% text in input stream as a string of character tokens of category +% code $12$ (with spaces having category code $10$). Thus for example +% \begin{verbatim} +% \cs_set:Npn \next:nn #1#2 { x #1~y #2 } +% \cs_replacement_spec:N \next:nn +% \end{verbatim} +% leaves \verb*|x#1 y#2| in the input stream. If the \meta{token} is +% not a macro then \cs{scan_stop:} is left in the input stream. +% \begin{texnote} +% If the argument specification contains the string |->|, then the +% function produces incorrect results. +% \end{texnote} +% \end{function} +% % \section{Using or removing tokens and arguments} % % Tokens in the input can be read and used or read and discarded. @@ -1931,8 +1995,7 @@ % \begin{variable}{\g_@@_deprecation_on_tl, \g_@@_deprecation_off_tl} % Some commands were more recently deprecated and not yet removed; % only make these into errors if the user requests it. This relies on -% two token lists, mostly filled up by calls to -% \cs{__kernel_patch_deprecation:nnNNpn} in each module. +% two token lists, filled up in \pkg{l3deprecation}. % \begin{macrocode} \__kernel_if_debug:TF { @@ -1956,82 +2019,6 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\__kernel_patch_deprecation:nnNNpn} -% \begin{macro}{\@@_deprecation_aux:nnNnn} -% Grab a definition (at present, must be \cs{cs_new_protected:Npn} or \cs{cs_new:Npn}). -% Add to \cs{g_@@_deprecation_on_tl} some code that makes the -% defined macro |#3| outer (and defines it as an error). Add to -% \cs{g_@@_deprecation_off_tl} the definition itself. In both -% cases we undefine the token with \cs{tex_let:D} to avoid taking a -% potentially outer macro as the argument of some \pkg{expl3} -% function. Finally, define the macro itself: if it is protected, -% make it produce a warning then redefine and call itself. The macro -% initially takes no parameters: -% together with the \texttt{x}-expanding assignment and \cs{exp_not:n} -% this gives a convenient way of storing the macro's definition in -% itself in order to only produce the warning once for each macro. -% If debugging is disabled, \cs{__kernel_patch_deprecation:nnNNpn} lets the -% definition happen. -% \begin{macrocode} -\__kernel_if_debug:TF - { - \cs_set_protected:Npn \__kernel_patch_deprecation:nnNNpn #1#2#3#4#5# - { - \if_meaning:w \cs_new_protected:Npn #3 - \exp_after:wN \use_i:nn - \else: - \if_meaning:w \cs_new:Npn #3 - \exp_after:wN \exp_after:wN \exp_after:wN \use_ii:nn - \else: - \__kernel_msg_error:nnx { kernel } { debug-unpatchable } - { \token_to_str:N #3 ~(for~deprecation) } - \exp_after:wN \exp_after:wN \exp_after:wN \use_none:nn - \fi: - \fi: - { \@@_deprecation_aux:nnNnn {#1} {#2} #4 {#5} } - { \@@_deprecation_expandable:nnNnn {#1} {#2} #4 {#5} } - } - \cs_set_protected:Npn \@@_deprecation_aux:nnNnn #1#2#3#4#5 - { - \tl_gput_right:Nn \g_@@_deprecation_on_tl - { - \tex_let:D #3 \scan_stop: - \__kernel_deprecation_error:Nnn #3 {#2} {#1} - } - \tl_gput_right:Nn \g_@@_deprecation_off_tl - { - \tex_let:D #3 \scan_stop: - \cs_set_protected:Npn #3 #4 {#5} - } - \cs_new_protected:Npx #3 - { - \exp_not:N \__kernel_msg_warning:nnxxx - { kernel } { deprecated-command } - {#1} { \token_to_str:N #3 } { \tl_to_str:n {#2} } - \exp_not:n { \cs_gset_protected:Npn #3 #4 {#5} } - \exp_not:N #3 - } - } - \cs_set_protected:Npn \@@_deprecation_expandable:nnNnn #1#2#3#4#5 - { - \tl_gput_right:Nn \g_@@_deprecation_on_tl - { - \tex_let:D #3 \scan_stop: - \__kernel_deprecation_error:Nnn #3 {#2} {#1} - } - \tl_gput_right:Nn \g_@@_deprecation_off_tl - { - \tex_let:D #3 \scan_stop: - \cs_set:Npn #3 #4 {#5} - } - \cs_new:Npn #3 #4 {#5} - } - } - { \cs_set_protected:Npn \__kernel_patch_deprecation:nnNNpn #1#2 { } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \begin{macro} % {\__kernel_patch:nnNNpn, \__kernel_patch_conditional:nNNpnn} % \begin{macro} @@ -3470,6 +3457,60 @@ % \end{macrocode} % \end{macro} % +% \subsection{Decomposing a macro definition} +% +% \begin{macro}{\cs_prefix_spec:N} +% \begin{macro}{\cs_argument_spec:N} +% \begin{macro}{\cs_replacement_spec:N} +% \begin{macro}{\@@_prefix_arg_replacement:wN} +% We sometimes want to test if a control sequence can be expanded to +% reveal a hidden value. However, we cannot just expand the macro +% blindly as it may have arguments and none might be +% present. Therefore we define these functions to pick either the +% prefix(es), the argument specification, or the replacement text from +% a macro. All of this information is returned as characters with +% catcode~$12$. If the token in question isn't a macro, the token +% \cs{scan_stop:} is returned instead. +% \begin{macrocode} +\use:x + { + \exp_not:n { \cs_new:Npn \@@_prefix_arg_replacement:wN #1 } + \tl_to_str:n { macro : } \exp_not:n { #2 -> #3 \q_stop #4 } + } + { #4 {#1} {#2} {#3} } +\cs_new:Npn \cs_prefix_spec:N #1 + { + \token_if_macro:NTF #1 + { + \exp_after:wN \@@_prefix_arg_replacement:wN + \token_to_meaning:N #1 \q_stop \use_i:nnn + } + { \scan_stop: } + } +\cs_new:Npn \cs_argument_spec:N #1 + { + \token_if_macro:NTF #1 + { + \exp_after:wN \@@_prefix_arg_replacement:wN + \token_to_meaning:N #1 \q_stop \use_ii:nnn + } + { \scan_stop: } + } +\cs_new:Npn \cs_replacement_spec:N #1 + { + \token_if_macro:NTF #1 + { + \exp_after:wN \@@_prefix_arg_replacement:wN + \token_to_meaning:N #1 \q_stop \use_iii:nnn + } + { \scan_stop: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \subsection{Doing nothing functions} % % \begin{macro}[EXP]{\prg_do_nothing:} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index 053c73124ba..9c1fa385fdf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -22,103 +22,6 @@ % % for those people who are interested. % -%<*driver|package> -% \begin{macro}{\GetIdInfo} -% \begin{macro}{\GetIdInfoAuxI, \GetIdInfoAuxII, \GetIdInfoAuxIII} -% The idea here is to extract out the information needed from a standard -% \textsc{svn} \texttt{Id} line, but to avoid a line that would get -% changed when the file is checked in. Hence the fact that none of the -% lines here include both a dollar sign and the \texttt{Id} keyword! -% -% At this stage, no test has taken place for the \eTeX{} extensions, and -% so using \tn{protected} could give an error. To avoid that, it is used -% by csname: if it's not available, the bootstrap code will bail out at -% the point of testing for the necessary primitives, while if it is available -% then \cs{GetIdInfo} and so on will be properly protected. All of this is -% then done in a group to avoid leaving \tn{protected} about as equivalent -% to \tn{relax} if the extensions are unavailable. -% \begin{macrocode} -\begingroup - \csname protected\endcsname\gdef\GetIdInfo - {% - \begingroup - \catcode 32 = 10 % - \GetIdInfoAuxI - }% -% \end{macrocode} -% A first check for a completely empty \textsc{svn} field. If that is -% not the case, there is a second case when a file created using -% \texttt{svn cp} but has not been checked in. That leaves a special -% marker \texttt{-1} version, which has no further data. Dealing correctly -% with that is the reason for the space in the line to use -% \cs{GetIdInforAuxII}. -% \begin{macrocode} - \csname protected\endcsname\gdef\GetIdInfoAuxI$#1$#2% - {% - \def\tempa{#1}% - \def\tempb{Id}% - \ifx\tempa\tempb - \def\tempa - {% - \endgroup - \def\ExplFileDate{0000/00/00}% - \def\ExplFileDescription{#2}% - \def\ExplFileName{[unknown]}% - \def\ExplFileExtension{[unknown extension]}% - \def\ExplFileVersion{-1}% - }% - \else - \def\tempa - {% - \endgroup - \def\ExplFileDescription{#2}% - \GetIdInfoAuxII$#1 $% - }% - \fi - \tempa - }% -% \end{macrocode} -% Here, |#1| is |Id|, |#2| is the file name, |#3| is the extension, -% |#4| is the version, |#5| is the check in date and |#6| is the check in -% time and user, plus some trailing spaces. If |#4| is the marker |-1| value -% then |#5| and |#6| are empty. -% \begin{macrocode} - \csname protected\endcsname\gdef\GetIdInfoAuxII$#1 #2.#3 #4 #5 #6$% - {% - \def\ExplFileName{#2}% - \def\ExplFileExtension{#3}% - \def\ExplFileVersion{#4}% - \begingroup - \def\tempa{#4}% - \def\tempb{-1}% - \ifx\tempa\tempb - \def\tempa - {% - \endgroup - \def\ExplFileDate{0000/00/00}% - }% - \else - \def\tempa - {% - \endgroup - \GetIdInfoAuxIII$#5$% - }% - \fi - \tempa - }% -% \end{macrocode} -% Convert an \textsc{svn}-style date into a \LaTeX{}-style one. -% \begin{macrocode} - \csname protected\endcsname\gdef\GetIdInfoAuxIII$#1-#2-#3$% - {% - \def\ExplFileDate{#1/#2/#3}% - }% -\endgroup -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -%</driver|package> %<*driver> \documentclass[full,kernel]{l3doc} \begin{document} @@ -140,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx index e2a4222c916..594d6cf0388 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -2270,49 +2270,6 @@ % \end{macrocode} % \end{macro} % -% \subsection{Deprecated functions} -% -% \begin{macro} -% { -% \box_set_eq_clear:NN, \box_set_eq_clear:cN, -% \box_set_eq_clear:Nc, \box_set_eq_clear:cc -% } -% \begin{macro} -% { -% \box_gset_eq_clear:NN, \box_gset_eq_clear:cN, -% \box_gset_eq_clear:Nc, \box_gset_eq_clear:cc -% } -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \box_set_eq_drop:N } -\cs_new_protected:Npn \box_set_eq_clear:NN #1#2 - { \tex_setbox:D #1 \tex_box:D #2 } -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \box_gset_eq_drop:N } -\cs_new_protected:Npn \box_gset_eq_clear:NN #1#2 - { \tex_global:D \tex_setbox:D #1 \tex_box:D #2 } -\cs_generate_variant:Nn \box_set_eq_clear:NN { c , Nc , cc } -\cs_generate_variant:Nn \box_gset_eq_clear:NN { c , Nc , cc } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\hbox_unpack_clear:N, \hbox_unpack_clear:c} -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \hbox_unpack_drop:N } -\cs_new_protected:Npn \hbox_unpack_clear:N - { \hbox_unpack_drop:N } -\cs_generate_variant:Nn \hbox_unpack_clear:N { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\vbox_unpack_clear:N, \vbox_unpack_clear:c} -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \vbox_unpack_drop:N } -\cs_new_protected:Npn \vbox_unpack_clear:N - { \vbox_unpack_drop:N } -\cs_generate_variant:Nn \vbox_unpack_clear:N { c } -% \end{macrocode} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index e0a2b218088..dae61ed7957 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -203,47 +203,6 @@ % operation is applied. % \end{function} % -% \section{Additions to \pkg{l3coffins}} -% -% \begin{function}[updated = 2019-01-23] -% { -% \coffin_resize:Nnn, \coffin_resize:cnn, -% \coffin_gresize:Nnn, \coffin_gresize:cnn -% } -% \begin{syntax} -% \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height} -% \end{syntax} -% Resized the \meta{coffin} to \meta{width} and \meta{total-height}, -% both of which should be given as dimension expressions. -% \end{function} -% -% \begin{function} -% { -% \coffin_rotate:Nn, \coffin_rotate:cn, -% \coffin_grotate:Nn, \coffin_grotate:cn -% } -% \begin{syntax} -% \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle} -% \end{syntax} -% Rotates the \meta{coffin} by the given \meta{angle} (given in -% degrees counter-clockwise). This process rotates both the -% coffin content and poles. Multiple rotations do not result in -% the bounding box of the coffin growing unnecessarily. -% \end{function} -% -% \begin{function}[updated = 2019-01-23] -% { -% \coffin_scale:Nnn, \coffin_scale:cnn, -% \coffin_gscale:Nnn, \coffin_gscale:cnn -% } -% \begin{syntax} -% \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale} -% \end{syntax} -% Scales the \meta{coffin} by a factors \meta{x-scale} and -% \meta{y-scale} in the horizontal and vertical directions, -% respectively. The two scale factors should be given as real numbers. -% \end{function} -% % \section{Additions to \pkg{l3expan}} % % \begin{function}[added = 2018-04-04, updated = 2019-02-08] @@ -340,9 +299,10 @@ % % \section{Additions to \pkg{l3file}} % -% \begin{function}[added = 2017-07-11]{\file_get_mdfive_hash:nN} +% \begin{function}[noTF, added = 2017-07-11, updated = 2019-02-16] +% {\file_get_mdfive_hash:nN} % \begin{syntax} -% \cs{file_get_mdfive_hash:nN} \Arg{file name} \meta{str var} +% \cs{file_get_mdfive_hash:nN} \Arg{file name} \meta{tl var} % \end{syntax} % Searches for \meta{file name} using the current \TeX{} search % path and the additional paths controlled by \cs{file_path_include:n}. @@ -355,9 +315,10 @@ % Where the file is not found, the \meta{str var} will be empty. % \end{function} % -% \begin{function}[added = 2017-07-09]{\file_get_size:nN} +% \begin{function}[noTF, added = 2017-07-09, updated = 2019-02-16] +% {\file_get_size:nN} % \begin{syntax} -% \cs{file_get_size:nN} \Arg{file name} \meta{str var} +% \cs{file_get_size:nN} \Arg{file name} \meta{tl var} % \end{syntax} % Searches for \meta{file name} using the current \TeX{} search % path and the additional paths controlled by \cs{file_path_include:n}. @@ -366,9 +327,10 @@ % This is not available in older versions of \XeTeX{}. % \end{function} % -% \begin{function}[added = 2017-07-09]{\file_get_timestamp:nN} +% \begin{function}[noTF, added = 2017-07-09, updated = 2019-02-16] +% {\file_get_timestamp:nN} % \begin{syntax} -% \cs{file_get_timestamp:nN} \Arg{file name} \meta{str var} +% \cs{file_get_timestamp:nN} \Arg{file name} \meta{tl var} % \end{syntax} % Searches for \meta{file name} using the current \TeX{} search % path and the additional paths controlled by \cs{file_path_include:n}. @@ -532,14 +494,15 @@ % having a similar interface as non-expandable messages, expandable % errors must be handled internally very differently from normal error % messages, as none of the tools to print to the terminal or the log -% file are expandable. As a result, the message text and arguments are -% not expanded, and messages must be very short (with default settings, +% file are expandable. As a result, short-hands such as |\{| or |\\| do +% not work, and messages must be very short (with default settings, % they are truncated after approximately 50 characters). It is % advisable to ensure that the message is understandable even when -% truncated. Another particularity of expandable messages is that they +% truncated, by putting the most important information up front. +% Another particularity of expandable messages is that they % cannot be redirected or turned off by the user. % -% \begin{function}[EXP, added = 2015-08-06] +% \begin{function}[EXP, added = 2015-08-06, updated = 2019-02-28] % { % \msg_expandable_error:nnnnnn , % \msg_expandable_error:nnnnn , @@ -636,14 +599,6 @@ % % \section{Additions to \pkg{l3prop}} % -% \begin{function}[EXP]{\prop_count:N, \prop_count:c} -% \begin{syntax} -% \cs{prop_count:N} \meta{property list} -% \end{syntax} -% Leaves the number of key--value pairs in the \meta{property list} in -% the input stream as an \meta{integer denotation}. -% \end{function} -% % \begin{function}[rEXP] % {\prop_map_tokens:Nn, \prop_map_tokens:cn} % \begin{syntax} @@ -857,24 +812,10 @@ % input stream according to the sign of the result. % \end{function} % -% \begin{function}{\skip_split_finite_else_action:nnNN} -% \begin{syntax} -% \cs{skip_split_finite_else_action:nnNN} \Arg{skipexpr} \Arg{action} -% ~~\meta{dimen_1} \meta{dimen_2} -% \end{syntax} -% Checks if the \meta{skipexpr} contains finite glue. If it does then it -% assigns -% \meta{dimen_1} the stretch component and \meta{dimen_2} the shrink -% component. If -% it contains infinite glue set \meta{dimen_1} and \meta{dimen_2} to $0$\,pt -% and place |#2| into the input stream: this is usually an error or -% warning message of some sort. -% \end{function} -% % \section{Additions to \pkg{l3sys}} % -% \begin{function}[added = 2019-01-16]{\sys_shell_get:nnN} -% \begin{function}[TF,added = 2019-01-16]{\sys_shell_get:nnN} +% \begin{function}[noTF, added = 2019-01-16, updated = 2019-02-16] +% {\sys_shell_get:nnN} % \begin{syntax} % \cs{sys_shell_get:nnN} \Arg{shell~command} \Arg{setup} \meta{tl~var} % \cs{sys_shell_get:nnNTF} \Arg{shell~command} \Arg{setup} \meta{tl~var} \Arg{true code} \Arg{false code} @@ -884,13 +825,13 @@ % \cs{tl_to_str:n}. Category codes may need to be set appropriately % via the \meta{setup} argument, which is run just before running the % \meta{shell command} (in a group). -% If shell escape is disabled, the \meta{tl~var} will be empty. +% If shell escape is disabled, the \meta{tl~var} will be set to +% \cs{q_no_value} in the non-branching version. % Note that quote characters (|"|) \emph{cannot} be used inside the % \meta{shell command}. The \cs{sys_shell_get:nnNTF} conditional % returns \texttt{true} if the shell is available and no quote is % detected, and \texttt{false} otherwise. % \end{function} -% \end{function} % % \begin{variable}[added = 2018-05-02]{\c_sys_engine_version_str} % The version string of the current engine, in the same form as @@ -1034,38 +975,6 @@ % Token groups (|{|\ldots|}|) are not single tokens. % \end{function} % -% \begin{function}[EXP]{\tl_reverse_tokens:n} -% \begin{syntax} -% \cs{tl_reverse_tokens:n} \Arg{tokens} -% \end{syntax} -% This function, which works directly on \TeX{} tokens, reverses -% the order of the \meta{tokens}: the first becomes the last and -% the last becomes first. Spaces are preserved. The reversal -% also operates within brace groups, but the braces themselves -% are not exchanged, as this would lead to an unbalanced token -% list. For instance, \cs{tl_reverse_tokens:n} |{a~{b()}}| -% leaves |{)(b}~a| in the input stream. This function requires -% two steps of expansion. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the token -% list does not expand further when appearing in an \texttt{x}-type -% argument expansion. -% \end{texnote} -% \end{function} -% -% \begin{function}[EXP]{\tl_count_tokens:n} -% \begin{syntax} -% \cs{tl_count_tokens:n} \Arg{tokens} -% \end{syntax} -% Counts the number of \TeX{} tokens in the \meta{tokens} and leaves -% this information in the input stream. Every token, including spaces and -% braces, contributes one to the total; thus for instance, the token count of -% |a~{bc}| is $6$. -% This function requires three expansions, -% giving an \meta{integer denotation}. -% \end{function} -% % \begin{function}[EXP, added = 2014-06-30, updated = 2016-01-12] % { % \tl_lower_case:n, \tl_upper_case:n, \tl_mixed_case:n, @@ -1662,544 +1571,6 @@ % \end{macro} % \end{macro} % -% \subsection{Additions to \pkg{l3coffins}} -% -% \begin{macrocode} -%<@@=coffin> -% \end{macrocode} -% -% \subsubsection{Rotating coffins} -% -% \begin{variable}{\l_@@_sin_fp} -% \begin{variable}{\l_@@_cos_fp} -% Used for rotations to get the sine and cosine values. -% \begin{macrocode} -\fp_new:N \l_@@_sin_fp -\fp_new:N \l_@@_cos_fp -% \end{macrocode} -% \end{variable} -% \end{variable} -% -% \begin{variable}{\l_@@_bounding_prop} -% A property list for the bounding box of a coffin. This is only needed -% during the rotation, so there is just the one. -% \begin{macrocode} -\prop_new:N \l_@@_bounding_prop -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_corners_prop, \l_@@_poles_prop} -% Used to avoid needing to track scope for intermediate steps. -% \begin{macrocode} -\prop_new:N \l_@@_corners_prop -\prop_new:N \l_@@_poles_prop -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_bounding_shift_dim} -% The shift of the bounding box of a coffin from the real content. -% \begin{macrocode} -\dim_new:N \l_@@_bounding_shift_dim -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_left_corner_dim} -% \begin{variable}{\l_@@_right_corner_dim} -% \begin{variable}{\l_@@_bottom_corner_dim} -% \begin{variable}{\l_@@_top_corner_dim} -% These are used to hold maxima for the various corner values: these -% thus define the minimum size of the bounding box after rotation. -% \begin{macrocode} -\dim_new:N \l_@@_left_corner_dim -\dim_new:N \l_@@_right_corner_dim -\dim_new:N \l_@@_bottom_corner_dim -\dim_new:N \l_@@_top_corner_dim -% \end{macrocode} -% \end{variable} -% \end{variable} -% \end{variable} -% \end{variable} -% -% \begin{macro} -% { -% \coffin_rotate:Nn, \coffin_rotate:cn, -% \coffin_grotate:Nn, \coffin_grotate:cn -% } -% \begin{macro}{\@@_rotate:NnNN} -% Rotating a coffin requires several steps which can be conveniently -% run together. The sine and cosine of the angle in degrees are -% computed. This is then used to set \cs{l_@@_sin_fp} and -% \cs{l_@@_cos_fp}, which are carried through unchanged for the rest -% of the procedure. -% \begin{macrocode} -\cs_new_protected:Npn \coffin_rotate:Nn #1#2 - { \@@_rotate:NnNN #1 {#2} \box_rotate:Nn \prop_set_eq:cN } -\cs_new_protected:Npn \coffin_grotate:Nn #1#2 - { \@@_rotate:NnNN #1 {#2} \box_grotate:Nn \prop_gset_eq:cN } -\cs_new_protected:Npn \@@_rotate:NnNN #1#2#3#4 - { - \fp_set:Nn \l_@@_sin_fp { sind ( #2 ) } - \fp_set:Nn \l_@@_cos_fp { cosd ( #2 ) } -% \end{macrocode} -% Use a local copy of the property lists to avoid needing to pass the -% name and scope around. -% \begin{macrocode} - \prop_set_eq:Nc \l_@@_corners_prop - { coffin ~ \@@_to_value:N #1 ~ corners } - \prop_set_eq:Nc \l_@@_poles_prop - { coffin ~ \@@_to_value:N #1 ~ poles } -% \end{macrocode} -% The corners and poles of the coffin can now be rotated around the -% origin. This is best achieved using mapping functions. -% \begin{macrocode} - \prop_map_inline:Nn \l_@@_corners_prop - { \@@_rotate_corner:Nnnn #1 {##1} ##2 } - \prop_map_inline:Nn \l_@@_poles_prop - { \@@_rotate_pole:Nnnnnn #1 {##1} ##2 } -% \end{macrocode} -% The bounding box of the coffin needs to be rotated, and to do this -% the corners have to be found first. They are then rotated in the same -% way as the corners of the coffin material itself. -% \begin{macrocode} - \@@_set_bounding:N #1 - \prop_map_inline:Nn \l_@@_bounding_prop - { \@@_rotate_bounding:nnn {##1} ##2 } -% \end{macrocode} -% At this stage, there needs to be a calculation to find where the -% corners of the content and the box itself will end up. -% \begin{macrocode} - \@@_find_corner_maxima:N #1 - \@@_find_bounding_shift: - #3 #1 {#2} -% \end{macrocode} -% The correction of the box position itself takes place here. The idea -% is that the bounding box for a coffin is tight up to the content, and -% has the reference point at the bottom-left. The $x$-direction is -% handled by moving the content by the difference in the positions of -% the bounding box and the content left edge. The $y$-direction is -% dealt with by moving the box down by any depth it has acquired. The -% internal box is used here to allow for the next step. -% \begin{macrocode} - \hbox_set:Nn \l_@@_internal_box - { - \tex_kern:D - \dim_eval:n - { \l_@@_bounding_shift_dim - \l_@@_left_corner_dim } - \exp_stop_f: - \box_move_down:nn { \l_@@_bottom_corner_dim } - { \box_use:N #1 } - } -% \end{macrocode} -% If there have been any previous rotations then the size of the -% bounding box will be bigger than the contents. This can be corrected -% easily by setting the size of the box to the height and width of the -% content. As this operation requires setting box dimensions and these -% transcend grouping, the safe way to do this is to use the internal box -% and to reset the result into the target box. -% \begin{macrocode} - \box_set_ht:Nn \l_@@_internal_box - { \l_@@_top_corner_dim - \l_@@_bottom_corner_dim } - \box_set_dp:Nn \l_@@_internal_box { 0 pt } - \box_set_wd:Nn \l_@@_internal_box - { \l_@@_right_corner_dim - \l_@@_left_corner_dim } - \hbox_set:Nn #1 { \box_use_drop:N \l_@@_internal_box } -% \end{macrocode} -% The final task is to move the poles and corners such that they are -% back in alignment with the box reference point. -% \begin{macrocode} - \prop_map_inline:Nn \l_@@_corners_prop - { \@@_shift_corner:Nnnn #1 {##1} ##2 } - \prop_map_inline:Nn \l_@@_poles_prop - { \@@_shift_pole:Nnnnnn #1 {##1} ##2 } -% \end{macrocode} -% Update the coffin data. -% \begin{macrocode} - #4 { coffin ~ \@@_to_value:N #1 ~ corners } - \l_@@_corners_prop - #4 { coffin ~ \@@_to_value:N #1 ~ poles } - \l_@@_poles_prop - } -\cs_generate_variant:Nn \coffin_rotate:Nn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_set_bounding:N} -% The bounding box corners for a coffin are easy enough to find: this -% is the same code as for the corners of the material itself, but -% using a dedicated property list. -% \begin{macrocode} -\cs_new_protected:Npn \@@_set_bounding:N #1 - { - \prop_put:Nnx \l_@@_bounding_prop { tl } - { { 0 pt } { \dim_eval:n { \box_ht:N #1 } } } - \prop_put:Nnx \l_@@_bounding_prop { tr } - { - { \dim_eval:n { \box_wd:N #1 } } - { \dim_eval:n { \box_ht:N #1 } } - } - \dim_set:Nn \l_@@_internal_dim { -\box_dp:N #1 } - \prop_put:Nnx \l_@@_bounding_prop { bl } - { { 0 pt } { \dim_use:N \l_@@_internal_dim } } - \prop_put:Nnx \l_@@_bounding_prop { br } - { - { \dim_eval:n { \box_wd:N #1 } } - { \dim_use:N \l_@@_internal_dim } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_rotate_bounding:nnn} -% \begin{macro}{\@@_rotate_corner:Nnnn} -% Rotating the position of the corner of the coffin is just a case -% of treating this as a vector from the reference point. The same -% treatment is used for the corners of the material itself and the -% bounding box. -% \begin{macrocode} -\cs_new_protected:Npn \@@_rotate_bounding:nnn #1#2#3 - { - \@@_rotate_vector:nnNN {#2} {#3} \l_@@_x_dim \l_@@_y_dim - \prop_put:Nnx \l_@@_bounding_prop {#1} - { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } - } -\cs_new_protected:Npn \@@_rotate_corner:Nnnn #1#2#3#4 - { - \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim - \prop_put:Nnx \l_@@_corners_prop {#2} - { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_rotate_pole:Nnnnnn} -% Rotating a single pole simply means shifting the co-ordinate of -% the pole and its direction. The rotation here is about the bottom-left -% corner of the coffin. -% \begin{macrocode} -\cs_new_protected:Npn \@@_rotate_pole:Nnnnnn #1#2#3#4#5#6 - { - \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim - \@@_rotate_vector:nnNN {#5} {#6} - \l_@@_x_prime_dim \l_@@_y_prime_dim - \prop_put:Nnx \l_@@_poles_prop {#2} - { - { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } - { \dim_use:N \l_@@_x_prime_dim } - { \dim_use:N \l_@@_y_prime_dim } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_rotate_vector:nnNN} -% A rotation function, which needs only an input vector (as dimensions) -% and an output space. The values \cs{l_@@_cos_fp} and -% \cs{l_@@_sin_fp} should previously have been set up correctly. -% Working this way means that the floating point work is kept to a -% minimum: for any given rotation the sin and cosine values do no -% change, after all. -% \begin{macrocode} -\cs_new_protected:Npn \@@_rotate_vector:nnNN #1#2#3#4 - { - \dim_set:Nn #3 - { - \fp_to_dim:n - { - \dim_to_fp:n {#1} * \l_@@_cos_fp - - \dim_to_fp:n {#2} * \l_@@_sin_fp - } - } - \dim_set:Nn #4 - { - \fp_to_dim:n - { - \dim_to_fp:n {#1} * \l_@@_sin_fp - + \dim_to_fp:n {#2} * \l_@@_cos_fp - } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_find_corner_maxima:N} -% \begin{macro}{\@@_find_corner_maxima_aux:nn} -% The idea here is to find the extremities of the content of the -% coffin. This is done by looking for the smallest values for the bottom -% and left corners, and the largest values for the top and right -% corners. The values start at the maximum dimensions so that the -% case where all are positive or all are negative works out correctly. -% \begin{macrocode} -\cs_new_protected:Npn \@@_find_corner_maxima:N #1 - { - \dim_set:Nn \l_@@_top_corner_dim { -\c_max_dim } - \dim_set:Nn \l_@@_right_corner_dim { -\c_max_dim } - \dim_set:Nn \l_@@_bottom_corner_dim { \c_max_dim } - \dim_set:Nn \l_@@_left_corner_dim { \c_max_dim } - \prop_map_inline:Nn \l_@@_corners_prop - { \@@_find_corner_maxima_aux:nn ##2 } - } -\cs_new_protected:Npn \@@_find_corner_maxima_aux:nn #1#2 - { - \dim_set:Nn \l_@@_left_corner_dim - { \dim_min:nn { \l_@@_left_corner_dim } {#1} } - \dim_set:Nn \l_@@_right_corner_dim - { \dim_max:nn { \l_@@_right_corner_dim } {#1} } - \dim_set:Nn \l_@@_bottom_corner_dim - { \dim_min:nn { \l_@@_bottom_corner_dim } {#2} } - \dim_set:Nn \l_@@_top_corner_dim - { \dim_max:nn { \l_@@_top_corner_dim } {#2} } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_find_bounding_shift:} -% \begin{macro}{\@@_find_bounding_shift_aux:nn} -% The approach to finding the shift for the bounding box is similar to -% that for the corners. However, there is only one value needed here and -% a fixed input property list, so things are a bit clearer. -% \begin{macrocode} -\cs_new_protected:Npn \@@_find_bounding_shift: - { - \dim_set:Nn \l_@@_bounding_shift_dim { \c_max_dim } - \prop_map_inline:Nn \l_@@_bounding_prop - { \@@_find_bounding_shift_aux:nn ##2 } - } -\cs_new_protected:Npn \@@_find_bounding_shift_aux:nn #1#2 - { - \dim_set:Nn \l_@@_bounding_shift_dim - { \dim_min:nn { \l_@@_bounding_shift_dim } {#1} } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_shift_corner:Nnnn} -% \begin{macro}{\@@_shift_pole:Nnnnnn} -% Shifting the corners and poles of a coffin means subtracting the -% appropriate values from the $x$- and $y$-components. For -% the poles, this means that the direction vector is unchanged. -% \begin{macrocode} -\cs_new_protected:Npn \@@_shift_corner:Nnnn #1#2#3#4 - { - \prop_put:Nnx \l_@@_corners_prop {#2} - { - { \dim_eval:n { #3 - \l_@@_left_corner_dim } } - { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } } - } - } -\cs_new_protected:Npn \@@_shift_pole:Nnnnnn #1#2#3#4#5#6 - { - \prop_put:Nnx \l_@@_poles_prop {#2} - { - { \dim_eval:n { #3 - \l_@@_left_corner_dim } } - { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } } - {#5} {#6} - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsubsection{Resizing coffins} -% -% \begin{variable}{\l_@@_scale_x_fp} -% \begin{variable}{\l_@@_scale_y_fp} -% Storage for the scaling factors in $x$ and $y$, respectively. -% \begin{macrocode} -\fp_new:N \l_@@_scale_x_fp -\fp_new:N \l_@@_scale_y_fp -% \end{macrocode} -% \end{variable} -% \end{variable} -% -% \begin{variable}{\l_@@_scaled_total_height_dim} -% \begin{variable}{\l_@@_scaled_width_dim} -% When scaling, the values given have to be turned into absolute values. -% \begin{macrocode} -\dim_new:N \l_@@_scaled_total_height_dim -\dim_new:N \l_@@_scaled_width_dim -% \end{macrocode} -% \end{variable} -% \end{variable} -% -% \begin{macro} -% { -% \coffin_resize:Nnn, \coffin_resize:cnn, -% \coffin_gresize:Nnn, \coffin_gresize:cnn -% } -% \begin{macro}{\@@_resize:NnnNN} -% Resizing a coffin begins by setting up the user-friendly names for -% the dimensions of the coffin box. The new sizes are then turned into -% scale factor. This is the same operation as takes place for the -% underlying box, but that operation is grouped and so the same -% calculation is done here. -% \begin{macrocode} -\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3 - { - \@@_resize:NnnNN #1 {#2} {#3} - \box_resize_to_wd_and_ht_plus_dp:Nnn - \prop_set_eq:cN - } -\cs_generate_variant:Nn \coffin_resize:Nnn { c } -\cs_new_protected:Npn \coffin_gresize:Nnn #1#2#3 - { - \@@_resize:NnnNN #1 {#2} {#3} - \box_gresize_to_wd_and_ht_plus_dp:Nnn - \prop_gset_eq:cN - } -\cs_generate_variant:Nn \coffin_gresize:Nnn { c } -\cs_new_protected:Npn \@@_resize:NnnNN #1#2#3#4#5 - { - \fp_set:Nn \l_@@_scale_x_fp - { \dim_to_fp:n {#2} / \dim_to_fp:n { \coffin_wd:N #1 } } - \fp_set:Nn \l_@@_scale_y_fp - { - \dim_to_fp:n {#3} - / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 } - } - #4 #1 {#2} {#3} - \@@_resize_common:NnnN #1 {#2} {#3} #5 - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_resize_common:NnnN} -% The poles and corners of the coffin are scaled to the appropriate -% places before actually resizing the underlying box. -% \begin{macrocode} -\cs_new_protected:Npn \@@_resize_common:NnnN #1#2#3#4 - { - \prop_set_eq:Nc \l_@@_corners_prop - { coffin ~ \@@_to_value:N #1 ~ corners } - \prop_set_eq:Nc \l_@@_poles_prop - { coffin ~ \@@_to_value:N #1 ~ poles } - \prop_map_inline:Nn \l_@@_corners_prop - { \@@_scale_corner:Nnnn #1 {##1} ##2 } - \prop_map_inline:Nn \l_@@_poles_prop - { \@@_scale_pole:Nnnnnn #1 {##1} ##2 } -% \end{macrocode} -% Negative $x$-scaling values place the poles in the wrong -% location: this is corrected here. -% \begin{macrocode} - \fp_compare:nNnT \l_@@_scale_x_fp < \c_zero_fp - { - \prop_map_inline:Nn \l_@@_corners_prop - { \@@_x_shift_corner:Nnnn #1 {##1} ##2 } - \prop_map_inline:Nn \l_@@_poles_prop - { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 } - } - #4 { coffin ~ \@@_to_value:N #1 ~ corners } - \l_@@_corners_prop - #4 { coffin ~ \@@_to_value:N #1 ~ poles } - \l_@@_poles_prop - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% \coffin_scale:Nnn, \coffin_scale:cnn, -% \coffin_gscale:Nnn, \coffin_gscale:cnn -% } -% \begin{macro}{\coffin_scale:NnnNN} -% For scaling, the opposite calculation is done to find the new -% dimensions for the coffin. Only the total height is needed, as this -% is the shift required for corners and poles. The scaling is done -% the \TeX{} way as this works properly with floating point values -% without needing to use the \texttt{fp} module. -% \begin{macrocode} -\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3 - { \@@_scale:NnnNN #1 {#2} {#3} \box_scale:Nnn \prop_set_eq:cN } -\cs_generate_variant:Nn \coffin_scale:Nnn { c } -\cs_new_protected:Npn \coffin_gscale:Nnn #1#2#3 - { \@@_scale:NnnNN #1 {#2} {#3} \box_gscale:Nnn \prop_gset_eq:cN } -\cs_generate_variant:Nn \coffin_gscale:Nnn { c } -\cs_new_protected:Npn \@@_scale:NnnNN #1#2#3#4#5 - { - \fp_set:Nn \l_@@_scale_x_fp {#2} - \fp_set:Nn \l_@@_scale_y_fp {#3} - #4 #1 { \l_@@_scale_x_fp } { \l_@@_scale_y_fp } - \dim_set:Nn \l_@@_internal_dim - { \coffin_ht:N #1 + \coffin_dp:N #1 } - \dim_set:Nn \l_@@_scaled_total_height_dim - { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_internal_dim } - \dim_set:Nn \l_@@_scaled_width_dim - { -\fp_abs:n { \l_@@_scale_x_fp } \coffin_wd:N #1 } - \@@_resize_common:NnnN #1 - { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim } - #5 - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_scale_vector:nnNN} -% This functions scales a vector from the origin using the pre-set scale -% factors in $x$ and $y$. This is a much less complex operation -% than rotation, and as a result the code is a lot clearer. -% \begin{macrocode} -\cs_new_protected:Npn \@@_scale_vector:nnNN #1#2#3#4 - { - \dim_set:Nn #3 - { \fp_to_dim:n { \dim_to_fp:n {#1} * \l_@@_scale_x_fp } } - \dim_set:Nn #4 - { \fp_to_dim:n { \dim_to_fp:n {#2} * \l_@@_scale_y_fp } } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_scale_corner:Nnnn} -% \begin{macro}{\@@_scale_pole:Nnnnnn} -% Scaling both corners and poles is a simple calculation using the -% preceding vector scaling. -% \begin{macrocode} -\cs_new_protected:Npn \@@_scale_corner:Nnnn #1#2#3#4 - { - \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim - \prop_put:Nnx \l_@@_corners_prop {#2} - { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } - } -\cs_new_protected:Npn \@@_scale_pole:Nnnnnn #1#2#3#4#5#6 - { - \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim - \prop_put:Nnx \l_@@_poles_prop {#2} - { - { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } - {#5} {#6} - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_x_shift_corner:Nnnn} -% \begin{macro}{\@@_x_shift_pole:Nnnnnn} -% These functions correct for the $x$ displacement that takes -% place with a negative horizontal scaling. -% \begin{macrocode} -\cs_new_protected:Npn \@@_x_shift_corner:Nnnn #1#2#3#4 - { - \prop_put:Nnx \l_@@_corners_prop {#2} - { - { \dim_eval:n { #3 + \box_wd:N #1 } } {#4} - } - } -\cs_new_protected:Npn \@@_x_shift_pole:Nnnnnn #1#2#3#4#5#6 - { - \prop_put:Nnx \l_@@_poles_prop {#2} - { - { \dim_eval:n { #3 + \box_wd:N #1 } } {#4} - {#5} {#6} - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \subsection{Additions to \pkg{l3fp-convert}} % % \begin{macrocode} @@ -2234,44 +1605,63 @@ % coverage varies in other engines. % \begin{macrocode} \cs_new_protected:Npn \file_get_mdfive_hash:nN #1#2 - { \@@_get_details:nnN {#1} { mdfivesum } {#2} } + { \file_get_mdfive_hash:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } } \cs_new_protected:Npn \file_get_size:nN #1#2 - { \@@_get_details:nnN {#1} { size } {#2} } + { \file_get_size:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } } \cs_new_protected:Npn \file_get_timestamp:nN #1#2 + { \file_get_timestamp:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } } +\prg_new_protected_conditional:Npnn \file_get_mdfive_hash:nN #1#2 { T , F , TF } + { \@@_get_details:nnN {#1} { mdfivesum } {#2} } +\prg_new_protected_conditional:Npnn \file_get_size:nN #1#2 { T , F , TF } + { \@@_get_details:nnN {#1} { size } {#2} } +\prg_new_protected_conditional:Npnn \file_get_timestamp:nN #1#2 { T , F , TF } { \@@_get_details:nnN {#1} { moddate } {#2} } \cs_new_protected:Npn \@@_get_details:nnN #1#2#3 { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_set:Nx #3 + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { - \use:c { tex_file #2 :D } \exp_after:wN - { \l_@@_full_name_str } + \tl_set:Nx #3 + { + \use:c { tex_file #2 :D } \exp_after:wN + { \l_@@_full_name_tl } + } + \prg_return_true: } + { \prg_return_false: } } \sys_if_engine_luatex:TF { \cs_set_protected:Npn \@@_get_details:nnN #1#2#3 { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_set:Nx #3 + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { - \lua_now:e + \tl_set:Nx #3 { - l3kernel.file#2 - ( " \lua_escape:e { \l_@@_full_name_str } " ) + \lua_now:e + { + l3kernel.file#2 + ( " \lua_escape:e { \l_@@_full_name_tl } " ) + } } + \prg_return_true: } - } + { \prg_return_false: } + } } { - \cs_set_protected:Npn \file_get_mdfive_hash:nN #1#2 + \prg_set_protected_conditional:Npnn \file_get_mdfive_hash:nN #1#2 + { T , F , TF } { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \tl_set:Nx #2 + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { - \tex_mdfivesum:D file \exp_after:wN - { \l_@@_full_name_str } + \tl_set:Nx #2 + { + \tex_mdfivesum:D file \exp_after:wN + { \l_@@_full_name_tl } + } + \prg_return_true: } + { \prg_return_false: } } \cs_if_exist:NF \tex_filesize:D { @@ -2281,6 +1671,7 @@ \__kernel_msg_error:nnx { kernel } { primitive-not-available } { \exp_not:c { (pdf)file #2 } } + \prg_return_false: } } } @@ -2301,16 +1692,14 @@ % \begin{macrocode} \cs_new_protected:Npn \file_if_exist_input:n #1 { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NF \l_@@_full_name_str - { \@@_input:V \l_@@_full_name_str } + \file_get_full_name:nNT {#1} \l_@@_full_name_tl + { \@@_input:V \l_@@_full_name_tl } } \cs_new_protected:Npn \file_if_exist_input:nF #1#2 { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl + { \@@_input:V \l_@@_full_name_tl } {#2} - { \@@_input:V \l_@@_full_name_str } } % \end{macrocode} % \end{macro} @@ -2401,10 +1790,14 @@ % \begin{macrocode} \cs_new:Npn \msg_expandable_error:nnnnnn #1#2#3#4#5#6 { - \exp_args:Nf \@@_expandable_error_module:nn + \exp_args:Ne \@@_expandable_error_module:nn { - \exp_args:Nf \tl_to_str:n - { \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} } + \exp_args:Nc \exp_args:Noooo + { \c_@@_text_prefix_tl #1 / #2 } + { \tl_to_str:n {#3} } + { \tl_to_str:n {#4} } + { \tl_to_str:n {#5} } + { \tl_to_str:n {#6} } } {#1} } @@ -2516,27 +1909,6 @@ %<@@=prop> % \end{macrocode} % -% \begin{macro}[EXP]{\prop_count:N, \prop_count:c} -% \begin{macro}[EXP]{\@@_count:nn} -% Counting the key--value pairs in a property list is done using the -% same approach as for other count functions: turn each entry into a -% \texttt{+1} then use integer evaluation to actually do the -% mathematics. -% \begin{macrocode} -\cs_new:Npn \prop_count:N #1 - { - \int_eval:n - { - 0 - \prop_map_function:NN #1 \@@_count:nn - } - } -\cs_new:Npn \@@_count:nn #1#2 { + 1 } -\cs_generate_variant:Nn \prop_count:N { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \begin{macro}[rEXP]{\prop_map_tokens:Nn, \prop_map_tokens:cn} % \begin{macro}{\@@_map_tokens:nwwn} % The mapping is very similar to \cs{prop_map_function:NN}. The @@ -2878,34 +2250,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macrocode} -%<@@=skip> -% \end{macrocode} -% -% \begin{macro}{\skip_split_finite_else_action:nnNN} -% This macro is useful when performing error checking in certain -% circumstances. If the \meta{skip} register holds finite glue it sets -% |#3| and |#4| to the stretch and shrink component, resp. If it holds -% infinite glue set |#3| and |#4| to zero and issue the special action -% |#2| which is probably an error message. -% Assignments are local. -% \begin{macrocode} -\cs_new:Npn \skip_split_finite_else_action:nnNN #1#2#3#4 - { - \skip_if_finite:nTF {#1} - { - #3 = \tex_gluestretch:D #1 \scan_stop: - #4 = \tex_glueshrink:D #1 \scan_stop: - } - { - #3 = \c_zero_skip - #4 = \c_zero_skip - #2 - } - } -% \end{macrocode} -% \end{macro} -% % \subsection{Additions to \pkg{l3sys}} % % \begin{macrocode} @@ -3045,7 +2389,7 @@ \cs_new_protected:Npn \sys_shell_get:nnN #1#2#3 { \sys_shell_get:nnNF {#1} {#2} #3 - { \tl_clear:N #3 } + { \tl_set:Nn #3 { \q_no_value } } } \prg_new_protected_conditional:Npnn \sys_shell_get:nnN #1#2#3 { T , F , TF } { @@ -3062,8 +2406,8 @@ \prg_return_false: } { - \if_false: { \fi: \group_begin: + \if_false: { \fi: \int_set_eq:NN \tex_tracingnesting:D \c_zero_int \exp_args:No \tex_everyeof:D { \c_@@_marker_tl } #2 \scan_stop: @@ -3222,122 +2566,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\tl_reverse_tokens:n} -% \begin{macro}[EXP]{\@@_reverse_group:nn} -% The same as \cs{tl_reverse:n} but with recursion within brace groups. -% \begin{macrocode} -\cs_new:Npn \tl_reverse_tokens:n #1 - { - \__kernel_exp_not:w \exp_after:wN - { - \exp:w - \@@_act:NNNnn - \@@_reverse_normal:nN - \@@_reverse_group:nn - \@@_reverse_space:n - { } - {#1} - } - } -\cs_new:Npn \@@_reverse_group:nn #1 - { - \@@_act_group_recurse:Nnn - \@@_act_reverse_output:n - { \tl_reverse_tokens:n } - } -% \end{macrocode} -% \end{macro} -% \begin{macro}[EXP]{\@@_act_group_recurse:Nnn} -% In many applications of \cs{@@_act:NNNnn}, we need to recursively -% apply some transformation within brace groups, then output. In this -% code, |#1| is the output function, |#2| is the transformation, -% which should expand in two steps, and |#3| is the group. -% \begin{macrocode} -\cs_new:Npn \@@_act_group_recurse:Nnn #1#2#3 - { - \exp_args:Nf #1 - { \exp_after:wN \exp_after:wN \exp_after:wN { #2 {#3} } } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\tl_count_tokens:n} -% \begin{macro}[EXP]{\@@_act_count_normal:nN, -% \@@_act_count_group:nn, \@@_act_count_space:n} -% The token count is computed through an \cs{int_eval:n} construction. -% Each \texttt{1+} is output to the \emph{left}, into the integer -% expression, and the sum is ended by the \cs{exp_end:} inserted by -% \cs{@@_act_end:wn} (which is technically implemented as \cs{c_zero_int}). -% Somewhat a hack! -% \begin{macrocode} -\cs_new:Npn \tl_count_tokens:n #1 - { - \int_eval:n - { - \@@_act:NNNnn - \@@_act_count_normal:nN - \@@_act_count_group:nn - \@@_act_count_space:n - { } - {#1} - } - } -\cs_new:Npn \@@_act_count_normal:nN #1 #2 { 1 + } -\cs_new:Npn \@@_act_count_space:n #1 { 1 + } -\cs_new:Npn \@@_act_count_group:nn #1 #2 - { 2 + \tl_count_tokens:n {#2} + } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsubsection{Deprecated functions} -% -% \begin{macro}[deprecated = 2020-12-31] -% { -% \tl_set_from_file:Nnn, \tl_set_from_file:cnn, -% \tl_gset_from_file:Nnn, \tl_gset_from_file:cnn, -% \tl_set_from_file_x:Nnn, \tl_set_from_file_x:cnn, -% \tl_gset_from_file_x:Nnn, \tl_gset_from_file_x:cnn -% } -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \file_get:nnN } -\cs_new_protected:Npn \tl_set_from_file:Nnn #1#2#3 - { \file_get:nnN {#3} {#2} #1 } -\cs_generate_variant:Nn \tl_set_from_file:Nnn { c } -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \file_get:nnN } -\cs_new_protected:Npn \tl_gset_from_file:Nnn #1#2#3 - { - \group_begin: - \file_get:nnN {#3} {#2} \l_@@_internal_a_tl - \tl_gset_eq:NN #1 \l_@@_internal_a_tl - \group_end: - } -\cs_generate_variant:Nn \tl_gset_from_file:Nnn { c } -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \file_get:nnN } -\cs_new_protected:Npn \tl_set_from_file_x:Nnn #1#2#3 - { - \group_begin: - \file_get:nnN {#3} {#2} \l_@@_internal_a_tl - #2 \scan_stop: - \tl_set:Nx \l_@@_internal_a_tl { \l_@@_internal_a_tl } - \exp_args:NNNo \group_end: - \tl_set:Nn #1 \l_@@_internal_a_tl - } -\cs_generate_variant:Nn \tl_set_from_file_x:Nnn { c } -\__kernel_patch_deprecation:nnNNpn { 2020-12-31 } { \file_get:nnN } -\cs_new_protected:Npn \tl_gset_from_file_x:Nnn #1#2#3 - { - \group_begin: - \file_get:nnN {#3} {#2} \l_@@_internal_a_tl - #2 \scan_stop: - \tl_gset:Nx #1 { \l_@@_internal_a_tl } - \group_end: - } -\cs_generate_variant:Nn \tl_gset_from_file_x:Nnn { c } -% \end{macrocode} -% \end{macro} -% % \subsubsection{Unicode case changing} % % The mechanisms needed for case changing are somewhat involved, particularly diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index 0fa08188cd9..17fc46306c8 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -1,7 +1,7 @@ % \iffalse meta-comment % %% File: l3clist.dtx -% +% % Copyright (C) 2004-2011 Frank Mittelbach, The LaTeX3 Project % (C) 2012-2019 The LaTeX3 Project % @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -337,7 +337,7 @@ % \begin{texnote} % The result is returned within \tn{unexpanded}, which means that the % comma list does not expand further when appearing in an -% \texttt{x}-type argument expansion. +% \texttt{x}-type or \texttt{e}-type argument expansion. % \end{texnote} % \end{function} % @@ -584,28 +584,16 @@ % in the previous section: a comma list should either be used as an % ordered data type or as a stack, but not in both ways. % -% \begin{function}[updated = 2012-05-14]{\clist_get:NN, \clist_get:cN} +% \begin{function}[noTF, added = 2012-05-14, updated = 2019-02-16] +% {\clist_get:NN, \clist_get:cN} % \begin{syntax} % \cs{clist_get:NN} \meta{comma list} \meta{token list variable} % \end{syntax} % Stores the left-most item from a \meta{comma list} in the % \meta{token list variable} without removing it from the % \meta{comma list}. The \meta{token list variable} is assigned locally. -% If the \meta{comma list} is empty the \meta{token list variable} -% is set to the marker value \cs{q_no_value}. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-14]{\clist_get:NN, \clist_get:cN} -% \begin{syntax} -% \cs{clist_get:NNTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{comma list} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{comma list} is non-empty, stores the top item from the -% \meta{comma list} in the \meta{token list variable} without removing it -% from the \meta{comma list}. The \meta{token list variable} is assigned -% locally. +% In the non-branching version, if the \meta{comma list} is empty the +% \meta{token list variable} is set to the marker value \cs{q_no_value}. % \end{function} % % \begin{function}[updated = 2011-09-06]{\clist_pop:NN, \clist_pop:cN} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx index 88ae571c742..48f4edbc6a3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -100,7 +100,7 @@ % % \section{Setting coffin content and poles} % -% \begin{function}[added = 2011-08-17, updated = 2011-09-03] +% \begin{function}[added = 2011-08-17, updated = 2019-01-21] % { % \hcoffin_set:Nn, \hcoffin_set:cn, % \hcoffin_gset:Nn, \hcoffin_gset:cn @@ -187,6 +187,47 @@ % \meta{offset} should be given as a dimension expression. % \end{function} % +% \section{Coffin affine transformations} +% +% \begin{function}[updated = 2019-01-23] +% { +% \coffin_resize:Nnn, \coffin_resize:cnn, +% \coffin_gresize:Nnn, \coffin_gresize:cnn +% } +% \begin{syntax} +% \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height} +% \end{syntax} +% Resized the \meta{coffin} to \meta{width} and \meta{total-height}, +% both of which should be given as dimension expressions. +% \end{function} +% +% \begin{function} +% { +% \coffin_rotate:Nn, \coffin_rotate:cn, +% \coffin_grotate:Nn, \coffin_grotate:cn +% } +% \begin{syntax} +% \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle} +% \end{syntax} +% Rotates the \meta{coffin} by the given \meta{angle} (given in +% degrees counter-clockwise). This process rotates both the +% coffin content and poles. Multiple rotations do not result in +% the bounding box of the coffin growing unnecessarily. +% \end{function} +% +% \begin{function}[updated = 2019-01-23] +% { +% \coffin_scale:Nnn, \coffin_scale:cnn, +% \coffin_gscale:Nnn, \coffin_gscale:cnn +% } +% \begin{syntax} +% \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale} +% \end{syntax} +% Scales the \meta{coffin} by a factors \meta{x-scale} and +% \meta{y-scale} in the horizontal and vertical directions, +% respectively. The two scale factors should be given as real numbers. +% \end{function} +% % \section{Joining and using coffins} % % \begin{function}[updated = 2019-01-22] @@ -1277,6 +1318,537 @@ % \end{macro} % \end{macro} % +% \subsection{Affine transformations} +% +% \begin{variable}{\l_@@_sin_fp} +% \begin{variable}{\l_@@_cos_fp} +% Used for rotations to get the sine and cosine values. +% \begin{macrocode} +\fp_new:N \l_@@_sin_fp +\fp_new:N \l_@@_cos_fp +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\l_@@_bounding_prop} +% A property list for the bounding box of a coffin. This is only needed +% during the rotation, so there is just the one. +% \begin{macrocode} +\prop_new:N \l_@@_bounding_prop +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_corners_prop, \l_@@_poles_prop} +% Used to avoid needing to track scope for intermediate steps. +% \begin{macrocode} +\prop_new:N \l_@@_corners_prop +\prop_new:N \l_@@_poles_prop +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_bounding_shift_dim} +% The shift of the bounding box of a coffin from the real content. +% \begin{macrocode} +\dim_new:N \l_@@_bounding_shift_dim +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_left_corner_dim} +% \begin{variable}{\l_@@_right_corner_dim} +% \begin{variable}{\l_@@_bottom_corner_dim} +% \begin{variable}{\l_@@_top_corner_dim} +% These are used to hold maxima for the various corner values: these +% thus define the minimum size of the bounding box after rotation. +% \begin{macrocode} +\dim_new:N \l_@@_left_corner_dim +\dim_new:N \l_@@_right_corner_dim +\dim_new:N \l_@@_bottom_corner_dim +\dim_new:N \l_@@_top_corner_dim +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{macro} +% { +% \coffin_rotate:Nn, \coffin_rotate:cn, +% \coffin_grotate:Nn, \coffin_grotate:cn +% } +% \begin{macro}{\@@_rotate:NnNNN} +% Rotating a coffin requires several steps which can be conveniently +% run together. The sine and cosine of the angle in degrees are +% computed. This is then used to set \cs{l_@@_sin_fp} and +% \cs{l_@@_cos_fp}, which are carried through unchanged for the rest +% of the procedure. +% \begin{macrocode} +\cs_new_protected:Npn \coffin_rotate:Nn #1#2 + { \@@_rotate:NnNNN #1 {#2} \box_rotate:Nn \prop_set_eq:cN \hbox_set:Nn } +\cs_generate_variant:Nn \coffin_rotate:Nn { c } +\cs_new_protected:Npn \coffin_grotate:Nn #1#2 + { \@@_rotate:NnNNN #1 {#2} \box_grotate:Nn \prop_gset_eq:cN \hbox_gset:Nn } +\cs_generate_variant:Nn \coffin_grotate:Nn { c } +\cs_new_protected:Npn \@@_rotate:NnNNN #1#2#3#4#5 + { + \fp_set:Nn \l_@@_sin_fp { sind ( #2 ) } + \fp_set:Nn \l_@@_cos_fp { cosd ( #2 ) } +% \end{macrocode} +% Use a local copy of the property lists to avoid needing to pass the +% name and scope around. +% \begin{macrocode} + \prop_set_eq:Nc \l_@@_corners_prop + { coffin ~ \@@_to_value:N #1 ~ corners } + \prop_set_eq:Nc \l_@@_poles_prop + { coffin ~ \@@_to_value:N #1 ~ poles } +% \end{macrocode} +% The corners and poles of the coffin can now be rotated around the +% origin. This is best achieved using mapping functions. +% \begin{macrocode} + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_rotate_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_rotate_pole:Nnnnnn #1 {##1} ##2 } +% \end{macrocode} +% The bounding box of the coffin needs to be rotated, and to do this +% the corners have to be found first. They are then rotated in the same +% way as the corners of the coffin material itself. +% \begin{macrocode} + \@@_set_bounding:N #1 + \prop_map_inline:Nn \l_@@_bounding_prop + { \@@_rotate_bounding:nnn {##1} ##2 } +% \end{macrocode} +% At this stage, there needs to be a calculation to find where the +% corners of the content and the box itself will end up. +% \begin{macrocode} + \@@_find_corner_maxima:N #1 + \@@_find_bounding_shift: + #3 #1 {#2} +% \end{macrocode} +% The correction of the box position itself takes place here. The idea +% is that the bounding box for a coffin is tight up to the content, and +% has the reference point at the bottom-left. The $x$-direction is +% handled by moving the content by the difference in the positions of +% the bounding box and the content left edge. The $y$-direction is +% dealt with by moving the box down by any depth it has acquired. The +% internal box is used here to allow for the next step. +% \begin{macrocode} + \hbox_set:Nn \l_@@_internal_box + { + \tex_kern:D + \dim_eval:n + { \l_@@_bounding_shift_dim - \l_@@_left_corner_dim } + \exp_stop_f: + \box_move_down:nn { \l_@@_bottom_corner_dim } + { \box_use:N #1 } + } +% \end{macrocode} +% If there have been any previous rotations then the size of the +% bounding box will be bigger than the contents. This can be corrected +% easily by setting the size of the box to the height and width of the +% content. As this operation requires setting box dimensions and these +% transcend grouping, the safe way to do this is to use the internal box +% and to reset the result into the target box. +% \begin{macrocode} + \box_set_ht:Nn \l_@@_internal_box + { \l_@@_top_corner_dim - \l_@@_bottom_corner_dim } + \box_set_dp:Nn \l_@@_internal_box { 0pt } + \box_set_wd:Nn \l_@@_internal_box + { \l_@@_right_corner_dim - \l_@@_left_corner_dim } + #5 #1 { \box_use_drop:N \l_@@_internal_box } +% \end{macrocode} +% The final task is to move the poles and corners such that they are +% back in alignment with the box reference point. +% \begin{macrocode} + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_shift_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_shift_pole:Nnnnnn #1 {##1} ##2 } +% \end{macrocode} +% Update the coffin data. +% \begin{macrocode} + #4 { coffin ~ \@@_to_value:N #1 ~ corners } + \l_@@_corners_prop + #4 { coffin ~ \@@_to_value:N #1 ~ poles } + \l_@@_poles_prop + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_set_bounding:N} +% The bounding box corners for a coffin are easy enough to find: this +% is the same code as for the corners of the material itself, but +% using a dedicated property list. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_bounding:N #1 + { + \prop_put:Nnx \l_@@_bounding_prop { tl } + { { 0pt } { \dim_eval:n { \box_ht:N #1 } } } + \prop_put:Nnx \l_@@_bounding_prop { tr } + { + { \dim_eval:n { \box_wd:N #1 } } + { \dim_eval:n { \box_ht:N #1 } } + } + \dim_set:Nn \l_@@_internal_dim { -\box_dp:N #1 } + \prop_put:Nnx \l_@@_bounding_prop { bl } + { { 0pt } { \dim_use:N \l_@@_internal_dim } } + \prop_put:Nnx \l_@@_bounding_prop { br } + { + { \dim_eval:n { \box_wd:N #1 } } + { \dim_use:N \l_@@_internal_dim } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_rotate_bounding:nnn} +% \begin{macro}{\@@_rotate_corner:Nnnn} +% Rotating the position of the corner of the coffin is just a case +% of treating this as a vector from the reference point. The same +% treatment is used for the corners of the material itself and the +% bounding box. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rotate_bounding:nnn #1#2#3 + { + \@@_rotate_vector:nnNN {#2} {#3} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_bounding_prop {#1} + { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } + } +\cs_new_protected:Npn \@@_rotate_corner:Nnnn #1#2#3#4 + { + \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_corners_prop {#2} + { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_rotate_pole:Nnnnnn} +% Rotating a single pole simply means shifting the co-ordinate of +% the pole and its direction. The rotation here is about the bottom-left +% corner of the coffin. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rotate_pole:Nnnnnn #1#2#3#4#5#6 + { + \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \@@_rotate_vector:nnNN {#5} {#6} + \l_@@_x_prime_dim \l_@@_y_prime_dim + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } + { \dim_use:N \l_@@_x_prime_dim } + { \dim_use:N \l_@@_y_prime_dim } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_rotate_vector:nnNN} +% A rotation function, which needs only an input vector (as dimensions) +% and an output space. The values \cs{l_@@_cos_fp} and +% \cs{l_@@_sin_fp} should previously have been set up correctly. +% Working this way means that the floating point work is kept to a +% minimum: for any given rotation the sin and cosine values do no +% change, after all. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rotate_vector:nnNN #1#2#3#4 + { + \dim_set:Nn #3 + { + \fp_to_dim:n + { + \dim_to_fp:n {#1} * \l_@@_cos_fp + - \dim_to_fp:n {#2} * \l_@@_sin_fp + } + } + \dim_set:Nn #4 + { + \fp_to_dim:n + { + \dim_to_fp:n {#1} * \l_@@_sin_fp + + \dim_to_fp:n {#2} * \l_@@_cos_fp + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_find_corner_maxima:N} +% \begin{macro}{\@@_find_corner_maxima_aux:nn} +% The idea here is to find the extremities of the content of the +% coffin. This is done by looking for the smallest values for the bottom +% and left corners, and the largest values for the top and right +% corners. The values start at the maximum dimensions so that the +% case where all are positive or all are negative works out correctly. +% \begin{macrocode} +\cs_new_protected:Npn \@@_find_corner_maxima:N #1 + { + \dim_set:Nn \l_@@_top_corner_dim { -\c_max_dim } + \dim_set:Nn \l_@@_right_corner_dim { -\c_max_dim } + \dim_set:Nn \l_@@_bottom_corner_dim { \c_max_dim } + \dim_set:Nn \l_@@_left_corner_dim { \c_max_dim } + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_find_corner_maxima_aux:nn ##2 } + } +\cs_new_protected:Npn \@@_find_corner_maxima_aux:nn #1#2 + { + \dim_set:Nn \l_@@_left_corner_dim + { \dim_min:nn { \l_@@_left_corner_dim } {#1} } + \dim_set:Nn \l_@@_right_corner_dim + { \dim_max:nn { \l_@@_right_corner_dim } {#1} } + \dim_set:Nn \l_@@_bottom_corner_dim + { \dim_min:nn { \l_@@_bottom_corner_dim } {#2} } + \dim_set:Nn \l_@@_top_corner_dim + { \dim_max:nn { \l_@@_top_corner_dim } {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_find_bounding_shift:} +% \begin{macro}{\@@_find_bounding_shift_aux:nn} +% The approach to finding the shift for the bounding box is similar to +% that for the corners. However, there is only one value needed here and +% a fixed input property list, so things are a bit clearer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_find_bounding_shift: + { + \dim_set:Nn \l_@@_bounding_shift_dim { \c_max_dim } + \prop_map_inline:Nn \l_@@_bounding_prop + { \@@_find_bounding_shift_aux:nn ##2 } + } +\cs_new_protected:Npn \@@_find_bounding_shift_aux:nn #1#2 + { + \dim_set:Nn \l_@@_bounding_shift_dim + { \dim_min:nn { \l_@@_bounding_shift_dim } {#1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_shift_corner:Nnnn} +% \begin{macro}{\@@_shift_pole:Nnnnnn} +% Shifting the corners and poles of a coffin means subtracting the +% appropriate values from the $x$- and $y$-components. For +% the poles, this means that the direction vector is unchanged. +% \begin{macrocode} +\cs_new_protected:Npn \@@_shift_corner:Nnnn #1#2#3#4 + { + \prop_put:Nnx \l_@@_corners_prop {#2} + { + { \dim_eval:n { #3 - \l_@@_left_corner_dim } } + { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } } + } + } +\cs_new_protected:Npn \@@_shift_pole:Nnnnnn #1#2#3#4#5#6 + { + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_eval:n { #3 - \l_@@_left_corner_dim } } + { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } } + {#5} {#6} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{variable}{\l_@@_scale_x_fp} +% \begin{variable}{\l_@@_scale_y_fp} +% Storage for the scaling factors in $x$ and $y$, respectively. +% \begin{macrocode} +\fp_new:N \l_@@_scale_x_fp +\fp_new:N \l_@@_scale_y_fp +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\l_@@_scaled_total_height_dim} +% \begin{variable}{\l_@@_scaled_width_dim} +% When scaling, the values given have to be turned into absolute values. +% \begin{macrocode} +\dim_new:N \l_@@_scaled_total_height_dim +\dim_new:N \l_@@_scaled_width_dim +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{macro} +% { +% \coffin_resize:Nnn, \coffin_resize:cnn, +% \coffin_gresize:Nnn, \coffin_gresize:cnn +% } +% \begin{macro}{\@@_resize:NnnNN} +% Resizing a coffin begins by setting up the user-friendly names for +% the dimensions of the coffin box. The new sizes are then turned into +% scale factor. This is the same operation as takes place for the +% underlying box, but that operation is grouped and so the same +% calculation is done here. +% \begin{macrocode} +\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3 + { + \@@_resize:NnnNN #1 {#2} {#3} + \box_resize_to_wd_and_ht_plus_dp:Nnn + \prop_set_eq:cN + } +\cs_generate_variant:Nn \coffin_resize:Nnn { c } +\cs_new_protected:Npn \coffin_gresize:Nnn #1#2#3 + { + \@@_resize:NnnNN #1 {#2} {#3} + \box_gresize_to_wd_and_ht_plus_dp:Nnn + \prop_gset_eq:cN + } +\cs_generate_variant:Nn \coffin_gresize:Nnn { c } +\cs_new_protected:Npn \@@_resize:NnnNN #1#2#3#4#5 + { + \fp_set:Nn \l_@@_scale_x_fp + { \dim_to_fp:n {#2} / \dim_to_fp:n { \coffin_wd:N #1 } } + \fp_set:Nn \l_@@_scale_y_fp + { + \dim_to_fp:n {#3} + / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 } + } + #4 #1 {#2} {#3} + \@@_resize_common:NnnN #1 {#2} {#3} #5 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_resize_common:NnnN} +% The poles and corners of the coffin are scaled to the appropriate +% places before actually resizing the underlying box. +% \begin{macrocode} +\cs_new_protected:Npn \@@_resize_common:NnnN #1#2#3#4 + { + \prop_set_eq:Nc \l_@@_corners_prop + { coffin ~ \@@_to_value:N #1 ~ corners } + \prop_set_eq:Nc \l_@@_poles_prop + { coffin ~ \@@_to_value:N #1 ~ poles } + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_scale_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_scale_pole:Nnnnnn #1 {##1} ##2 } +% \end{macrocode} +% Negative $x$-scaling values place the poles in the wrong +% location: this is corrected here. +% \begin{macrocode} + \fp_compare:nNnT \l_@@_scale_x_fp < \c_zero_fp + { + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_x_shift_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 } + } + #4 { coffin ~ \@@_to_value:N #1 ~ corners } + \l_@@_corners_prop + #4 { coffin ~ \@@_to_value:N #1 ~ poles } + \l_@@_poles_prop + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \coffin_scale:Nnn, \coffin_scale:cnn, +% \coffin_gscale:Nnn, \coffin_gscale:cnn +% } +% \begin{macro}{\coffin_scale:NnnNN} +% For scaling, the opposite calculation is done to find the new +% dimensions for the coffin. Only the total height is needed, as this +% is the shift required for corners and poles. The scaling is done +% the \TeX{} way as this works properly with floating point values +% without needing to use the \texttt{fp} module. +% \begin{macrocode} +\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3 + { \@@_scale:NnnNN #1 {#2} {#3} \box_scale:Nnn \prop_set_eq:cN } +\cs_generate_variant:Nn \coffin_scale:Nnn { c } +\cs_new_protected:Npn \coffin_gscale:Nnn #1#2#3 + { \@@_scale:NnnNN #1 {#2} {#3} \box_gscale:Nnn \prop_gset_eq:cN } +\cs_generate_variant:Nn \coffin_gscale:Nnn { c } +\cs_new_protected:Npn \@@_scale:NnnNN #1#2#3#4#5 + { + \fp_set:Nn \l_@@_scale_x_fp {#2} + \fp_set:Nn \l_@@_scale_y_fp {#3} + #4 #1 { \l_@@_scale_x_fp } { \l_@@_scale_y_fp } + \dim_set:Nn \l_@@_internal_dim + { \coffin_ht:N #1 + \coffin_dp:N #1 } + \dim_set:Nn \l_@@_scaled_total_height_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_internal_dim } + \dim_set:Nn \l_@@_scaled_width_dim + { -\fp_abs:n { \l_@@_scale_x_fp } \coffin_wd:N #1 } + \@@_resize_common:NnnN #1 + { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim } + #5 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_scale_vector:nnNN} +% This functions scales a vector from the origin using the pre-set scale +% factors in $x$ and $y$. This is a much less complex operation +% than rotation, and as a result the code is a lot clearer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_scale_vector:nnNN #1#2#3#4 + { + \dim_set:Nn #3 + { \fp_to_dim:n { \dim_to_fp:n {#1} * \l_@@_scale_x_fp } } + \dim_set:Nn #4 + { \fp_to_dim:n { \dim_to_fp:n {#2} * \l_@@_scale_y_fp } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_scale_corner:Nnnn} +% \begin{macro}{\@@_scale_pole:Nnnnnn} +% Scaling both corners and poles is a simple calculation using the +% preceding vector scaling. +% \begin{macrocode} +\cs_new_protected:Npn \@@_scale_corner:Nnnn #1#2#3#4 + { + \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_corners_prop {#2} + { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } + } +\cs_new_protected:Npn \@@_scale_pole:Nnnnnn #1#2#3#4#5#6 + { + \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } + {#5} {#6} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_x_shift_corner:Nnnn} +% \begin{macro}{\@@_x_shift_pole:Nnnnnn} +% These functions correct for the $x$ displacement that takes +% place with a negative horizontal scaling. +% \begin{macrocode} +\cs_new_protected:Npn \@@_x_shift_corner:Nnnn #1#2#3#4 + { + \prop_put:Nnx \l_@@_corners_prop {#2} + { + { \dim_eval:n { #3 + \box_wd:N #1 } } {#4} + } + } +\cs_new_protected:Npn \@@_x_shift_pole:Nnnnnn #1#2#3#4#5#6 + { + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_eval:n { #3 + \box_wd:N #1 } } {#4} + {#5} {#6} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Aligning and typesetting of coffins} % % \begin{macro} @@ -1698,6 +2270,14 @@ % \end{macrocode} % \end{variable} % +% \begin{macro}{\@@_color:n} +% Calls \tn{color}, and otherwise does nothing if \tn{color} is not defined. +% \begin{macrocode} +\cs_new_protected:Npn \@@_color:n #1 + { \cs_if_exist:NT \color { \color {#1} } } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\coffin_mark_handle:Nnnn, \coffin_mark_handle:cnnn} % \begin{macro}{\@@_mark_handle_aux:nnnnNnn} % Marking a single handle is relatively easy. The standard attachment @@ -1714,7 +2294,7 @@ \hbox:n { \tex_vrule:D width 1pt height 1pt \scan_stop: } % TODO %</initex> %<*package> - \color {#4} + \@@_color:n {#4} \rule { 1pt } { 1pt } %</package> } @@ -1726,7 +2306,7 @@ % TODO %</initex> %<*package> - \color {#4} + \@@_color:n {#4} %</package> \l_@@_display_font_tl ( \tl_to_str:n { #2 , #3 } ) @@ -1783,7 +2363,7 @@ \hbox:n { \tex_vrule:D width 1pt height 1pt \scan_stop: } % TODO %</initex> %<*package> - \color {#2} + \@@_color:n {#2} \rule { 1pt } { 1pt } %</package> } @@ -1829,7 +2409,7 @@ % TODO %</initex> %<*package> - \color {#6} + \@@_color:n {#6} %</package> \l_@@_display_font_tl ( \tl_to_str:n { #1 , ##1 } ) diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx index 738be5b26d6..42d6b15e1bb 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx index 23cf8f317f2..e0a930b68bd 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -54,6 +54,31 @@ % A few commands have had to be deprecated over the years. This module % defines deprecated and deleted commands to produce an error. % +% The life of a deprecated command has several stages. +% \begin{itemize} +% \item When we decide it should be eventually removed the command's +% definition is put in this file \pkg{l3deprecation.dtx} and the name +% of the command is added to the list in \pkg{l3obsolete.txt}. The +% command remains defined by default for $12$ or more months, +% typically until the end of a year. During that time, if \pkg{expl3} +% is loaded with any of the options \texttt{check-declarations} or +% \texttt{log-functions} or \texttt{enable-debug} typically used in +% package test files, the command will produce a warning. +% \item Then by default the command produces an error for all users, +% which can be suppressed for $6$ months through the option +% \texttt{undo-recent-deprecations}. +% \item After this $6$-month grace period, the command irreversibly +% produces an error. Its original definition can then be removed from +% the sources, leaving only the error definition. In +% \pkg{l3obsolete.txt} its name is moved from the \enquote{Deprecated +% functions and variables} list to the \enquote{Removed functions and +% variables} list. +% \end{itemize} +% Package authors are encouraged to have a test file with +% \cs{debug_on:n} |{deprecation}|, which makes commands at all stages of +% this list into errors. This helps detect uses of deprecated commands +% before user complain. +% % \end{documentation} % % \begin{implementation} @@ -68,6 +93,238 @@ %<@@=deprecation> % \end{macrocode} % +% \subsection{Helpers and variables} +% +% \begin{variable}{\l_@@_grace_period_bool} +% This is set to \texttt{true} when the deprecated command that is +% being defined is in its grace period, meaning between the time it +% becomes an error by default and the time $6$~months later where even +% \texttt{undo-recent-deprecations} stops restoring it. +% \begin{macrocode} +\bool_new:N \l_@@_grace_period_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[EXP]{\@@_date_compare:nNnTF, \@@_date_compare_aux:w} +% Expects |#1| and |#3| to be dates in the format YYYY-MM-DD (but +% accepts YYYY or YYYY-MM too, filling in zeros for the missing data). +% Compares them using |#2| (one of |<|, |=|, |>|). +% \begin{macrocode} +\cs_new:Npn \@@_date_compare:nNnTF #1#2#3 + { \@@_date_compare_aux:w #1 -0-0- \q_mark #2 #3 -0-0- \q_stop } +\cs_new:Npn \@@_date_compare_aux:w + #1 - #2 - #3 - #4 \q_mark #5 #6 - #7 - #8 - #9 \q_stop + { + \int_compare:nNnTF {#1} = {#6} + { + \int_compare:nNnTF {#2} = {#7} + { \int_compare:nNnTF {#3} #5 {#8} } + { \int_compare:nNnTF {#2} #5 {#7} } + } + { \int_compare:nNnTF {#1} #5 {#6} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_not_yet_deprecated:nTF, \@@_minus_six_months:w} +% Receives a deprecation \meta{date} and runs the \texttt{true} +% (\texttt{false}) branch if the \pkg{expl3} date is earlier (later) +% than \meta{date}. If \texttt{undo-recent-deprecations} is used we +% subtract $6$ months to the \pkg{expl3} date (equivalently add $6$ +% months to the \meta{date}). In addition, if the \pkg{expl3} date is +% between \meta{date} and \meta{date} plus $6$ months, +% \cs{l_@@_grace_period_bool} is set to \texttt{true}, otherwise +% \texttt{false}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_not_yet_deprecated:nTF #1 + { + \bool_set_false:N \l_@@_grace_period_bool + \exp_args:No \@@_date_compare:nNnTF { \ExplLoaderFileDate } < {#1} + { \use_i:nn } + { + \exp_args:Nf \@@_date_compare:nNnTF + { + \exp_after:wN \@@_minus_six_months:w + \ExplLoaderFileDate -0-0- \q_stop + } < {#1} + { + \bool_set_true:N \l_@@_grace_period_bool + \bool_if:NTF \l@expl@undo@recent@deprecations@bool + } + { \use_ii:nn } + } + } +\cs_new:Npn \@@_minus_six_months:w #1 - #2 - #3 - #4 \q_stop + { + \int_compare:nNnTF {#2} > 6 + { #1 - \int_eval:n { #2 - 6 } - #3 } + { \int_eval:n { #1 - 1 } - \int_eval:n { #2 + 6 } - #3 } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Patching definitions to deprecate} +% +% \begin{quote} +% \cs{__kernel_patch_deprecation:nnNNpn} \Arg{date} \Arg{replacement} +% \meta{definition} \meta{function} \meta{parameters} \Arg{code} +% \end{quote} +% defines the \meta{function} to produce a warning and run its +% \meta{code}, or to produce an error and not run any \meta{code}, +% depending on the \pkg{expl3} date. +% \begin{itemize} +% \item If the \pkg{expl3} date is less than the \meta{date} (plus +% $6$~months in case \texttt{undo-recent-deprecations} is used) then +% we define the \meta{function} to produce a warning and run its code. +% The warning is actually suppressed in two cases: +% \begin{itemize} +% \item if neither \texttt{undo-recent-deprecations} nor +% \texttt{enable-debug} are in effect we may be in an end-user's +% document so it is suppressed; +% \item if the command is expandable then we cannot produce a warning. +% \end{itemize} +% \item Otherwise, we define the \meta{function} to produce an error. +% \end{itemize} +% In both cases we additionally make \cs{debug_on:n} |{deprecation}| +% turn the \meta{function} into an \tn{outer} error, and +% \cs{debug_off:n} |{deprecation}| restore whatever the behaviour was +% without \cs{debug_on:n} |{deprecation}|. +% +% In later sections we use the \pkg{l3doc} key \texttt{deprecated} with +% a date equal to that \meta{date} plus $6$~months, so that \pkg{l3doc} +% will complain if we forget to remove the stale \meta{parameters} and +% \Arg{code}. +% +% In the explanations below, \meta{definition} \meta{function} +% \meta{parameters} \Arg{code} or assignments that only differ in the +% scope of the \meta{definition} will be called \enquote{the standard +% definition}. +% +% \begin{macro} +% { +% \__kernel_patch_deprecation:nnNNpn, \@@_patch_aux:nnNNnn, +% \@@_warn_once:nnNnn, +% \@@_patch_aux:Nn, +% \@@_just_error:nnNN +% } +% (The parameter text is grabbed using |#5#|.) The arguments of +% \cs{__kernel_deprecation_code:nn} are run upon \cs{debug_on:n} +% |{deprecation}| and \cs{debug_off:n} |{deprecation}|, respectively. +% In both scenarios we the \meta{function} may be \tn{outer} so we +% undefine it with \cs{tex_let:D} before redefining it, with +% \cs{__kernel_deprecation_error:Nnn} or with some code added shortly. +% +% Then check the date (taking into account +% \texttt{undo-recent-deprecations}) to see if the command should be +% deprecated right away (\texttt{false} branch of +% \cs{@@_not_yet_deprecated:nTF}), in which case +% \cs{@@_just_error:nnNN} makes \meta{function} into an error (not +% \tn{outer}), ignoring its \meta{parameters} and \meta{code} +% completely. +% +% Otherwise distinguish cases where we should give a warning from +% those where we shouldn't: warnings can only happen for protected +% commands, and we only want them if either +% \texttt{undo-recent-deprecations} or \texttt{enable-debug} is in +% force, not for standard users. +% \begin{macrocode} +\cs_new_protected:Npn \__kernel_patch_deprecation:nnNNpn #1#2#3#4#5# + { \@@_patch_aux:nnNNnn {#1} {#2} #3 #4 {#5} } +\cs_new_protected:Npn \@@_patch_aux:nnNNnn #1#2#3#4#5#6 + { + \__kernel_deprecation_code:nn + { + \tex_let:D #4 \scan_stop: + \__kernel_deprecation_error:Nnn #4 {#2} {#1} + } + { \tex_let:D #4 \scan_stop: } + \@@_not_yet_deprecated:nTF {#1} + { + \bool_if:nTF + { + \cs_if_eq_p:NN #3 \cs_new_protected:Npn && + \__kernel_if_debug:TF + { \c_true_bool } { \l@expl@undo@recent@deprecations@bool } + } + { \@@_warn_once:nnNnn {#1} {#2} #4 {#5} {#6} } + { \@@_patch_aux:Nn #3 { #4 #5 {#6} } } + } + { \@@_just_error:nnNN {#1} {#2} #3 #4 } + } +% \end{macrocode} +% In case we want a warning, the \meta{function} is defined to produce +% such a warning without grabbing any argument, then redefine itself +% to the standard definition that the \meta{function} should have, +% with arguments, and call that definition. The \texttt{x}-type +% expansion and \cs{exp_not:n} avoid needing to double the~|#|, which +% we could not do anyways. We then deal with the code for +% \cs{debug_off:n} |{deprecation}|: presumably someone doing that does +% not need the warning so we simply do the standard definition. +% \begin{macrocode} +\cs_new_protected:Npn \@@_warn_once:nnNnn #1#2#3#4#5 + { + \cs_new_protected:Npx #3 + { + \__kernel_if_debug:TF + { + \exp_not:N \__kernel_msg_warning:nnxxx + { kernel } { deprecated-command } + {#1} + { \token_to_str:N #3 } + { \tl_to_str:n {#2} } + } + { } + \exp_not:n { \cs_gset_protected:Npn #3 #4 {#5} } + \exp_not:N #3 + } + \__kernel_deprecation_code:nn { } + { \cs_set_protected:Npn #3 #4 {#5} } + } +% \end{macrocode} +% In case we want neither warning nor error, the \meta{function} is +% given its standard definition. Here |#1| is \cs{cs_new:Npn} or +% \cs{cs_new_protected:Npn}) and |#2| is \meta{function} +% \meta{parameters} \Arg{code}, so |#1#2| performs the assignment. +% For \cs{debug_off:n} |{deprecation}| we want to use the same +% assignment but with a different scope, hence the \cs{cs_if_eq:NNTF} +% test. +% \begin{macrocode} +\cs_new_protected:Npn \@@_patch_aux:Nn #1#2 + { + #1 #2 + \cs_if_eq:NNTF #1 \cs_new_protected:Npn + { \__kernel_deprecation_code:nn { } { \cs_set_protected:Npn #2 } } + { \__kernel_deprecation_code:nn { } { \cs_set:Npn #2 } } + } +% \end{macrocode} +% Finally, if we want an error we reuse the same \cs{@@_patch_aux:Nn} +% as the previous case. Indeed, we want \cs{debug_off:n} +% |{deprecation}| to make the \meta{function} into an error, just like +% it is by default. The error is expandable or not, and the last +% argument of the error message is empty or is \texttt{grace} to +% denote the case where we are in the $6$~month grace period, in which +% case the error message is more detailed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_just_error:nnNN #1#2#3#4 + { + \exp_args:NNx \@@_patch_aux:Nn #3 + { + \exp_not:N #4 + { + \cs_if_eq:NNTF #3 \cs_new_protected:Npn + { \exp_not:N \__kernel_msg_error:nnnnnn } + { \exp_not:N \__kernel_msg_expandable_error:nnnnnn } + { kernel } { deprecated-command } + {#1} + { \token_to_str:N #4 } + { \tl_to_str:n {#2} } + { \bool_if:NT \l_@@_grace_period_bool { grace } } + } + } + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\__kernel_deprecation_error:Nnn} % The \tn{outer} definition here ensures the command cannot appear % in an argument. Use this auxiliary on all commands that have been @@ -85,112 +342,118 @@ { \tl_to_str:n {#3} } { \token_to_str:N #1 } { \tl_to_str:n {#2} } } } -\__kernel_deprecation_error:Nnn \box_resize:cnn - { \box_resize_to_wd_and_ht_plus_dp:cnn } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \box_resize:Nnn - { \box_resize_to_wd_and_ht_plus_dp:Nnn } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \box_use_clear:c - { \box_use_drop:c } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \box_use_clear:N - { \box_use_drop:N } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \c_job_name_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\__kernel_msg_new:nnn { kernel } { deprecated-command } + { + '#2'~deprecated~on~#1. + \tl_if_empty:nF {#3} { ~Use~'#3'. } + \str_if_eq:nnT {#4} { grace } + { + \c_space_tl + For~6~months~after~that~date~one~can~restore~a~deprecated~ + command~by~loading~the~expl3~package~with~the~option~ + 'undo-recent-deprecations'. + } + } +% \end{macrocode} +% +% \subsection{Removed functions} +% +% \begin{macro}{\@@_old_protected:Nnn, \@@_old:Nnn} +% Short-hands for old commands whose definition does not matter +% anymore, i.e., commands past the grace period. +% \begin{macrocode} +\cs_new_protected:Npn \@@_old_protected:Nnn #1#2#3 + { + \__kernel_patch_deprecation:nnNNpn {#3} {#2} + \cs_new_protected:Npn #1 { } + } +\cs_new_protected:Npn \@@_old:Nnn #1#2#3 + { + \__kernel_patch_deprecation:nnNNpn {#3} {#2} + \cs_new:Npn #1 { } + } +\@@_old:Nnn \c_job_name_tl { \c_sys_jobname_str } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \c_minus_one - { -1 } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \dim_case:nnn +\@@_old:Nnn \dim_case:nnn { \dim_case:nnF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \file_add_path:nN - { \file_get_full_name:nN } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \file_if_exist_input:nT +\@@_old_protected:Nnn \file_if_exist_input:nT { \file_if_exist:nT and~ \file_input:n } { 2018-03-05 } -\__kernel_deprecation_error:Nnn \file_if_exist_input:nTF +\@@_old_protected:Nnn \file_if_exist_input:nTF { \file_if_exist:nT and~ \file_input:n } { 2018-03-05 } -\__kernel_deprecation_error:Nnn \file_list: - { \file_log_list: } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \file_path_include:n - { \seq_put_right:Nn \l_file_search_path_seq } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \file_path_remove:n - { \seq_remove_all:Nn \l_file_search_path_seq } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \g_file_current_name_tl - { \g_file_current_name_str } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \int_case:nnn +\@@_old:Nnn \int_case:nnn { \int_case:nnF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \int_from_binary:n +\@@_old:Nnn \int_from_binary:n { \int_from_bin:n } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \int_from_hexadecimal:n +\@@_old:Nnn \int_from_hexadecimal:n { \int_from_hex:n } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \int_from_octal:n +\@@_old:Nnn \int_from_octal:n { \int_from_oct:n } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \int_to_binary:n +\@@_old:Nnn \int_to_binary:n { \int_to_bin:n } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \int_to_hexadecimal:n +\@@_old:Nnn \int_to_hexadecimal:n { \int_to_hex:n } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \int_to_octal:n +\@@_old:Nnn \int_to_octal:n { \int_to_oct:n } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \ior_get_str:NN +\@@_old_protected:Nnn \ior_get_str:NN { \ior_str_get:NN } { 2018-03-05 } -\__kernel_deprecation_error:Nnn \ior_list_streams: - { \ior_show_list: } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \ior_log_streams: - { \ior_log_list: } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \luatex_if_engine_p: +\@@_old:Nnn \luatex_if_engine_p: { \sys_if_engine_luatex_p: } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \luatex_if_engine:F +\@@_old:Nnn \luatex_if_engine:F { \sys_if_engine_luatex:F } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \luatex_if_engine:T +\@@_old:Nnn \luatex_if_engine:T { \sys_if_engine_luatex:T } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \luatex_if_engine:TF +\@@_old:Nnn \luatex_if_engine:TF { \sys_if_engine_luatex:TF } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \pdftex_if_engine_p: +\@@_old:Nnn \pdftex_if_engine_p: { \sys_if_engine_pdftex_p: } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \pdftex_if_engine:F +\@@_old:Nnn \pdftex_if_engine:F { \sys_if_engine_pdftex:F } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \pdftex_if_engine:T +\@@_old:Nnn \pdftex_if_engine:T { \sys_if_engine_pdftex:T } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \pdftex_if_engine:TF +\@@_old:Nnn \pdftex_if_engine:TF { \sys_if_engine_pdftex:TF } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \prop_get:cn +\@@_old:Nnn \prop_get:cn { \prop_item:cn } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \prop_get:Nn +\@@_old:Nnn \prop_get:Nn { \prop_item:Nn } { 2016-01-05 } -\__kernel_deprecation_error:Nnn \quark_if_recursion_tail_break:N +\@@_old:Nnn \quark_if_recursion_tail_break:N { } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \quark_if_recursion_tail_break:n +\@@_old:Nnn \quark_if_recursion_tail_break:n { } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \scan_align_safe_stop: +\@@_old:Nnn \scan_align_safe_stop: { protected~commands } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \sort_ordered: - { \sort_return_same: } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \sort_reversed: - { \sort_return_swapped: } { 2018-12-27 } -\__kernel_deprecation_error:Nnn \str_case:nnn +\@@_old:Nnn \str_case:nnn { \str_case:nnF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \str_case:onn +\@@_old:Nnn \str_case:onn { \str_case:onF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \str_case_x:nnn +\@@_old:Nnn \str_case_x:nnn { \str_case_e:nnF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \tl_case:cnn +\@@_old:Nnn \tl_case:cnn { \tl_case:cnF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \tl_case:Nnn +\@@_old:Nnn \tl_case:Nnn { \tl_case:NnF } { 2015-07-14 } -\__kernel_deprecation_error:Nnn \tl_to_lowercase:n +\@@_old_protected:Nnn \tl_to_lowercase:n { \tex_lowercase:D } { 2018-03-05 } -\__kernel_deprecation_error:Nnn \tl_to_uppercase:n +\@@_old_protected:Nnn \tl_to_uppercase:n { \tex_uppercase:D } { 2018-03-05 } -\__kernel_deprecation_error:Nnn \token_new:Nn - { \cs_new_eq:NN } { 2018-12-29 } -\__kernel_deprecation_error:Nnn \xetex_if_engine_p: +\@@_old:Nnn \xetex_if_engine_p: { \sys_if_engine_xetex_p: } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \xetex_if_engine:F +\@@_old:Nnn \xetex_if_engine:F { \sys_if_engine_xetex:F } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \xetex_if_engine:T +\@@_old:Nnn \xetex_if_engine:T { \sys_if_engine_xetex:T } { 2017-01-01 } -\__kernel_deprecation_error:Nnn \xetex_if_engine:TF +\@@_old:Nnn \xetex_if_engine:TF { \sys_if_engine_xetex:TF } { 2017-01-01 } % \end{macrocode} % \end{macro} % -% \begin{macro}[deprecated = 2019-12-31]{\etex_beginL:D} +% \subsection{Deprecated primitives} +% +% \begin{macro}[deprecated = 2020-07-01]{\etex_beginL:D} % \begin{macro}{\@@_primitive:NN, \@@_primitive:w} % We renamed all primitives to \cs[no-index]{tex_\ldots{}:D} so all % others are deprecated. In \pkg{l3names}, \cs{__kernel_primitives:} @@ -229,7 +492,7 @@ \@@_primitive:w { \cs_to_str:N #2 } } } - { 2019-12-31 } + { 2020-01-01 } } \__kernel_primitives: } @@ -244,15 +507,560 @@ { \tex_let:D #2 #1 \cs_if_exist:cT { tex_ \cs_to_str:N #1 :D } + { \cs_set_eq:Nc #2 { tex_ \cs_to_str:N #1 :D } } + } + \__kernel_primitives: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3box} functions} +% +% \begin{macro}[deprecated = 2019-07-01] +% {\box_resize:Nnn, \box_resize:cnn, \box_use_clear:N, \box_use_clear:c} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn + { 2019-01-01 } { \box_resize_to_wd_and_ht_plus_dp:Nnn } +\cs_new_protected:Npn \box_resize:Nnn + { \box_resize_to_wd_and_ht_plus_dp:Nnn } +\__kernel_patch_deprecation:nnNNpn + { 2019-01-01 } { \box_resize_to_wd_and_ht_plus_dp:cnn } +\cs_new_protected:Npn \box_resize:cnn + { \box_resize_to_wd_and_ht_plus_dp:cnn } +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \box_use_drop:N } +\cs_new_protected:Npn \box_use_clear:N { \box_use_drop:N } +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \box_use_drop:c } +\cs_new_protected:Npn \box_use_clear:c { \box_use_drop:c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[deprecated = 2021-07-01] +% { +% \box_set_eq_clear:NN, \box_set_eq_clear:cN, +% \box_set_eq_clear:Nc, \box_set_eq_clear:cc +% } +% \begin{macro}[deprecated = 2021-07-01] +% { +% \box_gset_eq_clear:NN, \box_gset_eq_clear:cN, +% \box_gset_eq_clear:Nc, \box_gset_eq_clear:cc +% } +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \box_set_eq_drop:N } +\cs_new_protected:Npn \box_set_eq_clear:NN #1#2 + { \tex_setbox:D #1 \tex_box:D #2 } +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \box_gset_eq_drop:N } +\cs_new_protected:Npn \box_gset_eq_clear:NN #1#2 + { \tex_global:D \tex_setbox:D #1 \tex_box:D #2 } +\cs_generate_variant:Nn \box_set_eq_clear:NN { c , Nc , cc } +\cs_generate_variant:Nn \box_gset_eq_clear:NN { c , Nc , cc } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[deprecated = 2021-07-01]{\hbox_unpack_clear:N, \hbox_unpack_clear:c} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \hbox_unpack_drop:N } +\cs_new_protected:Npn \hbox_unpack_clear:N + { \hbox_unpack_drop:N } +\cs_generate_variant:Nn \hbox_unpack_clear:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[deprecated = 2021-07-01]{\vbox_unpack_clear:N, \vbox_unpack_clear:c} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \vbox_unpack_drop:N } +\cs_new_protected:Npn \vbox_unpack_clear:N + { \vbox_unpack_drop:N } +\cs_generate_variant:Nn \vbox_unpack_clear:N { c } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3file} functions} +% +% \begin{macrocode} +%<@@=deprecation> +% \end{macrocode} +% +% \begin{variable}[deprecated = 2019-07-01]{\g_file_current_name_tl} +% Contrarily to most other deprecated commands this is a token list so +% we have to resort to lower-level code. +% +% so we need to put code by hand in two token lists. We use +% \cs{tex_def:D} directly because \cs{g_file_current_name_tl} is made +% outer by \cs{debug_on:n} \texttt{\{deprecation\}}. +% \begin{macrocode} +\__kernel_deprecation_code:nn + { + \tex_let:D \g_file_current_name_tl \scan_stop: + \__kernel_deprecation_error:Nnn \g_file_current_name_tl + { \g_file_curr_name_str } { 2019-01-01 } + } + { + \tex_let:D \g_file_current_name_tl \scan_stop: + \cs_set_nopar:Npn \g_file_current_name_tl { \g_file_curr_name_str } + } +\@@_not_yet_deprecated:nTF { 2019-01-01 } + { + \tl_new:N \g_file_current_name_tl + \tl_gset:Nn \g_file_current_name_tl { \g_file_curr_name_str } + } + { + \cs_gset_nopar:Npn \g_file_current_name_tl + { + \__kernel_msg_expandable_error:nnnnn + { kernel } { deprecated-command } + { 2019-01-01 } { \g_file_current_name_tl } { \g_file_curr_name_str } + } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macrocode} +%<@@=file> +% \end{macrocode} +% +% \begin{macro}[deprecated = 2019-07-01]{\file_path_include:n, \file_path_remove:n} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn + { 2019-01-01 } { \seq_put_right:Nn \l_file_search_path_seq } +\cs_new_protected:Npn \file_path_include:n #1 + { + \__kernel_file_name_sanitize:nN {#1} \l_@@_full_name_str + \seq_if_in:NVF \l_file_search_path_seq \l_@@_full_name_str + { \seq_put_right:NV \l_file_search_path_seq \l_@@_full_name_str } + } +\__kernel_patch_deprecation:nnNNpn + { 2019-01-01 } { \seq_remove_all:Nn \l_file_search_path_seq } +\cs_new_protected:Npn \file_path_remove:n #1 + { + \__kernel_file_name_sanitize:nN {#1} \l_@@_full_name_str + \seq_remove_all:NV \l_file_search_path_seq \l_@@_full_name_str + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[deprecated = 2019-07-01]{\file_add_path:nN} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \file_get_full_name:nN } +\cs_new_protected:Npn \file_add_path:nN #1#2 + { + \file_get_full_name:nN {#1} #2 + \str_if_empty:NT #2 + { \tl_set:Nn #2 { \q_no_value } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[deprecated = 2019-07-01]{\file_list:} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \file_log_list: } +\cs_new_protected:Npn \file_list: { \file_log_list: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[added = 2014-08-22, updated = 2015-08-01, deprecated = 2019-07-01] +% {\ior_list_streams:, \ior_log_streams:, \iow_list_streams:, \iow_log_streams:} +% These got a more consistent naming. +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \ior_show_list: } +\cs_new_protected:Npn \ior_list_streams: { \ior_show_list: } +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \ior_log_list: } +\cs_new_protected:Npn \ior_log_streams: { \ior_log_list: } +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \iow_show_list: } +\cs_new_protected:Npn \iow_list_streams: { \iow_show_list: } +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \iow_log_list: } +\cs_new_protected:Npn \iow_log_streams: { \iow_log_list: } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3int} functions} +% +% \begin{macrocode} +%<@@=deprecation> +% \end{macrocode} +% +% \begin{variable}[deprecated = 2019-07-01]{\c_minus_one, \c_@@_minus_one} +% In order to toggle definitions on and off locally we declare an +% internal constant integer and copy it into \cs{c_minus_one}. +% \begin{macrocode} +\int_const:Nn \c_@@_minus_one { -1 } +\__kernel_deprecation_code:nn + { + \tex_let:D \c_minus_one \scan_stop: + \__kernel_deprecation_error:Nnn \c_minus_one { -1 } { 2019-01-01 } + } + { + \tex_let:D \c_minus_one \scan_stop: + \cs_set_eq:NN \c_minus_one \c_@@_minus_one + } +\@@_not_yet_deprecated:nTF { 2019-01-01 } + { \cs_new_eq:NN \c_minus_one \c_@@_minus_one } + { + \cs_gset_nopar:Npn \c_minus_one + { + \__kernel_msg_expandable_error:nnnnn + { kernel } { deprecated-command } + { 2019-01-01 } { \c_minus_one } { -1 } + \c_@@_minus_one + } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macrocode} +%<@@=int> +% \end{macrocode} +% +% \begin{variable}[deprecated = 2020-07-01] +% { +% \c_zero, \c_one, \c_two, \c_three, \c_four, \c_five, \c_six, +% \c_seven, \c_eight, \c_nine, \c_ten, \c_eleven, \c_twelve, +% \c_thirteen, \c_fourteen, \c_fifteen, \c_sixteen, \c_thirty_two, +% \c_one_hundred, \c_two_hundred_fifty_five, +% \c_two_hundred_fifty_six, \c_one_thousand, \c_ten_thousand, +% } +% \begin{macro}{\@@_deprecated_constants:nn} +% Constants that are now deprecated. By default define them with +% \cs{int_const:Nn}. To deprecate them call for instance +% \cs{__kernel_deprecation_error:Nnn} \cs{c_zero} |{0}| +% |{2020-01-01}|. To redefine them (locally), use +% \cs{@@_constdef:Nw}, with an \cs{exp_not:N} construction because the +% constants themselves are outer at that point. +% \begin{macrocode} +\cs_new_protected:Npn \@@_deprecated_constants:nn #1#2 + { + #1 \c_zero { 0 } #2 + #1 \c_one { 1 } #2 + #1 \c_two { 2 } #2 + #1 \c_three { 3 } #2 + #1 \c_four { 4 } #2 + #1 \c_five { 5 } #2 + #1 \c_six { 6 } #2 + #1 \c_seven { 7 } #2 + #1 \c_eight { 8 } #2 + #1 \c_nine { 9 } #2 + #1 \c_ten { 10 } #2 + #1 \c_eleven { 11 } #2 + #1 \c_twelve { 12 } #2 + #1 \c_thirteen { 13 } #2 + #1 \c_fourteen { 14 } #2 + #1 \c_fifteen { 15 } #2 + #1 \c_sixteen { 16 } #2 + #1 \c_thirty_two { 32 } #2 + #1 \c_one_hundred { 100 } #2 + #1 \c_two_hundred_fifty_five { 255 } #2 + #1 \c_two_hundred_fifty_six { 256 } #2 + #1 \c_one_thousand { 1000 } #2 + #1 \c_ten_thousand { 10000 } #2 + } +\@@_deprecated_constants:nn { \int_const:Nn } { } +\__kernel_deprecation_code:nn + { + \@@_deprecated_constants:nn + { \exp_after:wN \__kernel_deprecation_error:Nnn \exp_not:N } + { { 2020-01-01 } } + } + { + \@@_deprecated_constants:nn + { + \exp_after:wN \use:nnn + \exp_after:wN \@@_constdef:Nw \exp_not:N + } + { \exp_stop_f: } + } +% \end{macrocode} +% \end{macro} +% \end{variable} +% +% \begin{macro}[deprecated = 2020-07-01]{\@@_value:w} +% Made public. +% \begin{macrocode} +\cs_new_eq:NN \@@_value:w \int_value:w +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3luatex} functions} +% +% \begin{macrocode} +%<@@=lua> +% \end{macrocode} +% +% \begin{macro}[EXP, deprecated = 2020-07-01]{\lua_now_x:n, \lua_escape_x:n} +% \begin{macro}[deprecated = 2020-07-01]{\lua_shipout_x:n} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \lua_now:e } +\cs_new:Npn \lua_now_x:n #1 { \@@_now:n {#1} } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \lua_escape:e } +\cs_new:Npn \lua_escape_x:n #1 { \@@_escape:n {#1} } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \lua_shipout_e:n } +\cs_new_protected:Npn \lua_shipout_x:n #1 { \@@_shipout:n {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3msg} functions} +% +% \begin{macrocode} +%<@@=msg> +% \end{macrocode} +% +% \begin{macro}[deprecated = 2020-07-01]{\msg_log:n, \msg_term:n} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \iow_log:n } +\cs_new_protected:Npn \msg_log:n #1 + { + \iow_log:n { ................................................. } + \iow_wrap:nnnN { . ~ #1} { . ~ } { } \iow_log:n + \iow_log:n { ................................................. } + } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \iow_term:n } +\cs_new_protected:Npn \msg_term:n #1 + { + \iow_term:n { ************************************************* } + \iow_wrap:nnnN { * ~ #1} { * ~ } { } \iow_term:n + \iow_term:n { ************************************************* } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[deprecated = 2020-07-01]{\msg_interrupt:nnn} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { [Defined~error~message] } +\cs_new_protected:Npn \msg_interrupt:nnn #1#2#3 + { + \tl_if_empty:nTF {#3} + { + \@@_old_interrupt_wrap:nn { \\ \c_@@_no_info_text_tl } + {#1 \\\\ #2 \\\\ \c_@@_continue_text_tl } + } + { + \@@_old_interrupt_wrap:nn { \\ #3 } + {#1 \\\\ #2 \\\\ \c_@@_help_text_tl } + } + } +\cs_new_protected:Npn \@@_old_interrupt_wrap:nn #1#2 + { + \iow_wrap:nnnN {#1} { | ~ } { } \@@_old_interrupt_more_text:n + \iow_wrap:nnnN {#2} { ! ~ } { } \@@_old_interrupt_text:n + } +\cs_new_protected:Npn \@@_old_interrupt_more_text:n #1 + { + \exp_args:Nx \tex_errhelp:D + { + |''''''''''''''''''''''''''''''''''''''''''''''' + #1 \iow_newline: + |............................................... + } + } +\group_begin: + \char_set_lccode:nn {`\{} {`\ } + \char_set_lccode:nn {`\}} {`\ } + \char_set_lccode:nn {`\&} {`\!} + \char_set_catcode_active:N \& +\tex_lowercase:D + { + \group_end: + \cs_new_protected:Npn \@@_old_interrupt_text:n #1 + { + \iow_term:x { - \exp_args:NNc \cs_set_eq:NN #2 - { tex_ \cs_to_str:N #1 :D } + \iow_newline: + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + \iow_newline: + ! + } + \__kernel_iow_with:Nnn \tex_newlinechar:D { `\^^J } + { + \__kernel_iow_with:Nnn \tex_errorcontextlines:D { -1 } + { + \group_begin: + \cs_set_protected:Npn & + { + \tex_errmessage:D + { + #1 + \use_none:n + { ............................................ } + } + } + \exp_after:wN + \group_end: + & + } } } - \__kernel_primitives: } % \end{macrocode} % \end{macro} +% +% \subsection{Deprecated \pkg{l3prg} functions} +% +% \begin{macrocode} +%<@@=prg> +% \end{macrocode} +% +% \begin{macro}[deprecated = 2020-07-01] +% { +% \@@_break_point:Nn, +% \@@_break_point:, +% \@@_map_break:Nn, +% \@@_break:, +% \@@_break:n +% } +% Made public, but used by a few third-parties. It's not possible to +% perfectly support a mixture of \cs{@@_map_break:Nn} and +% \cs{prg_map_break:Nn} because they use different delimiters. The +% following code only breaks if someone tries to break from two +% \enquote{old-style} \cs{@@_map_break:Nn} \ldots{} +% \cs{@@_break_point:Nn} mappings in one go. Basically, the +% \cs{@@_map_break:Nn} converts a single \cs{@@_break_point:Nn} to +% \cs{prg_break_point:Nn}, and that delimiter had better be the right +% one. Then we call \cs{prg_map_break:Nn} which may end up breaking +% intermediate looks in the (unbraced) argument |#1|. It is essential +% to define the |break_point| functions before the corresponding +% |break| functions: otherwise \cs{debug_on:n} |{deprecation}| +% \cs{debug_off:n} |{deprecation}| would break when trying to restore +% the definitions because they would involve deprecated commands whose +% definition has not yet been restored. +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \prg_break_point:Nn } +\cs_new:Npn \@@_break_point:Nn { \prg_break_point:Nn } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \prg_break_point: } +\cs_new:Npn \@@_break_point: { \prg_break_point: } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \prg_map_break:Nn } +\cs_new:Npn \@@_map_break:Nn #1 \@@_break_point:Nn + { \prg_map_break:Nn #1 \prg_break_point:Nn } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \prg_break: } +\cs_new:Npn \@@_break: #1 \@@_break_point: { } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \prg_break:n } +\cs_new:Npn \@@_break:n #1#2 \@@_break_point: {#1} +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3sort} functions} +% +% \begin{macro}[deprecated = 2019-07-01]{\sort_ordered:, \sort_reversed:} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \sort_return_same: } +\cs_new_protected:Npn \sort_ordered: { \sort_return_same: } +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \sort_return_swapped: } +\cs_new_protected:Npn \sort_reversed: { \sort_return_swapped: } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3str} functions} +% +% \begin{macro}[EXP, deprecated = 2020-07-01, noTF]{\str_case_x:nn} +% \begin{macro}[EXP, deprecated = 2020-07-01, pTF]{\str_if_eq_x:nn} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_case_e:nn } +\cs_new:Npn \str_case_x:nn { \str_case_e:nn } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_case_e:nnT } +\cs_new:Npn \str_case_x:nnT { \str_case_e:nnT } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_case_e:nnF } +\cs_new:Npn \str_case_x:nnF { \str_case_e:nnF } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_case_e:nnTF } +\cs_new:Npn \str_case_x:nnTF { \str_case_e:nnTF } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_if_eq_p:ee } +\cs_new:Npn \str_if_eq_x_p:nn { \str_if_eq_p:ee } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_if_eq:eeT } +\cs_new:Npn \str_if_eq_x:nnT { \str_if_eq:eeT } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_if_eq:eeF } +\cs_new:Npn \str_if_eq_x:nnF { \str_if_eq:eeF } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \str_if_eq:eeTF } +\cs_new:Npn \str_if_eq_x:nnTF { \str_if_eq:eeTF } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsubsection{Deprecated \pkg{l3tl} functions} +% +% \begin{macrocode} +%<@@=tl> +% \end{macrocode} +% +% \begin{macro}[deprecated = 2021-07-01] +% { +% \tl_set_from_file:Nnn, \tl_set_from_file:cnn, +% \tl_gset_from_file:Nnn, \tl_gset_from_file:cnn, +% \tl_set_from_file_x:Nnn, \tl_set_from_file_x:cnn, +% \tl_gset_from_file_x:Nnn, \tl_gset_from_file_x:cnn +% } +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \file_get:nnN } +\cs_new_protected:Npn \tl_set_from_file:Nnn #1#2#3 + { \file_get:nnN {#3} {#2} #1 } +\cs_generate_variant:Nn \tl_set_from_file:Nnn { c } +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \file_get:nnN } +\cs_new_protected:Npn \tl_gset_from_file:Nnn #1#2#3 + { + \group_begin: + \file_get:nnN {#3} {#2} \l_@@_internal_a_tl + \tl_gset_eq:NN #1 \l_@@_internal_a_tl + \group_end: + } +\cs_generate_variant:Nn \tl_gset_from_file:Nnn { c } +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \file_get:nnN } +\cs_new_protected:Npn \tl_set_from_file_x:Nnn #1#2#3 + { + \group_begin: + \file_get:nnN {#3} {#2} \l_@@_internal_a_tl + #2 \scan_stop: + \tl_set:Nx \l_@@_internal_a_tl { \l_@@_internal_a_tl } + \exp_args:NNNo \group_end: + \tl_set:Nn #1 \l_@@_internal_a_tl + } +\cs_generate_variant:Nn \tl_set_from_file_x:Nnn { c } +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \file_get:nnN } +\cs_new_protected:Npn \tl_gset_from_file_x:Nnn #1#2#3 + { + \group_begin: + \file_get:nnN {#3} {#2} \l_@@_internal_a_tl + #2 \scan_stop: + \tl_gset:Nx #1 { \l_@@_internal_a_tl } + \group_end: + } +\cs_generate_variant:Nn \tl_gset_from_file_x:Nnn { c } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3tl-analysis} functions} +% +% \begin{macro}[deprecated = 2020-07-01] +% {\tl_show_analysis:N, \tl_show_analysis:n} +% Simple renames. +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \tl_analysis_show:N } +\cs_new_protected:Npn \tl_show_analysis:N { \tl_analysis_show:N } +\__kernel_patch_deprecation:nnNNpn { 2020-01-01 } { \tl_analysis_show:n } +\cs_new_protected:Npn \tl_show_analysis:n { \tl_analysis_show:n } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated \pkg{l3token} functions} +% +% \begin{macro}[deprecated = 2019-07-01]{\token_new:Nn} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2019-01-01 } { \cs_new_eq:NN } +\cs_new_protected:Npn \token_new:Nn #1#2 { \cs_new_eq:NN #1 #2 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP, deprecated = 2021-07-01] +% { +% \token_get_prefix_spec:N, +% \token_get_arg_spec:N, +% \token_get_replacement_spec:N +% } +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \cs_prefix_spec:N } +\cs_new:Npn \token_get_prefix_spec:N { \cs_prefix_spec:N } +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \cs_argument_spec:N } +\cs_new:Npn \token_get_arg_spec:N { \cs_argument_spec:N } +\__kernel_patch_deprecation:nnNNpn { 2021-01-01 } { \cs_replacement_spec:N } +\cs_new:Npn \token_get_replacement_spec:N { \cs_replacement_spec:N } +% \end{macrocode} % \end{macro} % % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx index 8cc7655d4dd..e6fdc679742 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx @@ -79,7 +79,7 @@ and all files in that bundle must be distributed together. % % \title{The \cls{l3doc} class} % \author{\Team} -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % \maketitle % \tableofcontents % @@ -334,6 +334,17 @@ and all files in that bundle must be distributed together. % class names, respectively. % \end{function} % +% \begin{function}{\NB, \NOTE} +% \begin{syntax} +% \cs{NB} \marg{tag} \marg{comments} +% \verb|\begin{NOTE}| \marg{tag} +% \qquad\meta{comments} +% \verb|\end{NOTE}| +% \end{syntax} +% Make notes in the source that are not typeset by default. When the \verb|show-notes| +% class option is active, the comments are typeset in a detokenized and verbatim mode, respectively. +% \end{function} +% % \subsection{Describing functions in the documentation} % % \DescribeEnv{function} @@ -694,6 +705,7 @@ and all files in that bundle must be distributed together. % \g_@@_checkfunc_bool, % \g_@@_checktest_bool, % \g_@@_cs_break_bool, +% \g_@@_show_notes_bool, % \g_@@_kernel_bool % } % Information about package options. @@ -703,6 +715,7 @@ and all files in that bundle must be distributed together. \bool_new:N \g_@@_checktest_bool \bool_new:N \g_@@_kernel_bool \bool_new:N \g_@@_cs_break_bool +\bool_new:N \g_@@_show_notes_bool \bool_gset_true:N \g_@@_cs_break_bool % \end{macrocode} % \end{variable} @@ -1430,6 +1443,13 @@ and all files in that bundle must be distributed together. % \end{macrocode} % % \begin{macrocode} +\DeclareOption { show-notes } + { \bool_gset_true:N \g_@@_show_notes_bool } +\DeclareOption { hide-notes } + { \bool_gset_false:N \g_@@_show_notes_bool } +% \end{macrocode} +% +% \begin{macrocode} \DeclareOption* { \PassOptionsToClass { \CurrentOption } { article } } \ExecuteOptions { full, kernel, nocheck, nochecktest, lm-default } \PassOptionsToClass { a4paper } { article } @@ -1885,6 +1905,7 @@ and all files in that bundle must be distributed together. \NewDocumentCommand { \CodedocExplainEXP } { } { \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{expstar}{}}% + \write \@auxout { \def \string \Codedoc@expstar { } } \@@_typeset_exp:\ indicates~fully~expandable~functions,~which~ can~be~used~within~an~\texttt{x}-type~argument~(in~plain~ \TeX{}~terms,~inside~an~\cs{edef}),~as~well~as~within~an~ @@ -1893,6 +1914,7 @@ and all files in that bundle must be distributed together. \NewDocumentCommand { \CodedocExplainREXP } { } { \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{rexpstar}{}}% + \write \@auxout { \def \string \Codedoc@rexpstar { } } \@@_typeset_rexp:\ indicates~ restricted~expandable~functions,~which~can~be~used~within~an~ \texttt{x}-type~argument~but~cannot~be~fully~expanded~within~an~ @@ -1901,6 +1923,7 @@ and all files in that bundle must be distributed together. \NewDocumentCommand { \CodedocExplainTF } { } { \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{explTF}{}}% + \write \@auxout { \def \string \Codedoc@explTF { } } \@@_typeset_TF:\ indicates~conditional~(\texttt{if})~functions~ whose~variants~with~\texttt{T},~\texttt{F}~and~\texttt{TF}~ argument~specifiers~expect~different~ @@ -2062,18 +2085,30 @@ and all files in that bundle must be distributed together. % to typeset conditionals and auxiliary functions. % \begin{macrocode} \cs_new_protected:Npn \@@_typeset_exp: - { \hyperlink{expstar} {$\star$} } + { + \cs_if_exist:NTF \Codedoc@expstar + { \hyperlink { expstar } } + { \mbox } + {$\star$} + } \cs_new_protected:Npn \@@_typeset_rexp: - { \hyperlink{rexpstar} {\ding{73}} } % hollow star + { + \cs_if_exist:NTF \Codedoc@rexpstar + { \hyperlink { rexpstar } } + { \mbox } + { \ding { 73 } } % hollow star + } \cs_new_protected:Npn \@@_typeset_TF: { - \hyperlink{explTF} + \cs_if_exist:NTF \Codedoc@explTF + { \hyperlink { explTF } } + { \mbox } { \color{black} \itshape TF \makebox[0pt][r] { - \color{red} + \cs_if_exist:NT \Codedoc@explTF { \color{red} } \underline { \phantom{\itshape TF} \kern-0.1em } } } @@ -2409,7 +2444,7 @@ and all files in that bundle must be distributed together. { \@@_date_set:Nn #1 {#2} \exp_args:No \@@_date_compare:nNnT - {#1} > { \tex_year:D - \tex_month:D - \tex_day:D } + {#1} > { \c_sys_year_int - \c_sys_month_int - \c_sys_day_int } { \msg_error:nnxx { l3doc } { future-date } { \tl_to_str:N \l_@@_macro_argument_tl } @@ -2430,7 +2465,7 @@ and all files in that bundle must be distributed together. { \@@_date_set:Nn \l_@@_tmpa_tl {#1} \exp_args:No \@@_date_compare:nNnT - { \l_@@_tmpa_tl } < { \tex_year:D - \tex_month:D - \tex_day:D } + { \l_@@_tmpa_tl } < { \c_sys_year_int - \c_sys_month_int - \c_sys_day_int } { \msg_error:nnxx { l3doc } { deprecated-function } { \tl_to_str:N \l_@@_macro_argument_tl } @@ -2495,6 +2530,7 @@ and all files in that bundle must be distributed together. \cs_new_protected:Npn \@@_function_typeset_stop: { \par + \dim_set:Nn \prevdepth { \box_dp:N \l_@@_descr_coffin } \allowbreak } % \end{macrocode} @@ -3435,6 +3471,57 @@ and all files in that bundle must be distributed together. % \end{environment} % \end{environment} % +% \subsubsection{NB and NOTE} +% +% These macros are intended for additional notes added to the source that are not typeset. +% +% \begin{macro}{\NB} +% \NB{wspr}{this is what I think about this!} +% \begin{verbatim} +% \NB{wspr}{this is what I think about this!} +% \end{verbatim} +% \begin{macrocode} +\bool_if:NTF \g_@@_show_notes_bool + { + \NewDocumentCommand\NB{mm} + { + (\emph{Note}\footnote{\ttfamily [#1]:~\detokenize{#2}}) + } + } + { + \NewDocumentCommand\NB{mm}{} + } +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{\NOTE} +% \begin{NOTE}{wspr} +% this is what I #$%& think about this! +% \end{NOTE} +% \begin{verbatim} +% \begin{NOTE}{wspr} +% this is what I #$%& think about this! +% \end{NOTE} +% \end{verbatim} +% \begin{macrocode} +\bool_if:NTF \g_@@_show_notes_bool + { + \NewDocumentEnvironment{NOTE}{m} + { + \par\noindent (\emph{Note}~[\texttt{#1}]:\par + \verbatim + } + { + \endverbatim + \par\noindent \emph{Note~end})\par + } + } + { + \NewDocumentEnvironment{NOTE}{m}{\comment}{\endcomment} + } +% \end{macrocode} +% \end{environment} +% % \subsection{Documenting templates} % % \begin{macrocode} @@ -3742,7 +3829,7 @@ and all files in that bundle must be distributed together. \@@_replace_at_at:N \l_@@_tmpa_tl \tl_gset:Nn \g_@@_module_name_tl {#2} - \tl_put_right:Nn \l_@@_tmpa_tl { < @ @ = #2 > } + \tl_put_right:Nn \l_@@_tmpa_tl { < \text { \verbatim@font @ @ = #2 } > } \tl_set:Nn \l_@@_tmpb_tl {#3} \@@_detect_internals:N \l_@@_tmpb_tl diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx index cdb9ece1da4..4ba471a549c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx index 05df8c01b28..33fa348aad9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -556,23 +556,23 @@ %<*package> \ProvidesExplFile %<*dvipdfmx> - {l3dvipdfmx.def}{2019-02-15}{} + {l3dvipdfmx.def}{2019-03-05}{} {L3 Experimental driver: dvipdfmx} %</dvipdfmx> %<*dvips> - {l3dvips.def}{2019-02-15}{} + {l3dvips.def}{2019-03-05}{} {L3 Experimental driver: dvips} %</dvips> %<*dvisvgm> - {l3dvisvgm.def}{2019-02-15}{} + {l3dvisvgm.def}{2019-03-05}{} {L3 Experimental driver: dvisvgm} %</dvisvgm> %<*pdfmode> - {l3pdfmode.def}{2019-02-15}{} + {l3pdfmode.def}{2019-03-05}{} {L3 Experimental driver: PDF mode} %</pdfmode> %<*xdvipdfmx> - {l3xdvipdfmx.def}{2019-02-15}{} + {l3xdvipdfmx.def}{2019-03-05}{} {L3 Experimental driver: xdvipdfmx} %</xdvipdfmx> %</package> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx index dd4d70f59d6..4748bf35aa3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -713,7 +713,7 @@ % \cs{exp_not:o} \Arg{tokens} % \end{syntax} % Expands the \meta{tokens} once, then prevents any further expansion -% in |x|-type arguments using \cs{exp_not:n}. +% in |x|-type or \texttt{e}-type arguments using \cs{exp_not:n}. % \end{function} % % \begin{function}[EXP]{\exp_not:V} @@ -721,7 +721,7 @@ % \cs{exp_not:V} \meta{variable} % \end{syntax} % Recovers the content of the \meta{variable}, then prevents expansion -% of this material in |x|-type arguments using \cs{exp_not:n}. +% of this material in |x|-type or \texttt{e}-type arguments using \cs{exp_not:n}. % \end{function} % % \begin{function}[EXP]{\exp_not:v} @@ -732,7 +732,7 @@ % converts this into a control sequence which should be a \meta{variable} % name. % The content of the \meta{variable} is recovered, and further -% expansion in |x|-type arguments is prevented using \cs{exp_not:n}. +% expansion in |x|-type or \texttt{e}-type arguments is prevented using \cs{exp_not:n}. % \begin{texnote} % Protected macros that appear in a \texttt{v}-type argument are % expanded despite being protected; \cs{exp_not:n} also has no @@ -759,7 +759,7 @@ % Expands \meta{tokens} fully until the first unexpandable token is % found (if it is a space it is removed). Expansion then stops, and % the result of the expansion (including any tokens which were not -% expanded) is protected from further expansion in |x|-type arguments +% expanded) is protected from further expansion in |x|-type or \texttt{e}-type arguments % using \cs{exp_not:n}. % \end{function} % @@ -1783,13 +1783,18 @@ { % \end{macrocode} % -% \begin{macro}[EXP]{\@@_e:nn} +% \begin{macro}[EXP]{\@@_e:nn, \@@_e_end:nn} % Repeatedly expand tokens, keeping track of fully-expanded tokens in % the second argument to \cs{@@_e:nn}; this function eventually % calls \cs{@@_e_end:nn} to leave \cs{exp_end:} in the input % stream, followed by the result of the expansion. There are many % special cases: spaces, brace groups, \tn{noexpand}, \tn{unexpanded}, % \tn{the}, \tn{primitive}. +% While we use brace tricks \cs{if_false:} |{| \cs{fi:}, the expansion +% of this function is always triggered by \cs{exp:w} so brace balance +% is eventually restored after that is hit with a single step of +% expansion. Otherwise we could not nest \texttt{e}-type expansions +% within each other. % \begin{macrocode} \cs_new:Npn \@@_e:nn #1 { @@ -1844,7 +1849,8 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_e:N} +% \begin{macro}[EXP] +% {\@@_e:N, \@@_e:Nnn, \@@_e_protected:Nnn, \@@_e_expandable:Nnn} % For an \texttt{N}-type token, call \cs{@@_e:Nnn} with arguments the % \meta{first token}, the remaining tokens to expand and what's % already been expanded. If the \meta{first token} is non-expandable, @@ -1887,14 +1893,74 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_e_primitive:Nnn} -% Quite rare. Will be implemented later. +% \begin{macro}[EXP] +% { +% \@@_e_primitive:Nnn, +% \@@_e_primitive_aux:NNw, +% \@@_e_primitive_aux:NNnn, +% \@@_e_primitive_other:NNnn, +% \@@_e_primitive_other_aux:nNNnn +% } +% We don't try hard to make sensible error recovery since the error +% recovery of \cs{tex_primitive:D} when followed by something else +% than a primitive depends on the engine. The only valid case is when +% what follows is \texttt{N}-type. Then distinguish special +% primitives \tn{unexpanded}, \tn{noexpand}, \tn{the}, \tn{primitive} +% from other primitives. In the \enquote{other} case, the only +% reasonable way to check if the primitive that follows +% \cs{tex_primitive:D} is expandable is to expand and compare the +% before-expansion and after-expansion results. If they coincide then +% probably the primitive is non-expandable and should be put in the +% output together with \cs{tex_primitive:D} (one can cook up contrived +% counter-examples where the true \tn{expanded} would have an infinite +% loop), and otherwise one should continue expanding. % \begin{macrocode} - \cs_new:Npn \@@_e_primitive:Nnn #1 + \cs_new:Npn \@@_e_primitive:Nnn #1#2 { - \__kernel_msg_expandable_error:nnn { kernel } { e-type } - { \primitive not~implemented } - \@@_e:nn + \if_false: { \fi: + \tl_if_head_is_N_type:nTF {#2} + { \@@_e_primitive_aux:NNw #1 } + { + \__kernel_msg_expandable_error:nnn { kernel } { e-type } + { Missing~primitive~name } + \@@_e_primitive_aux:NNw #1 \c_empty_tl + } + #2 + } + } + \cs_new:Npn \@@_e_primitive_aux:NNw #1#2 + { + \exp_after:wN \@@_e_primitive_aux:NNnn + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN { \if_false: } \fi: + } + \cs_new:Npn \@@_e_primitive_aux:NNnn #1#2 + { + \exp_args:Nf \str_case_e:nnTF { \cs_to_str:N #2 } + { + { unexpanded } { \@@_e_unexpanded:Nnn \exp_not:n } + { noexpand } { \@@_e_noexpand:Nnn \exp_not:N } + { the } { \@@_e_the:Nnn \tex_the:D } + { + \sys_if_engine_xetex:T { pdf } + \sys_if_engine_luatex:T { pdf } + primitive + } { \@@_e_primitive:Nnn #1 } + } + { \@@_e_primitive_other:NNnn #1 #2 } + } + \cs_new:Npn \@@_e_primitive_other:NNnn #1#2#3 + { + \exp_args:No \@@_e_primitive_other_aux:nNNnn + { #1 #2 #3 } + #1 #2 {#3} + } + \cs_new:Npn \@@_e_primitive_other_aux:nNNnn #1#2#3#4#5 + { + \str_if_eq:nnTF {#1} { #2 #3 #4 } + { \@@_e:nn {#4} { #5 #2 #3 } } + { \@@_e:nn {#1} {#5} } } % \end{macrocode} % \end{macro} @@ -1937,10 +2003,10 @@ % braces), unless that \meta{token} is \cs{scan_stop:} or a space % (recall that we don't implement the case of an implicit begin-group % token). An expandable \meta{token} is instead expanded, unless it -% is \tn{noexpand}. That primitive can be followed by an expandable -% \texttt{N}-type token, to be removed, by a non-expandable one, kept -% (and later causing an error), by a space, removed by -% \texttt{f}-expansion, or by a brace group or nothing (later causing +% is \tn{noexpand}. The latter primitive can be followed by an expandable +% \texttt{N}-type token (removed), by a non-expandable one (kept +% and later causing an error), by a space (removed by +% \texttt{f}-expansion), or by a brace group or nothing (later causing % an error). % \begin{macrocode} \cs_new:Npn \@@_e_unexpanded:Nnn #1 { \@@_e_unexpanded:nn } @@ -2098,20 +2164,41 @@ { #1 \exp_after:wN \@@_e_the_toks:n + \exp_after:wN { \if_false: } \fi: + } + { + \exp_after:wN ; + \exp_after:wN { \if_false: } \fi: #1 } - { \exp_after:wN ; } - \exp_after:wN { \if_false: } \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[EXP]{\@@_e_if_toks_register:NTF} -% We need to detect both \tn{toks} registers like \tn{toks@} (in -% \LaTeXe{}) and parameters such as \tn{everypar}, as the result of -% unpacking the register should not expand further. The list of -% parameters is finite so we just use a \cs{cs_if_exist:cTF} test to -% look up in a table. Registers are found by -% \cs{token_if_toks_register:NTF} by inspecting the meaning. We abuse +% \begin{macro}[EXP] +% { +% \@@_e_the_XeTeXinterchartoks:, +% \@@_e_the_errhelp:, +% \@@_e_the_everycr:, +% \@@_e_the_everydisplay:, +% \@@_e_the_everyeof:, +% \@@_e_the_everyhbox:, +% \@@_e_the_everyjob:, +% \@@_e_the_everymath:, +% \@@_e_the_everypar:, +% \@@_e_the_everyvbox:, +% \@@_e_the_output:, +% \@@_e_the_pdfpageattr:, +% \@@_e_the_pdfpageresources:, +% \@@_e_the_pdfpagesattr:, +% \@@_e_the_pdfpkmode: +% } +% We need to detect both \tn{toks} registers like \tn{toks@} in +% \LaTeXe{} and parameters such as \tn{everypar}, as the result of +% unpacking the register should not expand further. Registers are +% found by \cs{token_if_toks_register:NTF} by inspecting the meaning. +% The list of parameters is finite so we just use a +% \cs{cs_if_exist:cTF} test to look up in a table. We abuse % \cs{cs_to_str:N}'s ability to remove a leading escape character % whatever it is. % \begin{macrocode} @@ -2145,6 +2232,7 @@ \cs_new_eq:NN \@@_e_the_pdfpkmode: ? % \end{macrocode} % \end{macro} +% \end{macro} % % We are done emulating \texttt{e}-type argument expansion when % \tn{expanded} is unavailable. diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index a8262e75962..f81f3a488b5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -164,9 +164,10 @@ % % \subsection{Reading from files} % -% \begin{function}[added = 2012-06-24]{\ior_get:NN} +% \begin{function}[noTF, added = 2012-06-24, updated = 2019-02-17]{\ior_get:NN} % \begin{syntax} % \cs{ior_get:NN} \meta{stream} \meta{token list variable} +% \cs{ior_get:NNTF} \meta{stream} \meta{token list variable} \meta{true code} \meta{false code} % \end{syntax} % Function that reads one or more lines (until an equal number of left % and right braces are found) from the input \meta{stream} and stores @@ -191,6 +192,8 @@ % \end{verbatim} % Also notice that if multiple lines are read to match braces % then the resulting token list can contain \cs{par} tokens. +% In the non-branching version, where the file is not found the \meta{tl var} +% is set to \cs{q_no_value}. % \begin{texnote} % This protected macro is a wrapper around the \TeX{} primitive % \tn{read}. Regardless of settings, \TeX{} replaces trailing space @@ -203,9 +206,11 @@ % \end{texnote} % \end{function} % -% \begin{function}[added = 2016-12-04]{\ior_str_get:NN} +% \begin{function}[noTF, added = 2016-12-04, updated = 2019-02-17] +% {\ior_str_get:NN} % \begin{syntax} % \cs{ior_str_get:NN} \meta{stream} \meta{token list variable} +% \cs{ior_str_get:NNTF} \meta{stream} \meta{token list variable} \meta{true code} \meta{false code} % \end{syntax} % Function that reads one line from the input \meta{stream} and stores % the result locally in the \meta{token list} variable. If the @@ -223,6 +228,8 @@ % \end{verbatim} % results in a token list |a b c| with the letters |a|, |b|, and |c| % having category code~12. +% In the non-branching version, where the file is not found the \meta{tl var} +% is set to \cs{q_no_value}. % \begin{texnote} % This protected macro is a wrapper around the \eTeX{} primitive % \tn{readline}. Regardless of settings, \TeX{} removes trailing @@ -313,17 +320,17 @@ % \end{texnote} % \end{function} % -%\begin{function}[updated = 2012-02-10, EXP, pTF]{\ior_if_eof:N} -% \begin{syntax} -% \cs{ior_if_eof_p:N} \meta{stream} \\ -% \cs{ior_if_eof:NTF} \meta{stream} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the end of a \meta{stream} has been reached during a reading -% operation. The test also returns a \texttt{true} value if -% the \meta{stream} is not open. -%\end{function} +% \begin{function}[updated = 2012-02-10, EXP, pTF]{\ior_if_eof:N} +% \begin{syntax} +% \cs{ior_if_eof_p:N} \meta{stream} \\ +% \cs{ior_if_eof:NTF} \meta{stream} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the end of a \meta{stream} has been reached during a reading +% operation. The test also returns a \texttt{true} value if +% the \meta{stream} is not open. +% \end{function} % -% \section{Writing to files} +% \subsection{Writing to files} % % \begin{function}[updated = 2012-06-05]{\iow_now:Nn, \iow_now:Nx, \iow_now:cn, \iow_now:cx} % \begin{syntax} @@ -592,8 +599,7 @@ % \cs{l_file_search_path_seq}. % \end{function} % -% \begin{function}[added = 2019-01-16]{\file_get:nnN} -% \begin{function}[TF, added = 2019-01-16]{\file_get:nnN} +% \begin{function}[noTF, added = 2019-01-16, updated = 2019-02-16]{\file_get:nnN} % \begin{syntax} % \cs{file_get:nnN} \Arg{filename} \Arg{setup} \meta{tl} % \cs{file_get:nnNTF} \Arg{filename} \Arg{setup} \meta{tl} \Arg{true code} \Arg{false code} @@ -601,23 +607,25 @@ % Defines \meta{tl} to the contents of \meta{filename}. % Category codes may need to be set appropriately via the \meta{setup} % argument. -% While \cs{file_get:nnN} produces an error if the file is not found, -% \cs{file_get:nnNTF} runs the \meta{true code} (after the assignment -% to \meta{tl}) if the file is found and \meta{false code} otherwise. -% \end{function} +% The non-branching version sets the \meta{tl} to \cs{q_no_value} if the file is +% not found. The branching version runs the \meta{true code} after the +% assignment to \meta{tl} if the file is found, and \meta{false code} +% otherwise. % \end{function} % -% \begin{function}[updated = 2017-06-26] +% \begin{function}[noTF, updated = 2019-02-16] % {\file_get_full_name:nN, \file_get_full_name:VN} % \begin{syntax} -% \cs{file_get_full_name:nN} \Arg{file name} \meta{str var} +% \cs{file_get_full_name:nN} \Arg{file name} \meta{tl} +% \cs{file_get_full_name:nNTF} \Arg{file name} \meta{tl} \Arg{true code} \Arg{false code} % \end{syntax} % Searches for \meta{file name} in the path as detailed for -% \cs{file_if_exist:nTF}, and if found sets the \meta{str var} the +% \cs{file_if_exist:nTF}, and if found sets the \meta{tl var} the % fully-qualified name of the file, \emph{i.e.}~the path and file name. % This includes an extension |.tex| when the given \meta{file name} % has no extension but the file found has that extension. -% If the file is not found then the \meta{str var} is empty. +% In the non-branching version, the \meta{tl var} will be set to +% \cs{q_no_value} in the case that the file does not exist. % \end{function} % % \begin{function}[added = 2017-06-23, updated = 2017-06-26] @@ -782,10 +790,10 @@ % \end{macrocode} % \end{macro} % -% \begin{variable}{\l_@@_file_name_str} +% \begin{variable}{\l_@@_file_name_tl} % Data storage. % \begin{macrocode} -\str_new:N \l_@@_file_name_str +\tl_new:N \l_@@_file_name_tl % \end{macrocode} % \end{variable} % @@ -797,13 +805,12 @@ % \begin{macrocode} \prg_new_protected_conditional:Npnn \ior_open:Nn #1#2 { T , F , TF } { - \file_get_full_name:nN {#2} \l_@@_file_name_str - \str_if_empty:NTF \l_@@_file_name_str - { \prg_return_false: } + \file_get_full_name:nNTF {#2} \l_@@_file_name_tl { - \__kernel_ior_open:No #1 \l_@@_file_name_str + \__kernel_ior_open:No #1 \l_@@_file_name_tl \prg_return_true: } + { \prg_return_false: } } \prg_generate_conditional_variant:Nnn \ior_open:Nn { c } { T , F , TF } % \end{macrocode} @@ -955,19 +962,35 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\ior_get:NN} +% \begin{macro}{\ior_get:NN, \@@_get:NN} +% \begin{macro}[TF]{\ior_get:NN} % And here we read from files. % \begin{macrocode} \cs_new_protected:Npn \ior_get:NN #1#2 + { \ior_get:NNF #1 #2 { \tl_set:Nn #2 { \q_no_value } } } +\cs_new_protected:Npn \@@_get:NN #1#2 { \tex_read:D #1 to #2 } +\prg_new_protected_conditional:Npnn \ior_get:NN #1#2 { T , F , TF } + { + \ior_if_eof:NTF #1 + { \prg_return_false: } + { + \@@_get:NN #1 #2 + \prg_return_true: + } + } % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\ior_str_get:NN} +% \begin{macro}{\ior_str_get:NN, \@@_str_get:NN} +% \begin{macro}[TF]{\ior_str_get:NN} % Reading as strings is a more complicated wrapper, as we wish to % remove the endline character and restore it afterwards. % \begin{macrocode} \cs_new_protected:Npn \ior_str_get:NN #1#2 + { \ior_str_get:NNF #1 #2 { \tl_set:Nn #2 { \q_no_value } } } +\cs_new_protected:Npn \@@_str_get:NN #1#2 { \exp_args:Nno \use:n { @@ -976,8 +999,18 @@ \int_set:Nn \tex_endlinechar:D } { \int_use:N \tex_endlinechar:D } } +\prg_new_protected_conditional:Npnn \ior_str_get:NN #1#2 { T , F , TF } + { + \ior_if_eof:NTF #1 + { \prg_return_false: } + { + \@@_str_get:NN #1 #2 + \prg_return_true: + } + } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}[EXP]{\ior_map_break:, \ior_map_break:n} % Usual map breaking functions. @@ -1001,9 +1034,9 @@ % stream has only one \enquote{current line}. % \begin{macrocode} \cs_new_protected:Npn \ior_map_inline:Nn - { \@@_map_inline:NNn \ior_get:NN } + { \@@_map_inline:NNn \@@_get:NN } \cs_new_protected:Npn \ior_str_map_inline:Nn - { \@@_map_inline:NNn \ior_str_get:NN } + { \@@_map_inline:NNn \@@_str_get:NN } \cs_new_protected:Npn \@@_map_inline:NNn { \int_gincr:N \g__kernel_prg_map_int @@ -1173,10 +1206,10 @@ % \end{macrocode} % \end{macro} % -% \begin{variable}{\l_@@_file_name_str} +% \begin{variable}{\l_@@_file_name_tl} % Data storage. % \begin{macrocode} -\str_new:N \l_@@_file_name_str +\tl_new:N \l_@@_file_name_tl % \end{macrocode} % \end{variable} % @@ -1187,10 +1220,10 @@ % \begin{macrocode} \cs_new_protected:Npn \iow_open:Nn #1#2 { - \__kernel_file_name_sanitize:nN {#2} \l_@@_file_name_str + \__kernel_file_name_sanitize:nN {#2} \l_@@_file_name_tl \iow_close:N #1 \seq_gpop:NNTF \g_@@_streams_seq \l_@@_stream_tl - { \@@_open_stream:NV #1 \l_@@_file_name_str } + { \@@_open_stream:NV #1 \l_@@_file_name_tl } %<*initex> { \__kernel_msg_fatal:nn { kernel } { output-streams-exhausted } } %</initex> @@ -1198,7 +1231,7 @@ { \@@_new:N #1 \tl_set:Nx \l_@@_stream_tl { \int_eval:n {#1} } - \@@_open_stream:NV #1 \l_@@_file_name_str + \@@_open_stream:NV #1 \l_@@_file_name_tl } %</package> } @@ -1332,8 +1365,8 @@ \cs_set_protected:Npn \iow_term:x { \iow_now:Nx \c_term_iow } \cs_new_protected:Npn \iow_term:n { \iow_now:Nn \c_term_iow } % \end{macrocode} -%\end{macro} -%\end{macro} +% \end{macro} +% \end{macro} % % \subsubsection{Special characters for writing} % @@ -2092,11 +2125,11 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_base_name_str, \l_@@_full_name_str} +% \begin{variable}{\l_@@_base_name_tl, \l_@@_full_name_tl} % For storing the basename and full path whilst passing data internally. % \begin{macrocode} -\str_new:N \l_@@_base_name_str -\str_new:N \l_@@_full_name_str +\tl_new:N \l_@@_base_name_tl +\tl_new:N \l_@@_full_name_tl % \end{macrocode} % \end{variable} % @@ -2144,8 +2177,6 @@ \char_set_active_eq:NN ##1 \l_@@_internal_tl } \tl_set:Nx \l_@@_internal_tl {#1} - \tl_set:Nx \l_@@_internal_tl - { \tl_to_str:N \l_@@_internal_tl } \exp_args:NNNV \group_end: \str_set:Nn #2 \l_@@_internal_tl } @@ -2190,19 +2221,18 @@ \cs_new_protected:Npn \file_get:nnN #1#2#3 { \file_get:nnNF {#1} {#2} #3 - { \__kernel_file_missing:n {#1} } + { \tl_set:Nn #3 { \q_no_value } } } \prg_new_protected_conditional:Npnn \file_get:nnN #1#2#3 { T , F , TF } { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str - { \prg_return_false: } + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { \exp_args:NV \@@_get_aux:nnN - \l_@@_full_name_str + \l_@@_full_name_tl {#2} #3 \prg_return_true: } + { \prg_return_false: } } \cs_new_protected:Npn \@@_get_aux:nnN #1#2#3 { @@ -2229,6 +2259,7 @@ % \end{macro} % % \begin{macro}{\file_get_full_name:nN, \file_get_full_name:VN} +% \begin{macro}[TF]{\file_get_full_name:nN, \file_get_full_name:VN} % \begin{macro}{\@@_get_full_name_search:nN} % The way to test if a file exists is to try to open it: if it does % not exist then \TeX{} reports end-of-file. A search is made @@ -2242,7 +2273,13 @@ % \begin{macrocode} \cs_new_protected:Npn \file_get_full_name:nN #1#2 { - \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_str + \file_get_full_name:nNF {#1} #2 + { \tl_set:Nn #2 { \q_no_value } } + } +\cs_generate_variant:Nn \file_get_full_name:nN { V } +\prg_new_protected_conditional:Npnn \file_get_full_name:nN #1#2 { T , F , TF } + { + \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_tl \@@_get_full_name_search:nN { } \use:n \seq_map_inline:Nn \l_file_search_path_seq { \@@_get_full_name_search:nN { ##1 / } \seq_map_break:n } @@ -2253,35 +2290,43 @@ { \@@_get_full_name_search:nN { ##1 } \tl_map_break:n } } %</package> - \str_clear:N \l_@@_full_name_str + \tl_set:Nn \l_@@_full_name_tl { \q_no_value } \prg_break_point: - \str_if_empty:NF \l_@@_full_name_str + \quark_if_no_value:NTF \l_@@_full_name_tl + { + \ior_close:N \g_@@_internal_ior + \prg_return_false: + } { - \exp_args:NV \file_parse_full_name:nNNN \l_@@_full_name_str + \exp_args:NV \file_parse_full_name:nNNN \l_@@_full_name_tl \l_@@_dir_str \l_@@_name_str \l_@@_ext_str \str_if_empty:NT \l_@@_ext_str { \__kernel_ior_open:No \g_@@_internal_ior - { \l_@@_full_name_str .tex } + { \l_@@_full_name_tl .tex } \ior_if_eof:NF \g_@@_internal_ior - { \str_put_right:Nn \l_@@_full_name_str { .tex } } + { \tl_put_right:Nn \l_@@_full_name_tl { .tex } } } + \ior_close:N \g_@@_internal_ior + \tl_set_eq:NN #2 \l_@@_full_name_tl + \prg_return_true: } - \str_set_eq:NN #2 \l_@@_full_name_str - \ior_close:N \g_@@_internal_ior } -\cs_generate_variant:Nn \file_get_full_name:nN { V } +\cs_generate_variant:Nn \file_get_full_name:nNT { V } +\cs_generate_variant:Nn \file_get_full_name:nNF { V } +\cs_generate_variant:Nn \file_get_full_name:nNTF { V } \cs_new_protected:Npn \@@_get_full_name_search:nN #1#2 { \@@_name_quote:nN - { \tl_to_str:n {#1} \l_@@_base_name_str } - \l_@@_full_name_str - \__kernel_ior_open:No \g_@@_internal_ior \l_@@_full_name_str + { \tl_to_str:n {#1} \l_@@_base_name_tl } + \l_@@_full_name_tl + \__kernel_ior_open:No \g_@@_internal_ior \l_@@_full_name_tl \ior_if_eof:NF \g_@@_internal_ior { #2 { \prg_break: } } } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}[TF]{\file_if_exist:n} % The test for the existence of a file is a wrapper around the function to @@ -2291,10 +2336,9 @@ % \begin{macrocode} \prg_new_protected_conditional:Npnn \file_if_exist:n #1 { T , F , TF } { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str - { \prg_return_false: } + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl { \prg_return_true: } + { \prg_return_false: } } % \end{macrocode} % \end{macro} @@ -2304,9 +2348,9 @@ % \begin{macrocode} \cs_new_protected:Npn \__kernel_file_missing:n #1 { - \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_str + \__kernel_file_name_sanitize:nN {#1} \l_@@_base_name_tl \__kernel_msg_error:nnx { kernel } { file-not-found } - { \l_@@_base_name_str } + { \l_@@_base_name_tl } } % \end{macrocode} % \end{macro} @@ -2323,10 +2367,9 @@ % \begin{macrocode} \cs_new_protected:Npn \file_input:n #1 { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str + \file_get_full_name:nNTF {#1} \l_@@_full_name_tl + { \@@_input:V \l_@@_full_name_tl } { \__kernel_file_missing:n {#1} } - { \@@_input:V \l_@@_full_name_str } } \cs_new_protected:Npn \@@_input:n #1 { @@ -2491,6 +2534,75 @@ %</package> % \end{macrocode} % +% \subsection{GetIfInfo} +% +% \begin{macro}{\GetIdInfo} +% \begin{macro}{\@@_id_info_auxi:w, \@@_id_info_auxii:w, \@@_id_info_auxiii:w} +% As documented in \pkg{expl3.dtx} this function extracts file name +% etc from an \textsc{svn} \texttt{Id} line. This used to be how we +% got version number and so on in all modules, so it had to be defined +% in \pkg{l3bootstrap}. Now it's more convenient to define it after +% we have set up quite a lot of tools, and \pkg{l3file} seems the +% least unreasonable place for it. +% +% The idea here is to extract out the information needed from a standard +% \textsc{svn} \texttt{Id} line, but to avoid a line that would get +% changed when the file is checked in. Hence the fact that none of the +% lines here include both a dollar sign and the \texttt{Id} keyword! +% \begin{macrocode} +\cs_new_protected:Npn \GetIdInfo + { + \group_begin: + \char_set_catcode_space:n { 32 } + \exp_after:wN + \group_end: + \@@_id_info_auxi:w + } +% \end{macrocode} +% A first check for a completely empty \textsc{svn} field. If that is +% not the case, there is a second case when a file created using +% \texttt{svn cp} but has not been checked in. That leaves a special +% marker \texttt{-1} version, which has no further data. Dealing +% correctly with that is the reason for the space in the line to use +% \cs{@@_id_info_auxii:w}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_id_info_auxi:w $ #1 $ #2 + { + \tl_set:Nn \ExplFileDescription {#2} + \str_if_eq:nnTF {#1} { Id } + { + \tl_set:Nn \ExplFileDate { 0000/00/00 } + \tl_set:Nn \ExplFileName { [unknown] } + \tl_set:Nn \ExplFileExtension { [unknown~extension] } + \tl_set:Nn \ExplFileVersion {-1} + } + { \@@_id_info_auxii:w #1 ~ \q_stop } + } +% \end{macrocode} +% Here, |#1| is |Id|, |#2| is the file name, |#3| is the extension, +% |#4| is the version, |#5| is the check in date and |#6| is the check +% in time and user, plus some trailing spaces. If |#4| is the marker +% |-1| value then |#5| and |#6| are empty. +% \begin{macrocode} +\cs_new_protected:Npn \@@_id_info_auxii:w + #1 ~ #2.#3 ~ #4 ~ #5 ~ #6 \q_stop + { + \tl_set:Nn \ExplFileName {#2} + \tl_set:Nn \ExplFileExtension {#3} + \tl_set:Nn \ExplFileVersion {#4} + \str_if_eq:nnTF {#4} {-1} + { \tl_set:Nn \ExplFileDate { 0000/00/00 } } + { \@@_id_info_auxiii:w #5 - 0 - 0 - \q_stop } + } +% \end{macrocode} +% Convert an \textsc{svn}-style date into a \LaTeX{}-style one. +% \begin{macrocode} +\cs_new_protected:Npn \@@_id_info_auxiii:w #1 - #2 - #3 - #4 \q_stop + { \tl_set:Nn \ExplFileDate { #1/#2/#3 } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Messages} % % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx index 9c385192b53..5422ccde49d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx index 3c5e3486276..cdff9f98509 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx index 6e726d7f1c6..03d5e78cc8c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx index 1a93847d1ce..e19ae3431f0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -1156,7 +1156,7 @@ % \@@_small_int_test:NnnwNTF % } % Tests if the floating point argument is an integer or $\pm\infty$. -% If so, it is converted to an integer in the range $[-10^{8},10^{8}]$ +% If so, it is clipped to an integer in the range $[-10^{8},10^{8}]$ % and fed as a braced argument to the \meta{true code}. % Otherwise, the \meta{false code} is performed. % @@ -1207,37 +1207,6 @@ % \end{macro} % \end{macro} % -% \subsection{\texttt{x}-like expansion expandably} -% -% \begin{macro}[EXP]{\@@_expand:n} -% \begin{macro}[EXP]{\@@_expand_loop:nwnN} -% This expandable function behaves in a way somewhat similar to -% \cs{use:x}, but much less robust. The argument is -% \texttt{f}-expanded, then the leading item (often a single character -% token) is moved to a storage area after \cs{s_@@_mark}, and -% \texttt{f}-expansion is applied again, repeating until the argument -% is empty. The result built one piece at a time is then inserted in -% the input stream. Note that spaces are ignored by this procedure, -% unless surrounded with braces. Multiple tokens which do not need -% expansion can be inserted within braces. -% \begin{macrocode} -\cs_new:Npn \@@_expand:n #1 - { - \@@_expand_loop:nwnN { } - #1 \prg_do_nothing: - \s_@@_mark { } \@@_expand_loop:nwnN - \s_@@_mark { } \@@_use_i_until_s:nw ; - } -\cs_new:Npn \@@_expand_loop:nwnN #1#2 \s_@@_mark #3 #4 - { - \exp_after:wN #4 \exp:w \exp_end_continue_f:w - #2 - \s_@@_mark { #3 #1 } #4 - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \subsection{Fast string comparison} % % \begin{macro}{\@@_str_if_eq:nn} @@ -1247,10 +1216,9 @@ % No \pkg{l3sys} or \pkg{l3luatex} just yet so we have to define in terms of % primitives. % \begin{macrocode} -\cs_new:Npn \@@_str_if_eq:nn #1#2 { \tex_strcmp:D {#1} {#2} } -\sys_if_engine_luatex:T +\sys_if_engine_luatex:TF { - \cs_set:Npn \@@_str_if_eq:nn #1#2 + \cs_new:Npn \@@_str_if_eq:nn #1#2 { \tex_directlua:D { @@ -1262,6 +1230,7 @@ } } } + { \cs_new_eq:NN \@@_str_if_eq:nn \tex_strcmp:D } % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx index 77123e92b61..d4a81b3c8fb 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx index b7a76f0ce8c..af8c5d8a63a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -592,26 +592,19 @@ { \tl_if_empty:nF {#1} { - \@@_expand:n + \exp_last_unbraced:Ne \use_ii:nn { - { \use_ii:nn } \@@_array_to_clist_loop:Nw #1 { ? \prg_break: } ; \prg_break_point: } } } -\cs_new:Npx \@@_array_to_clist_loop:Nw #1#2; +\cs_new:Npn \@@_array_to_clist_loop:Nw #1#2; { - \exp_not:N \use_none:n #1 - \exp_not:N \exp_after:wN - { - \exp_not:N \exp_after:wN , - \exp_not:N \exp_after:wN \c_space_tl - \exp_not:N \exp:w - \exp_not:N \exp_end_continue_f:w - \exp_not:N \@@_to_tl_dispatch:w #1 #2 ; - } - \exp_not:N \@@_array_to_clist_loop:Nw + \use_none:n #1 + , ~ + \exp_not:f { \@@_to_tl_dispatch:w #1 #2 ; } + \@@_array_to_clist_loop:Nw } % \end{macrocode} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx index 1827c24b804..c4d2decc1df 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -64,6 +64,7 @@ % { % \@@_parse_word_exp:N , % \@@_parse_word_ln:N , +% \@@_parse_word_fact:N, % } % Unary functions. % \begin{macrocode} @@ -71,6 +72,8 @@ { \@@_parse_unary_function:NNN \@@_exp_o:w ? } \cs_new:Npn \@@_parse_word_ln:N { \@@_parse_unary_function:NNN \@@_ln_o:w ? } +\cs_new:Npn \@@_parse_word_fact:N + { \@@_parse_unary_function:NNN \@@_fact_o:w ? } % \end{macrocode} % \end{macro} % @@ -1247,6 +1250,124 @@ % \end{macrocode} % \end{macro} % +% \subsection{Factorial} +% +% \begin{variable}{\c_@@_fact_max_arg_int} +% The maximum integer whose factorial fits in the exponent range is +% $3248$, as $3249!\sim 10^{10000.8}$ +% \begin{macrocode} +\int_const:Nn \c_@@_fact_max_arg_int { 3248 } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[EXP]{\@@_fact_o:w} +% First detect $\pm 0$ and $+\infty$ and \texttt{nan}. Then note that +% factorial of anything with a negative sign (except $-0$) is +% undefined. Then call \cs{@@_small_int:wTF} to get an integer as the +% argument, and start a loop. This is not the most efficient way of +% computing the factorial, but it works all right. Of course we work +% with $24$ digits instead of~$16$. It is easy to check that +% computing factorials with this precision is enough. +% \begin{macrocode} +\cs_new:Npn \@@_fact_o:w #1 \s_@@ \@@_chk:w #2#3#4; @ + { + \if_case:w #2 \exp_stop_f: + \@@_case_return_o:Nw \c_one_fp + \or: + \or: + \if_meaning:w 0 #3 + \exp_after:wN \@@_case_return_same_o:w + \fi: + \or: + \@@_case_return_same_o:w + \fi: + \if_meaning:w 2 #3 + \@@_case_use:nw { \@@_invalid_operation_o:fw { fact } } + \fi: + \@@_fact_pos_o:w + \s_@@ \@@_chk:w #2 #3 #4 ; + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_fact_pos_o:w, \@@_fact_int_o:w} +% Then check the input is an integer, and call +% \cs{@@_facorial_int_o:n} with that \texttt{int} as an argument. If +% it's too big the factorial overflows. Otherwise call +% \cs{@@_sanitize:Nw} with a positive sign marker~|0| and an integer +% expression that will mop up any exponent in the calculation. +% \begin{macrocode} +\cs_new:Npn \@@_fact_pos_o:w #1; + { + \@@_small_int:wTF #1; + { \@@_fact_int_o:n } + { \@@_invalid_operation_o:fw { fact } #1; } + } +\cs_new:Npn \@@_fact_int_o:n #1 + { + \if_int_compare:w #1 > \c_@@_fact_max_arg_int + \@@_case_return:nw + { + \exp_after:wN \exp_after:wN \exp_after:wN \@@_overflow:w + \exp_after:wN \c_inf_fp + } + \fi: + \exp_after:wN \@@_sanitize:Nw + \exp_after:wN 0 + \int_value:w \@@_int_eval:w + \@@_fact_loop_o:w #1 . 4 , { 1 } { } { } { } { } { } ; + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_fact_loop_o:w} +% The loop receives an integer |#1| whose factorial we want to +% compute, which we progressively decrement, and the result so far as +% an extended-precision number |#2| in the form +% \meta{exponent}|,|\meta{mantissa}|;|. The loop goes in steps of two +% because we compute |#1*#1-1| as an integer expression (it must fit +% since |#1| is at most $3248$), then multiply with the result so far. +% We don't need to fill in most of the mantissa with zeros because +% \cs{@@_ep_mul:wwwwn} first normalizes the extended precision number +% to avoid loss of precision. When reaching a small enough number +% simply use a table of factorials less than $10^8$. This limit is +% chosen because the normalization step cannot deal with larger +% integers. +% \begin{macrocode} +\cs_new:Npn \@@_fact_loop_o:w #1 . #2 ; + { + \if_int_compare:w #1 < 12 \exp_stop_f: + \@@_fact_small_o:w #1 + \fi: + \exp_after:wN \@@_ep_mul:wwwwn + \exp_after:wN 4 \exp_after:wN , + \exp_after:wN { \int_value:w \@@_int_eval:w #1 * (#1 - 1) } + { } { } { } { } { } ; + #2 ; + { + \exp_after:wN \@@_fact_loop_o:w + \int_value:w \@@_int_eval:w #1 - 2 . + } + } +\cs_new:Npn \@@_fact_small_o:w #1 \fi: #2 ; #3 ; #4 + { + \fi: + \exp_after:wN \@@_ep_mul:wwwwn + \exp_after:wN 4 \exp_after:wN , + \exp_after:wN + { + \int_value:w + \if_case:w #1 \exp_stop_f: + 1 \or: 1 \or: 2 \or: 6 \or: 24 \or: 120 \or: 720 \or: 5040 + \or: 40320 \or: 362880 \or: 3628800 \or: 39916800 + \fi: + } { } { } { } { } { } ; + #3 ; + \@@_ep_to_float_o:wwN 0 + } +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx index 63632006068..7fed9ae6b51 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx index 956680401fb..a5e5dcef8c2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx index 1b2e99e6347..79ffd106299 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx index fd7689c8baf..da37a9e89c9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx index 41ae37c9e0c..e2c70701c70 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx index 64999b90a29..b9810a08d63 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx index 19986a962cf..7c19482bb3c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx index 82797003afb..aa3b0c81a12 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx @@ -49,7 +49,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -73,6 +73,7 @@ % $x\mathop{\&\&}y$, disjunction $x\mathop{\vert\vert}y$, ternary % operator $x\mathop{?}y\mathop{:}z$. % \item Exponentials: $\exp x$, $\ln x$, $x^y$. +% \item Integer factorial: $\operatorname{fact} x$. % \item Trigonometry: $\sin x$, $\cos x$, $\tan x$, $\cot x$, $\sec % x$, $\csc x$ expecting their arguments in radians, and % $\operatorname{sind} x$, $\operatorname{cosd} x$, @@ -1028,6 +1029,18 @@ % If the operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % +% \begin{function}[tested = m3fp-expo001]{fact} +% \begin{syntax} +% \cs{fp_eval:n} \{ |fact(| \meta{fpexpr} |)| \} +% \end{syntax} +% Computes the factorial of the \meta{fpexpr}. If the \meta{fpexpr} +% is an integer between $-0$ and $3248$ included, the result is finite +% and correctly rounded. Larger positive integers give $+\infty$ with +% \enquote{overflow}, while $|fact(|{+\infty}|)|=+\infty$ and +% $|fact(nan)|=|nan|$ with no exception. All other inputs give \nan{} +% with the \enquote{invalid operation} exception. +% \end{function} +% % \begin{function}[tested = m3fp-expo001]{ln} % \begin{syntax} % \cs{fp_eval:n} \{ |ln(| \meta{fpexpr} |)| \} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx index 2052e2010d2..16d8299ec8f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index 947a91fa8ab..577a66a44fc 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -63,10 +63,30 @@ % \begin{syntax} % \cs{int_eval:n} \Arg{integer expression} % \end{syntax} -% Evaluates the \meta{integer expression}, expanding any -% integer and token list variables within the \meta{expression} -% to their content (without requiring \cs{int_use:N}/\cs{tl_use:N}) -% and applying the standard mathematical rules. For example both +% Evaluates the \meta{integer expression} and leaves the result in the +% input stream as an integer denotation: for positive results an +% explicit sequence of decimal digits not starting with~\texttt{0}, +% for negative results \texttt{-}~followed by such a sequence, and +% \texttt{0}~for zero. The \meta{integer expression} should consist, +% after expansion, of \texttt{+}, \texttt{-}, \texttt{*}, \texttt{/}, +% \texttt{(}, \texttt{)} and of course integer operands. The result +% is calculated by applying standard mathematical rules with the +% following peculiarities: +% \begin{itemize} +% \item \texttt{/} denotes division rounded to the closest integer with +% ties rounded away from zero; +% \item there is an error and the overall expression evaluates to zero +% whenever the absolute value of any intermediate result exceeds +% $2^{31}-1$, except in the case of scaling operations +% $a$\texttt{*}$b$\texttt{/}$c$, for which $a$\texttt{*}$b$ may be +% arbitrarily large; +% \item parentheses may not appear after unary \texttt{+} or +% \texttt{-}, namely placing \texttt{+(} or \texttt{-(} at the start +% of an expression or after \texttt{+}, \texttt{-}, \texttt{*}, +% \texttt{/} or~\texttt{(} leads to an error. +% \end{itemize} +% Each integer operand can be either an integer variable (with no need +% for \cs{int_use:N}) or an integer denotation. For example both % \begin{verbatim} % \int_eval:n { 5 + 4 * 3 - ( 3 + 4 * 5 ) } % \end{verbatim} @@ -76,21 +96,27 @@ % \tl_set:Nn \l_my_tl { 5 } % \int_new:N \l_my_int % \int_set:Nn \l_my_int { 4 } -% \int_eval:n { \l_my_tl + \l_my_int * 3 - ( 3 + 4 * 5 ) } +% \int_eval:n { \l_my_tl + \l_my_int * 3 - ( 3 + 4 * 5 ) } % \end{verbatim} -% both evaluate to \( -6 \). The \Arg{integer expression} may -% contain the operators \texttt{+}, \texttt{-}, \texttt{*} and -% \texttt{/}, along with parenthesis \texttt{(} and \texttt{)}. -% Any functions within the expressions should expand to an -% \meta{integer denotation}: a sequence of a sign and digits matching -% the regex |\-?[0-9]+|). -% After expansion \cs{int_eval:n} yields an \meta{integer denotation} -% which is left in the input stream. +% evaluate to $-6$ because \cs[no-index]{l_my_tl} expands to the +% integer denotation~|5|. As the \meta{integer expression} is fully +% expanded from left to right during evaluation, fully expandable and +% restricted-expandable functions can both be used, and \cs{exp_not:n} +% and its variants have no effect while \cs{exp_not:N} may incorrectly +% interrupt the expression. % \begin{texnote} % Exactly two expansions are needed to evaluate \cs{int_eval:n}. % The result is \emph{not} an \meta{internal integer}, and therefore % requires suitable termination if used in a \TeX{}-style integer % assignment. +% +% As all \TeX{} integers, integer operands can also be dimension or +% skip variables, converted to integers in~\texttt{sp}, or octal +% numbers given as \texttt{'} followed by digits other than +% \texttt{8} and \texttt{9}, or hexadecimal numbers given as +% |"| followed by digits or upper case letters from +% \texttt{A} to~\texttt{F}, or the character code of some character +% or one-character control sequence, given as \texttt{`}\meta{char}. % \end{texnote} % \end{function} % @@ -100,9 +126,12 @@ % \end{syntax} % Evaluates the \meta{integer expression} as described for % \cs{int_eval:n}. The end of the expression is the first token -% encountered that cannot form part of such an expression. -% If that token is \cs{scan_stop:} it is removed, otherwise not. -% Spaces do \emph{not} terminate the expression. +% encountered that cannot form part of such an expression. If that +% token is \cs{scan_stop:} it is removed, otherwise not. Spaces do +% \emph{not} terminate the expression. However, spaces terminate +% explict integers, and this may terminate the expression: for +% instance, \cs{int_eval:w} \verb*|1 + 1 9| expands to \texttt{29} +% since the digit~\texttt{9} is not part of the expression. % \end{function} % % \begin{function}[EXP, updated = 2012-09-26]{\int_abs:n} @@ -698,9 +727,13 @@ % \cs{int_to_roman:n} \Arg{integer expression} % \end{syntax} % Places the value of the \meta{integer expression} in the input -% stream as Roman numerals, either lower case (\cs{int_to_roman:n}) -% or upper case (\cs{int_to_Roman:n}). The Roman numerals are letters -% with category code $11$ (letter). +% stream as Roman numerals, either lower case (\cs{int_to_roman:n}) or +% upper case (\cs{int_to_Roman:n}). If the value is negative or zero, +% the output is empty. The Roman numerals are letters with category +% code $11$ (letter). The letters used are |mdclxvi|, repeated as +% needed: the notation with bars (such as $\bar{\mbox{v}}$ for $5000$) +% is \emph{not} used. For instance \cs{int_to_roman:n} |{| 8249 |}| +% expands to |mmmmmmmmccxlix|. % \end{function} % % \section{Converting from other formats to integers} @@ -2557,75 +2590,6 @@ % \end{variable} % \end{variable} % -% \subsection{Deprecated} -% -% \begin{variable}[deprecated = 2019-12-31] -% { -% \c_zero, \c_one, \c_two, \c_three, \c_four, \c_five, \c_six, -% \c_seven, \c_eight, \c_nine, \c_ten, \c_eleven, \c_twelve, -% \c_thirteen, \c_fourteen, \c_fifteen, \c_sixteen, \c_thirty_two, -% \c_one_hundred, \c_two_hundred_fifty_five, -% \c_two_hundred_fifty_six, \c_one_thousand, \c_ten_thousand, -% } -% \begin{macro}{\@@_deprecated_constants:nn} -% Constants that are now deprecated. By default define them with -% \cs{int_const:Nn}. To deprecate them call for instance -% \cs{__kernel_deprecation_error:Nnn} \cs{c_zero} |{0}| -% |{2019-12-31}|. To redefine them (locally), use -% \cs{@@_constdef:Nw}, with an \cs{exp_not:N} construction because the -% constants themselves are outer at that point. -% \begin{macrocode} -\cs_new_protected:Npn \@@_deprecated_constants:nn #1#2 - { - #1 \c_zero { 0 } #2 - #1 \c_one { 1 } #2 - #1 \c_two { 2 } #2 - #1 \c_three { 3 } #2 - #1 \c_four { 4 } #2 - #1 \c_five { 5 } #2 - #1 \c_six { 6 } #2 - #1 \c_seven { 7 } #2 - #1 \c_eight { 8 } #2 - #1 \c_nine { 9 } #2 - #1 \c_ten { 10 } #2 - #1 \c_eleven { 11 } #2 - #1 \c_twelve { 12 } #2 - #1 \c_thirteen { 13 } #2 - #1 \c_fourteen { 14 } #2 - #1 \c_fifteen { 15 } #2 - #1 \c_sixteen { 16 } #2 - #1 \c_thirty_two { 32 } #2 - #1 \c_one_hundred { 100 } #2 - #1 \c_two_hundred_fifty_five { 255 } #2 - #1 \c_two_hundred_fifty_six { 256 } #2 - #1 \c_one_thousand { 1000 } #2 - #1 \c_ten_thousand { 10000 } #2 - } -\@@_deprecated_constants:nn { \int_const:Nn } { } -\__kernel_deprecation_code:nn - { - \@@_deprecated_constants:nn - { \__kernel_deprecation_error:Nnn } { { 2019-12-31 } } - } - { - \@@_deprecated_constants:nn - { - \exp_after:wN \use:nnn - \exp_after:wN \@@_constdef:Nw \exp_not:N - } - { \exp_stop_f: } - } -% \end{macrocode} -% \end{macro} -% \end{variable} -% -% \begin{macro}[deprecated = 2019-12-31]{\@@_value:w} -% Made public. -% \begin{macrocode} -\cs_new_eq:NN \@@_value:w \int_value:w -% \end{macrocode} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx index 43074d8f92b..53abc1853c0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx index 7499ddd923f..72834cf9bdf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -404,14 +404,6 @@ % because that would interfere with the action of the conditional. % \end{function} % -% \begin{function}{\__kernel_patch_deprecation:nnNNpn} -% \begin{syntax} -% \cs{__kernel_patch_deprecation:nnNNpn} \Arg{before} \Arg{after} -% \meta{definition} \meta{function}\meta{parameters} \Arg{type} \Arg{code} -% \end{syntax} -% Similar to \cs{__kernel_patch:nnNNpn} for deprecated functions. -% \end{function} -% % \begin{function} % {\__kernel_patch_args:nNNpn, \__kernel_patch_conditional_args:nNNpnn} % \begin{syntax} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index 062880a45c4..cafd46ec777 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -305,16 +305,16 @@ % Specifies that the \meta{key} path should inherit the keys listed % as \meta{parents}. For example, after setting % \begin{verbatim} -% \keys_define:n { foo } { test .code:n = \tl_show:n {#1} } -% \keys_define:n { } { bar .inherit:n = foo } +% \keys_define:nn { foo } { test .code:n = \tl_show:n {#1} } +% \keys_define:nn { } { bar .inherit:n = foo } % \end{verbatim} % setting % \begin{verbatim} -% \keys_set:n { bar } { test = a } +% \keys_set:nn { bar } { test = a } % \end{verbatim} % will be equivalent to % \begin{verbatim} -% \keys_set:n { foo } { test = a } +% \keys_set:nn { foo } { test = a } % \end{verbatim} % \end{function} % @@ -2478,14 +2478,10 @@ \exp_after:wN { \l_keys_value_tl } } { - \bool_if:NTF \l_@@_only_known_bool - { \@@_store_unused: } - { - \cs_if_exist:cTF - { \c_@@_inherit_root_tl \@@_parent:o \l_keys_path_tl } - { \@@_execute_inherit: } - { \@@_execute_unknown: } - } + \cs_if_exist:cTF + { \c_@@_inherit_root_tl \@@_parent:o \l_keys_path_tl } + { \@@_execute_inherit: } + { \@@_execute_unknown: } } } % \end{macrocode} @@ -2512,15 +2508,19 @@ } \cs_new_protected:Npn \@@_execute_unknown: { - \cs_if_exist:cTF - { \c_@@_code_root_tl \l_@@_module_tl / unknown } + \bool_if:NTF \l_@@_only_known_bool + { \@@_store_unused: } { - \cs:w \c_@@_code_root_tl \l_@@_module_tl / unknown - \exp_after:wN \cs_end: \exp_after:wN { \l_keys_value_tl } - } - { - \__kernel_msg_error:nnxx { kernel } { key-unknown } - { \l_keys_path_tl } { \l_@@_module_tl } + \cs_if_exist:cTF + { \c_@@_code_root_tl \l_@@_module_tl / unknown } + { + \cs:w \c_@@_code_root_tl \l_@@_module_tl / unknown + \exp_after:wN \cs_end: \exp_after:wN { \l_keys_value_tl } + } + { + \__kernel_msg_error:nnxx { kernel } { key-unknown } + { \l_keys_path_tl } { \l_@@_module_tl } + } } } \cs_new:Npn \@@_execute:nn #1#2 @@ -2536,7 +2536,7 @@ % When there is no relative path, things here are easy: just save the key % name and value. When we are working with a relative path, first we % need to turn it into a string: that can't happen earlier as we need -% to store |\q_no_value|. Then, use a standard delimited approach to fish +% to store \cs{q_no_value}. Then, use a standard delimited approach to fish % out the partial path. % \begin{macrocode} \cs_new_protected:Npn \@@_store_unused: @@ -2706,7 +2706,7 @@ { \exp_args:Nnf \msg_show_item_unbraced:nn { code } { - \exp_args:Nc \token_get_replacement_spec:N + \exp_args:Nc \cs_replacement_spec:N { \c_@@_code_root_tl \@@_trim_spaces:n { #2 / #3 } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index a9a52583115..077c4f066c0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -279,22 +279,6 @@ } % \end{macrocode} % -% \subsection{Deprecated functions} -% -% \begin{macro}[EXP, deprecated = 2019-12-31]{\lua_now_x:n, \lua_escape_x:n} -% \begin{macro}[deprecated = 2019-12-31]{\lua_shipout_x:n} -% For removal after 2019-12-31. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \lua_now:e } -\cs_new:Npn \lua_now_x:n #1 { \@@_now:n {#1} } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \lua_escape:e } -\cs_new:Npn \lua_escape_x:n #1 { \@@_escape:n {#1} } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \lua_shipout_e:n } -\cs_new_protected:Npn \lua_shipout_x:n #1 { \@@_shipout:n {#1} } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \begin{macrocode} %</tex> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx index 72bfd68be88..9eefca2a6f6 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -1699,11 +1699,6 @@ LaTeX~has~been~asked~to~use~a~control~sequence~'#1':\\ this~has~not~been~defined~yet. } -\__kernel_msg_new:nnn { kernel } { deprecated-command } - { - The~deprecated~command~'#2'~has~been~or~will~be~removed~on~#1. - \tl_if_empty:nF {#3} { ~Use~instead~'#3'. } - } \__kernel_msg_new:nnnn { kernel } { empty-search-pattern } { Empty~search~pattern. } { @@ -1757,7 +1752,7 @@ Only~expandable~tests~can~have~a~predicate~version. } \__kernel_msg_new:nnn { kernel } { randint-backward-range } - { Bounds~ordered~backwards~in~\int_rand:nn {#1}~{#2}. } + { Bounds~ordered~backwards~in~\iow_char:N\\int_rand:nn~{#1}~{#2}. } \__kernel_msg_new:nnnn { kernel } { conditional-form-unknown } { Conditional~form~'#1'~for~function~'#2'~unknown. } { @@ -1923,7 +1918,7 @@ \__kernel_msg_new:nnn { kernel } { misused-prop } { A~property~list~was~misused. } \__kernel_msg_new:nnn { kernel } { negative-replication } - { Negative~argument~for~\prg_replicate:nn. } + { Negative~argument~for~\iow_char:N\\prg_replicate:nn. } \__kernel_msg_new:nnn { kernel } { prop-keyval } { Missing/extra~'='~in~'#1'~(in~'..._keyval:Nn') } \__kernel_msg_new:nnn { kernel } { unknown-comparison } @@ -2034,15 +2029,21 @@ % The command built from the csname % \cs{c_@@_text_prefix_tl} |LaTeX / #1 / #2| % takes four arguments and builds the error text, which is fed to -% \cs{@@_expandable_error:n}. +% \cs{@@_expandable_error:n} with appropriate expansion: just as for +% usual messages the arguments are first turned to strings, then the +% message is fully expanded. % \begin{macrocode} +\exp_args_generate:n { oooo } \cs_new:Npn \__kernel_msg_expandable_error:nnnnnn #1#2#3#4#5#6 { - \exp_args:Nf \@@_expandable_error:n + \exp_args:Ne \@@_expandable_error:n { - \exp_args:NNc \exp_after:wN \exp_stop_f: + \exp_args:Nc \exp_args:Noooo { \c_@@_text_prefix_tl LaTeX / #1 / #2 } - {#3} {#4} {#5} {#6} + { \tl_to_str:n {#3} } + { \tl_to_str:n {#4} } + { \tl_to_str:n {#5} } + { \tl_to_str:n {#6} } } } \cs_new:Npn \__kernel_msg_expandable_error:nnnnn #1#2#3#4#5 @@ -2072,95 +2073,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[deprecated = 2019-12-31]{\msg_log:n, \msg_term:n} -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \iow_log:n } -\cs_new_protected:Npn \msg_log:n #1 - { - \iow_log:n { ................................................. } - \iow_wrap:nnnN { . ~ #1} { . ~ } { } \iow_log:n - \iow_log:n { ................................................. } - } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \iow_term:n } -\cs_new_protected:Npn \msg_term:n #1 - { - \iow_term:n { ************************************************* } - \iow_wrap:nnnN { * ~ #1} { * ~ } { } \iow_term:n - \iow_term:n { ************************************************* } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[deprecated = 2019-12-31]{\msg_interrupt:nnn} -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { [Defined~error~message] } -\cs_new_protected:Npn \msg_interrupt:nnn #1#2#3 - { - \tl_if_empty:nTF {#3} - { - \@@_old_interrupt_wrap:nn { \\ \c_@@_no_info_text_tl } - {#1 \\\\ #2 \\\\ \c_@@_continue_text_tl } - } - { - \@@_old_interrupt_wrap:nn { \\ #3 } - {#1 \\\\ #2 \\\\ \c_@@_help_text_tl } - } - } -\cs_new_protected:Npn \@@_old_interrupt_wrap:nn #1#2 - { - \iow_wrap:nnnN {#1} { | ~ } { } \@@_old_interrupt_more_text:n - \iow_wrap:nnnN {#2} { ! ~ } { } \@@_old_interrupt_text:n - } -\cs_new_protected:Npn \@@_old_interrupt_more_text:n #1 - { - \exp_args:Nx \tex_errhelp:D - { - |''''''''''''''''''''''''''''''''''''''''''''''' - #1 \iow_newline: - |............................................... - } - } -\group_begin: - \char_set_lccode:nn {`\{} {`\ } - \char_set_lccode:nn {`\}} {`\ } - \char_set_lccode:nn {`\&} {`\!} - \char_set_catcode_active:N \& -\tex_lowercase:D - { - \group_end: - \cs_new_protected:Npn \@@_old_interrupt_text:n #1 - { - \iow_term:x - { - \iow_newline: - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - \iow_newline: - ! - } - \__kernel_iow_with:Nnn \tex_newlinechar:D { `\^^J } - { - \__kernel_iow_with:Nnn \tex_errorcontextlines:D { -1 } - { - \group_begin: - \cs_set_protected:Npn & - { - \tex_errmessage:D - { - #1 - \use_none:n - { ............................................ } - } - } - \exp_after:wN - \group_end: - & - } - } - } - } -% \end{macrocode} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx index 07c5a4e47a0..77a3a07df45 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index c216c6dba78..5e74f2df7d6 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -1616,47 +1616,6 @@ % \end{macro} % \end{macro} % -% \subsection{Deprecated functions} -% -% \begin{macro}[deprecated = 2019-12-31]{\@@_break_point:Nn} -% \begin{macro}[deprecated = 2019-12-31]{\@@_break_point:} -% \begin{macro}[deprecated = 2019-12-31]{\@@_map_break:Nn} -% \begin{macro}[deprecated = 2019-12-31]{\@@_break:} -% \begin{macro}[deprecated = 2019-12-31]{\@@_break:n} -% Made public, but used by a few third-parties. It's not possible to -% perfectly support a mixture of \cs{@@_map_break:Nn} and -% \cs{prg_map_break:Nn} because they use different delimiters. The -% following code only breaks if someone tries to break from two -% \enquote{old-style} \cs{@@_map_break:Nn} \ldots{} -% \cs{@@_break_point:Nn} mappings in one go. Basically, the -% \cs{@@_map_break:Nn} converts a single \cs{@@_break_point:Nn} to -% \cs{prg_break_point:Nn}, and that delimiter had better be the right -% one. Then we call \cs{prg_map_break:Nn} which may end up breaking -% intermediate looks in the (unbraced) argument |#1|. It is essential -% to define the |break_point| functions before the corresponding -% |break| functions: otherwise \cs{debug_on:n} |{deprecation}| -% \cs{debug_off:n} |{deprecation}| would break when trying to restore -% the definitions because they would involve deprecated commands whose -% definition has not yet been restored. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \prg_break_point:Nn } -\cs_new:Npn \@@_break_point:Nn { \prg_break_point:Nn } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \prg_break_point: } -\cs_new:Npn \@@_break_point: { \prg_break_point: } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \prg_map_break:Nn } -\cs_new:Npn \@@_map_break:Nn #1 \@@_break_point:Nn - { \prg_map_break:Nn #1 \prg_break_point:Nn } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \prg_break: } -\cs_new:Npn \@@_break: #1 \@@_break_point: { } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \prg_break:n } -\cs_new:Npn \@@_break:n #1#2 \@@_break_point: {#1} -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx index b3f70773c4c..d83ea0f4ce2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -216,6 +216,14 @@ % \end{texnote} % \end{function} % +% \begin{function}[EXP]{\prop_count:N, \prop_count:c} +% \begin{syntax} +% \cs{prop_count:N} \meta{property list} +% \end{syntax} +% Leaves the number of key--value pairs in the \meta{property list} in +% the input stream as an \meta{integer denotation}. +% \end{function} +% % \section{Modifying property lists} % % \begin{function}[added = 2012-05-12] @@ -872,6 +880,27 @@ % \end{macro} % \end{macro} % +% \begin{macro}[EXP]{\prop_count:N, \prop_count:c} +% \begin{macro}[EXP]{\@@_count:nn} +% Counting the key--value pairs in a property list is done using the +% same approach as for other count functions: turn each entry into a +% \texttt{+1} then use integer evaluation to actually do the +% mathematics. +% \begin{macrocode} +\cs_new:Npn \prop_count:N #1 + { + \int_eval:n + { + 0 + \prop_map_function:NN #1 \@@_count:nn + } + } +\cs_new:Npn \@@_count:nn #1#2 { + 1 } +\cs_generate_variant:Nn \prop_count:N { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}[TF, tested = m3prop004] % {\prop_pop:NnN, \prop_pop:cnN, \prop_gpop:NnN, \prop_gpop:cnN} % Popping an item from a property list, keeping track of whether diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx index c3c45583597..eb50637c9a0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx index 5fab54fbcc7..cd8ecf7c4aa 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index 75b815fcd2e..052213d3aef 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx index 12876daaa36..1f23ab65c23 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx index a41b30fda8a..d78f29d838d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -742,7 +742,7 @@ % ~~~~~~\meta{extra arguments}\\ % ~~|}|\\ % \cs{@@_loop:wNn}~\ldots{}~\meta{prepared tokens}\\ -% ~~\meta{end-loop}~|{}|~|\q_stop| +% ~~\meta{end-loop}~|{}|~\cs{q_stop} % \end{quote} % In this example, which matches the structure of % \cs{@@_quick_split_i:NnnnnNn} and a few other functions below, the diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx index 028c89dce77..e97e0b190ec 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -791,6 +791,14 @@ % Displays the content of the \meta{str~var} on the terminal. % \end{function} % +% \begin{function}[added = 2019-02-15] +% {\str_log:N, \str_log:c, \str_log:n} +% \begin{syntax} +% \cs{str_log:N} \meta{str~var} +% \end{syntax} +% Writes the content of the \meta{str~var} in the log file. +% \end{function} +% % \section{Constant token lists} % % \begin{variable}[added = 2015-09-19] @@ -1942,36 +1950,15 @@ % \subsection{Viewing strings} % % \begin{macro}{\str_show:n, \str_show:N, \str_show:c} +% \begin{macro}{\str_log:n, \str_log:N, \str_log:c} % Displays a string on the terminal. % \begin{macrocode} \cs_new_eq:NN \str_show:n \tl_show:n \cs_new_eq:NN \str_show:N \tl_show:N \cs_generate_variant:Nn \str_show:N { c } -% \end{macrocode} -% \end{macro} -% -% \subsection{Deprecated functions} -% -% \begin{macro}[EXP, deprecated = 2019-12-31, noTF]{\str_case_x:nn} -% \begin{macro}[EXP, deprecated = 2019-12-31, pTF]{\str_if_eq_x:nn} -% For removal after 2019-12-31. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_case_e:nn } -\cs_new:Npn \str_case_x:nn { \str_case_e:nn } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_case_e:nnT } -\cs_new:Npn \str_case_x:nnT { \str_case_e:nnT } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_case_e:nnF } -\cs_new:Npn \str_case_x:nnF { \str_case_e:nnF } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_case_e:nnTF } -\cs_new:Npn \str_case_x:nnTF { \str_case_e:nnTF } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_if_eq_p:ee } -\cs_new:Npn \str_if_eq_x_p:nn { \str_if_eq_p:ee } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_if_eq:eeT } -\cs_new:Npn \str_if_eq_x:nnT { \str_if_eq:eeT } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_if_eq:eeF } -\cs_new:Npn \str_if_eq_x:nnF { \str_if_eq:eeF } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } { \str_if_eq:eeTF } -\cs_new:Npn \str_if_eq_x:nnTF { \str_if_eq:eeTF } +\cs_new_eq:NN \str_log:n \tl_log:n +\cs_new_eq:NN \str_log:N \tl_log:N +\cs_generate_variant:Nn \str_log:N { c } % \end{macrocode} % \end{macro} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx index c1d0fa59975..b2000f8f1b7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx index 7938652595f..987b7b23d45 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -1094,23 +1094,6 @@ } % \end{macrocode} % -% \subsection{Deprecated functions} -% -% \begin{macro}[deprecated = 2019-12-31] -% {\tl_show_analysis:N, \tl_show_analysis:n} -% Simple renames. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } - { \tl_analysis_show:N } -\cs_new_protected:Npn \tl_show_analysis:N #1 - { \tl_analysis_show:N #1 } -\__kernel_patch_deprecation:nnNNpn { 2019-12-31 } - { \tl_analysis_show:n } -\cs_new_protected:Npn \tl_show_analysis:n #1 - { \tl_analysis_show:n {#1} } -% \end{macrocode} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index 1c8867340c2..ec82eca63f0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -700,6 +700,16 @@ % giving an \meta{integer denotation}. % \end{function} % +% \begin{function}[EXP, added = 2019-02-25]{\tl_count_tokens:n} +% \begin{syntax} +% \cs{tl_count_tokens:n} \Arg{tokens} +% \end{syntax} +% Counts the number of \TeX{} tokens in the \meta{tokens} and leaves +% this information in the input stream. Every token, including spaces and +% braces, contributes one to the total; thus for instance, the token count of +% |a~{bc}| is $6$. +% \end{function} +% % \begin{function}[updated = 2012-01-08, EXP] % {\tl_reverse:n, \tl_reverse:V, \tl_reverse:o} % \begin{syntax} @@ -822,7 +832,7 @@ % \begin{texnote} % The result is returned within \cs{exp_not:n}, which means that the % token list does not expand further when appearing in an -% \texttt{x}-type argument expansion. +% \texttt{x}-type or \texttt{e}-type argument expansion. % \end{texnote} % \end{function} % @@ -1149,7 +1159,7 @@ % % \begin{variable}[added = 2017-11-14]{\c_novalue_tl} % A marker for the absence of an argument. This constant |tl| can safely -% be typeset (\emph{cf.}~|\q_nil|), with the result being |-NoValue-|. +% be typeset (\emph{cf.}~\cs{q_nil}), with the result being |-NoValue-|. % It is important to note that \cs{c_novalue_tl} is constructed such that it % will \emph{not} match the simple text input |-NoValue-|, \emph{i.e.} % that @@ -1571,6 +1581,10 @@ % % The two \cs{if_false:} \ldots{} \cs{fi:} are there to prevent % alignment tabs to cause a change of tabular cell while rescanning. +% We put the \enquote{opening} one after \cs{group_begin:} so that if +% one accidentally \texttt{f}-expands \cs{tl_set_rescan:Nnn} braces +% remain balanced. This is essential in \texttt{e}-type arguments +% when \tn{expanded} is not available. % \begin{macrocode} \cs_new_protected:Npn \tl_set_rescan:Nnn { \@@_set_rescan:NNnn \tl_set:No } @@ -1584,8 +1598,8 @@ } \cs_new_protected:Npn \@@_set_rescan:NNnn #1#2#3#4 { - \if_false: { \fi: \group_begin: + \if_false: { \fi: \int_set_eq:NN \tex_tracingnesting:D \c_zero_int \exp_args:No \tex_everyeof:D { \c_@@_rescan_marker_tl } \int_compare:nNnT \tex_endlinechar:D = { 32 } @@ -1804,7 +1818,7 @@ % \meta{pattern}~|#6| then we can use it as the \meta{delimiter} % through \cs{@@_replace_auxii:nNNNnn} |{#1}|. Otherwise, we end up % calling \cs{@@_replace:NnNNNnn} repeatedly with the first two -% arguments |\q_mark| |{?}|, |\?| |{??}|, |\??| |{???}|, and so on, +% arguments \cs{q_mark} |{?}|, |\?| |{??}|, |\??| |{???}|, and so on, % until |#6|~does not contain the control sequence~|#1|, which we take % as our~\meta{A}. The argument~|#2| only serves to collect~|?| % characters for~|#1|. Note that the order of the tests means that @@ -2126,9 +2140,12 @@ % groups makes the test work also for empty arguments. % The \cs{if_false:} constructions are a faster way to do % \cs{group_align_safe_begin:} and \cs{group_align_safe_end:}. +% The \cs{scan_stop:} ensures that \texttt{f}-expanding +% \cs{tl_if_in:nn} does not lead to unbalanced braces. % \begin{macrocode} \prg_new_protected_conditional:Npnn \tl_if_in:nn #1#2 { T , F , TF } { + \scan_stop: \if_false: { \fi: \cs_set:Npn \@@_tmp:w ##1 #2 { } \tl_if_empty:oTF { \@@_tmp:w #1 {} {} #2 } @@ -2427,6 +2444,36 @@ % \end{macro} % \end{macro} % +% +% \begin{macro}[EXP]{\tl_count_tokens:n} +% \begin{macro}[EXP]{\@@_act_count_normal:nN, +% \@@_act_count_group:nn, \@@_act_count_space:n} +% The token count is computed through an \cs{int_eval:n} construction. +% Each \texttt{1+} is output to the \emph{left}, into the integer +% expression, and the sum is ended by the \cs{exp_end:} inserted by +% \cs{@@_act_end:wn} (which is technically implemented as \cs{c_zero_int}). +% Somewhat a hack! +% \begin{macrocode} +\cs_new:Npn \tl_count_tokens:n #1 + { + \int_eval:n + { + \@@_act:NNNnn + \@@_act_count_normal:nN + \@@_act_count_group:nn + \@@_act_count_space:n + { } + {#1} + } + } +\cs_new:Npn \@@_act_count_normal:nN #1 #2 { 1 + } +\cs_new:Npn \@@_act_count_space:n #1 { 1 + } +\cs_new:Npn \@@_act_count_group:nn #1 #2 + { 2 + \tl_count_tokens:n {#2} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}{\tl_reverse_items:n} % \begin{macro}{\@@_reverse_items:nwNwn} % \begin{macro}{\@@_reverse_items:wn} @@ -2945,13 +2992,11 @@ % \end{macro} % % \begin{macro}[EXP,pTF]{\tl_if_head_is_group:n} -% Pass the first token of |#1| through \cs{token_to_str:N}, -% then check for the brace balance. The extra \texttt{?} -% caters for an empty argument.\footnote{Bruno: this could -% be made faster, but we don't: if we hope to ever have -% an e-type argument, we need all brace \enquote{tricks} -% to happen in one step of expansion, keeping the token -% list brace balanced at all times.} +% Pass the first token of |#1| through \cs{token_to_str:N}, then check +% for the brace balance. The extra \texttt{?} caters for an empty +% argument. This could be made faster, but we need all brace tricks +% to happen in one step of expansion, keeping the token list brace +% balanced at all times. % \begin{macrocode} \prg_new_conditional:Npnn \tl_if_head_is_group:n #1 { p , T , F , TF } { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx index f3338550ffb..49bdcfc632f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -931,66 +931,6 @@ % (as appropriate to the result of the test). % \end{function} % -% \section{Decomposing a macro definition} -% -% These functions decompose \TeX{} macros into their constituent -% parts: if the \meta{token} passed is not a macro then no decomposition -% can occur. In the latter case, all three functions leave \cs{scan_stop:} -% in the input stream. -% -% \begin{function}[EXP]{\token_get_arg_spec:N} -% \begin{syntax} -% \cs{token_get_arg_spec:N} \meta{token} -% \end{syntax} -% If the \meta{token} is a macro, this function leaves -% the primitive \TeX{} argument specification in input stream as -% a string of tokens of category code $12$ (with spaces having category -% code $10$). Thus for example for a token \cs{next} defined by -% \begin{verbatim} -% \cs_set:Npn \next #1#2 { x #1 y #2 } -% \end{verbatim} -% leaves |#1#2| in the input stream. If the \meta{token} is -% not a macro then \cs{scan_stop:} is left in the input stream. -% \begin{texnote} -% If the arg~spec. contains the string |->|, then the |spec| function -% produces incorrect results. -% \end{texnote} -% \end{function} -% -% \begin{function}[EXP]{\token_get_replacement_spec:N} -% \begin{syntax} -% \cs{token_get_replacement_spec:N} \meta{token} -% \end{syntax} -% If the \meta{token} is a macro, this function leaves -% the replacement text in input stream as -% a string of tokens of category code $12$ (with spaces having category -% code $10$). Thus for example for a token \cs{next} defined by -% \begin{verbatim} -% \cs_set:Npn \next #1#2 { x #1~y #2 } -% \end{verbatim} -% leaves \verb|x#1 y#2| in the input stream. If the \meta{token} is -% not a macro then \cs{scan_stop:} is left in the input stream. -% \begin{texnote} -% If the arg~spec. contains the string |->|, then the |spec| function -% produces incorrect results. -% \end{texnote} -% \end{function} -% -% \begin{function}[EXP]{\token_get_prefix_spec:N} -% \begin{syntax} -% \cs{token_get_prefix_spec:N} \meta{token} -% \end{syntax} -% If the \meta{token} is a macro, this function leaves -% the \TeX{} prefixes applicable in input stream as -% a string of tokens of category code $12$ (with spaces having category -% code $10$). Thus for example for a token \cs{next} defined by -% \begin{verbatim} -% \cs_set:Npn \next #1#2 { x #1~y #2 } -% \end{verbatim} -% leaves |\long| in the input stream. If the \meta{token} is -% not a macro then \cs{scan_stop:} is left in the input stream -% \end{function} -% % \section{Description of all possible tokens} % \label{sec:l3token:all-tokens} % @@ -2465,59 +2405,6 @@ % \end{macrocode} % \end{macro} % -% \subsection{Decomposing a macro definition} -% -% \begin{macro}{\token_get_prefix_spec:N} -% \begin{macro}{\token_get_arg_spec:N} -% \begin{macro}{\token_get_replacement_spec:N} -% \begin{macro}{\@@_get_prefix_arg_replacement:wN} -% We sometimes want to test if a -% control sequence can be expanded to reveal a hidden -% value. However, we cannot just expand the macro blindly as it may -% have arguments and none might be present. Therefore we define -% these functions to pick either the prefix(es), the argument -% specification, or the replacement text from a macro. All of this -% information is returned as characters with catcode~$12$. If the -% token in question isn't a macro, the token \cs{scan_stop:} is -% returned instead. -% \begin{macrocode} -\exp_args:Nno \use:nn - { \cs_new:Npn \@@_get_prefix_arg_replacement:wN #1 } - { \tl_to_str:n { macro : } #2 -> #3 \q_stop #4 } - { #4 {#1} {#2} {#3} } -\cs_new:Npn \token_get_prefix_spec:N #1 - { - \token_if_macro:NTF #1 - { - \exp_after:wN \@@_get_prefix_arg_replacement:wN - \token_to_meaning:N #1 \q_stop \use_i:nnn - } - { \scan_stop: } - } -\cs_new:Npn \token_get_arg_spec:N #1 - { - \token_if_macro:NTF #1 - { - \exp_after:wN \@@_get_prefix_arg_replacement:wN - \token_to_meaning:N #1 \q_stop \use_ii:nnn - } - { \scan_stop: } - } -\cs_new:Npn \token_get_replacement_spec:N #1 - { - \token_if_macro:NTF #1 - { - \exp_after:wN \@@_get_prefix_arg_replacement:wN - \token_to_meaning:N #1 \q_stop \use_iii:nnn - } - { \scan_stop: } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx index 333caddbc60..ed6991d49e1 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % |