phys-dim.mkiv /size: 28 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=phys-dim,
3%D        version=2011-06-13, % was digits and units 1997.03.19,
4%D          title=\CONTEXT\ Physics,
5%D       subtitle=Digits and Units,
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\registerctxluafile{phys-dim}{}
15
16% TAGGING NEEDS CHECKING ... WILL DO WHEN PARSER IS OK
17
18\unprotect
19
20%D \macros
21%D   {digits, setdigitmode, setdigitsign}
22%D
23%D This is an update of the \MKII\ digits mechanism. Beware,
24%D space delimited mode is now resticted!
25%D
26%D Depending on the digit mode the command \type {\digits}
27%D normalizes number patterns depending on the language set.
28%D
29%D \starttyping
30%D This will never be a \digits{1.000.000} seller.
31%D \stoptyping
32%D
33%D We still support the space delimited case but this is only for special
34%D purposes. When used in the text, you'd better use the argument variant.
35%D
36%D \startbuffer
37%D 1 \setdigitmode {1} \setdigitorder{0} \digits {12.345,90}
38%D 2 \setdigitmode {2} \setdigitorder{0} \digits {12.345,90}
39%D 3 \setdigitmode {3} \setdigitorder{0} \digits {12.345,90}
40%D 4 \setdigitmode {4} \setdigitorder{0} \digits {12.345,90}
41%D 5 \setdigitmode {5} \setdigitorder{0} \digits {12.345,90}
42%D 6 \setdigitmode {6} \setdigitorder{0} \digits {12.345,90}
43%D 1 \setdigitmode {1} \setdigitorder{1} \digits {12.345,90}
44%D 2 \setdigitmode {2} \setdigitorder{1} \digits {12.345,90}
45%D 3 \setdigitmode {3} \setdigitorder{1} \digits {12.345,90}
46%D 4 \setdigitmode {4} \setdigitorder{1} \digits {12.345,90}
47%D 5 \setdigitmode {5} \setdigitorder{1} \digits {12.345,90}
48%D 6 \setdigitmode {6} \setdigitorder{1} \digits {12.345,90}
49%D \stopbuffer
50%D
51%D \typebuffer
52%D
53%D This is typeset as:
54%D
55%D \startlines \getbuffer \stoplines
56%D
57%D The sign can be typeset as is or within the space of a
58%D digit.
59%D
60%D \startbuffer
61%D \setdigitsign 0 \digits {+12.345,90}
62%D \setdigitsign 1 \digits {+12.345,90}
63%D \stopbuffer
64%D
65%D \typebuffer
66%D
67%D This is typset as:
68%D
69%D \startlines
70%D \getbuffer
71%D \stoplines
72%D
73%D The digit modes are:
74%D
75%D \startitemize[n,packed]
76%D \item periods/comma
77%D \item commas/period
78%D \item thinmuskips/comma
79%D \item thinmuskips/period
80%D \item thickmuskips/comma
81%D \item thickmuskips/period
82%D \stopitemize
83%D
84%D The digit parser handles a bunch of special characters as
85%D well as different formats. We strongly suggest you to use
86%D the grouped call.
87%D
88%D \starttabulate[|l|l|l|]
89%D \NC \type{.}  \NC , .           \NC comma or period     \NC \NR
90%D \NC \type{,}  \NC , .           \NC comma or period     \NC \NR
91%D \NC \type{:}  \NC               \NC invisible period    \NC \NR
92%D \NC \type{;}  \NC               \NC invisible comma     \NC \NR
93%D \NC \type{_}  \NC               \NC invisible space     \NC \NR
94%D \NC \type{/}  \NC               \NC invisible sign      \NC \NR
95%D \NC \type{-}  \NC $-$           \NC minus sign          \NC \NR
96%D \NC \type{+}  \NC $+$           \NC plus sign           \NC \NR
97%D \NC \type{//} \NC               \NC invisible high sign \NC \NR
98%D \NC \type{--} \NC $\negative$   \NC high minus sign     \NC \NR
99%D \NC \type{++} \NC $\positive$   \NC high plus sign      \NC \NR
100%D \NC \type{=}  \NC $\zeroamount$ \NC zero padding        \NC \NR
101%D \stoptabulate
102%D
103%D These triggers are used in the following examples.
104%D
105%D \starttabulate[|l|r|]
106%D \NC \type{1}                      \NC \ruledhbox{\strut\digits{1}}                      \NC \NR
107%D \NC \type{12}                     \NC \ruledhbox{\strut\digits{12}}                     \NC \NR
108%D \NC \type{12.34}                  \NC \ruledhbox{\strut\digits{12.34}}                  \NC \NR
109%D \NC \type{123,456}                \NC \ruledhbox{\strut\digits{123,456}}                \NC \NR
110%D \NC \type{123,456.78}             \NC \ruledhbox{\strut\digits{123,456.78}}             \NC \NR
111%D \NC \type{12,34}                  \NC \ruledhbox{\strut\digits{12,34}}                  \NC \NR
112%D \NC \type{.1234}                  \NC \ruledhbox{\strut\digits{.1234}}                  \NC \NR
113%D \NC \type{1234}                   \NC \ruledhbox{\strut\digits{1234}}                   \NC \NR
114%D \NC \type{123,456.78^9}           \NC \ruledhbox{\strut\digits{123,456.78^9}}           \NC \NR
115%D \NC \type{123,456.78e9}           \NC \ruledhbox{\strut\digits{123,456.78e9}}           \NC \NR
116%D \NC \type{/123,456.78e-9}         \NC \ruledhbox{\strut\digits{/123,456.78e-9}}         \NC \NR
117%D \NC \type{-123,456.78e-9}         \NC \ruledhbox{\strut\digits{-123,456.78e-9}}         \NC \NR
118%D \NC \type{+123,456.78e-9}         \NC \ruledhbox{\strut\digits{+123,456.78e-9}}         \NC \NR
119%D \NC \type{//123,456.78e-9}        \NC \ruledhbox{\strut\digits{//123,456.78e-9}}        \NC \NR
120%D \NC \type{--123,456.78e-9}        \NC \ruledhbox{\strut\digits{--123,456.78e-9}}        \NC \NR
121%D \NC \type{++123,456.78e-9}        \NC \ruledhbox{\strut\digits{++123,456.78e-9}}        \NC \NR
122%D \NC \type{___,___,123,456,789.00} \NC \ruledhbox{\strut\digits{___,___,123,456,789.00}} \NC \NR
123%D \NC \type{___,___,_12,345,678.==} \NC \ruledhbox{\strut\digits{___,___,_12,345,678.==}} \NC \NR
124%D \stoptabulate
125
126\newconstant\c_phys_digits_order
127\newconstant\c_phys_digits_method
128\newconstant\c_phys_digits_sign  % we has sized (text script scriptscript)
129
130\unexpanded\def\setdigitmethod#1{\c_phys_digits_method #1\relax}
131\unexpanded\def\setdigitsign  #1{\c_phys_digits_sign   #1\relax}
132\unexpanded\def\setdigitorder #1{\c_phys_digits_order  #1\relax}
133
134\let\setdigitmode\setdigitmethod % compatibility
135
136\def\phys_digits_normalized % we could calculate once and remember
137  {\ifcase\c_phys_digits_sign
138     \expandafter\secondoftwoarguments
139   \else\ifmmode
140     \expandafter\expandafter\expandafter\phys_digits_normalized_math
141   \else
142     \expandafter\expandafter\expandafter\phys_digits_normalized_text
143   \fi\fi}
144
145\def\phys_digits_normalized_math#1#2%
146  {\setbox\scratchbox\hbox{\normalstartimath\Ustack{#1}\normalstopimath}%
147   \hbox to \wd\scratchbox{\hss{\normalstartimath\Ustack{#2}\normalstopimath}\hss}}
148
149\def\phys_digits_normalized_text#1#2%
150  {\setbox\scratchbox\hbox{#1}%
151   \hbox to \wd\scratchbox{\hss#2\hss}}
152
153\def\phys_digits_raised
154  {\ifmmode
155     \expandafter\normalsuperscript
156   \else
157     \expandafter\unitshigh
158   \fi}
159
160% we could use a symbolset but how many symbols are there ?
161
162% \definesymbol[units][times][\times]
163% \definesymbol[units][times][\cdots]
164
165% \def\digitstimessymbol{\symbol[units][times]}
166
167% \definesymbol[units][times][\times]
168% \definesymbol[units][times][\cdots]
169% \definesymbol[units][times][\invisibletimes]
170% \definesymbol[units][times][\ifmmode\cdot\else\kern.2\emwidth\cdot\kern.2\emwidth\fi]
171
172\unexpanded\def\digitstextbinop#1% assumes preceding
173  {\ifmmode\mathord{#1}\else\nobreak#1\fi}
174
175\def\digitstimessymbol{\digitstextbinop\times}
176
177\unexpanded\def\digitszeropadding   {\hphantom{0}}
178\unexpanded\def\digitsnegative      {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}}
179\unexpanded\def\digitspositive      {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}}
180\unexpanded\def\digitsnegative      {\phys_digits_normalized{0}{\mathematics{\negative}}}
181\unexpanded\def\digitspositive      {\phys_digits_normalized{0}{\mathematics{\positive}}}
182%unexpanded\def\digitsminus         {\phys_digits_normalized{0}{\mathematics{-}}}
183%unexpanded\def\digitsplus          {\phys_digits_normalized{0}{\mathematics{+}}}
184\unexpanded\def\digitsminus         {\phys_digits_normalized{0}{\mathminus}}
185\unexpanded\def\digitsplus          {\phys_digits_normalized{0}{\mathplus}}
186\unexpanded\def\digitsplusminus     {\phys_digits_normalized{0}{\mathplusminus}}
187\unexpanded\def\digitsspace         {\hphantom{0}}
188\unexpanded\def\digitsseparatorspace{\hphantom{.}}
189\unexpanded\def\digitssignspace     {\hphantom{\digitsminus}}
190\unexpanded\def\digitshighspace     {\hphantom{\digitspositive}}
191\unexpanded\def\digitspower       #1{\digitstimessymbol10\phys_digits_raised{#1}}
192\unexpanded\def\digitspowerplus   #1{\digitstimessymbol10\phys_digits_raised{\digitsplus#1}}
193\unexpanded\def\digitspowerminus  #1{\digitstimessymbol10\phys_digits_raised{\digitsminus#1}}
194\unexpanded\def\digitsdigit       #1{#1}
195
196\unexpanded\def\normaldigitscommasymbol {,}
197\unexpanded\def\normaldigitsperiodsymbol{.}
198
199\let\normaldigitsseparatorspace\digitsseparatorspace
200
201\installcorenamespace{digitscomma}
202\installcorenamespace{digitsperiod}
203\installcorenamespace{digitsspace}
204
205\letvalue{\??digitscomma 0}\normaldigitscommasymbol
206\letvalue{\??digitsperiod0}\normaldigitsperiodsymbol
207\letvalue{\??digitsspace 0}\normaldigitsseparatorspace
208
209\letvalue{\??digitscomma 1}\normaldigitsperiodsymbol
210\letvalue{\??digitsperiod1}\normaldigitscommasymbol
211\letvalue{\??digitsspace 1}\normaldigitsseparatorspace
212
213\letvalue{\??digitscomma 2}\normaldigitscommasymbol
214\letvalue{\??digitsperiod2}\normaldigitsperiodsymbol
215\letvalue{\??digitsspace 2}\normaldigitsseparatorspace
216
217\letvalue{\??digitscomma 3}\thinspace
218\letvalue{\??digitsperiod3}\normaldigitscommasymbol
219\letvalue{\??digitsspace 3}\thinspace
220
221\letvalue{\??digitscomma 4}\thinspace
222\letvalue{\??digitsperiod4}\normaldigitsperiodsymbol
223\letvalue{\??digitsspace 4}\thinspace
224
225\letvalue{\??digitscomma 5}\thickspace
226\letvalue{\??digitsperiod5}\normaldigitscommasymbol
227\letvalue{\??digitsspace 5}\thickspace
228
229\letvalue{\??digitscomma 6}\thickspace
230\letvalue{\??digitsperiod6}\normaldigitsperiodsymbol
231\letvalue{\??digitsspace 6}\thickspace
232
233\unexpanded\def\digitscommasymbol         {\csname\??digitscomma \number\c_phys_digits_method\endcsname}
234\unexpanded\def\digitsperiodsymbol        {\csname\??digitsperiod\number\c_phys_digits_method\endcsname}
235\unexpanded\def\digitsseparatorspace      {\csname\??digitsspace \number\c_phys_digits_method\endcsname}
236
237% \unexpanded\def\digitsfinalcomma          {\digitscommasymbol } % more for tracing
238% \unexpanded\def\digitsfinalperiod         {\digitsperiodsymbol} % more for tracing
239% \unexpanded\def\digitsintermediatecomma   {\digitscommasymbol } % more for tracing
240% \unexpanded\def\digitsintermediateperiod  {\digitsperiodsymbol} % more for tracing
241
242\unexpanded\def\digitsfinalcomma          {\digitsperiodsymbol} % more for tracing
243\unexpanded\def\digitsfinalperiod         {\digitsperiodsymbol} % more for tracing
244\unexpanded\def\digitsintermediatecomma   {\digitscommasymbol } % more for tracing
245\unexpanded\def\digitsintermediateperiod  {\digitscommasymbol } % more for tracing
246
247%D The user macro:
248
249\unexpanded\def\phys_digits_indeed#1%
250  {\dontleavehmode
251   \begingroup
252   \ifcase\c_phys_digits_order\expandafter\clf_digits_normal\else\expandafter\clf_digits_reverse\fi{\detokenize{#1}}%
253   \endgroup
254   \settrue\c_phys_units_dospace}
255
256\unexpanded\def\digits
257  {\doifelsenextbgroup\phys_digits_argument\phys_digits_spaced}
258
259\def\phys_digits_argument#1%
260  {\phys_digits_indeed{#1}}
261
262\def\phys_digits_spaced#1 % space delimited
263  {\phys_digits_indeed{#1}}
264
265%D \macros
266%D   {unit}
267%D
268%D We have been using the units module (and its predecessor) for over a decade
269%D now but when we moved on to \LUATEX\ a variant was prototyped that permits a
270%D less texie coding. I finally picked up that thread and cleaned up the code a
271%D bit so users can now play with it. (The main reason was that I wanted to
272%D test exporting.)
273%D
274%D \startbuffer
275%D 01: $10\unit{km/h}$
276%D 02: $\unit{10      km/h}$
277%D 03: \unit{km/h}
278%D 04: \unit{10 km/h}
279%D 05: \unit{10 km/h}
280%D 06: \unit{~1 km/h}
281%D 07: 10\unit{km/h}
282%D 08: 10 \unit{km/h}
283%D 09: $10 \unit{km/h}$
284%D 10: 10 \unit{KiloMeter/Hour}
285%D 11: 10 \unit{kilometer/hour}
286%D 12: 10 \unit{km/h}
287%D 13: 10 \unit{kilometer per hour}
288%D 14: 10 \unit{km / h}
289%D 15: 10 \unit{ km / h }
290%D 16: 10 \unit{km/ms2}
291%D 17: 10 \unit{meter per second}
292%D 18: 10 \unit{cubic meter}
293%D 19: 10 \unit{cubic meter per second}
294%D 21: 10 \unit{cubic meter / second}
295%D 22: $10 \unit{cubic meter / second}$
296%D 23: 30 \unit{kilo pascal }
297%D 24: 30 \unit{kilo pascal square meter / second}
298%D 25: 30 \unit{kilo pascal square meter / kelvin second}
299%D 26: \unit{30 kilo pascal square meter / kelvin second}
300%D 27: $30 \unit{kilo pascal square meter / kelvin second }$
301%D 28: 30 \unit{crap}
302%D 29: 30 \unit{AC}
303%D 30: $\frac{10 \unit{m/s}}{20 \unit{m/s}} $
304%D 31: {\ss 30 \unit{kilo pascal square meter / second kelvin}}
305%D 32: \unit{123.22^-3 km/s}
306%D 33: \unit{123.22e-3 km/s}
307%D \stopbuffer
308%D
309%D \typebuffer
310%D
311%D Result: \startlines \getbuffer \stoplines
312%D
313%D Depending on needs we can add more tweaks (also depends on to what
314%D extent we need to be compatible with \MKII.
315%D
316%D Formatting is supported too:
317%D
318%D \startbuffer
319%D \starttabulate[|l|l|l|]
320%D \HL
321%D \NC \unit{10 kilo gram}       \NC \digits{10}        \NC \unit{10}        \NC \NR
322%D \NC \unit{1 kilogram}         \NC \digits{1}         \NC \unit{1}         \NC \NR
323%D \NC \unit{0.1 kilogram}       \NC \digits{0.1}       \NC \unit{0.1}       \NC \NR
324%D \NC \unit{1.1 kilogram}       \NC \digits{1.1}       \NC \unit{1.1}       \NC \NR
325%D \NC \unit{11 kilogram}        \NC \digits{11}        \NC \unit{11}        \NC \NR
326%D \HL
327%D \NC \unit{00,000.10 kilogram} \NC \digits{00,000.10} \NC \unit{00,000.10} \NC \NR
328%D \NC \unit{@@,@@0.10 kilogram} \NC \digits{@@,@@0.10} \NC \unit{@@,@@0.10} \NC \NR
329%D \NC \unit{__,___.10 kilogram} \NC \digits{__,___.10} \NC \unit{__,___.10} \NC \NR
330%D \NC \unit{__,__0:10 kilogram} \NC \digits{__,__0:10} \NC \unit{__,__0:10} \NC \NR
331%D \NC \unit{__,___:10 kilogram} \NC \digits{__,___:10} \NC \unit{__,___:10} \NC \NR
332%D \HL
333%D \stoptabulate
334%D \stopbuffer
335%D
336%D \typebuffer \getbuffer
337%D
338%D Punctuation can be configures usiing \type {method}:
339%D
340%D \startbuffer
341%D \starttabulate[|l|l|l|]
342%D \HL
343%D \NC   \NC \setupunits[method=0]\unit{00,000.10 kilogram} \NC \setupunits[method=0]\unit{@@,@@0.10 kilogram} \NC \NR
344%D \NC 1 \NC \setupunits[method=1]\unit{00,000.10 kilogram} \NC \setupunits[method=1]\unit{@@,@@0.10 kilogram} \NC \NR
345%D \NC 2 \NC \setupunits[method=2]\unit{00,000.10 kilogram} \NC \setupunits[method=2]\unit{@@,@@0.10 kilogram} \NC \NR
346%D \NC 3 \NC \setupunits[method=3]\unit{00,000.10 kilogram} \NC \setupunits[method=3]\unit{@@,@@0.10 kilogram} \NC \NR
347%D \NC 4 \NC \setupunits[method=4]\unit{00,000.10 kilogram} \NC \setupunits[method=4]\unit{@@,@@0.10 kilogram} \NC \NR
348%D \NC 5 \NC \setupunits[method=5]\unit{00,000.10 kilogram} \NC \setupunits[method=5]\unit{@@,@@0.10 kilogram} \NC \NR
349%D \NC 6 \NC \setupunits[method=6]\unit{00,000.10 kilogram} \NC \setupunits[method=6]\unit{@@,@@0.10 kilogram} \NC \NR
350%D \HL
351%D \stoptabulate
352%D \stopbuffer
353%D
354%D \typebuffer \getbuffer
355
356% only a space when a number is part of the unit
357
358\installcorenamespace {unit}
359\installcorenamespace {unitseparator}
360\installcorenamespace {unitspace}
361
362\installcommandhandler \??unit {unit} \??unit
363
364\setupunit
365  [\c!alternative=,              % done: text
366   \c!separator=\v!normal,       % done: cdot|big|medium|space
367   \s!language=\currentlanguage, % done: (no interface yet)
368   \c!order=\v!normal,           % ,. (reverse: .,)
369   \c!method=0,
370  %\c!grid=\v!yes,               % (maybe)
371  %\c!style=...,                 % done
372  %\c!color=...,                 % done
373  %\c!space=...,                 % (maybe) small medium big
374  ]
375
376\definehigh[unitshigh][\c!style=\txx]
377\definelow [unitslow] [\c!style=\txx]
378
379\let\setupunits\setupunit
380
381\newconstant   \c_phys_units_mode   % 0=text 1=math 2=textinmath 3=mathintext
382\newconstant   \c_phys_units_state  % 0=start 1=suffix 2=operator 3=unit 4=prefix 5=number
383\newconditional\c_phys_units_quantity
384\newconditional\c_phys_units_number
385\newconditional\c_phys_units_dospace
386
387% [\unit   {micro ohm}]\par %  no space before unit
388% [10\unit {micro ohm}]\par %  no space before unit
389% [10 \unit{micro ohm}]\par %     space before unit
390% [ \unit  {micro ohm}]\par %     space before unit
391% [\unit{10 micro ohm}]\par %     space before unit
392
393\unexpanded\def\unitssmallspace {\thinspace}
394\unexpanded\def\unitsmediumspace{\medspace}
395\unexpanded\def\unitsbigspace   {\thickspace}
396\unexpanded\def\unitsbackspace  {\negthinspace}
397
398\unexpanded\def\installunitsseparator#1#2%
399  {\setvalue{\??unitseparator#1}{#2}}
400
401% \unexpanded\def\phys_units_separator
402%   {\edef\currentunitsseparator{\unitparameter\c!separator}%
403%    \csname\??unitseparator
404%      \ifcsname\??unitseparator\currentunitsseparator\endcsname\currentunitsseparator\else\v!normal\fi
405%    \endcsname}
406
407\unexpanded\def\phys_units_separator
408  {\ifcsname\??unitseparator\unitparameter\c!separator\endcsname
409     \lastnamedcs
410   \else
411     \csname\??unitseparator\v!normal\endcsname
412   \fi}
413
414\installunitsseparator\v!normal{\ifmmode\mathord{\cdot}\else\cdot\fi}
415
416\installunitsseparator\v!normal {\cdot}
417\installunitsseparator\v!big    {\unitsbigspace}
418\installunitsseparator\v!medium {\unitsmediumspace}
419\installunitsseparator\v!small  {\unitssmallspace}
420\installunitsseparator\v!none   {}
421
422\unexpanded\def\installunitsspace#1#2%
423  {\setvalue{\??unitspace#1}{#2}}
424
425% \unexpanded\def\phys_units_space
426%   {\unskip % weird, why is unskip needed
427%    \edef\currentunitsspace{\unitparameter\c!space}%
428%    \csname\??unitspace
429%      \ifcsname\??unitspace\currentunitsspace\endcsname\currentunitsspace\else\v!normal\fi
430%    \endcsname}
431
432\unexpanded\def\phys_units_space
433  {\unskip % weird, why is unskip needed
434   \edef\currentunitsspace{\unitparameter\c!space}%
435   \ifcsname\??unitspace\currentunitsspace\endcsname\lastnamedcs\else\unitsmediumspace\fi}
436
437\installunitsspace\v!normal {\unitsmediumspace}
438\installunitsspace\v!big    {\unitsbigspace}
439\installunitsspace\v!medium {\unitsmediumspace}
440\installunitsspace\v!small  {\unitssmallspace}
441\installunitsspace\v!none   {}
442
443\newtoks \everyunits % we keep the old \units command so we need a longer one
444
445\appendtoks
446    \disablemathpunctuation
447    \nocharacteralign
448\to \everyunits
449
450\appendtoks
451    \setuevalue\currentunit{\phys_units_direct{\currentunit}}
452\to \everydefineunit
453
454\unexpanded\def\phys_units_direct#1%
455  {\begingroup
456   \the\everyunits
457   \ifdim\lastskip>\zeropoint
458     \settrue\c_phys_units_dospace
459     \removelastskip
460   \fi
461   \c_phys_digits_method\unitparameter\c!method\relax
462   \ifmmode\else\dontleavehmode\fi
463   \edef\currentunit{#1}%
464   \edef\unitlanguage{\unitparameter\s!language}%
465   \let\prefixlanguage\unitlanguage
466   \let\operatorlanguage\unitlanguage
467%    \the\everyunits
468  %\removeunwantedspaces % not ok yet
469   \useunitstyleandcolor\c!style\c!color
470   \edef\currentunitsalternative{\unitparameter\c!alternative}%
471   \ifmmode
472     \ifx\currentunitsalternative\v!text
473       \expandafter\expandafter\expandafter\phys_units_direct_text_in_math
474     \else
475       \expandafter\expandafter\expandafter\phys_units_direct_math
476     \fi
477   \else
478     \ifx\currentunitsalternative\v!mathematics
479       \expandafter\expandafter\expandafter\phys_units_direct_math_in_text
480     \else
481       \expandafter\expandafter\expandafter\phys_units_direct_text
482     \fi
483   \fi}
484
485\unexpanded\def\phys_units_direct_text_in_math#1%
486  {\mathtext{%
487     \c_phys_units_mode\plustwo
488     \phys_units_indeed{#1}%
489     \phys_units_finish
490   }%
491   \endgroup}
492
493\unexpanded\def\phys_units_direct_math#1%
494  {\c_phys_units_mode\plusone
495   \rm\tf % slow
496   \mathtf
497   \phys_units_indeed{#1}%
498   \phys_units_finish
499   \endgroup}
500
501\unexpanded\def\phys_units_direct_text#1%
502  {\phys_units_indeed{#1}%
503   \phys_units_finish
504   \endgroup}
505
506\unexpanded\def\phys_units_direct_math_in_text#1%
507  {\removeunwantedspaces % brr
508   \startimath
509   \c_phys_units_mode\plusthree
510   \rm\tf
511   \mathtf
512   \phys_units_indeed{#1}%
513   \phys_units_finish
514   \stopimath
515   \endgroup}
516
517\unexpanded\def\phys_units_direct_nested#1#2%
518  {\phys_units_indeed{#2}}
519
520\appendtoks
521    \let\phys_units_direct\phys_units_direct_nested
522\to \everyunits
523
524\unexpanded\def\phys_units_indeed#1%
525  {\edef\p_order{\unitparameter\c!order}%
526   \ifx\p_order\v!reverse\expandafter\clf_unit_reverse\else\expandafter\clf_unit_normal\fi{\detokenize{#1}}}
527
528\unexpanded\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix
529\unexpanded\def\unitsPU   #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree}                           % unit
530\unexpanded\def\unitsPS   #1#2{\phys_units_next\prefixtext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone}              % suffix
531\unexpanded\def\unitsUS   #1#2{\phys_units_next\unittext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone}                % suffix
532\unexpanded\def\unitsP      #1{\phys_units_next\prefixtext{#1}1\c_phys_units_state\plusfour}                                        % prefix
533\unexpanded\def\unitsU      #1{\phys_units_next\unittext{#1}\c_phys_units_state\plusthree}                                          % unit
534\unexpanded\def\unitsS      #1{\phys_units_start{}\unitsraise{\suffixtext{#1}}\c_phys_units_state\plusone}                          % suffix
535\unexpanded\def\unitsO      #1{\phys_units_start\operatortext{#1}\c_phys_units_state\plustwo}                                       % operator
536\unexpanded\def\unitsN      #1{\phys_units_start#1\c_phys_units_state\plusfive}                                                     % number
537\unexpanded\def\unitsC      #1{\removeunwantedspaces\unittext{#1}\c_phys_units_state\plussix}                                       % connected
538\unexpanded\def\unitsQ      #1{\removeunwantedspaces\unitslower{#1}\c_phys_units_state\zerocount}
539\unexpanded\def\unitsR    #1#2{% todo: tagging
540                               \ifmmode
541                                 #2%
542                               \else\ifnum#1=\plusone
543                                 \digitstextbinop{#2}% before and after
544                               \else
545                                 \digitstextbinnop{#2}% after
546                               \fi\fi
547                               \c_phys_units_state\zerocount
548                               \setfalse\c_phys_units_dospace
549                               \setfalse\c_phys_units_number
550                               \setfalse\c_phys_units_quantity}
551
552\unexpanded\def\unitsRPM    {\unitsR\plusone  {±}} % todo: symbols
553\unexpanded\def\unitsRTO    {\unitsR\plusone  {}} % todo: symbols
554\unexpanded\def\unitsRabout {\unitsR\zerocount{±}} % todo: symbols
555\unexpanded\def\unitsPopen  {(}
556\unexpanded\def\unitsPclose {)}
557
558\unexpanded\def\unitrange#1{}
559
560% Fonts can have a celsius and lack a fahrenheit symbol and as we want
561% to be consistent so we check for the counterparts as well. It's slow
562% but ok. Of course we could go virtual instead.
563
564\def\phys_units_text_prime      {\textacute}
565\def\phys_units_text_doubleprime{\textacute\kern-.25em\textacute}
566\def\phys_units_text_celsius    {°C}
567\def\phys_units_text_fahrenheit {°F}
568
569\unexpanded\def\checkedtextprime
570  {\iffontchar\font"2032\relax\iffontchar\font"2033\relax
571     \else\phys_units_text_prime\fi\else\phys_units_text_prime
572   \fi}
573
574\unexpanded\def\checkedtextdoubleprime
575  {\iffontchar\font"2033\relax\iffontchar\font"2032\relax
576     \else\phys_units_text_doubleprime\fi\else\phys_units_text_doubleprime
577   \fi}
578
579% \unexpanded\def\checkedtextcelsius
580%   {\ifmmode
581%      \phys_units_text_celsius
582%    \else\iffontchar\font"2103\relax
583%      ℃\else\phys_units_text_celsius
584%    \fi\fi}
585%
586% \unexpanded\def\checkedtextfahrenheit
587%   {\ifmmode
588%      \phys_units_text_fahrenheit
589%    \else\iffontchar\font"2109\relax
590%      ℉\else\phys_units_text_fahrenheit
591%    \fi\fi}
592%
593% % but, as users don't like this ...
594
595\let\checkedtextcelsius   \phys_units_text_celsius
596\let\checkedtextfahrenheit\phys_units_text_fahrenheit
597
598\setelementnature[unit]    [mixed]
599\setelementnature[quantity][mixed]
600
601\let\phys_units_finish\relax
602
603\unexpanded\def\unitsNstart
604  {\ifmmode \else
605     \settrue\c_phys_units_quantity
606     \dostarttagged\t!quantity\empty
607     \settrue\c_phys_units_number
608     \dostarttagged\t!number\empty
609   \fi}
610
611\unexpanded\def\unitsNstop
612  {\ifconditional\c_phys_units_number
613     \setfalse\c_phys_units_number
614     \dostoptagged
615   \fi
616   \c_phys_units_state\plusfive}
617
618% This is a hack: for some reason \unit{micro meter} like patterns give
619% \unitsNstart\unitsNstop so there is a buglet in the parser
620
621\let\unitsNstartindeed\unitsNstart
622
623\unexpanded\def\unitsNstart
624  {\doifelsenextchar\unitsNstop\gobbleoneargument\unitsNstartindeed}
625
626% End of hack.
627
628\unexpanded\def\unitsNspace
629  {\space}
630
631\unexpanded\def\unitsN#1%
632  {\unitsNstart#1\unitsNstop}
633
634\def\phys_units_start
635  {\ifmmode
636     \dostarttagged\t!maction\t!unit
637     \bgroup % make an mrow
638   \else
639     \dostarttagged\t!unit\empty
640   \fi
641   \let\phys_units_finish\phys_units_stop
642   \let\phys_units_start\relax}
643
644\def\phys_units_stop
645  {\ifconditional\c_phys_units_number
646     \setfalse\c_phys_units_number
647     \dostoptagged
648   \fi
649   \ifconditional\c_phys_units_quantity
650     \setfalse\c_phys_units_quantity
651     \dostoptagged
652   \fi
653   \dostoptagged
654   \ifmmode
655     \egroup
656   \fi}
657
658\def\unitsraise
659  {\ifcase\c_phys_units_mode
660     \expandafter\unitshigh
661   \or
662     \expandafter\normalsuperscript
663   \or
664     \expandafter\unitshigh
665   \or
666     \expandafter\normalsuperscript
667   \fi}
668
669\def\unitslower
670  {\ifcase\c_phys_units_mode
671     \expandafter\unitslow
672   \or
673     \expandafter\normalsubscript
674   \or
675     \expandafter\unitslow
676   \or
677     \expandafter\normalsubscript
678   \fi}
679
680\unexpanded\def\phys_units_next
681  {\ifcase\c_phys_units_state % start
682     \ifconditional\c_phys_units_dospace
683      % \ifdim\lastskip=\zeropoint
684         \phys_units_space
685      % \else
686      %   % too tricky ... we could remove and add
687      % \fi
688     \fi
689   \or % 1: suffix
690     {\phys_units_separator}%
691   \or % 2: operator
692   \or % 3: unit
693     {\phys_units_separator}%
694   \or % 4: prefix
695   \or % 5: number
696     \phys_units_space
697   \or % 6: symbol (connected)
698   \fi
699   \setfalse\c_phys_units_dospace
700   \phys_units_start}
701
702\unexpanded\def\unitsTIMES
703  {\ifnum\c_phys_units_state=\plusone % suffix
704   \else
705     \unitssmallspace
706   \fi
707   \cdot} % or \times
708
709\unexpanded\def\unitsOUTOF
710  {\ifnum\c_phys_units_state=\plusone % suffix
711   \else
712     \unitssmallspace
713   \fi
714   :}
715
716\unexpanded\def\unitsSOLIDUS
717  {\ifnum\c_phys_units_state=\plusone % suffix
718     \unitsbackspace
719   \fi
720   {/}%
721   }%\unitsbackspace}
722
723\definelabelclass [unit]     [2]
724\definelabelclass [operator] [2]
725\definelabelclass [prefix]   [2]
726\definelabelclass [suffix]   [2] % This is only a label because we want to show them in a table.
727
728\clf_definelabels{prefix}{prefixes}\s!false\relax
729\clf_definelabels{unit}{units}\s!false\relax
730\clf_definelabels{operator}{operators}\s!false\relax
731\clf_definelabels{suffix}{suffixes}\s!false\relax
732
733%D You can define additional units:
734%D
735%D \starttyping
736%D \registerunit
737%D   [unit]
738%D   [point=point,
739%D    basepoint=basepoint,
740%D    scaledpoint=scaledpoint,
741%D    didot=didot,
742%D    cicero=cicero]
743%D \stoptyping
744%D
745%D Possible categories are: \type {prefix}, \type {unit}, \type {operator},
746%D \type {suffix}, \type {symbol},\type {packaged}. You also need to define
747%D labels:
748%D
749%D \starttyping
750%D \setupunittext
751%D   [point=pt,
752%D    basepoint=bp,
753%D    scaledpoint=sp,
754%D    didot=dd,
755%D    cicero=cc]
756%D \stoptyping
757
758\unexpanded\def\registerunit
759  {\dodoubleempty\phys_units_register}
760
761\def\phys_units_register[#1][#2]%
762  {\clf_registerunit{#1}{#2}}
763
764%D You can generate a list as follows:
765%D
766%D \starttyping
767%D \usemodule[phy-01]
768%D
769%D \ShowUnitsTable % [prefixes]
770%D \stoptyping
771
772%D Now we define the standard units command:
773
774\defineunit
775  [unit]
776
777%D Example:
778%D
779%D \startbuffer[definitions]
780%D \startluacode
781%D     languages.data.labels.prefixes.whatever = {
782%D         Kilo = "olik"
783%D     }
784%D
785%D     languages.data.labels.units.whatever = {
786%D         Meter  = "retem",
787%D         Second = "dnoces",
788%D     }
789%D
790%D     languages.data.labels.operators.whatever = {
791%D         Solidus = " rep "
792%D     }
793%D \stopluacode
794%D \stopbuffer
795%D
796%D \startbuffer[sample]
797%D \startlines
798%D \lunit{10 km/s}
799%D \lunit{10 Kilo Meter/s}
800%D \lunit{10 kilo Meter/s}
801%D \lunit{10 Kilo m/s}
802%D \lunit{10 k Meter/s}
803%D \stoplines
804%D \stopbuffer
805%D
806%D \typebuffer[definitions] \getbuffer[definitions]
807%D
808%D \startbuffer
809%D \typebuffer[sample]
810%D
811%D \defineunits[lunit]                 \getbuffer[sample]
812%D \defineunits[lunit][label=test]     \getbuffer[sample]
813%D \defineunits[lunit][label=whatever] \getbuffer[sample]
814%D \stopbuffer
815%D
816%D \typebuffer \getbuffer
817%D
818%D Another example:
819%D
820%D \starttyping
821%D \startluacode
822%D     languages.data.labels.units.foo = {
823%D         Liter = "l"
824%D     }
825%D     languages.data.labels.units.bar = {
826%D         Liter = "L"
827%D     }
828%D \stopluacode
829%D
830%D \defineunits[lunit]            \lunit{10 l/s}\par
831%D \defineunits[funit][label=foo] \funit{10 l/s}\par
832%D \defineunits[bunit][label=bar] \bunit{10 l/s}\par
833%D \stoptyping
834
835\protect \endinput
836