texlive[68504] Master/texmf-dist: non-decimal-units (10oct23)
commits+karl at tug.org
commits+karl at tug.org
Tue Oct 10 22:24:53 CEST 2023
Revision: 68504
https://tug.org/svn/texlive?view=revision&revision=68504
Author: karl
Date: 2023-10-10 22:24:53 +0200 (Tue, 10 Oct 2023)
Log Message:
-----------
non-decimal-units (10oct23)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/non-decimal-units/README.md
trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.pdf
trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.tex
trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.british.tex
trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.danish.tex
trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.german.tex
trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.sty
Added Paths:
-----------
trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.preamble.sty
Modified: trunk/Master/texmf-dist/doc/latex/non-decimal-units/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/non-decimal-units/README.md 2023-10-10 20:24:32 UTC (rev 68503)
+++ trunk/Master/texmf-dist/doc/latex/non-decimal-units/README.md 2023-10-10 20:24:53 UTC (rev 68504)
@@ -5,9 +5,9 @@
See [non-decimal-units.pdf](docs/non-decimal-units.pdf) for the documentation.
-Contents last updated 2023-09-27.
+Contents last updated 2023-10-10.
-<!-- Package available via CTAN at https://www.ctan.org/pkg/non-decimal-units -->
+Package available via CTAN at https://www.ctan.org/pkg/non-decimal-units
License: CC-BY-SA 4.0
Author: Mikkel Eide Eriksen <mikkel.eriksen at gmail.com>
Modified: trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.pdf
===================================================================
(Binary files differ)
Added: trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.preamble.sty
===================================================================
--- trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.preamble.sty (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.preamble.sty 2023-10-10 20:24:53 UTC (rev 68504)
@@ -0,0 +1,106 @@
+\usepackage{makeidx}
+\makeindex
+
+\usepackage{needspace}
+
+\usepackage{csquotes}
+\usepackage[english]{babel}
+\usepackage[
+ backend=biber,
+ urldate=long,
+ date=long,
+]{biblatex}
+\addbibresource{non-decimal-units.bib}
+
+\usepackage{enumitem}
+\usepackage[
+ hidelinks,
+]{hyperref}
+
+\usepackage{tcolorbox}
+\tcbuselibrary{documentation}
+\tcbuselibrary{minted}
+\tcbuselibrary{breakable}
+
+\definecolor{DarkDefinition}{rgb}{0.392,0.392,0.942}
+
+\tcbset{
+ listing engine=minted,
+ color definition=DarkDefinition,
+ floatplacement=h,
+ index colorize=true,
+ doc head={
+ interior style={
+ fill,
+ color=blue!10,
+ },
+ boxsep=2pt,
+ after skip=0pt,
+ nobeforeafter,
+ },
+ doc raster={
+ raster after skip=0pt,
+ },
+ before doc body={
+ \begin{tcolorbox}[
+ colback=blue!5,
+ colframe=blue!5,
+ arc=0pt,
+ outer arc=0pt,
+ before skip=0pt,
+ nobeforeafter,
+ ]
+ },
+ after doc body={\end{tcolorbox}},
+}
+
+\AtBeginEnvironment{tcb at manual@entry}{%
+ \needspace{4\baselineskip}%
+}
+
+\newtcbinputlisting{\unitlisting}[2]{%
+ listing file = {../latex/non-decimal-units.#1.tex},
+ title = Listing of units loaded with the \docAuxKey{#1} option,
+ listing only,
+ breakable,
+ minted options={fontsize=\small},
+ docexample,
+}
+
+\setlist[description]{
+ leftmargin=5em,
+ rightmargin=\leftmargin,
+ itemindent=\labelwidth,
+ align=right,
+ font=\docAuxKey,
+ noitemsep,
+}
+
+\usepackage{fnpct}
+
+\usepackage{tabularray}
+\UseTblrLibrary{booktabs}
+
+\usepackage{cleveref}
+
+\RequirePackage[autolanguage]{numprint}
+
+\usepackage[
+ danish,
+]{non-decimal-units}
+
+\RequirePackage{fontspec}
+\newfontfamily\mufifont{Palemonas MUFI}
+
+\RequirePackage[
+ MUFI,
+ fonts={
+ MUFI=\mufifont,
+ },
+]{unicode-alphabets}
+
+\nduKeys{%
+ units/mark/symbol=\mufi{markflour},
+ units/skilling/symbol=\mufi{schillgerm},
+ units/penning/symbol=\mufi{20B0},
+}
\ No newline at end of file
Property changes on: trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.preamble.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.tex 2023-10-10 20:24:32 UTC (rev 68503)
+++ trunk/Master/texmf-dist/doc/latex/non-decimal-units/non-decimal-units.tex 2023-10-10 20:24:53 UTC (rev 68504)
@@ -1,5 +1,8 @@
% !TEX TS-program = LuaLaTeX-shell-escape
-\documentclass{article}
+\documentclass[
+ a4paper,
+ margin=4cm
+]{article}
\usepackage{non-decimal-units.preamble}
@@ -6,10 +9,11 @@
\title{Non-Decimal Units for \LaTeX}
\author{Mikkel Eide Eriksen\\\href{mailto:mikkel.eriksen at gmail.com}{\texttt{mikkel.eriksen at gmail.com}}}
-\nduset{
+\nduKeys{
set aligned for environment=tabular,
- aliases/danish rigsdaler,
- restrict segment depth=2,
+ tabularray column type=U,
+ unit depth=skilling,
+ unit separator={~},
}
\begin{document}
@@ -18,7 +22,7 @@
\section{Preface} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-Many historical unit systems were non-decimal. For example, the Danish rigsdaler\footnote{\url{https://en.wikipedia.org/wiki/Danish_rigsdaler}} --- where 1 \nduName{danish rigsdaler}{0} consists of \nduFactor{danish rigsdaler}{1}~\nduName{danish rigsdaler}{1}, each again consisting of \nduFactor{danish rigsdaler}{2}~\nduName{danish rigsdaler}{2} for a total of 96 \nduName{danish rigsdaler}{2} per \nduName{danish rigsdaler}{0} --- was used from 1625 to 1875, when currency was decimalised to the current system of 1 krone = 100 øre.
+Many historical unit systems were non-decimal. For example, the Danish rigsdaler\footnote{\url{https://en.wikipedia.org/wiki/Danish_rigsdaler}} --- where 1 rigsdaler consists of 16~mark, each again consisting of 16~skilling for a total of 96 skilling per rigsdaler --- was used from 1625 to 1875, when currency was decimalised to the current system of 1 krone = 100 øre.
% https://en.wikipedia.org/wiki/Non-decimal_currency
@@ -30,7 +34,7 @@
In order to do this, values are divided into \emph{segments}, which are separated by decimal points: for example, the historical Danish monetary value \nduValue{danish rigsdaler}{1.2.3} is entered as \texttt{1.2.3}, which the code then formats appropriately.
-Issues can be reported at \url{https://github.com/mikkelee/latex-units/issues} but keep in mind I am not very experienced with \LaTeX ;)
+Issues can be reported at \url{https://github.com/mikkelee/latex-units/issues}.
\clearpage
\section{Configuration} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -45,16 +49,16 @@
\begin{description}
\item[british] Currencies
-\item[danish] Currencies and areas
+\item[danish] Currencies, areas, and weights
\item[german] Currencies
\end{description}
-Alternately, one may configure new units via \refCom{nduNewUnit}.
+Alternately, one may configure new units via \refCom{nduNewBaseUnit} and \refCom{nduNewUnitGroup}.
\end{docCommand}
\begin{docCommand}
- {nduset}
+ {nduKeys}
{\marg{options}}
Can be used to set options globally (in the preamble) or locally (in a group). See further documentation for possible keys/values.
@@ -70,18 +74,18 @@
\begin{docCommand}
{nduValue}
- {\marg{unit name}\oarg{options}\marg{value}}
+ {\marg{unit group}\oarg{options}\marg{value}}
-Formats \meta{value} according to the setup configured for the \meta{unit name}, as well as any provided \meta{options}. The number of decimal points and the values between them determine how many and which segments are displayed.
+Formats \meta{value} according to the setup configured for the \meta{unit group}, as well as any provided \meta{options}.
-Empty segments are skipped, unless the \refKey{replace nil with} key is set.
+If no special configuration is made, the number of decimal points and the values between them determine how many and which units are displayed. For example, empty values are skipped unless the \refKey{replace nil with} key is set.
\begin{dispExample*}{
title=Example usage: \docAuxCommand*{nduValue} macro
}
\nduValue{danish rigsdaler}{1.2.3}\\
-\nduValue{danish rigsdaler}{1..}\\
-\nduValue{danish rigsdaler}{.2.}\\
+\nduValue{danish rigsdaler}{1}\\
+\nduValue{danish rigsdaler}{.2}\\
\nduValue{danish rigsdaler}{..3}\\
\end{dispExample*}
\end{docCommand}
@@ -90,38 +94,56 @@
\subsubsection{Options}
\begin{docKeys}[
- doc name = show,
+ doc name = display,
]{
{
- doc parameter = {=values},
+ doc parameter = {=values only},
},
{
- doc parameter = {=values and symbols},
- doc description = initially \texttt{values and symbols},
+ doc parameter = {=formatted},
+ doc description = initially \texttt{formatted},
},
{
- doc parameter = {=symbols},
+ doc parameter = {=symbols only},
},
+ {
+ doc parameter = {=numprint},
+ },
}
-Changes which information is included in the expansion.
+ Changes which information is included in the expansion.
-Because only those segments with a value will be included, \docAuxKey*{show}=\docValue*{symbols} can be used to list the segment units (though if only one or two is needed, it may be preferable to use \refCom{nduSymbol}).
+ Because only present values will be included, \docAuxKey*{display}=\docValue*{symbols only} can be used to list the segment units (though it may be preferable to use \refCom{nduHeader} or \refCom{nduSymbol}).
\begin{dispExample}
\nduValue{danish hartkorn}
- [show=symbols]
+ [display=symbols only]
{0.0.0.0.0}
\nduValue{danish hartkorn}
- [show=symbols]
+ [display=values only]
{0.0...}
\end{dispExample}
+
+ Finally, it is possible to use the \href{https://ctan.org/pkg/numprint}{numprint} package to format numbers, especially useful for larger values. Note that this may be counter to the formatting of some units (eg. British pounds), in which case one may prefer the \docAuxKey{use numprint} key instead.
+
+\begin{dispExample}
+\nduValue{danish rigsdaler}
+ [display=numprint]
+ {1000}
+\end{dispExample}
\end{docKeys}
-See also \cref{units:new} for further discussion on possible options.
+\begin{docKey}
+ {format}
+ {=\marg{...}}
+ {initially \docAuxCommand*{VALUE}\docAuxCommand*{nobreakspace}\docAuxCommand*{SYMBOL}}
-\clearpage
+ Sets how a given base unit should be formatted for display.
+
+ The placeholders \docAuxCommand*{VALUE} and \docAuxCommand*{SYMBOL} will be substituted when the value is typeset.
+\end{docKey}
+
\begin{docKeys}
[]
{
@@ -140,156 +162,117 @@
The key \docAuxKey*{treat zero as nil} replaces 0 with nothing, which in turn means that setting both will replace both zero and nil with the custom string.
-These keys also apply in non-tabular contexts, but are probably most useful here.
-
-\begin{dispExample*}{
- title=Example usage: \docAuxKey*{replace nil with} key
-}
-\begingroup
-\nduset{
- treat zero as nil,
- replace nil with=---,
-}
-\begin{tabular}{r r}
- \toprule
- & \nduHeader{danish rigsdaler} \\
- \midrule
- a & \nduValue{danish rigsdaler}{1.2.3} \\
- b & \nduValue{danish rigsdaler}{100.0.0} \\
- c & \nduValue{danish rigsdaler}{.1.} \\
- \bottomrule
-\end{tabular}
-\endgroup
-\end{dispExample*}
\end{docKeys}
+\begin{docKey}
+ {unit depth}
+ {=\meta{unit name}}
+ {initially no restriction}
+
+ When calculating or displaying a value, only the segments up to and including \meta{unit name} will be considered.
+
+ In this document, the depth has been globally set to \texttt{skilling}, but older historical sub-units can be included by locally setting the depth to eg. \texttt{hvid} (or indeed not restricting it globally).
+
+ If the \meta{unit name} is not present in the current unit group, it has no effect.
+
+\begin{dispExample}
+\nduValue{danish rigsdaler}
+ [unit depth=skilling]
+ {1.2.3.4.5}
-\clearpage
-\subsection{Tabular Data} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\nduValue{danish rigsdaler}
+ [unit depth=penning]
+ {1.2.3.4.5}
+\end{dispExample}
+\end{docKey}
-In order to align values in a tabular context, the \docAuxKey*{aligned} key causes \docAuxCommand{nduValue} to wrap each segment in a cell of equal width, using \docAuxCommand*{makebox}.
+\begin{docKey}
+ {unit separator}
+ {=\meta{...}}
+ {initially \docAuxCommand*{nobreakspace}}
+
+ When displaying a value, this string will be inserted between each segment.
-Additionally, the \docAuxCommand*{nduHeader} macro provides a convenient header showing the unit symbols.
+\begin{dispExample}
+\nduValue{danish hartkorn}[
+ display=values only,
+ unit separator=.
+ ]
+ {1.2.3.4}
-All segments will be included in the headers and cells, whether they contain a value or not. If no value is provided for the segment, and no nil replacement is specified with the \refKey{replace nil with} key, the cell will be empty.
+\nduValue{danish rigsdaler}
+ [unit separator={---}]
+ {1.2.3}
+\end{dispExample}
-\begin{docCommand}
- {nduHeader}
- {\marg{unit name}\oarg{options}}
- Formats the unit symbols in boxes suitable for a header. See \cpageref{units:new} for configuration of symbols.
-\end{docCommand}
+\end{docKey}
-\clearpage
-\subsubsection{Options}
+\begin{docKey}
+ {use numprint}
+ {}
+ {not set initially}
+
+ When displaying a value, use the \href{https://ctan.org/pkg/numprint}{numprint} package, including when using the \docAuxKey{format} key. You can of course also configure the numprint settings, either in a group or locally.
-\begin{docKeys}
- []
- {
- {
- doc name = aligned,
- doc description = {initially not set},
- },
- {
- doc name = set aligned for environment,
- doc description = {initially set for \texttt{tabular}},
- },
- }
-
- Setting \docAuxKey*{aligned} will format the presently displayed header in aligned boxes, desirable in tabular contexts.
-
- Additionally, the \docAuxKey*{set aligned for environment} key can be set to an environment name, causing \docAuxKey*{aligned} to automatically be set aligned for those enviroments, using \docAuxCommand*{AtBeginEnvironment}. It can be set multiple times, once for each required environment.
-
-\begin{dispExample*}{
- title=Example usage: \docAuxCommand*{nduHeader} and \docAuxCommand*{nduValue} macros with \docAuxKey*{aligned} key.
-}
+\begin{dispExample}
\begingroup
-\begin{tabular}{r r}
- \toprule
- & \nduHeader{danish rigsdaler} \\
- \midrule
- a & \nduValue{danish rigsdaler}{1.2.3} \\
- b & \nduValue{danish rigsdaler}{100..} \\
- c & \nduValue{danish rigsdaler}{.1.} \\
- \bottomrule
-\end{tabular}
+\selectlanguage{ngerman}
+\nduValue{danish rigsdaler}
+ [use numprint]
+ {1000.0}
\endgroup
-\end{dispExample*}
+\end{dispExample}
-\end{docKeys}
-
-\begin{docKey}
- {cell width}
- {=\meta{length}}
- {initially \texttt{5em}}
-
-Changes the width of each segment.
-
-\begin{dispExample*}{
- title=Example usage: \docAuxKey*{cell width} key
-}
-\begingroup
-\nduset{
- cell width=3em,
-}
-\begin{tabular}{r r}
- \toprule
- & \nduHeader{danish rigsdaler} \\
- \midrule
- a & \nduValue{danish rigsdaler}{1.2.3} \\
- b & \nduValue{danish rigsdaler}{100..} \\
- c & \nduValue{danish rigsdaler}{.1.} \\
- \bottomrule
-\end{tabular}
-\endgroup
-\end{dispExample*}
\end{docKey}
\clearpage
-\subsection{Arithmetical Operations} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Arithmetical Operations} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-Basic arithmetic functions can be used to build a result for display. Internally, this is done by converting the value to a representation, which is the total number of the smallest usable unit, eg. \nduValue{danish rigsdaler}{1.2.3} is 131 \nduName{danish rigsdaler}{2}.
+Basic arithmetic functions can be used to build a result for display. This is done by converting the value to an internal representation and storing it in a global variable. The first time a variable is used, it is assumed that the value is 0.
-Results can be gathered in two ways, either manually via the \docAuxCommand*{nduMath} macro, or automatically via the \docAuxKey{add to variable} and \docAuxKey{subtract from variable} keys, the latter being especially suitable in tabular contexts.
+Results can be gathered in two ways, either manually via the \docAuxCommand*{nduMath} macro, or automatically via the \docAuxKey{add to variable} and \docAuxKey{subtract from variable} keys, the latter two being especially suitable in tabular contexts.
-\begin{docCommands}[]{
- {
- doc name = nduMath,
- doc parameter = \marg{unit name}\oarg{options}\marg{variable}\marg{operator}\marg{value}
- },
- {
- doc name = nduResult,
- doc parameter = \marg{unit name}\oarg{options}\marg{variable}
- }
-}
+\begin{docCommand}
+ {nduMath}
+ {\marg{unit name}\oarg{options}\marg{variable}\marg{operator}\marg{value}}
-The first arguments of \docAuxCommand*{nduMath} are identical to those of the \refCom{nduValue} macro. In addition, it has \meta{variable} and \meta{operator} (one of \texttt{+ - * /}) arguments. The first time a variable is used, it is assumed that the value is 0. The given value is then converted to its internal representation and stored in the variable. The command does not expand to any output.
+ The first arguments of \docAuxCommand*{nduMath} are identical to those of the \refCom{nduValue} macro. In addition, it has \meta{variable} and \meta{operator} (one of \texttt{+ - * /}) arguments. The command does not expand to any output.
-Note that mixing units in the same variable is not currently supported, and will likely give incorrect results.
+ Note that mixing unit groups in the same variable is not currently supported, and will likely give incorrect results.
-The \docAuxCommand*{nduResult} macro takes a stored \meta{variable} and formats it for display in the same way as \refCom{nduValue}.
-
-Both may be further configured via the \meta{options} in the same way as the other macros.
-
\begin{dispExample*}{
- title=Example usage: \docAuxCommand*{nduMath} and \docAuxCommand*{nduResult} macros
+ title=Example usage: \docAuxCommand*{nduMath} macro
}
\nduMath{danish rigsdaler}{example 1}{+}{0.0.10}
\nduMath{danish rigsdaler}{example 1}{+}{..8}
\nduMath{danish rigsdaler}{example 1}{+}{0.2}
\nduMath{danish rigsdaler}{example 1}{+}{0.5.1}
-\nduResult{danish rigsdaler}{example 1} % = 1.2.3
+% there is no output, the result 1.2.3
+% will be seen in the following example.
\end{dispExample*}
+\end{docCommand}
+
+\begin{docCommand}
+ {nduResult}
+ {\marg{unit name}\oarg{options}\marg{variable}}
+
+ The \docAuxCommand*{nduResult} macro takes a stored \meta{variable} and formats it via \meta{options} for display in the same way as \refCom{nduValue}.
+
\begin{dispExample*}{
title=Example usage: \docAuxCommand*{nduResult} macro
}
-\nduHeader{danish rigsdaler}\\
-\nduResult{danish rigsdaler}[aligned]{example 1}
+\nduResult{danish rigsdaler}{example 1} % = 1.2.3
+
+And let's add an additional 15 skilling:
+\nduMath{danish rigsdaler}{example 1}{+}{0.0.15}
+\nduResult{danish rigsdaler}{example 1} % = 1.3.2
\end{dispExample*}
-\end{docCommands}
+\end{docCommand}
+
\clearpage
-\subsubsection{Options}
+\subsection{Options for Arithmetical Operations}
\begin{docKeys}
[
@@ -304,14 +287,13 @@
},
}
-Setting either of these keys will cause all uses of \docAuxCommand*{nduValue} in the current group to be added to or subtracted from the variable with the given name.
+Setting either of these keys will cause all uses of \docAuxCommand*{nduValue} in the current group to be added to or subtracted from the variable with the given name. It can of course also be set on individual invocations of the command.
\begin{dispExample*}{
title=Example usage: \docAuxKey*{add to variable} key
}
\begingroup
-\nduset{
- cell width=3em,
+\nduKeys{
replace nil with=---,
add to variable=example 2
}
@@ -321,22 +303,12 @@
\midrule
a & \nduValue{danish rigsdaler}{1.2.3} \\
b & \nduValue{danish rigsdaler}{100.1.} \\
+ \midrule
+ total & \nduResult{danish rigsdaler}{example 2} \\ % = 101.3.3
\bottomrule
- total & \nduResult{danish rigsdaler}{example 2} \\ % = 101.3.3
\end{tabular}
\endgroup
\end{dispExample*}
-
-Results are global and remain accessible outside the group:
-\begin{dispExample}
-\nduResult{danish rigsdaler}{example 2}
-\end{dispExample}
-
-Adding an additional 15 \nduName{danish rigsdaler}{2} to the existing result gives:
-\begin{dispExample}
-\nduMath{danish rigsdaler}{example 2}{+}{0.0.15}
-\nduResult{danish rigsdaler}{example 2} % = 101.4.2
-\end{dispExample}
\end{docKeys}
\begin{docKey}
@@ -349,38 +321,151 @@
\begin{dispExample*}{
title=Example usage: \docAuxKey*{normalize} key
}
-100 \nduName{danish rigsdaler}{2} equal
+100 skilling equal
\nduValue{danish rigsdaler}[normalize]{..100} % 1.0.4
\end{dispExample*}
\end{docKey}
+\clearpage
+\section{Tabular Data} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\section{Accessing Information About Units} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+There are a couple of ways to display values in tabular context, centered around explicitly or implicitly setting the \docAuxKey{aligned} key, which causes \docAuxCommand{nduValue} to wrap each segment in a cell of configurable width.
+Additionally, all segments will be included in headers and cells, whether they contain a value or not (provided \docAuxKey{unit depth} allows it). If no value is provided for the segment, and no nil replacement is specified with the \refKey{replace nil with} key, the cell will be empty.
+
\begin{docCommand}
- {nduName}
- {\marg{unit name}\marg{segment}}
- Expands to the name of the the given segment of the unit.
-
- Set by \refKey{segment:name}.
+ {nduHeader}
+ {\marg{unit name}\oarg{options}}
+ Convenient header showing the unit symbols. See \cpageref{units:new} for configuration of symbols.
\end{docCommand}
+\subsection{Options for Tabular Data}
+
+\begin{docKey}
+ {aligned}
+ {}
+ {initially not set}
+
+Causes each value to be wrapped in right-aligned cells of configurable width.
+\end{docKey}
+
+\begin{docKey}
+ {cell widths}
+ {=\meta{length}}
+ {initially \texttt{3em}}
+
+Changes the width of each cell. One may supply a bracketed comma-separated list of widths. If the list is shorter than the number of base units in the group, the last width will be repeated. See page \pageref{example:table:widths} for example.
+\end{docKey}
+
+\begin{docKeys}
+ []
+ {
+ {
+ doc name = set aligned for environment,
+ doc parameter = {=\meta{name}},
+ doc description = {initially not set},
+ },
+ {
+ doc name = tabularray column type,
+ doc parameter = {=\meta{letter}},
+ doc description = {initially not set},
+ },
+ }
+
+ The \docAuxKey{set aligned for environment} key can be set to an environment name, causing \docAuxKey*{aligned} to automatically be set for those enviroments, using \docAuxCommand*{AtBeginEnvironment}. It can be set multiple times, once for each required environment. See page \pageref{example:table:environment} for example.
+
+ The \docAuxKey{tabularray column type} key can be used to create a column type, which automatically wraps the column contents in \docAuxCommand{nduValue}. The column type takes two arguments, a unit group and a set of key values for further configuration. Additionally, the special values \texttt{HEADER}, \texttt{RESULT}, and \texttt{SKIP} will respectively use \docAuxCommand{nduHeader}, \docAuxCommand{nduResult}, and skip the cell. See page \pageref{example:table:tabularray} for example\footnote{Thanks to Yukai Chou for help with \href{https://github.com/lvjr/tabularray}{tabularray} integration.}.
+
+\end{docKeys}
+
+\begin{dispExample*}{
+ title=Example of tabular data using \docAuxKey{set aligned for environment},
+ label=example:table:environment
+}
+\begingroup
+\nduKeys{
+% has been set in this document's preamble:
+% set aligned for environment=tabular,
+ treat zero as nil,
+ replace nil with=---,
+}
+\begin{tabular}{r r}
+ \toprule
+ & \nduHeader{danish rigsdaler} \\
+ \midrule
+ a & \nduValue{danish rigsdaler}{1.2.3} \\
+ b & \nduValue{danish rigsdaler}{100.0.0} \\
+ c & \nduValue{danish rigsdaler}{.1.} \\
+ \bottomrule
+\end{tabular}
+\endgroup
+\end{dispExample*}
+
+\begin{dispExample*}{
+ title=Example usage: \docAuxKey*{cell widths} key,
+ label=example:table:widths
+}
+\begingroup
+\nduKeys{
+ cell widths={5em, 1.5em},
+}
+\begin{tabular}{r r}
+ \toprule
+ & \nduHeader{danish rigsdaler} \\
+ \midrule
+ a & \nduValue{danish rigsdaler}{1.2.3} \\
+ b & \nduValue{danish rigsdaler}{100..} \\
+ c & \nduValue{danish rigsdaler}{.1.} \\
+ \bottomrule
+\end{tabular}
+\endgroup
+\end{dispExample*}
+
+\begin{dispExample*}{
+ title=Example of tabular data using \docAuxKey{tabularray column type},
+ label=example:table:tabularray
+}
+\begingroup
+% has been set in this document's preamble:
+% tabularray column type=U
+\begin{tblr}{
+ r
+ U{danish rigsdaler}{add to variable=table result 1}|
+ U{danish rigsdaler}{add to variable=table result 2}
+}
+ \toprule
+ & HEADER & HEADER\\
+ \midrule
+ a & 1.2.3 & ..15 \\
+ b & 100.0.0 & ..10 \\
+ c & .1. & ..2 \\
+ \midrule
+ total & RESULT & RESULT \\
+ \bottomrule
+\end{tblr}
+\endgroup
+\end{dispExample*}
+
+\clearpage
+\section{Accessing Information About Units} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
\begin{docCommand}
{nduSymbol}
- {\marg{unit name}\marg{segment}}
- Expands to the symbol of the the given segment of the unit.
+ {\marg{unit name}}
+ Expands to the symbol of the given base unit.
- Set by \refKey{segment:symbol}.
+ Set by \refKey{units:symbol}.
\end{docCommand}
\begin{docCommand}
{nduFactor}
- {\marg{unit name}\marg{segment}}
- Expands to the conversion factor of the the given segment of the unit, ie. how many of the underlying segment the given segment consists of.
+ {\marg{unit name}\marg{unit name}}
+ Expands to the conversion between two base units.
+ Set by \refKey{units:factor}.
\begin{dispExample}
-That is, 1 \nduName{danish rigsdaler}{0} consists of
-\nduFactor{danish rigsdaler}{1} \nduName{danish rigsdaler}{1}.
+That is, 1 \nduSymbol{rigsdaler} consists of
+\nduFactor{rigsdaler}{skilling} \nduSymbol{skilling}.
\end{dispExample}
\end{docCommand}
@@ -391,156 +476,66 @@
If the included units are not suitable, more can be created. Pull requests are also welcome at \url{https://github.com/mikkelee/latex-units}.
\begin{docCommand}
- {nduNewUnit}
+ {nduNewBaseUnit}
{\marg{unit name}\marg{key/value pairs}}
-Units can have up to 7 segments, numbered \meta{0-6}. The left-most segment, that is, the \emph{top} or \emph{root} segment, is numbered \texttt{0}.
+Creates a new base unit. It must contain at least a \docAuxKey{symbol}, but a \docAuxKey{factor} is also required for the math functions (see below).
-The numeral part of the below key paths \docAuxKey*{segment 0/} can be any integer up to \texttt{6}, ie. \docAuxKey*{segment 6/}. The internal number of segments is determined by how many name keys are created.
-
-See below for available settings.
-
\end{docCommand}
\begin{docCommand}
- {nduNewMacro}
- {\marg{unit name}\oarg{key/value pairs}\marg{control sequence}}
+ {nduNewUnitGroup}
+ {\marg{unit name}\oarg{key/value pairs}\marg{ordered base units}\oarg{control sequence}}
- It is possible to create shortcut macros for commonly used \meta{unit name}s with optional overriding options.
+ In order for the math functions to work, every base unit in the group must have a conversion path to the right-most base unit, eg. if a unit group consists of base units \texttt{A, B, C}, there must be defined factors for \texttt{B\rightarrow C} and either \texttt{A\rightarrow C} or \texttt{A\rightarrow B}; if only the latter is configured, an attempt to calculate and cache it will be made internally.
- These macros take the same arguments as the full \refCom{nduValue} macro, except without the first argument (ie. the name of the unit).
+ It is possible to create shortcut macros for commonly used unit groups with optional overriding options. These macros take the same arguments as the full \refCom{nduValue} macro, except without the first argument (ie. the name of the unit).
+
+ Including several sub units may make the math results awkward, as the algorithm is greedy.
\begin{dispExample}
-\nduNewMacro{rigsdaler.mark.skilling}
- [unit groups/rigsdaler.mark.skilling/segment 0/symbol={R\textsuperscript{dl}}]
- {myRdl}
-\myRdl{1.2.3}
+\nduNewUnitGroup{my sletdaler}
+ [units/sletdaler/symbol={Sletd.}]
+ {sletdaler, ort, skilling}
+ [\mySldl]
+\mySldl{1.2.3}
\end{dispExample}
\end{docCommand}
-%\begin{docCommand}
-% {nduCommonSymbols}
-% {\marg{key/value pairs}}
-%
-% It is possible to configure commonly used symbols using the form \texttt{\meta{name}=\meta{symbol}}. These will be used as fallbacks if no specific symbol is configured for a segment via \refKey{segment:symbol}.
-%
-%\end{docCommand}
-%
-%\begin{docCommand}
-% {nduCommonFactors}
-% {\marg{key/value pairs}}
-%
-% Not currently implemented.
-%
-%\end{docCommand}
-
\clearpage
-\subsubsection{Options}
+\subsection{Options For Base Units}
\begin{docKey}
- {segment separator}
- {=\meta{...}}
- {initially \texttt{\~{}}}
-
- When displaying a value, this string will be inserted between each segment.
-
-\begin{dispExample}
-\nduValue{danish hartkorn}[
- show=values,
- segment separator=.
- ]
- {1.2.3.4}
-
-\nduValue{danish rigsdaler}
- [segment separator={---}]
- {1.2.3}
-\end{dispExample}
-
-\end{docKey}
-
-\begin{docKey}
- {restrict segment depth}
- {=\meta{integer}}
- {initially no restriction}
-
- When calculating or displaying a value, only the segments up to and including \meta{integer} will be considered.
-
- In this document, the depth has been globally set to \texttt{2} for \docAuxKey*{danish rigsdaler}, but the older historical sub-unit \nduName{danish rigsdaler}{3} can be included by locally setting the depth to \texttt{3} (or indeed not restricting it globally).
-
-\begin{dispExample}
-\nduValue{danish rigsdaler}
- [restrict segment depth=3]
- {1.2.3.4}
-\end{dispExample}
-\end{docKey}
-
-\begin{docKey}
[]
- [doc label=segment:name]
- {segment \meta{n}/name}
- {=\meta{name}}
- {no default, initially undefined}
-
- Gives the proper name of the segment's unit. Used internally to determine how many segments the unit contains.
-
- Can be accessed with by \refCom{nduName}.
-\end{docKey}
-
-\begin{docKey}
- []
- [doc label=segment:symbol]
- {segment \meta{n}/symbol}
+ [doc label=units:symbol]
+ {units/\meta{unit name}/symbol}
{=\meta{symbol}}
- {no default, initially undefined}
+ {}
- Configures a symbol displaying the unit. This is used in \docAuxCommand{nduHeader} and is also available via \docAuxCommand{nduSym} when defining the \refKey{segment:display} (see below).
-
- If none is configured, an attempt to look up a common symbol by its name is made. These can be configured with \refCom{nduCommonSymbols}.
+ Configures a symbol displaying the unit. This is used in \docAuxCommand{nduValue}, \docAuxCommand{nduHeader}, and is also available via \docAuxCommand*{SYMBOL} when defining the \refKey{units:format} (see also \refKey{}).
\end{docKey}
-\begin{docKeys}
- [
- doc parameter = {=\meta{...}},
- ]
- {
- {
- doc name = {segment \meta{n}/prefix},
- doc label = segment:prefix,
- doc description = {initially set to \texttt{\{\}}},
- },
- {
- doc name = {segment \meta{n}/suffix},
- doc label = segment:suffix,
- doc description = {initially set to \texttt{\{~\docAuxCommand*{nduSym}\}}},
- },
- }
-
- When displaying a value, segments will be wrapped between the \meta{prefix} and \meta{suffix}.
-
- The macro \docAuxCommand{nduSym} is available here to show the symbol configured for the segment.
-\end{docKeys}
-
\begin{docKey}
[]
- [doc label=segment:display]
- {segment \meta{n}/display}
- {=\marg{prefix}\marg{suffix}}
+ [doc label=units:format]
+ {units/\meta{unit name}/format}
+ {=\marg{...}}
{}
- Sets both \refKey{segment:prefix} and \refKey{segment:suffix} at the same time.
+ Sets how a given base unit should be formatted for display. If none is given, the general top-level \docAuxKey{format} key is used.
\end{docKey}
\begin{docKey}
[]
- [doc label=segment:factor]
- {segment \meta{n}/factor}
- {=\meta{integer}}
- {no default, initially undefined}
+ [doc label=units:factor]
+ {units/\meta{unit name}/factor}
+ {=\meta{integer} \meta{unit name}}
+ {}
- The conversion factor of a segment is how many of the underlying segment the given segment consists of.
+ The conversion factor of a unit is how many of an underlying unit the given unit consists of. This can be specified multiple times.
- This is used in the math macros, in order to calculate the correct segment values.
+ This is used by the math macros and keys to calculate the sums and products.
Can be accessed via \refCom{nduFactor}.
\end{docKey}
@@ -549,39 +544,22 @@
\begin{dispExample}
\nduValue{danish rigsdaler}
- [segment 1/symbol=Mk.]
+ [units/mark/symbol=Mk.]
{.9.}
\nduValue{danish rigsdaler}
- [segment 0/display={}{~Rigsdaler og}]
+ [units/rigsdaler/format={\VALUE~Rigsdaler og}]
{1.2.3}
\nduValue{danish rigsdaler}[
- segment separator={---},
- segment 0/display={(}{)},
- segment 1/display={[}{]},
- segment 2/display={\{}{\}},
+ unit separator={---},
+ units/rigsdaler/format={(\VALUE)},
+ units/mark/format={[\VALUE]},
+ units/skilling/format={\{\VALUE\}},
]
{1.2.3}
\end{dispExample}
-\begin{docKey}
- {create macro named}
- {=\meta{control sequence}}
- {no default, initially empty}
-
- Units may provide a default shortcut macro, for example the \docValue*{danish rigsdaler} unit configures \docAuxCommand*{rdl}.
-
- This is done via \refCom{nduNewMacro} which describes the arguments of the resulting macros.
-
-\begin{dispExample*}{
- sidebyside,
- righthand width=1.75cm,
-}
-\rdl{2.3.}
-\end{dispExample*}
-\end{docKey}
-
\clearpage
\section{Included Units} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Modified: trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.british.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.british.tex 2023-10-10 20:24:32 UTC (rev 68503)
+++ trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.british.tex 2023-10-10 20:24:53 UTC (rev 68504)
@@ -2,26 +2,27 @@
% https://en.wikipedia.org/wiki/£sd
-\nduBaseUnits{%
- pound sterling={%
- symbol=£,
- display={\nduSym}{},
- },
- shilling={%
- symbol=s,
- factor=20 per pound sterling,
- display={}{\nduSym},
- },
- penny={%
- symbol=d,
- factor=12 per shilling,
- display={}{\nduSym},
- },
+\nduNewBaseUnit { pound~sterling } {
+ symbol = { £ } ,
+ factor = { 20~shilling } ,
+ format = { \SYMBOL\VALUE } ,
}
-\nduAliases{%
- british pound sterling lsd={%
- units=pound sterling.shilling.penny,
- segment separator={. },
- },
+\nduNewBaseUnit { shilling } {
+ symbol = { s } ,
+ factor = { 12~penny } ,
+ format = { \VALUE\SYMBOL } ,
}
+
+\nduNewBaseUnit { penny } {
+ symbol = { d } ,
+ format = { \VALUE\SYMBOL } ,
+}
+
+\nduNewUnitGroup { british~pound~sterling~lsd } [
+ unit~separator = {.~} ,
+] {
+ pound~sterling ,
+ shilling ,
+ penny
+}
Modified: trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.danish.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.danish.tex 2023-10-10 20:24:32 UTC (rev 68503)
+++ trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.danish.tex 2023-10-10 20:24:53 UTC (rev 68504)
@@ -1,122 +1,128 @@
%%% CURRENCY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\nduBaseUnits{%
- rigsbankdaler={%
- symbol=Rbd.,
- },
- rigsdaler={%
- symbol=Rdl.,
- },
- sletdaler={%
- symbol=Sldl.,
- },
- speciedaler={%
- symbol=Spdl.,
- },
- ort={symbol=Ort,factor=4 per rigsdaler},
- mark={%
- symbol=Mk.,
- factor=6 per rigsdaler,
- factor=4 per sletdaler,
- },
- skilling={%
- symbol=Sk.,
- factor=16 per mark,
- factor=24 per ort,
- factor=84 per speciedaler,
- factor=96 per rigsbankdaler,
- },
- hvid={%
- symbol=Hvid,
- factor=3 per skilling,
- },
- penning={%
- symbol=Pg.,
- factor=4 per hvid,
- factor=12 per skilling,
- },
+\nduNewBaseUnit { rigsdaler } {
+ symbol = { Rdl. } ,
+ factor = { 6~mark } ,
}
-\nduAliases{%
- danish rigsbankdaler={%
- units=rigsbankdaler.skilling,
- macro={rbd}{%
- normalize,
- treat zero as nil
- },
- },
- danish rigsdaler={%
- units=rigsdaler.mark.skilling.penning,
- macro={rdl}{%
- normalize,
- treat zero as nil
- },
- },
- danish sletdaler={%
- units=sletdaler.mark.skilling.penning,
- macro={sldl}{%
- normalize,
- treat zero as nil
- },
- },
+\nduNewBaseUnit { rigsbankdaler } {
+ symbol = { Rbdl. } ,
+ symbol = { 96~skilling } ,
}
+\nduNewBaseUnit { rigsdaler specie } {
+ symbol = { Rds. } ,
+ symbol = { 192~skilling } ,
+}
+\nduNewBaseUnit { speciedaler } {
+ symbol = { Spdl. } ,
+ factor = { 84~skilling } ,
+}
+
+\nduNewBaseUnit { sletdaler } {
+ symbol = { Sldl. } ,
+ factor = { 4~mark } ,
+}
+
+\nduNewBaseUnit { ort } {
+ symbol = { O. } ,
+ factor = { 24~skilling } ,
+}
+
+\nduNewBaseUnit { mark } {
+ symbol = { Mk. } ,
+ factor = { 16~skilling } ,
+}
+
+\nduNewBaseUnit { skilling } {
+ symbol = { Sk. } ,
+ factor = { 3~hvid } ,
+}
+
+\nduNewBaseUnit { hvid } {
+ symbol = { Hv. } ,
+ factor = { 4~penning } ,
+}
+
+\nduNewBaseUnit { penning } {
+ symbol = { P. } ,
+}
+
+\nduNewUnitGroup { danish~rigsdaler } {
+ rigsdaler ,
+ mark ,
+ skilling ,
+ hvid ,
+ penning
+}[\rdl]
+
+\nduNewUnitGroup { danish~sletdaler } {
+ sletdaler ,
+ mark ,
+ skilling ,
+ hvid ,
+ penning
+}[\sldl]
+
+\nduNewUnitGroup { danish~rigsbankdaler } {
+ rigsbankdaler ,
+ skilling
+}[\rbdl]
+
+\nduNewUnitGroup { danish~speciedaler } {
+ speciedaler ,
+ skilling
+}[\spdl]
+
%%%% AREA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\nduBaseUnits{%
- tønde={%
- symbol=Td.,
- },
- skæppe={%
- symbol=Skp.,
- factor=8 per tønde,
- },
- fjerdingkar={%
- symbol=Fjk.,
- factor=4 per skæppe,
- },
- album={%
- symbol=Alb.,
- factor=3 per fjerdingkar,
- },
- penning/factor=4 per album, % penning symbols defined under currency
+\nduNewBaseUnit { tønde } {
+ symbol = { Td. } ,
+ factor = { 8~skæppe } ,
}
-\nduAliases{%
- danish hartkorn={%
- units=tønde.skæppe.fjerdingkar.album.penning,
- macro={hartkorn}{%
- normalize,
- treat zero as nil
- },
- },
+\nduNewBaseUnit { skæppe } {
+ symbol = { Sk. } ,
+ factor = { 4~fjerdingkar } ,
}
+\nduNewBaseUnit { fjerdingkar } {
+ symbol = { Fj. } ,
+ factor = { 3~album } ,
+}
+\nduNewBaseUnit { album } {
+ symbol = { Alb. } ,
+ factor = { 4~penning } ,
+}
+
+\nduNewUnitGroup { danish~hartkorn } {
+ tønde,
+ skæppe,
+ fjerdingkar,
+ album,
+ penning
+}[\hartkorn]
+
%%%% WEIGHT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\nduBaseUnits{%
- skippund={%
- symbol=Spd.,
- },
- lispund={%
- symbol=Lpd.,
- factor=20 per skippund,
- },
- skaalpund={%
- symbol=Pd.,
- factor=16 per lispund,
- },
+\nduNewBaseUnit { skippund } {
+ symbol = { Spd. } ,
+ factor = { 20~lispund } ,
}
-\nduAliases{%
- danish pund={%
- units=skippund.lispund.skaalpund,
- macro={pund}{%
- normalize,
- treat zero as nil
- },
- },
+\nduNewBaseUnit { lispund } {
+ symbol = { Lpd. } ,
+ factor = { 16~skålpund } ,
}
+\nduNewBaseUnit { skålpund } {
+ symbol = { Pd. } ,
+}
+
+\nduNewUnitGroup { danish~pund } {
+ skippund,
+ lispund,
+ skålpund
+}
Modified: trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.german.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.german.tex 2023-10-10 20:24:32 UTC (rev 68503)
+++ trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.german.tex 2023-10-10 20:24:53 UTC (rev 68504)
@@ -1,21 +1,21 @@
%%% CURRENCY %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\nduBaseUnits{%
- reichsthaler={%
- symbol=Rthl., % \mufi{reichtalold}
- },
- groschen={%
- symbol=Gr., % \mufi{grosch}
- factor=30 per reichsthaler,
- },
- pfennig={%
- symbol=Pf., % \mufi{20B0}
- factor=12 per groschen,
- },
+\nduNewBaseUnit { reichsthaler } {
+ symbol = { Rthl. } ,
+ factor = { 30~groschen } ,
}
-\nduAliases{%
- german reichsthaler={%
- units=reichsthaler.groschen.pfennig,
- },
+\nduNewBaseUnit { groschen } {
+ symbol = { Gr. } ,
+ factor = { 12~pfennig } ,
}
+
+\nduNewBaseUnit { pfennig } {
+ symbol = { Pf. } ,
+}
+
+\nduNewUnitGroup { german~reichsthaler } {
+ reichsthaler ,
+ groschen ,
+ pfennig
+}
\ No newline at end of file
Modified: trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.sty 2023-10-10 20:24:32 UTC (rev 68503)
+++ trunk/Master/texmf-dist/tex/latex/non-decimal-units/non-decimal-units.sty 2023-10-10 20:24:53 UTC (rev 68504)
@@ -1,598 +1,798 @@
-\ProvidesPackage{non-decimal-units}[2023/09/27 Macros for displaying and manipulating historical non-decimal units]
+\RequirePackage{expl3}
+\ProvidesExplPackage{non-decimal-units}{2023/10/10}{1.0}{Macros for displaying and manipulating historical non-decimal units}
% License: CC-BY-SA 4.0
% Author: Mikkel Eide Eriksen <mikkel.eriksen at gmail.com>
-\RequirePackage{pgfkeys}
-\RequirePackage{pgfopts}
-\RequirePackage{bigintcalc}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Key setup
+%
-\RequirePackage{etoolbox}
-\RequirePackage{ifthen}
+\keys_define:nn { non-decimal-units }
+{
+ % nil/zero
+ replace~nil~with .tl_set:N = \l_ndu_replace_nil_with_tl ,
+ treat~zero~as~nil .bool_set:N = \l_ndu_treat_zero_as_nil_bool ,
+ treat~zero~as~nil .default:n = true ,
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % formatting
+ unit~separator .tl_set:N = \l_ndu_unit_separator_tl ,
+ unit~separator .default:n = { \nobreakspace } ,
+ default~format .tl_set:N = \l_ndu_default_format_tl ,
+ default~format .default:n = { \VALUE\nobreakspace\SYMBOL } ,
+ display .choice: ,
+ display .choices:nn =
+ { values~only, symbols~only, formatted, numprint }
+ { \tl_set_eq:NN \l_ndu_display_choice_tl \l_keys_choice_tl } ,
+ display .default:n = { formatted } ,
+ unit~depth .tl_set:N = \l_ndu_unit_depth_tl ,
+ use~numprint .bool_set:N = \l_ndu_use_numprint_bool ,
+ use~numprint .default:n = true ,
-\pgfkeys{/handlers/.store in cs/.code=\pgfkeysalso{%
- \pgfkeyscurrentpath/.code=\csdef{#1}{##1}}%
+ % tabular alignment
+ aligned .bool_set:N = \l_ndu_aligned_bool ,
+ aligned .default:n = true ,
+ cell~widths .code:n = {
+ \seq_set_from_clist:Nn \l_ndu_cell_widths_seq {#1}
+ } ,
+ cell~widths .default:n = 3em ,
+
+ % math
+ normalize .bool_set:N = \l_ndu_normalize_bool ,
+ normalize .default:n = true ,
+ current~variable .tl_set:N = \l_ndu_current_variable_tl ,
+ current~operator .tl_set:N = \l_ndu_current_operator_tl ,
+ add~to~variable .meta:n = {
+ current~variable = {#1} ,
+ current~operator = {+}
+ } ,
+ subtract~from~variable .meta:n = {
+ current~variable = {#1} ,
+ current~operator = {-}
+ } ,
+
+ % environments
+ set~aligned~for~environment .code = {
+ \AtBeginEnvironment{#1}{\nduKeys{aligned}}
+ } ,
}
-\def\nduset{\pgfqkeys{/ndu}}
+\NewDocumentCommand { \nduKeys } { m } {
+ \keys_set:nn { non-decimal-units } { #1 }
+}
-\newif\ifndushowvalues
-\newif\ifndushowaffixes
-\newif\ifndutreatzeroasnil
-\newif\ifndualigned
-\ndushowvaluestrue
-\ndushowaffixestrue
-\newif\ifndunormalize
+% set some defaults
+\keys_set:nn { non-decimal-units } {
+ unit~separator,
+ default~format,
+ display,
+ cell~widths,
+}
-\newcounter{autorepr}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Errors
+%
-\gdef\ndu at nextdelim{}%
-\gdef\ndu at delim{}%
+\msg_new:nnnn
+{ non-decimal-units } { missing-base-unit }
+{ No ~ base ~ unit ~ exists ~ named ~ #1 }
+{ You ~ will ~ need ~ to ~ add ~ it ~ with ~ nduNewBaseUnit. }
+%
-\nduset{%
- base units/.is family,
- base units/.unknown/.code={%
- \expandafter\nduBuildBaseUnitKeys\expandafter{\pgfkeyscurrentname}{#1}%
- },
- unit groups/.is family,
- unit groups/.unknown/.code={%
- \expandafter\nduBuildUnitGroupKeys\expandafter{\pgfkeyscurrentname}%
- },
- aliases/.is family,
- aliases/.unknown/.code={%
- \expandafter\nduBuildAliasKeys\expandafter{\pgfkeyscurrentname}{#1}%
- },
- show/.is choice,
- show/values/.code={\ndushowvaluestrue\ndushowaffixesfalse},
- show/values and symbols/.code={\ndushowvaluestrue\ndushowaffixestrue},
- show/symbols/.code={\ndushowvaluesfalse\ndushowaffixestrue},
- show=values and symbols,
- cell width/.initial=5em,
- add to variable/.code={%
- \csdef{ndu at current@variable}{#1}%
- \csdef{ndu at current@operator}{+}%
- },
- subtract from variable/.code={%
- \csdef{ndu at current@variable}{#1}%
- \csdef{ndu at current@operator}{-}%
- },
- replace nil with/.store in cs=ndu at nil@replacement,
- treat zero as nil/.is if=ndutreatzeroasnil,
- treat zero as nil=false,
- normalize/.is if=ndunormalize,
- normalize=false,
- segment separator/.initial={~},
- aligned/.is if=ndualigned,
- aligned=false,
- set aligned for environment/.code={%
- \AtBeginEnvironment{#1}{\nduset{aligned}}%
- },
-}
+\msg_new:nnnn
+{ non-decimal-units } { missing-unit-group }
+{ No ~ unit ~ group ~ exists ~ named ~ #1 }
+{ You ~ will ~ need ~ to ~ add ~ it ~ with ~ nduNewUnitGroup. }
-\newcommand\nduBuildBaseUnitKeys[2]{%
- \nduset{%
- base units/#1/.is family,base units/#1,
- symbol/.initial={#1},
- factor/.style args={##1 per ##2}{%
- /ndu/base units/##2/factors/#1/.initial=##1,
- },
- prefix/.initial={},
- suffix/.initial={~\nduSym},
- display/.style 2 args={%
- prefix={##1},
- suffix={##2},
- },
- #2,
- }%
-}
+\msg_new:nnnn
+{ non-decimal-units } { missing-factor }
+{ No ~ conversion ~ factor ~ exists ~ between ~ #1 ~ and ~ #2 }
+{ You ~ will ~ need ~ to ~ add ~ it ~ when ~ creating ~ the ~ base ~ unit ~ or ~ via ~ nduKeys. }
-\newcommand\nduBaseUnits[1]{%
- \nduset{%
- base units,#1,
- }%
-}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Unit setup
+%
-\newcommand\nduBuildUnitGroupKeys[1]{% called by .unknown handler
- \nduset{%
- unit groups/#1/.search also={/ndu},
- unit groups/#1/.is family,unit groups/#1,
- segment separator/.link=/ndu/segment separator,
- segment depth/.initial=-1,
- update segment depth/.code={%
- \ifnum##1>\pgfkeysvalueof{/ndu/unit groups/#1/segment depth}%
- \nduset{%
- unit groups/#1/segment depth=##1,
- }%
- \fi%
- },
- restrict segment depth/.link=/ndu/unit groups/#1/segment depth,
- }%
- \nduBuildSegments{#1}{#1}%
+\NewDocumentCommand { \nduNewBaseUnit } { m m } {
+ \prop_clear_new:c { l_ndu_factors_#1_prop }
+ \keys_define:nn { non-decimal-units / units / #1 } {
+ factor .code = {
+ \regex_extract_once:nnN { (\d+)\ (\D+) } { ##1 } \l_tmpa_seq
+ \prop_put:cxx { l_ndu_factors_#1_prop } { \seq_item:Nn \l_tmpa_seq 3 } { \seq_item:Nn \l_tmpa_seq 2 }
+ } ,
+ symbol .tl_set:c = { l_ndu_symbol_#1_tl } ,
+ format .tl_set:c = { l_ndu_format_#1_tl } ,
+ }
+ \keys_set:nn { non-decimal-units / units / #1 } { #2 }
}
-\newcommand\nduUnitGroups[1]{%
- \nduset{%
- unit groups,#1,
- }%
-}
+\NewDocumentCommand { \nduNewUnitGroup } { m o m o }
+{
+ \seq_set_from_clist:cn { l_ndu_group_#1_seq } {#3}
-\newcommand\nduBuildAliasKeys[2]{% called by .unknown handler
- \nduset{%
- aliases/#1/.is family,aliases/#1,
- units/.code={%
- % create unit group and set search path
- \pgfkeys{%
- /ndu/unit groups/##1,
- /ndu/aliases/#1/.search also={/ndu/unit groups/##1},
- /ndu/aliases/#1/unit group/.initial=##1,
- }%
- },
- macro/.code 2 args={%
- \nduNewMacro{#1}[##2]{##1}%
- },
- #2,
- }%
-}
+ % set base unit to rightmost item
+ \seq_get_right:cN { l_ndu_group_#1_seq } \l_tmpa_tl
+ \tl_set_eq:cN { l_ndu_base_unit_#1_tl } \l_tmpa_tl
-\newcommand\nduAliases[1]{%
- \nduset{%
- aliases,#1,
- }%
-}
+ % store keys for unit group
+ \tl_clear_new:c { l_ndu_options_#1_tl }
+ \IfValueT {#2} {
+ \tl_set:cn { l_ndu_options_#1_tl } {#2}
+ }
-\NewDocumentCommand\nduBuildSegments{ m > { \SplitArgument { 6 } { . } } m }{%
- \nduBuildSegments at internal{#1}#2%
+ % optionally create macro
+ \IfValueT {#4} {
+ \NewDocumentCommand { #4 } { O{} m } {
+ \group_begin:
+ \IfValueTF {#2} {
+ \nduValue{#1}[#2,##1]{##2}
+ }
+ {
+ \nduValue{#1}[##1]{##2}
+ }
+ \group_end:
+ }
+ }
}
-\newcommand\nduBuildSegments at internal[8]{%
- \nduNewUnit at segment{#1}{0}{#2}{#1}%
- \nduNewUnit at segment{#1}{1}{#3}{#2}%
- \nduNewUnit at segment{#1}{2}{#4}{#3}%
- \nduNewUnit at segment{#1}{3}{#5}{#4}%
- \nduNewUnit at segment{#1}{4}{#6}{#5}%
- \nduNewUnit at segment{#1}{5}{#7}{#6}%
- \nduNewUnit at segment{#1}{6}{#8}{#7}%
-}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Conversion factor initialization and access
+%
-\newcommand\nduNewUnit at segment[4]{%
- \IfValueT{#3}{%
- \nduset{
- unit groups/#1/segment #2/.is family,unit groups/#1/segment #2,
- name/.initial=#3,
- symbol/.link=/ndu/base units/#3/symbol,
- prefix/.link=/ndu/base units/#3/prefix,
- suffix/.link=/ndu/base units/#3/suffix,
- display/.style 2 args={%
- segment #2/prefix={##1}, % why is the segment needed here ???
- segment #2/suffix={##2},
- },
- factor/.link=/ndu/base units/#4/factors/#3,
- }%
- \nduset{%
- unit groups/#1/update segment depth=#2,
- }%
- }%
+\cs_new_protected:Nn \ndu_get_factor:Nnn
+{
+ % parameters
+ % #1: output result (int)
+ % #2: from unit (tl)
+ % #3: to unit (tl)
+ \tl_if_exist:cF { l_ndu_factors_#2_prop }
+ {
+ \msg_error:nnn { non-decimal-units } { missing-base-unit } { #2 }
+ }
+ \tl_if_exist:cF { l_ndu_factors_#3_prop }
+ {
+ \msg_error:nnn { non-decimal-units } { missing-base-unit } { #3 }
+ }
+ \str_if_eq:nnTF {#2} {#3}
+ {
+ \int_set:Nn #1 { 1 }
+ }
+ {
+ \prop_if_in:cnTF { l_ndu_factors_#2_prop } { #3 }
+ {
+ \prop_get:cnN { l_ndu_factors_#2_prop } { #3 } \l_tmpa_tl
+ \int_set:Nn #1 { \l_tmpa_tl }
+ }{
+ \int_zero_new:N \l__ndu_factor_product_int
+ \prop_map_inline:cn { l_ndu_factors_#2_prop } {
+ \str_if_eq:nnF {#3} {##1}
+ {
+ \int_zero_new:N \l__ndu_sub_factor_int
+ \ndu_get_factor:Nnn \l__ndu_sub_factor_int { ##1 } { #3 }
+ \int_set:Nn \l__ndu_factor_product_int { ##2 * \l__ndu_sub_factor_int }
+ \int_set:Nn #1 { \l__ndu_factor_product_int }
+ \prop_put:cnx { l_ndu_factors_#2_prop } { #3 } { \int_use:N \l__ndu_factor_product_int }
+ }
+ }
+ }
+ }
}
+\cs_generate_variant:Nn \ndu_get_factor:Nnn {
+ NnV,
+ NVV
+}
-\NewDocumentCommand\nduNewMacro{ m O{} m }{%
- \expandafter\NewDocumentCommand\csname#3\endcsname { O{} m } {%
- \begingroup%
- \nduset{unit groups/#1,#2}%
- \nduValue{#1}[##1]{##2}%
- \endgroup%
- }%
+% ndu_super_factors (call from nduNewUnitGroup)
+
+\NewDocumentCommand \nduFactor { m m } {
+ \ndu_get_factor:Nnn \l_tmpa_int { #1 } { #2 }
+ \int_use:N \l_tmpa_int
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Converting from/to representation
+%
-\newcommand\nduName[2]{%
- \pgfkeysifdefined{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/name}{%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/name}%
- }{%
- \PackageError{non-decimal-units}{No name defined for "\nduAliasOrGroup{#1}" segment #2}{}%
- \nduNameMissing%
- }%
-}
+\cs_new_protected:Nn \ndu_repr_to_seq:NNNNN
+{
+ % parameters
+ % #1: output result (seq)
+ % #2: unit group (seq)
+ % #3: base unit (tl)
+ % #4: value (int)
+ % #5: unit (tl)
+ \seq_clear:N #1
-\newcommand\nduSymbol[2]{%
- \pgfkeysifdefined{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/symbol}{%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/symbol}%
- }{%
- \PackageError{non-decimal-units}{No symbol defined for "\nduAliasOrGroup{#1}" segment #2 (\nduName{#1}{#2})}{}%
- \nduSymbolMissing%
- }%
-}
+ \int_zero_new:N \l__ndu_remainder_int
-\newcommand\nduPrefix[2]{%
- \pgfkeysifdefined{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/prefix}{%
- \gdef\nduSym{\nduSymbol{\nduAliasOrGroup{#1}}{#2}}%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/prefix}%
- }{%
- \PackageError{non-decimal-units}{No prefix defined for "\nduAliasOrGroup{#1}" segment #2 (\nduName{#1}{#2})}{}%
- \nduPrefixMissing%
- }%
-}
+ % initial value * base factor
+ \ndu_get_factor:NVV \l_tmpa_int { #5 } { #3 }
+ \int_set:Nn \l__ndu_remainder_int { #4 * \l_tmpa_int }
-\newcommand\nduSuffix[2]{%
- \pgfkeysifdefined{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/suffix}{%
- \gdef\nduSym{\nduSymbol{\nduAliasOrGroup{#1}}{#2}}%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/suffix}%
- }{%
- \PackageError{non-decimal-units}{No suffix defined for "\nduAliasOrGroup{#1}" segment #2 (\nduName{#1}{#2})}{}%
- \nduSuffixMissing%
- }%
-}
+ % for unit in units:
+ \seq_map_inline:Nn #2
+ {
+ \int_zero_new:N \l__ndu_factor_int
+ \int_zero_new:N \l__ndu_sum_int
-\newcommand\nduFactor[2]{%
- \pgfkeysifdefined{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/factor}{%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/segment #2/factor}%
- }{%
- % Having a PackageError here breaks bigintcalc.
- \nduFactorMissing@#1@#2%
- }%
-}
+ \ndu_get_factor:NnV \l__ndu_factor_int { ##1 } { #3 }
-\newcommand\ifnduFactorDefined[4]{%
- \pgfkeysifdefined{/ndu/base units/\nduName{#1}{\the\numexpr#2-1\relax}/factors/\nduName{#1}{#2}}{%
- #3%
- }{%
- #4%
- }%
+ % while (remainder >= factor_to_base):
+ \int_while_do:nn {\l__ndu_remainder_int >= \l__ndu_factor_int} {
+ % remainder -= factor_to_base
+ \int_sub:Nn \l__ndu_remainder_int \l__ndu_factor_int
+ % result[i] += 1
+ \int_incr:N \l__ndu_sum_int
+ }
+ \seq_put_right:Nx #1 {\int_use:N \l__ndu_sum_int}
+
+ % stop when we hit the desired unit depth
+ \str_if_eq:NNT {##1} {#5} {
+ \seq_map_break:
+ }
+ }
}
-
-\newcommand\nduNamedFactor[2]{%
- \pgfkeysifdefined{/ndu/base units/\nduAliasOrGroup{#1}/factors/#2}{%
- \pgfkeysvalueof{/ndu/base units/\nduAliasOrGroup{#1}/factors/#2}%
- }{%
- % Having a PackageError here breaks bigintcalc.
- \nduFactorMissing@#1@#2%
- }%
+\cs_generate_variant:Nn \ndu_repr_to_seq:NNNNN {
+ NccNc,
+ Ncccc
}
-\newcommand\nduSegmentDepth[1]{%
- \pgfkeysifdefined{/ndu/unit groups/\nduAliasOrGroup{#1}/restrict segment depth}{%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/restrict segment depth}%
- }{%
- \pgfkeysvalueof{/ndu/unit groups/\nduAliasOrGroup{#1}/segment depth}%
- }%
-}
+\cs_new_protected:Nn \ndu_repr_to_seq:NnN
+{
+ % parameters
+ % #1: output result (int)
+ % #2: unit group name (tl)
+ % #3: value (int)
+ \ndu_repr_to_seq:NccNc
+ #1
+ { l_ndu_group_#2_seq }
+ { l_ndu_base_unit_#2_tl }
+ #3
+ { l_ndu_base_unit_#2_tl }
-\newcommand\nduAliasOrGroup[1]{%
- \pgfkeysifdefined{/ndu/aliases/#1/unit group}{%
- \pgfkeysvalueof{/ndu/aliases/#1/unit group}%
- }{%
- #1%
- }%
}
+\cs_generate_variant:Nn \ndu_repr_to_seq:NnN {
+ Nnc
+}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\newcommand\ndu at if@depth at at@least[3]{%
- \ifnum#2>\nduSegmentDepth{#1}%
- \relax%
- \else%
- #3%
- \fi%
+\cs_new_protected:Nn \ndu_seq_to_repr:NNNN
+{
+ % parameters
+ % #1: output result (int)
+ % #2: unit group (seq)
+ % #3: base unit (tl)
+ % #4: input (seq)
+ \int_zero:N #1
+
+ \seq_map_indexed_inline:Nn #2
+ {
+ \tl_set:Nx \l__ndu_value_tl { \seq_item:Nn #4 {##1} }
+ \tl_if_blank:VF \l__ndu_value_tl {
+ \ndu_get_factor:NnV \l_tmpa_int { ##2 } { #3 }
+ \int_add:Nn #1 { \l__ndu_value_tl * \l_tmpa_int }
+ }
+ }
}
+\cs_generate_variant:Nn \ndu_seq_to_repr:NNNN {
+ NccN
+}
-\newcommand\ndu at nil@helper[4]{%
- \IfValueTF{#1}{%
- \ifblank{#1}{%
- \ifcsvoid{ndu at nil@replacement}{}{#2\ndu at nil@replacement{}#4}%
- }{%
- \ifndutreatzeroasnil%
- \expandafter\ifnum#1=0
- \ifcsvoid{ndu at nil@replacement}{}{#2\csuse{ndu at nil@replacement}#4}%
- \else%
- #2#3#4%
- \fi%
- \else%
- #2#3#4%
- \fi%
- }%
- }{%
- \ifcsvoid{ndu at nil@replacement}{}{#2\csuse{ndu at nil@replacement}#4}%
- }%
+\cs_new_protected:Nn \ndu_seq_to_repr:NnN
+{
+ % parameters
+ % #1: output result (seq)
+ % #2: unit group name (tl)
+ % #3: values (seq)
+ \ndu_seq_to_repr:NccN
+ #1
+ { l_ndu_group_#2_seq }
+ { l_ndu_base_unit_#2_tl }
+ #3
}
+\cs_generate_variant:Nn \ndu_seq_to_repr:NnN {
+ Nnc
+}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Formatting values
+%
-\NewDocumentCommand\nduValue{ m O{} m }{%
- \nduValue at unitgroup{\nduAliasOrGroup{#1}}[#2]{#3}%
-}
+\prg_new_protected_conditional:Nnn \ndu_if_not_nil_or_zero:Nn {T,TF}
+{
+ % parameters
+ % #1: output result (tl)
+ % #2: value (tl)
+ % returns T if value should be output, otherwise F
-\NewDocumentCommand\nduValue at unitgroup{ m O{} m }{%
- % #1 = unit group
- % #2 = options
- % #3 = values joined by .
- \nduset{unit groups/#1}%
- \begingroup%
- \nduset{unit groups/#1,#2}%
- \ifndualigned%
- \nduAlignedValue at entry{#1}{#3}%
- \else%
- \nduFormatValue at entry{#1}{#3}%
- \fi%
- \endgroup%
- \ifcsvoid{ndu at current@variable}{}{%
- \nduMath{#1}{\ndu at current@variable}{\ndu at current@operator}{#3}%
- }%
+ \tl_if_blank:nTF {#2}
+ {
+ % only output something if we are replacing nil
+ \tl_if_empty:NTF {\l_ndu_replace_nil_with_tl}
+ {
+ \prg_return_false:
+ }
+ {
+ \tl_set_eq:NN #1 \l_ndu_replace_nil_with_tl
+ \prg_return_true:
+ }
+ }
+ {
+ \bool_if:nTF {
+ \l_ndu_treat_zero_as_nil_bool &&
+ \int_compare_p:n { #2 = 0 }
+ } {
+ % only output something if we are replacing nil
+ \tl_if_empty:NTF {\l_ndu_replace_nil_with_tl}
+ {
+ \prg_return_false:
+ }
+ {
+ \tl_set_eq:NN #1 \l_ndu_replace_nil_with_tl
+ \prg_return_true:
+ }
+ }
+ {
+ % else output directly
+ \tl_set:Nx #1 { #2 }
+ \prg_return_true:
+ }
+ }
}
+\prg_generate_conditional_variant:Nnn \ndu_if_not_nil_or_zero:Nn
+{
+ Nx
+}
+{
+ T,TF
+}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% placeholder tokens for \ndu_format_display_helper
+\tl_new:N \VALUE
+\tl_new:N \SYMBOL
-\newcommand\nduFormatSegment[3]{%
- % #1 = unit group
- % #2 = segment
- % #3 = value
- %\csshow{nduSym}%
- \ndu at nil@helper{#3}{%
- \ndu at delim%
- \ifndushowaffixes\nduPrefix{#1}{#2}\fi%
- \edef\ndu at delim{\ndu at nextdelim}%
- }{%
- \ifndushowvalues#3\fi%
- }{%
- \ifndushowaffixes\nduSuffix{#1}{#2}\fi%
- }%
-}
+\tl_const:Nn \c__ndu_values_only_tl { values~only }
+\tl_const:Nn \c__ndu_symbols_only_tl { symbols~only }
+\tl_const:Nn \c__ndu_formatted_tl { formatted }
+\tl_const:Nn \c__ndu_numprint_tl { numprint }
-\newcommand\nduFormatValue at helper[3]{%
- \ndu at if@depth at at@least{#1}{#2}{%
- \nduFormatSegment{#1}{#2}{#3}%
- }%
+\cs_new_protected:Nn \ndu__numprint_helper:nn
+{
+ \numprint[#1]{#2}
}
-\newcommand\nduFormatValue at internal[8]{%
- % #1 = unit group
- % #2-8 = values
- \edef\ndu at nextdelim{\pgfkeysvalueof{/ndu/unit groups/#1/segment separator}}%
- \edef\ndu at delim{}%
- \nduFormatValue at helper{#1}{0}{#2}%
- \nduFormatValue at helper{#1}{1}{#3}%
- \nduFormatValue at helper{#1}{2}{#4}%
- \nduFormatValue at helper{#1}{3}{#5}%
- \nduFormatValue at helper{#1}{4}{#6}%
- \nduFormatValue at helper{#1}{5}{#7}%
- \nduFormatValue at helper{#1}{6}{#8}%
+\cs_new_protected:Nn \ndu_format_display_helper:Nnnn
+{
+ % parameters
+ % #1: output result (tl)
+ % #2: format (tl)
+ % #3: symbol (tl)
+ % #4: value (int)
+ \tl_case:Nn \l_ndu_display_choice_tl {
+ \c__ndu_symbols_only_tl {
+ \tl_set:Nn #1 { #3 }
+ }
+ \c__ndu_values_only_tl {
+ \tl_set:Nn #1 {
+ \bool_if:NTF \l_ndu_use_numprint_bool
+ { \ndu__numprint_helper:nn {} {#4} }
+ { #4 }
+ }
+ }
+ \c__ndu_formatted_tl {
+ \tl_set:Nn #1 { #2 }
+ \tl_replace_all:Nnn #1 { \SYMBOL } { #3 }
+ \tl_replace_all:Nnn #1 { \VALUE } {
+ \bool_if:NTF \l_ndu_use_numprint_bool
+ { \ndu__numprint_helper:nn {} {#4} }
+ { #4 }
+ }
+ }
+ \c__ndu_numprint_tl {
+ \tl_set:Nn #1 { \ndu__numprint_helper:nn {#3} {#4} }
+ }
+ }
}
-
-\NewDocumentCommand\nduFormatValue at entry{ m > { \SplitArgument { 6 } { . } } m }{%
- % #1 = unit group
- % #2 = values joined by .
- \ifndunormalize%
- \stepcounter{autorepr}%
- \nduConvertToRepr at internal{#1}{autorepr\arabic{autorepr}}#2%
- \nduResult{#1}{autorepr\arabic{autorepr}}%
- \else%
- \nduFormatValue at internal{#1}#2%
- \fi%
+\cs_generate_variant:Nn \ndu_format_display_helper:Nnnn {
+ NVVn,
+ NVVx
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\cs_new_protected:Nn \ndu_format_values:NNNN
+{
+ % parameters
+ % #1: output result (tl)
+ % #2: unit group (seq)
+ % #3: values (seq)
+ % #4: separator (tl)
+ \seq_clear:N #1
+ \seq_clear_new:N \l__ndu_formatted_segments_seq
-\newcommand*{\ndu at minwidthbox}[2]{%
- \makebox[{\ifdim#1<\width\width\else#1\fi}][r]{%
- #2%
- }%
-}
+ \seq_map_indexed_inline:Nn #3
+ {
+ \tl_clear_new:N \l__ndu_formatted_segment
+ \tl_clear_new:N \l__ndu_symbol_tl
+ \tl_set:Nx \l__ndu_symbol_tl { \tl_use:c { l_ndu_symbol_ \seq_item:Nn #2 {##1} _tl } }
-\newcommand\nduAlignedHeader at helper[2]{%
- \ndu at if@depth at at@least{#1}{#2}{\ndu at minwidthbox{\pgfkeysvalueof{/ndu/cell width}}{%
- \nduSymbol{#1}{#2}%
- }}%
-}
+ \tl_clear_new:N \l__ndu_format_tl
+ \tl_if_empty:cTF { l_ndu_format_ \seq_item:Nn #2 {##1} _tl }
+ {
+ \tl_set_eq:NN \l__ndu_format_tl \l_ndu_default_format_tl
+ }
+ {
+ \tl_set_eq:Nc \l__ndu_format_tl { l_ndu_format_ \seq_item:Nn #2 {##1} _tl }
+ }
-\newcommand\nduAlignedValue at helper[3]{%
- \ndu at if@depth at at@least{#1}{#2}{\ndu at minwidthbox{\pgfkeysvalueof{/ndu/cell width}}{\nduFormatSegment{#1}{#2}{#3}}}%
-}
+ \ndu_if_not_nil_or_zero:NnT \l_tmpa_tl { ##2 }
+ {
+ \ndu_format_display_helper:NVVx
+ \l__ndu_formatted_segment
+ \l__ndu_format_tl
+ \l__ndu_symbol_tl
+ { \l_tmpa_tl }
+ \seq_put_right:Nx \l__ndu_formatted_segments_seq \l__ndu_formatted_segment
+ }
-\newcommand\nduAlignedValue at internal[8]{%
- % #1 = unit group
- % #2-8 = values
- \nduAlignedValue at helper{#1}{0}{#2}%
- \nduAlignedValue at helper{#1}{1}{#3}%
- \nduAlignedValue at helper{#1}{2}{#4}%
- \nduAlignedValue at helper{#1}{3}{#5}%
- \nduAlignedValue at helper{#1}{4}{#6}%
- \nduAlignedValue at helper{#1}{5}{#7}%
- \nduAlignedValue at helper{#1}{6}{#8}%
+ % stop when we hit the desired unit depth
+ \tl_set:Nx \l__ndu_unit_tl { \seq_item:Nn #2 {##1} }
+ \tl_if_eq:NNT \l__ndu_unit_tl \l_ndu_unit_depth_tl
+ {
+ \seq_map_break:
+ }
+ }
+ \tl_set:Nn #1 { \seq_use:Nn {\l__ndu_formatted_segments_seq} {#4} }
}
+\cs_generate_variant:Nn \ndu_format_values:NNNN {
+ NcNN
+}
-\NewDocumentCommand\nduHeader{ m O{} }{%
- \nduHeader at unitgroup{\nduAliasOrGroup{#1}}[#2]%
+
+\prg_new_protected_conditional:Nnn \ndu_if_valid_dim:n {F}
+{
+ % adapted from https://tex.stackexchange.com/questions/498976/testing-for-a-length
+ \regex_match:nnTF
+ { \A [+\-]? ((\d+(\.\d*)?)|(\.\d+)) \s* (pt|pc|in|bp|cm|mm|dd|cc|sp|ex|em) \Z}
+ { #1 } % test string
+ { \prg_return_true: }
+ { \prg_return_false: }
}
+\prg_generate_conditional_variant:Nnn \ndu_if_valid_dim:n
+{
+ V
+}
+{
+ F
+}
-\NewDocumentCommand\nduHeader at unitgroup{ m O{} }{%
- \nduset{unit groups/#1}%
- \begingroup%
- \nduset{unit groups/#1,#2}%
- \nduAlignedHeader at helper{#1}{0}%
- \nduAlignedHeader at helper{#1}{1}%
- \nduAlignedHeader at helper{#1}{2}%
- \nduAlignedHeader at helper{#1}{3}%
- \nduAlignedHeader at helper{#1}{4}%
- \nduAlignedHeader at helper{#1}{5}%
- \nduAlignedHeader at helper{#1}{6}%
- \endgroup%
+
+\cs_new_protected:Nn \ndu_make_box:Nnn
+{
+ % parameter
+ % #1: output result (box)
+ % #2: contents (tl)
+ % #3: box index
+ \box_clear_new:N #1
+ \dim_zero_new:N \l__ndu_cell_width_dim
+ \tl_set:Nx \l_tmpa_tl { \seq_item:Nn \l_ndu_cell_widths_seq { #3 } }
+ \ndu_if_valid_dim:VF \l_tmpa_tl
+ {
+ \seq_get_right:NN \l_ndu_cell_widths_seq \l_tmpa_tl
+ }
+ \dim_set:Nn \l__ndu_cell_width_dim { \l_tmpa_tl }
+ \hbox_set_to_wd:Nnn #1 { \l__ndu_cell_width_dim } { #2 }
}
+\cs_generate_variant:Nn \ndu_make_box:Nnn {
+ cnn
+}
-\NewDocumentCommand\nduAlignedValue at entry{ m > { \SplitArgument { 6 } { . } } m }{%
- % #1 = unit group
- % #2 = values joined by .
- \begingroup%
- \nduset{show=values}%
- \ifndunormalize%
- \stepcounter{autorepr}%
- \nduConvertToRepr at internal{#1}{autorepr\arabic{autorepr}}#2%
- \nduResult{#1}[aligned]{autorepr\arabic{autorepr}}%
- \else%
- \nduAlignedValue at internal{#1}#2%
- \fi%
- \endgroup%
+
+\cs_new_protected:Nn \ndu_format_values_aligned:NNN
+{
+ % parameters
+ % #1: output result (tl)
+ % #2: unit group (seq)
+ % #3: values (seq)
+ \tl_set:Nn #1 { \leavevmode }
+
+ \seq_map_indexed_inline:Nn #2
+ {
+ \tl_clear_new:N \l__ndu_value_tl
+ \ndu_if_not_nil_or_zero:NxTF \l__ndu_value_tl { \seq_item:Nn #3 ##1 }
+ {
+ \ndu_make_box:cnn
+ { l__ndu_cell_ \int_to_alph:n {##1} _box }
+ { \hfill \tl_use:N \l__ndu_value_tl }
+ { ##1 }
+ }
+ {
+ \ndu_make_box:cnn
+ { l__ndu_cell_ \int_to_alph:n {##1} _box }
+ { \hfill }
+ { ##1 }
+ }
+
+ \tl_put_right:Nx #1 { \box_use:c { l__ndu_cell_ \int_to_alph:n {##1} _box } }
+
+ % stop when we hit the desired unit depth
+ \tl_if_eq:NnT \l_ndu_unit_depth_tl {##2}
+ {
+ \seq_map_break:
+ }
+ }
}
+\cs_generate_variant:Nn \ndu_format_values_aligned:NNN {
+ NcN
+}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% User commands
+%
-\newcommand\ndu at val@or at zero[1]{%
- \IfValueTF{#1}{%
- \ifblank{#1}{%
- 0%
- }{%
- #1%
- }%
- }{%
- 0%
- }%
-}
-\newcommand\nduConvertToRepr at helper[4]{%
- % convert from overlying unit and add value
- % #1 = unit group
- % #2 = repr name
- % #3 = segment
- % #4 = value
- \ndu at if@depth at at@least{#1}{#3}{%
- \ifnum#3=0%
- % no conversion at top level
- \else%
- \ifnduFactorDefined{#1}{#3}{%
- %\show#3%
- \csxdef{ndu at repr@#2}{\bigintcalcMul{\csuse{ndu at repr@#2}}{\nduFactor{#1}{#3}}}%
- }{%
- % there is no factor to the overlying unit
- % instead attempt to skip ahead to the underlying unit?
- \PackageError{non-decimal-units}{Cannot convert to representation because there is no conversion factor from \nduName{#1}{\the\numexpr#3-1\relax} to \nduName{#1}{#3}}{}%
- }%
- \fi%
- \csxdef{ndu at repr@#2}{\bigintcalcAdd{\csuse{ndu at repr@#2}}{\ndu at val@or at zero{#4}}}%
- \csxdef{ndu at repr@#2 at unit}{\nduName{#1}{#3}}%
- }%
+\cs_new_protected:Nn \ndu_set_options:nn
+{
+ % set keys for unit group
+ \tl_if_eq:cnF { l_ndu_options_#1_tl } { \c_novalue_tl }
+ {
+ \keys_set:nv { non-decimal-units } { l_ndu_options_#1_tl }
+ }
+
+ % set keys provided by command
+ \IfValueT {#2} { \keys_set:nn { non-decimal-units } { #2 } }
}
-\newcommand\nduConvertToRepr at internal[9]{%
- % #1 = unit group
- % #2 = repr name
- % #3-9 = values
- \csdef{ndu at repr@#2}{0}%
- \nduConvertToRepr at helper{#1}{#2}{0}{#3}%
- \nduConvertToRepr at helper{#1}{#2}{1}{#4}%
- \nduConvertToRepr at helper{#1}{#2}{2}{#5}%
- \nduConvertToRepr at helper{#1}{#2}{3}{#6}%
- \nduConvertToRepr at helper{#1}{#2}{4}{#7}%
- \nduConvertToRepr at helper{#1}{#2}{5}{#8}%
- \nduConvertToRepr at helper{#1}{#2}{6}{#9}%
+\NewDocumentCommand \nduValue { m o m } {
+ \tl_if_exist:cF { l_ndu_group_#1_seq }
+ {
+ \msg_error:nnn { non-decimal-units } { missing-unit-group } { #1 }
+ }
+ \group_begin:
+ \ndu_set_options:nn {#1} {#2}
+
+ \tl_clear_new:N \l__ndu_result_tl
+ \int_zero_new:N \l__ndu_normalized_int
+ \seq_set_split:Nnn \l_tmpa_seq { . } {#3}
+
+ % should we normalize the input?
+ \bool_if:nT \l_ndu_normalize_bool
+ {
+ \ndu_seq_to_repr:NnN
+ \l__ndu_normalized_int
+ { #1 }
+ \l_tmpa_seq
+ \ndu_repr_to_seq:NnN
+ \l_tmpa_seq
+ { #1 }
+ \l__ndu_normalized_int
+ }
+
+ % are we outputting aligned cells?
+ \bool_if:NTF \l_ndu_aligned_bool
+ {
+ \ndu_format_values_aligned:NcN
+ \l__ndu_result_tl
+ { l_ndu_group_#1_seq }
+ \l_tmpa_seq
+ }
+ {
+ \ndu_format_values:NcNN
+ \l__ndu_result_tl
+ { l_ndu_group_#1_seq }
+ \l_tmpa_seq
+ \l_ndu_unit_separator_tl
+ }
+
+ % should we do any math?
+ \tl_if_empty:NF \l_ndu_current_variable_tl
+ {
+ \nduMath{#1}[#2]{\l_ndu_current_variable_tl}{\l_ndu_current_operator_tl}{#3}
+ }
+
+ % output
+ \tl_use:N \l__ndu_result_tl
+ \group_end:
}
-\NewDocumentCommand\nduConvertToRepr{ m O{} m > { \SplitArgument { 6 } { . } } m }{%
- \nduset{unit groups/#1,#2}%
- \nduConvertToRepr at internal{#1}{#3}#4%
+\tl_const:Nn \c__ndu_plus_tl { + }
+\tl_const:Nn \c__ndu_minus_tl { - }
+
+\NewDocumentCommand \nduMath { m o m m m } {
+ \tl_if_exist:cF { l_ndu_group_#1_seq }
+ {
+ \msg_error:nnn { non-decimal-units } { missing-unit-group } { #1 }
+ }
+ \group_begin:
+ \ndu_set_options:nn {#1} {#2}
+
+ \int_if_exist:cF { g_ndu_variable_#3_int } {
+ \int_zero_new:c { g_ndu_variable_#3_int }
+ }
+
+ \int_zero_new:N \l__ndu_operand_int
+
+ \bool_if:nTF
+ {
+ % TODO hacky, but works
+ \str_if_eq_p:nV {#4} \c__ndu_plus_tl ||
+ \str_if_eq_p:nV {#4} \c__ndu_minus_tl ||
+ \tl_if_eq_p:NN {#4} \c__ndu_plus_tl ||
+ \tl_if_eq_p:NN {#4} \c__ndu_minus_tl
+ }
+ {
+ % plus or minus means we use the representation of the provided value
+ \seq_set_split:Nnn \l_tmpa_seq { . } { #5 }
+ \ndu_seq_to_repr:NnN
+ \l__ndu_operand_int
+ { #1 }
+ \l_tmpa_seq
+ }
+ {
+ % otherwise (multiplication/division) we use the number provided directly
+ \int_set:Nn \l__ndu_operand_int { #5 }
+ }
+
+ \int_gset:cn { g_ndu_variable_#3_int } {
+ \int_use:c { g_ndu_variable_#3_int }
+ #4
+ \l__ndu_operand_int
+ }
+ \group_end:
}
-\newcommand\nduFormatRepr at helper[3]{%
- % V = mod(R, F)
- % R = div(R - V, F)
- % #1 = unit group
- % #2 = repr name
- % #3 = segment (F)
- \ndu at if@depth at at@least{#1}{#3}{%
- \ifnum#3=0%
- \csxdef{ndu at repr@#2 at result@#3}{\csuse{ndu at repr@#2}}%
- \else%
- \ifnduFactorDefined{#1}{#3}{%
- \csxdef{ndu at repr@#2 at result@#3}{\bigintcalcMod{\csuse{ndu at repr@#2}}{\nduFactor{#1}{#3}}}%
- \csxdef{ndu at repr@#2}{\bigintcalcDiv{\bigintcalcSub{\csuse{ndu at repr@#2}}{\csuse{ndu at repr@#2 at result@#3}}}{\nduFactor{#1}{#3}}}%
- }{%
- % there is no factor to the underlying unit
- % instead attempt to skip ahead to the overlying unit?
- \PackageError{non-decimal-units}{Cannot convert from representation because there is no conversion factor from \nduName{#1}{\the\numexpr#3-1\relax} to \nduName{#1}{#3}}{}%
- }%
- \fi%
- }%
+\NewDocumentCommand \nduResult { m o m } {
+ \tl_if_exist:cF { l_ndu_group_#1_seq }
+ {
+ \msg_error:nnn { non-decimal-units } { missing-unit-group } { #1 }
+ }
+ \group_begin:
+ \ndu_set_options:nn {#1} {#2}
+
+ \int_if_exist:cF { g_ndu_variable_#3_int } {
+ \int_zero_new:c { g_ndu_variable_#3_int }
+ }
+
+ \tl_clear_new:N \l__ndu_result_tl
+
+ \ndu_repr_to_seq:Nnc
+ \l_tmpa_seq
+ { #1 }
+ { g_ndu_variable_#3_int }
+
+ % are we outputting aligned cells?
+ \bool_if:NTF \l_ndu_aligned_bool
+ {
+ \ndu_format_values_aligned:NcN
+ \l__ndu_result_tl
+ { l_ndu_group_#1_seq }
+ \l_tmpa_seq
+ }
+ {
+ \ndu_format_values:NcNN
+ \l__ndu_result_tl
+ { l_ndu_group_#1_seq }
+ \l_tmpa_seq
+ \l_ndu_unit_separator_tl
+ }
+
+ % output
+ \tl_use:N \l__ndu_result_tl
+ \group_end:
}
-\NewDocumentCommand\nduResult{ m O{} m }{%
- \nduResult at unitgroup{\nduAliasOrGroup{#1}}[#2]{#3}%
+\NewDocumentCommand \nduHeader { m o } {
+ \tl_if_exist:cF { l_ndu_group_#1_seq }
+ {
+ \msg_error:nnn { non-decimal-units } { missing-unit-group } { #1 }
+ }
+ \group_begin:
+ \ndu_set_options:nn {#1} {#2}
+ \tl_set:Nn \l__ndu_result_tl { \leavevmode }
+
+ % build boxes
+ \seq_set_eq:Nc \l_tmpa_seq { l_ndu_group_#1_seq }
+ \seq_map_indexed_inline:Nn \l_tmpa_seq
+ {
+ \ndu_make_box:cnn
+ { l__ndu_cell_ \int_to_alph:n {##1} _box }
+ { \hfill \tl_use:c { l_ndu_symbol_ ##2 _tl } }
+ { ##1 }
+ \tl_put_right:Nn \l__ndu_result_tl { \box_use:c { l__ndu_cell_ \int_to_alph:n {##1} _box } }
+
+ % stop when we hit the desired unit depth
+ \tl_if_eq:NnT \l_ndu_unit_depth_tl {##2}
+ {
+ \seq_map_break:
+ }
+ }
+
+ % output
+ \tl_use:N \l__ndu_result_tl
+ \group_end:
}
-\NewDocumentCommand\nduResult at unitgroup{ m O{} m }{%
- % #1 = unit group
- % #2 = options
- % #3 = repr name
- \nduset{unit groups/#1}%
- \csdef{ndu at repr@tmp #3}{\csuse{ndu at repr@#3}}%
- \nduFormatRepr at helper{#1}{tmp #3}{6}%
- \nduFormatRepr at helper{#1}{tmp #3}{5}%
- \nduFormatRepr at helper{#1}{tmp #3}{4}%
- \nduFormatRepr at helper{#1}{tmp #3}{3}%
- \nduFormatRepr at helper{#1}{tmp #3}{2}%
- \nduFormatRepr at helper{#1}{tmp #3}{1}%
- \nduFormatRepr at helper{#1}{tmp #3}{0}%
- \edef\ndu at nextdelim{\pgfkeysvalueof{/ndu/unit groups/#1/segment separator}}%
- \edef\ndu at delim{}%
- \begingroup%
- \nduset{unit groups/#1,#2}%
- \ifndualigned%
- \nduset{show=values}%
- \nduAlignedValue at helper{#1}{0}{\csuse{ndu at repr@tmp #3 at result@0}}%
- \nduAlignedValue at helper{#1}{1}{\csuse{ndu at repr@tmp #3 at result@1}}%
- \nduAlignedValue at helper{#1}{2}{\csuse{ndu at repr@tmp #3 at result@2}}%
- \nduAlignedValue at helper{#1}{3}{\csuse{ndu at repr@tmp #3 at result@3}}%
- \nduAlignedValue at helper{#1}{4}{\csuse{ndu at repr@tmp #3 at result@4}}%
- \nduAlignedValue at helper{#1}{5}{\csuse{ndu at repr@tmp #3 at result@4}}%
- \nduAlignedValue at helper{#1}{6}{\csuse{ndu at repr@tmp #3 at result@4}}%
- \else%
- \nduFormatValue at helper{#1}{0}{\csuse{ndu at repr@tmp #3 at result@0}}%
- \nduFormatValue at helper{#1}{1}{\csuse{ndu at repr@tmp #3 at result@1}}%
- \nduFormatValue at helper{#1}{2}{\csuse{ndu at repr@tmp #3 at result@2}}%
- \nduFormatValue at helper{#1}{3}{\csuse{ndu at repr@tmp #3 at result@3}}%
- \nduFormatValue at helper{#1}{4}{\csuse{ndu at repr@tmp #3 at result@4}}%
- \nduFormatValue at helper{#1}{5}{\csuse{ndu at repr@tmp #3 at result@4}}%
- \nduFormatValue at helper{#1}{6}{\csuse{ndu at repr@tmp #3 at result@4}}%
- \fi%
- \endgroup%
+\NewDocumentCommand \nduSymbol { m } {
+ \tl_use:c { l_ndu_symbol_#1_tl }
}
-\newcommand\nduMath[4]{%
- \nduMath at unitgroup{\nduAliasOrGroup{#1}}{#2}{#3}{#4}%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Column type for tabularray
+%
+
+% TODO: using the font key is pretty hacky...
+% need to ask if theres a better option
+% https://github.com/lvjr/tabularray/issues
+
+\keys_define:nn { non-decimal-units }
+{
+ tabularray~column~type .code = {
+ \NewColumnType {#1}[2] { Q[r, cmd=\ndu_tblr_cell:nnn {##1} {##2}] }
+ } ,
}
-\newcommand\nduMath at unitgroup[4]{%
- % #1 = unit group
- % #2 = repr name
- % #3 = operator
- % #4 = value
- \nduset{unit groups/#1}%
- \ifcsvoid{ndu at repr@#2}{\csxdef{ndu at repr@#2}{0}}{}%
- \ifthenelse{\equal{#3}{+}}{%
- \nduConvertToRepr{#1}{tmp #2}{#4}%
- \csxdef{ndu at repr@#2}{\bigintcalcAdd{\csuse{ndu at repr@#2}}{\csuse{ndu at repr@tmp #2}}}%
- }{%
- \ifthenelse{\equal{#3}{-}}{%
- \nduConvertToRepr{#1}{tmp #2}{#4}%
- \csxdef{ndu at repr@#2}{\bigintcalcSub{\csuse{ndu at repr@#2}}{\csuse{ndu at repr@tmp #2}}}%
- }{%
- \ifthenelse{\equal{#3}{*}}{%
- \csxdef{ndu at repr@#2}{\bigintcalcMul{\csuse{ndu at repr@#2}}{#4}}%
- }{%
- \ifthenelse{\equal{#3}{/}}{%
- \csxdef{ndu at repr@#2}{\bigintcalcDiv{\csuse{ndu at repr@#2}}{#4}}%
- }{%
- \PackageError{non-decimal-units}{Unrecognized math operator: #3}{Only + - * / are allowed.}%
- }%
- }%
- }%
- }%
+\tl_clear_new:N \l__ndu_tblr_column_type_tl
+
+\tl_const:Nn \c__ndu_HEADER_tl { HEADER }
+\tl_const:Nn \c__ndu_RESULT_tl { RESULT }
+\tl_const:Nn \c__ndu_SKIP_tl { SKIP }
+
+\cs_new_protected:Nn \ndu_tblr_cell:nnn
+{
+ \keys_set:nn { non-decimal-units } {
+ aligned,
+ #2
+ }
+ \tl_set:Nn \l_tmpa_tl {#3}
+ \tl_case:NnF \l_tmpa_tl {
+ \c__ndu_HEADER_tl {
+ \nduHeader
+ { #1 }
+ }
+ \c__ndu_RESULT_tl {
+ \nduResult
+ { #1 }
+ { \l_ndu_current_variable_tl }
+ }
+ \c__ndu_SKIP_tl {
+ % nothing
+ }
+ }
+ {
+ % format value if no special token was hit
+ % do math only once per tblr cell
+ % Will https://github.com/lvjr/tabularray/issues/179 introduce
+ % elenganter solution?
+ \cs_if_exist:cTF { \ndu__tblr_cell_get_csname: }
+ % or use a specific bool, e.g., \ndu__do_math_bool
+ { \tl_clear:N \l_ndu_current_variable_tl }
+ { \cs_gset:cpn { \ndu__tblr_cell_get_csname: } {} }
+ \nduValue
+ { #1 }
+ { #3 }
+ }
}
+% a csname distinct per tblr table, per cell
+\cs_new:Npn \ndu__tblr_cell_get_csname:
+ {
+ ndu__tblr_ \int_use:N \g__tblr_table_count_int
+ _cell_ \int_use:N \c at rownum _ \int_use:N \c at colnum
+ :
+ }
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Setup
+%
-\nduset{
- options/.cd,
- british/.code={\input{non-decimal-units.british}},
- danish/.code={\input{non-decimal-units.danish}},
+\keys_define:nn { non-decimal-units / options }
+{
+ british .code:n = { \input{non-decimal-units.british} } ,
+ danish .code:n = { \input{non-decimal-units.danish} } ,
+ german .code:n = { \input{non-decimal-units.german} } ,
}
-\ProcessPgfPackageOptions{/ndu/options}
+\IfFormatAtLeastTF { 2022-06-01 } {
+ \ProcessKeyOptions [ non-decimal-units / options ]
+}{
+ \RequirePackage { l3keys2e }
+ \ProcessKeysOptions { non-decimal-units / options }
+}
\ No newline at end of file
More information about the tex-live-commits
mailing list.