diff --git a/README b/README index 0a10f81..e99d361 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -------------------------------------------------------------------------- -XSIM 2020/03/11 v0.19 +XSIM 2020/03/16 v0.19 XSIMVERB 2019/12/29 v0.1a eXercise Sheets IMproved diff --git a/code/xsim.auxfile.code.tex b/code/xsim.auxfile.code.tex index c108eb1..2f31f20 100644 --- a/code/xsim.auxfile.code.tex +++ b/code/xsim.auxfile.code.tex @@ -85,14 +85,8 @@ \xsim_new_aux_property:cpn {readaux} { - % can I do this with expl3? - % cf. issue #60 - \InputIfFileExists { \c_sys_jobname_str .xsim } - { \xsim_verbose:n { Reading~ \c_sys_jobname_str .xsim } } - { - \xsim_verbose:n { \c_sys_jobname_str .xsim~ not~ found.} - \xsim_rerun: - } + \file_if_exist:nT { \c_sys_jobname_str .xsim } + { \file_input:n { \c_sys_jobname_str .xsim } } } % ---------------------------------------------------------------------------- @@ -106,27 +100,6 @@ split-aux-lists .initial:n = || } -\cs_new_protected:Npn \__xsim_set_list_value:nn #1#2 - { - \cs_undefine:c {____xsim_list_ \tl_to_str:n {#1!#2} :} - \cs_new:cpn {____xsim_list_ \tl_to_str:n {#1!#2} :} {} - } - -\cs_new_protected:Npn \__xsim_unset_list_value:nn #1#2 - { \cs_undefine:c {____xsim_list_ \tl_to_str:n {#1!#2} :} } - -% check if in list: -% #1: name -% #2: entry -\prg_new_conditional:Npnn \xsim_if_in_list:nn #1#2 {p,T,F,TF} - { - \cs_if_exist:cTF {____xsim_list_ \tl_to_str:n {#1!#2} :} - { \prg_return_true: } - { \prg_return_false: } - } -\cs_generate_variant:Nn \xsim_if_in_list:nnTF {nx} -\cs_generate_variant:Nn \xsim_if_in_list:nnT {nx} - % define list: % #1: name \cs_new_protected:Npn \xsim_new_list:n #1 @@ -142,7 +115,7 @@ \l__xsim_split_aux_lists_str { \tl_to_str:n {##1} } \seq_map_inline:cn {g__xsim_list_#1_seq} - { \__xsim_set_list_value:nn {#1} {####1} } + { \xsim_attribute_set:nnn {#1} {####1} {} } } } \xsim_at_begin_document:n @@ -165,6 +138,7 @@ { \xsim_verbose:n { Adding~ `#2'~ to~ list~ `#1'. } \str_set:Nn \l__xsim_tmpa_str {#2} + \xsim_attribute_set:nnn {#1} {#2} {} \seq_if_in:cVT {g__xsim_list_#1_seq} \l__xsim_tmpa_str { \seq_gremove_all:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str } \seq_gput_right:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str @@ -177,7 +151,8 @@ { \xsim_verbose:n { Removing~ `#2'~ to~ list~ `#1'. } \str_set:Nn \l__xsim_tmpa_str {#2} - \__xsim_unset_list_value:nn {#1} {#2} + \xsim_attribute_if_set:nnT {#1} {#2} + { \xsim_attribute_unset:nn {#1} {#2} } \seq_if_in:cVT {g__xsim_list_#1_seq} \l__xsim_tmpa_str { \seq_gremove_all:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str } \seq_if_in:cVT {g__xsim_list_recorded#1_seq} \l__xsim_tmpa_str @@ -185,6 +160,18 @@ } \cs_generate_variant:Nn \xsim_remove_from_list:nn {nx} +% check if in list: +% #1: name +% #2: entry +\prg_new_conditional:Npnn \xsim_if_in_list:nn #1#2 {p,T,F,TF} + { + \xsim_attribute_if_set:nnTF {#1} {#2} + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \xsim_if_in_list:nnTF {nx} +\cs_generate_variant:Nn \xsim_if_in_list:nnT {nx} + \bool_new:N \l__xsim_empty_lists_bool \cs_new_protected:Npn \xsim_empty_lists: { \bool_set_true:N \l__xsim_empty_lists_bool } @@ -231,4 +218,4 @@ % ---------------------------------------------------------------------------- \file_input_stop: -2020/03/10 - performance optimizations +2020/03/16 - performance optimizations diff --git a/code/xsim.base.code.tex b/code/xsim.base.code.tex index fbaf246..3bcfb21 100644 --- a/code/xsim.base.code.tex +++ b/code/xsim.base.code.tex @@ -53,7 +53,7 @@ \cs_generate_variant:Nn \seq_if_in:NnT {cV} \cs_generate_variant:Nn \seq_gremove_all:Nn {cV} \cs_generate_variant:Nn \seq_gput_right:Nn {cV} -\cs_generate_variant:Nn \prop_put:Nnn {cxx} +\cs_generate_variant:Nn \prop_put:Nnn {Nnx,cxx} \cs_generate_variant:Nn \prop_gput:Nnn {Nx,Nnx,cxx} \cs_generate_variant:Nn \prop_item:Nn {c} \cs_generate_variant:Nn \prop_if_in:NnTF {Nx} @@ -68,12 +68,11 @@ \cs_generate_variant:Nn \tl_if_eq:nnTF {ff,V} \cs_generate_variant:Nn \tl_if_eq:nnT {x} \cs_generate_variant:Nn \tl_if_blank:nTF {f} -\cs_generate_variant:Nn \tl_set_rescan:Nnn {Nnn} +\cs_generate_variant:Nn \tl_set_rescan:Nnn {Nnx} \cs_generate_variant:Nn \iow_now:Nn {NV} \cs_generate_variant:Nn \str_if_eq:nnT {x} \cs_generate_variant:Nn \str_if_eq:nnF {xx} \cs_generate_variant:Nn \str_if_eq_p:nn {e} -\cs_generate_variant:Nn \iow_now:Nn {NV} \cs_generate_variant:Nn \prg_new_protected_conditional:Npnn {c} % ---------------------------------------------------------------------------- @@ -136,6 +135,13 @@ { \prg_return_false: } } +\prg_new_conditional:Npnn \xsim_if_debug: {p,T,F,TF} + { + \bool_if:NTF \g__xsim_debug_bool + { \prg_return_true: } + { \prg_return_false: } + } + \prg_new_conditional:Npnn \xsim_if_package_blank: {p,T,F,TF} { \bool_if:NTF \g__xsim_blank_bool @@ -198,8 +204,78 @@ % ---------------------------------------------------------------------------- +\msg_new:nnn {xsim} {attribute-not-set} + { The~ attribute~ `#1'~ is~ not~ set~ \msg_line_context: } + +% #1: attribute +% #2: item +\cs_new_protected:Npn \xsim_attribute_new:nn #1#2 + { \cs_new:cpn {____xsim_attribute_ \tl_to_str:n {#1::#2} :} {} } + +% #1: attribute +% #2: item +% #3: value +\cs_new_protected:Npn \xsim_attribute_set:nnn #1#2#3 + { \cs_gset:cpx {____xsim_attribute_ \tl_to_str:n {#1::#2} :} { \exp_not:n {#3} } } +\cs_generate_variant:Nn \xsim_attribute_set:nnn {nnx} + +% #1: attribute +% #2: item +\cs_new_protected:Npn \xsim_attribute_unset:nn #1#2 + { \cs_undefine:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} } + +% #1: attribute +% #2: item +\cs_new:Npn \xsim_attribute_get:nn #1#2 + { + \cs_if_exist:cTF {____xsim_attribute_ \tl_to_str:n {#1::#2} :} + { \use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} } + { + \xsim_if_debug:T + { \msg_expandable_error:nnn {xsim} {attribute-not-set} {#1::#2} } + } + } + +% #1: attribute +% #2: item +\prg_new_conditional:Npnn \xsim_attribute_if_set:nn #1#2 {p,T,F,TF} + { + \cs_if_exist:cTF {____xsim_attribute_ \tl_to_str:n {#1::#2} :} + { \prg_return_true: } + { \prg_return_false: } + } + +% #1: attribute +% #2: item +\prg_new_conditional:Npnn \__xsim_if_attribute_eq:nnn #1#2#3 {p,T,F,TF} + { + \tl_if_eq:enTF + { \use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} } + {#3} + { \prg_return_true: } + { \prg_return_false: } + } + +% #1: attribute +% #2: item +\cs_new_protected:Npn \xsim_attribute_show:nn #1#2 + { + \iow_term:n {} + \iow_term:x + { + \c_space_tl \c_space_tl + \tl_to_str:n {#1::#2} + \c_space_tl \c_space_tl == \c_space_tl \c_space_tl + {\use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :}} + } + \iow_term:n {} + } + +% ---------------------------------------------------------------------------- + \cs_new_protected:Npn \xsim_setup:n #1 { \keys_set:nn {xsim} {#1} } % ---------------------------------------------------------------------------- \file_input_stop: +2020/03/15 - alternative to property lists for performance optimizations diff --git a/code/xsim.collections.code.tex b/code/xsim.collections.code.tex index b85ffa2..5aeb6e2 100644 --- a/code/xsim.collections.code.tex +++ b/code/xsim.collections.code.tex @@ -29,7 +29,7 @@ \xsim_load_modules:n {base} -\prop_new:N \g__xsim_collections_prop +\seq_new:N \g__xsim_collections_seq \bool_new:N \l____xsim_active_bool \msg_new:nnn {xsim} {collection-exists} @@ -66,7 +66,8 @@ { \msg_error:nnn {xsim} {collection-exists} {#1} } { \xsim_verbose:n { Declaring~ new~ collection~ `#1'. } - \prop_gput:Nnn \g__xsim_collections_prop {#1} { \c_false_bool } + \xsim_attribute_set:nnn {collection} {#1} { \c_false_bool } + \seq_gput_right:Nn \g__xsim_collections_seq {#1} \xsim_new_list:n {collection:#1} \seq_new:c {g__xsim_collection_#1_seq} } @@ -75,7 +76,7 @@ % #1: collection name \prg_new_conditional:Npnn \xsim_if_collection_exist:n #1 {T,F,TF} { - \prop_if_in:NnTF \g__xsim_collections_prop {#1} + \seq_if_in:NnTF \g__xsim_collections_seq {#1} { \prg_return_true: } { \prg_return_false: } } @@ -83,7 +84,9 @@ \xsim_new_collection:n {all~ exercises} \cs_new_protected:Npn \xsim_foreach_collection:n #1 - { \prop_map_inline:Nn \g__xsim_collections_prop {#1} } + { \seq_map_inline:Nn \g__xsim_collections_seq {#1} } + +\cs_new:Npn \xsim_collection_map_break: { \seq_map_break: } % ---------------------------------------------------------------------------- @@ -96,7 +99,7 @@ } { \xsim_verbose:n { Activating~ collection~ `#1'. } - \prop_gput:Nnn \g__xsim_collections_prop {#1} { \c_true_bool } + \xsim_attribute_set:nnn {collection} {#1} { \c_true_bool } \tl_if_blank:nF {#2} { \seq_gput_right:cn {g__xsim_collection_#1_seq} {#2} } } @@ -111,8 +114,8 @@ \xsim_if_collection_active:nTF {#1} { \xsim_verbose:n { Deactivating~ collection~ `#1'. } - \prop_gput:Nnn \g__xsim_collections_prop {#1} { \c_false_bool } - \seq_gclear:c {g__xsim_collection_#1_seq} + \xsim_attribute_set:nnn {collection} {#1} { \c_false_bool } + % \seq_gclear:c {g__xsim_collection_#1_seq} } { % TODO: warning } @@ -161,7 +164,7 @@ \seq_if_empty:cTF {g__xsim_collection_#1_seq} { \__xsim_add_to_collection:nnn {#1} {#2} {#3} } { - \seq_if_in:cnT {g__xsim_collection_#1_seq} {#2} + \seq_if_in:cnF {g__xsim_collection_#1_seq} {#2} { \__xsim_add_to_collection:nnn {#1} {#2} {#3} } } } @@ -349,11 +352,11 @@ % #1: collection name \prg_new_conditional:Npnn \xsim_if_collection_active:n #1 {T,F,TF} { - \prop_if_in:NnTF \g__xsim_collections_prop {#1} + \xsim_attribute_if_set:nnTF {collection} {#1} { \bool_lazy_and:nnTF { !\str_if_eq_p:en {#1} {all~ exercises} } - { \prop_item:Nn \g__xsim_collections_prop {#1} } + { \xsim_attribute_get:nn {collection} {#1} } { \prg_return_true: } { \prg_return_false: } } @@ -363,12 +366,12 @@ \prg_new_protected_conditional:Npnn \xsim_if_collections_active: {T,F,TF} { \bool_set_false:N \l____xsim_active_bool - \prop_map_inline:Nn \g__xsim_collections_prop + \xsim_foreach_collection:n { \xsim_if_collection_active:nT {##1} { \bool_set_true:N \l____xsim_active_bool - \prop_map_break: + \xsim_collection_map_break: } } \bool_if:NTF \l____xsim_active_bool @@ -381,7 +384,7 @@ \xsim_at_begin_document:n { \xsim_get_collections: - \xsim_activate_collection:n {all~ exercises} + \xsim_activate_collection:n {all~ exercises} } \xsim_at_end_document:n diff --git a/code/xsim.environments.code.tex b/code/xsim.environments.code.tex index 89f65c0..ca5f76f 100644 --- a/code/xsim.environments.code.tex +++ b/code/xsim.environments.code.tex @@ -55,9 +55,6 @@ \tl_new:N \ExerciseText \tl_set:Nn \ExerciseText { \msg_error:nn {xsim} {only-in-solution} } -\cs_generate_variant:Nn \tl_set_rescan:Nnn {Nnx} -\cs_generate_variant:Nn \prop_put:Nnn {Nnx} - % ---------------------------------------------------------------------------- \msg_new:nnn {xsim} {only-in-solution} diff --git a/code/xsim.exercises.code.tex b/code/xsim.exercises.code.tex index 608eacc..9ba49c6 100644 --- a/code/xsim.exercises.code.tex +++ b/code/xsim.exercises.code.tex @@ -33,10 +33,10 @@ collections } +\seq_new:N \l__xsim_exercise_types_seq \seq_new:N \l__xsim_parameters_seq \seq_new:N \l__xsim_fixed_parameters_seq \seq_new:N \l__xsim_mandatory_parameters_seq -\prop_new:N \g__xsim_exercises_prop \int_gzero_new:N \g_xsim_id_int \int_gzero_new:N \g_xsim_max_id_int \tl_new:N \l_xsim_current_id_tl @@ -78,17 +78,19 @@ % #2: parameter % #3: value \cs_new_protected:Npn \__xsim_set_parameter_type:nnn #1#2#3 - { \cs_set:cpn {__xsim_parameter_ \tl_to_str:n {#1!#2} :} {#3} } + { \xsim_attribute_set:nnn {#1} {#2} {#3} } % #1: type % #2: parameter \cs_new:Npn \xsim_get_parameter:nn #1#2 - { \cs_if_exist_use:c {__xsim_parameter_ \tl_to_str:n {#1!#2} :} } + { \xsim_attribute_get:nn {#1} {#2} } \cs_generate_variant:Nn \xsim_get_parameter:nn {o} +% #1: type +% #2: parameter \prg_new_conditional:Npnn \xsim_if_parameter_set:nn #1#2 {p,T,F,TF} { - \cs_if_exist:cTF {__xsim_parameter_ \tl_to_str:n {#1!#2} :} + \xsim_attribute_if_set:nnTF {#1} {#2} { \prg_return_true: } { \prg_return_false: } } @@ -162,7 +164,7 @@ % #1: type \prg_new_conditional:Npnn \xsim_if_type:n #1 {p,T,F,TF} { - \cs_if_exist:cTF {--__xsim_#1_type_parameter:} + \seq_if_in:NnTF \l__xsim_exercise_types_seq {#1} { \prg_return_true: } { \prg_return_false: } } @@ -282,7 +284,7 @@ \cs_new_protected:Npn \xsim_define_exercise_type_variables:n #1 { - % \prop_new:c {l__xsim_#1_type_parameters_prop} + \seq_put_right:Nn \l__xsim_exercise_types_seq {#1} \bool_new:c {l__xsim_#1_solution_print_bool} \bool_new:c {l__xsim_#1_exercise_print_bool} \bool_new:c {l__xsim_#1_exercise_use_bool} @@ -631,4 +633,4 @@ 2020/02/21 - implement issue #2 2020/03/01 - add options `s/name` and `/name` 2020/03/07 - set \ExerciseID and \ExerciseType only locally -2020/03/11 - performance optimizations +2020/03/14 - performance optimizations diff --git a/code/xsim.modules.code.tex b/code/xsim.modules.code.tex index bc82dcb..51b595f 100644 --- a/code/xsim.modules.code.tex +++ b/code/xsim.modules.code.tex @@ -87,7 +87,7 @@ { \msg_error:nnn {xsim} {module-missing} {#1} } } } -\cs_generate_variant:Nn \__xsim_load_module:n { V } +\cs_generate_variant:Nn \__xsim_load_module:n {V} \prg_new_conditional:Npnn \xsim_if_module_loaded:n #1 {p,T,F,TF} { @@ -163,8 +163,6 @@ \tl_set:Nx \l__xsim_module_version_tl {\c_xsim_version_tl} } -\cs_generate_variant:Nn \str_if_eq:nnF {xx} - \cs_new_protected:Npn \__xsim_module:nn #1#2 { \seq_gput_right:Nn \g__xsim_loaded_modules_seq {#1} diff --git a/code/xsim.properties.code.tex b/code/xsim.properties.code.tex index 28ec7d9..12a6fdf 100644 --- a/code/xsim.properties.code.tex +++ b/code/xsim.properties.code.tex @@ -66,26 +66,8 @@ % #1: type % #2: id % #3: property -\cs_new_protected:Npn \____xsim_define_property:nnn #1#2#3 - { \cs_new:cpn {____xsim_property_ \tl_to_str:n {#1!#2!#3} :} {} } - -% #1: type -% #2: id -% #3: property -\cs_new_protected:Npn \____xsim_set_property:nnnn #1#2#3#4 - { \cs_set:cpn {____xsim_property_ \tl_to_str:n {#1!#2!#3} :} {#4} } - -% #1: type -% #2: id -% #3: property -\cs_new_protected:Npn \____xsim_unset_property:nnn #1#2#3 - { \cs_undefine:c {____xsim_property_ \tl_to_str:n {#1!#2!#3} :} } - -% #1: type -% #2: id -% #3: property -\cs_new:Npn \____xsim_get_property:nnn #1#2#3 - { \cs_if_exist_use:c {____xsim_property_ \tl_to_str:n {#1!#2!#3} :} } +\cs_new_protected:Npn \__xsim_define_property:nnn #1#2#3 + { \xsim_attribute_new:nn {#1!#2} {#3} } % check if property is set: % #1: type @@ -93,7 +75,7 @@ % #3: property \prg_new_conditional:Npnn \xsim_if_property_set:nnn #1#2#3 {p,T,F,TF} { - \cs_if_exist:cTF {____xsim_property_ \tl_to_str:n {#1!#2!#3} :} + \xsim_attribute_if_set:nnTF {#1!#2} {#3} { \prg_return_true: } { \prg_return_false: } } @@ -132,8 +114,6 @@ \seq_if_in:NnF \l__xsim_unique_properties_seq {#4} { \seq_put_right:Nn \l__xsim_unique_properties_seq {#4} } \seq_new:c {l__xsim_unique_property_#4_values_seq} - \prop_new:c {g__xsim_property_#4_type_prop} - \prop_new:c {g__xsim_property_#4_id_prop} } { \xsim_verbose:n { Declaring~ new~ exercise~ property~ `#4'. } } } @@ -259,6 +239,17 @@ \__xsim_set_property_reverse:nnnn {#1} {#2} {#3} {#4} } +% #1: type +% #2: id +% #3: property +\cs_new_protected:Npn \__xsim_unset_property:nnn #1#2#3 + { + \xsim_verbose:n + { Un-setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'. } + \__xsim_remove_property_from_list:nnn {#1} {#2} {#3} + \xsim_attribute_unset:nn {#1!#2} {#3} + } + % #1: type % #2: id % #3: property @@ -284,7 +275,7 @@ \__xsim_remove_property_from_list:nnn {#1} {#2} {#3} % now we can safely add the property to the list: \xsim_add_to_list:nn {#3} {#1-#2=={#4}} - \____xsim_set_property:nnnn {#1} {#2} {#3} {#4} + \xsim_attribute_set:nnn {#1!#2} {#3} {#4} } \cs_generate_variant:Nn \__xsim_set_property:nnnn {VVnV} @@ -294,19 +285,8 @@ % #4: value \cs_new_protected:Npn \__xsim_set_property_reverse:nnnn #1#2#3#4 { - \prop_gput:cnn {g__xsim_property_#3_type_prop} {#4} {#1} - \prop_gput:cnn {g__xsim_property_#3_id_prop} {#4} {#2} - } - -% #1: type -% #2: id -% #3: property -\cs_new_protected:Npn \__xsim_unset_property:nnn #1#2#3 - { - \xsim_verbose:n - { Un-setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'. } - \__xsim_remove_property_from_list:nnn {#1} {#2} {#3} - \____xsim_unset_property:nnn {#1} {#2} {#3} + \xsim_attribute_set:nnn {type:#3} {#4} {#1} + \xsim_attribute_set:nnn {id:#3} {#4} {#2} } \tl_set:Nx \l__xsim_tmpa_tl { \cs_to_str:N \{ } @@ -324,6 +304,9 @@ \str_set:Nn #3 {#6} } +% #1: type +% #2: id +% #3: property \cs_new_protected:Npn \__xsim_remove_property_from_list:nnn #1#2#3 { % make sure we change the entry if it has been recorded previously: @@ -391,20 +374,19 @@ % ---------------------------------------------------------------------------- -\prop_new:N \g__xsim_property_aliases_prop \seq_new:N \g__xsim_property_aliases_seq % #1: property \prg_new_conditional:Npnn \xsim_if_property_alias:n #1 {p,T,F,TF} { - \prop_if_in:NnTF \g__xsim_property_aliases_prop {#1} + \seq_if_in:NnTF \g__xsim_property_aliases_seq {#1} { \prg_return_true: } { \prg_return_false: } } % #1: property \cs_new:Npn \xsim_property_alias:n #1 - { \prop_item:Nn \g__xsim_property_aliases_prop {#1} } + { \xsim_attribute_get:nn {#1} {alias} } % #1: property % #2: alias of @@ -414,8 +396,7 @@ { \xsim_verbose:n { Making~ property~ `#1'~ an~ alias~ of~ property~ `#2'. } - \prop_new:c {g__xsim_property_#1_alias_prop} - \prop_gput:Nnn \g__xsim_property_aliases_prop {#1} {#2} + \xsim_attribute_set:nnn {#1} {alias} {#2} \seq_gput_right:Nn \g__xsim_property_aliases_seq {#1} } } @@ -440,8 +421,7 @@ \xsim_if_property_set:nnxT {#1} {#2} { \xsim_property_alias:n {#3} } { - \prop_gput:cxx {g__xsim_property_#3_alias_prop} - { \xsim_get_property:nnn {#1} {#2} {#3} } + \xsim_attribute_set:nnx {alias:#1!#2} {#3} { \xsim_get_property:nnf {#1} {#2} { \xsim_property_alias:n {#3} } @@ -465,18 +445,18 @@ % #2: id % #3: property \cs_new:Npn \xsim_get_property:nnn #1#2#3 - { \____xsim_get_property:nnn {#1} {#2} {#3} } + { \xsim_attribute_get:nn {#1!#2} {#3} } \cs_generate_variant:Nn \xsim_get_property:nnn {nx,ne,xx,oo,no,nnf,nf,oof,nV} % #1: property % #2: value \cs_new:Npn \xsim_get_id_for_property:nn #1#2 - { \prop_item:cn {g__xsim_property_#1_id_prop} {#2} } + { \xsim_attribute_get:nn {id:#1} {#2} } % #1: property % #2: value \cs_new:Npn \xsim_get_type_for_property:nn #1#2 - { \prop_item:cn {g__xsim_property_#1_type_prop} {#2} } + { \xsim_attribute_get:nn {type:#1} {#2} } \cs_generate_variant:Nn \xsim_get_type_for_property:nn {nV} % #1: id or ID @@ -557,4 +537,4 @@ % ---------------------------------------------------------------------------- \file_input_stop: 2020/03/09 - add meaningful error if a comma is missing in the property list -2020/03/10 - performance optimizations +2020/03/14 - performance optimizations diff --git a/code/xsim.random.code.tex b/code/xsim.random.code.tex index 4229637..cdd23e3 100644 --- a/code/xsim.random.code.tex +++ b/code/xsim.random.code.tex @@ -94,7 +94,7 @@ % #1: random list id % #2: sequence variable to set list from \cs_new_protected:Npn \xsim_save_random_list:nN #1#2 - { + { % TODO: check if #2 is empty \xsim_random_list_if_exist:nF {#1} { \xsim_new_random_list:n {#1} } \xsim_random_list_if_empty:nT {#1} @@ -103,6 +103,7 @@ \xsim_add_property_to_aux:nn {random} { {#1} { \xsim_use_random_list:nn {#1} {,} } } } +\cs_generate_variant:Nn \xsim_save_random_list:nN {x} % #1: collection % #2: number of items @@ -142,7 +143,7 @@ { \l__xsim_tmpa_int } \g__xsim_random_list_seq } - \xsim_save_random_list:nN + \xsim_save_random_list:xN { \int_to_alph:n { \g__xsim_random_list_id_int } } \g__xsim_random_list_seq \xsim_verbose:x diff --git a/code/xsim.solutions.code.tex b/code/xsim.solutions.code.tex index 2666d1a..0a69194 100644 --- a/code/xsim.solutions.code.tex +++ b/code/xsim.solutions.code.tex @@ -35,7 +35,7 @@ \bool_new:N \l__xsim_printsolutions_conditions_bool \bool_new:N \l____xsim_this_condition_bool -\prop_new:N \l__xsim_printsolutions_conditions_prop +\seq_new:N \l__xsim_printsolutions_conditions_seq \int_new:N \l_xsim_printsolutions_section_int \int_new:N \l_xsim_printsolutions_chapter_int @@ -194,7 +194,8 @@ \cs_new_protected:Npn \xsim_declare_printsolutions_condition:nn #1#2 { \bool_new:c {l__xsim_printsolutions_#1_condition_bool} - \prop_put:Nnn \l__xsim_printsolutions_conditions_prop {#1} {#2} + \seq_put_right:Nn \l__xsim_printsolutions_conditions_seq {#1} + \xsim_attribute_set:nnn {printsolutions} {#1} {#2} } \prg_new_conditional:Npnn \__xsim_printsolutions_if_condition:n #1 {T,F,TF} @@ -218,11 +219,12 @@ { \__xsim_printsolutions_condition_false: \bool_set_true:N \l____xsim_this_condition_bool - \prop_map_inline:Nn \l__xsim_printsolutions_conditions_prop + \seq_map_inline:Nn \l__xsim_printsolutions_conditions_seq { \bool_if:cT {l__xsim_printsolutions_##1_condition_bool} { - ##2 {#1} {#2} {#3} + \xsim_attribute_get:nn {printsolutions} {##1} + {#1} {#2} {#3} { } { \bool_set_false:N \l____xsim_this_condition_bool } } @@ -409,3 +411,4 @@ \file_input_stop: 2020/02/23 - resolve bug #56 +2020/03/16 - performance optimizations diff --git a/code/xsim.sty b/code/xsim.sty index dc5b761..79ab9b4 100644 --- a/code/xsim.sty +++ b/code/xsim.sty @@ -29,7 +29,7 @@ \ExplSyntaxOn -\tl_const:Nn \c_xsim_date_tl {2020/03/11} +\tl_const:Nn \c_xsim_date_tl {2020/03/16} \tl_const:Nn \c_xsim_version_major_number_tl {0} \tl_const:Nn \c_xsim_version_minor_number_tl {19} \tl_const:Nn \c_xsim_version_subrelease_tl {} @@ -57,6 +57,7 @@ \bool_new:N \g__xsim_final_bool \bool_new:N \g__xsim_verbose_bool +\bool_new:N \g__xsim_debug_bool \bool_new:N \g_xsim_clear_aux_bool \bool_new:N \g__xsim_write_to_file_bool \bool_new:N \g_xsim_use_aux_bool @@ -67,6 +68,7 @@ { final .bool_gset:N = \g__xsim_final_bool , verbose .bool_gset:N = \g__xsim_verbose_bool , + debug .bool_gset:N = \g__xsim_debug_bool , clear-aux .bool_gset:N = \g_xsim_clear_aux_bool , no-files .bool_gset_inverse:N = \g__xsim_write_to_file_bool , no-files .initial:n = false , @@ -82,6 +84,7 @@ { final .code:n = \msg_error:nnn {xsim} {load-time-option} {final} , verbose .code:n = \msg_error:nnn {xsim} {load-time-option} {verbose} , + debug .code:n = \msg_error:nnn {xsim} {load-time-option} {debug} , clear-aux .code:n = \msg_error:nnn {xsim} {load-time-option} {clear-aux} , no-files .code:n = \msg_error:nnn {xsim} {load-time-option} {no-files} , use-aux .code:n = \msg_error:nnn {xsim} {load-time-option} {use-aux} , diff --git a/code/xsim.templates.code.tex b/code/xsim.templates.code.tex index 7644074..35bd173 100644 --- a/code/xsim.templates.code.tex +++ b/code/xsim.templates.code.tex @@ -36,11 +36,21 @@ I~ am~ using~ the~ template~ `#3'~ (template~ type~ `#1')~ instead. } +\msg_new:nnn {xsim} {template-type-exists} + { The~ template~ type~ `#1'~ already~ exists~ \msg_line_context: } + +% ---------------------------------------------------------------------------- +\seq_new:N \l__xsim_template_types_seq + % #1: template type \cs_new_protected:Npn \xsim_new_template_type:n #1 { - \xsim_verbose:n { Declaring~ new~ template~ type~ `#1'. } - \prop_new:c {l__xsim_#1_template_prop} + \seq_if_in:NnTF \l__xsim_template_types_seq {#1} + { \msg_error:nnn {xsim} {template-type-exists} {#1} } + { + \xsim_verbose:n { Declaring~ new~ template~ type~ `#1'. } + \seq_put_right:Nn \l__xsim_template_types_seq {#1} + } } % #1: template type @@ -50,12 +60,12 @@ { \xsim_verbose:n { Defining~ new~ template~ `#2'~ of~ type~ `#1'. } \tl_new:c {l__xsim_template_#1_#2_setup_tl} - \prop_put:cnn {l__xsim_#1_template_prop} {#2} {#3} + \xsim_attribute_set:nnn {template::#1} {#2} {#3} } \prg_new_conditional:Npnn \xsim_if_template_exist:nn #1#2 {T,F,TF} { - \prop_if_in:cnTF {l__xsim_#1_template_prop} {#2} + \xsim_attribute_if_set:nnTF {template::#1} {#2} { \prg_return_true: } { \prg_return_false: } } @@ -63,7 +73,7 @@ % #1: template type % #2: template name \cs_new_protected:Npn \__xsim_get_template:nn #1#2 - { \prop_item:cn {l__xsim_#1_template_prop} {#2} } + { \xsim_attribute_get:nn {template::#1} {#2} } % ---------------------------------------------------------------------------- diff --git a/doc/examples/xsim.collections.tex b/doc/examples/xsim.collections.tex index beca191..990391e 100644 --- a/doc/examples/xsim.collections.tex +++ b/doc/examples/xsim.collections.tex @@ -5,7 +5,7 @@ \DeclareExerciseCollection{foo-medium} \DeclareExerciseTagging{difficulty} -\usepackage{filecontents,lipsum} +\usepackage{lipsum} \begin{filecontents*}{foo.tex} \begin{exercise}[difficulty=easy,points=1] foo one \lipsum[4] diff --git a/doc/xsim-manual.cls b/doc/xsim-manual.cls index 1209f2f..e40029d 100644 --- a/doc/xsim-manual.cls +++ b/doc/xsim-manual.cls @@ -492,7 +492,7 @@ \tcbset{enhanced,enhanced jigsaw} \newtcolorbox{bewareofthedog}{ - colback = white , + colback = red!2!white!98 , colframe = red , underlay={% \path[draw=none] @@ -595,21 +595,7 @@ \cnltx@after@example@hook }% \endcnltxcode - }\newcommand*\xsimman@readoptions[1]{% - \catcode`\^^M=13 - \xsimman@read@options{#1}% -} - -\begingroup -\catcode`\^^M=13 -\gdef\xsimman@read@options#1#2^^M{% - \ifblank{#2}{}{\xsimman@read@options@#2}% - #1% - \XSIMfilewritestart*{\jobname.tmp}% -}% -\endgroup - -\def\xsimman@read@options@[#1]{\pgfqkeys{/cnltx}{#1}} + } \RenewDocumentEnvironment{sourcecode}{} {% @@ -983,6 +969,7 @@ \xsim@add@version{0.16a} {2020-01-16} \xsim@add@version{0.17} {2020-02-21} \xsim@add@version{0.18} {2020-02-23} +\xsim@add@version{0.19} {2020-03-16} % ---------------------------------------------------------------------------- \newrobustcmd*\xsimauxfileinfo{% diff --git a/doc/xsim.history b/doc/xsim.history index cb9fd8e..ca36c27 100644 --- a/doc/xsim.history +++ b/doc/xsim.history @@ -148,7 +148,8 @@ HISTORY: - change \printexercise and \printsolution to accept a clist of either ids or IDs (or mixed) - new templates in the `layouts' style - v0.19 2020/03/11 - improve performance + v0.19 2020/03/16 - improve performance - only set \ExerciseID and \ExerciseType locally to ensure correct values when exercises (of different types) are nested + - new load-time option `debug' - only for development diff --git a/doc/xsim_manual.pdf b/doc/xsim_manual.pdf index 03d1892..f3d4e64 100644 Binary files a/doc/xsim_manual.pdf and b/doc/xsim_manual.pdf differ diff --git a/doc/xsim_manual.tex b/doc/xsim_manual.tex index e301758..d3adf28 100644 --- a/doc/xsim_manual.tex +++ b/doc/xsim_manual.tex @@ -68,6 +68,9 @@ \section{Licence, Requirements and \texorpdfstring{\textsc{readme}}{README}} package. Be careful: if you're in the middle of an important project it might be better to wait with the update until you've finished the project. Every update might be breaking some things. + + Please also be aware that \xsim\ is actively developed and many things may + still change. However, I will try my best to keep the interface stable. \end{bewareofthedog} \section{Motivation and Background} @@ -1483,6 +1486,10 @@ \subsubsection{Further Commands for Usage in Template Definitions} Can be used to refer to the current exercise type. \expandable\command{ExerciseID} Can be used to refer to the current exercise id. + \expandable\command{ExerciseText} + Can be used inside solutions to retrieve the text of the corresponding + solution. This is propably seldom useful as in most use cases the + exercise property \property{solution} is the easier alternative. \expandable\command{ExerciseCollection} Can be used in certain templates to refer to the collection that is currently inserted.