diff options
author | Karl Berry <karl@freefriends.org> | 2016-10-19 20:38:20 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-10-19 20:38:20 +0000 |
commit | 52b787d36c60fda90673669dd2809c95c1fdfca5 (patch) | |
tree | beb7faf87e1ab5be65f7437e500619b20eba20a1 /Master/texmf-dist/source/latex/l3kernel/l3doc.dtx | |
parent | 97a401ad817da2dafd1069df9d87a28ed39df69b (diff) |
l3 (19oct16)
git-svn-id: svn://tug.org/texlive/trunk@42306 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3doc.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3doc.dtx | 2027 |
1 files changed, 1287 insertions, 740 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx index c7148f54747..c4638af4fc2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx @@ -75,7 +75,7 @@ Do not distribute a modified version of this file. % %<*driver|class> \RequirePackage{expl3,xparse,calc} -\GetIdInfo$Id: l3doc.dtx 6474 2016-04-11 18:09:21Z qinglee $ +\GetIdInfo$Id: l3doc.dtx 6701 2016-09-08 13:56:52Z qinglee $ {L3 Experimental documentation class} %</driver|class> % @@ -282,7 +282,7 @@ Do not distribute a modified version of this file. % \end{syntax} % These commands are provided to typeset control sequences. % |\cmd\foo| produces \enquote{\cmd\foo} and |\cs{foo}| produces the -% same (\enquote{\texttt{\string\foo|}}). In general, \cs{cs} is more robust since +% same. In general, \cs{cs} is more robust since % it doesn't rely on catcodes being \enquote{correct} and is therefore % recommended. % @@ -297,7 +297,10 @@ Do not distribute a modified version of this file. % The \meta{options} are a key--value list which can contain the % following keys: % \begin{itemize} -% \item |index=|\meta{module}: the \meta{csname} will be indexed in +% \item |index=|\meta{name}: the \meta{csname} will be indexed as if +% one had written \cs{cs}\Arg{name}. +% \item |no-index|: the \meta{csname} will not be indexed. +% \item |module=|\meta{module}: the \meta{csname} will be indexed in % the list of commands from the \meta{module}; the \meta{module} % can in particular be |TeX| for \enquote{\TeX{} and \LaTeXe{}} % commands, or empty for commands which should be placed in the @@ -308,13 +311,14 @@ Do not distribute a modified version of this file. % \end{itemize} % \end{function} % +% % \begin{function}{\tn} % \begin{syntax} % \cs{tn} \oarg{options} \marg{csname} % \end{syntax} % Analoguous to \cs{cs} but intended for \enquote{traditional} \TeX{} % or \LaTeXe{} commands; they will be indexed accordingly. This is in -% fact equivalent to \cs{cs} |[index=TeX, replace=false,| +% fact equivalent to \cs{cs} |[module=TeX, replace=false,| % \meta{options}|]| \Arg{csname}. % \end{function} % @@ -383,9 +387,10 @@ Do not distribute a modified version of this file. % % Function environments take an optional argument to indicate whether % the function(s) it describes are expandable or restricted-expandable -% or defined in conditional forms. Use |EXP|, |rEXP|, |TF|, or |pTF| for +% or defined in conditional forms. Use |EXP|, |rEXP|, |TF|, |pTF|, or |noTF| for % this; note that |pTF| implies |EXP| since predicates must always be -% expandable. As an example: +% expandable, and that |noTF| means that the function without |TF| +% should be documented in addition to |TF|. As an example: % \begin{framed} % \vspace{-\baselineskip} % \begin{verbatim} @@ -426,6 +431,7 @@ Do not distribute a modified version of this file. % environment. Some changes in \pkg{l3doc}: it now accepts % comma-separated lists of functions, to avoid a very large number of % consecutive |\end{macro}| statements. +% Spaces and new lines are ignored (the option |[verb]| prevents this). % \begin{verbatim} % % \begin{macro}{\foo:N, \foo:c} % % \begin{macrocode} @@ -564,175 +570,6 @@ Do not distribute a modified version of this file. %<@@=codedoc> % \end{macrocode} % -% \subsection{Variants and helpers} -% -% \begin{macro} -% { -% \tl_count:f, -% \tl_greplace_all:Nxn, -% \tl_if_head_eq_charcode:oNTF, -% \tl_if_head_eq_charcode:oNT, -% \tl_if_head_eq_charcode:oNF, -% \tl_if_in:NoTF, -% \tl_if_in:NoT, -% \tl_if_in:NoF, -% \tl_remove_all:Nx, -% \tl_replace_all:Nxn, -% \tl_replace_all:Nnx, -% \tl_replace_all:Non, -% \tl_replace_all:Nno, -% \tl_replace_once:Noo, -% \prop_get:NxNTF, -% \prop_put:Nxn, -% \prop_gput:NVx, -% } -% A few missing variants. -% \begin{macrocode} -\cs_generate_variant:Nn \tl_count:n { f } -\cs_generate_variant:Nn \tl_greplace_all:Nnn { Nx } -\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNTF { o } -\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { o } -\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { o } -\cs_generate_variant:Nn \tl_if_in:NnTF { No } -\cs_generate_variant:Nn \tl_if_in:NnT { No } -\cs_generate_variant:Nn \tl_if_in:NnF { No } -\cs_generate_variant:Nn \tl_remove_all:Nn { Nx } -\cs_generate_variant:Nn \tl_replace_all:Nnn { Nx , Nnx, No , Nno } -\cs_generate_variant:Nn \tl_replace_once:Nnn { Noo } -\cs_generate_variant:Nn \prop_get:NnNTF { Nx } -\cs_generate_variant:Nn \prop_put:Nnn { Nx } -\cs_generate_variant:Nn \prop_gput:Nnn { NVx } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[int]{\@@_replace_at_at:N} -% \begin{macro}[aux]{\@@_replace_at_at_aux:Nn} -% If there is no \meta{module~name}, do nothing. Otherwise replace -% all other-|@| by letter-|@| and all other-|_| by letter-|_|, then -% replace |_@@| by |__|\meta{module~name} and |@@| by -% |__|\meta{module~name} too. The result contains |_| with category -% code letter because this is what the |macrocode| environment -% expects. Other use cases can apply \cs{tl_to_str:n} if needed. -% Note that we include spaces between the -% |@| in the code below, since it is also processed through the same -% replacement rules. -% \begin{macrocode} -\cs_new_protected:Npn \@@_replace_at_at:N #1 - { - \tl_if_empty:NF \g_@@_module_name_tl - { - \exp_args:NNo \@@_replace_at_at_aux:Nn - #1 \g_@@_module_name_tl - } - } -\cs_new_protected:Npn \@@_replace_at_at_aux:Nn #1#2 - { - \tl_replace_all:Non #1 { \token_to_str:N @ } { @ } - \tl_replace_all:Non #1 { \token_to_str:N _ } { _ } - \tl_replace_all:Nnn #1 { _ @ @ } { _ _ #2 } - \tl_replace_all:Nnn #1 { @ @ } { _ _ #2 } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[aux]{\@@_verb_get_seq:nN} -% The argument~|#1| is given with catcodes $10$ (space), $12$ (other) -% and $13$ (active). Turn active characters to other. Remove any -% \enquote{\%} character at the beginning of a line. Remove tabs and -% newlines. Finally, convert |_@@| and |@@| to |__|\meta{module name} -% (if it is non-empty). At this point, \cs{l_@@_tmpa_tl} contains a -% comma-delimited list of names, where |@| and~|_| have category code -% letter. Turn it to a string, parse it as a comma-delimited list, -% and turn the result into a sequence of function/macro names. -% \begin{macrocode} -\cs_new_protected:Npn \@@_verb_get_seq:nN #1#2 - { - \tl_set:Nx \l_@@_tmpa_tl { \tl_to_str:n {#1} } - \tl_remove_all:Nx \l_@@_tmpa_tl - { \iow_char:N \^^M \iow_char:N \% } - \tl_remove_all:Nx \l_@@_tmpa_tl { \tl_to_str:n { ^ ^ A } } - \tl_remove_all:Nx \l_@@_tmpa_tl { \iow_char:N \^^I } - \tl_remove_all:Nx \l_@@_tmpa_tl { \iow_char:N \^^M } - \@@_replace_at_at:N \l_@@_tmpa_tl - \exp_args:NNx \seq_set_from_clist:Nn #2 - { \tl_to_str:N \l_@@_tmpa_tl } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[aux,rEXP] -% {\@@_signature_base_form:n, \@@_signature_base_form_aux:n} -% Expands to the \enquote{base form} of the signature. For instance, -% given |noxcfvV| it would obtain |nnnNnnn|, or given |ow| it would -% obtain |nw|. The loop stops at the first token that is not -% recognized. -% \begin{macrocode} -\cs_new:Npn \@@_signature_base_form:n #1 - { \@@_signature_base_form_aux:n #1 \c_empty_tl } -\cs_new:Npn \@@_signature_base_form_aux:n #1 - { - \str_case:nnTF {#1} - { - { N } { N } - { c } { N } - { n } { n } - { o } { n } - { f } { n } - { x } { n } - { V } { n } - { v } { n } - } - { \@@_signature_base_form_aux:n } - {#1} - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[aux]{\@@_predicate_from_base:N} -% Get predicate from a function's base name. This \enquote{works} for -% functions with no signature too. -% \begin{macrocode} -\cs_new:Npn \@@_predicate_from_base:N #1 - { - \__cs_get_function_name:N #1 _p: - \__cs_get_function_signature:N #1 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[int]{\CodedocUseCs} -% To implement commands which can be used in bookmarks and moving -% arguments, it appears necessary to have an analogue of \cs{use:c} -% using only user-level category codes, or to make all auxiliaries -% user-level. -% \begin{macrocode} -\cs_new_protected:Npn \CodedocUseCs #1 { \use:c { \tl_to_str:n {#1} } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[int]{\CodedocUnexpandedTokens} -% \begin{macro}[aux]{\CodedocUnexpandedTokens } -% \begin{macro}[aux]{\@@_exp_not:n} -% Function used as \cs{CodedocUnexpandedTokens} \meta{junk} -% \Arg{argument}. The braces are necessary, and \meta{junk}, ignored, -% must not contain braces. When used in a typesetting context, the -% function calls an auxiliary (whose name has a trailing space) which -% leaves the \meta{argument} in the input stream. When used in an -% \texttt{x}-expansion context instead, the auxiliary does not expand, -% and \cs{@@_exp_not:n} \Arg{argument} expands to itself. If this is -% written into a file and read back, the result has the original form -% \cs{CodedocUnexpandedTokens} \meta{junk} \Arg{argument}. -% \begin{macrocode} -\cs_new:Npn \CodedocUnexpandedTokens #1 # - { \use:c { CodedocUnexpandedTokens ~ } \@@_exp_not:n } -\cs_new_protected:cpn { CodedocUnexpandedTokens ~ } #1#2 {#2} -\cs_new:Npn \@@_exp_not:n #1 { \exp_not:n { \@@_exp_not:n {#1} } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% % \subsection{Variables} % % \begin{variable}{\g_docinput_clist} @@ -762,13 +599,13 @@ Do not distribute a modified version of this file. % \end{variable} % % \begin{variable}[int] -% {\l_@@_names_coffin, \l_@@_descr_coffin, \l_@@_syntax_coffin} +% {\l_@@_functions_coffin, \l_@@_descr_coffin, \l_@@_syntax_coffin} % These coffins contain respectively the list of function names % (argument of the \env{function} environment), the text between % |\begin{function}| and |\end{function}|, and the syntax given in the % \env{syntax} environment. % \begin{macrocode} -\coffin_new:N \l_@@_names_coffin +\coffin_new:N \l_@@_functions_coffin \coffin_new:N \l_@@_descr_coffin \coffin_new:N \l_@@_syntax_coffin % \end{macrocode} @@ -784,7 +621,7 @@ Do not distribute a modified version of this file. % % \begin{variable}[int]{\l_@@_long_name_bool, \l_@@_trial_width_dim} % The boolean \cs{l_@@_long_name_bool} is \texttt{true} if the width -% \cs{l_@@_trial_width_dim} of the coffin \cs{l_@@_names_coffin} +% \cs{l_@@_trial_width_dim} of the coffin \cs{l_@@_functions_coffin} % (containing the current function names) is bigger than the space % available in the margin. % \begin{macrocode} @@ -825,20 +662,28 @@ Do not distribute a modified version of this file. % \l_@@_macro_aux_bool, % \l_@@_macro_TF_bool, % \l_@@_macro_pTF_bool, +% \l_@@_macro_noTF_bool, % \l_@@_macro_EXP_bool, % \l_@@_macro_rEXP_bool, % \l_@@_macro_var_bool, +% \l_@@_override_module_tl, +% \l_@@_macro_documented_tl, % } % Contain information about some options of function/macro -% environments: +% environments. We initialize \cs{l_@@_override_module_tl} to avoid +% overriding module names by an empty name (meaning no module). % \begin{macrocode} \bool_new:N \l_@@_macro_internal_bool \bool_new:N \l_@@_macro_aux_bool \bool_new:N \l_@@_macro_TF_bool \bool_new:N \l_@@_macro_pTF_bool +\bool_new:N \l_@@_macro_noTF_bool \bool_new:N \l_@@_macro_EXP_bool \bool_new:N \l_@@_macro_rEXP_bool \bool_new:N \l_@@_macro_var_bool +\tl_new:N \l_@@_override_module_tl +\tl_set:Nn \l_@@_override_module_tl { \q_no_value } +\tl_new:N \l_@@_macro_documented_tl % \end{macrocode} % \end{variable} % @@ -856,32 +701,62 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{variable} % -% \begin{variable}[int]{\l_@@_tmpa_tl, \l_@@_tmpb_tl, \l_@@_tmpa_int} +% \begin{variable}[int]{\l_@@_tmpa_tl, \l_@@_tmpb_tl, \l_@@_tmpa_int, \l_@@_tmpa_seq} % Some temporary variables. % \begin{macrocode} \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl \int_new:N \l_@@_tmpa_int +\int_new:N \l_@@_tmpa_seq +% \end{macrocode} +% \end{variable} +% +% \begin{variable}[int]{\l_@@_names_block_tl} +% List of local sequence variables (produced through +% \cs{@@_lseq_name:n}), one for each set of variants in a +% \env{function} or \env{macro} environment. More precisely these +% sequences are named after the base forms, such as \cs{clist_count:n} +% or \cs{clist_count:N} (which are not variants). Each of these +% sequences have the base name (without any signature) as their first +% item, followed by the list of variant's signatures, or +% \cs{scan_stop:} to denote the absence of signature (no colon). +% \begin{macrocode} +\tl_new:N \l_@@_names_block_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}[int]{\g_@@_variants_seq} +% Stores rather temporarily the list of variants (signatures only) of +% a function/macro that is being documented. It is global because we +% need it to keep its value throughout cells of an alignment. +% \begin{macrocode} +\seq_new:N \g_@@_variants_seq % \end{macrocode} % \end{variable} % -% \begin{variable}[int]{\l_@@_functions_block_prop} -% Contains information about the functions to typeset and their -% variants. +% \begin{variable}[int]{\l_@@_names_verb_bool} +% Set to |true| if the main argument of a macro/function environment +% should be used as is, without removing any comma or space. % \begin{macrocode} -\prop_new:N \l_@@_functions_block_prop +\bool_new:N \l_@@_names_verb_bool % \end{macrocode} % \end{variable} % -% \begin{variable}[int]{\l_@@_function_input_seq, \l_@@_macro_input_seq} -% Both the \env{function} and the \env{macro} environments read their -% argument verbatim, then remove percent signs (at the beginning of -% lines), tabs and new lines, convert |_@@| and |@@| by -% |__|\meta{module name} if appropriate, and interpret the result as a -% comma list, which they store in these two sequences. +% \begin{variable}[int]{\l_@@_names_seq} +% List of functions/environments/\ldots{} appearing as arguments of a +% given \env{function} or \env{macro} environment. These are the +% names after conversion of |_@@| and |@@| to |__|\meta{module name} +% and other sanitizing. % \begin{macrocode} -\seq_new:N \l_@@_function_input_seq -\seq_new:N \l_@@_macro_input_seq +\seq_new:N \l_@@_names_seq +% \end{macrocode} +% \end{variable} +% +% \begin{variable}[int]{\g_@@_nested_names_seq} +% Collects all macros in nested \env{macro} environments, to use them +% in the \enquote{End definition} text. +% \begin{macrocode} +\seq_new:N \g_@@_nested_names_seq % \end{macrocode} % \end{variable} % @@ -895,25 +770,23 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{variable} % -% \begin{variable}[int]{\g_@@_function_name_prefix_tl} -% The \enquote{prefix} of the current function is a backslash if the -% function starts with it, and otherwise is empty. -% \begin{macrocode} -\tl_new:N \g_@@_function_name_prefix_tl -% \end{macrocode} -% \end{variable} -% % \begin{variable} -% {\l_@@_index_macro_tl, \l_@@_index_key_tl, \l_@@_index_module_tl} +% { +% \l_@@_index_macro_tl, \l_@@_index_key_tl, +% \l_@@_index_module_tl, \l_@@_index_internal_bool +% } % When analyzing a control sequence found within a \env{macrocode} % environment, \cs{l_@@_index_macro_tl} holds the control sequence % (partially a string), \cs{l_@@_index_key_tl} holds what will be used % as a sort key in the index, and \cs{l_@@_index_module_tl} is the -% subindex in which the control sequence will be listed. +% subindex in which the control sequence will be listed. Finally, +% \cs{l_@@_index_internal_bool} indicates when the control sequence is +% internal and should be indexed in a slightly different subindex. % \begin{macrocode} \tl_new:N \l_@@_index_macro_tl \tl_new:N \l_@@_index_key_tl \tl_new:N \l_@@_index_module_tl +\bool_new:N \l_@@_index_internal_bool % \end{macrocode} % \end{variable} % @@ -941,8 +814,8 @@ Do not distribute a modified version of this file. % indexing commands, and the number of macros so far (including those % from surrounding \env{macro} environments). % \begin{macrocode} -\box_new:N \l_@@_macro_index_box \box_new:N \l_@@_macro_box +\box_new:N \l_@@_macro_index_box \int_new:N \l_@@_macro_int % \end{macrocode} % \end{variable} @@ -951,6 +824,8 @@ Do not distribute a modified version of this file. % { % \l_@@_cmd_tl, % \l_@@_cmd_index_tl, +% \l_@@_cmd_module_tl, +% \l_@@_cmd_noindex_bool, % \l_@@_cmd_replace_bool, % } % Variables used to control the behaviour of \cs{cmd}, \cs{cs} and @@ -958,6 +833,8 @@ Do not distribute a modified version of this file. % \begin{macrocode} \tl_new:N \l_@@_cmd_tl \tl_new:N \l_@@_cmd_index_tl +\tl_new:N \l_@@_cmd_module_tl +\bool_new:N \l_@@_cmd_noindex_bool \bool_new:N \l_@@_cmd_replace_bool % \end{macrocode} % \end{variable} @@ -995,17 +872,40 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{variable} % -% \begin{variable}[int]{\l_@@_no_label_bool} -% This boolean prevents the insertions of \tn{label}s in a -% \env{function} environment. This is only useful when a function's -% documentation appears multiple times, for instance in -% \file{source3body.tex} some examples repeat the documentation from -% actual functions. +% \begin{variable}[int]{\l_@@_function_label_clist, \l_@@_no_label_bool} +% Option of a \env{function} environment which replaces the label that +% would normally be inserted by labels for the given list of control +% sequences. This is only useful to avoid duplicate labels when a +% function's documentation appears multiple times. % \begin{macrocode} +\clist_new:N \l_@@_function_label_clist \bool_new:N \l_@@_no_label_bool % \end{macrocode} % \end{variable} % +% \begin{variable}[int]{\l_@@_date_added_tl, \l_@@_date_updated_tl} +% Values of some options of the \env{function} environment. +% \begin{macrocode} +\tl_new:N \l_@@_date_added_tl +\tl_new:N \l_@@_date_updated_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}[int]{\l_@@_macro_argument_tl} +% Save the argument of a \env{macro} or \env{function} environment for +% use in error messages. +% \begin{macrocode} +\tl_new:N \l_@@_macro_argument_tl +% \end{macrocode} +% \end{variable} +% +% ^^A Bruno: what does the next line do? +% \begin{macrocode} +% \int_new:N \c@CodelineNo +% \end{macrocode} +% +% \subsection{Variants and helpers} +% % \begin{macro}[aux]{\@@_tmpa:w, \@@_tmpb:w} % Auxiliary macros for temporary use. % \begin{macrocode} @@ -1014,9 +914,334 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % -% Bruno: can I delete this next line? +% \begin{macro} +% { +% \seq_set_split:NoV, +% \str_case:fn, +% \tl_count:f, +% \tl_greplace_all:Nxn, +% \tl_greplace_all:Nno, +% \tl_if_head_eq_charcode:oNTF, +% \tl_if_head_eq_charcode:oNT, +% \tl_if_head_eq_charcode:oNF, +% \tl_if_head_eq_meaning:VNF, +% \tl_if_in:noTF, +% \tl_if_in:NoTF, +% \tl_if_in:NoT, +% \tl_if_in:NoF, +% \tl_remove_all:Nx, +% \tl_replace_all:Nxn, +% \tl_replace_all:Nnx, +% \tl_replace_all:Non, +% \tl_replace_all:Nno, +% \tl_replace_once:Noo, +% \tl_to_str:f, +% \tl_to_str:o, +% \prop_get:NxNTF, +% \prop_put:Nxn, +% \prop_gput:NVx, +% } +% A few missing variants. % \begin{macrocode} -% \int_new:N \c@CodelineNo +\cs_generate_variant:Nn \seq_set_split:Nnn { NoV } +\cs_generate_variant:Nn \str_case:nn { fn } +\cs_generate_variant:Nn \tl_count:n { f } +\cs_generate_variant:Nn \tl_greplace_all:Nnn { Nx , Nno } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNTF { o } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { o } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { o } +\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNF { V } +\cs_generate_variant:Nn \tl_if_in:nnTF { no } +\cs_generate_variant:Nn \tl_if_in:NnTF { No } +\cs_generate_variant:Nn \tl_if_in:NnT { No } +\cs_generate_variant:Nn \tl_if_in:NnF { No } +\cs_generate_variant:Nn \tl_remove_all:Nn { Nx } +\cs_generate_variant:Nn \tl_replace_all:Nnn { Nx , Nnx, No , Nno } +\cs_generate_variant:Nn \tl_replace_once:Nnn { Noo } +\cs_generate_variant:Nn \tl_to_str:n { f , o } +\cs_generate_variant:Nn \prop_get:NnNTF { Nx } +\cs_generate_variant:Nn \prop_put:Nnn { Nx } +\cs_generate_variant:Nn \prop_gput:Nnn { NVx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int,TF]{\@@_if_almost_str:n} +% Used to test if the argument of |\cmd| or other macros to be indexed +% is almost a string or not: for instance this will be wrong if |#1| +% contains |\meta{...}|. The surprising |f|-expansion are there to +% cope with the case of |#1| starting with \cs{c_@@_backslash_tl} +% which should be expanded and considered to be \enquote{normal}. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_if_almost_str:n #1 { TF , T , F } + { + \int_compare:nNnTF + { \tl_count:n {#1} } + < { \tl_count:f { \tl_to_str:f {#1} } } + { \prg_return_false: } + { \prg_return_true: } + } +\cs_generate_variant:Nn \@@_if_almost_str:nT { V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_replace_at_at:N} +% \begin{macro}[aux]{\@@_replace_at_at_aux:Nn} +% The goal is to replace |@@| by the current module name. If there is +% no \meta{module~name}, do nothing. Otherwise, sanitize the catcodes +% of |@| and~|_| and replace both |_@@| and |@@| by +% |__|\meta{module~name}. The result contains |_| with category +% code letter because this is what the |macrocode| environment +% expects. Other use cases can apply \cs{tl_to_str:n} if needed. +% Note that we include spaces between the +% |@| in the code below, since it is also processed through the same +% replacement rules. +% \begin{macrocode} +\cs_new_protected:Npn \@@_replace_at_at:N #1 + { + \tl_if_empty:NF \g_@@_module_name_tl + { + \exp_args:NNo \@@_replace_at_at_aux:Nn + #1 \g_@@_module_name_tl + } + } +\cs_new_protected:Npn \@@_replace_at_at_aux:Nn #1#2 + { + \tl_replace_all:Non #1 { \token_to_str:N @ } { @ } + \tl_replace_all:Non #1 { \token_to_str:N _ } { _ } + \tl_replace_all:Nnn #1 { _ @ @ } { _ _ #2 } + \tl_replace_all:Nnn #1 { @ @ } { _ _ #2 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux,rEXP]{\@@_signature_base_form:n} +% \begin{macro}[aux] +% {\@@_signature_base_form_aux:n, \@@_signature_base_form_aux:w} +% Expands to the \enquote{base form} of the signature. For instance, +% given |noxcfvV| it would obtain |nnnNnnn|, or given |ow| it would +% obtain |nw|. The loop stops at the first token that is not +% recognized; the rest is enclosed in \cs{exp_not:n}. +% \begin{macrocode} +\cs_new:Npn \@@_signature_base_form:n #1 + { \@@_signature_base_form_aux:n #1 \q_stop } +\cs_new:Npn \@@_signature_base_form_aux:n #1 + { + \str_case:nnTF {#1} + { + { N } { N } + { c } { N } + { n } { n } + { o } { n } + { f } { n } + { x } { n } + { V } { n } + { v } { n } + } + { \@@_signature_base_form_aux:n } + { \@@_signature_base_form_aux:w #1 } + } +\cs_new:Npn \@@_signature_base_form_aux:w #1 \q_stop + { \exp_not:n {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux]{\@@_predicate_from_base:n} +% Get predicate from a function's base name. The code is not broken +% by functions with no signature. The |n|-type version can be used +% for keys and other non-control sequences. The output after +% |x|-expansion is a string. +% \begin{macrocode} +\cs_new:Npn \@@_predicate_from_base:n #1 + { + \@@_get_function_name:n {#1} + \tl_to_str:n { _p: } + \@@_get_function_signature:n {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_split_function_do:nn, \@@_split_function_do:on} +% \begin{macro}[aux]{\@@_get_function_name:n, \@@_get_function_signature:n} +% \begin{macro}[aux]{\@@_split_function_auxi:w, \@@_split_function_auxii:w} +% Similar to internal functions defined in \pkg{l3basics}, but here we +% operate on strings directly rather than control sequences. +% \begin{macrocode} +\cs_new:Npn \@@_get_function_name:n #1 + { \@@_split_function_do:nn {#1} { \use_i:nnn } } +\cs_new:Npn \@@_get_function_signature:n #1 + { \@@_split_function_do:nn {#1} { \use_ii:nnn } } +\cs_set_protected:Npn \@@_tmpa:w #1 + { + \cs_new:Npn \@@_split_function_do:nn ##1 + { + \exp_after:wN \@@_split_function_auxi:w + \tl_to_str:n {##1} \q_mark \c_true_bool + #1 \q_mark \c_false_bool + \q_stop + } + \cs_new:Npn \@@_split_function_auxi:w + ##1 #1 ##2 \q_mark ##3##4 \q_stop ##5 + { \@@_split_function_auxii:w {##5} ##1 \q_mark \q_stop {##2} ##3 } + \cs_new:Npn \@@_split_function_auxii:w + ##1##2 \q_mark ##3 \q_stop + { ##1 {##2} } + } +\exp_args:No \@@_tmpa:w { \token_to_str:N : } +\cs_generate_variant:Nn \@@_split_function_do:nn { o } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux, rEXP]{\@@_key_get_base:nN} +% Get the base form of a function and store it. As part of getting +% the base form, change trailing |T| or |F| to |TF|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_key_get_base:nN #1#2 + { + \@@_if_almost_str:nTF {#1} + { + \@@_key_get_base_TF:nN {#1} \l_@@_tmpa_tl + \tl_set:Nx #2 + { \@@_split_function_do:on \l_@@_tmpa_tl { \@@_base_form_aux:nnN } } + } + { \tl_set:Nn #2 {#1} } + } +\cs_new:Npx \@@_key_get_base_TF:nN #1#2 + { + \tl_set:Nx #2 { \exp_not:N \tl_to_str:n {#1} \scan_stop: } + \tl_if_in:NnTF #2 { \tl_to_str:n { F } \scan_stop: } + { + \tl_if_in:NnF #2 { \tl_to_str:n { TF } \scan_stop: } + { + \tl_replace_once:Nnn #2 + { \tl_to_str:n { F } \scan_stop: } + { \tl_to_str:n { TF } \scan_stop: } + } + } + { + \tl_replace_once:Nnn #2 + { \tl_to_str:n { T } \scan_stop: } + { \tl_to_str:n { TF } \scan_stop: } + } + \tl_remove_once:Nn #2 { \scan_stop: } + } +\cs_new:Npn \@@_base_form_aux:nnN #1#2#3 + { + \exp_not:n {#1} + \bool_if:NT #3 + { + \token_to_str:N : + \str_if_eq:nnTF { #1 ~ } { \exp_args } + { \exp_not:n {#2} } + { \@@_signature_base_form:n {#2} } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_base_form_signature_do:nnn} +% Do |#2{#1}| if there is no signature, or if |#1| contains two colons +% in a row (this covers the weird function |\::N| and so on). +% Otherwise apply |#3| with the following two arguments: the base form +% of |#1|, and the original signature with an extra pair of braces. +% \begin{macrocode} +\cs_new_protected:Npn \@@_base_form_signature_do:nnn #1#2#3 + { + \@@_split_function_do:nn {#1} + { \@@_base_form_aux:nnnnnN {#1} {#2} {#3} } + } +\cs_new_protected:Npn \@@_base_form_aux:nnnnnN #1#2#3#4#5#6 + { + \bool_if:NTF #6 + { + \tl_if_head_eq_charcode:nNTF {#4} : + { #2 {#1} } + { + \use:x + { + \exp_not:n {#3} + { \@@_base_form_aux:nnN {#4} {#5} #6 } + } + {#4} {#5} + } + } + { #2 {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int, pTF]{\@@_date_compare:nNn} +% \begin{macro}[aux]{\@@_date_compare_aux:nnnNnnn, \@@_date_compare_aux:w} +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_date_compare:nNn #1#2#3 { TF , T , F , p } + { \@@_date_compare_aux:w #1--- \q_mark #2 #3--- \q_stop } +\cs_new:Npn \@@_date_compare_aux:w + #1 - #2 - #3 - #4 \q_mark #5 #6 - #7 - #8 - #9 \q_stop + { + \@@_date_compare_aux:nnnNnnn + { \tl_if_empty:nTF {#1} { 0 } {#1} } + { \tl_if_empty:nTF {#2} { 0 } {#2} } + { \tl_if_empty:nTF {#3} { 0 } {#3} } + #5 + { \tl_if_empty:nTF {#6} { 0 } {#6} } + { \tl_if_empty:nTF {#7} { 0 } {#7} } + { \tl_if_empty:nTF {#8} { 0 } {#8} } + } +\cs_new:Npn \@@_date_compare_aux:nnnNnnn #1#2#3#4#5#6#7 + { + \int_compare:nNnTF {#1} = {#5} + { + \int_compare:nNnTF {#2} = {#6} + { + \int_compare:nNnTF {#3} #4 {#7} + { \prg_return_true: } { \prg_return_false: } + } + { + \int_compare:nNnTF {#2} #4 {#6} + { \prg_return_true: } { \prg_return_false: } + } + } + { + \int_compare:nNnTF {#1} #4 {#5} + { \prg_return_true: } { \prg_return_false: } + } + \use_none:n + \q_stop + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux]{\@@_gprop_name:n, \@@_lseq_name:n} +% We need to keep track of some information about control sequences +% (and other strings) that are being (or have been) documented. Some +% is stored into global props and some into local seqs, whose name +% does not follow conventions: it is \cs[no-index]{g_@@} or +% \cs[no-index]{l_@@} followed by a space and by the string, which can +% be arbitrary. We cannot reasonably use a single big |prop| for +% speed reasons. +% \begin{macrocode} +\cs_new:Npn \@@_gprop_name:n #1 { g_@@ ~ \tl_to_str:n {#1} } +\cs_new:Npn \@@_lseq_name:n #1 { l_@@ ~ \tl_to_str:n {#1} } +% \end{macrocode} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { l3doc } { no-signature-TF } + { Function/macro~'#1'~cannot~be~turned~into~a~conditional. } + { + A~function~or~macro~environment~with~option~pTF,~TF~or~noTF~ + received~the~argument~'#1'.~This~function's~name~has~no~ + ':'~hence~it~is~not~clear~where~to~add~'_p'~or~'TF'.~ + Please~follow~expl3~naming~conventions. + } +\msg_new:nnn { l3doc } { deprecated-function } + { The~deprecated~function(s)~'#1'~should~have~been~removed~on~#2. } % \end{macrocode} % % \subsection{Options and configuration} @@ -1061,7 +1286,8 @@ Do not distribute a modified version of this file. % % \begin{macrocode} \DeclareOption* { \PassOptionsToClass { \CurrentOption } { article } } -\ExecuteOptions { full, a4paper, nocheck, nochecktest, lm-default } +\ExecuteOptions { full, nocheck, nochecktest, lm-default } +\PassOptionsToClass { a4paper } { article } % \end{macrocode} % % Input a local configuration file, if it exists, with a message to the @@ -1141,7 +1367,7 @@ Do not distribute a modified version of this file. % A few more letters are \enquote{private} in a \LaTeX3 programming % environment. % \begin{macrocode} -\cs_gset_nopar:Npn \MakePrivateLetters +\cs_gset:Npn \MakePrivateLetters { \char_set_catcode_letter:N \@ \char_set_catcode_letter:N \_ @@ -1172,6 +1398,40 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % +% \begin{macro}[int]{\ifnot@excluded} +% This function tests whether a macro name stored in +% \tn{macro@namepart} was excluded from indexing by \tn{DoNotIndex}. +% Rather than trying to fix catcodes that come into here, turn +% everything to string catcodes. This is somewhat inefficient as we +% could have ensured that \tn{index@excludelist} has string catcodes +% in the first place. +% \begin{macrocode} +\cs_set_protected:Npn \ifnot@excluded + { + \exp_args:Nxx \expanded@notin + { \c_@@_backslash_tl \tl_to_str:N \macro@namepart , } + { \exp_args:NV \tl_to_str:n \index@excludelist } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pdfstringnewline} +% \begin{macro}[aux]{\@@_pdfstring_newline:w} +% We avoid some hyperref warnings by making |\\| (almost) trivial in +% bookmarks: more precisely it might be used with a star and an +% optional argument, which we thus remove using an \pkg{xparse} +% expandable command. Since there cannot be trailing optional +% arguments, pick up an extra mandatory one and put it back. +% \begin{macrocode} +\cs_new:Npn \pdfstringnewline { : ~ } +\DeclareExpandableDocumentCommand + { \@@_pdfstring_newline:w } { s o m } { \pdfstringnewline #3 } +\pdfstringdefDisableCommands + { \cs_set_eq:NN \\ \@@_pdfstring_newline:w } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Design} % % Increase the text width slightly so that width the standard fonts @@ -1193,7 +1453,7 @@ Do not distribute a modified version of this file. % Customise lists. % \begin{macrocode} \cs_new_eq:NN \@@_oldlist:nn \list -\cs_gset_nopar:Npn \list #1 #2 +\cs_gset:Npn \list #1 #2 { \@@_oldlist:nn {#1} { #2 \dim_zero:N \listparindent } } \setlength \parindent { 2em } \setlength \itemindent { 0pt } @@ -1214,7 +1474,7 @@ Do not distribute a modified version of this file. % Different design and/or structure is called for). % \begin{macrocode} \@addtoreset{section}{part} -\cs_gset_nopar:Npn \l@section #1#2 +\cs_gset:Npn \l@section #1#2 { \ifnum \c@tocdepth >\z@ \addpenalty\@secpenalty @@ -1230,7 +1490,7 @@ Do not distribute a modified version of this file. \endgroup \fi } -\cs_gset_nopar:Npn \l@subsection +\cs_gset:Npn \l@subsection { \@dottedtocline{2}{2.5em}{2.3em} } % #2 = 1.5em % \end{macrocode} % \end{macro} @@ -1273,33 +1533,56 @@ Do not distribute a modified version of this file. % \end{macro} % % \begin{macro}{\cmd, \cs, \tn} -% To work within bookmarks, these commands must be expandable. They -% rely on a common auxiliary \cs{@@_cmd:nn} which receives as +% They rely on a common auxiliary \cs{@@_cmd:nn} which receives as % arguments the options and some tokens whose string representation % starts with a backslash (to support cases such as |\cs{pkg_\ldots}|, % we do not turn the whole argument into a string). % \begin{macrocode} -\DeclareExpandableDocumentCommand \cmd { O{} m } +\DeclareDocumentCommand \cmd { O{} m } { \@@_cmd:no {#1} { \token_to_str:N #2 } } -\DeclareExpandableDocumentCommand \cs { O{} m } +\DeclareDocumentCommand \cs { O{} m } { \@@_cmd:no {#1} { \c_@@_backslash_tl #2 } } -\DeclareExpandableDocumentCommand \tn { O{} m } +\DeclareDocumentCommand \tn { O{} m } { \@@_cmd:no - { index = TeX , replace = false , #1 } + { module = TeX , replace = false , #1 } { \c_@@_backslash_tl #2 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\meta} -% To work within a bookmark, this command must be expandable. +% A document-level command. % \begin{macrocode} -\DeclareExpandableDocumentCommand { \meta } { m } +\DeclareDocumentCommand \meta { m } { \@@_meta:n {#1} } % \end{macrocode} % \end{macro} % +% \begin{macro}[aux] +% { +% \@@_pdfstring_cmd:w, +% \@@_pdfstring_cs:w, +% \@@_pdfstring_meta:w +% } +% To work within a bookmark, these commands must be expandable. +% \begin{macrocode} +\DeclareExpandableDocumentCommand + { \@@_pdfstring_cmd:w } { o m } { \token_to_str:N #2 } +\DeclareExpandableDocumentCommand + { \@@_pdfstring_cs:w } { o m } { \textbackslash \tl_to_str:n {#2} } +\cs_new:Npn \@@_pdfstring_meta:w #1 + { < \tl_to_str:n {#1} > } +\pdfstringdefDisableCommands + { + \cs_set_eq:NN \cmd \@@_pdfstring_cmd:w + \cs_set_eq:NN \cs \@@_pdfstring_cs:w + \cs_set_eq:NN \tn \@@_pdfstring_cs:w + \cs_set_eq:NN \meta \@@_pdfstring_meta:w + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\Arg, \marg, \oarg, \parg} % |\marg{text}| prints \marg{text}, \enquote{mandatory argument}.\\ % |\oarg{text}| prints \oarg{text}, \enquote{optional argument}.\\ @@ -1447,24 +1730,54 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{environment} % -% \subsubsection{Implementing text markup} +% \begin{macro}{\CodedocExplain, \CodedocExplainEXP, \CodedocExplainREXP, \CodedocExplainTF} +% Explanation of stars and |TF| notations, for use in third-party +% packages. +% \begin{macrocode} +\NewDocumentCommand { \CodedocExplain } { } + { \CodedocExplainEXP \ \CodedocExplainREXP \ \CodedocExplainTF } +\NewDocumentCommand { \CodedocExplainEXP } { } + { + \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{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~ + \texttt{f}-type~argument. + } +\NewDocumentCommand { \CodedocExplainREXP } { } + { + \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{rexpstar}{}}% + \@@_typeset_rexp:\ indicates~ + restricted~expandable~functions,~which~can~be~used~within~an~ + \texttt{x}-type~argument~but~cannot~be~fully~expanded~within~an~ + \texttt{f}-type~argument. + } +\NewDocumentCommand { \CodedocExplainTF } { } + { + \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{explTF}{}}% + \@@_typeset_TF:\ indicates~conditional~(\texttt{if})~functions~ + whose~variants~with~\texttt{T},~\texttt{F}~and~\texttt{TF}~ + argument~specifiers~expect~different~ + \enquote{true}/\enquote{false}~branches. + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Implementing text markup} % % Keys for \cs{cmd}, \cs{cs} and \cs{tn}. % \begin{macrocode} \keys_define:nn { l3doc/cmd } { index .tl_set:N = \l_@@_cmd_index_tl , + module .tl_set:N = \l_@@_cmd_module_tl , + no-index .bool_set:N = \l_@@_cmd_noindex_bool , replace .bool_set:N = \l_@@_cmd_replace_bool , } % \end{macrocode} % % \begin{macro}[int]{\@@_cmd:nn, \@@_cmd:no} -% \begin{macro}[aux]{\@@_cmd_aux:nn} -% Within a |pdfstring|, use the second argument directly. Otherwise -% call \cs{@@_cmd_aux:nn}: the indirection through -% \cs{CodedocUnexpandedTokens} and \cs{CodedocUseCs} makes things -% work when they pass through a -% file. Apply the key--value \meta{options}~|#1| after setting some +% Apply the key--value \meta{options}~|#1| after setting some % default values. Then (unless |replace=false|) replace |@@| in~|#2|, % which is a bit tricky: the |_| must be given the catcode expected by % \cs{@@_replace_at_at:N}, but should be reverted to their original @@ -1473,23 +1786,16 @@ Do not distribute a modified version of this file. % \tn{verbatim@font}, after turning it to harmless characters if % needed (and keeping the underscore breakable); in any case, spaces % must be turned into \tn{@xobeysp}. Finally, produce an index entry. +% Indexing is suppressed when \cs{l_@@_cmd_noindex_bool} is true. % \begin{macrocode} -\cs_new:Npn \@@_cmd:nn #1#2 - { - \texorpdfstring - { - \CodedocUnexpandedTokens - { \CodedocUseCs { @@_cmd_aux:nn } {#1} {#2} } - } - {#2} - } -\cs_generate_variant:Nn \@@_cmd:nn { no } -\cs_new_protected:Npn \@@_cmd_aux:nn #1#2 +\cs_new_protected:Npn \@@_cmd:nn #1#2 { + \bool_set_false:N \l_@@_cmd_noindex_bool \bool_set_true:N \l_@@_cmd_replace_bool \tl_set:Nn \l_@@_cmd_index_tl { \q_no_value } + \tl_set:Nn \l_@@_cmd_module_tl { \q_no_value } \keys_set:nn { l3doc/cmd } {#1} - \tl_set:No \l_@@_cmd_tl { \token_to_str:N #2 } + \tl_set:Nn \l_@@_cmd_tl {#2} \bool_if:NT \l_@@_cmd_replace_bool { \tl_set_rescan:Nnn \l_@@_tmpb_tl { } { _ } @@ -1500,9 +1806,7 @@ Do not distribute a modified version of this file. \mode_if_math:T { \mbox } { \verbatim@font - \int_compare:nNnF - { \tl_count:N \l_@@_cmd_tl } - < { \tl_count:f { \tl_to_str:N \l_@@_cmd_tl } } + \@@_if_almost_str:VT \l_@@_cmd_tl { \tl_set:Nx \l_@@_cmd_tl { \tl_to_str:N \l_@@_cmd_tl } \tl_replace_all:Non \l_@@_cmd_tl @@ -1511,23 +1815,31 @@ Do not distribute a modified version of this file. \tl_replace_all:Nnn \l_@@_cmd_tl { ~ } { \@xobeysp } \l_@@_cmd_tl } - \exp_args:No \@@_key_get:n { \l_@@_cmd_tl } - \quark_if_no_value:NF \l_@@_cmd_index_tl - { \tl_set_eq:NN \l_@@_index_module_tl \l_@@_cmd_index_tl } - \@@_special_index_module:ooon - { \l_@@_index_key_tl } - { \l_@@_index_macro_tl } - { \l_@@_index_module_tl } - { } + \bool_if:NF \l_@@_cmd_noindex_bool + { + \quark_if_no_value:NF \l_@@_cmd_index_tl + { \tl_set_eq:NN \l_@@_cmd_tl \l_@@_cmd_index_tl } + \exp_args:No \@@_key_get:n { \l_@@_cmd_tl } + \quark_if_no_value:NF \l_@@_cmd_module_tl + { + \tl_set:Nx \l_@@_index_module_tl + { \tl_to_str:N \l_@@_cmd_module_tl } + } + \@@_special_index_module:ooonN + { \l_@@_index_key_tl } + { \l_@@_index_macro_tl } + { \l_@@_index_module_tl } + { } + \l_@@_index_internal_bool + } } +\cs_generate_variant:Nn \@@_cmd:nn { no } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro} % { % \@@_meta:n, -% \@@_meta_aux:n, % \@@_ensuremath_sb:n, % \@@_meta_original:n % } @@ -1538,16 +1850,7 @@ Do not distribute a modified version of this file. % \cs{@@_ensuremath_sb:n} (which creates math subscripts), then runs % the code used for \tn{meta} in \pkg{doc.sty}. % \begin{macrocode} -\cs_new:Npn \@@_meta:n #1 - { - \texorpdfstring - { - \CodedocUnexpandedTokens - { \CodedocUseCs { @@_meta_aux:n } {#1} } - } - { < #1 > } - } -\cs_new_protected:Npn \@@_meta_aux:n #1 +\cs_new_protected:Npn \@@_meta:n #1 { \tl_set:Nn \l_@@_tmpa_tl {#1} \tl_map_inline:nn @@ -1580,25 +1883,257 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % +% \subsubsection{Common between \env{macro} and \env{function}} +% +% \begin{macro} +% { +% \@@_typeset_exp:, \@@_typeset_rexp:, +% \@@_typeset_TF:, \@@_typeset_aux:n +% } +% Used by \cs{@@_macro_single:nNN} and in the \env{function} environment +% to typeset conditionals and auxiliary functions. +% \begin{macrocode} +\cs_new_protected:Npn \@@_typeset_exp: + { \hyperlink{expstar} {$\star$} } +\cs_new_protected:Npn \@@_typeset_rexp: + { \hyperlink{rexpstar} {\ding{73}} } % hollow star +\cs_new_protected:Npn \@@_typeset_TF: + { + \hyperlink{explTF} + { + \color{black} + \itshape TF + \makebox[0pt][r] + { + \color{red} + \underline { \phantom{\itshape TF} \kern-0.1em } + } + } + } +\cs_new_protected:Npn \@@_typeset_aux:n #1 + { + { \color[gray]{0.7} #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% {\@@_get_hyper_target:nN, \@@_get_hyper_target:oN, \@@_get_hyper_target:xN} +% Create a \pkg{hyperref} anchor from a macro name~|#1| and stores it +% in the token list variable~|#2|. For instance, |\prg_replicate:nn| +% gives |doc/function//prg/replicate:nn|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_get_hyper_target:nN #1#2 + { + \tl_set:Nx #2 { \tl_to_str:n {#1} } + \tl_replace_all:Nxn #2 { \iow_char:N \_ } { / } + \tl_remove_all:Nx #2 { \iow_char:N \\ } + \tl_put_left:Nn #2 { doc/function// } + } +\cs_generate_variant:Nn \@@_get_hyper_target:nN { o , x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_names_get_seq:nN} +% The argument~|#1| (argument of a |function| or |macro| environment) +% has catcodes $10$ (space), $12$ (other) and $13$ (active). Sanitize +% catcodes. If the |verb| option was used, output a one-item +% sequence. Otherwise, remove any \enquote{\%} character at the +% beginning of a line. Remove tabs and newlines. Finally, convert +% |_@@| and |@@| to |__|\meta{module name} (if it is non-empty). At +% this point, \cs{l_@@_tmpa_tl} contains a comma-delimited list of +% names, where |@| and~|_| have category code letter. Turn it to a +% string, parse it as a comma-delimited list (in particular this +% removes spaces), and output a sequence of function/macro names. +% \begin{macrocode} +\cs_new_protected:Npn \@@_names_get_seq:nN #1#2 + { + \tl_set:Nx \l_@@_tmpa_tl { \tl_to_str:n {#1} } + \bool_if:NTF \l_@@_names_verb_bool + { + \seq_clear:N #2 + \seq_put_right:NV #2 \l_@@_tmpa_tl + } + { + \tl_remove_all:Nx \l_@@_tmpa_tl + { \iow_char:N \^^M \iow_char:N \% } + \tl_remove_all:Nx \l_@@_tmpa_tl { \tl_to_str:n { ^ ^ A } } + \tl_remove_all:Nx \l_@@_tmpa_tl { \iow_char:N \^^I } + \tl_remove_all:Nx \l_@@_tmpa_tl { \iow_char:N \^^M } + \@@_replace_at_at:N \l_@@_tmpa_tl + \exp_args:NNx \seq_set_from_clist:Nn #2 + { \tl_to_str:N \l_@@_tmpa_tl } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_names_parse:, \@@_names_parse_one:n} +% The goal is to group variants together. We populate +% \cs{l_@@_names_block_tl} with local sequence variable named with +% \cs{@@_lseq_name:n} after the base forms. When encountering a new +% base form, set the corresponding local sequence to hold the +% \meta{base name} (stripped of the signature) and add the local +% sequence to the list \cs{l_@@_names_block_tl}. In all cases append +% the signature to the local sequence, which thus takes the form +% \meta{base name}, \meta{signature_1}, \meta{signature_2} and so on. +% If the original function had no signature (no colon) then use +% \cs{scan_stop:} as the signature (there can be no variant). We +% special case commands |#1| starting with |\::|, namely weird +% functions named |\::N| and the like. +% \begin{macrocode} +\cs_new_protected:Npn \@@_names_parse: + { + \tl_clear:N \l_@@_names_block_tl + \seq_map_function:NN + \l_@@_names_seq + \@@_names_parse_one:n + } +\cs_new_protected:Npn \@@_names_parse_one:n #1 + { + \@@_split_function_do:nn {#1} + { \@@_names_parse_one_aux:nnNn } + {#1} + } +\cs_new_protected:Npn \@@_names_parse_one_aux:nnNn #1#2#3#4 + { + \bool_if:NTF #3 + { + \tl_if_head_eq_charcode:nNTF {#2} : + { \@@_names_parse_aux:nnn {#4} {#4} { \scan_stop: } } + { + \exp_args:Nx \@@_names_parse_aux:nnn + { \@@_base_form_aux:nnN {#1} {#2} #3 } + {#1} {#2} + } + } + { + \bool_if:NT \l_@@_macro_TF_bool + { \msg_error:nnx { l3doc } { no-signature-TF } {#4} } + \@@_names_parse_aux:nnn {#4} {#4} { \scan_stop: } + } + } +\cs_new_protected:Npn \@@_names_parse_aux:nnn #1 + { \exp_args:Nc \@@_names_parse_aux:Nnn { \@@_lseq_name:n {#1} } } +\cs_new_protected:Npn \@@_names_parse_aux:Nnn #1#2#3 + { + \tl_if_in:NnF \l_@@_names_block_tl {#1} + { + \tl_put_right:Nn \l_@@_names_block_tl {#1} + \seq_clear_new:N #1 + \seq_put_right:Nn #1 {#2} + } + \seq_put_right:Nn #1 {#3} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_names_typeset:} +% \begin{macro}[aux]{\@@_names_typeset_auxi:n} +% This code is in particular used when typesetting function names in a +% \env{function} environment. The mapping to \cs{l_@@_names_block_tl} +% cannot use \cs{tl_map_inline:Nn} because the code following |\\| +% would not be expandable, thus breaking \tn{bottomrule}. +% +% Call \cs{@@_names_typeset_auxi:n} on each local sequence (which +% holds a set of variants). The first step is to pop the base form +% and change spaces to category other so +% that they get displayed eventually. Then store the variants in +% \cs{g_@@_variants_seq}, remove the first, which will be displayed +% more prominently, and reconstruct the actual name, passing it to +% \cs{@@_names_typeset_auxii:n}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_names_typeset: + { + \tl_map_function:NN \l_@@_names_block_tl + \@@_names_typeset_auxi:n + } +\cs_new_protected:Npn \@@_names_typeset_auxi:n #1 + { + \seq_pop:NN #1 \l_@@_tmpa_tl + \tl_gset_eq:NN \g_@@_base_name_tl \l_@@_tmpa_tl + \tl_greplace_all:Nno \g_@@_base_name_tl + { ~ } { \c_catcode_other_space_tl } + \seq_get:NN #1 \l_@@_tmpa_tl + \str_if_eq_x:nnTF { \l_@@_tmpa_tl } { \scan_stop: } + { + \seq_gclear:N \g_@@_variants_seq + \@@_names_typeset_auxii:x { \g_@@_base_name_tl } + } + { + \seq_gset_eq:NN \g_@@_variants_seq #1 + \seq_gpop:NN \g_@@_variants_seq \l_@@_tmpb_tl + \@@_names_typeset_auxii:x + { \g_@@_base_name_tl : \l_@@_tmpb_tl } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux] +% {\@@_names_typeset_auxii:n, \@@_names_typeset_auxii:x} +% In case the option |pTF| was given, typeset predicates before the +% |TF| functions. In case the option |noTF| was given, typeset the +% non-|TF| function as well. Pass the relevant boolean in both cases +% to control whether to append |TF|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_names_typeset_auxii:n #1 + { + \bool_if:NT \l_@@_macro_pTF_bool + { + \@@_names_typeset_block:xN + { \@@_predicate_from_base:n {#1} } + \c_false_bool + } + \bool_if:NT \l_@@_macro_noTF_bool + { \@@_names_typeset_block:nN {#1} \c_false_bool } + \@@_names_typeset_block:nN {#1} \l_@@_macro_TF_bool + } +\cs_generate_variant:Nn \@@_names_typeset_auxii:n { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_names_typeset_block:nN, \@@_names_typeset_block:xN} +% Names in \env{function} and \env{macro} environments are typeset +% differently. To distinguish the two note that +% \cs{l_@@_nested_macro_int} is at least one when in an \env{macro} +% environment (we assume \env{function} is not nested inside it). A +% block is a function with all its variants. +% \begin{macrocode} +\cs_new_protected:Npn \@@_names_typeset_block:nN + { + \int_compare:nNnTF \l_@@_nested_macro_int = 0 + { \@@_typeset_function_block:nN } + { \@@_macro_typeset_block:nN } + } +\cs_generate_variant:Nn \@@_names_typeset_block:nN { x } +% \end{macrocode} +% \end{macro} +% % \subsubsection{The \env{function} environment} % % \begin{macrocode} \keys_define:nn { l3doc/function } { + TF .value_forbidden:n = true , TF .code:n = { \bool_set_true:N \l_@@_macro_TF_bool } , + EXP .value_forbidden:n = true , EXP .code:n = { \bool_set_true:N \l_@@_macro_EXP_bool \bool_set_false:N \l_@@_macro_rEXP_bool } , + rEXP .value_forbidden:n = true , rEXP .code:n = { \bool_set_false:N \l_@@_macro_EXP_bool \bool_set_true:N \l_@@_macro_rEXP_bool } , + pTF .value_forbidden:n = true , pTF .code:n = { \bool_set_true:N \l_@@_macro_pTF_bool @@ -1606,13 +2141,43 @@ Do not distribute a modified version of this file. \bool_set_true:N \l_@@_macro_EXP_bool \bool_set_false:N \l_@@_macro_rEXP_bool } , + noTF .value_forbidden:n = true , + noTF .code:n = + { + \bool_set_true:N \l_@@_macro_noTF_bool + \bool_set_true:N \l_@@_macro_TF_bool + } , added .tl_set:N = \l_@@_date_added_tl , updated .tl_set:N = \l_@@_date_updated_tl , + deprecated .code:n = { \@@_deprecated_on:n {#1} } , tested .code:n = { } , - no-label .bool_set:N = \l_@@_no_label_bool , + label .code:n = + { + \clist_set:Nn \l_@@_function_label_clist {#1} + \bool_set_true:N \l_@@_no_label_bool + } , + verb .value_forbidden:n = true , + verb .bool_set:N = \l_@@_names_verb_bool , + module .tl_set:N = \l_@@_override_module_tl , } % \end{macrocode} % +% \begin{macro}[aux]{\@@_deprecated_on:n} +% Complain if a deprecated function should have been removed earlier. +% In any case, mark it as internal to suppress the text +% \enquote{documented on page \ldots{}}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_deprecated_on:n #1 + { + \@@_date_compare:nNnT {#1} < { \tex_year:D / \tex_month:D / \tex_day:D } + { + \msg_error:nnxx { l3doc } { deprecated-function } + { \tl_to_str:N \l_@@_macro_argument_tl } {#1} + } + \bool_set_true:N \l_@@_macro_internal_bool + } +% \end{macrocode} +% \end{macro} % % \begin{macro}[int]{\@@_function:nnw} % \begin{arguments} @@ -1626,7 +2191,7 @@ Do not distribute a modified version of this file. % Initialize some variables. Parse the key--value list. Clean up the % list of functions, then go through them to extract some data. After % this, typeset the function names in the coffin -% \cs{l_@@_names_coffin} and measure it to know if it fits in the +% \cs{l_@@_functions_coffin} and measure it to know if it fits in the % margin. Finally, start a vertical coffin for the main part of the % environment. This coffin stops when the environment ends, then all % the pieces are assembled into a single coffin, which is typeset. @@ -1635,13 +2200,15 @@ Do not distribute a modified version of this file. { \@@_function_typeset_start: \@@_function_init: + \tl_set:Nn \l_@@_macro_argument_tl {#2} \keys_set:nn { l3doc/function } {#1} - \@@_verb_get_seq:nN {#2} \l_@@_function_input_seq - \@@_function_parse: + \@@_names_get_seq:nN {#2} \l_@@_names_seq + \@@_names_parse: \@@_function_typeset: + \@@_function_reset: \@@_function_descr_start:w } -\cs_new_protected_nopar:Npn \@@_function_end: +\cs_new_protected:Npn \@@_function_end: { \@@_function_descr_stop: \@@_function_assemble: @@ -1658,12 +2225,11 @@ Do not distribute a modified version of this file. % scene. Further code typesets a coffin, so we end the paragraph and % allow a page break. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_function_typeset_start: +\cs_new_protected:Npn \@@_function_typeset_start: { \par \bigskip \noindent - \phantomsection } -\cs_new_protected_nopar:Npn \@@_function_typeset_stop: +\cs_new_protected:Npn \@@_function_typeset_stop: { \par \allowbreak @@ -1682,102 +2248,46 @@ Do not distribute a modified version of this file. \coffin_clear:N \l_@@_descr_coffin \box_gclear:N \g_@@_syntax_box \coffin_clear:N \l_@@_syntax_coffin - \coffin_clear:N \l_@@_names_coffin + \coffin_clear:N \l_@@_functions_coffin \bool_set_false:N \l_@@_macro_TF_bool \bool_set_false:N \l_@@_macro_pTF_bool + \bool_set_false:N \l_@@_macro_noTF_bool \bool_set_false:N \l_@@_macro_EXP_bool \bool_set_false:N \l_@@_macro_rEXP_bool \bool_set_false:N \l_@@_no_label_bool + \bool_set_false:N \l_@@_names_verb_bool + \clist_clear:N \l_@@_function_label_clist + \tl_set:Nn \l_@@_override_module_tl { \q_no_value } \char_set_catcode_active:N \< - \cs_set_protected_nopar:Npn < ##1 > { \meta {##1} } + \cs_set_protected:Npn < ##1 > { \meta {##1} } } \group_end: % \end{macrocode} % \end{macro} % -% \begin{macro}[aux] -% { -% \@@_function_parse:, -% \@@_function_parse_one:n, -% \@@_function_parse_cs_aux:nnN -% } -% The idea here is to populate \cs{l_@@_functions_block_prop} with -% information about the functions being typeset and their variants. -% The property list uses a specific format: the keys contained are the -% function \enquote{names} (stripped of signature) with values -% specified by a comma-separated list of (braced) signatures: -% \begin{center} -% |> {my_function} => {| \meta{sig_1} |,| \meta{sig_2} |, ... }| -% \end{center} -% In the case where the function has no signature (no colon), we use -% a \meta{sig} equal to \cs{scan_stop:}. -% This somewhat arcane syntax is chosen to distinguish between all -% variants of control sequence that may be being documented -% here. (With or without \pkg{expl3} function syntax.) -% -% If |#1| does not start with |\| then the \enquote{name prefix} is -% empty and we store \cs{scan_stop:} as the value for the key |#1|, not -% bothering with variants. If instead |#1| starts with |\| then the -% \enquote{name prefix} is |\| and we omit the first character of |#1| -% subsequently. If the next character is |:| then we have one of the -% weird functions named |\::N| and so on, and we ignore variants, -% putting \cs{scan_stop:} directly as the value for the key |::N|. -% Otherwise, we have a regular control sequence, which we decompose -% using \cs{@@_function_parse_cs_aux:nnN}. -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_function_parse: - { - \seq_map_function:NN - \l_@@_function_input_seq - \@@_function_parse_one:n - } -\cs_new_protected:Npn \@@_function_parse_one:n #1 - { - \tl_if_head_eq_charcode:nNTF {#1} \c_@@_backslash_token - { - \tl_gset_eq:NN \g_@@_function_name_prefix_tl \c_@@_backslash_tl - \exp_args:No \tl_if_head_eq_charcode:nNTF { \use_none:n #1 } : - { - \prop_put:Nxn \l_@@_functions_block_prop - { \use_none:n #1 } { \scan_stop: } - } - { - \exp_args:Nc \__cs_split_function:NN { \use_none:n #1 } - \@@_function_parse_cs_aux:nnN - } - } - { - \tl_gclear:N \g_@@_function_name_prefix_tl - \prop_put:Nnn \l_@@_functions_block_prop {#1} { \scan_stop: } - } - } -\cs_new_protected:Npn \@@_function_parse_cs_aux:nnN #1#2#3 +% \begin{macro}[aux]{\@@_function_reset:} +% Clear some variables. +% \begin{macrocode} +\cs_new_protected:Npn \@@_function_reset: { - \prop_get:NnNF - \l_@@_functions_block_prop {#1} \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \prop_put:Nnx \l_@@_functions_block_prop {#1} - { - \l_@@_tmpb_tl , - \bool_if:NTF #3 { {#2} } { \scan_stop: } - } + \tl_set:Nn \l_@@_override_module_tl { \q_no_value } } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_function_typeset:} -% Typeset in the coffin \cs{l_@@_names_coffin} the functions listed in -% \cs{l_@@_functions_block_prop} and the relevant dates, then set +% Typeset in the coffin \cs{l_@@_functions_coffin} the functions listed in +% \cs{l_@@_names_block_tl} and the relevant dates, then set % \cs{l_@@_long_name_bool} to be \texttt{true} if this coffin is % larger than the available width in the margin. The function -% \cs{@@_typeset_names:} is quite involved hence given later. +% \cs{@@_typeset_functions:} is quite involved hence given later. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_function_typeset: +\cs_new_protected:Npn \@@_function_typeset: { \dim_zero:N \l_@@_trial_width_dim - \hcoffin_set:Nn \l_@@_names_coffin { \@@_typeset_names: } + \hcoffin_set:Nn \l_@@_functions_coffin { \@@_typeset_functions: } \dim_set:Nn \l_@@_trial_width_dim - { \box_wd:N \l_@@_names_coffin } + { \box_wd:N \l_@@_functions_coffin } \bool_set:Nn \l_@@_long_name_bool { \dim_compare_p:nNn \l_@@_trial_width_dim > \marginparwidth } } @@ -1792,12 +2302,12 @@ Do not distribute a modified version of this file. % \env{function} environment. This is closed by \cs{@@_function_end:} % (the end of a \env{function} environment). % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_function_descr_start:w +\cs_new_protected:Npn \@@_function_descr_start:w { \vcoffin_set:Nnw \l_@@_descr_coffin { \textwidth } \noindent \ignorespaces } -\cs_new_protected_nopar:Npn \@@_function_descr_stop: +\cs_new_protected:Npn \@@_function_descr_stop: { \vcoffin_set_end: } % \end{macrocode} % \end{macro} @@ -1809,7 +2319,7 @@ Do not distribute a modified version of this file. % coffin. The relative positions depend on whether the names coffin % fits in the margin. Then typeset the combination. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_function_assemble: +\cs_new_protected:Npn \@@_function_assemble: { \hcoffin_set:Nn \l_@@_syntax_coffin { \box_use:N \g_@@_syntax_box } @@ -1821,7 +2331,7 @@ Do not distribute a modified version of this file. {0pt} {0pt} \coffin_join:NnnNnnnn \l_@@_output_coffin {l} {t} - \l_@@_names_coffin {r} {t} + \l_@@_functions_coffin {r} {t} {-\marginparsep} {0pt} \coffin_join:NnnNnnnn \l_@@_output_coffin {l} {b} @@ -1842,7 +2352,7 @@ Do not distribute a modified version of this file. {0pt} {-\medskipamount} \coffin_join:NnnNnnnn \l_@@_output_coffin {l} {t} - \l_@@_names_coffin {r} {t} + \l_@@_functions_coffin {r} {t} {-\marginparsep} {0pt} \coffin_typeset:Nnnnn \l_@@_output_coffin {\l_@@_syntax_coffin-l} {\l_@@_syntax_coffin-T} @@ -1852,20 +2362,24 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_typeset_names:} -% This function builds the \cs{l_@@_names_coffin} by typesetting the +% \begin{macro}[aux]{\@@_typeset_functions:} +% This function builds the \cs{l_@@_functions_coffin} by typesetting the % function names (with variants) and the relevant dates in a % \env{tabular} environment. The use of rules \tn{toprule}, % \tn{midrule} and \tn{bottomrule} requires whatever lies between the % last |\\| and the rule to be expandable, making our lives a bit % complicated. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_typeset_names: +\cs_new_protected:Npn \@@_typeset_functions: { \small\ttfamily - \begin{tabular} { @{} l @{} r @{} } + \HD@savedestfalse + \HD@target + \Hy@MakeCurrentHref { HD. \int_use:N \c@HD@hypercount } + \begin{tabular} [t] { @{} l @{} >{\hspace{\tabcolsep}} r @{} } \toprule - \@@_typeset_functions: + \@@_function_extra_labels: + \@@_names_typeset: \@@_typeset_dates: \bottomrule \end{tabular} @@ -1874,152 +2388,54 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_typeset_functions:} -% \begin{macro}[aux] -% {\@@_typeset_functions_auxi:nn, \@@_typeset_functions_auxii:nn} -% \begin{arguments} -% \item Function/macro/variable name (stripped of signature in the -% first case, if any) -% \item Comma-list containing information about the signature -% variants being documented (if any) -% \end{arguments} -% The mapping to \cs{l_@@_functions_block_prop} cannot use -% \cs{prop_map_inline:Nn} because the code following |\\| would not be -% expandable, thus breaking \tn{bottomrule}. The loop goes as -% follows: go through the list of variants |#2|, and collect them by -% \enquote{base form} in a \cs{l_@@_variants_prop} whose keys are the -% base form and whose values are the variants which can be obtained -% from that base form using \cs{cs_generate_variant:Nn}. Then start a -% nested loop through these base forms, calling -% \cs{@@_typeset_functions_auxii:nn}. This auxiliary does not care -% about the base form. It stores the variants it receives in -% \cs{g_@@_variants_clist}, remove the first, which will be displayed -% more prominently, and reconstructs its actual name, passing it to -% the \cs{@@_typeset_functions_auxiii:N} auxiliary. -% -% Braces around |##1| are crucial since this item can be empty. -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_typeset_functions: - { - \prop_map_function:NN \l_@@_functions_block_prop - \@@_typeset_functions_auxi:nn - } -\cs_new_protected:Npn \@@_typeset_functions_auxi:nn #1#2 - { - \tl_gset:Nn \g_@@_base_name_tl {#1} - \prop_clear:N \l_@@_variants_prop - \clist_map_inline:nn {#2} - { - \tl_set:Nx \l_@@_tmpa_tl - { \@@_signature_base_form:n {##1} } - \prop_get:NoNTF \l_@@_variants_prop - \l_@@_tmpa_tl \l_@@_tmpb_tl - { \tl_put_right:Nn \l_@@_tmpb_tl { , {##1} } } - { \tl_set:Nn \l_@@_tmpb_tl { {##1} } } - \prop_put:Noo \l_@@_variants_prop - \l_@@_tmpa_tl \l_@@_tmpb_tl - } - \prop_map_function:NN \l_@@_variants_prop - \@@_typeset_functions_auxii:nn - } -\cs_new_protected:Npn \@@_typeset_functions_auxii:nn #1#2 - { - \clist_gset:Nn \g_@@_variants_clist {#2} - \clist_gpop:NN \g_@@_variants_clist \l_@@_tmpb_tl - \exp_args:Nc \@@_typeset_functions_auxiii:N - { - \g_@@_base_name_tl - \exp_last_unbraced:Nf \token_if_eq_meaning:NNF - { \tl_head:f { \l_@@_tmpb_tl ? } } - \scan_stop: - { : \l_@@_tmpb_tl } - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[aux]{\@@_typeset_functions_auxiii:N} +% ^^A TODO: collect all index targets from a given function environment in a box and stick it at the top. +% \begin{macro}[int] +% {\@@_typeset_function_block:nN, \@@_typeset_function_block:xN} +% \begin{macro}[aux]{\@@_function_index:n, \@@_function_index:x} +% |#1| is a csname, |#2| a boolean indicating whether to add |TF| or not. % \begin{macrocode} -\cs_new_protected:Npn \@@_typeset_functions_auxiii:N #1 +\cs_new_protected:Npn \@@_typeset_function_block:nN #1#2 { - \bool_if:NT \l_@@_macro_pTF_bool - { - \tl_set:Nx \l_@@_pTF_name_tl - { \@@_predicate_from_base:N #1 } - \@@_function_index:x { \l_@@_pTF_name_tl } - } \@@_function_index:x - { - \cs_to_str:N #1 - \bool_if:NT \l_@@_macro_TF_bool { \tl_to_str:n {TF} } - } - \bool_if:NT \l_@@_macro_pTF_bool - { - \exp_args:Nc \@@_typeset_function_block:NN - { \l_@@_pTF_name_tl } \c_false_bool - } - \@@_typeset_function_block:NN #1 \l_@@_macro_TF_bool - } -\cs_new_protected:Npn \@@_function_index:x #1 - { - \tl_set:Nx \l_@@_tmpa_tl - { \g_@@_function_name_prefix_tl #1 } - \seq_gput_right:No \g_doc_functions_seq { \l_@@_tmpa_tl } - \@@_special_index:on { \l_@@_tmpa_tl } { usage } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\@@_typeset_function_block:NN} -% The first argument is a control sequence, the second a boolean which -% controls whether to typeset |TF| or not. -% \begin{macrocode} -\cs_new_protected:Npn \@@_typeset_function_block:NN #1#2 - { - \@@_function_label:x - { \g_@@_function_name_prefix_tl \cs_to_str:N #1 } - \g_@@_function_name_prefix_tl \cs_to_str:N #1 + { #1 \bool_if:NT #2 { \tl_to_str:n {TF} } } + \@@_function_label:xN {#1} #2 + #1 \bool_if:NT #2 { \@@_typeset_TF: } \@@_typeset_expandability: - \clist_if_empty:NF \g_@@_variants_clist - { \@@_typeset_variant_list:NN #1#2 } + \seq_if_empty:NF \g_@@_variants_seq + { \@@_typeset_variant_list:nN {#1} #2 } \\ } +\cs_generate_variant:Nn \@@_typeset_function_block:nN { x } +\cs_new_protected:Npn \@@_function_index:n #1 + { + \seq_gput_right:Nn \g_doc_functions_seq {#1} + \@@_special_index:nn {#1} { usage } + } +\cs_generate_variant:Nn \@@_function_index:n { x } % \end{macrocode} % % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_typeset_expandability: +\cs_new_protected:Npn \@@_typeset_expandability: { & - \bool_if:NT \l_@@_macro_EXP_bool - { - \hspace{\tabcolsep} - \hyperlink{expstar} {$\star$} - } - \bool_if:NT \l_@@_macro_rEXP_bool - { - \hspace{\tabcolsep} - \hyperlink{rexpstar} {\ding{73}} % hollow star - } + \bool_if:NT \l_@@_macro_EXP_bool { \@@_typeset_exp: } + \bool_if:NT \l_@@_macro_rEXP_bool { \@@_typeset_rexp: } } % \end{macrocode} % +% |#1| is the function, |#2| whether to add |TF|. % \begin{macrocode} -\cs_new_protected:Npn \@@_typeset_variant_list:NN #1#2 +\cs_new_protected:Npn \@@_typeset_variant_list:nN #1#2 { \\ - \@@_typeset_aux:n - { - \g_@@_function_name_prefix_tl - \__cs_get_function_name:N #1 - } + \@@_typeset_aux:n { \@@_get_function_name:n {#1} } : - \int_compare:nTF { \clist_count:N \g_@@_variants_clist == 1 } - { \clist_use:Nn \g_@@_variants_clist { } } + \int_compare:nTF { \seq_count:N \g_@@_variants_seq == 1 } + { \seq_use:Nn \g_@@_variants_seq { } } { \textrm( - \clist_use:Nn \g_@@_variants_clist { \textrm| } + \seq_use:Nn \g_@@_variants_seq { \textrm| } \textrm) } \bool_if:NT #2 { \@@_typeset_TF: } @@ -2027,30 +2443,44 @@ Do not distribute a modified version of this file. } % \end{macrocode} % -% TODO: understand whether we need one more boolean to only -% put labels if the whole document is typeset. +% |#1| is the function name, |#2| whether to add |TF|. % \begin{macrocode} -\cs_new_protected:Npn \@@_function_label:n #1 +\cs_new_protected:Npn \@@_function_extra_labels: + { + \bool_if:NT \l_@@_no_label_bool + { + \clist_map_inline:Nn \l_@@_function_label_clist + { + \@@_get_hyper_target:oN { \token_to_str:N ##1 } + \l_@@_tmpa_tl + \exp_args:No \label { \l_@@_tmpa_tl } + } + } + } +\cs_new_protected:Npn \@@_function_label:nN #1#2 { - % \bool_if:NT \g_@@_typeset_implementation_bool - % { \bool_if:NF \l_@@_no_label_bool { - \@@_get_hyper_target:nN {#1} \l_@@_tmpa_tl + \@@_get_hyper_target:xN + { + \exp_not:n {#1} + \bool_if:NT #2 { \tl_to_str:n {TF} } + } + \l_@@_tmpa_tl \exp_args:No \label { \l_@@_tmpa_tl } } - % } } -\cs_generate_variant:Nn \@@_function_label:n { x } +\cs_generate_variant:Nn \@@_function_label:nN { x } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}[internal]{\@@_typeset_dates:} % To display metadata for when functions are added/modified. % This function must be expandable since it produces rules for use in % alignments. % \begin{macrocode} -\cs_new_nopar:Npn \@@_typeset_dates: +\cs_new:Npn \@@_typeset_dates: { \bool_if:nF { @@ -2090,7 +2520,7 @@ Do not distribute a modified version of this file. \arrayrulecolor{white} \begin{tabular} { @{} l @{} } \toprule - \begin{minipage}{\l_@@_syntax_dim} + \begin{minipage}[t]{\l_@@_syntax_dim} \raggedright \obeyspaces \obeylines @@ -2107,22 +2537,27 @@ Do not distribute a modified version of this file. % % \subsubsection{The \env{macro} environment} % -% Keyval for the \env{macro} environment. TODO: use -% |.value_forbidden:|. TODO: provide document command for talking about -% keys. +% Keyval for the \env{macro} environment. +% TODO: provide document command for documenting keys. % \begin{macrocode} \keys_define:nn { l3doc/macro } { + aux .value_forbidden:n = true , aux .code:n = { \bool_set_true:N \l_@@_macro_aux_bool } , + internal .value_forbidden:n = true , internal .code:n = { \bool_set_true:N \l_@@_macro_internal_bool } , + int .value_forbidden:n = true , int .code:n = { \bool_set_true:N \l_@@_macro_internal_bool } , + var .value_forbidden:n = true , var .code:n = { \bool_set_true:N \l_@@_macro_var_bool } , + TF .value_forbidden:n = true , TF .code:n = { \bool_set_true:N \l_@@_macro_TF_bool } , + pTF .value_forbidden:n = true , pTF .code:n = { \bool_set_true:N \l_@@_macro_TF_bool @@ -2130,11 +2565,19 @@ Do not distribute a modified version of this file. \bool_set_true:N \l_@@_macro_EXP_bool \bool_set_false:N \l_@@_macro_rEXP_bool } , + noTF .value_forbidden:n = true , + noTF .code:n = + { + \bool_set_true:N \l_@@_macro_TF_bool + \bool_set_true:N \l_@@_macro_noTF_bool + } , + EXP .value_forbidden:n = true , EXP .code:n = { \bool_set_true:N \l_@@_macro_EXP_bool \bool_set_false:N \l_@@_macro_rEXP_bool } , + rEXP .value_forbidden:n = true , rEXP .code:n = { \bool_set_false:N \l_@@_macro_EXP_bool @@ -2146,6 +2589,10 @@ Do not distribute a modified version of this file. } , added .code:n = {} , % TODO updated .code:n = {} , % TODO + deprecated .code:n = { \@@_deprecated_on:n {#1} } , + verb .bool_set:N = \l_@@_names_verb_bool , + module .tl_set:N = \l_@@_override_module_tl , + documented-as .tl_set:N = \l_@@_macro_documented_tl , } % \end{macrocode} % @@ -2154,17 +2601,22 @@ Do not distribute a modified version of this file. % comma-list of \meta{names}, read verbatim by \pkg{xparse}. First % initialize some variables before applying the \meta{options}, then % parse the \meta{names} to get a sequence of macro names, then apply -% \cs{@@_macro_single:n} to each (this step is more subtle than -% \cs{seq_map_function:NN} because of |TF|/|pTF|). Finally typeset +% \cs{@@_macro_single:nNN} to each (this step is more subtle than +% \cs{seq_map_function:NN} because of |TF|/|pTF|/|noTF|). Finally typeset % the macro names in the margin. % \begin{macrocode} \cs_new_protected:Npn \@@_macro:nnw #1#2 { \@@_macro_init: + \tl_set:Nn \l_@@_macro_argument_tl {#2} \keys_set:nn { l3doc/macro } {#1} - \@@_verb_get_seq:nN {#2} \l_@@_macro_input_seq - \@@_macro_map:N \@@_macro_single:n - \@@_macro_typeset: + \@@_names_get_seq:nN {#2} \l_@@_names_seq + \@@_names_parse: + \@@_macro_adjust_internal: + \@@_macro_save_names: + \@@_names_typeset: + \@@_macro_dump: + \@@_macro_reset: } % \end{macrocode} % \end{macro} @@ -2174,56 +2626,98 @@ Do not distribute a modified version of this file. % \cs{l_@@_nested_macro_int} counts the number of \env{macro} % environments around the current point (is $0$ outside). % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_macro_init: +\cs_new_protected:Npn \@@_macro_init: { \int_incr:N \l_@@_nested_macro_int \bool_set_false:N \l_@@_macro_aux_bool \bool_set_false:N \l_@@_macro_internal_bool \bool_set_false:N \l_@@_macro_TF_bool \bool_set_false:N \l_@@_macro_pTF_bool + \bool_set_false:N \l_@@_macro_noTF_bool \bool_set_false:N \l_@@_macro_EXP_bool \bool_set_false:N \l_@@_macro_rEXP_bool \bool_set_false:N \l_@@_macro_var_bool \bool_set_false:N \l_@@_macro_tested_bool + \bool_set_false:N \l_@@_names_verb_bool + \tl_set:Nn \l_@@_override_module_tl { \q_no_value } + \tl_clear:N \l_@@_macro_documented_tl \cs_set_eq:NN \testfile \@@_print_testfile:n \box_clear:N \l_@@_macro_index_box \vbox_set:Nn \l_@@_macro_box { - \hbox:n { \strut } + \hbox:n + { + \strut + \int_compare:nNnT \l_@@_macro_int = \c_zero + { \HD@target } + } \vskip \int_eval:n { \l_@@_macro_int - 1 } \baselineskip } } % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_macro_map:N} -% Applies |#1| to all macros. In the |pTF| case, this means going -% twice through the sequence \cs{l_@@_macro_input_seq}, once for the -% predicates and once for the |TF| variants. +% \begin{macro}[aux]{\@@_macro_reset:} +% We ensure that \cs{cs} commands nested inside a macro whose module +% is imposed are not affected. % \begin{macrocode} -\cs_new_protected:Npn \@@_macro_map:N #1 +\cs_new_protected:Npn \@@_macro_reset: { - \bool_if:NT \l_@@_macro_pTF_bool + \tl_set:Nn \l_@@_override_module_tl { \q_no_value } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_macro_adjust_internal:} +% If the macros are neither marked as internal nor auxiliary, and all +% macros in \cs{l_@@_names_seq} contain |__| then mark them as being +% internal. +% \begin{macrocode} +\cs_new_protected:Npn \@@_macro_adjust_internal: + { + \bool_if:NF \l_@@_macro_internal_bool { - \bool_set_false:N \l_@@_macro_TF_bool - \seq_map_inline:Nn \l_@@_macro_input_seq + \bool_if:NF \l_@@_macro_aux_bool { - \tl_set:Nn \l_@@_tmpa_tl {##1} - \tl_replace_once:Noo \l_@@_tmpa_tl - { \tl_to_str:n { : } } { \tl_to_str:n { _p: } } - \exp_args:No #1 \l_@@_tmpa_tl + \bool_set_true:N \l_@@_macro_internal_bool + \seq_map_inline:Nn \l_@@_names_seq + { + \tl_if_in:noF {##1} { \tl_to_str:n { __ } } + { \bool_set_false:N \l_@@_macro_internal_bool } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_macro_save_names:} +% The list of names defined in a set of \env{macro} environments is +% eventually used to display on which page they are documented. +% \begin{macrocode} +\cs_new_protected:Npn \@@_macro_save_names: + { + \tl_map_inline:Nn \l_@@_names_block_tl + { + \seq_set_eq:NN \l_@@_tmpa_seq ##1 + \seq_pop:NN \l_@@_tmpa_seq \l_@@_tmpa_tl + \seq_get:NN \l_@@_tmpa_seq \l_@@_tmpb_tl + \seq_gput_right:Nx \g_@@_nested_names_seq + { + \l_@@_tmpa_tl + \str_if_eq_x:nnF { \l_@@_tmpb_tl } { \scan_stop: } + { : \l_@@_tmpb_tl } + \bool_if:NT \l_@@_macro_TF_bool { TF } } - \bool_set_true:N \l_@@_macro_TF_bool } - \seq_map_function:NN \l_@@_macro_input_seq #1 } % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_macro_typeset:} +% \begin{macro}[aux]{\@@_macro_dump:} % This calls |\makelabel{}| % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_macro_typeset: +\cs_new_protected:Npn \@@_macro_dump: { \topsep\MacroTopsep \trivlist @@ -2244,7 +2738,32 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_macro_single:n} +% \begin{macro}[aux]{\@@_macro_typeset_block:nN} +% Used to typeset a macro and its variants. |#1| is the macro name, +% |#2| is a boolean controlling whether to add |TF|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_macro_typeset_block:nN #1#2 + { + \@@_macro_single:nNN {#1} \c_true_bool #2 + \seq_if_empty:NF \g_@@_variants_seq + { + \@@_macro_typeset_variant_list:xN + { \@@_get_function_name:n {#1} } #2 + } + } +\cs_generate_variant:Nn \@@_macro_typeset_block:nN { x } +\cs_new_protected:Npn \@@_macro_typeset_variant_list:nN #1#2 + { + \seq_map_inline:Nn \g_@@_variants_seq + { \@@_macro_single:nNN { #1 : ##1 } \c_false_bool #2 } + } +\cs_generate_variant:Nn \@@_macro_typeset_variant_list:nN { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_macro_single:nNN} +% The arguments are |#1| a macro name (without |TF|), |#2| a boolean +% determining whether or not to index, and |#3| whether or not to add |TF|. % Let's start to mess around with \cls{doc}'s \env{macro} environment. % See \file{doc.dtx} for a full explanation of the original % environment. It's rather \emph{enthusiastically} commented. @@ -2255,71 +2774,78 @@ Do not distribute a modified version of this file. % The assignments to \cs{saved@macroname} and \cs{saved@indexname} % are used by \pkg{doc}'s \cs{changes} mechanism. % \begin{macrocode} -\cs_new_protected:Npn \@@_macro_single:n #1 +\cs_new_protected:Npn \@@_macro_single:nNN #1#2#3 { \tl_set:Nn \saved@macroname {#1} - \@@_macro_typeset_one:n {#1} - \exp_args:Nx \@@_macro_index:n - { - #1 - \bool_if:NT \l_@@_macro_TF_bool { \tl_to_str:n { TF } } - } + \@@_macro_typeset_one:nN {#1} #3 + \bool_if:NT #3 { \DoNotIndex {#1} } + \exp_args:Nx \@@_macro_index:nN + { #1 \bool_if:NT #3 { \tl_to_str:n { TF } } } + #2 } -\cs_new_protected:Npn \@@_macro_index:n #1 +\cs_new_protected:Npn \@@_macro_index:nN #1#2 { - \bool_if:NF \l_@@_macro_aux_bool - { \seq_gput_right:Nn \g_doc_macros_seq {#1} } - \hbox_set:Nw \l_@@_macro_index_box - % This box only contains targets... it seems inefficient. - \hbox_unpack_clear:N \l_@@_macro_index_box - \int_gincr:N \c@CodelineNo - \@@_special_index:nn {#1} { main } - \DoNotIndex {#1} - \int_gdecr:N \c@CodelineNo - \exp_args:NNNo \hbox_set_end: - \tl_set:Nn \saved@indexname { \l_@@_index_key_tl } + \DoNotIndex {#1} + \bool_if:NT #2 + { + \bool_if:NF \l_@@_macro_aux_bool + { \seq_gput_right:Nn \g_doc_macros_seq {#1} } + \hbox_set:Nw \l_@@_macro_index_box + \hbox_unpack_clear:N \l_@@_macro_index_box + \int_gincr:N \c@CodelineNo + \@@_special_index:nn {#1} { main } + \int_gdecr:N \c@CodelineNo + \exp_args:NNNo \hbox_set_end: + \tl_set:Nn \saved@indexname { \l_@@_index_key_tl } + } } % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_macro_typeset_one:n} +% \begin{macro}[aux]{\@@_macro_typeset_one:nN} % For a long time, \cls{l3doc} collected the macro names as labels in % the first items of nested \tn{trivlist}, but these were not closed % properly with \tn{endtrivlist}. Also, it interacted in surprising % ways with \pkg{hyperref} targets. Now, we collect typeset macro % names by hand in the box \cs{l_@@_macro_box}. Note the space |\ |. +% |#1| is the macro name, |#2| whether to add |TF|. % \begin{macrocode} -\cs_new_protected:Npn \@@_macro_typeset_one:n #1 +\cs_new_protected:Npn \@@_macro_typeset_one:nN #1#2 { \vbox_set:Nn \l_@@_macro_box { \vbox_unpack_clear:N \l_@@_macro_box - \hbox { \llap { \@@_print_macroname:n {#1} \ } } + \hbox { \llap { \@@_print_macroname:nN {#1} #2 \ } } } \int_incr:N \l_@@_macro_int } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_print_macroname:n} +% \begin{macro}{\@@_print_macroname:nN} +% In the name, spaces are replaced by other spaces to ensure they get +% displayed in case there are any. % \begin{macrocode} -\cs_new_protected:Npn \@@_print_macroname:n #1 +\cs_new_protected:Npn \@@_print_macroname:nN #1#2 { \strut - \HD@target - - % TODO: INEFFICIENT(!) - \exp_args:NNx \seq_if_in:NnTF \g_doc_functions_seq - { #1 \bool_if:NT \l_@@_macro_TF_bool { \tl_to_str:n {TF} } } + \@@_get_hyper_target:xN { - \@@_get_hyper_target:nN {#1} \l_@@_tmpa_tl - \exp_last_unbraced:NNo \hyperref [ \l_@@_tmpa_tl ] + \exp_not:n {#1} + \bool_if:NT #2 { \tl_to_str:n {TF} } } + \l_@@_tmpa_tl + \cs_if_exist:cTF { r@ \l_@@_tmpa_tl } + { \exp_last_unbraced:NNo \hyperref [ \l_@@_tmpa_tl ] } { \use:n } { - \int_compare:nTF { \tl_count:n {#1} <= 28 } + \int_compare:nTF { \str_count:n {#1} <= 28 } { \MacroFont } { \MacroLongFont } - \@@_macroname_prefix:n {#1} \@@_macroname_suffix: + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_replace_all:Nno \l_@@_tmpa_tl + { ~ } { \c_catcode_other_space_tl } + \@@_macroname_prefix:o \l_@@_tmpa_tl + \@@_macroname_suffix:N #2 } } \cs_new_protected:Npn \@@_macroname_prefix:n #1 @@ -2327,8 +2853,9 @@ Do not distribute a modified version of this file. \bool_if:NTF \l_@@_macro_aux_bool { \@@_typeset_aux:n {#1} } {#1} } -\cs_new_protected_nopar:Npn \@@_macroname_suffix: - { \bool_if:NTF \l_@@_macro_TF_bool { \@@_typeset_TF: } { } } +\cs_generate_variant:Nn \@@_macroname_prefix:n { o } +\cs_new_protected:Npn \@@_macroname_suffix:N #1 + { \bool_if:NTF #1 { \@@_typeset_TF: } { } } % \end{macrocode} % \end{macro} % @@ -2401,23 +2928,24 @@ Do not distribute a modified version of this file. % % \begin{macro}[aux]{\@@_test_missing:n} % Keys in \cs{g_@@_missing_tests_prop} are lists of macros given as -% arguments of one \env{macro} environment. Values are comma lists of -% filenames (Bruno thinks). +% arguments of one \env{macro} environment. Values are pairs of a +% file name and a comment about the missing tests. % \begin{macrocode} \cs_new_protected:Npn \@@_test_missing:n #1 { - \tl_set:Nx \l_@@_tmpb_tl - { \seq_use:Nn \l_@@_macro_input_seq { , } } - \prop_if_in:NVTF \g_@@_missing_tests_prop \l_@@_tmpb_tl - { - \prop_get:NVN \g_@@_missing_tests_prop \l_@@_tmpb_tl - \l_@@_tmpa_tl - } - { \tl_clear:N \l_@@_tmpa_tl } - \clist_set:Nx \l_@@_tmpa_clist { \l_@@_tmpa_tl , #1 } - \prop_gput:NVV \g_@@_missing_tests_prop \l_@@_tmpb_tl - \l_@@_tmpa_clist + \@@_test_missing_aux:Nxn + \g_@@_missing_tests_prop + { \seq_use:Nn \l_@@_names_seq { , } } + { { \g_file_current_name_tl \iow_char:N \ (#1) } } + } +\cs_new_protected:Npn \@@_test_missing_aux:Nnn #1#2#3 + { + \prop_get:NnNTF #1 {#2} \l_@@_tmpa_tl + { \tl_put_right:Nn \l_@@_tmpa_tl { , #3 } } + { \tl_set:Nn \l_@@_tmpa_tl {#3} } + \prop_put:Nno #1 {#2} \l_@@_tmpa_tl } +\cs_generate_variant:Nn \@@_test_missing_aux:Nnn { Nx } % \end{macrocode} % \end{macro} % @@ -2435,11 +2963,8 @@ Do not distribute a modified version of this file. \@@_macro_end_check_tested: \int_compare:nNnT \l_@@_nested_macro_int = 1 { - \@@_macro_end_style:n - { - \@@_print_end_definition: - \@@_print_documented: - } + \@@_macro_end_style:n { \@@_print_end_definition: } + \seq_gclear:N \g_@@_nested_names_seq } } % \end{macrocode} @@ -2450,7 +2975,7 @@ Do not distribute a modified version of this file. % auxiliary nor a variable (and it does not have a test), then add it % to the sequence of non-tested macros. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_macro_end_check_tested: +\cs_new_protected:Npn \@@_macro_end_check_tested: { \bool_if:nT { @@ -2462,7 +2987,7 @@ Do not distribute a modified version of this file. { \seq_gput_right:Nx \g_@@_not_tested_seq { - \seq_use:Nn \l_@@_macro_input_seq { , } + \seq_use:Nn \l_@@_names_seq { , } \bool_if:NTF \l_@@_macro_pTF_bool {~(pTF)} { \bool_if:NT \l_@@_macro_TF_bool {~(TF)} } } @@ -2486,45 +3011,38 @@ Do not distribute a modified version of this file. % \begin{macro}[aux] % { % \@@_print_end_definition:, -% \@@_macro_end_wrap_items:N, +% \@@_macro_end_wrap_item:n, % \@@_print_documented: % } -% Surround each item by \tn{texttt} and |TF| if needed, replacing |_| +% Surround each item by \tn{texttt}, replacing |_| % by \tn{_} as well. Then list the % macro names through \cs{seq_use:Nnnn}, unless there are too many. % Finally, if the macro is neither auxiliary nor internal, add a link % to where it is documented. % \begin{macrocode} -\cs_new_protected:Npn \@@_macro_end_wrap_items:N #1 +\cs_new_protected:Npn \@@_macro_end_wrap_item:n #1 { - \bool_if:NT \l_@@_macro_TF_bool - { \seq_set_map:NNn #1 #1 { ##1 TF } } - \seq_set_map:NNn #1 #1 - { - \exp_not:n - { - \tl_set:Nn \l_@@_tmpa_tl {##1} - \tl_replace_all:Non \l_@@_tmpa_tl - { \token_to_str:N _ } { \_ } - \texttt { \l_@@_tmpa_tl } - } - } + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_replace_all:Non \l_@@_tmpa_tl + { \token_to_str:N _ } { \_ } + \texttt { \l_@@_tmpa_tl } } -\cs_new_protected_nopar:Npn \@@_print_end_definition: +\cs_new_protected:Npn \@@_print_end_definition: { - \group_begin: - \@@_macro_end_wrap_items:N \l_@@_macro_input_seq + \seq_set_map:NNn \l_@@_tmpa_seq + \g_@@_nested_names_seq + { \exp_not:n { \@@_macro_end_wrap_item:n {##1} } } End~ definition~ for~ - \int_compare:nTF { \seq_count:N \l_@@_macro_input_seq <= 3 } + \int_compare:nTF { \seq_count:N \l_@@_tmpa_seq <= 3 } { - \seq_use:Nnnn \l_@@_macro_input_seq + \seq_use:Nnnn \l_@@_tmpa_seq { \,~and~ } { \,,~ } { \,,~and~ } - \@. } - { \seq_item:Nn \l_@@_macro_input_seq {1}\,~and~others. } - \group_end: + { \seq_item:Nn \l_@@_tmpa_seq {1}\,~and~others } + \@. + \@@_print_documented: } -\cs_new_protected_nopar:Npn \@@_print_documented: +\cs_new_protected:Npn \@@_print_documented: { \bool_if:nT { @@ -2533,13 +3051,25 @@ Do not distribute a modified version of this file. } { \int_set:Nn \l_@@_tmpa_int - { \seq_count:N \l_@@_macro_input_seq } + { \seq_count:N \g_@@_nested_names_seq } + \tl_if_empty:NTF \l_@@_macro_documented_tl + { + \tl_set:Nx \l_@@_macro_documented_tl + { \seq_item:Nn \g_@@_nested_names_seq { 1 } } + } + { + \tl_set:Nf \l_@@_macro_documented_tl + { + \exp_after:wN \token_to_str:N + \l_@@_macro_documented_tl + } + } \int_compare:nNnTF \l_@@_tmpa_int = 1 {~This~} {~These~} \bool_if:NTF \l_@@_macro_var_bool {variable} {function} \int_compare:nNnTF \l_@@_tmpa_int = 1 {~is~} {s~are~} documented~on~page~ - \exp_args:Nx \@@_get_hyper_target:nN - { \seq_item:Nn \l_@@_macro_input_seq { 1 } } + \@@_get_hyper_target:oN + \l_@@_macro_documented_tl \l_@@_tmpa_tl \exp_args:Nx \pageref { \l_@@_tmpa_tl } . } @@ -2547,51 +3077,6 @@ Do not distribute a modified version of this file. % \end{macrocode} % \end{macro} % -% \subsubsection{Common between \env{macro} and \env{function}} -% -% \begin{macro}{\@@_typeset_TF:, \@@_typeset_aux:n} -% Used by \cs{@@_macro_single:n} and in the \env{function} environment -% to typeset conditionals and auxiliary functions. -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_typeset_TF: - { - \hyperlink{explTF} - { - \color{black} - \itshape TF - \makebox[0pt][r] - { - \color{red} - \underline { \phantom{\itshape TF} \kern-0.1em } - } - } - } -\cs_new_protected:Npn \@@_typeset_aux:n #1 - { - { \color[gray]{0.7} #1 } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_get_hyper_target:nN} -% Create a \pkg{hyperref} anchor from a macro name~|#1| and stores it -% in the token list variable~|#2|. For instance, |\prg_replicate:nn| -% gives |doc/function//prg/replicate:nn|. -% \begin{macrocode} -\cs_new_protected:Npn \@@_get_hyper_target:nN #1#2 - { - \tl_set:Nx #2 - { - \tl_to_str:n {#1} - \bool_if:NT \l_@@_macro_TF_bool { \tl_to_str:n {TF} } - } - \tl_replace_all:Nxn #2 { \iow_char:N \_ } { / } - \tl_remove_all:Nx #2 { \iow_char:N \\ } - \tl_put_left:Nn #2 { doc/function// } - } -% \end{macrocode} -% \end{macro} -% % \subsubsection{Misc} % % \begin{macro}{\DescribeOption} @@ -2665,7 +3150,7 @@ Do not distribute a modified version of this file. % The actual character from the font |manfnt|: % \begin{macrocode} \font \manual = manfnt \scan_stop: -\cs_gset_nopar:Npn \dbend { {\manual\char127} } +\cs_gset:Npn \dbend { {\manual\char127} } % \end{macrocode} % % Defines the single danger bend. Use it whenever there is a feature in @@ -2676,7 +3161,7 @@ Do not distribute a modified version of this file. { \begin{trivlist}\item[]\noindent \begingroup\hangindent=2pc\hangafter=-2 - \cs_set_nopar:Npn \par{\endgraf\endgroup} + \cs_set:Npn \par{\endgraf\endgroup} \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces } { @@ -2694,7 +3179,7 @@ Do not distribute a modified version of this file. { \begin{trivlist}\item[]\noindent \begingroup\hangindent=3.5pc\hangafter=-2 - \cs_set_nopar:Npn \par{\endgraf\endgroup} + \cs_set:Npn \par{\endgraf\endgroup} \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\ignorespaces }{ \par\end{trivlist} @@ -2851,8 +3336,8 @@ Do not distribute a modified version of this file. \relax\clearpage \docincludeaux \IfFileExists{#1.fdd} - { \cs_set_nopar:Npn \currentfile{#1.fdd} } - { \cs_set_nopar:Npn \currentfile{#1.dtx} } + { \cs_set:Npn \currentfile{#1.fdd} } + { \cs_set:Npn \currentfile{#1.dtx} } \int_compare:nNnTF \@auxout = \@partaux { \@latexerr{\string\include\space cannot~be~nested}\@eha } { \@docinclude #1 } @@ -2867,7 +3352,7 @@ Do not distribute a modified version of this file. \@tempswatrue \if@partsw \@tempswafalse - \cs_set_nopar:Npx \@tempb{#1} + \cs_set:Npx \@tempb{#1} \@for\@tempa:=\@partlist\do { \ifx\@tempa\@tempb\@tempswatrue\fi @@ -2886,7 +3371,7 @@ Do not distribute a modified version of this file. \part{\currentfile} { \cs_set_eq:NN \ttfamily\relax - \cs_gset_nopar:Npx \filekey + \cs_gset:Npx \filekey { \filekey, \thepart = { \ttfamily \currentfile } } } \DocInput{\currentfile} @@ -2919,14 +3404,14 @@ Do not distribute a modified version of this file. % % \begin{macro}{\docincludeaux} % \begin{macrocode} -\cs_gset_nopar:Npn \docincludeaux +\cs_gset:Npn \docincludeaux { \tl_set:Nn \thepart { \alphalph { part } } \tl_set:Nn \filesep { \thepart - } \cs_set_eq:NN \filekey \use_none:n \tl_gput_right:Nn \index@prologue { - \cs_gset_nopar:Npn \@oddfoot + \cs_gset:Npn \@oddfoot { \parbox { \textwidth } { @@ -2937,7 +3422,7 @@ Do not distribute a modified version of this file. \cs_set_eq:NN \@evenfoot \@oddfoot } \cs_gset_eq:NN \docincludeaux \relax - \cs_gset_nopar:Npn \@oddfoot + \cs_gset:Npn \@oddfoot { \cs_if_exist:cTF { ver @ \currentfile } { File~\thepart :~{\ttfamily\currentfile}~ } @@ -3035,7 +3520,7 @@ Do not distribute a modified version of this file. % \end{macrocode} % % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_show_functions_defined: +\cs_new_protected:Npn \@@_show_functions_defined: { \bool_if:nT { \g_@@_typeset_implementation_bool && \g_@@_checkfunc_bool } @@ -3108,7 +3593,7 @@ Do not distribute a modified version of this file. % \end{macrocode} % % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_show_not_tested: +\cs_new_protected:Npn \@@_show_not_tested: { \bool_if:NT \g_@@_checktest_bool { @@ -3229,26 +3714,31 @@ Do not distribute a modified version of this file. { \use:x { - \@@_special_index_module:nnnn + \@@_special_index_module:nnnnN { \quotechar #1 } { \quotechar \bslash \quotechar #1 } { } { } + \c_false_bool } } % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\@@_special_index:nn} +% ^^A TODO this override is somewhat a hack % \begin{macrocode} \cs_new_protected:Npn \@@_special_index:nn #1#2 { \@@_key_get:n {#1} - \@@_special_index_module:ooon + \quark_if_no_value:NF \l_@@_override_module_tl + { \tl_set_eq:NN \l_@@_index_module_tl \l_@@_override_module_tl } + \@@_special_index_module:ooonN { \l_@@_index_key_tl } { \l_@@_index_macro_tl } { \l_@@_index_module_tl } {#2} + \l_@@_index_internal_bool } \cs_generate_variant:Nn \@@_special_index:nn { o } % \end{macrocode} @@ -3256,45 +3746,57 @@ Do not distribute a modified version of this file. % % \begin{macro} % { -% \@@_special_index_module:nnnn, -% \@@_special_index_module:ooon, -% \@@_special_index_aux:nnnnn, -% \@@_special_index_aux:onnnn, +% \@@_special_index_module:nnnnN, +% \@@_special_index_module:ooonN, +% \@@_special_index_aux:nnnnnn, % \@@_special_index_set:Nn, % } % Remotely based on Heiko's replacement to play nicely with % \pkg{hypdoc}. We use \tn{verb} or a \tn{verbatim@font} construction % depending on whether the number of tokens in |#2| is equal to its -% number of characters. +% number of characters: if it is not then that suggests that there is +% a construct such as |\meta{...}|. % \begin{macrocode} \tl_new:N \l_@@_index_escaped_macro_tl -\cs_new_protected:Npn \@@_special_index_module:nnnn #1#2#3#4 +\cs_new_protected:Npn \@@_special_index_module:nnnnN #1#2#3#4#5 { \use:x { - \exp_not:n { \@@_special_index_aux:nnnnn {#1} {#2} } - \str_case_x:nnF {#3} + \exp_not:n { \@@_special_index_aux:nnnnnn {#1} {#2} } + \tl_if_empty:nTF {#3} + { { } { } { } } { - { } { { } { } } - { TeX } + \str_if_eq_x:nnTF {#3} { TeX } + { + { TeX~and~LaTeX2e } + { \string\TeX{}~and~\string\LaTeXe{} } + } { - { TeX~and~LaTeX2e~commands } - { \string\TeX{}~and~\string\LaTeXe{}~commands: } + {#3} + { \string\pkg{#3} } } + { \bool_if:NT #5 { ~internal } ~commands: } } - { { #3~commands } { \string\pkg{#3}~commands: } } } {#4} } -\cs_generate_variant:Nn \@@_special_index_module:nnnn { ooo } -\cs_new_protected:Npn \@@_special_index_aux:nnnnn #1#2#3#4#5 +\cs_generate_variant:Nn \@@_special_index_module:nnnnN { ooo } +\cs_new_protected:Npn \@@_special_index_aux:nnnnnn #1#2#3#4#5#6 { - \HD@target \@@_special_index_set:Nn \l_@@_index_escaped_macro_tl {#2} - \index + \str_if_eq:onTF { \@currenvir } { macrocode } + { \codeline@wrindex } { - \tl_if_empty:nF { #3 #4 } - { #3 \actualchar #4 \levelchar } + \str_case:nnF {#6} + { + { main } { \codeline@wrindex } + { usage } { \index } + } + { \HD@target \index } + } + { + \tl_if_empty:nF { #3 #4 #5 } + { #3 #5 \actualchar #4 #5 \levelchar } #1 \actualchar { @@ -3302,20 +3804,13 @@ Do not distribute a modified version of this file. \l_@@_index_escaped_macro_tl } \encapchar - hdclindex{\the\c@HD@hypercount}{#5} + hdclindex{\the\c@HD@hypercount}{#6} } } -\cs_generate_variant:Nn \@@_special_index_aux:nnnnn { o } \cs_new_protected:Npn \@@_special_index_set:Nn #1#2 { \tl_set:Nx #1 { \tl_to_str:n {#2} } - \int_compare:nNnTF { \tl_count:n {#2} } < { \tl_count:N #1 } - { - \tl_set:Nn #1 {#2} - \tl_replace_all:Non #1 - { \c_@@_backslash_tl } - { \token_to_str:N \bslash \c_space_tl } - } + \@@_if_almost_str:nTF {#2} { \exp_args:Nx \tl_map_inline:nn { \tl_to_str:N \verbatimchar \token_to_str:N _ } @@ -3337,6 +3832,12 @@ Do not distribute a modified version of this file. #1 \verbatimchar } } + { + \tl_set:Nn #1 {#2} + \tl_replace_all:Non #1 + { \c_@@_backslash_tl } + { \token_to_str:N \bslash \c_space_tl } + } } % \end{macrocode} % \end{macro} @@ -3345,90 +3846,136 @@ Do not distribute a modified version of this file. % % \begin{macro}[aux]{\@@_key_get:n} % Sets \cs{l_@@_index_macro_tl}, \cs{l_@@_index_key_tl}, and -% \cs{l_@@_index_module_tl} from |#1|. The \cs{l_@@_index_macro_tl} -% contains~|#1| directly. The starting point for the \meta{key} is -% |#1| as a string. If it the first character is a backslash, remove +% \cs{l_@@_index_module_tl} from |#1|. The base function is stored by +% \cs{@@_key_get_base:nN} in \cs{l_@@_index_macro_tl}, falling back to +% |#1| if it contains markup or has no signature. +% +% The starting point for the \meta{key} is \cs{l_@@_index_key_tl} as a +% string. If it the first character is a backslash, remove % it. Then recognize |expl| functions and variables by the presence % of |:| or~|_| and \TeX{}/\LaTeXe{} commands by the presence of~|@|. -% For |expl| names, we call \cs{@@_key_expl:}, which is responsible -% for removing some characters and finding the module name, while for -% \TeX{}/\LaTeXe{} commands the module name is |TeX|, and others have -% an empty module name. The function \cs{@@_key_expl:} detects a -% leading~|.| and removes it (key property), and otherwise does the -% following: if the second character is~|_| and the first is as well, -% then remove both (internal |expl| function); if the second character -% is~|_| but the first is not (the case of an |expl| variable), then -% remove both and remove a subsequent~|_| character (for internal -% variables). In all cases, call \cs{@@_key_get_module:}, which sets -% \cs{l_@@_index_module_tl} by removing anything after |_| or~|:| in -% \cs{l_@@_index_key_tl}. +% For |expl| names, we call \cs{@@_key_func:} or \cs{@@_key_var:}, +% which are responsible for removing some characters and finding the +% module name, while for \TeX{}/\LaTeXe{} commands the module name is +% |TeX|, and others have an empty module name. % \begin{macrocode} \cs_new_protected:Npn \@@_key_get:n #1 { - \tl_set:Nn \l_@@_index_macro_tl {#1} - \tl_set:Nx \l_@@_index_key_tl { \tl_to_str:n {#1} } + \@@_key_get_base:nN {#1} \l_@@_index_macro_tl + \tl_set:Nx \l_@@_index_key_tl + { \tl_to_str:N \l_@@_index_macro_tl } \tl_clear:N \l_@@_index_module_tl + \tl_if_in:NoTF \l_@@_index_key_tl { \tl_to_str:n { __ } } + { \bool_set_true:N \l_@@_index_internal_bool } + { \bool_set_false:N \l_@@_index_internal_bool } \tl_if_head_eq_charcode:oNT { \l_@@_index_key_tl } \c_@@_backslash_token { \@@_key_pop: } \tl_if_in:NoTF \l_@@_index_key_tl { \token_to_str:N : } - { \@@_key_expl: } + { \@@_key_func: } { \tl_if_in:NoTF \l_@@_index_key_tl { \token_to_str:N _ } - { \@@_key_expl: } + { \@@_key_var: } { \tl_if_in:NoT \l_@@_index_key_tl { \token_to_str:N @ } { \tl_set:Nn \l_@@_index_module_tl { TeX } } } } } -\cs_new_protected_nopar:Npn \@@_key_pop: +\cs_new_protected:Npn \@@_key_pop: { \tl_set:Nx \l_@@_index_key_tl { \tl_tail:N \l_@@_index_key_tl } } -\cs_new_protected_nopar:Npn \@@_key_expl: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_key_trim_module:n, \@@_key_drop_underscores:} +% Helper that removes from \cs{l_@@_index_module_tl} everything after +% the first occurence of |#1|. Helper that removes any leading +% underscore from \cs{l_@@_index_key_tl}. +% \begin{macrocode} +\cs_set:Npn \@@_key_trim_module:n #1 { - \tl_if_head_eq_charcode:oNTF { \l_@@_index_key_tl } . - { \@@_key_pop: } - { - \exp_args:Nx \tl_if_head_eq_charcode:nNT - { \exp_args:No \str_tail:n \l_@@_index_key_tl } _ - { - \tl_if_head_eq_charcode:oNTF { \l_@@_index_key_tl } _ - { - \@@_key_pop: - \@@_key_pop: - } - { - \@@_key_pop: - \@@_key_pop: - \tl_if_head_eq_charcode:oNT { \l_@@_index_key_tl } _ - { \@@_key_pop: } - } - } - } - \@@_key_get_module: + \cs_set:Npn \@@_tmpa:w ##1 #1 ##2 \q_stop + { \exp_not:n {##1} } + \tl_set:Nx \l_@@_index_module_tl + { \exp_after:wN \@@_tmpa:w \l_@@_index_module_tl #1 \q_stop } + } +\cs_new_protected:Npn \@@_key_drop_underscores: + { + \tl_if_head_eq_charcode:oNT { \l_@@_index_key_tl } _ + { \@@_key_pop: \@@_key_drop_underscores: } } % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_key_get_module:, \@@_key_get_module_aux:n} -% Sets \cs{l_@@_index_module_tl} from \cs{l_@@_index_key_tl}, by -% removing anything after |:| or |_|, taking care of not expanding the -% rest for cases such as |\cs{\meta{name}:\meta{signature}}|. +% \begin{macro}[aux]{\@@_key_func:} +% The function \cs{@@_key_func:} is used if there is a colon, so +% either for usual \pkg{expl3} functions or for keys from +% \pkg{l3keys}. After removing from the key a leading dot (for the +% latter case), and any leading underscore, the module name is the +% part before any colon or underscore. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_key_get_module: +\cs_new_protected:Npn \@@_key_func: { + \tl_if_head_eq_charcode:oNT { \l_@@_index_key_tl } . + { \@@_key_pop: } + \@@_key_drop_underscores: \tl_set_eq:NN \l_@@_index_module_tl \l_@@_index_key_tl - \exp_args:No \@@_key_get_module_aux:n { \token_to_str:N : } - \exp_args:No \@@_key_get_module_aux:n { \token_to_str:N _ } + \exp_args:No \@@_key_trim_module:n { \token_to_str:N : } + \exp_args:No \@@_key_trim_module:n { \token_to_str:N _ } } -\cs_new_protected:Npn \@@_key_get_module_aux:n #1 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_key_var:, \@@_key_get_module:} +% The function \cs{@@_key_var:} covers cases with no~|:| but with~|_|, +% typically variables but occasionally non-\pkg{expl3} functions such +% as \Lua{} function with underscores. First test the second +% character: if that is~|_| then assume we have a proper variable, +% otherwise use the part before any underscore as the module name. +% For variables, distinguish quarks and scan marks (starting with |q| +% and~|s|), then drop the first letter (local/global/constant marker) +% and underscores. If there is no underscore left we had something +% like \cs{c_zero} which we assume is an integer constant. If there +% is one underscore we assume it is a variable like \cs{c_empty_tl} +% whose module name is the last part. Otherwise the module name is +% the part before any underscore. +% \begin{macrocode} +\cs_new_protected:Npn \@@_key_var: { - \cs_set:Npn \@@_tmpa:w ##1 #1 ##2 \q_stop { \exp_not:n {##1} } - \tl_set:Nx \l_@@_index_module_tl - { \exp_after:wN \@@_tmpa:w \l_@@_index_module_tl #1 \q_stop } + \exp_args:Nx \tl_if_head_eq_charcode:nNTF + { \exp_args:No \str_tail:n \l_@@_index_key_tl } _ + { + \str_case:fn { \str_head:N \l_@@_index_key_tl } + { + { q } { \tl_set:Nn \l_@@_index_module_tl { quark } } + { s } { \tl_set:Nn \l_@@_index_module_tl { quark } } + } + \@@_key_pop: + \@@_key_pop: + \@@_key_drop_underscores: + \tl_if_empty:NT \l_@@_index_module_tl + { + \seq_set_split:NoV \l_@@_tmpa_seq + { \token_to_str:N _ } \l_@@_index_key_tl + \tl_set:Nx \l_@@_index_module_tl + { + \int_case:nnF { \seq_count:N \l_@@_tmpa_seq } + { + { 0 } { } + { 1 } { int } + { 2 } { \seq_item:Nn \l_@@_tmpa_seq { 2 } } + } + { \seq_item:Nn \l_@@_tmpa_seq { 1 } } + } + } + } + { + \tl_set_eq:NN \l_@@_index_module_tl \l_@@_index_key_tl + \exp_args:No \@@_key_trim_module:n { \token_to_str:N _ } + } } % \end{macrocode} % \end{macro} |