document large parts of grouped theorems

This commit is contained in:
Maximilian Keßler 2022-01-18 01:47:57 +01:00
parent b3982c64b7
commit 880a30debf
2 changed files with 420 additions and 75 deletions

View file

@ -692,98 +692,49 @@
% \subsection{Theorem groups}
%
%
% \begin{function}{\groupthm_new_theorem_group_by_keys:nn}
% \begin{function}
% {
% \groupthm_new_theorem_group_by_keys:nn,
% \groupthm_renew_theorem_group_by_keys:nn,
% \groupthm_provide_theorem_group_by_keys:nn,
% \groupthm_declare_theorem_group_by_keys:nn
% }
% \begin{syntax}
% \cs{groupthm_new_theorem_group_by_keys:nn}\ma{keys}\ma{theorem group}
% \end{syntax}
%
% \LaTeX3 version of \cs{NewTheoremGroup}
% \LaTeX3 versions of \cs{NewTheoremGroup}, \cs{RenewTheoremGroup},
% \cs{ProvideTheoremGroup} and \cs{DeclareTheoremGroup}
%
% \end{function}
%
%
%
% \begin{function}{\groupthm_renew_theorem_group_by_keys:nn}
% \begin{syntax}
% \cs{groupthm_renew_theorem_group_by_keys:nn}\ma{keys}
% \ma{theorem group}
% \end{syntax}
%
% \LaTeX3 version of \cs{RenewTheoremGroup}
%
% \end{function}
%
%
%
% \begin{function}{\groupthm_provide_theorem_group_by_keys:nn}
% \begin{syntax}
% \cs{groupthm_provide_theorem_group_by_keys:nn}
% \ma{keys}\ma{theorem group}
% \end{syntax}
%
% \LaTeX3 version of \cs{ProvideTheoremGroup}
%
% \end{function}
%
%
%
% \begin{function}{\groupthm_declare_theorem_group_by_keys:nn}
% \begin{syntax}
% \cs{groupthm_declare_theorem_group_by_keys:nn}
% \ma{keys}\ma{theorem group}
% \end{syntax}
%
% \LaTeX3 version of \cs{DeclareTheoremGroup}
%
% \end{function}
%
%
%
% \begin{function}{\groupthm_new_theorem_group:nnnnn, \groupthm_new_theorem_group:nVVVV}
% \begin{function}
% {
% \groupthm_new_theorem_group:nnnnn,
% \groupthm_renew_theorem_group:nnnnn,
% \groupthm_provide_theorem_group:nnnnn,
% \groupthm_declare_theorem_group:nnnnn,
% \groupthm_new_theorem_group:nVVVV,
% \groupthm_renew_theorem_group:nVVVV,
% \groupthm_provide_theorem_group:nVVVV,
% \groupthm_declare_theorem_group:nVVVV
% }
% \begin{syntax}
% \cs{groupthm_new_theorem_group:nnnnn}\ma{theorem group}\ma{prename tl}
% \ma{postname tl}\ma{mapname clist}\ma{thmtools clist}
% \end{syntax}
%
% Non-keyval version of \cs{groupthm_new_theorem_group_by_keys:nn}
% Non-keyval versions of
% \cs{groupthm_new_theorem_group_by_keys:nn},
% \cs{groupthm_renew_theorem_group_by_keys:nn},
% \cs{groupthm_provide_theorem_group_by_keys:nn}
% and
% \cs{groupthm_declare_theorem_group_by_keys:nn}
%
% \end{function}
%
%
%
% \begin{function}{\groupthm_renew_theorem_group:nnnnn, \groupthm_renew_theorem_group:nVVVV}
% \begin{syntax}
% \cs{groupthm_renew_theorem_group:nnnnn}\ma{theorem group}\ma{prename tl}
% \ma{postname tl}\ma{mapname clist}\ma{thmtools clist}
% \end{syntax}
%
% Non-keyval version of \cs{groupthm_renew_theorem_group_by_keys:nn}
%
% \end{function}
%
%
% \begin{function}{\groupthm_provide_theorem_group:nnnnn, \groupthm_provide_theorem_group:nVVVV}
% \begin{syntax}
% \cs{groupthm_provide_theorem_group:nnnnn}\ma{theorem group}\ma{prename tl}
% \ma{postname tl}\ma{mapname clist}\ma{thmtools clist}
% \end{syntax}
%
% Non-keyval version of \cs{groupthm_provide_theorem_group_by_keys:nn}
%
% \end{function}
%
%
% \begin{function}{\groupthm_declare_theorem_group:nnnnn, \groupthm_declare_theorem_group:nVVVV}
% \begin{syntax}
% \cs{groupthm_declare_theorem_group:nnnnn}\ma{theorem group}\ma{prename tl}
% \ma{postname tl}\ma{mapname clist}\ma{thmtools clist}
% \end{syntax}
%
% Non-keyval version of \cs{groupthm_declare_theorem_group_by_keys:nn}
%
% \end{function}
%
%
%
% \begin{function}{\groupthm_declare_theorem_group_rule:nnnn}
% \begin{syntax}
@ -1599,11 +1550,363 @@
}
% \end{macrocode}
% \end{macro}
%
% \subsection{Iterating over powersets}
% For generating the different variants of a theorem family,
% we need to iterate over over the powerset of some list.
% This is a collection of hacks that perform exactly this,
% but these are poorly documented for now.
%
%
% \begin{macro}{\@@_powerset_clist_foreach:Nn}
% \begin{syntax}
% \cs{@@_powerset_clist_foreach:Nn}\meta{clist}\ma{code}
% \end{syntax}
%
% Executes \meta{code} for each subset of the given clist variable.
% The value of the (local) variable is changes throughout the iteration,
% and is thus available regularly in \meta{code}.
% Its value is restored at the end of the iteration.
%
% \begin{macrocode}
\clist_new:N \l_powerset_copied_clist
\seq_new:N \l_powerset_saved_seq
\cs_generate_variant:Nn \clist_remove_all:Nn { N V }
\cs_new:Npn \__powerset_clist_foreach_aux:Nn #1 #2
{
\clist_if_empty:NTF \l_powerset_copied_clist
{
#2
}
{
\clist_get:NN \l_powerset_copied_clist \l_tmpa_tl
\seq_push:NV \l_powerset_saved_seq \l_tmpa_tl
\clist_pop:NN \l_powerset_copied_clist { \l_tmpa_tl }
\__powerset_clist_foreach_aux:Nn #1 {#2}
\seq_get:NN \l_powerset_saved_seq \l_tmpa_tl
\clist_put_left:NV #1 \l_tmpa_tl
\__powerset_clist_foreach_aux:Nn #1 {#2}
\seq_get:NN \l_powerset_saved_seq \l_tmpa_tl
\clist_remove_all:NV #1 \l_tmpa_tl
\clist_push:NV \l_powerset_copied_clist \l_tmpa_tl
\seq_pop:NN \l_powerset_saved_seq \l_tmpa_tl
}
}
\cs_new:Npn \powerset_clist_foreach:Nn #1 #2
{
\clist_set_eq:NN \l_powerset_copied_clist #1
\clist_clear:N #1
\clist_remove_duplicates:N \l_powerset_copied_clist
\__powerset_clist_foreach_aux:Nn #1 {#2}
\clist_set_eq:NN #1 \l_powerset_copied_clist
}
% \end{macrocode}
% \end{macro}
%
%
%
%
% \subsection{Grouped Theorems}
%
%
% \begin{macro}{\@@_use_theorem_group:n}
% \begin{syntax}
% \cs{@@_use_theorem_group:n}\meta{theorem group}
% \end{syntax}
%
% Uses this theorem group, i.e.~applies its definition by writing
% to the internal hooks.
% A proper error message is emitted if the group is not defined.
%
% \begin{macrocode}
\cs_new:Npn \@@_use_theorem_group:n #1
{
\cs_if_exist_use:cF { @@_use_group_#1: }
{
\msg_error:nnn { groupthm } { unknown ~ group } { #1 }
}
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\@@_use_function_on_name:n}
% \begin{syntax}
% \cs{@@_use_function_on_name:n}\meta{function}
% \end{syntax}
%
% The \meta{function} is expected to be of type \texttt{:n},
% This applies the function to the \cs{l_@@_name_tl}
%
% \begin{macrocode}
\cs_new:Npn \@@_use_function_on_name:n #1
{
\tl_set:Nx \l_@@_name_tl
{
#1 { \tl_use:N \l_@@_name_tl }
}
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\@@_declare_grouped_theorem_aux:nnnn}
% \begin{syntax}
% \cs{@@_declare_grouped_theorem_aux:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% This is the internal backend that declares a grouped theorem
% by retrieving all the group properties and issuing a (single) \cs{declaretheorem}
% command of \pkg{thmtools}.
%
% \begin{macrocode}
\cs_new:Npn \@@_declare_grouped_theorem_aux:nnnn #1 #2 #3 #4
{
% \end{macrocode}
% First, set local variables to default values and store current name.
% \begin{macrocode}
\tl_clear:N \l_@@_prename_tl
\tl_set:Nn \l_@@_name_tl { #3 }
\tl_clear:N \l_@@_postname_tl
\clist_clear:N \l_@@_mapname_clist
\clist_clear:N \l_@@_thmtools_clist
% \end{macrocode}
% Clear all hooks
% \begin{macrocode}
\hook_gremove_code:nn { @@/prename }{*}
\hook_gremove_code:nn { @@/postname }{*}
\hook_gremove_code:nn { @@/mapname }{*}
\hook_gremove_code:nn { @@/thmtools }{*}
% \end{macrocode}
% Now, retrieve the group properties, by writing these into the hooks
% \begin{macrocode}
\clist_map_function:nN { #2 } \group_use:n
% \end{macrocode}
% Execute the hooks, so that local variables will get modified according to the groups
% and in the order that were specified for the hooks.
% \begin{macrocode}
\hook_use:n { @@/prename }
\hook_use:n { @@/postname }
\hook_use:n { @@/mapname }
\hook_use:n { @@/thmtools }
% \end{macrocode}
% We are left with dealing with the obtained data.
% We first map on the name, before appending to it.
% \begin{macrocode}
\clist_map_function:NN \l_@@_mapname_clist \map_use_on_name:n
% \end{macrocode}
% We now glue the name together of its three parts,
% and pass this key directly to the \pkg{thmtools} arguments
% \begin{macrocode}
\clist_put_right:Nx \l_@@_thmtools_clist
{
name = \tl_use:N \l_@@_prename_tl
\tl_use:N \l_@@_name_tl
\tl_use:N \l_@@_postname_tl
}
% \end{macrocode}
% Finally, apply the additional \pkg{thmtools} keys for this specific theorem.
% Putting them last will overwrite keys that were given by the groups.
% \begin{macrocode}
\clist_put_right:n \l_@@_thmtools_clist { #4 }
% \end{macrocode}
% We can now pass our list to \pkg{thmtools}, declaring the theorem.
% \begin{macrocode}
\@@_declare_theorem:nV
{ #1 }
\l_@@_thmtools_clist
}
% \end{macrocode}
% \end{macro}
%
%
%
% As usual, we provide a \texttt{new} and a \texttt{provide} variant wrapped
% around this that do proper error checking.
%
%
%
% \begin{macro}{\groupthm_new_grouped_theorem:nnnn}
% \begin{syntax}
% \cs{groupthm_new_grouped_theorem:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% \begin{macrocode}
\cs_new:Npn \groupthm_new_grouped_theorem:nnnn #1 #2 #3 #4
{
% \end{macrocode}
% Note that the next comparison depends on \pkg{thmtools} declaring
% environments, and that \LaTeX\ handles environments called with the
% |\begin{environment}| syntax by calling |\environment| subsequently.
% \begin{macrocode}
\cs_if_exist:cTF { #1 }
{
\msg_error:{ groupthm } { wrong ~ definition }
{ grouped ~ theorem } { #1 } { already }
}
{
\@@_groupthm_declare_grouped_theorem_aux:nnnn
{ #1 } { #2 } { #3 } { #4 }
}
}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\groupthm_provide_grouped_theorem:nnnn}
% \begin{syntax}
% \cs{groupthm_provide_grouped_theorem:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% \begin{macrocode}
\cs_new:Npn \groupthm_provide_grouped_theorem:nnnn #1 #2 #3 #4
{
% \end{macrocode}
% Note that the next comparison depends on \pkg{thmtools} declaring
% environments, and that \LaTeX\ handles environments called with the
% |\begin{environment}| syntax by calling |\environment| subsequently.
% \begin{macrocode}
\cs_if_exist:cF { #1 }
{
\@@_groupthm_declare_grouped_theorem_aux:nnnn
{ #1 } { #2 } { #3 } { #4 }
}
}
% \end{macrocode}
% \end{macro}
%
%
% The star variants of these that add the \texttt{unnumbered} group
% are straightforward:
%
%
% \begin{macro}{\groupthm_new_grouped_theorem_star:nnnn}
% \begin{syntax}
% \cs{groupthm_new_grouped_theorem_star:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% \begin{macrocode}
\cs_new:Npn \groupthm_new_grouped_theorem_star:nnnn #1 #2 #3 #4
{
\groupthm_new_grouped_theorem:nnnn
{ #1 } { #2, unnumbered } { #3 } { #4 }
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\groupthm_provide_grouped_theorem_star:nnnn}
% \begin{syntax}
% \cs{groupthm_provide_grouped_theorem_star:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% \begin{macrocode}
\cs_new:Npn \groupthm_provide_grouped_theorem_star:nnnn #1 #2 #3 #4
{
\groupthm_provide_grouped_theorem:nnnn
{ #1 } { #2, unnumbered } { #3 } { #4 }
}
% \end{macrocode}
% \end{macro}
%
%
% On top of these, we can provide the shorter versions that will generate
% two theorems each, one with and one without a \enquote{*} in its
% environment name
%
%
%
% \begin{macro}{\groupthm_new_theorem:nnnn}
% \begin{syntax}
% \cs{groupthm_new_theorem:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
%
% \begin{macrocode}
\cs_new:Npn \groupthm_new_theorem:nnnn #1 #2 #3 #4
{
\groupthm_new_grouped_theorem:nnnn
{ #1 } { #2 } { #3 } { #4 }
\groupthm_new_grouped_theorem:nnnn
{ #1* } { #2, starred } { #3 } { #4 }
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\groupthm_provide_theorem:nnnn}
% \begin{syntax}
% \cs{groupthm_provide_theorem:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
%
% \begin{macrocode}
\cs_new:Npn \groupthm_provide_theorem:nnnn #1 #2 #3 #4
{
\groupthm_provide_grouped_theorem:nnnn
{ #1 } { #2 } { #3 } { #4 }
\groupthm_provide_grouped_theorem:nnnn
{ #1* } { #2, starred } { #3 } { #4 }
}
% \end{macrocode}
% \end{macro}
%
%
% Combining these is also not difficult:
%
%
%
%
% \begin{macro}{\groupthm_new_theorem_star:nnnn}
% \begin{syntax}
% \cs{groupthm_new_theorem_star:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% \begin{macrocode}
\cs_new:Npn \groupthm_new_theorem_star:nnnn #1 #2 #3 #4
{
\groupthm_new_theorem:nnnn
{ #1 } { #2, unnumbered } { #3 } { #4 }
}
% \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\groupthm_provide_theorem_star:nnnn}
% \begin{syntax}
% \cs{groupthm_provide_theorem_star:nnnn}\ma{environment name}
% \ma{groups clist}\ma{theorem name}\ma{thmtools keys}
% \end{syntax}
%
% \begin{macrocode}
\cs_new:Npn \groupthm_provide_theorem_star:nnnn #1 #2 #3 #4
{
\groupthm_provide_theorem:nnnn
{ #1 } { #2, unnumbered } { #3 } { #4 }
}
% \end{macrocode}
% \end{macro}
%
% We now provide the corresponding key-valued interfaces around these.
%
%
%
%
%

View file

@ -129,6 +129,21 @@
{ unrelated }
{ #1 }
}
\cs_new:Npn \__groupthm_add_to_sort_hook:n #1
{
\hook_gput_code:nnn { __groupthm/groupsort }
{ #1 }
{
\clist_put_left:Nn \l__groupthm_group_clist { #1 }
}
}
\cs_new:Npn \__groupthm_sort_theorem_group_names:
{
\hook_gremove_code:nn { __groupthm/groupsort }{*}
\clist_map_function:NN \l__groupthm_group_clist \__add_to_sort_hook:n
\clist_clear:N \l__groupthm_group_clist
\hook_use:n { __groupthm/groupsort }
}
\cs_new:Npn \__groupthm_declare_theorem_group_aux:nnnnn #1#2#3#4#5
{
\cs_new:cpn { __groupthm_use_group_#1: }
@ -282,6 +297,33 @@
{
\groupthm_declare_theorem_group_by_keys:nn { #1 } { #2 }
}
\cs_new:Npn \groupthm_declare_theorem_group_rule:nnnn #1 #2 #3 #4
{
\str_set:Nx \l_tmpa_str { \tl_trim_spaces:n { #3 } }
\str_if_eq:VnT \l_tmpa_str { higher }
{
\str_set:Nn \l_tmpa_tl { after }
}
\str_if_eq:VnT \l_tmpa_str { lower }
{
\str_set:Nn \l_tmpa_tl { before }
}
\str_if_eq:nnTF { #1 } { ?? }
{
\hook_gset_rule:nnVn {??} {#2} \l_tmpa_tl {#4}
}
{
\hook_gset_rule:nnVn { __groupthm / #1 } {#2} \l_tmpa_tl {#4}
}
}
\NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m }
{
\groupthm_declare_theorem_group_rule:nnnn {#1} {#2} {#3} {#4}
}
\endinput
%%
%% End of file `groupthm.sty'.