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