- Make all packages Expl3.

- Replace ifthen dependency with wrappers for Latex3 conditionals.
- Debug CrossRef and WrapBoxout.
This commit is contained in:
2025-09-18 16:51:12 -05:00
parent 72ab67463b
commit e2a0277635
21 changed files with 278 additions and 183 deletions

View File

@@ -2,19 +2,22 @@
\ProvidesExplPackage{PrimeTeX/packages/CrossRef}{2025-09-16}{1.0}{
Custom label and reference commands.
}
%<@@=CrossRef>
\prop_const_from_keyval:Nn \c_section_names_prop {
0 = Part\nobreakspace,
1 = Chapter\nobreakspace,
2 = Section\nobreakspace,
3 = Subsection\nobreakspace,
4 = Sub-subsection\nobreakspace,
5 = Paragraph\nobreakspace,
6 = Subparagraph\nobreakspace,
9 = Appendix\nobreakspace,
\debug_on:n {all}
\prop_const_from_keyval:Nn \c_@@_section_names_prop {
1 = Part\nobreakspace,
2 = Chapter\nobreakspace,
3 = Section\nobreakspace,
4 = Subsection\nobreakspace,
5 = Sub-subsection\nobreakspace,
6 = Paragraph\nobreakspace,
7 = Subparagraph\nobreakspace,
8 = Appendix\nobreakspace,
}
\prop_const_from_keyval:Nn \c_section_levels_prop {
\prop_const_from_keyval:Nn \c_@@_section_levels_prop {
part = 0,
chapter = 1,
section = 2,
@@ -24,162 +27,196 @@
subparagraph = 6,
}
\str_const:Nn \c_label_delimiter_str {/}
\str_const:Nn \c_label_parent_str {.}
\str_const:Nn \c_label_wildcard_str {~}
\str_const:Nn \c_appendices_label_str {appendices}
\str_const:Nn \c_@@_label_delimiter_str {/}
\str_const:Nn \c_@@_label_parent_str {.}
\str_const:Nn \c_@@_label_wildcard_str {~}
\str_const:Nn \c_@@_appendices_label_str {appendices}
\seq_new:N \g_label_seq
\seq_new:N \g_@@_label_seq
\seq_gclear:N \g_@@_label_seq
\NewDocumentCommand{\Part}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {part} {#1} {#2} {#3} {#4}
\RenewDocumentCommand{\parttitle}{}{#2}
\@@_heading:nnnnn {part} {#1} {#2} {#3} {#4}
\RenewDocumentCommand{\parttitle}{}{#3}
}
\NewDocumentCommand{\Chapter}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {chapter} {#1} {#2} {#3} {#4}
\@@_heading:nnnnn {chapter} {#1} {#2} {#3} {#4}
}
\NewDocumentCommand{\Section}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {section} {#1} {#2} {#3} {#4}
\@@_heading:nnnnn {section} {#1} {#2} {#3} {#4}
}
\NewDocumentCommand{\Subsection}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {subsection} {#1} {#2} {#3} {#4}
\@@_heading:nnnnn {subsection} {#1} {#2} {#3} {#4}
}
\NewDocumentCommand{\Subsubsection}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {subsubsection} {#1} {#2} {#3} {#4}
\@@_heading:nnnnn {subsubsection} {#1} {#2} {#3} {#4}
}
\NewDocumentCommand{\Paragraph}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {paragraph} {#1} {#2} {#3} {#4}
\@@_heading:nnnnn {paragraph} {#1} {#2} {#3} {#4}
}
\NewDocumentCommand{\Subparagraph}{s t^ m >{\TrimSpaces}m}{
\_heading:nnnnn {subparagaph} {#1} {#2} {#3} {#4}
\@@_heading:nnnnn {subparagaph} {#1} {#2} {#3} {#4}
}
\NewDocumentCommand{\Appendices}{}{
\_heading:nnnnn {part} {\c_true_bool} {\c_false_bool} {Appendices} {\c_appendices_label_str}
\@@_heading:nnnnn {part} {\c_true_bool} {\c_false_bool} {Appendices} {\c_@@_appendices_label_str}
}
\NewDocumentCommand{\GetCurrentLabel}{}{
\seq_use:Nn \g_label_seq {\c_label_delimiter_str}
\seq_use:Nn \g_@@_label_seq {\c_@@_label_delimiter_str}
}
\NewDocumentCommand{\SetCurrentLabel}{
% #1: Delimiter
O{\c_label_delimiter_str}
O{\c_@@_label_delimiter_str}
% #2: Label string.
>{\TrimSpaces}m
}{
\seq_set_split:Nnn \g_label_seq {#1} {#2}
\seq_set_split:Nnn \g_@@_label_seq {#1} {#2}
}
\RenewDocumentCommand{\Ref}{
% #1: Star (No star = include section name in reference, star = do not include).
s
% #2: Label string delimiter (defaults to "/").
O{\c_label_delimiter_str}
O{\c_@@_label_delimiter_str}
% #3: Label Reference
>{\TrimSpaces}m
% #4: Parent label symbol (defaults to ".").
O{\c_label_parent_str}
O{\c_@@_label_parent_str}
% #5: Label wildcard symbol (defaults to "~").
O{\c_label_wildcard_str}
O{\c_@@_label_wildcard_str}
}{ \group_begin:
% Put the parameters in string variables so we can work with them.
\str_const:Nn \c_label_delimiter_str {#2}
\str_const:Nn \c_label_parent_str {#4}
\str_const:Nn \c_label_wildcard_str {#5}
\str_const:Ne \c_regex_str {
/|([\c_label_parent_str\c_label_wildcard_str])
\str_const:Nn \c_@@_label_delimiter_str {#2}
\str_const:Nn \c_@@_label_parent_str {#4}
\str_const:Nn \c_@@_label_wildcard_str {#5}
\str_const:Ne \c_@@_regex_str {
% MATCH delimiter, parent, and wildcard symbols, but CAPTURE only
% parents and wildcards, NOT delimiters.
/|(\c_@@_label_parent_str|\c_@@_label_wildcard_str)
}
\seq_new:N \l_label_seq
\seq_new:N \l_ref_seq
\seq_new:N \l_@@_label_seq
\seq_new:N \l_@@_ref_seq
\str_new:N \l_ref_str
\str_set:Nn \l_ref_str {#3}
\str_new:N \l_@@_ref_str
\str_set:Nn \l_@@_ref_str {#3}
% Split the string on the delimiters.
\seq_set_regex_split:NNn \l_ref_seq \c_regex_str {\l_ref_str}
\seq_set_regex_split:NNn \l_@@_ref_seq \c_@@_regex_str {\l_@@_ref_str}
% Copy the current label sequence to a local variable.
\seq_set_eq:NN \l_label_seq \g_label_seq
\seq_set_eq:NN \l_@@_label_seq \g_@@_label_seq
% Iterate through the reference sequence, removing one element from the
% end of the temporary label sequence for each parent symbol.
\seq_map_indexed_function:NN \l_ref_seq \_seq_map:nn
% If the first character in the label string is a delimiter, it is an
% absolute reference and we don't have to do anything to it.
% Otherwise, we have to convert it from a relative reference to an absolute.
\str_if_eq:nnTF {\str_head:N \l_ref_str} {\c_label_delimiter_str} {
\seq_map_indexed_function:NN \l_@@_ref_seq \_seq_map:nn
% % Add the shortened temporary label sequence to the beginning of the
% % reference sequence.
\seq_concat:NNN \l_@@_ref_seq \l_@@_label_seq \l_@@_ref_seq
% % Join the reference sequence back into a delimited string.
\str_set:Nn \l_@@_ref_str {\seq_use:Nn \l_@@_ref_seq {#1}}
\str_if_eq:nnF {\str_head:N \l_@@_ref_str} {\c_@@_label_delimiter_str} {
\str_put_left:Nn \l_@@_ref_str {\c_@@_label_delimiter_str}
}
} {
% Add a delimiter before each parent symbol so we can split the string.
\str_replace_all:Nnn \l_ref_str {\c_label_parent_str} {
\c_label_delimiter_str\c_label_parent_str
}
% Remove empty items from the sequence.
\seq_remove_all:Nn \l_ref_seq {}
% Add the shortened temporary label sequence to the beginning of the
% reference sequence.
\seq_concat:NNN \l_ref_seq \l_label_seq \l_ref_seq
% Join the reference sequence back into a delimited string.
\str_set:Nn \l_ref_str {\seq_use:Nn \l_ref_seq {#1}}
\str_put_left:Nn \l_ref_str {\c_label_delimiter_str}
}
% Output the section name only if no star is passed.
\bool_if:nF {#1} {
\str_if_eq:nnTF {\seq_item:Nn \l_ref_seq {1}} {\c_appendices_label_str} {
\str_if_eq:nnTF {\seq_item:Nn \l_@@_ref_seq {1}} {\c_@@_appendices_label_str} {
% If the part label is "appendices", the section name is "Appendix".
\prop_item:Nn \c_section_names_prop {9}
\prop_item:Nn \c_@@_section_names_prop {9}
}{
% Otherwise, look up the correct section name.
\prop_item:Nn \c_section_names_prop {\seq_count:N \l_ref_seq - 1}
\prop_item:Nn \c_@@_section_names_prop {\seq_count:N \l_@@_ref_seq - 1}
}
}
% Create a reference with the string we just created.
\ref{\l_ref_str}
\ref{\l_@@_ref_str}
\cs_new:Nn \_seq_map:nn {
\str_case:nn {#2} {
{\c_label_parent_str} {\seq_pop_right:NN \l_label_seq \l_tmpa_tl}
{\c_label_wildcard_str} {
\seq_item:Nn \l_label_temp_str {#1}}
{\c_@@_label_parent_str} {
\seq_pop_right:NN \l_@@_label_seq \l_@@_tmpa_tl
\seq_pop_left:NN \l_@@_ref_seq \l_@@_tmpa_tl
}
{\c_@@_label_wildcard_str} {
\seq_pop_left:NN \l_@@_label_seq \l_@@_tmpa_tl
\l_@@_tmpa_tl
}
}
}
\group_end: }
\int_new:N \l_level_index_int
\int_new:N \l_section_level_int
\int_new:N \l_@@_current_level_int
\int_new:N \l_@@_pop_count_int
\int_new:N \l_@@_pop_index_int
\cs_new:Nn \_heading:nnnnn {
\seq_new:N \l_@@_label_seq
\str_new:N \l_@@_label_str
\cs_new:Nn \@@_heading:nnnnn { \group_begin:
% #1: Section name: part, chapter, section, etc.
% #2: Star (passed to default sectioning command)
% #3: ^ token: suppresses sectioning command.
% #4: Section title
% #5: Label
\prop_get:NnN \c_section_levels_prop {#1} \l_section_level_int
\debug_on:n {all}
% Get the numeric level of the section command.
\prop_get:NnN \c_@@_section_levels_prop {#1} \l_@@_current_level_int
% \message{^^J@@_heading:~#5~\seq_use:Ne \g_@@_label_seq {\c_@@_label_delimiter_str}}
\seq_set_eq:NN \l_@@_label_seq \g_@@_label_seq
\int_set:Nn \l_@@_pop_count_int {
\seq_count:N \l_@@_label_seq - \l_@@_current_level_int
}
\int_while_do:nNnn {\l_@@_pop_index_int} < {\l_@@_pop_count_int} {
\seq_if_empty:NF \l_@@_label_seq {
\seq_pop_right:NN \l_@@_label_seq \l_tmpa_tl
}
\int_incr:N \l_@@_pop_index_int
}
% Add the new label to the end of the modified label sequence.
\seq_put_right:Ne \l_@@_label_seq {#5}
\seq_gset_eq:NN \g_@@_label_seq \l_@@_label_seq
% Join the label sequence into a string.
\str_set:Ne \l_@@_label_str {
\seq_use:Ne \l_@@_label_seq {\c_@@_label_delimiter_str}
}
% Add a delimiter to the beginning of the label string to indicate this is
% an absolute reference.
\str_put_left:Ne \l_@@_label_str {\c_@@_label_delimiter_str}
% If the caret argument is NOT present, output the heading.
\bool_if:nF {#3} {
% Pass along the star argument if it is present.
\bool_if:nTF {#2} {
\use:c {#1} * {#4}
} {
\use:c {#1} {#4}
}
}
\int_set:Nn \l_level_index_int {\seq_count:N \g_label_seq}
\int_do_while:nNnn {\l_level_index_int} > {\l_section_level_int} {
\seq_pop_right:NN \g_label_seq \l_tmpa_tl
\int_decr:N \l_level_index_int
}
\seq_put_right:Nn \g_label_seq {#5}
\str_set:Nn \l_label_str {\seq_use:Nn \g_label_seq \c_label_delimiter_str}
\str_put_left:Nn \l_label_str {\c_label_delimiter_str}
\exp_args:Ne \label {\l_label_str}
}
% Output the label.
\exp_args:Ne \label {\l_@@_label_str}
\group_end: }
\debug_off:n {all}