% updatemarks-nums.sty % Copyright 2024 Wenjian Chern. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Wenjian Chern. % % This work consists of the files updatemarks-nums.sty % \@ifundefined{ProvidesExplPackage}{\RequirePackage{expl3}} \ProvidesExplPackage{updatemarks-nums}{2024/02/19}{v0.1}{parse number range} \tl_new:N \l__parserange_tmpa_tl \tl_new:N \l__parserange_tmpb_tl \seq_new:N \l__parserange_tmp_seq \int_new:N \l__parserange_begin_int \int_new:N \l__parserange_end_int \int_new:N \l__parserange_max_int \int_new:N \l__parserange_min_int \bool_new:N \l__parserange_invalid_bool \quark_new:N \q__parserange \cs_new_protected:Npn \parserange_check: { \cs_set_eq:NN \__parserange_single:n \__parserange_single_check:n \cs_set_eq:NN \__parserange_range: \__parserange_range_check: } \cs_new_protected:Npn \parserange_nocheck: { \cs_set_eq:NN \__parserange_single:n \__parserange_single_nocheck:n \cs_set_eq:NN \__parserange_range: \__parserange_range_nocheck: } \cs_new_protected:Npn \parserange:nnnN #1#2#3#4 { \seq_set_eq:NN #4 \c_empty_seq \int_set:Nn \l__parserange_min_int { \__parserange_to_int:n {#1} } \int_set:Nn \l__parserange_max_int { \__parserange_to_int:n {#2} } \clist_map_inline:nn {#3} { \__parserange_aux:n {##1} \bool_if:NF \l__parserange_invalid_bool { \seq_concat:NNN #4 #4 \l__parserange_tmp_seq } } } \cs_generate_variant:Nn \parserange:nnnN { nnvN, nneN } \cs_new_protected:Npn \parserange:nnN { \parserange:nnnN { 1 } } \cs_generate_variant:Nn \parserange:nnN { nvN, neN } \cs_new_protected:Npn \__parserange_aux:n #1 { \bool_set_false:N \l__parserange_invalid_bool \seq_clear:N \l__parserange_tmp_seq \__parserange_action:nnn {#1} { \__parserange_single:n {#1} } { \tl_if_empty:NTF \l__parserange_tmpa_tl { \int_set_eq:NN \l__parserange_begin_int \l__parserange_min_int } { \int_set:Nn \l__parserange_begin_int { \exp_args:No \__parserange_to_int:n \l__parserange_tmpa_tl } } \tl_if_empty:NTF \l__parserange_tmpb_tl { \int_set_eq:NN \l__parserange_end_int \l__parserange_max_int } { \int_set:Nn \l__parserange_end_int { \exp_args:No \__parserange_to_int:n \l__parserange_tmpb_tl } } \__parserange_range: } } \cs_new_protected:Npn \parserange_use_delimiter:n #1 { \tl_if_empty:nTF {#1} { \cs_set:Npn \__parserange_action:nnn ##1 { \__parserange_aux:w ##1 \prg_do_nothing: \q_nil \q__parserange } \cs_set:Npn \__parserange_aux:w ##1##2 ##3 \q__parserange { \tl_set:Nx \l__parserange_tmpa_tl { \tl_trim_spaces:n {##1} } \tl_set:Nx \l__parserange_tmpa_tl { \tl_trim_spaces:n {##2} } \quark_if_nil:nTF {##3} } } { \cs_set:Npn \__parserange_action:nnn ##1 { \__parserange_aux:w ##1 #1 #1 \q__parserange } \cs_set:Npn \__parserange_aux:w ##1 #1 ##2 #1 ##3 \q__parserange { \tl_set:Nx \l__parserange_tmpa_tl { \tl_trim_spaces:n {##1} } \tl_set:Nx \l__parserange_tmpb_tl { \tl_trim_spaces:n {##2} } \tl_if_blank:nTF {##3} } } } \cs_new_protected:Npn \parserange_set_to_int:n { \cs_set:Npn \__parserange_to_int:n ##1 } \parserange_set_to_int:n {#1} \cs_new_protected:Npn \parserange_use_default_delimiter: { \cs_set:Npn \__parserange_action:nnn ##1 { \__parserange_aux:w ##1 -> -> \q__parserange } \cs_set:Npn \__parserange_aux:w ##1 -> ##2 -> ##3 \q__parserange { \tl_set:Nx \l__parserange_tmpa_tl { \tl_trim_spaces:n {##1} } \tl_set:Nx \l__parserange_tmpb_tl { \tl_trim_spaces:n {##2} } \tl_if_blank:nTF {##3} { \use_i:nn } { \use_ii:nn } } } \parserange_use_default_delimiter: % \parserange_use_delimiter:n {->} \cs_new:Npn \__parserange_single_check:n #1 { \bool_lazy_or:nnTF { \int_compare_p:nNn {#1} > \l__parserange_max_int } { \int_compare_p:nNn {#1} < \l__parserange_min_int } { \bool_set_true:N \l__parserange_invalid_bool } { \seq_put_right:Nx \l__parserange_tmp_seq { \int_eval:n { \__parserange_to_int:n {#1} } } } } \cs_new:Npn \__parserange_single_nocheck:n #1 { \seq_put_right:Nx \l__parserange_tmp_seq { \int_eval:n { \__parserange_to_int:n {#1} } } } \cs_new_eq:NN \__parserange_single:n \__parserange_single_check:n \cs_new:Npn \__parserange_range_check: { \int_compare:nNnT \l__parserange_begin_int < \l__parserange_min_int { \int_set_eq:NN \l__parserange_begin_int \l__parserange_min_int } \int_compare:nNnT \l__parserange_end_int > \l__parserange_max_int { \int_set_eq:NN \l__parserange_end_int \l__parserange_max_int } \bool_lazy_or:nnTF { \int_compare_p:nNn \l__parserange_begin_int > \l__parserange_max_int } { \int_compare_p:nNn \l__parserange_begin_int > \l__parserange_end_int } { \bool_set_true:N \l__parserange_invalid_bool } { \int_step_inline:nnn { \l__parserange_begin_int } { \l__parserange_end_int } { \seq_put_right:Nn \l__parserange_tmp_seq {##1} } } } \cs_new:Npn \__parserange_range_nocheck: { \int_compare:nNnTF \l__parserange_begin_int > \l__parserange_end_int { \bool_set_true:N \l__parserange_invalid_bool } { \int_step_inline:nnn { \l__parserange_begin_int } { \l__parserange_end_int } { \seq_put_right:Nn \l__parserange_tmp_seq {##1} } } } \cs_new_eq:NN \__parserange_range: \__parserange_range_check: