diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex b/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex new file mode 100644 index 00000000000..ec88d1be00a --- /dev/null +++ b/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex @@ -0,0 +1,495 @@ +% ---------------------------------------------------------------------------- +% the XSIM package - properties module +% +% eXercise Sheets IMproved +% +% ---------------------------------------------------------------------------- +% Clemens Niederberger +% Web: https://github.com/cgnieder/xsim +% E-Mail: contact@mychemistry.eu +% ---------------------------------------------------------------------------- +% Copyright 2017 Clemens Niederberger +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 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 Clemens Niederberger. +% ---------------------------------------------------------------------------- +% If you have any ideas, questions, suggestions or bugs to report, please +% feel free to contact me. +% ---------------------------------------------------------------------------- +\XSIMmodule{properties}{properties of exercises} + +\xsim_load_modules:n {base,auxfile} + +\msg_new:nnn {xsim} {unknown-property} + { + You~ tried~ to~ set~ the~ property~ `#1'~ \msg_line_context: . \\ + This~ property~ does~ not~ exist.~ Check~ for~ a~ typo~ or~ \\ + define~ the~ property~ yourself. + } + +\msg_new:nnn {xsim} {property-unique} + { + You~ tried~ to~ set~ the~ property~ `#1'~ \msg_line_context: . \\ + This~ property~ has~ to~ have~ a~ unique~ value~ and~ thus~ \\ + cannot~ be~ set~ to~ `#2'~ since~ this~ value~ is~ already~ talen. + } + +\msg_new:nnn {xsim} {no-boolean-property} + { + You~ tried~ to~ check~ the~ boolean~ value~ of~ property~ `#1'~ + \msg_line_context: . \\ + However,~ property~ `#1'~ is~ not~ a~ boolean~ property! + } + +\seq_new:N \l__xsim_properties_seq +\seq_new:N \l__xsim_boolean_properties_seq +\seq_new:N \l__xsim_unique_properties_seq +\seq_new:N \l__xsim_noupdate_properties_seq +\prop_new:N \g__xsim_properties_prop + +% new property: +% #1: boolean if unique +% #2: boolean if boolean +% #3: boolean if noupdate +% #4: property name +\cs_new_protected:Npn \xsim_declare_property:nnnn #1#2#3#4 + { + \xsim_if_property_exist:nF {#4} + { + \seq_put_right:Nn \l__xsim_properties_seq {#4} + \bool_if:nTF {#3} + { + \seq_if_in:NnF \l__xsim_noupdate_properties_seq {#4} + { \seq_put_right:Nn \l__xsim_noupdate_properties_seq {#4} } + } + { \xsim_new_list:n {#4} } + \bool_if:nTF {#2} + { + \xsim_verbose:n + { Declaring~ new~ boolean~ exercise~ property~ `#4'. } + \seq_if_in:NnF \l__xsim_boolean_properties_seq {#4} + { \seq_put_right:Nn \l__xsim_boolean_properties_seq {#4} } + } + { + \bool_if:nTF {#1} + { + \xsim_verbose:n + { Declaring~ new~ unique~ exercise~ property~ `#4'. } + \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'. } } + } + \bool_if:nF {#3} + { + \AtEndDocument { \xsim_update_list:n {#4} } + \AtBeginDocument { \__xsim_set_property_from_list:n {#4} } + } + } + } + +% check if property exists: +\prg_new_conditional:Npnn \xsim_if_property_exist:n #1 {p,T,F,TF} + { + \seq_if_in:NnTF \l__xsim_properties_seq {#1} + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \xsim_if_property_exist:nTF {x} + +\prg_new_conditional:Npnn \xsim_if_property_noupdate:n #1 {p,T,F,TF} + { + \seq_if_in:NnTF \l__xsim_noupdate_properties_seq {#1} + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \xsim_if_property_noupdate:nF {V} + +\prg_new_conditional:Npnn \xsim_if_property_boolean:n #1 {p,T,F,TF} + { + \seq_if_in:NnTF \l__xsim_boolean_properties_seq {#1} + { \prg_return_true: } + { \prg_return_false: } + } + +\prg_new_conditional:Npnn \xsim_if_property_unique:n #1 {p,T,F,TF} + { + \seq_if_in:NnTF \l__xsim_unique_properties_seq {#1} + { \prg_return_true: } + { \prg_return_false: } + } + +% #1: property +% #2: value +\prg_new_conditional:Npnn \xsim_if_property_unique_value:nn #1#2 {p,T,F,TF} + { + \xsim_if_property_unique:nTF {#1} + { + \seq_if_in:cnTF {l__xsim_unique_property_#1_values_seq} {#2} + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } + +% #1: type +% #2: id +% #3: property +% #4: value +\cs_new_protected:Npn \xsim_set_property:nnnn #1#2#3#4 + { + \xsim_if_property_exist:nTF {#3} + { + \xsim_if_property_set:nnnTF {#1} {#2} {#3} + { + \xsim_if_property_unique_value:nnTF {#3} {#4} + { \msg_warning:nnnn {xsim} {property-unique} {#3} {#4} } + { + \xsim_if_property_boolean:nTF {#3} + { \__xsim_set_boolean_property:nnnn {#1} {#2} {#3} {#4} } + { + \xsim_if_property_unique:nTF {#3} + { \__xsim_set_unique_property:nnnn {#1} {#2} {#3} {#4} } + { \__xsim_set_property:nnnn {#1} {#2} {#3} {#4} } + } + } + } + { + \xsim_if_property_boolean:nTF {#3} + { \__xsim_set_boolean_property:nnnn {#1} {#2} {#3} {#4} } + { + \xsim_if_property_unique:nTF {#3} + { \__xsim_set_unique_property:nnnn {#1} {#2} {#3} {#4} } + { \__xsim_set_property:nnnn {#1} {#2} {#3} {#4} } + } + } + } + { \msg_error:nnn {xsim} {unknown-property} {#3} } + } +\cs_generate_variant:Nn \xsim_set_property:nnnn {nnxx,nnnV,nV,nVnx,nnnx} + +\cs_new_protected:Npn \__xsim_set_boolean_property:nnnn #1#2#3#4 + { + \str_case_x:nnTF { \str_lower_case:n {#4} } + { + {} {} + {true} {} + } + { \__xsim_set_property:nnnn {#1} {#2} {#3} {true} } + { \__xsim_set_property:nnnn {#1} {#2} {#3} {false} } + } + +\cs_new_protected:Npn \__xsim_set_unique_property:nnnn #1#2#3#4 + { + \__xsim_set_property:nnnn {#1} {#2} {#3} {#4} + \__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_if_property_exist:nTF {#3} + { \__xsim_unset_property:nnn {#1} {#2} {#3} } + { \msg_error:nnn {xsim} {unknown-property} {#3} } + } +\cs_generate_variant:Nn \xsim_unset_property:nnn {nx,nnx,nV} + +% #1: type +% #2: id +% #3: property +% #4: value +\cs_new_protected:Npn \__xsim_set_property:nnnn #1#2#3#4 + { + \xsim_verbose:n + { + Setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'~ to~ + value~ `#4'. + } + \__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}} + \prop_gput:Nnn \g__xsim_properties_prop {#2!#1!#3} {#4} + } +\cs_generate_variant:Nn \__xsim_set_property:nnnn {VVnV} + +% #1: type +% #2: id +% #3: property +% #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} + \prop_gremove:Nn \g__xsim_properties_prop {#2!#1!#3} + } + +\tl_set:Nx \l__xsim_tmpa_tl { \cs_to_str:N \{ } +\tl_set:Nx \l__xsim_tmpb_tl { \cs_to_str:N \} } +\use:x + { + \cs_new_protected:Npn + \exp_not:N \__xsim_extract_property_list_entry:NNNwww + ##1##2##3##4-##5== \l__xsim_tmpa_tl ##6 \l__xsim_tmpb_tl + \exp_not:N \q_stop + } + { + \str_set:Nn #1 {#4} + \str_set:Nn #2 {#5} + \str_set:Nn #3 {#6} + } + +\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: + \xsim_foreach_list_entry:nn {#3} + { + \__xsim_extract_property_list_entry:NNNwww + \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop + \str_if_eq:xnT { \l__xsim_tmpa_str - \l__xsim_tmpb_str } {#1-#2} + { + \xsim_remove_from_list:nx {#3} + { #1-#2 == {\l__xsim_tmpc_str} } + } + } + % make sure we change the entry if it has been set during the current run: + \xsim_foreach_new_list_entry:nn {#3} + { + \__xsim_extract_property_list_entry:NNNwww + \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop + \str_if_eq:xnT { \l__xsim_tmpa_str - \l__xsim_tmpb_str } {#1-#2} + { + \xsim_remove_from_list:nx {#3} + { #1-#2 == {\l__xsim_tmpc_str} } + } + } + } + +\cs_new_protected:Npn \__xsim_set_property_from_list:n #1 + { + \xsim_foreach_list_entry:nn {#1} + { + \__xsim_extract_property_list_entry:NNNwww + \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop + \tl_set_rescan:Nnx \l__xsim_tmpc_tl {} { \l__xsim_tmpc_str } + \__xsim_set_property:VVnV + \l__xsim_tmpa_str + \l__xsim_tmpb_str + {#1} + \l__xsim_tmpc_tl + } + } + +% set properties: +% #1: type +% #2: id +% #3: csv list of properties +\cs_new_protected:Npn \xsim_set_properties:nnn #1#2#3 + { + \clist_map_inline:nn {#3} + { + \seq_set_split:Nnx \l__xsim_tmpa_seq {=} { \tl_trim_spaces:n {##1} } + \xsim_set_property:nnxx + {#1} + {#2} + { \seq_item:Nn \l__xsim_tmpa_seq {1} } + { \seq_item:Nn \l__xsim_tmpa_seq {2} } + } + \xsim_property_set_aliases:nn {#1} {#2} + } +\cs_generate_variant:Nn \xsim_set_properties:nnn {nnx,nxx,nV,nVx} + +% check if property is set: +% #1: type +% #2: id +% #3: property +\prg_new_protected_conditional:Npnn \xsim_if_property_set:nnn #1#2#3 {T,F,TF} + { + \prop_if_in:NxTF \g__xsim_properties_prop + { #2 ! #1 ! #3 } + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \xsim_if_property_set:nnnTF {nnx,xx,nV} +\cs_generate_variant:Nn \xsim_if_property_set:nnnF {nx,nnx,xx} +\cs_generate_variant:Nn \xsim_if_property_set:nnnT {nnx,xx} + +% ---------------------------------------------------------------------------- + +\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} + { \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} } + +% #1: property +% #2: alias of +\cs_new_protected:Npn \xsim_make_property_alias:nn #1#2 + { + \xsim_if_property_alias:nF {#1} + { + \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} + \seq_gput_right:Nn \g__xsim_property_aliases_seq {#1} + } + } + +% #1: type +% #2: id +% #3: property +\cs_new_protected:Npn \xsim_property_set_alias:nnn #1#2#3 + { + \xsim_if_property_set:nnnF {#1} {#2} {#3} + { + \xsim_if_property_set:nnxT {#1} {#2} + { \xsim_property_alias:n {#3} } + { + \xsim_set_property:nnnx {#1} {#2} {#3} + { + \xsim_get_property:nnf {#1} {#2} + { \xsim_property_alias:n {#3} } + } + } + } + \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_get_property:nnf {#1} {#2} + { \xsim_property_alias:n {#3} } + } + } + } +\cs_generate_variant:Nn \xsim_property_set_alias:nnn {nV} + +% #1: type +% #2: id +\cs_new_protected:Npn \xsim_property_set_aliases:nn #1#2 + { + \seq_map_inline:Nn \g__xsim_property_aliases_seq + { \xsim_property_set_alias:nnn {#1} {#2} {##1} } + } + +% ---------------------------------------------------------------------------- + +% retrieve properties: +% #1: type +% #2: id +% #3: property +\cs_new:Npn \xsim_get_property:nnn #1#2#3 + { \prop_item:Nn \g__xsim_properties_prop { #2 ! #1 ! #3 } } +\cs_generate_variant:Nn \xsim_get_property:nnn {nx,xx,oo,no,nnf,nf,oof,nV} + +\cs_new:Npn \__xsim_get_property_tmp:n #1 {} +\cs_generate_variant:Nn \__xsim_get_property_tmp:n {V} + +% #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} } + +% #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} } +\cs_generate_variant:Nn \xsim_get_type_for_property:nn {nV} + +% #1: type +% #2: id +% #3: property +\cs_new_protected:Npn \xsim_get_property_if_set:nnnTF #1#2#3#4#5 + { + \group_begin: + \xsim_if_property_exist:nTF {#3} + { + \xsim_if_property_set:nnnTF {#1} {#2} {#3} + { + \tl_set:Nx \PropertyValue + { \xsim_get_property:nnn {#1} {#2} {#3} } + \cs_set:Npn \__xsim_get_property_tmp:n ##1 {#4} + \__xsim_get_property_tmp:V \PropertyValue + } + {#5} + } + { \msg_error:nnn {xsim} {unknown-property} {#3} } + \group_end: + } +\cs_new_protected:Npn \xsim_get_property_if_set:nnnT #1#2#3#4 + { \xsim_get_property_if_set:nnnTF {#1} {#2} {#3} {#4} {} } +\cs_new_protected:Npn \xsim_get_property_if_set:nnnF #1#2#3#4 + { \xsim_get_property_if_set:nnnTF {#1} {#2} {#3} {} {#4} } +\cs_generate_variant:Nn \xsim_get_property_if_set:nnnTF {oo} + +% #1: type +% #2: id +% #3: property +\prg_new_conditional:Npnn \xsim_if_boolean_property:nnn #1#2#3 {T,F,TF} + { + \xsim_if_property_exist:nTF {#3} + { + \xsim_if_property_boolean:nTF {#3} + { + \xsim_if_property_set:nnnTF {#1} {#2} {#3} + { + \bool_if:cTF { c_ \xsim_get_property:nnn {#1} {#2} {#3} _bool} + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } + { \msg_error:nnn {xsim} {no-boolean-property} {#3} } + } + { \msg_error:nnn {xsim} {unknown-property} {#3} } + } +\cs_generate_variant:Nn \xsim_if_boolean_property:nnnTF {oo} +\cs_generate_variant:Nn \xsim_if_boolean_property:nnnF {nV} + +\cs_new_protected:Npn \xsim_save_property:nnnN #1#2#3#4 + { \prop_get:NnN \g__xsim_properties_prop { #2 ! #1 ! #3 } #4 } +\cs_generate_variant:Nn \xsim_save_property:nnnN {nx,xx} + +\cs_new_protected:Npn \xsim_gsave_property:nnnN #1#2#3#4 + { + \xsim_save_property:nnnN {#1} {#2} {#3} #4 + \tl_gset:NV #4 #4 + } +\cs_generate_variant:Nn \xsim_gsave_property:nnnN {nx,xx} + +% ---------------------------------------------------------------------------- +\tex_endinput:D |