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