beta 2014.02.14 17:07
[context.git] / tex / context / base / mult-aux.mkiv
1 %D \module
2 %D   [       file=mult-aux,
3 %D        version=2010.08.2,
4 %D          title=\CONTEXT\ Multilingual Macros,
5 %D       subtitle=Helpers,
6 %D         author=Hans Hagen,
7 %D           date=\currentdate,
8 %D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9 %C
10 %C This module is part of the \CONTEXT\ macro||package and is
11 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12 %C details.
13
14 % todo: setupxxx and setupxxxs (so a plural for the root setup and
15 % we can consider blocking the root)
16
17 % todo (e.g for columnsets and registers): \definexxx[parent][1]
18 %
19
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.
23
24 % todo: doifelse<whatever>
25
26 \writestatus{loading}{ConTeXt Multilingual Macros / Helpers}
27
28 \registerctxluafile{mult-aux}{1.001}
29
30 \unprotect
31
32 %D \starttyping
33 %D \unprotect
34 %D     \def\????aa{@@@@aa}
35 %D
36 %D     \installparameterhandler   \????aa {whatever}
37 %D     \installsetuphandler       \????aa {whatever}
38 %D     \installdefinehandler      \????aa {whatever} \????aa % #3 == defaultroot
39 %D     \installfontandcolorhandler\????aa {whatever}
40 %D
41 %D   % \installcommandhandler     \????aa {whatever} \????aa
42 %D \protect
43 %D
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)
51 %D
52 %D \starttext
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
59 %D \stoptext
60 %D \stoptyping
61
62 % problem: every* could clash
63 %
64 % There can be less {} in the following definitions if we assume \??aa and \c!somecs
65 %
66 % todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root
67 %
68 % it might be more efficient to do this at the lua and
69 %
70 % watch the push/pop and predefinition of current .. this is needed for nested
71 % definitions and overloaded defines using the predefined one
72
73 % todo: add (relaxed) postsetup and postdefine hooks, just after the everys
74
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.
84 %
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
88
89 \let\m_mult_interfaces_namespace\empty
90
91 \def\mult_interfaces_get_parameters#1[#2%
92   {\if\noexpand#2]%
93      \expandafter\gobbleoneargument
94    \else
95      \def\m_mult_interfaces_namespace{#1}%
96      \expandafter\mult_interfaces_get_parameters_indeed
97    \fi#2}
98
99 \def\mult_interfaces_get_parameters_indeed#1]% namespace already set
100   {\mult_interfaces_get_parameters_item#1,],\_e_o_p_}
101
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
105    \else\if]#1%
106      \doubleexpandafter\gobbleoneargument
107    \else
108      \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_
109      \doubleexpandafter\mult_interfaces_get_parameters_item
110    \fi\fi#2}
111
112 \def\mult_interfaces_get_parameters_error#1#2#3%
113   {\showassignerror{#2}{\the\inputlineno\space(#1)}}
114
115 \def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
116   {\ifx\empty#1\empty
117      \expandafter\mult_interfaces_get_parameters_error
118    \else\ifx#3\empty
119      \doubleexpandafter\mult_interfaces_get_parameters_error
120    \else
121      \doubleexpandafter\dosetvalue
122    \fi\fi
123    \m_mult_interfaces_namespace{#1}{#2}}
124
125 \newif\ifassignment
126
127 \def\mult_check_for_assignment_indeed#1=#2#3\_end_
128   {\if#2@\assignmentfalse\else\assignmenttrue\fi}
129
130 \def\mult_check_for_assignment#1%
131   {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_}
132
133 % End of experimental code.
134
135 % the commented detokenized variant that backtracks ... needs testing usage first
136 %
137 % \let\whatever\relax
138 %
139 % \definetest[oeps][bagger=\whatever]
140 %
141 % \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
142 % \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
143
144 \def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
145
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}}
158
159 \unexpanded\def\installparameterhandler#1#2%
160   {\normalexpanded
161      {\mult_interfaces_install_parameter_handler
162         {\noexpand#1}% \??aa
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
171
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}}
175
176 \unexpanded\def\installrootparameterhandler#1#2%
177   {\normalexpanded
178      {\mult_interfaces_install_root_parameter_handler
179         {\noexpand#1}% \??aa
180         \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
181         \expandafter\noexpand\csname root#2parameter\endcsname}}
182
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}%
188    \def#6{#1#2:}%
189    \def#7##1{#1##1:}%
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}}}
192
193 \unexpanded\def\installparameterhashhandler#1#2%
194   {\expandafter\let\csname#2namespace\endcsname#1%
195    \normalexpanded
196      {\mult_interfaces_install_parameter_hash_handler
197         {\noexpand#1}% \??aa
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}}
206
207 % In \MKIV\ we can probably use the english variant for all other
208 % languages too.
209
210 % todo: inline the \do*value
211
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
218
219 \startinterface english
220
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
227
228 \stopinterface
229
230 \unexpanded\def\installparametersethandler#1#2%
231   {\normalexpanded
232      {\mult_interfaces_install_parameter_set_handler
233         {\noexpand#1}% \??aa
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}}
239
240 \let\dousecurrentstyleparameter\relax
241 \let\dousecurrentcolorparameter\relax
242
243 \let\currentstyleparameter\empty
244 \let\currentcolorparameter\empty
245
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}}
258
259 \unexpanded\def\installstyleandcolorhandler#1#2%
260   {\normalexpanded
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}}
266
267 \let\definehandlerparent\empty
268
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}%
273    \fi \fi}
274
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}%
278    \newtoks#6%
279    \newtoks#7%
280    \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
281      {\let#9#4%
282       \edef#4{##1}%
283       \ifthirdargument
284         \the#6% predefine
285         \edef#8{##2}%
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
290         \the#6% predefine
291         \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_
292         \ifassignment
293           \let#8\empty
294           \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
295           \mult_interfaces_get_parameters{#1#4:}[##2]%
296         \else
297           \edef#8{##2}%
298           \mult_check_for_parent{#1}{#3}#4#8%
299           \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
300         \fi
301       \else
302         \the#6% predefine
303         \let#8\empty
304         \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
305       \fi\fi
306       \the#7%
307       \let#4#9}}
308
309 \unexpanded\def\installdefinehandler#1#2#3%
310   {\normalexpanded
311      {\mult_interfaces_install_define_handler
312         {\noexpand#1}% \??aa
313         \expandafter\noexpand\csname define#2\endcsname
314         {\noexpand#3}% root
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}}
321
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
326    \newtoks#5%
327    \newtoks#8%
328    \unexpanded\def#4[##1][##2]% maybe helper
329      {\let#7#3%
330       \ifsecondargument
331         \def#9####1% we will have a simple one as well
332           {\edef#3{####1}%
333            \mult_interfaces_get_parameters{#1#3:}[##2]%
334            \the#5}%
335         \processcommalist[##1]#9%
336       \else
337         \let#3\empty
338         \mult_interfaces_get_parameters{#1:}[##1]%
339         \the#5%
340       \fi
341       \let#3#7%
342       \the#8}}
343
344 \unexpanded\def\installsetuphandler#1#2%
345   {\normalexpanded
346      {\mult_interfaces_install_setup_handler
347         {\noexpand#1}% \??aa
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}}
356
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
361
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:}}}
366
367 \unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
368   {\newtoks#5%
369    \newconstant#2%
370    \newtoks#8%
371    \newtoks#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]
376         \let#7#3%
377         \let#6#3%
378         \edef#3{##1}%
379         #2\doingrootsetupnamed
380         \mult_interfaces_get_parameters{#1#3:}[##2]%
381         \the#5%
382         \ifx#3#6\the#8\fi % only switchsetups if previous == current
383         \let#3#7%
384       \else\iffirstargument
385         % \mult_check_for_assignment{##1}%
386           \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
387         \ifassignment
388           % \setuplayout[key=value]
389           \let#7#3%
390           \let#6#3%
391           \let#3\empty
392           #2\doingrootsetuproot
393           \mult_interfaces_get_parameters{#1:}[##1]%
394           \the#5%
395           \the#8% switchsetups
396           \let#3#7%
397         \else
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
401           #2\doingrootsetnamed
402           \the#5%     % we can check for previous vs current
403           \the#8% switchsetups
404         \fi
405       \else
406         % \setuplayout
407         \let#6#3%      % previous becomes current
408         \let#3\empty   % current becomes empty
409         #2\doingrootsetroot
410         \the#5%
411         \the#8% switchsetups
412       \fi\fi
413       #2\zerocount % mode is always zero at the end
414       \the#9}}
415
416 \unexpanded\def\installswitchsetuphandler#1#2%
417   {\normalexpanded
418      {\mult_interfaces_install_switch_setup_handler_a
419         {\noexpand#1}% \??aa
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
425         {\noexpand#1}% \??aa
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}}
434
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:}}%
439    \newtoks#5%
440    \def#4[##1][##2][##3]%
441      {\let#8#3%
442       \ifthirdargument
443         \def#9####1%
444           {\edef#3{####1}%
445            \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
446            \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
447            \the#5}%
448         \processcommalist[##1]#9%
449       \else\ifsecondargument
450         \def#9####1%
451           {\edef#3{####1}%
452            #7% checks parent and sets if needed
453            \mult_interfaces_get_parameters{#1#3:}[##2]%
454            \the#5}%
455         \processcommalist[##1]#9%
456       \else
457         \let#3\empty
458         \mult_interfaces_get_parameters{#1:}[##1]%
459         \the#5%
460       \fi\fi
461       \let#3#8}}
462
463 \unexpanded\def\installautosetuphandler#1#2%
464   {\normalexpanded
465      {\mult_interfaces_install_auto_setup_handler
466         {\noexpand#1}% \??aa
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}}
475
476 \unexpanded\def\installbasicparameterhandler#1#2%
477   {\installparameterhandler    {#1}{#2}%
478    \installparameterhashhandler{#1}{#2}%
479    \installparametersethandler {#1}{#2}%
480    \installrootparameterhandler{#1}{#2}}
481
482 \unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
483   {\installbasicparameterhandler{#1}{#2}%
484    \installautosetuphandler     {#1}{#2}}
485
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}}
491
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}}
497
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}}
503
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}}
508
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.
517
518 %D We don't need colons for such simple cases.
519
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}}
525
526 \unexpanded\def\installdirectparameterhandler#1#2%
527   {\normalexpanded
528      {\mult_interfaces_install_direct_parameter_handler
529         {\noexpand#1}%
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}}
534
535 \unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
536   {\unexpanded\def#2{\dosingleempty#3}%
537    \newtoks#5%
538    \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
539    \def#4{\mult_interfaces_get_parameters#1}}
540
541 \unexpanded\def\installdirectsetuphandler#1#2%
542   {\normalexpanded
543      {\mult_interfaces_install_direct_setup_handler
544         {\noexpand#1}% \??aa
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}}
549
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}}%
555
556 \startinterface english
557
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}}%
563
564 \stopinterface
565
566 \unexpanded\def\installdirectparametersethandler#1#2%
567   {\normalexpanded
568      {\mult_interfaces_install_direct_parameter_set_handler
569         {\noexpand#1}% \??aa
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}}
574
575 \let\installdirectstyleandcolorhandler\installstyleandcolorhandler
576
577 \unexpanded\def\installdirectcommandhandler#1#2%
578   {\installdirectparameterhandler    {#1}{#2}%
579    \installdirectsetuphandler        {#1}{#2}%
580    \installdirectparametersethandler {#1}{#2}%
581    \installdirectstyleandcolorhandler{#1}{#2}}
582
583 \unexpanded\def\installsetuponlycommandhandler#1#2%
584   {\installdirectparameterhandler{#1}{#2}%
585    \installdirectsetuphandler    {#1}{#2}%
586   }% maybe \installdirectparametersethandler {#1}{#2}%
587
588 % Experiment:
589
590 % \installcorenamespace {one}
591 % \installcorenamespace {two}
592 %
593 % \installcommandhandler \??one {one} \??one
594 % \installcommandhandler \??two {two} \??two
595 %
596 % \defineone[test] \setupone[test][alpha=first]
597 % \definetwo[test] \setuptwo[test][beta=second]
598 %
599 % \protect
600 %
601 % \def\currentone{test}
602 % \def\currenttwo{test}
603 %
604 % \relateparameterhandlers {two} {test} {one} {test}
605 %
606 % yes:\oneparameter{alpha}\par
607 % nop:\oneparameter{beta}\par
608 % yes:\twoparameter{alpha}\par
609 % yes:\twoparameter{beta}\par
610
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}}
613
614 %D Here is another experiment:
615
616 \unexpanded\def\installactionhandler#1%
617   {\normalexpanded
618      {\mult_interfaces_install_action_handler
619         {#1}%
620         \expandafter\noexpand\csname current#1\endcsname
621         \expandafter\noexpand\csname setupcurrent#1\endcsname
622         \expandafter\noexpand\csname #1_action\endcsname}}
623
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]%
627      {\begingroup
628       \ifsecondargument
629         \edef#2{##1}%
630         #3[##2]%
631       \else\iffirstargument
632         \doifassignmentelse{##1}
633           {\let#2\empty
634            #3[##1]}%
635           {\edef#2{##1}}%
636       \else
637         \let#2\empty
638       \fi\fi
639       \directsetup{handler:action:#1}%
640       \endgroup}}
641
642 % First we had, in tune with the regular system variables:
643 %
644 % \starttyping
645 % \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
646 % \stoptyping
647 %
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).
658 %
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).
664
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
667
668 \newcount\c_mult_interfaces_n_of_namespaces
669
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>}
672
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>}
676
677 \def\v_interfaces_prefix_template % consistently %03i>
678   {\number\c_mult_interfaces_n_of_namespaces>}
679
680 \unexpanded\def\installnamespace#1% for modules and users
681   {\ifcsname ????#1\endcsname
682      \writestatus\m!system{duplicate user namespace '#1'}\wait
683    \else
684      \global\advance\c_mult_interfaces_n_of_namespaces\plusone
685      \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}%
686    \fi}
687
688 \unexpanded\def\installcorenamespace#1%
689   {\ifcsname ??#1\endcsname
690      \writestatus\m!system{duplicate core namespace '#1'}\wait
691    \else
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")}%
695    \fi}
696
697 \def\mult_interfaces_get_parameters_error#1#2#3% redefined
698   {\ctxcommand{showassignerror("#1","#2","#3",\the\inputlineno)}%
699    \waitonfatalerror}
700
701 % We install two core namespaces here, as we want nice error messages. Maybe
702 % we will reserve the first 9.
703
704 \installcorenamespace{fontinstanceready}
705 \installcorenamespace{fontinstancebasic}
706 \installcorenamespace{fontinstanceclass}
707
708 %D The next one is handy for local assignments.
709
710 \installcorenamespace{dummy}
711
712 \letvalue\??dummy\empty
713
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}
718
719 % \unexpanded\def\getdummyparameters
720 %   {\mult_interfaces_get_parameters\??dummy}
721
722 \unexpanded\def\getdummyparameters[#1%
723   {\if\noexpand#1]%
724      \expandafter\gobbleoneargument
725    \else
726      \let\m_mult_interfaces_namespace\??dummy
727      \expandafter\mult_interfaces_get_parameters_indeed
728    \fi#1}
729
730 \mult_interfaces_install_style_and_color_handler
731   \directdummyparameter
732   \usedummystyleandcolor
733   \usedummystyleparameter
734   \usedummycolorparameter
735
736 % Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
737 % but we don't gain much. Actually we might just inline all definitions.
738
739 % \enabletrackers[interfaces.namespaces,context.flush]
740 %
741 % \definenamespace
742 %   [xy]
743 %   [type=module,
744 %    comment=test module,
745 %    version=1,
746 %    name=test,
747 %    style=yes,
748 %    command=yes,
749 %    setup=list,
750 %    set=yes,
751 %    parent=xy]
752 %
753 % \unprotect
754 % \getparameters
755 %   [\????xy]
756 %   [text=]
757 % \protect
758 %
759 % \definetest[one]
760 %
761 % \starttext
762 %
763 %   “\testparameter{text}”
764 %
765 %   \setuptest[text=foo]
766 %
767 %   “\testparameter{text}”
768 %
769 %   \setuptest[one][text=bar]
770 %
771 %   “\testparameter{text}”
772 %
773 % \stoptext
774 %
775 % This is a user (module) command:
776
777 \unexpanded\def\definenamespace
778   {\dodoubleargument\mult_interfaces_define_name_space}
779
780 \def\mult_interfaces_define_name_space[#1][#2]% namespace settings
781   {\ctxlua{interfaces.namespaces.define(\!!bs#1\!!es,\!!bs#2\!!es)}}
782
783 \def\listnamespaces
784   {\ctxlua{interfaces.namespaces.list()}}
785
786 %D Helper:
787 %D
788 %D \starttyping
789 %D \showparentchain{@@am}{left}
790 %D \stoptyping
791
792 \unexpanded\def\showparentchain#1#2%
793   {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}
794
795 \def\mult_interfaces_show_parent_chain#1%
796   {#1 => %
797    \ifcsname#1:\s!parent\endcsname
798       \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
799    \fi}
800
801 %D Another helper (needs to be applied):
802
803 \unexpanded\def\doifelsecommandhandler#1#2% namespace name
804   {\ifcsname#1#2:\s!parent\endcsname
805      \expandafter\firstoftwoarguments
806    \else
807      \expandafter\secondoftwoarguments
808    \fi}
809
810 \unexpanded\def\doifcommandhandler#1#2% namespace name
811   {\ifcsname#1#2:\s!parent\endcsname
812      \expandafter\firstofoneargument
813    \else
814      \expandafter\gobbleoneargument
815    \fi}
816
817 \unexpanded\def\doifnotcommandhandler#1#2% namespace name
818   {\ifcsname#1#2:\s!parent\endcsname
819      \expandafter\gobbleoneargument
820    \else
821      \expandafter\firstofoneargument
822    \fi}
823
824 \let\doifcommandhandlerelse\doifelsecommandhandler
825
826 % another set of (fast) helpers (grep for usage):
827
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}
830
831 \def\mult_aux_expand_namespace_parameter#1#2% \cs \c!yy
832   {#1\endcsname#1\else#2\fi\endcsname}
833
834 \def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
835   {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
836
837 \def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
838   {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}}
839
840 \def\syst_helpers_expand_checked_value#1#2%
841   {#1\endcsname#1\else#2\fi\endcsname}
842
843 %D Conventions:
844 %D
845 %D \starttyping
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
854 %D
855 %D \edef\p_class_whatever{\classparameter\c!whatever}
856 %D \edef\m_class_whatever{whatever}
857 %D \stoptyping
858
859 \protect