%D \module %D [ file=phys-dim, %D version=2011-06-13, % was digits and units 1997.03.19, %D title=\CONTEXT\ Physics, %D subtitle=Digits and Units, %D author={Hans Hagen}, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \registerctxluafile{phys-dim}{} % TAGGING NEEDS CHECKING ... WILL DO WHEN PARSER IS OK \unprotect %D \macros %D {digits, setdigitmode, setdigitsign} %D %D This is an update of the \MKII\ digits mechanism. Beware, %D space delimited mode is now resticted! %D %D Depending on the digit mode the command \type {\digits} %D normalizes number patterns depending on the language set. %D %D \starttyping %D This will never be a \digits{1.000.000} seller. %D \stoptyping %D %D We still support the space delimited case but this is only for special %D purposes. When used in the text, you'd better use the argument variant. %D %D \startbuffer %D 1 \setdigitmode {1} \setdigitorder{0} \digits {12.345,90} %D 2 \setdigitmode {2} \setdigitorder{0} \digits {12.345,90} %D 3 \setdigitmode {3} \setdigitorder{0} \digits {12.345,90} %D 4 \setdigitmode {4} \setdigitorder{0} \digits {12.345,90} %D 5 \setdigitmode {5} \setdigitorder{0} \digits {12.345,90} %D 6 \setdigitmode {6} \setdigitorder{0} \digits {12.345,90} %D 1 \setdigitmode {1} \setdigitorder{1} \digits {12.345,90} %D 2 \setdigitmode {2} \setdigitorder{1} \digits {12.345,90} %D 3 \setdigitmode {3} \setdigitorder{1} \digits {12.345,90} %D 4 \setdigitmode {4} \setdigitorder{1} \digits {12.345,90} %D 5 \setdigitmode {5} \setdigitorder{1} \digits {12.345,90} %D 6 \setdigitmode {6} \setdigitorder{1} \digits {12.345,90} %D \stopbuffer %D %D \typebuffer %D %D This is typeset as: %D %D \startlines \getbuffer \stoplines %D %D The sign can be typeset as is or within the space of a %D digit. %D %D \startbuffer %D \setdigitsign 0 \digits {+12.345,90} %D \setdigitsign 1 \digits {+12.345,90} %D \stopbuffer %D %D \typebuffer %D %D This is typset as: %D %D \startlines %D \getbuffer %D \stoplines %D %D The digit modes are: %D %D \startitemize[n,packed] %D \item periods/comma %D \item commas/period %D \item thinmuskips/comma %D \item thinmuskips/period %D \item thickmuskips/comma %D \item thickmuskips/period %D \stopitemize %D %D The digit parser handles a bunch of special characters as %D well as different formats. We strongly suggest you to use %D the grouped call. %D %D \starttabulate[|l|l|l|] %D \NC \type{.} \NC , . \NC comma or period \NC \NR %D \NC \type{,} \NC , . \NC comma or period \NC \NR %D \NC \type{:} \NC \NC invisible period \NC \NR %D \NC \type{;} \NC \NC invisible comma \NC \NR %D \NC \type{_} \NC \NC invisible space \NC \NR %D \NC \type{/} \NC \NC invisible sign \NC \NR %D \NC \type{-} \NC $-$ \NC minus sign \NC \NR %D \NC \type{+} \NC $+$ \NC plus sign \NC \NR %D \NC \type{//} \NC \NC invisible high sign \NC \NR %D \NC \type{--} \NC $\negative$ \NC high minus sign \NC \NR %D \NC \type{++} \NC $\positive$ \NC high plus sign \NC \NR %D \NC \type{=} \NC $\zeroamount$ \NC zero padding \NC \NR %D \stoptabulate %D %D These triggers are used in the following examples. %D %D \starttabulate[|l|r|] %D \NC \type{1} \NC \ruledhbox{\strut\digits{1}} \NC \NR %D \NC \type{12} \NC \ruledhbox{\strut\digits{12}} \NC \NR %D \NC \type{12.34} \NC \ruledhbox{\strut\digits{12.34}} \NC \NR %D \NC \type{123,456} \NC \ruledhbox{\strut\digits{123,456}} \NC \NR %D \NC \type{123,456.78} \NC \ruledhbox{\strut\digits{123,456.78}} \NC \NR %D \NC \type{12,34} \NC \ruledhbox{\strut\digits{12,34}} \NC \NR %D \NC \type{.1234} \NC \ruledhbox{\strut\digits{.1234}} \NC \NR %D \NC \type{1234} \NC \ruledhbox{\strut\digits{1234}} \NC \NR %D \NC \type{123,456.78^9} \NC \ruledhbox{\strut\digits{123,456.78^9}} \NC \NR %D \NC \type{123,456.78e9} \NC \ruledhbox{\strut\digits{123,456.78e9}} \NC \NR %D \NC \type{/123,456.78e-9} \NC \ruledhbox{\strut\digits{/123,456.78e-9}} \NC \NR %D \NC \type{-123,456.78e-9} \NC \ruledhbox{\strut\digits{-123,456.78e-9}} \NC \NR %D \NC \type{+123,456.78e-9} \NC \ruledhbox{\strut\digits{+123,456.78e-9}} \NC \NR %D \NC \type{//123,456.78e-9} \NC \ruledhbox{\strut\digits{//123,456.78e-9}} \NC \NR %D \NC \type{--123,456.78e-9} \NC \ruledhbox{\strut\digits{--123,456.78e-9}} \NC \NR %D \NC \type{++123,456.78e-9} \NC \ruledhbox{\strut\digits{++123,456.78e-9}} \NC \NR %D \NC \type{___,___,123,456,789.00} \NC \ruledhbox{\strut\digits{___,___,123,456,789.00}} \NC \NR %D \NC \type{___,___,_12,345,678.==} \NC \ruledhbox{\strut\digits{___,___,_12,345,678.==}} \NC \NR %D \stoptabulate \newconstant\c_phys_digits_order \newconstant\c_phys_digits_method \newconstant\c_phys_digits_sign % we has sized (text script scriptscript) \unexpanded\def\setdigitmethod#1{\c_phys_digits_method #1\relax} \unexpanded\def\setdigitsign #1{\c_phys_digits_sign #1\relax} \unexpanded\def\setdigitorder #1{\c_phys_digits_order #1\relax} \let\setdigitmode\setdigitmethod % compatibility \def\phys_digits_normalized % we could calculate once and remember {\ifcase\c_phys_digits_sign \expandafter\secondoftwoarguments \else\ifmmode \expandafter\expandafter\expandafter\phys_digits_normalized_math \else \expandafter\expandafter\expandafter\phys_digits_normalized_text \fi\fi} \def\phys_digits_normalized_math#1#2% {\setbox\scratchbox\hbox{\normalstartimath\Ustack{#1}\normalstopimath}% \hbox to \wd\scratchbox{\hss{\normalstartimath\Ustack{#2}\normalstopimath}\hss}} \def\phys_digits_normalized_text#1#2% {\setbox\scratchbox\hbox{#1}% \hbox to \wd\scratchbox{\hss#2\hss}} \def\phys_digits_raised {\ifmmode \expandafter\normalsuperscript \else \expandafter\unitshigh \fi} % we could use a symbolset but how many symbols are there ? % \definesymbol[units][times][\times] % \definesymbol[units][times][\cdots] % \def\digitstimessymbol{\symbol[units][times]} % \definesymbol[units][times][\times] % \definesymbol[units][times][\cdots] % \definesymbol[units][times][\invisibletimes] % \definesymbol[units][times][\ifmmode\cdot\else\kern.2\emwidth\cdot\kern.2\emwidth\fi] \unexpanded\def\digitstextbinop#1% assumes preceding {\ifmmode\mathord{#1}\else\nobreak#1\fi} \def\digitstimessymbol{\digitstextbinop\times} \unexpanded\def\digitszeropadding {\hphantom{0}} \unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}} \unexpanded\def\digitspositive {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}} \unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\mathematics{\negative}}} \unexpanded\def\digitspositive {\phys_digits_normalized{0}{\mathematics{\positive}}} %unexpanded\def\digitsminus {\phys_digits_normalized{0}{\mathematics{-}}} %unexpanded\def\digitsplus {\phys_digits_normalized{0}{\mathematics{+}}} \unexpanded\def\digitsminus {\phys_digits_normalized{0}{\mathminus}} \unexpanded\def\digitsplus {\phys_digits_normalized{0}{\mathplus}} \unexpanded\def\digitsplusminus {\phys_digits_normalized{0}{\mathplusminus}} \unexpanded\def\digitsspace {\hphantom{0}} \unexpanded\def\digitsseparatorspace{\hphantom{.}} \unexpanded\def\digitssignspace {\hphantom{\digitsminus}} \unexpanded\def\digitshighspace {\hphantom{\digitspositive}} \unexpanded\def\digitspower #1{\digitstimessymbol10\phys_digits_raised{#1}} \unexpanded\def\digitspowerplus #1{\digitstimessymbol10\phys_digits_raised{\digitsplus#1}} \unexpanded\def\digitspowerminus #1{\digitstimessymbol10\phys_digits_raised{\digitsminus#1}} \unexpanded\def\digitsdigit #1{#1} \unexpanded\def\normaldigitscommasymbol {,} \unexpanded\def\normaldigitsperiodsymbol{.} \let\normaldigitsseparatorspace\digitsseparatorspace \installcorenamespace{digitscomma} \installcorenamespace{digitsperiod} \installcorenamespace{digitsspace} \letvalue{\??digitscomma 0}\normaldigitscommasymbol \letvalue{\??digitsperiod0}\normaldigitsperiodsymbol \letvalue{\??digitsspace 0}\normaldigitsseparatorspace \letvalue{\??digitscomma 1}\normaldigitsperiodsymbol \letvalue{\??digitsperiod1}\normaldigitscommasymbol \letvalue{\??digitsspace 1}\normaldigitsseparatorspace \letvalue{\??digitscomma 2}\normaldigitscommasymbol \letvalue{\??digitsperiod2}\normaldigitsperiodsymbol \letvalue{\??digitsspace 2}\normaldigitsseparatorspace \letvalue{\??digitscomma 3}\thinspace \letvalue{\??digitsperiod3}\normaldigitscommasymbol \letvalue{\??digitsspace 3}\thinspace \letvalue{\??digitscomma 4}\thinspace \letvalue{\??digitsperiod4}\normaldigitsperiodsymbol \letvalue{\??digitsspace 4}\thinspace \letvalue{\??digitscomma 5}\thickspace \letvalue{\??digitsperiod5}\normaldigitscommasymbol \letvalue{\??digitsspace 5}\thickspace \letvalue{\??digitscomma 6}\thickspace \letvalue{\??digitsperiod6}\normaldigitsperiodsymbol \letvalue{\??digitsspace 6}\thickspace \unexpanded\def\digitscommasymbol {\csname\??digitscomma \number\c_phys_digits_method\endcsname} \unexpanded\def\digitsperiodsymbol {\csname\??digitsperiod\number\c_phys_digits_method\endcsname} \unexpanded\def\digitsseparatorspace {\csname\??digitsspace \number\c_phys_digits_method\endcsname} % \unexpanded\def\digitsfinalcomma {\digitscommasymbol } % more for tracing % \unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing % \unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing % \unexpanded\def\digitsintermediateperiod {\digitsperiodsymbol} % more for tracing \unexpanded\def\digitsfinalcomma {\digitsperiodsymbol} % more for tracing \unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing \unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing \unexpanded\def\digitsintermediateperiod {\digitscommasymbol } % more for tracing %D The user macro: \unexpanded\def\phys_digits_indeed#1% {\dontleavehmode \begingroup \ifcase\c_phys_digits_order\expandafter\clf_digits_normal\else\expandafter\clf_digits_reverse\fi{\detokenize{#1}}% \endgroup \settrue\c_phys_units_dospace} \unexpanded\def\digits {\doifelsenextbgroup\phys_digits_argument\phys_digits_spaced} \def\phys_digits_argument#1% {\phys_digits_indeed{#1}} \def\phys_digits_spaced#1 % space delimited {\phys_digits_indeed{#1}} %D \macros %D {unit} %D %D We have been using the units module (and its predecessor) for over a decade %D now but when we moved on to \LUATEX\ a variant was prototyped that permits a %D less texie coding. I finally picked up that thread and cleaned up the code a %D bit so users can now play with it. (The main reason was that I wanted to %D test exporting.) %D %D \startbuffer %D 01: $10\unit{km/h}$ %D 02: $\unit{10 km/h}$ %D 03: \unit{km/h} %D 04: \unit{10 km/h} %D 05: \unit{10 km/h} %D 06: \unit{~1 km/h} %D 07: 10\unit{km/h} %D 08: 10 \unit{km/h} %D 09: $10 \unit{km/h}$ %D 10: 10 \unit{KiloMeter/Hour} %D 11: 10 \unit{kilometer/hour} %D 12: 10 \unit{km/h} %D 13: 10 \unit{kilometer per hour} %D 14: 10 \unit{km / h} %D 15: 10 \unit{ km / h } %D 16: 10 \unit{km/ms2} %D 17: 10 \unit{meter per second} %D 18: 10 \unit{cubic meter} %D 19: 10 \unit{cubic meter per second} %D 21: 10 \unit{cubic meter / second} %D 22: $10 \unit{cubic meter / second}$ %D 23: 30 \unit{kilo pascal } %D 24: 30 \unit{kilo pascal square meter / second} %D 25: 30 \unit{kilo pascal square meter / kelvin second} %D 26: \unit{30 kilo pascal square meter / kelvin second} %D 27: $30 \unit{kilo pascal square meter / kelvin second }$ %D 28: 30 \unit{crap} %D 29: 30 \unit{AC} %D 30: $\frac{10 \unit{m/s}}{20 \unit{m/s}} $ %D 31: {\ss 30 \unit{kilo pascal square meter / second kelvin}} %D 32: \unit{123.22^-3 km/s} %D 33: \unit{123.22e-3 km/s} %D \stopbuffer %D %D \typebuffer %D %D Result: \startlines \getbuffer \stoplines %D %D Depending on needs we can add more tweaks (also depends on to what %D extent we need to be compatible with \MKII. %D %D Formatting is supported too: %D %D \startbuffer %D \starttabulate[|l|l|l|] %D \HL %D \NC \unit{10 kilo gram} \NC \digits{10} \NC \unit{10} \NC \NR %D \NC \unit{1 kilogram} \NC \digits{1} \NC \unit{1} \NC \NR %D \NC \unit{0.1 kilogram} \NC \digits{0.1} \NC \unit{0.1} \NC \NR %D \NC \unit{1.1 kilogram} \NC \digits{1.1} \NC \unit{1.1} \NC \NR %D \NC \unit{11 kilogram} \NC \digits{11} \NC \unit{11} \NC \NR %D \HL %D \NC \unit{00,000.10 kilogram} \NC \digits{00,000.10} \NC \unit{00,000.10} \NC \NR %D \NC \unit{@@,@@0.10 kilogram} \NC \digits{@@,@@0.10} \NC \unit{@@,@@0.10} \NC \NR %D \NC \unit{__,___.10 kilogram} \NC \digits{__,___.10} \NC \unit{__,___.10} \NC \NR %D \NC \unit{__,__0:10 kilogram} \NC \digits{__,__0:10} \NC \unit{__,__0:10} \NC \NR %D \NC \unit{__,___:10 kilogram} \NC \digits{__,___:10} \NC \unit{__,___:10} \NC \NR %D \HL %D \stoptabulate %D \stopbuffer %D %D \typebuffer \getbuffer %D %D Punctuation can be configures usiing \type {method}: %D %D \startbuffer %D \starttabulate[|l|l|l|] %D \HL %D \NC \NC \setupunits[method=0]\unit{00,000.10 kilogram} \NC \setupunits[method=0]\unit{@@,@@0.10 kilogram} \NC \NR %D \NC 1 \NC \setupunits[method=1]\unit{00,000.10 kilogram} \NC \setupunits[method=1]\unit{@@,@@0.10 kilogram} \NC \NR %D \NC 2 \NC \setupunits[method=2]\unit{00,000.10 kilogram} \NC \setupunits[method=2]\unit{@@,@@0.10 kilogram} \NC \NR %D \NC 3 \NC \setupunits[method=3]\unit{00,000.10 kilogram} \NC \setupunits[method=3]\unit{@@,@@0.10 kilogram} \NC \NR %D \NC 4 \NC \setupunits[method=4]\unit{00,000.10 kilogram} \NC \setupunits[method=4]\unit{@@,@@0.10 kilogram} \NC \NR %D \NC 5 \NC \setupunits[method=5]\unit{00,000.10 kilogram} \NC \setupunits[method=5]\unit{@@,@@0.10 kilogram} \NC \NR %D \NC 6 \NC \setupunits[method=6]\unit{00,000.10 kilogram} \NC \setupunits[method=6]\unit{@@,@@0.10 kilogram} \NC \NR %D \HL %D \stoptabulate %D \stopbuffer %D %D \typebuffer \getbuffer % only a space when a number is part of the unit \installcorenamespace {unit} \installcorenamespace {unitseparator} \installcorenamespace {unitspace} \installcommandhandler \??unit {unit} \??unit \setupunit [\c!alternative=, % done: text \c!separator=\v!normal, % done: cdot|big|medium|space \s!language=\currentlanguage, % done: (no interface yet) \c!order=\v!normal, % ,. (reverse: .,) \c!method=0, %\c!grid=\v!yes, % (maybe) %\c!style=..., % done %\c!color=..., % done %\c!space=..., % (maybe) small medium big ] \definehigh[unitshigh][\c!style=\txx] \definelow [unitslow] [\c!style=\txx] \let\setupunits\setupunit \newconstant \c_phys_units_mode % 0=text 1=math 2=textinmath 3=mathintext \newconstant \c_phys_units_state % 0=start 1=suffix 2=operator 3=unit 4=prefix 5=number \newconditional\c_phys_units_quantity \newconditional\c_phys_units_number \newconditional\c_phys_units_dospace % [\unit {micro ohm}]\par % no space before unit % [10\unit {micro ohm}]\par % no space before unit % [10 \unit{micro ohm}]\par % space before unit % [ \unit {micro ohm}]\par % space before unit % [\unit{10 micro ohm}]\par % space before unit \unexpanded\def\unitssmallspace {\thinspace} \unexpanded\def\unitsmediumspace{\medspace} \unexpanded\def\unitsbigspace {\thickspace} \unexpanded\def\unitsbackspace {\negthinspace} \unexpanded\def\installunitsseparator#1#2% {\setvalue{\??unitseparator#1}{#2}} % \unexpanded\def\phys_units_separator % {\edef\currentunitsseparator{\unitparameter\c!separator}% % \csname\??unitseparator % \ifcsname\??unitseparator\currentunitsseparator\endcsname\currentunitsseparator\else\v!normal\fi % \endcsname} \unexpanded\def\phys_units_separator {\ifcsname\??unitseparator\unitparameter\c!separator\endcsname \lastnamedcs \else \csname\??unitseparator\v!normal\endcsname \fi} \installunitsseparator\v!normal{\ifmmode\mathord{\cdot}\else\cdot\fi} \installunitsseparator\v!normal {\cdot} \installunitsseparator\v!big {\unitsbigspace} \installunitsseparator\v!medium {\unitsmediumspace} \installunitsseparator\v!small {\unitssmallspace} \installunitsseparator\v!none {} \unexpanded\def\installunitsspace#1#2% {\setvalue{\??unitspace#1}{#2}} % \unexpanded\def\phys_units_space % {\unskip % weird, why is unskip needed % \edef\currentunitsspace{\unitparameter\c!space}% % \csname\??unitspace % \ifcsname\??unitspace\currentunitsspace\endcsname\currentunitsspace\else\v!normal\fi % \endcsname} \unexpanded\def\phys_units_space {\unskip % weird, why is unskip needed \edef\currentunitsspace{\unitparameter\c!space}% \ifcsname\??unitspace\currentunitsspace\endcsname\lastnamedcs\else\unitsmediumspace\fi} \installunitsspace\v!normal {\unitsmediumspace} \installunitsspace\v!big {\unitsbigspace} \installunitsspace\v!medium {\unitsmediumspace} \installunitsspace\v!small {\unitssmallspace} \installunitsspace\v!none {} \newtoks \everyunits % we keep the old \units command so we need a longer one \appendtoks \disablemathpunctuation \nocharacteralign \to \everyunits \appendtoks \setuevalue\currentunit{\phys_units_direct{\currentunit}} \to \everydefineunit \unexpanded\def\phys_units_direct#1% {\begingroup \the\everyunits \ifdim\lastskip>\zeropoint \settrue\c_phys_units_dospace \removelastskip \fi \c_phys_digits_method\unitparameter\c!method\relax \ifmmode\else\dontleavehmode\fi \edef\currentunit{#1}% \edef\unitlanguage{\unitparameter\s!language}% \let\prefixlanguage\unitlanguage \let\operatorlanguage\unitlanguage % \the\everyunits %\removeunwantedspaces % not ok yet \useunitstyleandcolor\c!style\c!color \edef\currentunitsalternative{\unitparameter\c!alternative}% \ifmmode \ifx\currentunitsalternative\v!text \expandafter\expandafter\expandafter\phys_units_direct_text_in_math \else \expandafter\expandafter\expandafter\phys_units_direct_math \fi \else \ifx\currentunitsalternative\v!mathematics \expandafter\expandafter\expandafter\phys_units_direct_math_in_text \else \expandafter\expandafter\expandafter\phys_units_direct_text \fi \fi} \unexpanded\def\phys_units_direct_text_in_math#1% {\mathtext{% \c_phys_units_mode\plustwo \phys_units_indeed{#1}% \phys_units_finish }% \endgroup} \unexpanded\def\phys_units_direct_math#1% {\c_phys_units_mode\plusone \rm\tf % slow \mathtf \phys_units_indeed{#1}% \phys_units_finish \endgroup} \unexpanded\def\phys_units_direct_text#1% {\phys_units_indeed{#1}% \phys_units_finish \endgroup} \unexpanded\def\phys_units_direct_math_in_text#1% {\removeunwantedspaces % brr \startimath \c_phys_units_mode\plusthree \rm\tf \mathtf \phys_units_indeed{#1}% \phys_units_finish \stopimath \endgroup} \unexpanded\def\phys_units_direct_nested#1#2% {\phys_units_indeed{#2}} \appendtoks \let\phys_units_direct\phys_units_direct_nested \to \everyunits \unexpanded\def\phys_units_indeed#1% {\edef\p_order{\unitparameter\c!order}% \ifx\p_order\v!reverse\expandafter\clf_unit_reverse\else\expandafter\clf_unit_normal\fi{\detokenize{#1}}} \unexpanded\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix \unexpanded\def\unitsPU #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree} % unit \unexpanded\def\unitsPS #1#2{\phys_units_next\prefixtext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix \unexpanded\def\unitsUS #1#2{\phys_units_next\unittext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix \unexpanded\def\unitsP #1{\phys_units_next\prefixtext{#1}1\c_phys_units_state\plusfour} % prefix \unexpanded\def\unitsU #1{\phys_units_next\unittext{#1}\c_phys_units_state\plusthree} % unit \unexpanded\def\unitsS #1{\phys_units_start{}\unitsraise{\suffixtext{#1}}\c_phys_units_state\plusone} % suffix \unexpanded\def\unitsO #1{\phys_units_start\operatortext{#1}\c_phys_units_state\plustwo} % operator \unexpanded\def\unitsN #1{\phys_units_start#1\c_phys_units_state\plusfive} % number \unexpanded\def\unitsC #1{\removeunwantedspaces\unittext{#1}\c_phys_units_state\plussix} % connected \unexpanded\def\unitsQ #1{\removeunwantedspaces\unitslower{#1}\c_phys_units_state\zerocount} \unexpanded\def\unitsR #1#2{% todo: tagging \ifmmode #2% \else\ifnum#1=\plusone \digitstextbinop{#2}% before and after \else \digitstextbinnop{#2}% after \fi\fi \c_phys_units_state\zerocount \setfalse\c_phys_units_dospace \setfalse\c_phys_units_number \setfalse\c_phys_units_quantity} \unexpanded\def\unitsRPM {\unitsR\plusone {±}} % todo: symbols \unexpanded\def\unitsRTO {\unitsR\plusone {–}} % todo: symbols \unexpanded\def\unitsRabout {\unitsR\zerocount{±}} % todo: symbols \unexpanded\def\unitsPopen {(} \unexpanded\def\unitsPclose {)} \unexpanded\def\unitrange#1{} % Fonts can have a celsius and lack a fahrenheit symbol and as we want % to be consistent so we check for the counterparts as well. It's slow % but ok. Of course we could go virtual instead. \def\phys_units_text_prime {\textacute} \def\phys_units_text_doubleprime{\textacute\kern-.25em\textacute} \def\phys_units_text_celsius {°C} \def\phys_units_text_fahrenheit {°F} \unexpanded\def\checkedtextprime {\iffontchar\font"2032\relax\iffontchar\font"2033\relax ′\else\phys_units_text_prime\fi\else\phys_units_text_prime \fi} \unexpanded\def\checkedtextdoubleprime {\iffontchar\font"2033\relax\iffontchar\font"2032\relax ″\else\phys_units_text_doubleprime\fi\else\phys_units_text_doubleprime \fi} % \unexpanded\def\checkedtextcelsius % {\ifmmode % \phys_units_text_celsius % \else\iffontchar\font"2103\relax % ℃\else\phys_units_text_celsius % \fi\fi} % % \unexpanded\def\checkedtextfahrenheit % {\ifmmode % \phys_units_text_fahrenheit % \else\iffontchar\font"2109\relax % ℉\else\phys_units_text_fahrenheit % \fi\fi} % % % but, as users don't like this ... \let\checkedtextcelsius \phys_units_text_celsius \let\checkedtextfahrenheit\phys_units_text_fahrenheit \setelementnature[unit] [mixed] \setelementnature[quantity][mixed] \let\phys_units_finish\relax \unexpanded\def\unitsNstart {\ifmmode \else \settrue\c_phys_units_quantity \dostarttagged\t!quantity\empty \settrue\c_phys_units_number \dostarttagged\t!number\empty \fi} \unexpanded\def\unitsNstop {\ifconditional\c_phys_units_number \setfalse\c_phys_units_number \dostoptagged \fi \c_phys_units_state\plusfive} % This is a hack: for some reason \unit{micro meter} like patterns give % \unitsNstart\unitsNstop so there is a buglet in the parser \let\unitsNstartindeed\unitsNstart \unexpanded\def\unitsNstart {\doifelsenextchar\unitsNstop\gobbleoneargument\unitsNstartindeed} % End of hack. \unexpanded\def\unitsNspace {\space} \unexpanded\def\unitsN#1% {\unitsNstart#1\unitsNstop} \def\phys_units_start {\ifmmode \dostarttagged\t!maction\t!unit \bgroup % make an mrow \else \dostarttagged\t!unit\empty \fi \let\phys_units_finish\phys_units_stop \let\phys_units_start\relax} \def\phys_units_stop {\ifconditional\c_phys_units_number \setfalse\c_phys_units_number \dostoptagged \fi \ifconditional\c_phys_units_quantity \setfalse\c_phys_units_quantity \dostoptagged \fi \dostoptagged \ifmmode \egroup \fi} \def\unitsraise {\ifcase\c_phys_units_mode \expandafter\unitshigh \or \expandafter\normalsuperscript \or \expandafter\unitshigh \or \expandafter\normalsuperscript \fi} \def\unitslower {\ifcase\c_phys_units_mode \expandafter\unitslow \or \expandafter\normalsubscript \or \expandafter\unitslow \or \expandafter\normalsubscript \fi} \unexpanded\def\phys_units_next {\ifcase\c_phys_units_state % start \ifconditional\c_phys_units_dospace % \ifdim\lastskip=\zeropoint \phys_units_space % \else % % too tricky ... we could remove and add % \fi \fi \or % 1: suffix {\phys_units_separator}% \or % 2: operator \or % 3: unit {\phys_units_separator}% \or % 4: prefix \or % 5: number \phys_units_space \or % 6: symbol (connected) \fi \setfalse\c_phys_units_dospace \phys_units_start} \unexpanded\def\unitsTIMES {\ifnum\c_phys_units_state=\plusone % suffix \else \unitssmallspace \fi \cdot} % or \times \unexpanded\def\unitsOUTOF {\ifnum\c_phys_units_state=\plusone % suffix \else \unitssmallspace \fi :} \unexpanded\def\unitsSOLIDUS {\ifnum\c_phys_units_state=\plusone % suffix \unitsbackspace \fi {/}% }%\unitsbackspace} \definelabelclass [unit] [2] \definelabelclass [operator] [2] \definelabelclass [prefix] [2] \definelabelclass [suffix] [2] % This is only a label because we want to show them in a table. \clf_definelabels{prefix}{prefixes}\s!false\relax \clf_definelabels{unit}{units}\s!false\relax \clf_definelabels{operator}{operators}\s!false\relax \clf_definelabels{suffix}{suffixes}\s!false\relax %D You can define additional units: %D %D \starttyping %D \registerunit %D [unit] %D [point=point, %D basepoint=basepoint, %D scaledpoint=scaledpoint, %D didot=didot, %D cicero=cicero] %D \stoptyping %D %D Possible categories are: \type {prefix}, \type {unit}, \type {operator}, %D \type {suffix}, \type {symbol},\type {packaged}. You also need to define %D labels: %D %D \starttyping %D \setupunittext %D [point=pt, %D basepoint=bp, %D scaledpoint=sp, %D didot=dd, %D cicero=cc] %D \stoptyping \unexpanded\def\registerunit {\dodoubleempty\phys_units_register} \def\phys_units_register[#1][#2]% {\clf_registerunit{#1}{#2}} %D You can generate a list as follows: %D %D \starttyping %D \usemodule[phy-01] %D %D \ShowUnitsTable % [prefixes] %D \stoptyping %D Now we define the standard units command: \defineunit [unit] %D Example: %D %D \startbuffer[definitions] %D \startluacode %D languages.data.labels.prefixes.whatever = { %D Kilo = "olik" %D } %D %D languages.data.labels.units.whatever = { %D Meter = "retem", %D Second = "dnoces", %D } %D %D languages.data.labels.operators.whatever = { %D Solidus = " rep " %D } %D \stopluacode %D \stopbuffer %D %D \startbuffer[sample] %D \startlines %D \lunit{10 km/s} %D \lunit{10 Kilo Meter/s} %D \lunit{10 kilo Meter/s} %D \lunit{10 Kilo m/s} %D \lunit{10 k Meter/s} %D \stoplines %D \stopbuffer %D %D \typebuffer[definitions] \getbuffer[definitions] %D %D \startbuffer %D \typebuffer[sample] %D %D \defineunits[lunit] \getbuffer[sample] %D \defineunits[lunit][label=test] \getbuffer[sample] %D \defineunits[lunit][label=whatever] \getbuffer[sample] %D \stopbuffer %D %D \typebuffer \getbuffer %D %D Another example: %D %D \starttyping %D \startluacode %D languages.data.labels.units.foo = { %D Liter = "l" %D } %D languages.data.labels.units.bar = { %D Liter = "L" %D } %D \stopluacode %D %D \defineunits[lunit] \lunit{10 l/s}\par %D \defineunits[funit][label=foo] \funit{10 l/s}\par %D \defineunits[bunit][label=bar] \bunit{10 l/s}\par %D \stoptyping \protect \endinput