494 lines
12 KiB
Text
494 lines
12 KiB
Text
__HEADER__(Grouping theorems for easier customization.)
|
|
|
|
|
|
\ExplSyntaxOn
|
|
|
|
\RequirePackage{amsthm}
|
|
\RequirePackage{thmtools}
|
|
\RequirePackage{mkessler-powerset}
|
|
|
|
\hook_new:n { groupthm / prename }
|
|
\hook_new:n { groupthm / postname }
|
|
\hook_new:n { groupthm / mapname }
|
|
\hook_new:n { groupthm / thmtools }
|
|
|
|
\hook_new:n { groupthm / groupsort }
|
|
|
|
|
|
\newcounter{indocument}
|
|
\newcounter{insection}[section]
|
|
\newcounter{insubsection}[subsection]
|
|
|
|
|
|
%%% LaTeX3 Wrappers around external commands
|
|
|
|
\cs_new:Nn \declaretheorem:nn
|
|
{
|
|
\declaretheorem [ #2 ] { #1 }
|
|
}
|
|
|
|
\cs_generate_variant:Nn \declaretheorem:nn { n V }
|
|
\cs_generate_variant:Nn \hook_gset_rule:nnnn { n n V n }
|
|
|
|
|
|
%%% Messages
|
|
|
|
\msg_new:nnn { groupthm } { unknown ~ key }
|
|
{
|
|
Unknown ~ key ~ '#1' ~ supplied ~ \msg_line_context:
|
|
}
|
|
|
|
\msg_new:nnn { groupthm } { unknown ~ group }
|
|
{
|
|
Unknown ~ group ~ '#1' ~ supplied ~ \msg_line_context:
|
|
}
|
|
|
|
%%% Variables
|
|
|
|
\tl_new:N \l_groupthm_key_prename_tl
|
|
\tl_new:N \l_groupthm_key_name_tl
|
|
\tl_new:N \l_groupthm_key_postname_tl
|
|
\clist_new:N \l_groupthm_key_group_clist
|
|
\clist_new:N \l_groupthm_key_mapname_clist
|
|
\clist_new:N \l_groupthm_key_thmtools_clist
|
|
|
|
\tl_new:N \l_groupthm_prename_tl
|
|
\tl_new:N \l_groupthm_name_tl
|
|
\tl_new:N \l_groupthm_postname_tl
|
|
\tl_new:N \l_groupthm_mapname_clist
|
|
\tl_new:N \l_groupthm_thmtools_clist
|
|
|
|
\tl_new:N \l_groupthm_relation_tl
|
|
|
|
\clist_new:N \l_groupthm_group_clist
|
|
|
|
\clist_new:N \g_groupthm_defined_theorem_groups_clist
|
|
|
|
%%% Keys
|
|
|
|
\keys_define:nn { groupthm }
|
|
{
|
|
prename .tl_set:N = \l_groupthm_key_prename_tl,
|
|
prename .default:n = \c_empty_tl,
|
|
prename .groups:n = { theoremgroup },
|
|
name .tl_set:N = \l_groupthm_key_name_tl,
|
|
name .default:n = \c_novalue_tl,
|
|
name .groups:n = { groupedtheorem, theoremvariants },
|
|
postname .tl_set:N = \l_groupthm_key_postname_tl,
|
|
postname .default:n = \c_empty_tl,
|
|
postname .groups:n = { theoremgroup },
|
|
group .clist_set:N = \l_groupthm_key_group_clist,
|
|
group .default:n = {},
|
|
group .groups:n = { groupedtheorem },
|
|
mapname .clist_set:N = \l_groupthm_mapname_clist,
|
|
mapname .default:n = {},
|
|
mapname .groups:n = { theoremgroup },
|
|
thmtools .clist_set:N = \l_groupthm_thmtools_clist,
|
|
thmtools .default:n = {},
|
|
thmtools .groups:n = { theoremgroup, groupedtheorem, theoremvariants },
|
|
unknown .code:n = \msg_error:nnn { groupthm } { unknown ~ group } { \l_keys_key_str }
|
|
}
|
|
|
|
|
|
% groupname, prename, postname, mapname, thmtools
|
|
\cs_new:Npn \new_theorem_group:nnnnn #1#2#3#4#5
|
|
{
|
|
\cs_new:cpn { group_use_#1: }
|
|
{
|
|
\hook_gput_code:nnn { groupthm / prename } { #1 }
|
|
{
|
|
\tl_put_left:Nx \l_groupthm_prename_tl { #2 }
|
|
}
|
|
\hook_gput_code:nnn { groupthm / postname } { #1 }
|
|
{
|
|
\tl_put_right:Nx \l_groupthm_postname_tl { #3 }
|
|
}
|
|
\hook_gput_code:nnn { groupthm / mapname } { #1 }
|
|
{
|
|
\clist_put_right:Nn \l_groupthm_mapname_clist { #4 }
|
|
}
|
|
\hook_gput_code:nnn { groupthm / thmtools } { #1 }
|
|
{
|
|
\clist_put_right:Nn \l_groupthm_thmtools_clist { #5 }
|
|
}
|
|
}
|
|
|
|
\cs_set:Npn \help:n ##1 {
|
|
\hook_gset_rule:nnnn { groupthm / groupsort }
|
|
{ #1 }
|
|
{ before }
|
|
{ ##1 }
|
|
}
|
|
|
|
\clist_map_function:NN \g_groupthm_defined_theorem_groups_clist \help:n
|
|
|
|
\clist_gput_left:Nn \g_groupthm_defined_theorem_groups_clist { #1 }
|
|
}
|
|
\cs_generate_variant:Nn \new_theorem_group:nnnnn { n V V V V }
|
|
|
|
\cs_new:Npn \new_theorem_group_by_keys:nn #1#2
|
|
{
|
|
\keys_set_groups:nnn { groupthm } { theoremgroup } { prename, postname, mapname, thmtools }
|
|
\keys_set_groups:nnn { groupthm } { theoremgroup } { #2 }
|
|
\new_theorem_group:nVVVV { #1 }
|
|
\l_groupthm_key_prename_tl
|
|
\l_groupthm_key_postname_tl
|
|
\l_groupthm_mapname_clist
|
|
\l_groupthm_thmtools_clist
|
|
}
|
|
|
|
\NewDocumentCommand{\NewTheoremGroup}{ O{} m }
|
|
{
|
|
\new_theorem_group_by_keys:nn { #2 } { #1 }
|
|
}
|
|
|
|
|
|
|
|
%%% Grouped Theorems
|
|
|
|
\cs_new:Npn \group_use:n #1
|
|
{
|
|
\cs_if_exist_use:cF { group_use_#1: }
|
|
{
|
|
\msg_error:nnn { groupthm } { unknown ~ group } { #1 }
|
|
}
|
|
}
|
|
|
|
\cs_new:Npn \map_use_on_name:n #1
|
|
{
|
|
\tl_set:Nx \l_groupthm_name_tl
|
|
{
|
|
#1 { \tl_use:N \l_groupthm_name_tl }
|
|
}
|
|
}
|
|
|
|
% envname, groups, name, thmtools
|
|
\cs_new:Npn \new_grouped_theorem:nnnn #1 #2 #3 #4
|
|
{
|
|
|
|
|
|
\tl_clear:N \l_groupthm_prename_tl
|
|
\tl_set:Nn \l_groupthm_name_tl { #3 }
|
|
\tl_clear:N \l_groupthm_postname_tl
|
|
\clist_clear:N \l_groupthm_mapname_clist
|
|
\clist_set:Nn \l_groupthm_thmtools_clist { #4 }
|
|
|
|
\hook_gremove_code:nn { groupthm / prename }{*}
|
|
\hook_gremove_code:nn { groupthm / postname }{*}
|
|
\hook_gremove_code:nn { groupthm / mapname }{*}
|
|
\hook_gremove_code:nn { groupthm / thmtools }{*}
|
|
|
|
\clist_map_function:nN { #2 } \group_use:n
|
|
|
|
% \ShowHook{ groupthm / postname }
|
|
\hook_use:n { groupthm / prename }
|
|
\hook_use:n { groupthm / postname }
|
|
\hook_use:n { groupthm / mapname }
|
|
\hook_use:n { groupthm / thmtools }
|
|
|
|
\clist_map_function:NN \l_groupthm_mapname_clist \map_use_on_name:n
|
|
|
|
\clist_put_right:Nx \l_groupthm_thmtools_clist
|
|
{
|
|
name = \tl_use:N \l_groupthm_prename_tl
|
|
\tl_use:N \l_groupthm_name_tl
|
|
\tl_use:N \l_groupthm_postname_tl
|
|
}
|
|
|
|
\declaretheorem:nV
|
|
{ #1 }
|
|
\l_groupthm_thmtools_clist
|
|
}
|
|
\cs_generate_variant:Nn \new_grouped_theorem:nnnn { n V V V }
|
|
\cs_generate_variant:Nn \new_grouped_theorem:nnnn { x V n n }
|
|
|
|
% envname, keys
|
|
\cs_new:Npn \new_grouped_theorem_from_keys:nn #1 #2
|
|
{
|
|
\keys_set_groups:nnn { groupthm } { groupedtheorem } { name, group, thmtools }
|
|
\keys_set_groups:nnn { groupthm } { groupedtheorem } { #2 }
|
|
|
|
% Construct name
|
|
\tl_if_eq:NnTF \l_groupthm_key_name_tl { \c_novalue_tl }
|
|
{
|
|
\tl_set:Nx \l_groupthm_name_tl
|
|
{
|
|
\text_titlecase_first:n {#1}
|
|
}
|
|
}
|
|
{
|
|
\tl_set_eq:NN \l_groupthm_name_tl \l_groupthm_key_name_tl
|
|
}
|
|
|
|
\new_grouped_theorem:nVVV
|
|
{ #1 }
|
|
\l_groupthm_key_group_clist
|
|
\l_groupthm_name_tl
|
|
\l_groupthm_key_thmtools_clist
|
|
}
|
|
|
|
\NewDocumentCommand{\NewGroupedTheorem}{O{} m}
|
|
{
|
|
\new_grouped_theorem_from_keys:nn { #2 } { #1 }
|
|
}
|
|
|
|
|
|
|
|
%% Rules for different theorem groups
|
|
|
|
\cs_generate_variant:Nn \hook_gset_rule:nnnn { n n V n }
|
|
|
|
% hook group1 relation group2
|
|
\cs_new:Npn \declare_theorem_group_rule:nnnn #1 #2 #3 #4
|
|
{
|
|
\tl_set:Nx \l_groupthm_relation_tl { \tl_trim_spaces:n { #3 } }
|
|
|
|
\tl_if_eq:nnT { higher } { #3 }
|
|
{
|
|
\tl_set:Nn \l_groupthm_relation_tl { after }
|
|
}
|
|
|
|
\tl_if_eq:nnT { lower } { #3 }
|
|
{
|
|
\tl_set:Nn \l_groupthm_relation_tl { before }
|
|
}
|
|
|
|
\hook_gset_rule:nnVn {#1} {#2} \l_groupthm_relation_tl {#4}
|
|
}
|
|
|
|
% hook, group1, relation, group2
|
|
\NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m }
|
|
{
|
|
\declare_theorem_group_rule:nnnn {#1} {#2} {#3} {#4}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
%%% Hacks for sorting groupnames
|
|
|
|
\cs_new:Npn \__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 \__sort_group_names:
|
|
{
|
|
|
|
% \tl_show:n { sorting}
|
|
% \clist_show:N \l_groupthm_group_clist
|
|
|
|
\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
|
|
% \ShowHook { groupthm / groupsort }
|
|
\hook_use:n { groupthm / groupsort }
|
|
|
|
% \clist_show:N \l_groupthm_group_clist
|
|
}
|
|
|
|
|
|
%%% Theorem variants generation
|
|
|
|
\ExplSyntaxOn
|
|
|
|
% envname, name, thmtools, list of groups
|
|
\cs_new:Npn \generate_theorem_variants:nnnn #1 #2 #3 #4
|
|
{
|
|
\clist_set:Nn \l_groupthm_group_clist { #4 }
|
|
\powerset_clist_foreach:Nn \l_groupthm_group_clist
|
|
{
|
|
\__sort_group_names:
|
|
|
|
% \tl_show:n { Generating new theorem variant }
|
|
% \clist_show:N \l_groupthm_group_clist
|
|
|
|
\new_grouped_theorem:xVnn
|
|
{__#1__groups_\clist_use:Nn \l_groupthm_group_clist {_}}
|
|
\l_groupthm_group_clist
|
|
{ #2 }
|
|
{ #3 }
|
|
}
|
|
}
|
|
\cs_generate_variant:Nn \generate_theorem_variants:nnnn { n V V V }
|
|
|
|
|
|
% envname, keys
|
|
\cs_new:Npn \generate_theorem_variants_from_keys:nn #1 #2
|
|
{
|
|
\keys_set_groups:nnn { groupthm } { theoremvariants } { name, thmtools }
|
|
\keys_set_groups:nnn { groupthm } { theoremvariants } { #2 }
|
|
|
|
\tl_if_eq:NnTF \l_groupthm_key_name_tl { \c_novalue_tl }
|
|
{
|
|
\tl_set:Nx \l_groupthm_name_tl
|
|
{
|
|
\text_titlecase_first:n {#1}
|
|
}
|
|
}
|
|
{
|
|
\tl_set_eq:NN \l_groupthm_name_tl \l_groupthm_key_name_tl
|
|
}
|
|
|
|
\clist_set_eq:NN \l_groupthm_group_clist \l_groupthm_key_group_clist
|
|
|
|
\clist_put_left:Nn \l_groupthm_group_clist { starred }
|
|
|
|
\generate_theorem_variants:nVVV
|
|
{ #1 }
|
|
\l_groupthm_name_tl
|
|
\l_groupthm_key_thmtools_clist
|
|
\l_groupthm_group_clist
|
|
}
|
|
|
|
\NewDocumentCommand { \GenerateTheoremVariants } { O{} m }
|
|
{
|
|
\generate_theorem_variants_from_keys:nn { #2 } { #1 }
|
|
}
|
|
|
|
%%% Theorem variants declaration / parsing
|
|
\cs_new:Npn \add_theorem_to_group:n #1
|
|
{
|
|
\clist_put_left:Nn \l_groupthm_group_clist { #1 }
|
|
}
|
|
|
|
\cs_new:Npn \__new_theorem_variant_parser_aux:nnnn #1 #2 #3 #4
|
|
{
|
|
\exp_args:Nx\NewDocumentEnvironment
|
|
{
|
|
#1\IfBooleanT{#4}{*}
|
|
}
|
|
{#2}
|
|
{
|
|
\clist_clear:N \l_groupthm_group_clist
|
|
|
|
#3
|
|
|
|
\IfBooleanT{#4}
|
|
{
|
|
\add_theorem_to_group:n { starred }
|
|
}
|
|
\__sort_group_names:
|
|
\begin{__#1__groups_\clist_use:Nn \l_groupthm_group_clist{_}}
|
|
}
|
|
{
|
|
\clist_clear:N \l_groupthm_group_clist
|
|
|
|
#3
|
|
|
|
\IfBooleanT{#4}
|
|
{
|
|
\add_theorem_to_group:n { starred }
|
|
}
|
|
\__sort_group_names:
|
|
\end{__#1__groups_\clist_use:Nn \l_groupthm_group_clist{_}}
|
|
}
|
|
}
|
|
|
|
% envname, signature, definition
|
|
\cs_new:Npn \new_theorem_variant_parser:nnn #1 #2 #3
|
|
{
|
|
\__new_theorem_variant_parser_aux:nnnn { #1 } { #2 } { #3 } { \BooleanTrue }
|
|
\__new_theorem_variant_parser_aux:nnnn { #1 } { #2 } { #3 } { \BooleanFalse }
|
|
}
|
|
|
|
%% Exposing clean interface for parsing theorem variants
|
|
|
|
\NewDocumentCommand { \AddTheoremToGroup } { m }
|
|
{
|
|
\add_theorem_to_group:n { #1 }
|
|
}
|
|
|
|
\DeclareDocumentCommand{ \DeclareTheoremVariants }{ m m m }
|
|
{
|
|
\new_theorem_variant_parser:nnn { #1 } { #2 } { #3 }
|
|
}
|
|
|
|
|
|
%%%%% Convenience macros for usage of this package
|
|
|
|
% evname, star?
|
|
\cs_new:Npn \declare_standard_theorem_variants:n #1
|
|
{
|
|
\DeclareTheoremVariants { #1 } { !s !t+ }
|
|
{
|
|
\IfBooleanT{##1}
|
|
{
|
|
\AddTheoremToGroup { star }
|
|
}
|
|
\IfBooleanT{##2}
|
|
{
|
|
\AddTheoremToGroup { dagger }
|
|
}
|
|
}
|
|
}
|
|
|
|
% envname, name, thmtools
|
|
\cs_new:Npn \generate_standard_theorem_variants:nnn #1 #2 #3
|
|
{
|
|
\generate_theorem_variants:nnnn { #1 } { #2 } { #3 } { star, dagger, starred }
|
|
}
|
|
|
|
|
|
% envname, keys
|
|
\cs_new:Npn \generate_standard_theorem_variants_from_keys:nn
|
|
{
|
|
% TODO
|
|
}
|
|
|
|
\DeclareDocumentCommand{\GenerateDefaultTheoremVariants}{ O{} m }
|
|
{
|
|
\generate_standard_theorem_variants_from_keys:nn { #2 } { #1 }
|
|
}
|
|
|
|
%%% Default groups available
|
|
|
|
\NewTheoremGroup
|
|
[
|
|
]{ all }
|
|
|
|
\NewTheoremGroup
|
|
[
|
|
thmtools = { sibling = insection }
|
|
] { big }
|
|
|
|
\NewTheoremGroup
|
|
[
|
|
postname = { $\dagger$ },
|
|
thmtools = { sibling = insubsection }
|
|
] { dagger }
|
|
|
|
\NewTheoremGroup
|
|
[
|
|
thmtools = { sibling = insubsection }
|
|
] { small }
|
|
|
|
\NewTheoremGroup
|
|
[
|
|
thmtools = { sibling = insubsection },
|
|
postname = { * },
|
|
] { star }
|
|
|
|
\NewTheoremGroup
|
|
[
|
|
thmtools = { numbered = no }
|
|
] { starred }
|
|
|
|
\DeclareTheoremGroupRule { big } { incompatible-error } { small }
|
|
|
|
\DeclareTheoremGroupRule { all } { lower } { big }
|
|
\DeclareTheoremGroupRule { all } { lower } { small }
|
|
\DeclareTheoremGroupRule { all } { lower } { dagger }
|
|
\DeclareTheoremGroupRule { all } { lower } { star }
|
|
|
|
\DeclareTheoremGroupRule { starred } { higher } { big }
|
|
\DeclareTheoremGroupRule { starred } { higher } { small }
|
|
\DeclareTheoremGroupRule { starred } { higher } { dagger }
|
|
\DeclareTheoremGroupRule { starred } { higher } { star }
|
|
|
|
\DeclareTheoremGroupRule { starred } { higher } { starred}
|