diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/semantex')
-rw-r--r-- | Master/texmf-dist/tex/latex/semantex/semantex.sty | 3101 |
1 files changed, 3101 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/semantex/semantex.sty b/Master/texmf-dist/tex/latex/semantex/semantex.sty new file mode 100644 index 00000000000..8e8361c8dc7 --- /dev/null +++ b/Master/texmf-dist/tex/latex/semantex/semantex.sty @@ -0,0 +1,3101 @@ +\RequirePackage{expl3,xparse} +\ProvidesExplPackage{semantex}{2020/05/30}{0.1alpha}{} +% IMPORTANT: + +% Because of the definition of \semantexnormalscaling, the package now requires amsmath + +% Think about changing “upper” etc. into “supper”, whereas what is now +% “upper” could be called “uppernosep” or something similar. + +% Fix left sub- and superscripts, e.g. the right spacing + +% Allow “.” (nothing) as delimiter, even in the case of normal or \big etc + +% Instead of checking if you are equal to semantexvarible when doing +% inheritance, check if you are your own parent. This allows multiple +% “primitive” classes. +% Also remove commands like \newsemantexvariable etc. +% in order to force people to create their own classes + +% Create 2valuekeys, 3valuekeys etc. + +% Test if \exp_not:n can be removed in #1 (=\keyvalue) if +% another \exp_not:n is added in the data manipulation commands. + +% Build groups and \ext_args:NV around the definition of +% \l_semantex_key_value_temp in order to only +% define this command locally. + +% Allow two keys, nopar and absolutelynopar. The difference is that +% nopar becomes par if there is more than one argument + +% Allow left arguments! + + +% LIST OF BUGS: + +%IM A change has been made in catlimits. It shows the existence of a +%IM kind of bug in semantex + +%IM Removed \!\!\!\! in catlimits + + +\msg_new:nnnn { semantex } { keyval_not_found } { Unknown~key~#1~passed~to~object~#2~on~input~line~\msg_line_number: } {} + +\msg_new:nnnn { semantex } { arg_valuekey_not_found } { Unknown~argument~key~#1~passed~to~object~#2~on~input~line~\msg_line_number: } {} + +\msg_new:nnnn { semantex } { tl_not_found } { Unknown~data~#1~passed~to~object~#2~on~input~line~\msg_line_number: } {} +%IM should be changed so that this is passed to the actual object, not +%IM the parent object, e.g., by having a third argument containing the +%IM actual object in \g_semantex_data_tl_get:nn + + +\msg_new:nnnn { semantex } { parent_not_found } { Unknown~class~#1~set~as~parent~of~object~#2~on~input~line~\msg_line_number: } {} + +\msg_new:nnnn { semantex } { data_tl_not_found } { Unknown~data~#1~passed~to~object~#2~on~input~line~\msg_line_number: } {} + +% Extra cs variants we need: + +\cs_generate_variant:Nn \keyval_parse:NNn { cco } +\cs_generate_variant:Nn \tl_if_blank:nTF { vTF } + +\tl_set:Nn \semantexbullet {\raisebox{-0.25ex}{\scalebox{1.2}{$\cdot$}}} +\tl_set:Nn \semantexdoublebullet {\semantexbullet\semantexbullet} + +\tl_set:Nn \semantexslot { \mathord{-} } + + + + + +\DeclareDocumentCommand\newbinaryclass{mO{}} % new binary-type class +{ + % #1 = class name + % #2 = options + \semantexnewclass { #1 } { #2 } + \exp_args:Nc\DeclareDocumentCommand{#1}{mo}{ + % the actual \#1 command + \IfValueTF{##2} + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##1 }, ##2 } + } + { + \semantexrenderclass { #1 } { symbol = { ##1 } } + } + } + \exp_args:Nc\DeclareDocumentCommand{#1withoptions}{mmo}{ + \IfValueTF{##3} + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##2 }, ##1, ##3 } + } + { + \semantexrenderclass { #1 } { symbol = { ##2 }, ##1 } + } + } + \exp_args:Nc\DeclareDocumentCommand{new#1}{mgO{}} + { + % the command for creating a new object of class #1 + % ##1 = command name, with backslash + % ##2 = symbol + % ##3 = options + \IfValueTF{##2} + { + \semantexnewobject { #1 } ##1 { parent = #1, symbol = { ##2 }, ##3 } + } + { + \semantexnewobject { #1 } ##1 { parent = #1, ##3 } + } + % create the object with name ##1 + \DeclareDocumentCommand{##1}{o}{ + % the actual \##1 command + \IfValueTF { ####1 } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1 } + } + { + \semantexrenderobject { ##1 } { } + } + } + } +} + +%IM Consider using \semantexIfNoValueOrDotTF on the argument + +\DeclareDocumentCommand\newvariableclass{mO{}} % new variable-type class +{ + % #1 = class name + % #2 = options + \semantexnewclass { #1 } { #2 } + \exp_args:Nc\DeclareDocumentCommand{#1}{mog}{ + % the actual \#1 command + \IfValueTF { ##2 } + { + \IfValueTF { ##3 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1},##2,arg={##3} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1},##2} + } + } + { + \IfValueTF { ##3 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1},arg={##3} } + } + { + \semantexrenderclass { #1 } { symbol={##1} } + } + } + } + \exp_args:Nc\DeclareDocumentCommand{#1withoptions}{mmog}{ + \IfValueTF { ##3 } + { + \IfValueTF { ##4 }{ + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, ##3,arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, ##3 } + } + } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1,arg={##4} } + } + { + \semantexrenderclass { #1 } { symbol={##2}, ##1 } + } + } + } + \exp_args:Nc\DeclareDocumentCommand{new#1}{mgO{}} + { + % the command for creating a new object of class #1 + % ##1 = command name, with backslash + % ##2 = symbol + % ##3 = options + \IfValueTF{##2} + { + \semantexnewobject { #1 } ##1 { parent = #1, symbol = { ##2 }, ##3 } + } + { + \semantexnewobject { #1 } ##1 { parent = #1, ##3 } + } + % creates the object with name ##1 + \DeclareDocumentCommand{##1}{og}{ + % the actual \##1 command + \IfValueTF{####1}{ + \IfValueTF{####2} + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, arg={####2} } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1} + } + } + { + \IfValueTF{####2} + { + \semantexrenderobject { ##1 } { ifoutput=true,arg={####2} } + } + { + \semantexrenderobject { ##1 } {} + } + } + } + } +} + +\DeclareDocumentCommand\newcohomologyclass{mO{}} % new cohomology-type class +% The intention is to phase this out; use variable type instead, +%for the sake of consistency in notation. +{ + % #1 = class name + % #2 = options + \semantexnewclass { #1 } { #2 } + \exp_args:Nc\DeclareDocumentCommand{#1}{mogg}{ + % the actual \#1 command + \IfValueTF{##2} + { + \IfValueTF { ##3 } + { + \semantexifeqTF { ##3 }{ * } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, *, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, * } + } + } + { + \semantexifeqTF { ##3 }{ ** } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, **, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, ** } + } + } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, degreedefault={##3}, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, degreedefault={##3} } + } + } + } + } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ##2 } + } + } + } + { + \IfValueTF { ##3 } + { + \semantexifeqTF { ##3 }{ * } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##1}, *, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##1}, *} + } + } + { + \semantexifeqTF { ##3 }{ ** } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, **, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, ** } + } + } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, degreedefault={##3}, arg={##4} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, degreedefault={##3} } + } + } + } + } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##1}, arg={##4} } + } + { + \semantexrenderclass { #1 } { symbol={##1}, arg={##4} } + } + } + } + } + \exp_args:Nc\DeclareDocumentCommand{#1withoptions}{mmogg}{ + \IfValueTF{##3} + { + \IfValueTF { ##4 } + { + \semantexifeqTF { ##4 }{ * } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, ##3, *, arg={##5} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, ##3, * } + } + } + { + \semantexifeqTF { ##4 }{ ** } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } {ifoutput=true, symbol={##2}, ##1, ##3, **, arg={##5} } + } + { + \semantexrenderclass { #1 } {ifoutput=true, symbol={##2}, ##1, ##3, ** } + } + } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1,##3, degreedefault={##4}, arg={##5} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1,##3, degreedefault={##4} } + } + } + } + } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, ##3, arg={##5} } + } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, ##3 } + } + } + } + { + \IfValueTF { ##4 } + { + \semantexifeqTF { ##4 }{ * } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##2} ,##1, *, arg={##5} } + } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##2} ,##1, *} + } + } + { + \semantexifeqTF { ##4 }{ ** } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##2} , ##1, **, arg={##5} } + } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##2} , ##1, ** } + } + } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##2}, ##1, degreedefault={##4}, arg={##5} } + } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol={##2}, ##1, degreedefault={##4} } + } + } + } + } + { + \IfValueTF { ##5 } + { + \semantexrenderclass { #1 } { ifoutput=true,symbol={##2}, ##1, arg={##5} } + } + { + \semantexrenderclass { #1 } { symbol={##2}, ##1 } + } + } + } + } + \exp_args:Nc\DeclareDocumentCommand{new#1}{mgO{}} + { + % the command for creating a new object of class #1 + % ##1 = command name, with backslash + % ##2 = symbol + % ##3 = options + \IfValueTF{##2} + { + \semantexnewobject { #1 } { ##1 }{ parent = #1, symbol = { ##2 }, ##3 } + } + { + \semantexnewobject { #1 } { ##1 }{ parent = #1, ##3 } + } + % creates the object with name ##1 + \DeclareDocumentCommand{##1}{ogg}{ + % the actual \##1 command + \IfValueTF{####1} + { + \IfValueTF{####2} + { + \semantexifeqTF { ####2 } { * } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, *, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, * } + } + } + { + \semantexifeqTF { ####2 } { ** } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true, ####1, **, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true, ####1, ** } + } + } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, degreedefault={ ####2 }, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, degreedefault={ ####2 } } + } + } + } + } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1 } + } + } + } + { + \IfValueTF{####2} + { + \semantexifeqTF { ####2 } { * } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true, *, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true, * } + } + } + { + \semantexifeqTF { ####2 } { ** } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true,**, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,** } + } + } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true,degreedefault={ ####2 }, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,degreedefault={ ####2 } } + } + } + } + } + { + \IfValueTF{####3} + { + \semantexrenderobject { ##1 } { ifoutput=true, arg={ ####3 } } + } + { + \semantexrenderobject { ##1 } { } + } + } + } + } + } +} + + +%\DeclareDocumentCommand\newtupleclass{mO{}} % new tuple-type class +%{ +% % #1 = class name +% % #2 = options +% \semantexnewclass { #1 } { #2 } +% \exp_args:Nc\DeclareDocumentCommand{#1}{mog}{ +% % the actual \#1 command +% % (maybe this does not even make sense for tuples) +% \IfValueTF { ##2 } +% { +% \IfValueTF { ##3 } +% { +% \semantexrenderclass { #1 }{ ifoutput=true,symbol = { ##1 },##2, arg = { ##3 } } +% } +% { +% \semantexrenderclass { #1 }{ ifoutput=true,symbol = { ##1 },##2 } +% } +% } +% { +% \IfValueTF { ##3 } +% { +% \semantexrenderclass { #1 }{ ifoutput=true,symbol = { ##1 }, arg = { ##3 } } +% } +% { +% \semantexrenderclass { #1 }{ symbol = { ##1 } } +% } +% } +% } +% \exp_args:Nc\DeclareDocumentCommand{#1withoptions}{mmog}{ +% \IfValueTF { ##3 } +% { +% \IfValueTF { ##4 } +% { +% \semantexrenderclass { #1 }{ ifoutput=true, symbol = { ##2 }, ##1, ##3, arg = { ##4 } } +% } +% { +% \semantexrenderclass { #1 }{ ifoutput=true, symbol = { ##2 }, ##1, ##3 } +% } +% } +% { +% \IfValueTF { ##4 } +% { +% \semantexrenderclass { #1 }{ ifoutput=true, symbol = { ##2 }, ##1, arg = { ##4 } } +% } +% { +% \semantexrenderclass { #1 }{ symbol = { ##2 }, ##1 } +% } +% } +% } +% \exp_args:Nc\DeclareDocumentCommand{new#1}{mmmmmO{}} +% { +% % the command for creating a new object of class #1 +% % ##1 = command name, with backslash +% % ##2 = symbol +% % ##3 = options +% \semantexnewobject { #1 } { ##1 } % creates the object with name ##1 +% { parent = #1, leftpar = { ##2 }, argsep = { ##3 }, rightpar = { ##4 }, argdots = { ##5 }, ##6 } +% \DeclareDocumentCommand{##1}{og}{ +% % the actual \##1 command +% \IfValueTF{####1} +% { +% \IfValueTF { ####2 } +% { +% \semantexrenderobject { ##1 } { ifoutput=true,####1, arg = { ####2 } } +% } +% { +% \semantexrenderobject { ##1 } { ifoutput=true,####1 } +% } +% } +% { +% \IfValueTF { ####2 } +% { +% \semantexrenderobject { ##1 } { ifoutput=true, arg = { ####2 } } +% } +% { +% \semantexrenderobject { ##1 } { } +% } +% } +% } +% } +%} + +\DeclareDocumentCommand\newdelimiterclass{mO{}} % new delimiter-type class +{ + % #1 = class name + % #2 = options + \semantexnewclass { #1 } { +% valuekeys={ +% {arg}{argwithoutkeyval={\l_semantex_key_value_temp}}, +% %Currently, using no braces around \l_semantex_key_value_temp is necessary for \semantexdelimsize to work +% % with par=auto +% }, + #2 + } + \exp_args:Nc\DeclareDocumentCommand{#1}{mog} % maybe this does not even make sense for delimiters + { + \IfValueTF { ##2 } + { + \IfValueTF { ##3 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##1 }, ##2, arg = { ##3 } } + } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##1 }, ##2 } + } + } + { + \IfValueTF { ##3 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##1 }, arg = { ##3 } } + } + { + \semantexrenderclass { #1 } { symbol = { ##1 } } + } + } + } + % the actual \#1 command + \exp_args:Nc\DeclareDocumentCommand{#1withoptions}{mmog} + { + \IfValueTF { ##3 } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##2 }, ##1, ##3, arg = { ##4 } } + } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##2 }, ##1, ##3 } + } + } + { + \IfValueTF { ##4 } + { + \semantexrenderclass { #1 } { ifoutput=true, symbol = { ##2 }, ##1, arg = { ##4 } } + } + { + \semantexrenderclass { #1 } { symbol = { ##2 }, ##1 } + } + } + } + \exp_args:Nc\DeclareDocumentCommand{new#1}{mmmO{}} + { + % the command for creating a new object of class #1 + % ##1 = command name, with backslash + % ##2 = symbol + % ##3 = options + \semantexnewobject { #1 } { ##1 }{ parent = #1, leftpar = { ##2 }, rightpar = { ##3 }, ##4 } + % creates the object with name ##1 + \DeclareDocumentCommand{##1}{og}{ + % the actual \##1 command + \IfValueTF { ####1 } + { + \IfValueTF { ####2 } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1, arg = { ####2 } } + } + { + \semantexrenderobject { ##1 } { ifoutput=true,####1 } + } + } + { + \IfValueTF { ####2 } + { + \semantexrenderobject { ##1 } { ifoutput=true, arg = { ####2 } } + } + { + \semantexrenderobject { ##1 } { } + } + } + } + } +} + +\cs_generate_variant:Nn \tl_if_eq:nnTF { xnTF } + +\cs_generate_variant:Nn \tl_if_eq:nnF { xnF } + +\cs_generate_variant:Nn \tl_if_eq:nnT { xnT } + +\DeclareDocumentCommand{\semantexifblankordotTF}{mmm} +{ + \tl_if_blank:nTF { #1 } + { #2 } + { + \tl_if_eq:xnTF { \tl_trim_spaces:n { #1 } } { . } { #2 } { #3 } + } +} + +\DeclareDocumentCommand{\semantexifblankordotT}{mm} +{ + \tl_if_blank:nTF { #1 } + { #2 } + { + \tl_if_eq:xnT { \tl_trim_spaces:n { #1 } } { . } { #2 } + } +} + +\DeclareDocumentCommand{\semantexifblankordotF}{mm} +{ + \tl_if_blank:nF { #1 } + { + \tl_if_eq:xnF { \tl_trim_spaces:n { #1 } } { . } { #2 } + } +} + +\cs_set_eq:NN\semantexifeqTF\tl_if_eq:nnTF + +\cs_set_eq:NN\semantexifeqT\tl_if_eq:nnT + +\cs_set_eq:NN\semantexifeqF\tl_if_eq:nnF + + + +\cs_new:Npn \g_semantex_new_class:nn#1#2{ + % create a new class + % #1 = name of class + % #2 = standard keyval setup; the parent class by default is semantexvariable + \g_semantex_new_object:nnn { semantexvariable } { #1 } { #2 } +} + +\cs_set_eq:NN\semantexnewclass\g_semantex_new_class:nn + +\seq_new:N \semantex_all_objects_seq +\seq_put_right:Nn \semantex_all_objects_seq { semantexvariable } + + +\cs_new:Npn \g_semantex_new_object:nnn#1#2#3{ + % create new object + % #1 = class of command + % #2 = name of command, without backslash + % #3 = standard keyval setup + + \g_semantex_data_tl_provide:nn { #2 } { parent } + + \g_semantex_data_tl_set:nnn {#2 } { parent } { semantexvariable } + + \cs_set:cpn { g_semantex_data_cs_#2_valuekey:nn } ##1##2 % command controlling valuekeys + { \g_semantex_valuekey:nnn { ##2 } { ##1 } { #2 } } + + \cs_set:cpn { g_semantex_data_cs_#2_novaluekey:n } ##1 % command controlling novaluekeys + { \g_semantex_novaluekey:nn { ##1 } { #2 } } + + % Now a similar collection of keyval commands for the *argument* + + \cs_set:cpn { g_semantex_data_cs_#2_arg_valuekey:nn } ##1##2 + { \g_semantex_arg_valuekey:nnn { ##2 } { ##1 }{ #2 } } + + \cs_set:cpn { g_semantex_data_cs_#2_arg_novaluekey:n } ##1 + { \g_semantex_arg_novaluekey:nn { ##1 } { #2 } } + + + % initially sets up the keyval interface of the object + \g_semantex_keys_set:nn { #2 } { parent=#1, #3 } + + \seq_put_right:Nx \semantex_all_objects_seq { #2 } +} + + +\cs_generate_variant:Nn \g_semantex_new_object:nnn { nxn } + +\cs_set:Npn \semantexnewobject#1#2#3 +{ \g_semantex_new_object:nxn { #1 }{ \cs_to_str:N #2 } { #3 } } + + + + +%------------------------------- + +% Commands for rendering: + +\tl_new:N\l__semantex_symbol_temp + +\cs_new_protected:Npn \g_semantex_render:nn#1#2 +{ + % the main command for rendering an object + % #1 = name of object + % #2 = options + \group_begin: + \g_semantex_data_tl_inherit:nn { #1 } { symbol } + \g_semantex_keys_set:nn { #1 } { #2 } + \g_semantex_primitive_valuekey_parse:nn { #1 } { } % not the right place to run this? + \g_semantex_data_bool_get:nnTF { #1 } { output } + { + \g_semantex_primitive_valuekey_innerreturn:nn { #1 }{} + \g_semantex_data_bool_get:nnTF { #1 } { rightreturnbeforerender } + { + \g_semantex_primitive_valuekey_rightreturn:nn { #1 }{} + } + { + % do nothing + } + \tl_set:Nx\l__semantex_render_symbol_temp { \g_semantex_data_tl_get:nn { #1 } { symbol } } %IM chang to "store" solution + \g_semantex_data_tl_get_store:nnN { #1 } { upper_index } \l__semantex_render_upper_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { lower_index } \l__semantex_render_lower_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { upper_left_index } \l__semantex_render_upper_left_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { lower_left_index } \l__semantex_render_lower_left_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { preupper } \l__semantex_render_preupper_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postupper } \l__semantex_render_postupper_temp + \g_semantex_data_tl_get_store:nnN { #1 } { prelower } \l__semantex_render_prelower_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postlower } \l__semantex_render_postlower_temp + \g_semantex_data_tl_get_store:nnN { #1 } { preupperleft } \l__semantex_render_preupperleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postupperleft } \l__semantex_render_postupperleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { prelowerleft } \l__semantex_render_prelowerleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postlowerleft } \l__semantex_render_postlowerleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { texclass } \l__semantex_render_texclass_temp + \tl_set:Nx \l__semantex_render_temp + { + \exp_not:c { + \g_semantex_data_tl_get:nn { #1 } { output }withoptions + } + { + upperaddleft={\exp_not:V\l__semantex_render_upper_index_temp}, + loweraddleft={\exp_not:V\l__semantex_render_lower_index_temp}, + upperleftaddright={\exp_not:V\l__semantex_render_upper_left_index_temp}, + lowerleftaddright={\exp_not:V\l__semantex_render_lower_left_index_temp}, + preupper={\exp_not:V\l__semantex_render_preupper_temp}, + postupper={\exp_not:V\l__semantex_render_postupper_temp}, + prelower={\exp_not:V\l__semantex_render_prelower_temp}, + postlower={\exp_not:V\l__semantex_render_postlower_temp}, + preupperleft={\exp_not:V\l__semantex_render_preupperleft_temp}, + postupperleft={\exp_not:V\l__semantex_render_postupperleft_temp}, + prelowerleft={\exp_not:V\l__semantex_render_prelowerleft_temp}, + postlowerleft={\exp_not:V\l__semantex_render_postlowerleft_temp}, + texclass={\l__semantex_render_texclass_temp}, + \g_semantex_data_tl_get_exp_not:nn { #1 } { output_options }, + } + { \exp_not:V \l__semantex_render_symbol_temp } + } + } + { + \g_semantex_primitive_valuekey_return:nn { #1 }{} +% \tl_set:Nx \l__semantex_render_temp { \exp_not:V \l__semantex_symbol_temp } +% \tl_set:Nx\l__semantex_render_temp { \g_semantex_data_tl_get:nn { #1 } { symbol } } % this is the ordinary solution that generally just works + %\tl_set:Nx\l__semantex_render_temp { \exp_not:n{\exp_not:v { semantex_data_tl_#1_symbol } }} +% \g_semantex_data_tl_get_store:nnN { #1 } { symbol } \l__semantex_render_symbol_temp + \tl_if_blank:xTF { \g_semantex_data_tl_get:nn { #1 } { texclass } }{ + \tl_set:Nx\l__semantex_render_symbol_temp { \g_semantex_data_tl_get:nn { #1 } { symbol } } + } + { + \tl_set:Nx\l__semantex_render_symbol_temp { \g_semantex_data_tl_get:nn { #1 } { texclass } { \g_semantex_data_tl_get:nn { #1 } { symbol } } } + } + \tl_set:Nx\l__semantex_render_temp { + \exp_not:V \l__semantex_render_symbol_temp + } + } + \exp_last_unbraced:NV + \group_end: + \l__semantex_render_temp +} + +\cs_set_eq:NN\semantexrenderclass\g_semantex_render:nn % a front-end command + +\cs_set:Npn\semantexrenderobject#1#2 +{ + \g_semantex_render:nn { \cs_to_str:N #1 } { #2 } +} + + + +\cs_generate_variant:Nn\tl_if_blank:nTF { xTF } + +\cs_new:Npn \g_semantex_right_indices:nnnnnn#1#2#3#4#5#6 +{ + \tl_if_blank:nF { #2 } { \sp{#1 #2 #3} } + \tl_if_blank:nF { #5 } { \sb{#4 #5 #6} } + % Using x here was the source of a very long + % debugging; inputting underbrace in the index + % caused problems +} + +\cs_new:Npn \g_semantex_left_indices:nnnnnn#1#2#3#4#5#6 +{ + \tl_if_blank:nTF { #2 } { + \tl_if_blank:nF { #5 } { {}\sb{#4 #5 #6} } + } + { + {} \sp{#1 #2 #3} + \tl_if_blank:nF { #5 } { \sb{#4 #5 #6} } + } +} + + + +\tl_new:N\semantexdelimsize + +%So far, this is experimental: +%\makeatletter %this part requires amsmath +\newcommand{\semantexnormalscaling}{\bBigg@{0.8}} +\newcommand{\semantexnormalscalingl}{\mathopen\semantexnormalscaling} +\newcommand{\semantexnormalscalingr}{\mathclose\semantexnormalscaling} +\newcommand{\semantexnormalscalingm}{\mathrel\semantexnormalscaling} +%\makeatother + + +\cs_new:Npn \g_semantex_parentheses:nnnnnn#1#2#3#4#5#6 +{ + \tl_if_blank:nF { #5 } + { + \str_case:nnF { #1 } + { + { normal } { + \group_begin: + %\semantexnormalscalingl#2 #4 #5 #6 \semantexnormalscalingr#3 + \mathopen#2 #4 #5 #6 \mathclose#3 + \group_end: + } + { auto } { + \group_begin: + \tl_set:Nn\semantexdelimsize{\middle} + %\tl_set_eq:NN\semantexdelimsize\middle + \mathopen{}\mathclose\bgroup\left#2 + #4 #5 #6 + \aftergroup\egroup\right#3 + \group_end: + } + { * } { + \group_begin: + \tl_set:Nn\semantexdelimsize{\middle} + %\tl_set_eq:NN\semantexdelimsize\middle + \mathopen{}\mathclose\bgroup\left#2 + #4 #5 #6 + \aftergroup\egroup\right#3 + \group_end: + } +% { \big } { +% \group_begin: +% \tl_set_eq:NN\semantexdelimsize\big +% \mathopen\big#2 #4 \mathclose\big#3 +% \group_end: +% } +% { \Big } { +% \group_begin: +% \tl_set_eq:NN\semantexdelimsize\Big +% \mathopen\Big#2 #4 \mathclose\Big#3 +% \group_end: +% } +% { \bigg } { +% \group_begin: +% \tl_set_eq:NN\semantexdelimsize\bigg +% \mathopen\bigg#2 #4 \mathclose\bigg#3 +% \group_end: +% } +% { \Bigg } { +% \group_begin: +% \tl_set_eq:NN\semantexdelimsize\Bigg +% \mathopen\Bigg#2 #4 \mathclose\Bigg#3 +% \group_end: +% } + } + { + \group_begin: + \tl_set_eq:NN\semantexdelimsize#1 + %\tl_set:Nx\semantexdelimsize{\exp_not:N#1} + \mathopen#1#2 #4 #5 #6 \mathclose#1#3 + \group_end: + } + } +} + +\cs_new:Npn \g_semantex_no_parentheses:nnn#1#2#3 +{ + \tl_if_blank:nF { #2 } + { + \group_begin: + \tl_clear:N\semantexdelimsize + #1 #2 #3 + \group_end: + } +} + +\cs_new:Npn \g_semantex_symbol_parentheses:nnnn#1#2#3#4 +{ + \tl_if_blank:nF { #4 } + { + \str_case:nnF { #1 } + { + { normal } { \mathopen#2 #4 \mathclose#3 } + { auto } { \mathopen{}\mathclose\bgroup\left#2 #4 \aftergroup\egroup\right#3 } + { * } { \mathopen{}\mathclose\bgroup\left#2 #4 \aftergroup\egroup\right#3 } + } + { \mathopen#1#2 #4 \mathclose#1#3 } + } +} + + + + +%-------------------------------------------- +% Commands to modify and obtain data + +\cs_generate_variant:Nn \str_if_eq:nnTF { fnTF , onTF } + +%\cs_new:Npn \g_semantex_data_tl_get_proto:nnn#1#2#3 +%{ +% % #1 = name of object +% % #2 = the data to get +% % #3 = also the name of object, but being stored +% % when passing to the parent, in order to make +% % error messages meaningful +% \tl_if_exist:cTF { semantex_data_tl_#1_#2 } +% { +% \use:c { semantex_data_tl_#1_#2 } +% } +% { +% \tl_if_eq:nnTF { #1 } { semantexvariable } +% { +% \msg_error:nnnn { semantex } { data_tl_not_found } { #2 } { #3 } +% } +% { +% \g_semantex_data_tl_get_proto:nnn { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { #1 } +% } +% } +%} +% +%\cs_new:Npn \g_semantex_data_tl_get:nn#1#2 +%{ +% \g_semantex_data_tl_get_proto:nnn { #1 } { #2 } { #1 } +%} + +\cs_new:Npn \g_semantex_data_tl_get:nn#1#2 +{ + % #1 = name of object + % #2 = the data to get + % #3 = also the name of object, but being stored + % when passing to the parent, in order to make + % error messages meaningful + \tl_if_exist:cTF { semantex_data_tl_#1_#2 } + { + \use:c { semantex_data_tl_#1_#2 } + } + { + \g_semantex_data_tl_get:nn { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } + } +} + +\cs_new:Npn \g_semantex_data_tl_get_exp_not:nn#1#2 +{ + % #1 = name of object + % #2 = the data to get + \tl_if_exist:cTF { semantex_data_tl_#1_#2 } + { + \exp_not:v { semantex_data_tl_#1_#2 } + } + { + \g_semantex_data_tl_get:nn { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } + } +} + +%\cs_generate_variant:Nn \g_semantex_data_tl_get:nn { cn } + +\cs_new:Npn \g_semantex_data_tl_get_store:nnN#1#2#3% maybe should be PROTECTED?? +{ + % #1 = name of object + % #2 = the data to get + % #3 = where to store it + \tl_if_exist:cTF { semantex_data_tl_#1_#2 } + { + \tl_set_eq:Nc #3 { semantex_data_tl_#1_#2 } + } + { + \g_semantex_data_tl_get_store:nnN { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } #3 + } +} + +\cs_generate_variant:Nn \g_semantex_data_tl_get_store:nnN { nnc } + +\cs_new:Npn\g_semantex_data_tl_provide:nn#1#2 +{ + \tl_if_exist:cF { semantex_data_tl_#1_#2 } + { + \tl_set:cn { semantex_data_tl_#1_#2 } {} + } +} + +\cs_new:Npn\g_semantex_data_tl_inherit:nn#1#2 +{ + % #1 = object + % #2 = piece of token list data + % Takes the data #2 from the parent of #1 and saves it locally + % to the object #1. After this, no more inheritance is taking place + % from the parent, and the data can be changed locally on the level + % of #1. + \tl_if_exist:cF { semantex_data_tl_#1_#2 } + { + \g_semantex_data_tl_get_store:nnc { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { semantex_data_tl_#1_#2 } + } + { + \g_semantex_data_tl_get_store:nnc { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { semantex_data_tl_#1_#2 } + %IM could be replaced by simply { #1 } { #2 } once the check is made + %IM based on "if_provided" + } +} + +\cs_new:Npn\g_semantex_data_tl_inherit_x:nn#1#2 +{ + % The same as inherit; historically, this one did an x type + % expansion first, but after changes in other places, this + % no longer appeard to be necessary. I decided to keep up the + % separation of the two, just in case. + \tl_if_exist:cF { semantex_data_tl_#1_#2 } + { + \g_semantex_data_tl_get_store:nnc { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { semantex_data_tl_#1_#2 } + } + { + \g_semantex_data_tl_get_store:nnc { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { semantex_data_tl_#1_#2 } + %IM could be replaced by simply { #1 } { #2 } once the check is made + %IM based on "if_provided" + } +} + +\cs_new:Npn \g_semantex_data_tl_set:nnn#1#2#3 +{ + %\g_semantex_data_tl_provide:nn { #1 } { #2 } + \tl_set:cn { semantex_data_tl_#1_#2 } { #3 } +} + +\cs_generate_variant:Nn \g_semantex_data_tl_set:nnn { nnx } + +\cs_new:Npn \g_semantex_data_tl_put_right:nnn#1#2#3 +{ + \g_semantex_data_tl_inherit:nn { #1 } { #2 } + \tl_put_right:cn { semantex_data_tl_#1_#2 } { #3 } +} + +\cs_generate_variant:Nn \g_semantex_data_tl_put_right:nnn { nnx } + +\cs_new:Npn \g_semantex_data_tl_put_left:nnn#1#2#3 +{ + \g_semantex_data_tl_inherit:nn { #1 } { #2 } + \tl_put_left:cn { semantex_data_tl_#1_#2 } { #3 } +} + +\cs_generate_variant:Nn \g_semantex_data_tl_put_left:nnn { nnx } + +\cs_new:Npn \g_semantex_data_tl_clear:nn#1#2 +{ + \g_semantex_data_tl_provide:nn { #1 } { #2 } + \tl_clear:c { semantex_data_tl_#1_#2 } +} + +\cs_new:Npn \g_semantex_data_seq_get_store:nnN#1#2#3{% maybe should be PROTECTED?? + % #1 = name of object + % #2 = the sequence to get + % #3 = the command to store it in + \bool_if_exist:cTF { semantex_data_seq_#1_#2_bool_if_provided } + { + \bool_if:cTF { semantex_data_seq_#1_#2_bool_if_provided } + { \seq_set_eq:Nc#3 { semantex_data_seq_#1_#2 } } + { \g_semantex_data_seq_get_store:vnN{ semantex_data_tl_#1_parent }{#2}#3 } + } + { + \g_semantex_data_seq_get_store:nnN{ \g_semantex_data_tl_get:nn { #1 } { parent } }{#2}#3% + } +} + +\cs_generate_variant:Nn \g_semantex_data_seq_get_store:nnN { vnN, nnc, vnc } + +\cs_new:Npn\g_semantex_data_seq_provide:nn#1#2 +{ + \bool_if_exist:cTF { semantex_data_seq_#1_#2_bool_if_provided } + { + \bool_if:cF { semantex_data_seq_#1_#2_bool_if_provided } + { + \seq_new:c { semantex_data_seq_#1_#2 } + \bool_set_true:c { semantex_data_seq_#1_#2_bool_if_provided } + } + } + { + \bool_new:c { semantex_data_seq_#1_#2_bool_if_provided } + \bool_set_true:c { semantex_data_seq_#1_#2_bool_if_provided } + \seq_if_exist:cF { semantex_data_seq_#1_#2 } { + \seq_new:c { semantex_data_seq_#1_#2 } + } + } +} + +\cs_new:Npn\g_semantex_data_seq_inherit:nn#1#2 +{ + \bool_if_exist:cTF { semantex_data_seq_#1_#2_bool_if_provided } + { + \bool_if:cF { semantex_data_seq_#1_#2_bool_if_provided } + { + \g_semantex_data_seq_get_store:vnc { semantex_data_tl_#1_parent } { #2 } { semantex_data_seq_#1_#2 } + \bool_set_true:c { semantex_data_seq_#1_#2_bool_if_provided } + } + } + { + \bool_new:c { semantex_data_seq_#1_#2_bool_if_provided } + \bool_set_true:c { semantex_data_seq_#1_#2_bool_if_provided } + \seq_if_exist:cF { semantex_data_seq_#1_#2 } { \seq_new:c { semantex_data_seq_#1_#2 } } + \g_semantex_data_seq_get_store:vnc { semantex_data_tl_#1_parent } { #2 } { semantex_data_seq_#1_#2 } + } +} + +\cs_new:Npn\g_semantex_data_seq_put_right:nnn#1#2#3 +{ + \g_semantex_data_seq_inherit:nn { #1 } { #2 } + \seq_put_right:cn { semantex_data_seq_#1_#2 } { #3 } +} + +\cs_new:Npn \g_semantex_data_prop_provide:nn#1#2 +{ + % #1 = name of the object + % #2 = name of the prop + \prop_if_exist:cF { semantex_data_prop_#1_#2 } { \prop_new:c { semantex_data_prop_#1_#2 } } +} + +\cs_new:Npn \g_semantex_data_prop_put:nnnn#1#2#3#4 +{ + \prop_put:cnn { semantex_data_prop_#1_#2 } { #3 } { #4 } +} + + +\cs_new:Npn \g_semantex_valuekey_get:nnNTF#1#2#3#4#5{% + % #1 = name of the object + % #2 = keyval data to get + % #3 = command to store possible data in + % #4 = if true (not to be used) + % #5 = if false + \prop_get:cnNTF { semantex_data_prop_#1_custom_valuekeys } { #2 }#3%\l_semantex_valuekey_get_temp + { #4 } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { #5 } + { + \g_semantex_valuekey_get:xnNTF { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } #3 { #4 } { #5 } + } + } +} + +\cs_generate_variant:Nn \g_semantex_valuekey_get:nnNTF { vnNTF, xnNTF } + +\cs_new:Npn \g_semantex_novaluekey_get:nnNTF#1#2#3#4#5{% + % #1 = name of the object + % #2 = singlekey data to get + % #3 = command to store possible data in + % #4 = if true (not to be used) + % #5 = if false + \prop_get:cnNTF { semantex_data_prop_#1_custom_novaluekeys } { #2 } #3 + { #4 } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { #5 } + { + \g_semantex_novaluekey_get:xnNTF { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } #3 { #4 } { #5 } + } + } +} + +\cs_generate_variant:Nn \g_semantex_novaluekey_get:nnNTF { vnNTF, xnNTF } + +%\cs_new:N\l_semantex_arg_valuekey_get_parent_temp + +\cs_new:Npn \g_semantex_arg_valuekey_get:nnNTF#1#2#3#4#5{% + % #1 = name of the object + % #2 = keyval data to get + % #3 = command to store possible data in + % #4 = if true (not to be used) + % #5 = if false + \prop_get:cnNTF { semantex_data_prop_#1_custom_arg_valuekeys } { #2 }#3%\l_semantex_valuekey_get_temp + { #4 } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { #5 } + { + \g_semantex_arg_valuekey_get:xnNTF { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } #3 { #4 } { #5 } + } + } +} + +\cs_generate_variant:Nn \g_semantex_arg_valuekey_get:nnNTF { vnNTF, xnNTF } + +\prop_new:N\l_semantex_arg_valuekey_get_temp + +\cs_new:Npn \g_semantex_arg_novaluekey_get:nnNTF#1#2#3#4#5{% + % #1 = name of the object + % #2 = singlekey data to get + % #3 = command to store possible data in + % #4 = if true (not to be used) + % #5 = if false + \prop_get:cnNTF { semantex_data_prop_#1_custom_arg_novaluekeys } { #2 } #3 + { #4 } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { #5 } { \g_semantex_arg_novaluekey_get:xnNTF { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } #3 { #4 } { #5 } } + } +} + +\cs_generate_variant:Nn \g_semantex_arg_novaluekey_get:nnNTF { vnNTF, xnNTF } + +\cs_new:Npn\g_semantex_data_bool_get:nnTF#1#2#3#4 +{ + % #1 = name of the object + % #2 = boolean to get + % #3 = if true + % #4 = if false + \bool_if_exist:cTF { semantex_data_bool_#1_if_#2_bool_if_provided } + { + \bool_if:cTF { semantex_data_bool_#1_if_#2_bool_if_provided } + { + \bool_if:cTF { semantex_data_bool_#1_if_#2 } { #3 } { #4 } + } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { #4 } { \g_semantex_data_bool_get:xnTF { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { #3 } { #4 } } + } + } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { #4 } { \g_semantex_data_bool_get:xnTF { \g_semantex_data_tl_get:nn { #1 } { parent } } { #2 } { #3 } { #4 } } + } +} + +\cs_generate_variant:Nn \g_semantex_data_bool_get:nnTF { xnTF, vnTF } + +\cs_new:Npn\g_semantex_data_bool_provide:nn#1#2 +{ + % #1 = name of the object + % #2 = boolean to provide + \bool_if_exist:cTF { semantex_data_bool_#1_if_#2_bool_if_provided } + { + \bool_if:cF { semantex_data_bool_#1_if_#2_bool_if_provided } + { \bool_set_true:c { semantex_data_bool_#1_if_#2_bool_if_provided } } + } + { + \bool_new:c { semantex_data_bool_#1_if_#2 } + \bool_new:c { semantex_data_bool_#1_if_#2_bool_if_provided } + \bool_set_true:c { semantex_data_bool_#1_if_#2_bool_if_provided } + } +} + +\cs_new:Npn\g_semantex_data_bool_set_true:nn#1#2 +{ + % #1 = name of the object + % #2 = boolean to provide + \g_semantex_data_bool_provide:nn { #1 } { #2 } + \bool_set_true:c { semantex_data_bool_#1_if_#2 } +} + +\cs_new:Npn\g_semantex_data_bool_set_false:nn#1#2 +{ + % #1 = name of the object + % #2 = boolean to provide + \g_semantex_data_bool_provide:nn { #1 } { #2 } + \bool_set_false:c { semantex_data_bool_#1_if_#2 } +} + +\cs_new:Npn\g_semantex_data_cs_get:nnn#1#2#3 +{ + % #1 = name of the object + % #2 = command sequence to get + % #3 = what to apply said command sequence to + \cs_if_exist:cTF { g_semantex_data_cs_#1_#2:n } + { \use:c { g_semantex_data_cs_#1_#2:n } { #3 } } + { + \tl_if_eq:nnTF { #1 } { semantexvariable } + { + % should probably throw an error by now, but later! + } + { + \g_semantex_data_cs_get:xnn { \g_semantex_data_tl_get:nn{#1}{parent} } { #2 } { #3 } + } + } +} + +\cs_generate_variant:Nn \g_semantex_data_cs_get:nnn { xnn } + +\cs_new:Npn \g_semantex_keys_set:nn#1#2 +{ + % #1 = object + % #2 = keys + \keyval_parse:cco %IM think about wthether o-type is really necessary. + { g_semantex_data_cs_#1_novaluekey:n } + { g_semantex_data_cs_#1_valuekey:nn } + { #2 } +} + +\cs_new:Npn \g_semantex_arg_keys_set:nn#1#2 +{ + % #1 = object + % #2 = keys + \keyval_parse:cco %IM -||- + { g_semantex_data_cs_#1_arg_novaluekey:n } + { g_semantex_data_cs_#1_arg_valuekey:nn } + { #2 } +} + +\cs_generate_variant:Nn \clist_map_function:nN { nc } + +\cs_new:Npn \g_semantex_arg_novaluekeys_set:nn#1#2 +{ + \clist_map_function:nc {#2} { g_semantex_data_cs_#1_arg_novaluekey:n } +} + +\DeclareDocumentCommand\setupclass{mm}{ % a user-level command for setting up the object + % #1 = class + % #2 = setup + %\exp_args:Nx + \g_semantex_keys_set:nn { #1 }{ #2 } +} + +\DeclareDocumentCommand\setupobject{mm}{% + % #1 = object + % #2 = setup + \g_semantex_keys_set:nn { \cs_to_str:N #1 } { #2 } +} + + + + + +% Now for the commands that implement the keyval interface. +% These commands are used by the command \g_semantex_data_cs_#1_keys_set, see +% above. +% There is a fixed collection of primitive commands. +% Furthermore, the user has the option to create a collection +% of new commands, which are all stored in the property list +% called \semantex_data_prop_#1_custom_valuekeys +% These valuekeys contain code that must be executable by other keys +% (e.g., primitive ones) +% The key value is accessible to the user via the temporary command +% \l_semantex_key_value_temp + +\providecommand\semantexdataprovide{} +\providecommand\semantexdataset{} +\providecommand\semantexdatasetx{} +\providecommand\semantexdataputright{} +\providecommand\semantexdataputrightx{} +\providecommand\semantexdataputleft{} +\providecommand\semantexdataputleftx{} +\providecommand\semantexdataget{} +\providecommand\semantexdatagetexpnot{} +\providecommand\semantexdataclear{} +\providecommand\semantexsetkeys{} +\providecommand\semantexsetkeysx{} +\providecommand\semantexstrifeq{} +\providecommand\semantexboolprovide{} +\providecommand\semantexboolsettrue{} +\providecommand\semantexboolsetfalse{} +\providecommand\semantexboolif{} + +% CHANGE TO CAMEL CASE! + + +\cs_generate_variant:Nn\str_if_eq:nnTF {xxTF,ooTF} + +\cs_new:Npn\g_semantex_primitive_valuekey_execute:nn#1#2 +{ + \renewcommand\semantexdataprovide[1]{\g_semantex_data_tl_provide:nn{#1}{##1}} + \renewcommand\semantexdataset[2]{\g_semantex_data_tl_set:nnn{#1}{##1}{##2}} + \renewcommand\semantexdatasetx[2]{\g_semantex_data_tl_set:nnx{#1}{##1}{##2}} + \renewcommand\semantexdataputright[2]{\g_semantex_data_tl_put_right:nnn{#1}{##1}{##2}} + \renewcommand\semantexdataputrightx[2]{\g_semantex_data_tl_put_right:nnx{#1}{##1}{##2}} + \renewcommand\semantexdataputleft[2]{\g_semantex_data_tl_put_left:nnn{#1}{##1}{##2}} + \renewcommand\semantexdataputleftx[2]{\g_semantex_data_tl_put_left:nnx{#1}{##1}{##2}} + \renewcommand\semantexdataget[1]{\g_semantex_data_tl_get:nn{#1}{##1}} + \renewcommand\semantexdatagetexpnot[1]{\g_semantex_data_tl_get_exp_not:nn{#1}{##1}} + \renewcommand\semantexdataclear[1]{\g_semantex_data_tl_clear:nn{#1}{##1}} + \renewcommand\semantexsetkeys[1]{\g_semantex_keys_set:nn{#1}{##1}} + \renewcommand\semantexsetkeysx[1]{\g_semantex_keys_set:nx{#1}{##1}} + \renewcommand\semantexstrifeq[4]{\str_if_eq:xxTF{##1}{##2}{##3}{##4}} + \renewcommand\semantexboolprovide[1]{\g_semantex_data_bool_provide:nn{#1}{##1}} + \renewcommand\semantexboolsettrue[1]{\g_semantex_data_bool_set_true:nn{#1}{##1}} + \renewcommand\semantexboolsetfalse[1]{\g_semantex_data_bool_set_false:nn{#1}{##1}} + \renewcommand\semantexboolif[3]{\g_semantex_data_bool_get:nnTF{#1}{##1}{##2}{##3}} + %\exp_not:n{#2} + % how about erase and forget? + #2 +} + +\cs_new:Npn\g_semantex_primitive_valuekey_parse:nn#1#2 +{ + \g_semantex_data_tl_inherit:nn { #1 } { parseoptions } + % But we need to also reset this, plus all data variables that + % it used; nope, not necessary + \g_semantex_keys_set:nx { #1 } { + \g_semantex_data_tl_get_exp_not:nn { #1 } { parseoptions } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_parseoptions:nn#1#2 +{ + \g_semantex_data_tl_put_right:nnn { #1 } { parseoptions } { #2 } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_return:nn#1#2 +{ + \g_semantex_primitive_valuekey_innerreturn:nn { #1 }{} + \g_semantex_primitive_valuekey_rightreturn:nn { #1 }{} + \g_semantex_primitive_valuekey_leftreturn:nn { #1 }{} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_innerreturn:nn#1#2 +{ + \g_semantex_data_tl_inherit:nn { #1 } { symbol } + \g_semantex_data_seq_inherit:nn { #1 } { commands_sequence } + \g_semantex_data_seq_get_store:nnN { #1 } { commands_sequence } \l__semantex_data_seq_commands_sequence_temp + %\seq_map_inline:cn { semantex_data_seq_#1_commands_sequence } + \seq_map_inline:Nn \l__semantex_data_seq_commands_sequence_temp + { + \g_semantex_data_tl_set:nnx { #1 } { symbol } + { + \exp_not:n {\exp_not:N ##1} { + \g_semantex_data_tl_get_exp_not:nn { #1 } { symbol } + } + % This was the solution that happened to solve + % the expansion issues best + } + } + \seq_clear:c { semantex_data_seq_#1_commands_sequence } +} + +\tl_new:N\l__semantex_rightreturn_par_temp + +\tl_new:N\l__semantex_rightreturn_nopar_temp + +\cs_generate_variant:Nn \g_semantex_keys_set:nn { nx , no } + +\cs_new:Npn\g_semantex_primitive_valuekey_rightreturn:nn#1#2 +{ + \g_semantex_data_tl_inherit_x:nn { #1 } { upper_index } + \g_semantex_data_tl_inherit_x:nn { #1 } { lower_index } + \g_semantex_data_tl_inherit_x:nn { #1 } { preupper } + \g_semantex_data_tl_inherit_x:nn { #1 } { postupper } + \g_semantex_data_tl_inherit_x:nn { #1 } { prelower } + \g_semantex_data_tl_inherit_x:nn { #1 } { postlower } + \g_semantex_data_tl_inherit_x:nn { #1 } { arg } + \g_semantex_data_tl_get_store:nnN { #1 } { upper_index } \l__semantex_rightreturn_upper_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { lower_index } \l__semantex_rightreturn_lower_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { symbol } \l__semantex_rightreturn_symbol_temp + \g_semantex_data_tl_get_store:nnN { #1 } { preupper } + \l__semantex_rightreturn_preupper_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postupper } + \l__semantex_rightreturn_postupper_temp + \g_semantex_data_tl_get_store:nnN { #1 } { prelower } + \l__semantex_rightreturn_prelower_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postlower } + \l__semantex_rightreturn_postlower_temp + \g_semantex_data_tl_set:nnx { #1 } { symbol } + { + \exp_not:V \l__semantex_rightreturn_symbol_temp + % Setup indices: + \exp_not:N\g_semantex_right_indices:nnnnnn + { \exp_not:V \l__semantex_rightreturn_preupper_temp } + { \exp_not:V \l__semantex_rightreturn_upper_index_temp } + { \exp_not:V \l__semantex_rightreturn_postupper_temp } + { \exp_not:V \l__semantex_rightreturn_prelower_temp } + { \exp_not:V \l__semantex_rightreturn_lower_index_temp } + { \exp_not:V \l__semantex_rightreturn_postlower_temp } + } + \g_semantex_data_bool_get:nnTF { #1 } { par } + { + \g_semantex_data_tl_get_store:nnN { #1 } { par_size } + \l__semantex_rightreturn_par_size_temp + \g_semantex_data_tl_get_store:nnN { #1 } { par_open } \l__semantex_rightreturn_par_open_temp + \g_semantex_data_tl_get_store:nnN { #1 } { par_close } \l__semantex_rightreturn_par_close_temp + \g_semantex_data_tl_get_store:nnN { #1 } { arg } \l__semantex_rightreturn_arg_temp + \g_semantex_data_tl_get_store:nnN { #1 } { prearg } \l_semantex_rightreturn_prearg_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postarg } \l_semantex_rightreturn_postarg_temp + \tl_set:Nx\l__semantex_rightreturn_par_temp + { + { \exp_not:V \l__semantex_rightreturn_par_size_temp } + { \exp_not:V \l__semantex_rightreturn_par_open_temp } + { \exp_not:V \l__semantex_rightreturn_par_close_temp } + { \exp_not:V \l_semantex_rightreturn_prearg_temp } + { \exp_not:V \l__semantex_rightreturn_arg_temp } + { \exp_not:V \l_semantex_rightreturn_postarg_temp } + } + \tl_put_left:Nn\l__semantex_rightreturn_par_temp + { + \exp_not:N + \g_semantex_parentheses:nnnnnn + } + \g_semantex_data_tl_put_right:nnx { #1 } { symbol } + { + \exp_not:V\l__semantex_rightreturn_par_temp + } + } + { + \tl_set:Nx\l__semantex_rightreturn_nopar_temp + { + { \g_semantex_data_tl_get_exp_not:nn { #1 } { prearg } } + { \g_semantex_data_tl_get_exp_not:nn { #1 } { arg } } + { \g_semantex_data_tl_get_exp_not:nn { #1 } { postarg } } + } + \tl_put_left:Nn\l__semantex_rightreturn_nopar_temp + { + \exp_not:N + \g_semantex_no_parentheses:nnn + } + \g_semantex_data_tl_put_right:nnx { #1 } { symbol } + { + \exp_not:V\l__semantex_rightreturn_nopar_temp + } + } + \g_semantex_data_tl_clear:nn { #1 } { upper_index } + \g_semantex_data_bool_provide:nn { #1 } { first_upper } + \g_semantex_data_bool_set_true:nn { #1 } { first_upper } + \g_semantex_data_tl_clear:nn { #1 } { lower_index } + \g_semantex_data_bool_provide:nn { #1 } { first_lower } + \g_semantex_data_bool_set_true:nn { #1 } { first_lower } + \g_semantex_data_tl_clear:nn { #1 } { arg } + \g_semantex_data_bool_provide:nn { #1 } { first_arg } + \g_semantex_data_bool_set_true:nn { #1 } { first_arg } + \g_semantex_data_tl_clear:nn { #1 } { preupper } + \g_semantex_data_tl_clear:nn { #1 } { postupper } + \g_semantex_data_tl_clear:nn { #1 } { prelower } + \g_semantex_data_tl_clear:nn { #1 } { postlower } + %IM maybe one should enclose the new symbol in another group + %IM Maybe should also reset stuff like par size + %IM reset leftpar, rightpar, parsize etc. also +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_leftreturn:nn#1#2 +{ + \g_semantex_data_tl_inherit_x:nn { #1 } { upper_left_index } + \g_semantex_data_tl_inherit_x:nn { #1 } { lower_left_index } + \g_semantex_data_tl_inherit_x:nn { #1 } { preupperleft } + \g_semantex_data_tl_inherit_x:nn { #1 } { postupperleft } + \g_semantex_data_tl_inherit_x:nn { #1 } { prelowerleft } + \g_semantex_data_tl_inherit_x:nn { #1 } { postlowerleft } + %IMPLEMENT THIS!!! + % Clean up the following names + \g_semantex_data_tl_get_store:nnN { #1 } { upper_left_index } \l__semantex_leftreturn_upper_left_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { lower_left_index } \l__semantex_leftreturn_lower_left_index_temp + \g_semantex_data_tl_get_store:nnN { #1 } { symbol } \l__semantex_leftreturn_symbol_temp + \g_semantex_data_tl_get_store:nnN { #1 } { preupperleft } \l__semantex_leftreturn_preupperleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postupperleft } \l__semantex_leftreturn_postupperleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { prelowerleft } \l__semantex_leftreturn_prelowerleft_temp + \g_semantex_data_tl_get_store:nnN { #1 } { postlowerleft } \l__semantex_leftreturn_postlowerleft_temp + \g_semantex_data_tl_set:nnx { #1 } { symbol } + { + % Setup indices: + \exp_not:N\g_semantex_left_indices:nnnnnn + { + \exp_not:V \l__semantex_leftreturn_preupperleft_temp + } + { + \exp_not:V \l__semantex_leftreturn_upper_left_index_temp + } + { + \exp_not:V \l__semantex_leftreturn_postupperleft_temp + } + { + \exp_not:V \l__semantex_leftreturn_prelowerleft_temp + } + { + \exp_not:V \l__semantex_leftreturn_lower_left_index_temp + } + { + \exp_not:V \l__semantex_leftreturn_postlowerleft_temp + } + \exp_not:V \l__semantex_leftreturn_symbol_temp + } + \g_semantex_data_tl_clear:nn { #1 } { upper_left_index } + \g_semantex_data_bool_provide:nn { #1 } { first_upper_left } + \g_semantex_data_bool_set_true:nn { #1 } { first_upper_left } + \g_semantex_data_tl_clear:nn { #1 } { lower_left_index } + \g_semantex_data_bool_provide:nn { #1 } { first_lower_left } + \g_semantex_data_bool_set_true:nn { #1 } { first_lower_left } + \g_semantex_data_tl_clear:nn { #1 } { preupperleft } + \g_semantex_data_tl_clear:nn { #1 } { postupperleft } + \g_semantex_data_tl_clear:nn { #1 } { prelowerleft } + \g_semantex_data_tl_clear:nn { #1 } { postlowerleft } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_parent:nn#1#2{ + % Must inherit everything from the parent class + %\tl_clear_new:c { semantex_data_tl_#1_parent } + %\g_semantex_data_tl_provide:nn { #1 } { parent } + %IM This should always be declared, so no need for if_provided checks + %IM This does not work, for unknown reasons: +% \seq_if_in:NxTF \semantex_all_objects_seq { #2 } +% { \tl_set:cn { semantex_data_tl_#1_parent } { #2 } } +% { \msg_error:nnnn { semantex } { parent_not_found } { #2 } { #1 } } + %IM control if exists! + %\tl_set:cn { semantex_data_tl_#1_parent } { #2 } + \g_semantex_data_tl_set:nnn { #1 } { parent } { #2 } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_class:nn\g_semantex_primitive_valuekey_parent:nn + + + +\cs_new:Npn\g_semantex_primitive_valuekey_copy:nn#1#2{ + % Must inherit everything from the parent class + \g_semantex_primitive_valuekey_parent:nn{#1}{ \cs_to_str:N #2 } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_valuekeys:nn#1#2{ + % Add new valuekeys via the interface + % valuekeys={ + % {key1}{do something with \l_semantex_key_value_temp}, + % {key2}{g=\l_semantex_key_value_temp,i=\l_semantex_key_value_temp}, + % } + \g_semantex_data_prop_provide:nn { #1 } { custom_valuekeys } + \clist_map_inline:nn { #2 }{ + \g_semantex_valuekey_equality_format:nnn{#1}##1 + } +} + +\cs_generate_variant:Nn\g_semantex_data_prop_put:nnnn {nnno} + +\cs_new:Npn \g_semantex_valuekey_equality_format:nnn#1#2#3 +{ + \cs_set:Npn\l__semantex_valuekey_equality_format_temp:n##1{#3} + \g_semantex_data_prop_put:nnno {#1} {custom_valuekeys} {#2} {\l__semantex_valuekey_equality_format_temp:n{\l_semantex_key_value_temp}} + %IM Remove spaces in #2 +} + +\cs_new:Npn\g_semantex_primitive_valuekey_novaluekeys:nn#1#2{ + % Add sinple keys, taking no values, via the + % interface + % novaluekeys={ + % {key1}{print something}, + % {key2}{d=42,i=42}, + % } + \g_semantex_data_prop_provide:nn { #1 } { custom_novaluekeys } + \clist_map_inline:nn { #2 }{ + \g_semantex_valuekey_noequality_format:nnn{#1}##1 + } +} + +\cs_new:Npn \g_semantex_valuekey_noequality_format:nnn#1#2#3{ + %\prop_put:cnn { semantex_data_prop_#1_custom_novaluekeys }{#2}{#3} + \g_semantex_data_prop_put:nnnn {#1} {custom_novaluekeys} {#2} {#3} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argvaluekeys:nn#1#2{ + % Add new valuekeys via the interface + % valuekeys={ + % {key1}{do something with \l_semantex_key_value_temp}, + % {key2}{g=\l_semantex_key_value_temp,i=\l_semantex_key_value_temp}, + % } + \g_semantex_data_prop_provide:nn { #1 } { custom_arg_valuekeys } + \clist_map_inline:nn { #2 }{ + \g_semantex_arg_valuekey_equality_format:nnn{#1}##1 + } +} + +\cs_new:Npn \g_semantex_arg_valuekey_equality_format:nnn#1#2#3{ + %\prop_put:cnn { semantex_data_prop_#1_custom_arg_valuekeys }{#2}{#3} + \cs_set:Npn\l__semantex_arg_valuekey_equality_format_temp:n##1{#3} + \g_semantex_data_prop_put:nnno {#1} {custom_arg_valuekeys} {#2} {\l__semantex_arg_valuekey_equality_format_temp:n{\l_semantex_arg_key_value_temp}} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argnovaluekeys:nn#1#2{ + % Add sinple keys, taking no values, via the + % interface + % novaluekeys={ + % {key1}{print something}, + % {key2}{g=42,i=42}, + % } + \g_semantex_data_prop_provide:nn { #1 } { custom_arg_novaluekeys } + \clist_map_inline:nn { #2 }{ + \g_semantex_arg_valuekey_noequality_format:nnn{#1}##1 + } +} + +\cs_new:Npn \g_semantex_arg_valuekey_noequality_format:nnn#1#2#3{ + \g_semantex_data_prop_put:nnnn {#1} {custom_arg_novaluekeys} {#2} {#3} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_symbol:nn#1#2{ + % Sets the value of the symbol + \g_semantex_data_tl_set:nnn { #1 } { symbol } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_texclass:nn#1#2{ + % Sets the value of the symbol + \g_semantex_data_tl_set:nnn { #1 } { texclass } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_slot:nn#1#2{ + % Sets the value of the symbol + \g_semantex_data_tl_set:nnn { #1 } { slot } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_symbolputright:nn#1#2{ + \g_semantex_data_tl_put_right:nnn { #1 } { symbol } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_symbolputleft:nn#1#2{ + \g_semantex_data_tl_put_left:nnn { #1 } { symbol } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_command:nn#1#2{ + % Adds one entry on the left of the command + % sequence to be applied to the symbol + \g_semantex_data_seq_put_right:nnn { #1 } { commands_sequence } { #2 } %IM maybe \exp_not:n { #2 }? +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argwithkeyval:nn#1#2{ + % Sets the argument (printed in parentheses + % after the symbol) + \g_semantex_arg_keys_set:nn { #1 } {{{ #2 }}} + %IM for unknown reasons, one needs these extra braces. + %IM This should be moved to the arg valuekeys themselves + %IM where ifoutput=true is also declared +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argwithnovaluekeys:nn#1#2{ + % Sets the argument (printed in parentheses + % after the symbol) + \g_semantex_arg_novaluekeys_set:nn { #1 } { #2 } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argwithonenovaluekey:nn#1#2{ + % Sets the argument (printed in parentheses + % after the symbol) + \use:c { g_semantex_data_cs_#1_arg_novaluekey:n } {{{{ #2 }}}} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argwithoutkeyval:nn#1#2{ + \g_semantex_data_tl_put_right:nnn { #1 } { arg } { \exp_not:n { #2 } } + \g_semantex_primitive_valuekey_ifrightreturnbeforerender:nn{#1}{true} +} + + +%\cs_new:Npn\g_semantex_primitive_valuekey_useargwithkeyval:nn#1#2 +%{ +%% \g_semantex_primitive_valuekey_valuekeys:nn { #1 } +%% { +%% {arg} { argwithkeyval={ \l_semantex_key_value_temp } }, +%% } +% \g_semantex_keys_set:nn { #1 }{ +% \exp_not:n{valuekeys={ +% {arg}{ argwithkeyval={\l_semantex_key_value_temp} }, +% },} +% } +%} + + +\cs_new:Npn\g_semantex_primitive_valuekey_argsep:nn#1#2 +{ + %\g_semantex_data_tl_provide:nn { #1 } { argsep } + \g_semantex_data_tl_set:nnn { #1 } { argsep } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_argdots:nn#1#2 +{ +% \g_semantex_data_tl_provide:nn { #1 } { argdots } + \g_semantex_data_tl_set:nnn { #1 } { argdots } { \exp_not:n { #2 } } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_prearg:nn#1#2{ + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:nnn { #1 } { prearg } { \exp_not:n { #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_postarg:nn#1#2{ + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_right:nnn { #1 } { postarg } { \exp_not:n{ #2 } } + } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_output:nn#1#2 +{ + \g_semantex_data_tl_set:nnn { #1 } { output } { #2 } + % Maybe allow output=self +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_outputoptions:nn#1#2{ + \g_semantex_data_tl_put_right:nnn { #1 } { output_options } { #2, } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_ifrightreturnbeforerender:nn#1#2{ + % tells whether to use the output class or not + \str_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { rightreturnbeforerender } + } + { + \str_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { rightreturnbeforerender } + } + { + %IM do nothing right now, but should + %IM probably throw an error + } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_ifoutput:nn#1#2{ %IMPLEMENT THIS + % tells whether to output or not + \str_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { output } + } + { + \str_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { output } + } + { + %IM do nothing right now, but should + %IM probably throw an error + } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_gradingpos:nn#1#2{ + % tells whether to use upper or lower indices + \g_semantex_data_bool_provide:nn { #1 } { upper_grading } + \str_case:nnTF { #2 } + { + { upper } + { + \g_semantex_data_bool_set_true:nn { #1 } { upper_grading } + } + { lower } + { + \g_semantex_data_bool_set_false:nn { #1 } { upper_grading } + } + } + { + % do nohting + } + { + % do nothing at the moment, but should probably throw an error + } +} + +\cs_set_eq:NN \g_semantex_primitive_valuekey_gradingposition:nn \g_semantex_primitive_valuekey_gradingpos:nn + +% Upper and lower right indices: + +\cs_new:Npn\g_semantex_primitive_valuekey_upper:nn#1#2{ + % adds to the upper index + \tl_if_blank:nF{#2}{ + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { \exp_not:n{ #2 } } + % For a long time, when using x type expansions when checking + % if indices were empty, two \exp_not:n's were necessary here. + % Thankfully, I can now happily remove them again, it seems. + %\g_semantex_data_bool_provide:nn { #1 } { first_upper } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper } + } +} + + + +\cs_new:Npn\g_semantex_primitive_valuekey_supper:nn#1#2{ + % adds to the upper index, with a separator + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_upper } + { + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_right:nnx { #1 } { upper_index } + { \exp_not:n { \g_semantex_data_tl_get:nn { #1 } { uppersep } } } + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { \exp_not:n { #2 } } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_upperaddleft:nn#1#2{ + % adds to the upper index + \tl_if_blank:nF{#2}{ + \g_semantex_data_tl_put_left:nnn { #1 } { upper_index } { \exp_not:n{ #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_preupper:nn#1#2{ + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:cn { #1 } { preupper } { \exp_not:n{ #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_postupper:nn#1#2{ + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_right:nnn { #1 } { postupper } { \exp_not:n{ #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_lower:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { \exp_not:n { #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_slower:nn#1#2{ + % adds to the lower index, with a separator + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_lower } + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_right:nnx { #1 } { lower_index } + { \exp_not:n { \g_semantex_data_tl_get:nn { #1 } { lowersep } } } + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { \exp_not:n { #2 } } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_loweraddleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_index } { \exp_not:n { #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_prelower:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:nnn { #1 } { prelower } { \exp_not:n { #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_postlower:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_right:nnn { #1 } { postlower } { \exp_not:n{ #2 } } + } +} + +\cs_generate_variant:Nn \tl_if_blank:nTF { vTF } + +\cs_new:Npn \g_semantex_primitive_upper_lower_auxiliary_first_arg:nn#1#2 { #1 } + +\cs_new:Npn \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn#1#2 { #2 } + +\cs_new:Npn\g_semantex_primitive_valuekey_uppersep:nn#1#2{ + % uppersep={separator}{contents} adds contents to the upper index + % with the appropriate index separator + \g_semantex_data_bool_inherit:nn { #1 } { first_upper } + \g_semantex_data_bool_get:nnTF { #1 } { first_upper } + { + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { + \exp_not:n { + \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 + } + } + } + { + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { + \exp_not:n { + \g_semantex_primitive_upper_lower_auxiliary_first_arg:nn #2 + \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 + } + } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_lowersep:nn#1#2{ + % lowersep={separator}{contents} adds contents to the lower index + % with the appropriate index separator + \g_semantex_data_bool_get:nnTF { #1 } { first_lower } + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { + \exp_not:n { + \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 + } + } + } + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { + \exp_not:n { \g_semantex_primitive_upper_lower_auxiliary_first_arg:nn #2 \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 + } + } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_cupper:nn#1#2{ + % adds to the upper index, with a comma as separator + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_upper } + { + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_right:nnn { #1 } { upper_index } { , \exp_not:n { #2 } } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper } + } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_clower:nn#1#2{ + % adds to the lower index, with a comma as separator + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_lower } + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_index } { , \exp_not:n { #2 } } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirstupper:nn#1#2 +{ + \tl_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { first_upper } + } + { + \tl_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { first_upper } + } + { + %IM Throw error later + } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirstlower:nn#1#2 +{ + \tl_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { first_lower } + } + { + \tl_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { first_lower } + } + { + %IM Throw error later + } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_setuppersep:nn#1#2 +{ + \g_semantex_data_tl_set:nnn { #1 } { uppersep } { \exp_not:n { #2 }} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_setlowersep:nn#1#2 +{ + \g_semantex_data_tl_set:nnn { #1 } { lowersep } { \exp_not:n { #2 }} +} + +%--------------- Left indices: + +\cs_new:Npn\g_semantex_primitive_valuekey_upperleft:nn#1#2{ + % adds to the upper left index + \tl_if_blank:nF{#2}{ + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { \exp_not:n{ #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper_left } + } +} + + + +\cs_new:Npn\g_semantex_primitive_valuekey_supperleft:nn#1#2{ + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_upper_left } + { + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { \exp_not:n { #2 } } + \g_semantex_data_tl_put_left:nnx { #1 } { upper_left_index } + { \exp_not:n { \g_semantex_data_tl_get:nn { #1 } { uppersep } } } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper_left } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_upperleftaddright:nn#1#2{ + % adds to the upper index + \tl_if_blank:nF{#2}{ + \g_semantex_data_tl_put_right:nnn { #1 } { upper_left_index } { \exp_not:n{ #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper_left } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_preupperleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:nnn { #1 } { preupperleft } { \exp_not:n{ #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_postupperleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_right:nnn { #1 } { postupperleft } { \exp_not:n{ #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_lowerleft:nn#1#2{ + % adds to the lower left index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { \exp_not:n{ #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower_left } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_slowerleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_lower_left } + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { \exp_not:n { #2 } } + \g_semantex_data_tl_put_left:nnx { #1 } { lower_left_index } + { \exp_not:n { \g_semantex_data_tl_get:nn { #1 } { lowerleftsep } } } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower_left } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_lowerleftaddright:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} %This test really shouldn’t be made. + { + \g_semantex_data_tl_put_right:nnn { #1 } { lower_left_index } { \exp_not:n{ #2 } } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower_left } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_prelowerleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_left:nnn { #1 } { prelowerleft } { \exp_not:n{ #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_postlowerleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_tl_put_right:nnn { #1 } { postlowerleft } { \exp_not:n{ #2 } } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_upperleftsep:nn#1#2{ + % adds to the upper index + \g_semantex_data_bool_get:nnTF { #1 } { first_left_upper } + { + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { + \exp_not:n { \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 } + } + } + { + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { + \exp_not:n { \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 \g_semantex_primitive_upper_lower_auxiliary_first_arg:nn #2 } + } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_left_upper } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_lowerleftsep:nn#1#2{ + % adds to the lower index + \g_semantex_data_bool_get:nnTF { #1 } { first_lower_left } + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { + \exp_not:n { \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 } + } + } + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { + \exp_not:n { \g_semantex_primitive_upper_lower_auxiliary_second_arg:nn #2 \g_semantex_primitive_upper_lower_auxiliary_first_arg:nn #2 } + } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower_left } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_cupperleft:nn#1#2{ + % adds to the upper index + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_upper_left } + { + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_left:nnn { #1 } { upper_left_index } { \exp_not:n { #2 } , } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_upper_left } + } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_clowerleft:nn#1#2{ + % adds to the lower index + \tl_if_blank:nF{#2} + { + \g_semantex_data_bool_get:nnTF { #1 } { first_lower_left } + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { \exp_not:n { #2 } } + } + { + \g_semantex_data_tl_put_left:nnn { #1 } { lower_left_index } { \exp_not:n { #2 } , } + } + \g_semantex_data_bool_set_false:nn { #1 } { first_lower_left } + } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirstupperleft:nn#1#2 +{ + \tl_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { first_upper_left } + } + { + \tl_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { first_upper_left } + } + { + %IM Throw error later + } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirstlowerleft:nn#1#2 +{ + \tl_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { first_lower_left } + } + { + \tl_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { first_lower_left } + } + { + %IM Throw error later + } + } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_setupperleftsep:nn#1#2 +{ + \g_semantex_data_tl_set:nnn { #1 } { upperleftsep } { \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_setlowerleftsep:nn#1#2 +{ + \g_semantex_data_tl_set:nnn { #1 } { lowerleftsep } { \exp_not:n { #2 } } +} + +%--------------- + +% Contrary to what you might think, the following commands ARE +% sometimes needed. + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirstd:nn#1#2 +{ + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { \g_semantex_primitive_valuekey_iffirstupper:nn { #1 } { #2 } } + { \g_semantex_primitive_valuekey_iffirstlower:nn { #1 } { #2 } } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_iffirstdeg:nn\g_semantex_primitive_valuekey_iffirstd:nn + +\cs_set_eq:NN\g_semantex_primitive_valuekey_iffirstdegree:nn\g_semantex_primitive_valuekey_iffirstd:nn + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirsti:nn#1#2 +{ + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { \g_semantex_primitive_valuekey_iffirstlower:nn { #1 } { #2 } } + { \g_semantex_primitive_valuekey_iffirstupper:nn { #1 } { #2 } } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_iffirstindex:nn\g_semantex_primitive_valuekey_iffirsti:nn + +\cs_new:Npn\g_semantex_primitive_valuekey_d:nn#1#2 +{ + % adds to the d-index (upper by default) + % I added an \exp_not:n here and in similar commands to + % take care of \underbrace expansion issues. However, + % I am puzzled as to why it was necessary. + %\bool_if:cTF { semantex_data_bool_#1_if_upper_grading } + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { + \g_semantex_primitive_valuekey_upper:nn { #1 } { #2 } + } + { + \g_semantex_primitive_valuekey_lower:nn { #1 } { #2 } + } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_deg:nn\g_semantex_primitive_valuekey_d:nn + +\cs_set_eq:NN\g_semantex_primitive_valuekey_degree:nn\g_semantex_primitive_valuekey_d:nn + +\cs_new:Npn\g_semantex_primitive_valuekey_sd:nn#1#2 +{ + % adds to the d-index (upper by default) + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { + \g_semantex_primitive_valuekey_supper:nn { #1 } { #2 } + } + { + \g_semantex_primitive_valuekey_slower:nn { #1 } { #2 } + } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_sdeg:nn\g_semantex_primitive_valuekey_sd:nn + +\cs_set_eq:NN\g_semantex_primitive_valuekey_sdegree:nn\g_semantex_primitive_valuekey_sd:nn + +\cs_new:Npn\g_semantex_primitive_valuekey_cd:nn#1#2{ %IM Maybe remove this. + % adds to the d-index (upper by default) + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { + \g_semantex_primitive_valuekey_cupper:nn { #1 } { #2 } + } + { + \g_semantex_primitive_valuekey_clower:nn { #1 } { #2 } + } +} + + + + +\cs_set_eq:NN\g_semantex_primitive_valuekey_cdeg:nn\g_semantex_primitive_valuekey_cd:nn + +\cs_set_eq:NN\g_semantex_primitive_valuekey_cdegree:nn\g_semantex_primitive_valuekey_cd:nn + + +\cs_new:Npn\g_semantex_primitive_valuekey_i:nn#1#2{ + % adds to the i-index (lower by default) + %\bool_if:cTF { semantex_data_bool_#1_if_upper_grading } + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { + \g_semantex_primitive_valuekey_lower:nn { #1 } { #2 } + } + { + \g_semantex_primitive_valuekey_upper:nn { #1 } { #2 } + } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_index:nn\g_semantex_primitive_valuekey_i:nn + +\cs_new:Npn\g_semantex_primitive_valuekey_si:nn#1#2{ + % adds to the i-index (lower by default) + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { + \g_semantex_primitive_valuekey_slower:nn { #1 } { #2 } + } + { + \g_semantex_primitive_valuekey_supper:nn { #1 } { #2 } + } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_sindex:nn\g_semantex_primitive_valuekey_si:nn + +\cs_new:Npn\g_semantex_primitive_valuekey_ci:nn#1#2{ + % adds to the i-index (lower by default) + %\bool_if:cTF { semantex_data_bool_#1_if_upper_grading } + \g_semantex_data_bool_get:nnTF { #1 } { upper_grading } + { + \g_semantex_primitive_valuekey_clower:nn { #1 } { #2 } + } + { + \g_semantex_primitive_valuekey_cupper:nn { #1 } { #2 } + } +} + +\cs_set_eq:NN\g_semantex_primitive_valuekey_cindex:nn\g_semantex_primitive_valuekey_ci:nn + + +\cs_new:Npn\g_semantex_primitive_valuekey_par:nn#1#2{ + % sets the size of the parentheses + \g_semantex_data_tl_set:nnn { #1 } { par_size }{ \exp_not:n { #2 } } + \g_semantex_primitive_valuekey_ifpar:nn { #1 } { true } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_parsize:nn#1#2{ + % sets the size of the parentheses + \g_semantex_data_tl_set:nnn { #1 } { par_size }{ \exp_not:n { #2 } } +} + + + + +\cs_new:Npn\g_semantex_primitive_valuekey_leftpar:nn#1#2{ +% \g_semantex_data_tl_set:nnn { #1 } { par_open }{ \exp_not:n { #2 } } + \tl_set:cn { semantex_data_tl_#1_par_open }{ \exp_not:n { #2 } } +} + + + + + +\cs_new:Npn\g_semantex_primitive_valuekey_rightpar:nn#1#2{ + \g_semantex_data_tl_set:nnn { #1 } { par_close }{ \exp_not:n { #2 } } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_ifpar:nn#1#2{ %IMPLEMENT THIS + % tells whether to use the output class or not + \g_semantex_data_bool_provide:nn { #1 } { par } + \str_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { par } + } + { + \str_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { par } + } + { + %IM do nothing right now, but should + %IM probably throw an error + } + } +} + + + +\cs_new:Npn\g_semantex_primitive_valuekey_spar:nn#1#2 +{ + \tl_if_blank:nTF { #2 } + { + \g_semantex_primitive_valuekey_return:nn { #1 }{} + \g_semantex_data_tl_set:nnx { #1 } { symbol } + { + { \g_semantex_data_tl_get_exp_not:nn { #1 } { spar_size } } + %IM like in _return + { \g_semantex_data_tl_get:nn { #1 } { spar_open } } + { \g_semantex_data_tl_get:nn { #1 } { spar_close } } + { \g_semantex_data_tl_get_exp_not:nn { #1 } { symbol } } +% { \l__semantex_spar_symbol_temp } + } + \g_semantex_data_tl_put_left:nnn { #1 } { symbol } + { + \exp_not:N + \g_semantex_symbol_parentheses:nnnn + } + } + { + \g_semantex_data_tl_inherit:nn { #1 } { symbol } + \g_semantex_primitive_valuekey_return:nn { #1 }{} + \g_semantex_data_tl_set:nnx { #1 } { symbol } + { + { \exp_not:n { \exp_not:n { #2 } } } + { \g_semantex_data_tl_get:nn { #1 } { spar_open } } + { \g_semantex_data_tl_get:nn { #1 } { spar_close } } + { \g_semantex_data_tl_get_exp_not:nn { #1 } { symbol } } + } + \g_semantex_data_tl_put_left:nnn { #1 } { symbol } + { + \exp_not:N + \g_semantex_symbol_parentheses:nnnn + } + } +} + + +\cs_new:Npn\g_semantex_primitive_valuekey_iffirstarg:nn#1#2 +{ + \tl_if_eq:nnTF { #2 } { true } + { + \g_semantex_data_bool_set_true:nn { #1 } { first_arg } + } + { + \tl_if_eq:nnTF { #2 } { false } + { + \g_semantex_data_bool_set_false:nn { #1 } { first_arg } + } + { + %IM Throw error later + } + } +} + +\cs_new:Npn\g_semantex_auxiliary_first_arg:nn#1#2 { #1 } +\cs_new:Npn\g_semantex_auxiliary_second_arg:nn#1#2 { #2 } + +%\cs_new:Npn\g_semantex_primitive_valuekey_otherspar:nn#1#2 +%{ +% \g_semantex_data_tl_inherit:nn { #1 } { spar_size } +% \g_semantex_data_tl_inherit:nn { #1 } { symbol } +% \g_semantex_primitive_novaluekey_return:n { #1 } +%% \tl_set:Nn\l__semantex_spar_temp +%% { +%% \exp_not:N +%% \g_semantex_symbol_parentheses:nnnn +%% } +%% \tl_put_right:Nx\l__semantex_spar_temp +%% { +%% { \exp_not:v { semantex_data_tl_#1_spar_size } } +%% { \g_semantex_auxiliary_first_arg:nn#2 } +%% { \g_semantex_auxiliary_second_arg:nn#2 } +%% { \exp_not:v { semantex_data_tl_#1_symbol } } +%% } +%% \tl_set:cx { semantex_data_tl_#1_symbol } { \exp_not:V\l__semantex_spar_temp } +% \tl_set:cx { semantex_data_tl_#1_symbol } +% { +% %{ \exp_not:c { semantex_data_tl_#1_spar_size } } +% { \exp_not:n { \use:c { semantex_data_tl_#1_spar_size } } } +% { \g_semantex_auxiliary_first_arg:nn #2 } +% { \g_semantex_auxiliary_second_arg:nn #2 } +% { \exp_not:v { semantex_data_tl_#1_symbol } } +% } +% \tl_put_left:cn { semantex_data_tl_#1_symbol } +% { +% \exp_not:N +% \g_semantex_symbol_parentheses:nnnn +% } +%} + +\cs_new:Npn\g_semantex_primitive_valuekey_otherspar:nn#1#2 +{ + \g_semantex_primitive_valuekey_otherspar_auxiliary:nnn { #1 } #2 +} + +\cs_new:Npn\g_semantex_primitive_valuekey_otherspar_auxiliary:nnn#1#2#3 +{ + %IM DOES NOT WORK!!!!! + \g_semantex_data_tl_inherit:nn { #1 } { spar_size } + \g_semantex_data_tl_get_store:nnN { #1 } { spar_size } \l__semantex_otherspar_spar_size_temp + \g_semantex_data_tl_inherit:nn { #1 } { symbol } + \g_semantex_primitive_valuekey_return:nn { #1 }{} +% \tl_set:Nn\l__semantex_spar_temp +% { +% \exp_not:N +% \g_semantex_symbol_parentheses:nnnn +% } +% \tl_put_right:Nx\l__semantex_spar_temp +% { +% { \exp_not:v { semantex_data_tl_#1_spar_size } } +% { \g_semantex_auxiliary_first_arg:nn#2 } +% { \g_semantex_auxiliary_second_arg:nn#2 } +% { \exp_not:v { semantex_data_tl_#1_symbol } } +% } +% \tl_set:cx { semantex_data_tl_#1_symbol } { \exp_not:V\l__semantex_spar_temp } + \g_semantex_data_tl_set:nnx { #1 } { symbol } + { + %{ \exp_not:c { semantex_data_tl_#1_spar_size } } + %{ \exp_not:n { \use:c { semantex_data_tl_#1_spar_size } } } + %{ normal } + %{ \exp_not:n { \exp_not:v { semantex_data_tl_#1_spar_size } } } + { \exp_not:V \l__semantex_otherspar_spar_size_temp } + { \exp_not:n { \exp_not:n { #2 } } } + { \exp_not:n { \exp_not:n { #3 } } } + { \g_semantex_data_tl_get_exp_not:nn { #1 } { symbol } } + } + \g_semantex_data_tl_put_left:nnn { #1 } { symbol } + { + \exp_not:N + \g_semantex_symbol_parentheses:nnnn + } +% \tl_put_left:cx { g_auomath_#1_symbol } +% { +% \exp_not:N +% \g_semantex_symbol_parentheses:nnnn +% } + %\tl_put_left:cn { semantex_data_tl_#1_symbol } + %{ + % \exp_not:N + % \g_semantex_symbol_parentheses:nnnn + %} +} + +\cs_new:Npn\g_semantex_primitive_valuekey_sparsize:nn#1#2{ + % sets the size of the parentheses + \g_semantex_data_tl_set:nnn { #1 } { spar_size }{ \exp_not:n { #2 } } +} + +\cs_new:Npn\g_semantex_primitive_valuekey_leftspar:nn#1#2{ + \g_semantex_data_tl_set:nnn { #1 } { spar_open }{ \exp_not:n { \exp_not:n { #2 } } } + %IM Two \exp_not necessary for unknown reasons + %IM Doing the same at leftpar yields an error. +} + +\cs_new:Npn\g_semantex_primitive_valuekey_rightspar:nn#1#2{ + \g_semantex_data_tl_set:nnn { #1 } { spar_close }{ \exp_not:n { \exp_not:n { #2 } } } + %IM Two \exp_not necessary for unknown reasons + %IM Doing the same at leftpar yields an error. +} + + + + + + +%\msg_new:nnnn { semantex } { singlekey_not_found } { Unknown~key~#1~passed~to~object~#2~on~input~line~\msg_line_number: } {} + +\cs_generate_variant:Nn \g_semantex_keys_set:nn { nx, no, nV } + +\cs_generate_variant:Nn \exp_args:Nnx { cnx } + +\cs_new:Npn \g_semantex_valuekey:nnn#1#2#3{ + % Takes care of valuekeys, keys with a value + % For the sake of implementation, the arguments + % come in a strange order + % #1 = value of key + % #2 = name of the key + % #3 = object + %\tl_set:Nn\l_semantex_key_value_temp{#1} + \tl_set:Nn\l_semantex_key_value_temp{\exp_not:n{#1}} + %\tl_set:Nx\l_semantex_key_value_temp{\exp_not:n{\exp_not:n{#1}}} % stores the content of the key in the temporary command \l_semantex_key_value_temp + %\tl_set:Nn\l_semantex_key_value_temp{#1} + %\tl_set:No\l_semantex_key_value_temp{\exp_not:n{#1}} % stores the content of the key in the temporary command \l_semantex_key_value_temp + %IM think about using extra {...} to avoid interference with keyval str + \g_semantex_valuekey_get:nnNTF { #3 } { #2 } \l_semantex_custom_valuekey_temp + { + \g_semantex_keys_set:nx { #3 } + { \l_semantex_custom_valuekey_temp } + } + { + \cs_if_exist:cTF { g_semantex_primitive_valuekey_#2:nn } + { + \use:c { g_semantex_primitive_valuekey_#2:nn }{ #3 }{ #1 } + } + { + \msg_error:nnnn { semantex } { keyval_not_found } { #2 } { #3 } + } + } +} + +\cs_generate_variant:Nn \g_semantex_keys_set:nn { nx } + +\cs_new:Npn \g_semantex_novaluekey:nn#1#2 +{ + % #1 = name of the key + % #2 = object +% % takes care of single keys, keys without a value + \g_semantex_novaluekey_get:nnNTF { #2 } { #1 } \l_semantex_custom_novaluekey_temp + { + \g_semantex_keys_set:nx { #2 } + { + \l_semantex_custom_novaluekey_temp + } + } + { + \g_semantex_keys_set:nn { #2 } { default = { #1 } } + } +} + +%IMplement the same thing for upper, lower?? Probably not. + +\cs_new:Npn \g_semantex_arg_primitive_valuekey_sep_auxiliary_function_withsep:nn#1#2 +{ + #1#2 +} + +\cs_new:Npn \g_semantex_arg_primitive_valuekey_sep_auxiliary_function_withoutsep:nn#1#2 +{ + #2 +} + +\cs_new:Npn \g_semantex_primitive_arg_valuekey_sep:nn#1#2 +{ + \g_semantex_data_bool_get:nnTF { #1 } { first_arg } + { + \g_semantex_data_tl_put_right:nnn { #1 } { arg } { + \exp_not:n { \g_semantex_arg_primitive_valuekey_sep_auxiliary_function_withoutsep:nn #2 } + } + %IM These do not use :x, unlike the ones below + } + { + \g_semantex_data_tl_put_right:nnn { #1 } { arg } { \exp_not:n { \g_semantex_arg_primitive_valuekey_sep_auxiliary_function_withsep:nn #2 } } + } + \g_semantex_primitive_valuekey_ifrightreturnbeforerender:nn{#1}{true} + \g_semantex_data_bool_set_false:nn { #1 } { first_arg } +} + +\cs_new:Npn \g_semantex_primitive_arg_valuekey_standardsep:nn#1#2 +{ + \g_semantex_data_bool_get:nnTF { #1 } { first_arg } + { + \g_semantex_data_tl_put_right:nnn { #1 } { arg } { \exp_not:n { #2 } } + %IM Recently corrected + % Previously, this was cx, but I didn’t see any point of this; + % this was mostly to create symmetry with the below case where + % cx is strictly necessary. + } + { + \g_semantex_data_tl_put_right:nnx { #1 } { arg } { \exp_not:n { \g_semantex_data_tl_get:nn { #1 } { argsep } } } + \g_semantex_data_tl_put_right:nnn { #1 } { arg } {\exp_not:n { #2 } } + % As an experiment, I tried changing cx to cn, and it failed + % when changing the separator on the fly. + } +% \g_semantex_primitive_valuekey_ifoutput:nn { #1 } { true } + \g_semantex_primitive_valuekey_ifrightreturnbeforerender:nn{#1}{true} + \g_semantex_data_bool_set_false:nn { #1 } { first_arg } +} + +\cs_new:Npn \g_semantex_primitive_arg_valuekey_dots:nn#1#2 +{ + \g_semantex_primitive_arg_valuekey_standardsep:nn { #1 } { \g_semantex_data_tl_get:nn { #1 } { argdots } } +} + +\cs_new:Npn \g_semantex_primitive_arg_valuekey_slot:nn#1#2 +{ + \g_semantex_primitive_arg_valuekey_standardsep:nn { #1 } { \g_semantex_data_tl_get:nn { #1 } { slot } } +} + +\cs_generate_variant:Nn \g_semantex_arg_keys_set:nn { nx } + +\cs_new:Npn \g_semantex_arg_valuekey:nnn#1#2#3 +{ + % Takes care of valuekeys, keys with a value + % For the sake of implementation, the arguments + % come in a strange order + % #1 = value of key + % #2 = name of the key + % #3 = object + \tl_set:Nn\l_semantex_arg_key_value_temp{\exp_not:n{#1}} % stores the content of the key in the temporary command \l_semantex_key_value_temp + \g_semantex_arg_valuekey_get:nnNTF { #3 } { #2 } \l_semantex_custom_arg_valuekey_temp + { + \g_semantex_arg_keys_set:nx { #3 } { \l_semantex_custom_arg_valuekey_temp } + } + { + \cs_if_exist:cTF { g_semantex_primitive_arg_valuekey_#2:nn } + { + \use:c { g_semantex_primitive_arg_valuekey_#2:nn }{ #3 }{ #1 }% + } + { + \msg_error:nnnn { semantex } { arg_valuekey_not_found } { #2 } { #3 } + } + } +} + + +\cs_new:Npn \g_semantex_arg_novaluekey:nn#1#2 +{ + % #1 = name of the key + % #2 = object +% % takes care of single keys, keys without a value +% the class key is not actually necessary + \g_semantex_arg_novaluekey_get:nnNTF { #2 } { #1 } \l_semantex_custom_arg_novaluekey_temp + { + %\exp_args:NNno + %\exp_args:Nno + %\use:c { g_semantex_data_cs_#3_arg:n } + \g_semantex_arg_keys_set:nx { #2 } + { + \l_semantex_custom_arg_novaluekey_temp + } + } + { + \g_semantex_data_tl_inherit_x:nn { #2 } { arg } + \g_semantex_arg_keys_set:nn { #2 } { default={\exp_not:n { #1 } }} + %\g_semantex_arg_keys_set:nn { #3 } { default={#1}} + %IM THis \exp_not:n was added late, might be needed elsewhere, too. + } +} + + +\g_semantex_data_tl_provide:nn { semantexvariable } { output } + +\g_semantex_data_tl_set:nnn { semantexvariable } { output } { semantexvariable } + +\g_semantex_data_tl_provide:nn { semantexvariable } { upper_index } + +\g_semantex_data_tl_provide:nn { semantexvariable } { uppersep } + +\g_semantex_data_tl_set:nnn { semantexvariable } { uppersep } { , } + +%IM Also, need commands like forgetupperindex, reverting to the class standard + +\g_semantex_data_tl_provide:nn { semantexvariable } { lower_index } + +\g_semantex_data_tl_provide:nn { semantexvariable } { lowersep } + +\g_semantex_data_tl_set:nnn { semantexvariable } { lowersep } { , } + +\g_semantex_data_tl_provide:nn { semantexvariable } { preupper } + +\g_semantex_data_tl_provide:nn { semantexvariable } { postupper } + +\g_semantex_data_tl_provide:nn { semantexvariable } { prelower } + +\g_semantex_data_tl_provide:nn { semantexvariable } { postlower } + +\g_semantex_data_tl_provide:nn { semantexvariable } { upper_left_index } + +\g_semantex_data_tl_provide:nn { semantexvariable } { upperleftsep } + +\g_semantex_data_tl_set:nnn { semantexvariable } { upperleftsep } { , } + +%IM do the same with all the others, INCLUDING if_upper_grading and symbol +%IM Also, need commands like forgetupperindex, reverting to the class standard + +\g_semantex_data_tl_provide:nn { semantexvariable } { lower_left_index } + +\g_semantex_data_tl_provide:nn { semantexvariable } { lowerleftsep } + +\g_semantex_data_tl_set:nnn { semantexvariable } { lowerleftsep } { , } + + +\g_semantex_data_tl_provide:nn { semantexvariable } { preupperleft } + +\g_semantex_data_tl_provide:nn { semantexvariable } { postupperleft } + +\g_semantex_data_tl_provide:nn { semantexvariable } { prelowerleft } + +\g_semantex_data_tl_provide:nn { semantexvariable } { postlowerleft } + + +\g_semantex_data_bool_provide:nn { semantexvariable } { first_upper_left } +\g_semantex_data_bool_set_true:nn { semantexvariable } { first_upper_left } + +\g_semantex_data_bool_provide:nn { semantexvariable } { first_lower_left } +\g_semantex_data_bool_set_true:nn { semantexvariable } { first_lower_left } + + + +\g_semantex_data_tl_provide:nn { semantexvariable } { prearg } + +\g_semantex_data_tl_provide:nn { semantexvariable } { postarg } +%IMplement these later + +\g_semantex_data_tl_provide:nn { semantexvariable } { arg } + +\g_semantex_data_tl_provide:nn { semantexvariable } { argsep } +\g_semantex_data_tl_set:nnn { semantexvariable } { argsep } {,} + +\g_semantex_data_tl_provide:nn { semantexvariable } { slot } +\g_semantex_data_tl_set:nnn { semantexvariable } { slot } { \semantexslot } + +\g_semantex_data_tl_provide:nn { semantexvariable } { argdots } +\g_semantex_data_tl_set:nnn { semantexvariable } { argdots } {\dots} + +\g_semantex_data_tl_provide:nn { semantexvariable } { symbol } + +\g_semantex_data_seq_provide:nn { semantexvariable } { commands_sequence } + + +\g_semantex_data_bool_provide:nn { semantexvariable } { upper_grading } +\g_semantex_data_bool_set_true:nn { semantexvariable } { upper_grading } + +\g_semantex_data_bool_provide:nn { semantexvariable } { output } + +\g_semantex_data_tl_provide:nn { semantexvariable } { output_options } + +\g_semantex_data_bool_provide:nn { semantexvariable } { first_arg } +\g_semantex_data_bool_set_true:nn { semantexvariable } { first_arg } + +\g_semantex_data_bool_provide:nn { semantexvariable } { first_upper } +\g_semantex_data_bool_set_true:nn { semantexvariable } { first_upper } + +\g_semantex_data_bool_provide:nn { semantexvariable } { first_lower } +\g_semantex_data_bool_set_true:nn { semantexvariable } { first_lower } + +\g_semantex_data_bool_provide:nn { semantexvariable } { par } +\g_semantex_data_bool_set_true:nn { semantexvariable } { par } + +\g_semantex_data_bool_provide:nn { semantexvariable } { rightreturnbeforerender } + +\g_semantex_data_tl_provide:nn { semantexvariable } { parseoptions } + +\g_semantex_data_tl_provide:nn { semantexvariable } { texclass } + + +%\tl_set:Nn\g_objectmath_semantexvariable_upper_index { hej } +%\tl_set:Nn \g_semantexvariable_output { semantexvariable } +%\bool_new:N \g_semantexvariable_output_if_provided +%\bool_set_true:N \g_semantexvariable_output_if_provided + + +\newvariableclass{semantexvariable}[ + %parent=semantexvariable, + symbol=, + gradingpos=upper, + %upper=, + %lower=, + leftpar=(, + rightpar=), + par=normal, + leftspar=(, + rightspar=), + sparsize=normal, + %arg=, + ifoutput=false, + output=semantexvariable, + novaluekeys={ + {bullet}{d={\noexpand\semantexbullet}}, + {doublebullet}{d={\noexpand\semantexdoublebullet}}, + {prime}{upper={\prime}}, + {'}{prime}, + {''}{prime,prime}, + {'''}{prime,prime,prime}, + {ibullet}{i={\noexpand\semantexbullet}}, + {idoublebullet}{i={\noexpand\semantexdoublebullet}}, + {*}{bullet}, + {**}{doublebullet}, + {i*}{ibullet}, + {i**}{idoublebullet}, + {smash}{command=\noexpand\smash}, +% (widebar}{command=\noexpand\widebar},%For unknown reasons, this only seems to work when run as a primitive + {tilde}{command=\noexpand\tilde}, + {widetilde}{command=\widetilde}, + {overline}{command=\noexpand\overline}, + {bar}{command=\noexpand\bar}, + {bold}{command=\noexpand\mathbf}, + {roman}{command=\noexpand\mathrm}, + {mathord}{texclass=\mathord}, + {mathbin}{texclass=\mathbin}, + {mathop}{texclass=\mathop}, + {mathrel}{texclass=\mathrel}, + {leftreturn}{leftreturn=}, + {innerreturn}{innerreturn=}, + {rightreturn}{rightreturn=}, + {return}{return=}, + {spar}{spar=}, + {parse}{parse=}, + {par}{ifpar=true}, + {nopar}{ifpar=false}, + % The following four commands do not work due to expansion issues: +% {useargwithkeyval}{useargwithkeyval=}, +% {argwithkeyval}{ +% valuekeys={ +% {arg}{argwithkeyval={\noexpand\l_semantex_key_value_temp}}, +% }, +% }, +% {argwithnovaluekeys}{ +% valuekeys={ +% {arg}{argwithnovaluekeys={\noexpand\l_semantex_key_value_temp}}, +% }, +% }, +% {argwithoutkeyval}{ +% valuekeys={ +% {arg}{argwithoutkeyval={\noexpand\l_semantex_key_value_temp}}, +% }, +% }, +% {argwithonenovaluekey}{ +% valuekeys={ +% {arg}{argwithonenovaluekey={\noexpand\l_semantex_key_value_temp}}, +% }, +% }, + }, + valuekeys={ + {default}{si={#1}}, +% {arg}{argwithkeyval={#1}}, + {arg}{argwithnovaluekeys={#1}}, + {degreedefault}{sd={#1}}, + {parseoptions}{ + execute={ + \semantexdataputright{parseoptions}{#1} + }, + }, + }, +% argwithnovaluekeys, + argvaluekeys={ + {default}{standardsep={#1}}, + }, + argnovaluekeys={ + {slot}{slot=}, + {-}{slot=}, + {*}{slot=}, + {...}{dots=}, + }, + %command=, +% useargwithkeyval, +]
\ No newline at end of file |