diff --git a/packages/CrossRef.sty b/packages/CrossRef.sty index e032bf0..710bc04 100644 --- a/packages/CrossRef.sty +++ b/packages/CrossRef.sty @@ -26,9 +26,10 @@ \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 \l_label_seq +\seq_new:N \g_label_seq \NewDocumentCommand{\Part}{s t^ m >{\TrimSpaces}m}{ \_heading:nnnnn {part} {#1} {#2} {#3} {#4} @@ -64,7 +65,7 @@ } \NewDocumentCommand{\GetCurrentLabel}{}{ - \seq_use:NV \l_label_seq \c_label_delimiter_str + \seq_use:Nn \g_label_seq {\c_label_delimiter_str} } \NewDocumentCommand{\SetCurrentLabel}{ @@ -73,61 +74,87 @@ % #2: Label string. >{\TrimSpaces}m }{ - \seq_set_split:Nee \l_label_seq {#1} {#2} + \seq_set_split:Nnn \g_label_seq {#1} {#2} } -\int_new:N \l_level_index_int - -\seq_new:N \l_label_temp_seq -\seq_new:N \l_ref_seq - -\str_new:N \l_ref_str - \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} - % #3: Label + % #3: Label Reference >{\TrimSpaces}m % #4: Parent label symbol (defaults to "."). O{\c_label_parent_str} -}{ - \str_set:Nn \l_ref_str {#3} - \str_if_eq:nnTF {\str_head:N \l_ref_str} {#2} { - \str_replace_all:Nnn \l_ref_str {#4} {#2} - \seq_set_split:Nee \l_ref_seq {#2} {#3} - - \int_set:Nn \l_level_index_int {1} - - \int_do_until:nNnn {\l_level_index_int} > {\seq_count:N \l_ref_seq} { - \str_if_empty:nTF {\seq_item:Nn \l_ref_seq {\l_level_index_int}} { - \seq_set_item:Nnn \l_ref_seq { - \l_level_index_int - } { - \seq_item:Nn \l_label_seq {\l_level_index_int} - } - } - \int_incr:N \l_level_index_int - } - - \str_set:Nn \l_ref_str {\seq_use:Nn \l_ref_seq {#1}} - } { - \str_set:Nn \l_ref_str {#3} + % #5: Label wildcard symbol (defaults to "~"). + 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]) } + \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} + + % Split the string on the delimiters. + \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 + + % 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} { + + } { + % 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} { - % Section name \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} }{ + % Otherwise, look up the correct section name. \prop_item:Nn \c_section_names_prop {\seq_count:N \l_ref_seq - 1} } } - \str_put_left:Nn \l_ref_str {\c_label_delimiter_str} - \ref{\l_ref_str} -} + % Create a reference with the string we just created. + \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}} + } + } +\group_end: } + +\int_new:N \l_level_index_int \int_new:N \l_section_level_int \cs_new:Nn \_heading:nnnnn { @@ -146,13 +173,13 @@ \use:c {#1} {#4} } } - \int_set:Nn \l_level_index_int {\seq_count:N \l_label_seq} + \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 \l_label_seq \l_tmpa_tl + \seq_pop_right:NN \g_label_seq \l_tmpa_tl \int_decr:N \l_level_index_int } - \seq_put_right:Nn \l_label_seq {#5} - \str_set:Nn \l_label_str {\seq_use:Nn \l_label_seq \c_label_delimiter_str} + \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} } \ No newline at end of file