4 %D title=\CONTEXT\ Multilingual Macros,
8 %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
10 %C This module is part of the \CONTEXT\ macro||package and is
11 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
14 % todo: setupxxx and setupxxxs (so a plural for the root setup and
15 % we can consider blocking the root)
17 % todo (e.g for columnsets and registers): \definexxx[parent][1]
20 %D A generalization of \MKIV-like inheritance. Just something to play
21 %D with (interface might change). The code here evolved in an email
22 %D exchange between me and Wolgang Schuster.
24 % todo: doifelse<whatever>
26 \writestatus{loading}{ConTeXt Multilingual Macros / Helpers}
28 \registerctxluafile{mult-aux}{1.001}
34 %D \def\????aa{@@@@aa}
36 %D \installparameterhandler \????aa {whatever}
37 %D \installsetuphandler \????aa {whatever}
38 %D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot
39 %D \installfontandcolorhandler\????aa {whatever}
41 %D % \installcommandhandler \????aa {whatever} \????aa
44 %D % \whateverparameter \c!test
45 %D % \whateverparameterhash \c!test
46 %D % \namedwhateverparameter \mycurrentwhatever \c!test
47 %D % \usewhateverstyleandcolor \c!style \c!color
48 %D % \everydefinewhatever (sets \currentwhatever)
49 %D % \everypresetwhatever (can be used to reset parameters as we can redefine)
50 %D % \everysetupwhatever (sets \currentwhatever)
53 %D \definewhatever[first] \definewhatever[second][first]
54 %D test: \def\currentwhatever{first} \whateverparameter{method} \par
55 %D \setupwhatever [method=unset] test: \def\currentwhatever{first} \whateverparameter{method} \par
56 %D \setupwhatever[first] [method=first] test: \def\currentwhatever{first} \whateverparameter{method} \par
57 %D test: \def\currentwhatever{second} \whateverparameter{method} \par
58 %D \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par
62 % problem: every* could clash
64 % There can be less {} in the following definitions if we assume \??aa and \c!somecs
66 % todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root
68 % it might be more efficient to do this at the lua and
70 % watch the push/pop and predefinition of current .. this is needed for nested
71 % definitions and overloaded defines using the predefined one
73 % todo: add (relaxed) postsetup and postdefine hooks, just after the everys
75 % Start of experimental code: especially tables can have many assignments
76 % and although most time is spent in the typesetting anyway, we can squeeze
77 % out a little bit. Of course having 500 rows of 50 columns each with some
78 % setting does not happen that often. One should keep in mind that in the
79 % average document having some 500 assignments is no exception but there we're
80 % talking of neglectable runtime for them. Of course in the definitions below
81 % there is no real gain, only in the generated \setup* commands. Another
82 % situation with many assignments is \XML\ where we can pass attributes
83 % and normally don't do testing of them making sense.
85 % \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
86 % \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
87 % \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s
89 \let\m_mult_interfaces_namespace\empty
91 \def\mult_interfaces_get_parameters#1[#2%
93 \expandafter\gobbleoneargument
95 \def\m_mult_interfaces_namespace{#1}%
96 \expandafter\mult_interfaces_get_parameters_indeed
99 \def\mult_interfaces_get_parameters_indeed#1]% namespace already set
100 {\mult_interfaces_get_parameters_item#1,],\_e_o_p_}
102 \def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
103 {\if,#1,% dirty trick for testing #1=empty
104 \expandafter\mult_interfaces_get_parameters_item
106 \doubleexpandafter\gobbleoneargument
108 \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_
109 \doubleexpandafter\mult_interfaces_get_parameters_item
112 \def\mult_interfaces_get_parameters_error#1#2#3%
113 {\showassignerror{#2}{\the\inputlineno\space(#1)}}
115 \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
117 \expandafter\mult_interfaces_get_parameters_error
119 \doubleexpandafter\mult_interfaces_get_parameters_error
121 \doubleexpandafter\dosetvalue
123 \m_mult_interfaces_namespace{#1}{#2}}
127 \def\mult_check_for_assignment_indeed#1=#2#3\_end_
128 {\if#2@\assignmentfalse\else\assignmenttrue\fi}
130 \def\mult_check_for_assignment#1%
131 {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_}
133 % End of experimental code.
135 % the commented detokenized variant that backtracks ... needs testing usage first
137 % \let\whatever\relax
139 % \definetest[oeps][bagger=\whatever]
141 % \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
142 % \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
144 \def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
146 \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)
147 {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
148 %\def#3##1{\csname#4{#1#2}{##1}\endcsname}%
149 \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
150 \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
151 \def#5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
152 \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}%
153 \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
154 % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
155 % \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}}%
156 \def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
157 \def#9##1{\csname#1#2:##1\endcsname}}
159 \unexpanded\def\installparameterhandler#1#2%
161 {\mult_interfaces_install_parameter_handler
163 \expandafter\noexpand\csname current#2\endcsname
164 \expandafter\noexpand\csname #2parameter\endcsname
165 \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter_hash
166 \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter_hash
167 \expandafter\noexpand\csname named#2parameter\endcsname
168 \expandafter\noexpand\csname detokenized#2parameter\endcsname
169 \expandafter\noexpand\csname strict#2parameter\endcsname % checked
170 \expandafter\noexpand\csname direct#2parameter\endcsname}} % unchecked
172 \unexpanded\def\mult_interfaces_install_root_parameter_handler#1#2#3%
173 {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
174 \def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}}
176 \unexpanded\def\installrootparameterhandler#1#2%
178 {\mult_interfaces_install_root_parameter_handler
180 \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
181 \expandafter\noexpand\csname root#2parameter\endcsname}}
183 \unexpanded\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9%
184 {\ifx#2\relax\let#2\empty\fi
185 \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
186 \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
187 \def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
190 \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}%
191 \unexpanded\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}}
193 \unexpanded\def\installparameterhashhandler#1#2%
194 {\expandafter\let\csname#2namespace\endcsname#1%
196 {\mult_interfaces_install_parameter_hash_handler
198 \expandafter\noexpand\csname current#2\endcsname
199 \expandafter\noexpand\csname #2parameterhash\endcsname
200 \expandafter\noexpand\csname do#2parameterhash\endcsname % or : #2_parameter_hash
201 \expandafter\noexpand\csname do#2parentparameterhash\endcsname % or : #2_parent_parameter_hash
202 \expandafter\noexpand\csname current#2hash\endcsname
203 \expandafter\noexpand\csname named#2hash\endcsname
204 \expandafter\noexpand\csname check#2parent\endcsname
205 \expandafter\noexpand\csname chaintocurrent#2\endcsname}}
207 % In \MKIV\ we can probably use the english variant for all other
210 % todo: inline the \do*value
212 \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
213 {\ifx#2\relax\let#2\empty\fi
214 \unexpanded\def#3{\dosetvalue {#1#2:}}% ##1 {##2} (braces are mandate)
215 \unexpanded\def#4{\dosetevalue{#1#2:}}% ##1 {##2} (braces are mandate)
216 \unexpanded\def#5{\doletvalue {#1#2:}}% ##1 ##2
217 \unexpanded\def#6{\doletvalue {#1#2:}\empty}}% ##1
219 \startinterface english
221 \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
222 {\ifx#2\relax\let#2\empty\fi
223 \unexpanded\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
224 \unexpanded\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
225 \unexpanded\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2
226 \unexpanded\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1
230 \unexpanded\def\installparametersethandler#1#2%
232 {\mult_interfaces_install_parameter_set_handler
234 \expandafter\noexpand\csname current#2\endcsname
235 \expandafter\noexpand\csname set#2parameter\endcsname
236 \expandafter\noexpand\csname setexpanded#2parameter\endcsname
237 \expandafter\noexpand\csname let#2parameter\endcsname
238 \expandafter\noexpand\csname reset#2parameter\endcsname}}
240 \let\dousecurrentstyleparameter\relax
241 \let\dousecurrentcolorparameter\relax
243 \let\currentstyleparameter\empty
244 \let\currentcolorparameter\empty
246 \unexpanded\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
247 {\unexpanded\def#2##1##2% style color
248 {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline)
249 \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi
250 \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch)
251 \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}%
252 \unexpanded\def#3##1% style
253 {\edef\currentstyleparameter{#1{##1}}% this name is public
254 \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}%
255 \unexpanded\def#4##1% color
256 {\edef\currentcolorparameter{#1{##1}}% this name is public
257 \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}
259 \unexpanded\def\installstyleandcolorhandler#1#2%
261 {\mult_interfaces_install_style_and_color_handler
262 \expandafter\noexpand\csname #2parameter\endcsname
263 \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
264 \expandafter\noexpand\csname use#2styleparameter\endcsname
265 \expandafter\noexpand\csname use#2colorparameter\endcsname}}
267 \let\definehandlerparent\empty
269 \def\mult_check_for_parent#1#2#3#4%
270 {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else
271 \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
272 \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
275 \unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
276 {\ifx#4\relax\let#4\empty\fi % see \defineregister
277 \unexpanded\def#2{\dotripleempty#5}%
280 \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
286 \mult_check_for_parent{#1}{#3}#4#8%
287 \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
288 \mult_interfaces_get_parameters{#1#4:}[##3]%
289 \else\ifsecondargument
291 \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_
294 \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
295 \mult_interfaces_get_parameters{#1#4:}[##2]%
298 \mult_check_for_parent{#1}{#3}#4#8%
299 \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
304 \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
309 \unexpanded\def\installdefinehandler#1#2#3%
311 {\mult_interfaces_install_define_handler
313 \expandafter\noexpand\csname define#2\endcsname
315 \expandafter\noexpand\csname current#2\endcsname
316 \expandafter\noexpand\csname define_#2\endcsname % semi-public
317 \expandafter\noexpand\csname everypreset#2\endcsname
318 \expandafter\noexpand\csname everydefine#2\endcsname
319 \expandafter\noexpand\csname current#2parent\endcsname
320 \expandafter\noexpand\csname saved_defined_#2\endcsname}}
322 \unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9%
323 {\ifx#3\relax\let#3\empty\fi
324 \unexpanded\def#2{\dodoubleempty#4}%
325 \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
328 \unexpanded\def#4[##1][##2]% maybe helper
331 \def#9####1% we will have a simple one as well
333 \mult_interfaces_get_parameters{#1#3:}[##2]%
335 \processcommalist[##1]#9%
338 \mult_interfaces_get_parameters{#1:}[##1]%
344 \unexpanded\def\installsetuphandler#1#2%
346 {\mult_interfaces_install_setup_handler
348 \expandafter\noexpand\csname setup#2\endcsname
349 \expandafter\noexpand\csname current#2\endcsname
350 \expandafter\noexpand\csname setup_#2\endcsname % semi-public
351 \expandafter\noexpand\csname everysetup#2\endcsname
352 \expandafter\noexpand\csname setupcurrent#2\endcsname
353 \expandafter\noexpand\csname saved_setup_current#2\endcsname
354 \expandafter\noexpand\csname everysetup#2root\endcsname
355 \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
357 \let\doingrootsetupnamed\plusone % \setuplayout[name][key=value]
358 \let\doingrootsetuproot \plustwo % \setuplayout [key=value]
359 \let\doingrootsetnamed \plusthree % \setuplayout[name]
360 \let\doingrootsetroot \plusfour % \setuplayout
362 \unexpanded\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5%
363 {\ifx#3\relax\let#3\empty\fi
364 \unexpanded\def#2{\dodoubleempty#4}%
365 \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}}
367 \unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
372 \ifx#6\relax\let#6\empty\fi
373 \unexpanded\def#4[##1][##2]% maybe helper
374 {\ifsecondargument % no commalist here
375 % \setuplayout[whatever][key=value]
379 #2\doingrootsetupnamed
380 \mult_interfaces_get_parameters{#1#3:}[##2]%
382 \ifx#3#6\the#8\fi % only switchsetups if previous == current
384 \else\iffirstargument
385 % \mult_check_for_assignment{##1}%
386 \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
388 % \setuplayout[key=value]
392 #2\doingrootsetuproot
393 \mult_interfaces_get_parameters{#1:}[##1]%
398 % \setuplayout[whatever]
399 \let#6#3% % previous becomes current
400 \edef#3{##1}% this will catch reset so one needs to test for it
402 \the#5% % we can check for previous vs current
407 \let#6#3% % previous becomes current
408 \let#3\empty % current becomes empty
413 #2\zerocount % mode is always zero at the end
416 \unexpanded\def\installswitchsetuphandler#1#2%
418 {\mult_interfaces_install_switch_setup_handler_a
420 \expandafter\noexpand\csname setup#2\endcsname
421 \expandafter\noexpand\csname current#2\endcsname
422 \expandafter\noexpand\csname setup_#2\endcsname % semi-public
423 \expandafter\noexpand\csname setupcurrent#2\endcsname
424 \mult_interfaces_install_switch_setup_handler_b
426 \expandafter\noexpand\csname #2setupmode\endcsname
427 \expandafter\noexpand\csname current#2\endcsname
428 \expandafter\noexpand\csname setup_#2\endcsname % semi-public
429 \expandafter\noexpand\csname everysetup#2\endcsname
430 \expandafter\noexpand\csname previous#2\endcsname
431 \expandafter\noexpand\csname saved_setup_current#2\endcsname
432 \expandafter\noexpand\csname everyswitch#2\endcsname
433 \expandafter\noexpand\csname everysetup#2root\endcsname}}
435 \unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9%
436 {\ifx#3\relax\let#3\empty\fi
437 \unexpanded\def#2{\dotripleempty#4}%
438 \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}%
440 \def#4[##1][##2][##3]%
445 \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
446 \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
448 \processcommalist[##1]#9%
449 \else\ifsecondargument
452 #7% checks parent and sets if needed
453 \mult_interfaces_get_parameters{#1#3:}[##2]%
455 \processcommalist[##1]#9%
458 \mult_interfaces_get_parameters{#1:}[##1]%
463 \unexpanded\def\installautosetuphandler#1#2%
465 {\mult_interfaces_install_auto_setup_handler
467 \expandafter\noexpand\csname setup#2\endcsname
468 \expandafter\noexpand\csname current#2\endcsname
469 \expandafter\noexpand\csname setup_#2\endcsname % semi-public
470 \expandafter\noexpand\csname everysetup#2\endcsname
471 \expandafter\noexpand\csname setupcurrent#2\endcsname
472 \expandafter\noexpand\csname check#2parent\endcsname
473 \expandafter\noexpand\csname saved_setup_current#2\endcsname
474 \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
476 \unexpanded\def\installbasicparameterhandler#1#2%
477 {\installparameterhandler {#1}{#2}%
478 \installparameterhashhandler{#1}{#2}%
479 \installparametersethandler {#1}{#2}%
480 \installrootparameterhandler{#1}{#2}}
482 \unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
483 {\installbasicparameterhandler{#1}{#2}%
484 \installautosetuphandler {#1}{#2}}
486 \unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
487 {\installbasicparameterhandler{#1}{#2}%
488 \installdefinehandler {#1}{#2}{#3}%
489 \installsetuphandler {#1}{#2}%
490 \installstyleandcolorhandler {#1}{#2}}
492 \unexpanded\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
493 {\installbasicparameterhandler{#1}{#2}%
494 \installdefinehandler {#1}{#2}{#3}%
495 \installswitchsetuphandler {#1}{#2}%
496 \installstyleandcolorhandler {#1}{#2}}
498 \unexpanded\def\installautocommandhandler#1#2#3% automatically defined cloned setups
499 {\installbasicparameterhandler{#1}{#2}%
500 \installdefinehandler {#1}{#2}{#3}%
501 \installautosetuphandler {#1}{#2}%
502 \installstyleandcolorhandler {#1}{#2}}
504 \unexpanded\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
505 {\installbasicparameterhandler{#1}{#2}%
506 \installsetuphandler {#1}{#2}%
507 \installstyleandcolorhandler {#1}{#2}}
509 %D Many mechanisms have some kind of inheritance in place, and these are
510 %D the speed||critical ones. Therefore there is no reason to stick to
511 %D \type {\@@xxkey} for the sake of performance. For this reason we also
512 %D provide a direct variant. This permits a more consistent treatment of
513 %D namespaces. A \type {\whateverparameter} call is three times slower
514 %D and a \type {\directwhateverparameter} call two times but for some
515 %D 100K expansions we only loose some .1 second which is neglectable
516 %D given the small amount of expansions in real runs.
518 %D We don't need colons for such simple cases.
520 \unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
521 {\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
522 \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
523 % \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}}%
524 \def#5##1{\csname#1##1\endcsname}}
526 \unexpanded\def\installdirectparameterhandler#1#2%
528 {\mult_interfaces_install_direct_parameter_handler
530 \expandafter\noexpand\csname current#2\endcsname
531 \expandafter\noexpand\csname #2parameter\endcsname
532 \expandafter\noexpand\csname detokenized#2parameter\endcsname
533 \expandafter\noexpand\csname direct#2parameter\endcsname}}
535 \unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
536 {\unexpanded\def#2{\dosingleempty#3}%
538 \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
539 \def#4{\mult_interfaces_get_parameters#1}}
541 \unexpanded\def\installdirectsetuphandler#1#2%
543 {\mult_interfaces_install_direct_setup_handler
545 \expandafter\noexpand\csname setup#2\endcsname
546 \expandafter\noexpand\csname setup_#2\endcsname % semi-public
547 \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
548 \expandafter\noexpand\csname everysetup#2\endcsname}}
550 \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
551 {\unexpanded\def#2{\dosetvalue #1}%
552 \unexpanded\def#3{\dosetevalue#1}%
553 \unexpanded\def#4{\doletvalue #1}%
554 \unexpanded\def#5{\doletvalue #1\empty}}%
556 \startinterface english
558 \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
559 {\unexpanded\def#2##1{\expandafter \def\csname#1##1\endcsname}%
560 \unexpanded\def#3##1{\expandafter\edef\csname#1##1\endcsname}%
561 \unexpanded\def#4##1{\expandafter \let\csname#1##1\endcsname}%
562 \unexpanded\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}%
566 \unexpanded\def\installdirectparametersethandler#1#2%
568 {\mult_interfaces_install_direct_parameter_set_handler
570 \expandafter\noexpand\csname set#2parameter\endcsname
571 \expandafter\noexpand\csname setexpanded#2parameter\endcsname
572 \expandafter\noexpand\csname let#2parameter\endcsname
573 \expandafter\noexpand\csname reset#2parameter\endcsname}}
575 \let\installdirectstyleandcolorhandler\installstyleandcolorhandler
577 \unexpanded\def\installdirectcommandhandler#1#2%
578 {\installdirectparameterhandler {#1}{#2}%
579 \installdirectsetuphandler {#1}{#2}%
580 \installdirectparametersethandler {#1}{#2}%
581 \installdirectstyleandcolorhandler{#1}{#2}}
583 \unexpanded\def\installsetuponlycommandhandler#1#2%
584 {\installdirectparameterhandler{#1}{#2}%
585 \installdirectsetuphandler {#1}{#2}%
586 }% maybe \installdirectparametersethandler {#1}{#2}%
590 % \installcorenamespace {one}
591 % \installcorenamespace {two}
593 % \installcommandhandler \??one {one} \??one
594 % \installcommandhandler \??two {two} \??two
596 % \defineone[test] \setupone[test][alpha=first]
597 % \definetwo[test] \setuptwo[test][beta=second]
601 % \def\currentone{test}
602 % \def\currenttwo{test}
604 % \relateparameterhandlers {two} {test} {one} {test}
606 % yes:\oneparameter{alpha}\par
607 % nop:\oneparameter{beta}\par
608 % yes:\twoparameter{alpha}\par
609 % yes:\twoparameter{beta}\par
611 \unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
612 {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}
614 %D Here is another experiment:
616 \unexpanded\def\installactionhandler#1%
618 {\mult_interfaces_install_action_handler
620 \expandafter\noexpand\csname current#1\endcsname
621 \expandafter\noexpand\csname setupcurrent#1\endcsname
622 \expandafter\noexpand\csname #1_action\endcsname}}
624 \unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4%
625 {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
626 \unexpanded\def#4[##1][##2]%
631 \else\iffirstargument
632 \doifassignmentelse{##1}
639 \directsetup{handler:action:#1}%
642 % First we had, in tune with the regular system variables:
645 % \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
648 % The following variant is nicer and in principle faster but that gets
649 % unnoticed unless lots of expansion happens. Also, we can use long tags
650 % but the internal expansion will be relatively small (and unlikely more
651 % than 4 characters). For instance, \??xx used to expand to @@xx but now
652 % becomes for instance 123::. This is one character more but in quite some
653 % cases we had : after such a tag in the old situation. In the new situation
654 % we create more namespaces and don't need that : any more, so we end up
655 % with on the average the same amount of tokens and definitely less when
656 % we consider cases like \??xx:\c!align: which now is just \??somealign and
657 % therefore has length 5 now (instead of 4+1+5+1=10).
659 % Eventualy we will have a verbose \blablanamespace and the difference between
660 % core and regular can go ... after all, \xxxparameter can already clash between
661 % the two prefix groups .. if users use this mechanism a lot they should use
662 % verbose names anyway (the old two character names were mostly an optimization
663 % as they also expanded to these characters).
665 % todo: register namespaces at lua end for logging and reverse resolve
666 % todo: move this to syst-ini so that we can use it real early
668 \newcount\c_mult_interfaces_n_of_namespaces
670 %def\v_interfaces_prefix_template{\number \c_mult_interfaces_n_of_namespaces>}
671 \def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>}
673 \def\v_interfaces_prefix_template % consistently %03i>
674 {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\else\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi\fi
675 \number\c_mult_interfaces_n_of_namespaces>}
677 \def\v_interfaces_prefix_template % consistently %03i>
678 {\number\c_mult_interfaces_n_of_namespaces>}
680 \unexpanded\def\installnamespace#1% for modules and users
681 {\ifcsname ????#1\endcsname
682 \writestatus\m!system{duplicate user namespace '#1'}\wait
684 \global\advance\c_mult_interfaces_n_of_namespaces\plusone
685 \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}%
688 \unexpanded\def\installcorenamespace#1%
689 {\ifcsname ??#1\endcsname
690 \writestatus\m!system{duplicate core namespace '#1'}\wait
692 \global\advance\c_mult_interfaces_n_of_namespaces\plusone
693 \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}%
694 \ctxcommand{registernamespace(\number\c_mult_interfaces_n_of_namespaces,"#1")}%
697 \def\mult_interfaces_get_parameters_error#1#2#3% redefined
698 {\ctxcommand{showassignerror("#1","#2","#3",\the\inputlineno)}%
701 % We install two core namespaces here, as we want nice error messages. Maybe
702 % we will reserve the first 9.
704 \installcorenamespace{fontinstanceready}
705 \installcorenamespace{fontinstancebasic}
706 \installcorenamespace{fontinstanceclass}
708 %D The next one is handy for local assignments.
710 \installcorenamespace{dummy}
712 \letvalue\??dummy\empty
714 \def\dummyparameter #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname}
715 \def\directdummyparameter#1{\csname\??dummy#1\endcsname}
716 \unexpanded\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname}
717 \unexpanded\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname}
719 % \unexpanded\def\getdummyparameters
720 % {\mult_interfaces_get_parameters\??dummy}
722 \unexpanded\def\getdummyparameters[#1%
724 \expandafter\gobbleoneargument
726 \let\m_mult_interfaces_namespace\??dummy
727 \expandafter\mult_interfaces_get_parameters_indeed
730 \mult_interfaces_install_style_and_color_handler
731 \directdummyparameter
732 \usedummystyleandcolor
733 \usedummystyleparameter
734 \usedummycolorparameter
736 % Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
737 % but we don't gain much. Actually we might just inline all definitions.
739 % \enabletrackers[interfaces.namespaces,context.flush]
744 % comment=test module,
763 % “\testparameter{text}”
765 % \setuptest[text=foo]
767 % “\testparameter{text}”
769 % \setuptest[one][text=bar]
771 % “\testparameter{text}”
775 % This is a user (module) command:
777 \unexpanded\def\definenamespace
778 {\dodoubleargument\mult_interfaces_define_name_space}
780 \def\mult_interfaces_define_name_space[#1][#2]% namespace settings
781 {\ctxlua{interfaces.namespaces.define(\!!bs#1\!!es,\!!bs#2\!!es)}}
784 {\ctxlua{interfaces.namespaces.list()}}
789 %D \showparentchain{@@am}{left}
792 \unexpanded\def\showparentchain#1#2%
793 {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}
795 \def\mult_interfaces_show_parent_chain#1%
797 \ifcsname#1:\s!parent\endcsname
798 \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
801 %D Another helper (needs to be applied):
803 \unexpanded\def\doifelsecommandhandler#1#2% namespace name
804 {\ifcsname#1#2:\s!parent\endcsname
805 \expandafter\firstoftwoarguments
807 \expandafter\secondoftwoarguments
810 \unexpanded\def\doifcommandhandler#1#2% namespace name
811 {\ifcsname#1#2:\s!parent\endcsname
812 \expandafter\firstofoneargument
814 \expandafter\gobbleoneargument
817 \unexpanded\def\doifnotcommandhandler#1#2% namespace name
818 {\ifcsname#1#2:\s!parent\endcsname
819 \expandafter\gobbleoneargument
821 \expandafter\firstofoneargument
824 \let\doifcommandhandlerelse\doifelsecommandhandler
826 % another set of (fast) helpers (grep for usage):
828 \def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \c!yy
829 {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}
831 \def\mult_aux_expand_namespace_parameter#1#2% \cs \c!yy
832 {#1\endcsname#1\else#2\fi\endcsname}
834 \def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
835 {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
837 \def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
838 {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}}
840 \def\syst_helpers_expand_checked_value#1#2%
841 {#1\endcsname#1\else#2\fi\endcsname}
846 %D \newcount \c_class_whatever
847 %D \newconditional \c_class_whatever
848 %D \newconstant \c_class_whatever
849 %D \newdimen \d_class_whatever
850 %D \newskip \s_class_whatever
851 %D \newmuskip \s_class_whatever
852 %D \newbox \b_class_whatever
853 %D \newtoks \t_class_whatever
855 %D \edef\p_class_whatever{\classparameter\c!whatever}
856 %D \edef\m_class_whatever{whatever}