diff options
Diffstat (limited to 'macros/latex/contrib/siunitx/siunitx-table.dtx')
-rw-r--r-- | macros/latex/contrib/siunitx/siunitx-table.dtx | 1445 |
1 files changed, 1445 insertions, 0 deletions
diff --git a/macros/latex/contrib/siunitx/siunitx-table.dtx b/macros/latex/contrib/siunitx/siunitx-table.dtx new file mode 100644 index 0000000000..d16d2d7780 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-table.dtx @@ -0,0 +1,1445 @@ +% \iffalse meta-comment +% +% File: siunitx-table.dtx Copyright (C) 2016-2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-table} -- Formatting numbers in tables^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \section{Numbers in tables} +% +% This submodule is concerned with formatting numbers in table cells or +% similar fixed-width contexts. The main function, \cs{siunitx_cell_begin:w}, +% is designed to work with the normal \LaTeXe{} tablular cell construct +% featuring \cs{ignorespaces}. Therefore, if used outside of a \LaTeXe{} +% tabular, it is necessary to provide this token. +% +% \begin{function}{\siunitx_cell_begin:w, \siunitx_cell_end:} +% \begin{syntax} +% \cs{siunitx_cell_begin:w} \meta{preamble} \cs{ignorespaces} +% \meta{content} +% \cs{siunitx_cell_end:} +% \end{syntax} +% Collects the \meta{preamble} and \meta{content} tokens, and determines +% if it is text or a number (as parsed by \cs{siunitx_number_parse:nN}). +% It produces output of a fixed width suitable for alignment in a table, +% although it is not \emph{required} that the code is used within a cell. +% Note that |\ignorespaces| must occur in the \enquote{cell}: it marks +% the end of the \TeX{} |\halign| template. +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{table-align-comparator} +% \begin{syntax} +% |table-align-comparator| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of comparators is attempted +% within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-exponent} +% \begin{syntax} +% |table-align-exponent| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of exponents is attempted +% within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-text-after} +% \begin{syntax} +% |table-align-text-after| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of text falling after a number +% is attempted within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-text-before} +% \begin{syntax} +% |table-align-text-before| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of text falling before a number +% is attempted within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-uncertainty} +% \begin{syntax} +% |table-align-uncertainty| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of separated uncertainty values +% is attempted within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-alignment} +% \begin{syntax} +% |table-alignment| = |center|\verb"|"|left|\verb"|"|right| +% \end{syntax} +% Selects the alignment of all tabular content with the margins of the table +% cell (or other boundary). See also |table-number-alignment| and +% |table-text-alignment|. The standard setting is |center|. +% \end{function} +% +% \begin{function}{table-alignment-mode} +% \begin{syntax} +% |table-alignment-mode| = |format|\verb"|"|marker|\verb"|"|none| +% \end{syntax} +% Selects the method used to align numbers with the desired position in the +% cell (set by |table-alignment|). When set to |format|, a dedicated +% amount of space is calculated from the |table-format|. When |marker| +% is selected, alignment is carried out symmetrically around the decimal +% marker. Finally, |none| switches off all alignment: numbers are parsed +% and formatted but with no attempt at placement within the cell. The +% standard setting is |marker|. +% \end{function} +% +% \begin{function}{table-auto-round} +% \begin{syntax} +% |table-auto-round| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether numbers are rounded to fit within +% the |table-format| specification (if possible). The standard +% setting is |false|. +% \end{function} +% +% \begin{function}{table-column-width} +% \begin{syntax} +% |table-column-width| = \meta{width} +% \end{syntax} +% Sets the width of the table column used for numbers. This is only used +% when |table-fixed-width| is |true|. +% \end{function} +% +% \begin{function}{table-fixed-width} +% \begin{syntax} +% |table-fixed-width| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether a fixed-width column is used for numbers +% in tables. When |true|, the width is taken from |table-column-width|. The +% standard setting is |false|. +% \end{function} +% +% \begin{function}{table-format} +% \begin{syntax} +% |table-format| = \meta{format} +% \end{syntax} +% Describes the amount of space that should be reserved when +% |table-alignment-mode| is set to |format|. The \meta{format} takes the +% same general form as input for a table cell, with the numerical parts +% describing how many digits to reserve space for. For example, |1.2e3| +% would allow space for one digit in the integer part, two in the decimal +% part and three in the exponent part. Signs can be allowed for using any +% valid input sign, so for example |+1.2 \pm 1.2| would allow for a sign, +% a number with one integer and two decimal digits and a uncertainty of +% the same size. +% \end{function} +% +% \begin{function}{table-number-alignment} +% \begin{syntax} +% |table-number-alignment| = |center|\verb"|"|left|\verb"|"|right| +% \end{syntax} +% Selects the alignment of numerical content with the margins of the table +% cell (or other boundary). See also |table-alignment| and +% |table-text-alignment|. The standard setting is |center|. +% \end{function} +% +% \begin{function}{table-text-alignment} +% \begin{syntax} +% |table-text-alignment| = |center|\verb"|"|left|\verb"|"|right| +% \end{syntax} +% Selects the alignment of non-numerical content with the margins of the +% table cell (or other boundary). See also |table-alignment| and +% |table-number-alignment|. The standard setting is |center|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-table} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_table> +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_box, \l_@@_tmp_dim, \l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\box_new:N \l_@@_tmp_box +\dim_new:N \l_@@_tmp_dim +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Interface functions} +% +% \begin{variable}{\l_@@_text_bool} +% Used to track that a cell is purely text. +% \begin{macrocode} +\bool_new:N \l_@@_text_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_cell_begin:w} +% \begin{macro}{\siunitx_cell_end:} +% The start and end of the cell need to deal with the possibility of +% a cell containing only text. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_cell_begin:w + { + \bool_set_false:N \l_@@_text_bool + \bool_if:NTF \l_siunitx_number_parse_bool + { \@@_collect_begin: } + { \@@_direct_begin: } + } +\cs_new_protected:Npn \siunitx_cell_end: + { + \bool_if:NF \l_@@_text_bool + { + \bool_if:NTF \l_siunitx_number_parse_bool + { \@@_collect_end: } + { \@@_direct_end: } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Collecting tokens} +% +% \begin{variable}{\l_@@_collect_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_collect_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_begin:} +% \begin{macro}{\@@_collect_begin:w} +% Collecting a tabular cell means doing a token-by-token collection. +% In previous versions of \pkg{siunitx} that was done along with picking +% out the numerical part, but the code flow ends up very tricky. Here, +% therefore, we just collect up the unchanged tokens first. The definition of +% \cs{cr} is used to allow collection of any tokens +% inserted after the main content when dealing with the last cell of a row: +% the \enquote{group} around it is needed to avoid issues with the underlying +% |\halign|. (The approach is based on that in \pkg{collcell}.) Whilst the +% group formed by a cell will normally tidy up |\cr|, we add an extra one as +% the collected material could be a tabular in itself. We use an auxiliary to +% fish out the |\ignorespaces| from the template: that has to go to avoid +% issues with the peek-ahead code (everything before the |#| needs to be +% read \emph{before} the Appendix~D trick gets applied). Some packages +% add additional tokens before the |\ignorespaces|, which are dealt with by +% the delimited argument. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_begin: + { + \group_begin: + \tl_clear:N \l_@@_collect_tl + \if_false: { \fi: + \cs_set_protected:Npn \cr + { + \@@_collect_loop: + \tex_cr:D + } + \if_false: } \fi: + \@@_collect_begin:w + } +\cs_new_protected:Npn \@@_collect_begin:w #1 \ignorespaces + { \@@_collect_loop: #1 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_collect_loop:} +% \begin{macro}{\@@_collect_group:n} +% \begin{macro}{\@@_collect_token:N} +% \begin{macro}{\@@_collect_search:NnF} +% \begin{macro}{\@@_collect_search_aux:NNn} +% Collecting up the cell content needs a loop: this is done using +% a |peek| approach as it's most natural. (A slower approach is possible +% using something like the |\text_lowercase:n| loop code.) The set of +% possible tokens is somewhat limited compared to an arbitrary cell +% (\foreign{cf.}~the approach in \pkg{collcell}): the special cases are +% pulled out for manual handling. The flexible lookup approach is more-or-less +% the same idea as in the kernel |case| functions. The |\relax| special case +% covers the case where |\\| has been expanded in an empty cell. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_loop: + { + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_collect_group:n } + { \@@_collect_token:N } + } +\cs_new_protected:Npn \@@_collect_group:n #1 + { + \tl_put_right:Nn \l_@@_collect_tl { {#1} } + \@@_collect_loop: + } +\cs_new_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \unskip { \@@_collect_loop: } + \end { \tabularnewline \end } + \relax { \relax } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end: } + } + { + \tl_put_right:Nn \l_@@_collect_tl {#1} + \@@_collect_loop: + } + } +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \@maybe@unskip { \@@_collect_loop: } + \tab@setcr { \@@_collect_loop: } + \unskip { \@@_collect_loop: } + \end { \tabularnewline \end } + \relax { \relax } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end: } + } + { + \tl_put_right:Nn \l_@@_collect_tl {#1} + \@@_collect_loop: + } + } + } + { } + } +\cs_new_protected:Npn \@@_collect_search:NnF #1#2#3 + { + \@@_collect_search_aux:NNn #1 + #2 + #1 {#3} + \q_stop + } +\cs_new_protected:Npn \@@_collect_search_aux:NNn #1#2#3 + { + \token_if_eq_meaning:NNTF #1 #2 + { \use_i_delimit_by_q_stop:nw {#3} } + { \@@_collect_search_aux:NNn #1 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Separating collected material} +% +% The input needs to be divided into numerical tokens and those which appear +% before and after them. This needs a second loop and validation. +% +% \begin{variable}{\l_@@_before_tl, \l_@@_number_tl, \l_@@_after_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_before_tl +\tl_new:N \l_@@_number_tl +\tl_new:N \l_@@_after_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_end:} +% \begin{macro}{\@@_collect_end:n} +% \begin{macro}[EXP]{\@@_collect_end_aux:n} +% \begin{macro}[EXP]{\@@_collect_end:w} +% At the end of the cell, escape the group and check for expansion. We +% only do that if the entire content is not a brace group: there is more +% likely to be problematic content in the case of a header. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_end: + { + \exp_args:NNV \group_end: + \@@_collect_end:n \l_@@_collect_tl + \exp_args:NV \@@_split:nNNN + \l_@@_collect_tl + \l_@@_before_tl + \l_@@_number_tl + \l_@@_after_tl + \tl_if_empty:NTF \l_@@_number_tl + { \@@_print_text:V \l_@@_before_tl } + { + \@@_print:VVV + \l_@@_before_tl + \l_@@_number_tl + \l_@@_after_tl + } + } +\cs_new_protected:Npn \@@_collect_end:n #1 + { + \str_if_eq:eeTF { \exp_not:n {#1} } + { { \@@_collect_end_aux:n {#1} } } + { \tl_set:Nn } + { \protected@edef } + \l_@@_collect_tl {#1} + } +\cs_new:Npn \@@_collect_end_aux:n #1 + { \exp_after:wN \@@_collect_end:w #1 \q_stop } +\cs_new:Npn \@@_collect_end:w #1 \q_stop + { \exp_not:n {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_split:nNNN} +% \begin{macro}{\@@_split_loop:NNN} +% \begin{macro}{\@@_split_group:NNNn} +% \begin{macro}{\@@_split_token:NNNN} +% Splitting into parts uses the fact that numbers cannot contain groups +% and that we can track where we are up to based on the content of the +% token lists. +% \begin{macrocode} +\cs_new_protected:Npn \@@_split:nNNN #1#2#3#4 + { + \tl_clear:N #2 + \tl_clear:N #3 + \tl_clear:N #4 + \@@_split_loop:NNN #2#3#4 #1 \q_recursion_tail \q_recursion_stop + \@@_split_tidy:N #2 + \@@_split_tidy:N #4 + } +\cs_new_protected:Npn \@@_split_loop:NNN #1#2#3 + { + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_split_group:NNNn #1#2#3 } + { \@@_split_token:NNNN #1#2#3 } + } +\cs_new_protected:Npn \@@_split_group:NNNn #1#2#3#4 + { + \tl_if_empty:NTF #2 + { \tl_put_right:Nn #1 { {#4} } } + { \tl_put_right:Nn #3 { {#4} } } + \@@_split_loop:NNN #1#2#3 + } +\cs_new_protected:Npn \@@_split_token:NNNN #1#2#3#4 + { + \quark_if_recursion_tail_stop:N #4 + \tl_if_empty:NTF \l_@@_after_tl + { + \siunitx_if_number_token:NTF #4 + { \tl_put_right:Nn #2 {#4} } + { + \tl_if_empty:NTF #2 + { \tl_put_right:Nn #1 {#4} } + { \tl_put_right:Nn #3 {#4} } + } + } + { \tl_put_right:Nn #3 {#4} } + \@@_split_loop:NNN #1#2#3 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_split_tidy:N} +% \begin{macro}{\@@_split_tidy:Nn, \@@_split_tidy:NV} +% A quick test for the entire content being surrounded by a set of braces: +% rather than look explicitly, use the fact that a string comparison can +% detect the same thing. The auxiliary is needed to avoid having to go +% \foreign{via} a |:D| function (for the expansion behaviour). +% \begin{macrocode} +\cs_new_protected:Npn \@@_split_tidy:N #1 + { + \tl_if_empty:NF #1 + { \@@_split_tidy:NV #1 #1 } + } +\cs_new_protected:Npn \@@_split_tidy:Nn #1#2 + { + \str_if_eq:onT { \exp_after:wN { \use:n #2 } } {#2} + { \tl_set:No #1 { \use:n #2 } } + } +\cs_generate_variant:Nn \@@_split_tidy:Nn { NV } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: spacing} +% +% Getting the general alignment correct in tables is made more complex than one +% would like by the \pkg{colortbl} package. In the original \LaTeXe{} +% definition, cell material is centred by a construction of the (primitive) +% form +% \begin{verbatim} +% \hfil +% # +% \hfil +% \end{verbatim} +% which only uses \texttt{fil} stretch. That is altered by \pkg{colortbl} to +% broadly +% \begin{verbatim} +% \hskip 0pt plus 0.5fill +% \kern 0pt +% # +% \hskip 0pt plus 0.5fill +% \end{verbatim} +% which means there is \texttt{fill} stretch to worry about and the kern as +% well. +% +% \begin{macro}{\@@_skip:n} +% To prevent combination of skips, a kern is inserted after each one. +% This is best handled as a short auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_skip:n #1 + { + \skip_horizontal:n {#1} + \tex_kern:D \c_zero_skip + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_column_width_dim, \l_@@_fixed_width_bool} +% Settings which apply to aligned columns in general. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-column-width .dim_set:N = + \l_@@_column_width_dim , + table-fixed-width .bool_set:N = + \l_@@_fixed_width_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_align_center:n, \@@_align_left:n, \@@_align_right:n} +% \begin{macro}{\@@_align_auxi:nn, \@@_align_auxii:nn} +% The beginning and end of each table cell have to adjust the position of +% the content using glue. When \pkg{colortbl} is loaded the glue is done in +% two parts: one for our positioning and one to explicitly override that from +% the package. Using a two-step auxiliary chain avoids needing to repeat any +% code and the impact of the extra expansion should be trivial. +% \begin{macrocode} +\cs_new_protected:Npn \@@_align_center:n #1 + { \@@_align_auxi:nn {#1} { 0pt~plus~0.5fill } } +\cs_new_protected:Npn \@@_align_left:n #1 + { \@@_align_auxi:nn {#1} { 0pt } } +\cs_new_protected:Npn \@@_align_right:n #1 + { \@@_align_auxi:nn {#1} { 0pt~plus~1fill } } +\cs_new_protected:Npn \@@_align_auxi:nn #1#2 + { + \bool_if:NTF \l_@@_fixed_width_bool + { \hbox_to_wd:nn \l_@@_column_width_dim } + { \use:n } + { + \@@_skip:n {#2} + #1 + \@@_skip:n { 0pt~plus~1fill - #2 } + } + } +\AtBeginDocument + { + \@ifpackageloaded { colortbl } + { + \cs_new_eq:NN + \@@_align_auxii:nn + \@@_align_auxi:nn + \cs_set_protected:Npn \@@_align_auxi:nn #1#2 + { + \@@_skip:n{ 0pt~plus~-0.5fill } + \@@_align_auxii:nn {#1} {#2} + \@@_skip:n { 0pt~plus~-0.5fill } + } + } + { } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Printing just text} +% +% In cases where there is no numerical part, \pkg{siunitx} allows alignment +% of the \enquote{escaped} text independent of the underlying column type. +% +% \begin{variable}{\l_@@_align_text_tl} +% Alignment is handled using a |tl| as this allows a fast lookup at the +% point of use. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-text-alignment .choices:nn = + { center , left , right } + { \tl_set:Nn \l_@@_align_text_tl {#1} } , + } +\tl_new:N \l_@@_align_text_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print_text:n, \@@_print_text:V} +% Printing escaped text is easy: just place it in correctly in the +% column. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_text:n #1 + { + \bool_set_true:N \l_@@_text_bool + \use:c { @@_align_ \l_@@_align_text_tl :n } {#1} + } +\cs_generate_variant:Nn \@@_print_text:n { V } +% \end{macrocode} +% \end{macro} +% +% \subsection{Number alignment: core ideas} +% +% \begin{variable}{\l_@@_integer_box, \l_@@_decimal_box} +% Boxes for the content before and after the decimal marker. +% \begin{macrocode} +\box_new:N \l_@@_integer_box +\box_new:N \l_@@_decimal_box +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_fil:} +% A primitive renamed. +% \begin{macrocode} +\cs_new_eq:NN \@@_fil: \tex_hfil:D +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_cleanup_decimal:w} +% To remove the excess marker tokens in a decimal part. +% \begin{macrocode} +\cs_new:Npn \@@_cleanup_decimal:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil + { #1#2#3#4#5#6#7 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_center_marker:} +% When centering on the decimal marker, the easiest approach is to simply +% re-box the two parts. That is needed whether or not we are parsing numbers, +% so is best as a short auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_center_marker: + { + \dim_compare:nNnTF + { \box_wd:N \l_@@_integer_box } + > { \box_wd:N \l_@@_decimal_box } + { + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { \box_wd:N \l_@@_integer_box } + { + \hbox_unpack:N \l_@@_decimal_box + \@@_fil: + } + } + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { \box_wd:N \l_@@_decimal_box } + { + \@@_fil: + \hbox_unpack:N \l_@@_integer_box + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable} +% {\l_@@_auto_round_bool, \l_@@_align_mode_tl, \l_@@_align_number_tl} +% Options for tables with defined space. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-alignment .meta:n = + { table-number-alignment = #1 , table-text-alignment = #1 }, + table-alignment-mode .choices:nn = + { none , format , marker } + { \tl_set_eq:NN \l_@@_align_mode_tl \l_keys_choice_tl } , + table-auto-round .bool_set:N = + \l_@@_auto_round_bool , + table-format .code:n = + { + \@@_split:nNNN {#1} + \l_@@_before_model_tl + \l_@@_model_tl + \l_@@_after_model_tl + \exp_args:NV \@@_generate_model:n \l_@@_model_tl + \tl_set:Nn \l_@@_align_mode_tl { format } + } , + table-number-alignment .choices:nn = + { center , left , right } + { \tl_set_eq:NN \l_@@_align_number_tl \l_keys_choice_tl } + } +\tl_new:N \l_@@_align_mode_tl +\tl_new:N \l_@@_align_number_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_format_tl, \l_@@_model_tl} +% The input and output versions of the model entry in a table. +% \begin{macrocode} +\tl_new:N \l_@@_format_tl +\tl_new:N \l_@@_before_model_tl +\tl_new:N \l_@@_model_tl +\tl_new:N \l_@@_after_model_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_generate_model:n} +% \begin{macro}{\@@_generate_model:nnnnnnn} +% \begin{macro}[EXP]{\@@_generate_model_S:nnw} +% \begin{macro}[EXP]{\@@_generate_model_S:nnn} +% Creating a model for a table at this stage means parsing the format and +% converting that to an appropriate model. Things are quite straight-forward +% other than the uncertainty part. At this stage there is no point in +% formatting the model: that has to happen at point-of-use. Notice that +% the uncertainty part needs to allow for the case where we cross the +% decimal. +% \begin{macrocode} +\cs_new_protected:Npn \@@_generate_model:n #1 + { + \group_begin: + \bool_set_true:N \l_siunitx_number_parse_bool + \keys_set:nn { siunitx } { retain-explicit-plus = true } + \siunitx_number_parse:nN {#1} \l_@@_format_tl + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_format_tl \l_@@_format_tl + \tl_if_empty:NF \l_@@_format_tl + { + \exp_after:wN \@@_generate_model:nnnnnnn + \l_@@_format_tl + } + } +\cs_new_protected:Npn \@@_generate_model:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_set:Nx \l_@@_model_tl + { + \exp_not:n { {#1} {#2} } + { \prg_replicate:nn {#3} { 8 } } + { \prg_replicate:nn { 0 #4 } { 8 } } + { + \tl_if_blank:nF {#5} + { + \use:c { @@_generate_model_ \tl_head:n {#5} :nnw } + {#4} #5 + } + } + \exp_not:n { {#6} } + { + \int_compare:nNnTF {#7} = 0 + { 0 } + { \prg_replicate:nn {#7} { 8 } } + } + } + } +\cs_new:Npn \@@_generate_model_S:nnw #1#2#3 + { + { S } + { + \exp_args:Nff \@@_generate_model_S:nnn + { \tl_count:n {#1} } { \tl_count:n {#3} } + {#3} + } + } +\cs_new:Npn \@@_generate_model_S:nnn #1#2#3 + { + \prg_replicate:nn + { + \int_compare:nNnTF {#2} > {#1} + { + \str_range:nnn {#3} { 1 } {#1} + + + \str_range:nnn {#3} { 1 + #1 } {#2} + } + {#3} + } + { 8 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Directly printing without collection} +% +% Collecting the number allows for various effects but is not as fast +% as simply aligning on the first token that is a decimal marker. The +% strategy here is that used by \pkg{dcolumn}. +% +% \begin{macro}{\@@_direct_begin:} +% \begin{macro}{\@@_direct_begin:w} +% \begin{macro}{\@@_direct_end:} +% \begin{macro} +% { +% \@@_direct_marker: , +% \@@_direct_marker_switch: , +% \@@_direct_marker_end: +% } +% \begin{macro}{\@@_direct_format:} +% \begin{macro}[EXP]{\@@_direct_format:nnnnnnn} +% \begin{macro}{\@@_direct_format:w} +% \begin{macro} +% { +% \@@_direct_format_switch: , +% \@@_direct_format_end: +% } +% \begin{macro}{\@@_direct_none:, \@@_direct_none_end:} +% After removing the |\ignorespaces| at the start of the cell (see comments +% for \cs{@@_collect_begin:N}), check to see if there is a |{| and branch +% as appropriate. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_begin: + { \@@_direct_begin:w } +\cs_new_protected:Npn \@@_direct_begin:w #1 \ignorespaces + { + #1 + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_print_text:n } + { + \m@th + \use:c { @@_direct_ \l_@@_align_mode_tl : } + } + } +\cs_new_protected:Npn \@@_direct_end: + { \use:c { @@_direct_ \l_@@_align_mode_tl _end: } } +% \end{macrocode} +% When centring the content about a decimal marker, the trick is +% to collect everything into two boxes and then compare the sizes. +% As we are always in math mode, we can use a math active token +% to make the switch. The up-front setting of the |decimal| box deals +% with the case where there is no decimal part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_marker: + { + \hbox_set:Nn \l_@@_tmp_box + { \ensuremath { \mathord { \l_siunitx_number_output_decimal_tl } } } + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { \box_wd:N \l_@@_tmp_box } + { \@@_fil: } + \hbox_set:Nw \l_@@_integer_box + \c_math_toggle_token + \tl_map_inline:Nn \l_siunitx_number_input_decimal_tl + { + \char_set_active_eq:NN ##1 \@@_direct_marker_switch: + \char_set_mathcode:nn { `##1 } { "8000 } + } + } +\cs_new_protected:Npn \@@_direct_marker_switch: + { + \c_math_toggle_token + \hbox_set_end: + \hbox_set:Nw \l_@@_decimal_box + \c_math_toggle_token + \l_siunitx_number_output_decimal_tl + } +\cs_new_protected:Npn \@@_direct_marker_end: + { + \c_math_toggle_token + \hbox_set_end: + \@@_center_marker: + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + } +% \end{macrocode} +% For the version where there is space reserved, first format and decompose +% that, then create appropriately-sized boxes. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_format: + { + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:NN \l_@@_model_tl \q_nil } + \exp_after:wN \@@_direct_format_aux:w + \l_@@_tmp_tl \q_stop + } +\cs_new_protected:Npn \@@_direct_format_aux:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_stop + { + \hbox_set:Nn \l_@@_tmp_box + { \ensuremath { \@@_cleanup_decimal:w #4 } } + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { \box_wd:N \l_@@_tmp_box } + { \@@_fil: } + \hbox_set:Nn \l_@@_tmp_box { \ensuremath { #1#2#3 } } + \hbox_set_to_wd:Nnw \l_@@_integer_box + { \box_wd:N \l_@@_tmp_box } + \c_math_toggle_token + \tl_map_inline:Nn \l_siunitx_number_input_decimal_tl + { + \char_set_active_eq:NN ##1 \@@_direct_format_switch: + \char_set_mathcode:nn { `##1 } { "8000 } + } + \@@_fil: + } +\cs_new_protected:Npn \@@_direct_format_switch: + { + \c_math_toggle_token + \hbox_set_end: + \hbox_set_to_wd:Nnw \l_@@_decimal_box + { \box_wd:N \l_@@_decimal_box } + \c_math_toggle_token + \mathord { \l_siunitx_number_output_decimal_tl } + } +\cs_new_protected:Npn \@@_direct_format_end: + { + \c_math_toggle_token + \@@_fil: + \hbox_set_end: + \use:c { @@_align_ \l_@@_align_number_tl :n } + { + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + } + } +% \end{macrocode} +% No parsing and no alignment is easy. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_none: { \c_math_toggle_token } +\cs_new_protected:Npn \@@_direct_none_end: { \c_math_toggle_token } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: main functions} +% +% \begin{variable}{\l_@@_before_box, \l_@@_after_box} +% For alignment of text outside of a number. +% \begin{macrocode} +\box_new:N \l_@@_before_box +\box_new:N \l_@@_after_box +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_carry_dim} +% Used to \enquote{carry forward} the amount of white space which needs to +% be inserted after the decimal marker. +% \begin{macrocode} +\dim_new:N \l_@@_carry_dim +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_align_comparator_bool , +% \l_@@_align_exponent_bool , +% \l_@@_align_after_bool , +% \l_@@_align_before_bool , +% \l_@@_align_uncertainty_bool +% } +% Alignment is handled using a |tl| as this allows a fast lookup at the +% point of use. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-align-comparator .bool_set:N = + \l_@@_align_comparator_bool , + table-align-exponent .bool_set:N = + \l_@@_align_exponent_bool , + table-align-text-after .bool_set:N = + \l_@@_align_after_bool , + table-align-text-before .bool_set:N = + \l_@@_align_before_bool , + table-align-uncertainty .bool_set:N = + \l_@@_align_uncertainty_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print:nnn, \@@_print:VVV} +% \begin{macro}{\@@_print_marker:nnn} +% \begin{macro}{\@@_print_marker:w} +% \begin{macro}[EXP]{\@@_print_marker_aux:w} +% \begin{macro}{\@@_print_format:nnn} +% \begin{macro} +% { +% \@@_print_marker_auxi:w, +% \@@_print_marker_auxii:w, +% \@@_print_marker_auxiii:w +% } +% \begin{macro}{\@@_print_format_after:N} +% \begin{macro}{\@@_print_format_box:Nn} +% \begin{macro}{\@@_print_none:nnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:nnn #1#2#3 + { \use:c { @@_print_ \l_@@_align_mode_tl :nnn } {#1} {#2} {#3} } +\cs_generate_variant:Nn \@@_print:nnn { VVV } +% \end{macrocode} +% When centering on the decimal marker, alignment is relatively simple, and +% close in concept to that used without parsing. First we need to deal with any +% text before or after the number. For text \emph{before}, there's the case +% where is has no width and might be a font or color change: that has to be +% filtered out first. Then we can adjust the size of this material and that +% after the number such that they are equal. The number itself can then be +% formatted, splitting at he decimal marker. A bit more size adjustment, then +% the number itself and any text at the end can be inserted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_marker:nnn #1#2#3 + { + \hbox_set:Nn \l_@@_before_box {#1} + \dim_compare:nNnT { \box_wd:N \l_@@_before_box } = { 0pt } + { + \box_clear:N \l_@@_before_box + #1 + } + \hbox_set:Nn \l_@@_after_box {#3} + \dim_compare:nNnTF + { \box_wd:N \l_@@_after_box } + > { \box_wd:N \l_@@_before_box } + { + \hbox_set_to_wd:Nnn \l_@@_before_box + { \box_wd:N \l_@@_after_box } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + } + { + \hbox_set_to_wd:Nnn \l_@@_after_box + { \box_wd:N \l_@@_before_box } + { + \hbox_unpack:N \l_@@_after_box + \@@_fil: + } + } + \box_use_drop:N \l_@@_before_box + \siunitx_number_parse:nN {#2} \l_@@_tmp_tl + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_tmp_tl + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:NN \l_@@_tmp_tl \q_nil } + \exp_after:wN \@@_print_marker:w + \l_@@_tmp_tl \q_stop + \box_use_drop:N \l_@@_after_box + } +\cs_new_protected:Npn \@@_print_marker:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_stop + { + \hbox_set:Nn \l_@@_integer_box + { \siunitx_print_number:n { #1#2#3 } } + \hbox_set:Nn \l_@@_decimal_box + { + \siunitx_print_number:x + { \@@_print_marker_aux:w #4 } + } + \@@_center_marker: + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + } +\cs_new:Npn \@@_print_marker_aux:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil + { + \exp_not:n {#1#2#3#4#5} + \tl_if_blank:nT {#1#2#3#4#5} { { } } + \exp_not:n {#6#7} + } +% \end{macrocode} +% For positioning based on a format, we have to work part-by-part as there +% are a number of alignment points to get right. As for the |marker| approach, +% first we check if the material before the numerical content is of zero +% width. Next we need to format the model and content numbers, before +% starting an auxiliary chain to pick out the various parts in order. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format:nnn #1#2#3 + { + \hbox_set:Nn \l_@@_tmp_box { \l_@@_before_model_tl } + \hbox_set:Nn \l_@@_before_box {#1} + \dim_compare:nNnT { \box_wd:N \l_@@_before_box } = { 0pt } + { + \box_clear:N \l_@@_before_box + #1 + } + \hbox_set_to_wd:Nnn \l_@@_before_box + { \box_wd:N \l_@@_tmp_box } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + \siunitx_number_parse:nN {#2} \l_@@_tmp_tl + \group_begin: + \bool_if:NT \l_@@_auto_round_bool + { + \exp_args:Nx \keys_set:nn { siunitx } + { + round-mode = places , + round-pad = true , + round-precision = + \exp_after:wN \@@_print_format:nnnnnn + \l_@@_format_tl + } + } + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_tmp_tl + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_tmp_tl + \tl_set:Nx \l_@@_tmp_tl + { + \siunitx_number_output:NN \l_@@_model_tl \q_nil + \exp_not:N \q_mark + \siunitx_number_output:NN \l_@@_tmp_tl \q_nil + } + \exp_after:wN \@@_print_format_auxi:w + \l_@@_tmp_tl \q_stop + \hbox_set:Nn \l_@@_tmp_box { \l_@@_after_model_tl } + \hbox_set_to_wd:Nnn \l_@@_after_box + { \box_wd:N \l_@@_tmp_box + \l_@@_carry_dim } + { + \bool_if:NT \l_@@_align_after_bool + { \skip_horizontal:n { \l_@@_carry_dim } } + #3 + \@@_fil: + } + \use:c { @@_align_ \l_@@_align_number_tl :n } + { + \box_use_drop:N \l_@@_before_box + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + \box_use_drop:N \l_@@_after_box + } + } +\cs_new:Npn \@@_print_format:nnnnnn #1#2#3#4#5#6#7 + { 0 #4 } +% \end{macrocode} +% The first numerical part to handle is the comparator. Any white space we +% need to add goes into the text part \emph{if} alignment is not active +% (\foreign{i.e.}~we are looking \enquote{backwards} to place this filler). +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxi:w + #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box {#1} + \bool_if:NTF \l_@@_align_before_bool + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { \box_wd:N \l_@@_tmp_box } + { + \@@_fil: + \tl_if_blank:nF {#3} + { \siunitx_print_number:n {#3} } + } + } + { + \@@_print_format_box:Nn \l_@@_integer_box {#3} + \hbox_set_to_wd:Nnn \l_@@_before_box + { + \box_wd:N \l_@@_before_box + + \box_wd:N \l_@@_tmp_box + - \box_wd:N \l_@@_integer_box + } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + } + \@@_print_format_auxii:w #2 \q_mark #4 \q_stop + } +% \end{macrocode} +% The integer part follows much the same pattern, except now it is control +% of the comparator alignment that determines where the white space goes. +% As we already have content in the |integer| box, we need to measure how +% much \emph{extra} material has been added. To avoid using more boxes +% or re-setting, we do that by recording sizes before and after the change. +% (In effect, \cs{l_@@_tmp_dim} is here \enquote{l_@@_comparator_dim}.) +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxii:w + #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box {#1#2} + \bool_lazy_and:nnTF + { \l_@@_align_comparator_bool } + { \dim_compare_p:nNn { \box_wd:N \l_@@_integer_box } > { 0pt } } + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { + \box_wd:N \l_@@_integer_box + + \box_wd:N \l_@@_tmp_box + } + { + \hbox_unpack:N \l_@@_integer_box + \@@_fil: + \siunitx_print_number:n {#4#5} + } + } + { + \bool_if:NTF \l_@@_align_before_bool + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { + \box_wd:N \l_@@_integer_box + + \box_wd:N \l_@@_tmp_box + } + { + \@@_fil: + \hbox_unpack:N \l_@@_integer_box + \siunitx_print_number:n {#4#5} + } + } + { + \dim_set:Nn \l_@@_tmp_dim + { \box_wd:N \l_@@_integer_box } + \hbox_set:Nn \l_@@_integer_box + { + \hbox_unpack:N \l_@@_integer_box + \siunitx_print_number:n {#4#5} + } + \hbox_set_to_wd:Nnn \l_@@_before_box + { + \box_wd:N \l_@@_before_box + + \box_wd:N \l_@@_tmp_box + + \l_@@_tmp_dim + - \box_wd:N \l_@@_integer_box + } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + } + } + \@@_print_format_auxiii:w #3 \q_mark #6 \q_stop + } +% \end{macrocode} +% We now deal with the decimal part: there is nothing already in the +% |decimal| box, so the basics are easy. We need to \enquote{carry forward} +% any white space, as where it gets inserted depends on the options for +% subsequent parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxiii:w + #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box {#1#2} + \@@_print_format_box:Nn \l_@@_decimal_box {#4#5} + \dim_set:Nn \l_@@_carry_dim + { + \box_wd:N \l_@@_tmp_box + - \box_wd:N \l_@@_decimal_box + } + \@@_print_format_auxiv:w #3 \q_mark #6 \q_stop + } +% \end{macrocode} +% Any separated uncertainty is now picked up. That has a number of parts, so +% the first step is to look for a sign (which will be |#1|). We then split, +% either simply tidying up the markers if there is no uncertainty, or +% setting it. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxiv:w + #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop + { + \tl_if_blank:nTF {#1} + { \@@_print_format_auxv:w } + { \@@_print_format_auxvi:w } + #1#2 \q_mark #3#4 \q_stop + } +\cs_new_protected:Npn \@@_print_format_auxv:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_mark + #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop + { \@@_print_format_auxvii:w #4 \q_mark #8 \q_stop } +% \end{macrocode} +% Sorting out the placement of the uncertainty requires both the model and +% real data widths, so we store the former to avoiding needing more boxes. +% It's then just a case of putting the carry-over white space in the right +% place. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxvi:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_mark + #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box { { } #1#2#3 } + \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box } + \@@_print_format_box:Nn \l_@@_tmp_box { { } #5#6#7 } + \@@_print_format_after:N \l_@@_align_uncertainty_bool + \@@_print_format_auxvii:w #4 \q_mark #8 \q_stop + } +% \end{macrocode} +% Finally, we get to the exponent part: the multiplication symbol is +% |#1| and the number itself is |#2|. The code is almost the same as for +% uncertainties, which allows a shared auxiliary to be used. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxvii:w + #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop + { + \tl_if_blank:nF {#2} + { + \@@_print_format_box:Nn \l_@@_tmp_box { { } #1#2 } + \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box } + \@@_print_format_box:Nn \l_@@_tmp_box { { } #3#4 } + \@@_print_format_after:N \l_@@_align_exponent_bool + } + } +% \end{macrocode} +% A simple auxiliary to avoid relatively expensive use of the print routine +% for empty parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_box:Nn #1#2 + { + \hbox_set:Nn #1 + { + \tl_if_blank:nF {#2} + { \siunitx_print_number:n {#2} } + } + } +% \end{macrocode} +% A common routine for placing material after the decimal marker and +% \enquote{shuffling}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_after:N #1 + { + \bool_if:NTF #1 + { + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { + \box_wd:N \l_@@_decimal_box + + \l_@@_carry_dim + + \box_wd:N \l_@@_tmp_box + } + { + \hbox_unpack:N \l_@@_decimal_box + \@@_fil: + \hbox_unpack:N \l_@@_tmp_box + } + \dim_set:Nn \l_@@_carry_dim + { + \l_@@_tmp_dim + - \box_wd:N \l_@@_tmp_box + } + } + { + \hbox_set:Nn \l_@@_decimal_box + { + \hbox_unpack:N \l_@@_decimal_box + \hbox_unpack:N \l_@@_tmp_box + } + \dim_add:Nn \l_@@_carry_dim + { + \l_@@_tmp_dim + - \box_wd:N \l_@@_tmp_box + } + } + } +% \end{macrocode} +% With no alignment, everything supplied is treated more-or-less the +% same as \cs{num} (but without the \pkg{xparse} wrapper). +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_none:nnn #1#2#3 + { + \use:c { @@_align_ \l_@@_align_number_tl :n } + { + #1 + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print_number:V \l_@@_tmp_tl + #3 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + table-align-comparator = true , + table-align-exponent = true , + table-align-text-after = true , + table-align-text-before = true , + table-align-uncertainty = true , + table-alignment = center , + table-auto-round = false , + table-column-width = 0pt , + table-fixed-width = false , + table-format = 2.2 , + table-number-alignment = center , + table-text-alignment = center , +% \end{macrocode} +% Out of order as |table-format| sets this implicitly too. +% \begin{macrocode} + table-alignment-mode = marker + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex |