summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex
diff options
context:
space:
mode:
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.tex495
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