diff options
author | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-01-12 17:15:07 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-01-12 17:15:07 +0100 |
commit | 8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch) | |
tree | 94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/mkiv/mult-aux.mkiv | |
parent | f5aed2e51223c36c84c5f25a6cad238b2af59087 (diff) | |
download | context-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz |
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/mkiv/mult-aux.mkiv')
-rw-r--r-- | tex/context/base/mkiv/mult-aux.mkiv | 1268 |
1 files changed, 1268 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/mult-aux.mkiv b/tex/context/base/mkiv/mult-aux.mkiv new file mode 100644 index 000000000..693edc90e --- /dev/null +++ b/tex/context/base/mkiv/mult-aux.mkiv @@ -0,0 +1,1268 @@ +%D \module +%D [ file=mult-aux, +%D version=2010.08.2, +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=Helpers, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +% todo: setupxxx and setupxxxs (so a plural for the root setup and +% we can consider blocking the root) + +% todo (e.g for columnsets and registers): \definexxx[parent][1] +% + +%D A generalization of \MKIV-like inheritance. Just something to play +%D with (interface might change). The code here evolved in an email +%D exchange between me and Wolgang Schuster. + +% todo: doifelse<whatever> + +\writestatus{loading}{ConTeXt Multilingual Macros / Helpers} + +\registerctxluafile{mult-aux}{1.001} + +\unprotect + +\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % cancel: dec:24 hex:18 + +%D \starttyping +%D \unprotect +%D \def\????aa{@@@@aa} +%D +%D \installparameterhandler \????aa {whatever} +%D \installsetuphandler \????aa {whatever} +%D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot +%D \installfontandcolorhandler\????aa {whatever} +%D +%D % \installcommandhandler \????aa {whatever} \????aa +%D \protect +%D +%D % \whateverparameter \c!test +%D % \whateverparameterhash \c!test +%D % \namedwhateverparameter \mycurrentwhatever \c!test +%D % \usewhateverstyleandcolor \c!style \c!color +%D % \everydefinewhatever (sets \currentwhatever) +%D % \everypresetwhatever (can be used to reset parameters as we can redefine) +%D % \everysetupwhatever (sets \currentwhatever) +%D +%D \starttext +%D \definewhatever[first] \definewhatever[second][first] +%D test: \def\currentwhatever{first} \whateverparameter{method} \par +%D \setupwhatever [method=unset] test: \def\currentwhatever{first} \whateverparameter{method} \par +%D \setupwhatever[first] [method=first] test: \def\currentwhatever{first} \whateverparameter{method} \par +%D test: \def\currentwhatever{second} \whateverparameter{method} \par +%D \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par +%D \stoptext +%D \stoptyping + +% problem: every* could clash +% +% There can be less {} in the following definitions if we assume \??aa and \c!somecs +% +% todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root +% +% it might be more efficient to do this at the lua and +% +% watch the push/pop and predefinition of current .. this is needed for nested +% definitions and overloaded defines using the predefined one + +% todo: add (relaxed) postsetup and postdefine hooks, just after the everys + +% Start of experimental code: especially tables can have many assignments +% and although most time is spent in the typesetting anyway, we can squeeze +% out a little bit. Of course having 500 rows of 50 columns each with some +% setting does not happen that often. One should keep in mind that in the +% average document having some 500 assignments is no exception but there we're +% talking of neglectable runtime for them. Of course in the definitions below +% there is no real gain, only in the generated \setup* commands. Another +% situation with many assignments is \XML\ where we can pass attributes +% and normally don't do testing of them making sense. +% +% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s +% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s +% \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s + +\let\m_mult_interfaces_namespace\empty + +\def\mult_interfaces_get_parameters#1[#2% + {\if\noexpand#2]% + \expandafter\gobbleoneargument + \else + \def\m_mult_interfaces_namespace{#1}% + \expandafter\mult_interfaces_get_parameters_indeed + \fi#2} + +\def\mult_interfaces_get_parameters_indeed#1]% namespace already set + {\mult_interfaces_get_parameters_item#1,],\_e_o_p_} + +\def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before , + {\if,#1,% dirty trick for testing #1=empty + \expandafter\mult_interfaces_get_parameters_item + \else\if]#1% + \doubleexpandafter\gobbleoneargument + \else + \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_ + % \doubleexpandafter\mult_interfaces_get_parameters_item % saves skipping when at end + \fi\fi#2} + +\def\mult_interfaces_get_parameters_error#1#2% #3% + {\mult_interfaces_get_parameters_error_indeed{#1}{#2}% + \gobbleoneargument} + +\def\mult_interfaces_get_parameters_error_indeed#1#2% + {\showassignerror{#2}{\the\inputlineno\space(#1)}} + +\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_ + {\ifx\empty#1\empty + \expandafter\mult_interfaces_get_parameters_error + \else\ifx#3\empty + \doubleexpandafter\mult_interfaces_get_parameters_error + \else + \doubleexpandafter\mult_interfaces_def + \fi\fi + \m_mult_interfaces_namespace{#1}{#2}% + \doubleexpandafter\mult_interfaces_get_parameters_item} + +\startinterface english + + % some 10% faster + + \let\mult_interfaces_get_parameters_error\undefined + + \def\mult_interfaces_get_parameters_error_one#1\csname#2#3\endcsname#4% + {\mult_interfaces_get_parameters_error_indeed{#2}{#3}\iftrue} + + \def\mult_interfaces_get_parameters_error_two#1\csname#2#3\endcsname#4% + {\mult_interfaces_get_parameters_error_indeed{#2}{#3}} + + \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_ + {\ifx\empty#1\empty + \mult_interfaces_get_parameters_error_one + \else\ifx#3\empty + \mult_interfaces_get_parameters_error_two + \else + \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}% + \fi\fi + \doubleexpandafter\mult_interfaces_get_parameters_item} + + % interesting but not faster + % + % \def\mult_interfaces_get_parameters_error_one#1\m_mult_interfaces_namespace#2\fi\fi% + % {\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#2}\m_mult_interfaces_namespace\s!dummy\fi} + % + % \def\mult_interfaces_get_parameters_error_two#1\m_mult_interfaces_namespace#2\fi\fi% + % {\mult_interfaces_get_parameters_error_indeed\m_mult_interfaces_namespace{#2}\m_mult_interfaces_namespace\s!dummy\fi\fi} + % + % \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_ + % {\expandafter\def\csname + % \ifx\empty#1\empty + % \mult_interfaces_get_parameters_error_one + % \else\ifx#3\empty + % \mult_interfaces_get_parameters_error_two + % \else + % \m_mult_interfaces_namespace#1% + % \fi\fi + % \endcsname{#2} + % \doubleexpandafter\mult_interfaces_get_parameters_item} + +\stopinterface + +\newif\ifassignment + +\def\mult_check_for_assignment_indeed#1=#2#3\_end_ + {\if#2@\assignmentfalse\else\assignmenttrue\fi} + +\def\mult_check_for_assignment#1% + {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_} + +% End of experimental code. + +\unexpanded\def\mult_interfaces_let #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\unexpanded\def\mult_interfaces_lete#1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} +\unexpanded\def\mult_interfaces_def #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} + +\startinterface english + + \unexpanded\def\mult_interfaces_let #1#2{\expandafter \let\csname#1#2\endcsname} + \unexpanded\def\mult_interfaces_lete#1#2{\expandafter \let\csname#1#2\endcsname\empty} + \unexpanded\def\mult_interfaces_def #1#2{\expandafter \def\csname#1#2\endcsname} + \unexpanded\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1#2\endcsname} + \unexpanded\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1#2\endcsname} + \unexpanded\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1#2\endcsname} + +\stopinterface + +% the commented detokenized variant that backtracks ... needs testing usage first +% +% \let\whatever\relax +% +% \definetest[oeps][bagger=\whatever] +% +% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par +% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par + +\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter} + +\unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only) + {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing + %\def#3##1{\csname#4{#1#2}{##1}\endcsname}% + \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% + \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% + %\def#5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? + \def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? + \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% + \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack + % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version + % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}% +%% \def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}% + \def#8##1{\begincsname#1#2:##1\endcsname}% + \def#9##1{\csname#1#2:##1\endcsname}} % can go when we use \begincsname + +% pre-expansion can be a bit faster but handly any effect on a normal run so let's go for +% saving some memory +% +% \unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only) +% {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing +% %\def#3##1{\csname#4{#1#2}{##1}\endcsname}% +% \edef#3##1{\noexpand\csname\noexpand\ifcsname#1\noexpand#2:##1\endcsname#1\noexpand#2:##1\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname#1\noexpand#2:\s!parent\endcsname{##1}\noexpand\fi\endcsname}% +% \edef#4##1##2{\noexpand\ifcsname##1:##2\endcsname##1:##2\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname##1:\s!parent\endcsname{##2}\noexpand\fi}% +% \def #5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? +% \edef#6##1##2{\noexpand\csname\noexpand\ifcsname#1##1:##2\endcsname#1##1:##2\noexpand\else\noexpand\expandafter\noexpand#5\noexpand\csname#1##1:\s!parent\endcsname{##2}\noexpand\fi\endcsname}% +% \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack +% % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version +% % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}% +% \edef#8##1{\noexpand\csname\noexpand\ifcsname#1\noexpand#2:##1\endcsname#1\noexpand#2:##1\noexpand\else\s!empty\noexpand\fi\endcsname}% +% \edef#9##1{\noexpand\csname#1#2:##1\endcsname}} + +\unexpanded\def\installparameterhandler#1#2% + {\normalexpanded + {\mult_interfaces_install_parameter_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname #2parameter\endcsname + \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter + \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter + \expandafter\noexpand\csname named#2parameter\endcsname + \expandafter\noexpand\csname detokenized#2parameter\endcsname + \expandafter\noexpand\csname strict#2parameter\endcsname % checked + \expandafter\noexpand\csname direct#2parameter\endcsname}} % unchecked + +\unexpanded\def\mult_interfaces_install_root_parameter_handler#1#2#3% + {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root + %\def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}} + %\def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\??empty\fi\endcsname}} + \def#3##1{\begincsname#1:##1\endcsname}} + +\unexpanded\def\installrootparameterhandler#1#2% + {\normalexpanded + {\mult_interfaces_install_root_parameter_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname + \expandafter\noexpand\csname root#2parameter\endcsname}} + +\unexpanded\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9% + {\ifx#2\relax\let#2\empty\fi + \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used? + \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% + \def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}% + \def#6{#1#2:}% + \def#7##1{#1##1:}% + \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}% + \unexpanded\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}} + +\unexpanded\def\installparameterhashhandler#1#2% + {\expandafter\let\csname#2namespace\endcsname#1% + \normalexpanded + {\mult_interfaces_install_parameter_hash_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname #2parameterhash\endcsname + \expandafter\noexpand\csname do#2parameterhash\endcsname % or : #2_parameter_hash + \expandafter\noexpand\csname do#2parentparameterhash\endcsname % or : #2_parent_parameter_hash + \expandafter\noexpand\csname current#2hash\endcsname + \expandafter\noexpand\csname named#2hash\endcsname + \expandafter\noexpand\csname check#2parent\endcsname + \expandafter\noexpand\csname chaintocurrent#2\endcsname}} + +% In \MKIV\ we can probably use the english variant for all other +% languages too. + +% todo: inline the def/let + +\unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% + {\ifx#2\relax\let#2\empty\fi + \unexpanded\def#3{\mult_interfaces_def {#1#2:}}% ##1 {##2} (braces are mandate) + \unexpanded\def#4{\mult_interfaces_edef{#1#2:}}% ##1 {##2} (braces are mandate) + \unexpanded\def#5{\mult_interfaces_let {#1#2:}}% ##1 ##2 + \unexpanded\def#6{\mult_interfaces_lete{#1#2:}}}% ##1 + +\startinterface english + + \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% + {\ifx#2\relax\let#2\empty\fi + \unexpanded\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) + \unexpanded\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) + \unexpanded\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2 + \unexpanded\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1 + +\stopinterface + +\unexpanded\def\installparametersethandler#1#2% + {\normalexpanded + {\mult_interfaces_install_parameter_set_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname set#2parameter\endcsname + \expandafter\noexpand\csname setexpanded#2parameter\endcsname + \expandafter\noexpand\csname let#2parameter\endcsname + \expandafter\noexpand\csname reset#2parameter\endcsname}} + +\let\dousecurrentstyleparameter\relax +\let\dousecurrentcolorparameter\relax + +\let\currentstyleparameter\empty +\let\currentcolorparameter\empty + +\unexpanded\def\mult_interfaces_install_style_and_color_handler#1#2#3#4% + {\unexpanded\def#2##1##2% style color + {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline) + \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi + \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch) + \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}% + \unexpanded\def#3##1% style + {\edef\currentstyleparameter{#1{##1}}% this name is public + \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}% + \unexpanded\def#4##1% color + {\edef\currentcolorparameter{#1{##1}}% this name is public + \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}} + +\unexpanded\def\installstyleandcolorhandler#1#2% + {\normalexpanded + {\mult_interfaces_install_style_and_color_handler + \expandafter\noexpand\csname #2parameter\endcsname + \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters + \expandafter\noexpand\csname use#2styleparameter\endcsname + \expandafter\noexpand\csname use#2colorparameter\endcsname}} + +\let\definehandlerparent\empty + +\def\mult_check_for_parent#1#2#3#4% + {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else + \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}% + \fi \fi} + +%def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi} +%def\getparentchain #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi} +%def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi} + +\def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi} +\def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname} +\def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname} + +\unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones + {\ifx#4\relax\let#4\empty\fi % see \defineregister + \unexpanded\def#2{\dotripleempty#5}% + \newtoks#6% + \newtoks#7% + \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] + {\let#9#4% + \edef#4{##1}% + \ifthirdargument + \the#6% predefine + \edef#8{##2}% + \mult_check_for_parent{#1}{#3}#4#8% + \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#4:}[##3]% + \else\ifsecondargument + \the#6% predefine + \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_ + \ifassignment + \let#8\empty + \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% + \mult_interfaces_get_parameters{#1#4:}[##2]% + \else + \edef#8{##2}% + \mult_check_for_parent{#1}{#3}#4#8% + \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% + \fi + \else + \the#6% predefine + \let#8\empty + \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% + \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% + \fi\fi + \the#7% + \let#4#9}} + +\unexpanded\def\installdefinehandler#1#2#3% + {\normalexpanded + {\mult_interfaces_install_define_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname define#2\endcsname + {\noexpand#3}% root + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname define_#2\endcsname % semi-public + \expandafter\noexpand\csname everypreset#2\endcsname + \expandafter\noexpand\csname everydefine#2\endcsname + \expandafter\noexpand\csname current#2parent\endcsname + \expandafter\noexpand\csname saved_defined_#2\endcsname}} + +\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9% + {\ifx#3\relax\let#3\empty\fi + \unexpanded\def#2{\dodoubleempty#4}% + \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it + \newtoks#5% + \newtoks#8% + \unexpanded\def#4[##1][##2]% maybe helper + {\let#7#3% + \ifsecondargument + \def#9####1% we will have a simple one as well + {\edef#3{####1}% + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#5}% + \processcommalist[##1]#9% + \else + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#5% + \fi + \let#3#7% + \the#8}} + +\unexpanded\def\installsetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_setup_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname setup_#2\endcsname % semi-public + \expandafter\noexpand\csname everysetup#2\endcsname + \expandafter\noexpand\csname setupcurrent#2\endcsname + \expandafter\noexpand\csname saved_setup_current#2\endcsname + \expandafter\noexpand\csname everysetup#2root\endcsname + \expandafter\noexpand\csname nested_setup_current#2\endcsname}} + +\let\doingrootsetupnamed\plusone % \setuplayout[name][key=value] +\let\doingrootsetuproot \plustwo % \setuplayout [key=value] +\let\doingrootsetnamed \plusthree % \setuplayout[name] +\let\doingrootsetroot \plusfour % \setuplayout + +\unexpanded\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5% + {\ifx#3\relax\let#3\empty\fi + \unexpanded\def#2{\dodoubleempty#4}% + \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}} + +\unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9% + {\newtoks#5% + \newconstant#2% + \newtoks#8% + \newtoks#9% + \ifx#6\relax\let#6\empty\fi + \unexpanded\def#4[##1][##2]% maybe helper + {\ifsecondargument % no commalist here + % \setuplayout[whatever][key=value] + \let#7#3% + \let#6#3% + \edef#3{##1}% + #2\doingrootsetupnamed + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#5% + \ifx#3#6\the#8\fi % only switchsetups if previous == current + \let#3#7% + \else\iffirstargument + % \mult_check_for_assignment{##1}% + \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_ + \ifassignment + % \setuplayout[key=value] + \let#7#3% + \let#6#3% + \let#3\empty + #2\doingrootsetuproot + \mult_interfaces_get_parameters{#1:}[##1]% + \the#5% + \the#8% switchsetups + \let#3#7% + \else + % \setuplayout[whatever] + \let#6#3% % previous becomes current + \edef#3{##1}% this will catch reset so one needs to test for it + #2\doingrootsetnamed + \the#5% % we can check for previous vs current + \the#8% switchsetups + \fi + \else + % \setuplayout + \let#6#3% % previous becomes current + \let#3\empty % current becomes empty + #2\doingrootsetroot + \the#5% + \the#8% switchsetups + \fi\fi + #2\zerocount % mode is always zero at the end + \the#9}} + +\unexpanded\def\installswitchsetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_switch_setup_handler_a + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname setup_#2\endcsname % semi-public + \expandafter\noexpand\csname setupcurrent#2\endcsname + \mult_interfaces_install_switch_setup_handler_b + {\noexpand#1}% \??aa + \expandafter\noexpand\csname #2setupmode\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname setup_#2\endcsname % semi-public + \expandafter\noexpand\csname everysetup#2\endcsname + \expandafter\noexpand\csname previous#2\endcsname + \expandafter\noexpand\csname saved_setup_current#2\endcsname + \expandafter\noexpand\csname everyswitch#2\endcsname + \expandafter\noexpand\csname everysetup#2root\endcsname}} + +\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9% + {\ifx#3\relax\let#3\empty\fi + \unexpanded\def#2{\dotripleempty#4}% + \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% + \newtoks#5% + \def#4[##1][##2][##3]% + {\let#8#3% + \ifthirdargument + \def#9####1% + {\edef#3{####1}% + \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent + \the#5}% + \processcommalist[##1]#9% + \else\ifsecondargument + \def#9####1% + {\edef#3{####1}% + #7% checks parent and sets if needed + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#5}% + \processcommalist[##1]#9% + \else + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#5% + \fi\fi + \let#3#8}} + +\unexpanded\def\installautosetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_auto_setup_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname setup_#2\endcsname % semi-public + \expandafter\noexpand\csname everysetup#2\endcsname + \expandafter\noexpand\csname setupcurrent#2\endcsname + \expandafter\noexpand\csname check#2parent\endcsname + \expandafter\noexpand\csname saved_setup_current#2\endcsname + \expandafter\noexpand\csname nested_setup_current#2\endcsname}} + +\unexpanded\def\installbasicparameterhandler#1#2% + {\installparameterhandler {#1}{#2}% + \installparameterhashhandler{#1}{#2}% + \installparametersethandler {#1}{#2}% + \installrootparameterhandler{#1}{#2}} + +\unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installautosetuphandler {#1}{#2}} + +\unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}{#3}% + \installsetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\unexpanded\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self) + {\installbasicparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}{#3}% + \installswitchsetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\unexpanded\def\installautocommandhandler#1#2#3% automatically defined cloned setups + {\installbasicparameterhandler{#1}{#2}% + \installdefinehandler {#1}{#2}{#3}% + \installautosetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +\unexpanded\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining + {\installbasicparameterhandler{#1}{#2}% + \installsetuphandler {#1}{#2}% + \installstyleandcolorhandler {#1}{#2}} + +%D Many mechanisms have some kind of inheritance in place, and these are +%D the speed||critical ones. Therefore there is no reason to stick to +%D \type {\@@xxkey} for the sake of performance. For this reason we also +%D provide a direct variant. This permits a more consistent treatment of +%D namespaces. A \type {\whateverparameter} call is three times slower +%D and a \type {\directwhateverparameter} call two times but for some +%D 100K expansions we only loose some .1 second which is neglectable +%D given the small amount of expansions in real runs. + +%D We don't need colons for such simple cases. + +\unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5% +%%{\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}% + {\def#3##1{\begincsname#1##1\endcsname}% + \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}% + % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}% + \def#5##1{\csname#1##1\endcsname}} + +\unexpanded\def\installdirectparameterhandler#1#2% + {\normalexpanded + {\mult_interfaces_install_direct_parameter_handler + {\noexpand#1}% + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname #2parameter\endcsname + \expandafter\noexpand\csname detokenized#2parameter\endcsname + \expandafter\noexpand\csname direct#2parameter\endcsname}} + +\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5% + {\unexpanded\def#2{\dosingleempty#3}% + \newtoks#5% + \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}% + \def#4{\mult_interfaces_get_parameters#1}} + +\unexpanded\def\installdirectsetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_direct_setup_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname setup_#2\endcsname % semi-public + \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency) + \expandafter\noexpand\csname everysetup#2\endcsname}} + +\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% + {\unexpanded\def#2{\mult_interfaces_def #1}% + \unexpanded\def#3{\mult_interfaces_edef#1}% + \unexpanded\def#4{\mult_interfaces_let #1}% + \unexpanded\def#5{\mult_interfaces_let #1\empty}}% + +\startinterface english + + \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% + {\unexpanded\def#2##1{\expandafter \def\csname#1##1\endcsname}% + \unexpanded\def#3##1{\expandafter\edef\csname#1##1\endcsname}% + \unexpanded\def#4##1{\expandafter \let\csname#1##1\endcsname}% + \unexpanded\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}% + +\stopinterface + +\unexpanded\def\installdirectparametersethandler#1#2% + {\normalexpanded + {\mult_interfaces_install_direct_parameter_set_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname set#2parameter\endcsname + \expandafter\noexpand\csname setexpanded#2parameter\endcsname + \expandafter\noexpand\csname let#2parameter\endcsname + \expandafter\noexpand\csname reset#2parameter\endcsname}} + +\let\installdirectstyleandcolorhandler\installstyleandcolorhandler + +\unexpanded\def\installdirectcommandhandler#1#2% + {\installdirectparameterhandler {#1}{#2}% + \installdirectsetuphandler {#1}{#2}% + \installdirectparametersethandler {#1}{#2}% + \installdirectstyleandcolorhandler{#1}{#2}} + +\unexpanded\def\installsetuponlycommandhandler#1#2% + {\installdirectparameterhandler{#1}{#2}% + \installdirectsetuphandler {#1}{#2}% + }% maybe \installdirectparametersethandler {#1}{#2}% + +% Experiment: + +% \installcorenamespace {one} +% \installcorenamespace {two} +% +% \installcommandhandler \??one {one} \??one +% \installcommandhandler \??two {two} \??two +% +% \defineone[test] \setupone[test][alpha=first] +% \definetwo[test] \setuptwo[test][beta=second] +% +% \protect +% +% \def\currentone{test} +% \def\currenttwo{test} +% +% \relateparameterhandlers {two} {test} {one} {test} +% +% yes:\oneparameter{alpha}\par +% nop:\oneparameter{beta}\par +% yes:\twoparameter{alpha}\par +% yes:\twoparameter{beta}\par + +\unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance} + {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}} + +%D Here is another experiment: + +\unexpanded\def\installactionhandler#1% + {\normalexpanded + {\mult_interfaces_install_action_handler + {#1}% + \expandafter\noexpand\csname current#1\endcsname + \expandafter\noexpand\csname setupcurrent#1\endcsname + \expandafter\noexpand\csname #1_action\endcsname}} + +\unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4% + {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}% + \unexpanded\def#4[##1][##2]% + {\begingroup + \ifsecondargument + \edef#2{##1}% + #3[##2]% + \else\iffirstargument + \doifelseassignment{##1} + {\let#2\empty + #3[##1]}% + {\edef#2{##1}}% + \else + \let#2\empty + \fi\fi + \directsetup{handler:action:#1}% + \endgroup}} + +% First we had, in tune with the regular system variables: +% +% \starttyping +% \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}} +% \stoptyping +% +% The following variant is nicer and in principle faster but that gets +% unnoticed unless lots of expansion happens. Also, we can use long tags +% but the internal expansion will be relatively small (and unlikely more +% than 4 characters). For instance, \??xx used to expand to @@xx but now +% becomes for instance 123::. This is one character more but in quite some +% cases we had : after such a tag in the old situation. In the new situation +% we create more namespaces and don't need that : any more, so we end up +% with on the average the same amount of tokens and definitely less when +% we consider cases like \??xx:\c!align: which now is just \??somealign and +% therefore has length 5 now (instead of 4+1+5+1=10). +% +% Eventualy we will have a verbose \blablanamespace and the difference between +% core and regular can go ... after all, \xxxparameter can already clash between +% the two prefix groups .. if users use this mechanism a lot they should use +% verbose names anyway (the old two character names were mostly an optimization +% as they also expanded to these characters). + +% todo: register namespaces at lua end for logging and reverse resolve +% todo: move this to syst-ini so that we can use it real early + +\newcount\c_mult_interfaces_n_of_namespaces + +%def\v_interfaces_prefix_template{\number \c_mult_interfaces_n_of_namespaces>} +\def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>} + +\def\v_interfaces_prefix_template % consistently %03i> + {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\else\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi\fi + \number\c_mult_interfaces_n_of_namespaces>} + +\def\v_interfaces_prefix_template % consistently %03i> + {\number\c_mult_interfaces_n_of_namespaces>} + +\unexpanded\def\installnamespace#1% for modules and users + {\ifcsname ????#1\endcsname + \writestatus\m!system{duplicate user namespace '#1'}\wait + \else + \global\advance\c_mult_interfaces_n_of_namespaces\plusone + \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}% + \fi} + +\unexpanded\def\installcorenamespace#1% + {\ifcsname ??#1\endcsname + \writestatus\m!system{duplicate core namespace '#1'}\wait + \else + \global\advance\c_mult_interfaces_n_of_namespaces\plusone + \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}% + \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}% + \fi} + +\def\mult_interfaces_get_parameters_error_indeed#1#2% + {\clf_showassignerror{#1}{#2}\inputlineno} % no longer \waitonfatalerror + +% We install two core namespaces here, as we want nice error messages. Maybe +% we will reserve the first 9. + +\installcorenamespace{fontinstanceready} +\installcorenamespace{fontinstancebasic} +\installcorenamespace{fontinstanceclass} + +%D The next one is handy for local assignments. + +\installcorenamespace{dummy} + +\letvalue\??dummy\empty + +%% \def\dummyparameter #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname} + \def\dummyparameter #1{\begincsname\??dummy#1\endcsname} + \def\directdummyparameter#1{\csname\??dummy#1\endcsname} +\unexpanded\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname} +\unexpanded\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname} + +% \unexpanded\def\getdummyparameters +% {\mult_interfaces_get_parameters\??dummy} + +\unexpanded\def\getdummyparameters[#1% + {\if\noexpand#1]% + \expandafter\gobbleoneargument + \else + \let\m_mult_interfaces_namespace\??dummy + \expandafter\mult_interfaces_get_parameters_indeed + \fi#1} + +\mult_interfaces_install_style_and_color_handler + \directdummyparameter + \usedummystyleandcolor + \usedummystyleparameter + \usedummycolorparameter + +% Maybe a \definecorenamespace[name][directparameter,directsetup][parent] +% but we don't gain much. Actually we might just inline all definitions. + +% \enabletrackers[interfaces.namespaces,context.flush] +% +% \definenamespace +% [xy] +% [type=module, +% comment=test module, +% version=1, +% name=test, +% style=yes, +% command=yes, +% setup=list, +% set=yes, +% parent=xy] +% +% \unprotect +% \getparameters +% [\????xy] +% [text=] +% \protect +% +% \definetest[one] +% +% \starttext +% +% “\testparameter{text}” +% +% \setuptest[text=foo] +% +% “\testparameter{text}” +% +% \setuptest[one][text=bar] +% +% “\testparameter{text}” +% +% \stoptext +% +% This is a user (module) command: + +\unexpanded\def\definenamespace + {\dodoubleargument\mult_interfaces_define_name_space} + +\def\mult_interfaces_define_name_space[#1][#2]% namespace settings + {\clf_definenamespace{#1}{#2}} + +\def\listnamespaces + {\clf_listnamespaces} + +%D Helper: +%D +%D \starttyping +%D \showparentchain{@@am}{left} +%D \stoptyping + +\unexpanded\def\showparentchain#1#2% + {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}} + +% \def\mult_interfaces_show_parent_chain#1% +% {#1 => % +% \ifcsname#1:\s!parent\endcsname +% \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname +% \fi} + +\def\mult_interfaces_show_parent_chain#1% + {#1 => % + \ifcsname#1:\s!parent\endcsname + %\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname + \expandafter\mult_interfaces_show_parent_chain\lastnamedcs + \fi} + +%D Another helper (needs to be applied): + +\unexpanded\def\doifelsecommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\let\doifcommandhandlerelse\doifelsecommandhandler + +\unexpanded\def\doifcommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\unexpanded\def\doifnotcommandhandler#1#2% namespace name + {\ifcsname#1#2:\s!parent\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\let\doifcommandhandlerelse\doifelsecommandhandler + +% another set of (fast) helpers (grep for usage): + +\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy + {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3} + +\def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy + {#1\endcsname#1\else#2\fi\endcsname} + +\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy + {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname} + +\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname + {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}} + +\def\syst_helpers_expand_checked_value#1#2% + {#1\endcsname#1\else#2\fi\endcsname} + +%D Conventions: +%D +%D \starttyping +%D \newcount \c_class_whatever +%D \newconditional \c_class_whatever +%D \newconstant \c_class_whatever +%D \newdimen \d_class_whatever +%D \newskip \s_class_whatever +%D \newmuskip \s_class_whatever +%D \newbox \b_class_whatever +%D \newtoks \t_class_whatever +%D +%D \edef\p_class_whatever{\classparameter\c!whatever} +%D \edef\m_class_whatever{whatever} +%D \stoptyping + +% experiment: in principle this is faster but not that noticeable as we don't do that +% many assignments and mechanism that do are also slow; the advantage is mostly nicer +% in tracing + +\def\s!simple{simple} +\def\s!single{single} +\def\s!double{double} +\def\s!triple{triple} + +\unexpanded\def\syst_helpers_double_empty#1#2#3% + {\syst_helpers_argument_reset + \doifelsenextoptional + {\syst_helpers_double_empty_one_yes_mult#2#3}% + {\syst_helpers_double_empty_one_nop_mult#1}} + +\def\syst_helpers_double_empty_one_yes_mult#1#2[#3]% + {\firstargumenttrue + \doifelsenextoptional + {\secondargumenttrue#2[{#3}]}% + {\syst_helpers_double_empty_two_nop_mult#1{#3}}} + +\def\syst_helpers_double_empty_one_nop_mult% #1% + {\firstargumentfalse + \secondargumentfalse + }% #1} + +\def\syst_helpers_double_empty_two_nop_mult + {\secondargumentfalse + \if_next_blank_space_token + \expandafter\syst_helpers_double_empty_one_spaced_mult + \else + \expandafter\syst_helpers_double_empty_one_normal_mult + \fi} + +\def\syst_helpers_double_empty_one_spaced_mult#1#2{#1[{#2}] } +\def\syst_helpers_double_empty_one_normal_mult#1#2{#1[{#2}]} + +\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8% + {\ifx#3\relax\let#3\empty\fi + \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it + \newtoks#4% + \newtoks#7% + \edef\m_mult_interface_setup{\csstring#2_}% + \unexpanded\edef#2{\syst_helpers_double_empty + \csname\m_mult_interface_setup\s!simple\endcsname + \csname\m_mult_interface_setup\s!single\endcsname + \csname\m_mult_interface_setup\s!double\endcsname}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]% + {\let#6#3% + \def#8####1% we will have a simple one as well + {\edef#3{####1}% + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#4}% + \processcommalist[##1]#8% + \let#3#6% + \the#7}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]% + {\let#6#3% + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#4% + \let#3#6% + \the#7}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname% + {\let#6#3% + \let#3\empty + \the#4% + \let#3#6% + \the#7}} + +\unexpanded\def\installsetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_setup_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname everysetup#2\endcsname + \expandafter\noexpand\csname setupcurrent#2\endcsname + \expandafter\noexpand\csname saved_setup_current#2\endcsname + \expandafter\noexpand\csname everysetup#2root\endcsname + \expandafter\noexpand\csname nested_setup_current#2\endcsname}} + +\unexpanded\def\syst_helpers_triple_empty#1#2#3#4% + {\syst_helpers_argument_reset + \doifelsenextoptional + {\syst_helpers_triple_empty_one_yes_mult#2#3#4}% + {\syst_helpers_triple_empty_one_nop_mult#1}} + +\def\syst_helpers_triple_empty_one_yes_mult#1#2#3[#4]% + {\firstargumenttrue + \doifelsenextoptional + {\syst_helpers_triple_empty_two_yes_mult#2#3{#4}}% + {\syst_helpers_triple_empty_two_nop_mult#1{#4}}} + +\def\syst_helpers_triple_empty_two_yes_mult#1#2#3[#4]% + {\secondargumenttrue + \doifelsenextoptional + {\thirdargumenttrue#2[{#3}][{#4}]}% + {\syst_helpers_triple_empty_three_nop_mult#1{#3}{#4}}} + +\def\syst_helpers_triple_empty_one_nop_mult % #1% + {\firstargumentfalse + \secondargumentfalse + \thirdargumentfalse + } % #1 + +\def\syst_helpers_triple_empty_two_nop_mult + {\secondargumentfalse + \thirdargumentfalse + \if_next_blank_space_token + \expandafter\syst_helpers_triple_empty_two_spaced_mult + \else + \expandafter\syst_helpers_triple_empty_two_normal_mult + \fi} + +\def\syst_helpers_triple_empty_three_nop_mult + {\thirdargumentfalse + \if_next_blank_space_token + \expandafter\syst_helpers_triple_empty_three_spaced_mult + \else + \expandafter\syst_helpers_triple_empty_three_normal_mult + \fi} + +\def\syst_helpers_triple_empty_two_spaced_mult #1#2{#1[{#2}] } +\def\syst_helpers_triple_empty_two_normal_mult #1#2{#1[{#2}]} +\def\syst_helpers_triple_empty_three_spaced_mult#1#2#3{#1[{#2}][{#3}] } +\def\syst_helpers_triple_empty_three_normal_mult#1#2#3{#1[{#2}][{#3}]} + +\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8% + {\ifx#3\relax\let#3\empty\fi + \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% + \newtoks#4% + \edef\m_mult_interface_setup{\csstring#2_}% + \unexpanded\edef#2{\syst_helpers_triple_empty + \csname\m_mult_interface_setup\s!simple\endcsname + \csname\m_mult_interface_setup\s!single\endcsname + \csname\m_mult_interface_setup\s!double\endcsname + \csname\m_mult_interface_setup\s!triple\endcsname}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!triple\endcsname[##1][##2][##3]% + {\let#7#3% + \def#8####1% + {\edef#3{####1}% + \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent + \the#4}% + \processcommalist[##1]#8% + \let#3#7}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]% + {\let#7#3% + \def#8####1% + {\edef#3{####1}% + #6% checks parent and sets if needed + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#4}% + \processcommalist[##1]#8% + \let#3#7}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]% + {\let#7#3% + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#4% + \let#3#7}% + \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname% + {\let#7#3% + \let#3\empty + \the#4% + \let#3#7}} + +\unexpanded\def\installautosetuphandler#1#2% + {\normalexpanded + {\mult_interfaces_install_auto_setup_handler + {\noexpand#1}% \??aa + \expandafter\noexpand\csname setup#2\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname everysetup#2\endcsname + \expandafter\noexpand\csname setupcurrent#2\endcsname + \expandafter\noexpand\csname check#2parent\endcsname + \expandafter\noexpand\csname saved_setup_current#2\endcsname + \expandafter\noexpand\csname nested_setup_current#2\endcsname}} + +% okay, we can also get rid of the #9, but this code looks pretty bad, while the previous is +% still okay given that we can also use #6 as setup (so in fact we can save some cs again and +% only use one extra) +% +% \global\advance\commalevel \plusone +% \expandafter\def\csname\??nextcommalevel\the\commalevel\endcsname####1,% +% {\edef#3{####1}% +% \mult_interfaces_get_parameters{#1#3:}[##2]% +% \the#5% +% \syst_helpers_do_process_comma_item}% +% \expandafter\syst_helpers_do_do_process_comma_item\gobbleoneargument\relax##1,]\relax +% % \syst_helpers_do_do_process_comma_item##1,]\relax +% \global\advance\commalevel \minusone + +% The next one is experimental (and used in publications): + +\let\c_mult_set\relax + +\unexpanded\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7% + {\newcount#3% + \let#6\empty + \unexpanded\def#2% + {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname + \ifx\c_mult_set\relax + \expandafter\newtoks\c_mult_set + \expandafter\let\csname #1_t_#6\endcsname\c_mult_set + \fi} + \unexpanded\def#4##1% + {\pushmacro#6% + \advance#3\plusone + \edef#6{##1}% + \unprotect}% + \unexpanded\def#5% + {\protect + \advance#3\minusone + \popmacro#6}% + \unexpanded\def#7##1% + {\edef#6{##1}% + #2% + \the\c_mult_set\relax}} + +\unexpanded\def\installdefinitionset#1#2% + {\normalexpanded + {\mult_interfaces_install_definition_set + {\noexpand#1}% \??aa + \expandafter\noexpand\csname set_#2_toks\endcsname + \expandafter\noexpand\csname #2_nesting_depth\endcsname + \expandafter\noexpand\csname push#2\endcsname + \expandafter\noexpand\csname pop#2\endcsname + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname use#2\endcsname}} + +\unexpanded\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc + {\let#5#2% + \unexpanded\def#2% + {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}% + \unexpanded\def#6% + {\dodoubleempty#7}% + \unexpanded\def#7[##1][##2]% + {\ifsecondargument + #3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}% + \else\iffirstargument + #3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}% + \fi\fi}} + +\unexpanded\def\installdefinitionsetmember#1#2#3#4% + {\normalexpanded + {\mult_interfaces_install_definition_set_member + {\noexpand#3}% \??aa + \expandafter\noexpand\csname setup#4\endcsname + \expandafter\noexpand\csname set_#2_toks\endcsname + \expandafter\noexpand\csname #2_nesting_depth\endcsname + \expandafter\noexpand\csname normal_setup_#4\endcsname + \expandafter\noexpand\csname delayed_setup_#4\endcsname + \expandafter\noexpand\csname do_delayed_setup_#4\endcsname + \expandafter\noexpand\csname setup#4_\s!single\endcsname + \expandafter\noexpand\csname setup#4_\s!double\endcsname}} + +%D Another experiment: + +\unexpanded\def\mult_interfaces_install_parent_injector#1#2#3#4% + {\unexpanded\def#4##1% + {\ifx#3\empty + \expandafter\def\csname#1#2:\s!parent\endcsname{#1##1}% + \fi}} + +\unexpanded\def\installparentinjector#1#2% + {\normalexpanded{\mult_interfaces_install_parent_injector + {\noexpand#1}% + \expandafter\noexpand\csname current#2\endcsname + \expandafter\noexpand\csname current#2parent\endcsname + \expandafter\noexpand\csname inject#2parent\endcsname}} + +\protect + +%\unprotect +% \installcorenamespace {test} \installcommandhandler \??test {test} \??test +% \unexpanded\def\TestMeA[#1]% +% {\edef\currenttest{#1} +% \edef\p_before{\testparameter\c!before}% +% \ifx\p_before\empty \relax \else \relax \fi} +% \unexpanded\def\TestMeB[#1]% +% {\edef\currenttest{#1} +% \doifelsenothing{\testparameter\c!before}\relax\relax} +% \unexpanded\def\TestMeC[#1]% +% {\edef\currenttest{#1} +% \expandafter\expandafter\expandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi} +% \unexpanded\def\TestMeD[#1]% +% {\edef\currenttest{#1} +% \doubleexpandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi} +% \protect +% +% \starttext +% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed] +% \resettimer \dorecurse{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502 +% \resettimer \dorecurse{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530 +% \resettimer \dorecurse{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487 +% \resettimer \dorecurse{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493 +% \stoptext |