diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx b/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx new file mode 100644 index 00000000000..1b22b33a469 --- /dev/null +++ b/Master/texmf-dist/source/latex/siunitx/siunitx-table.dtx @@ -0,0 +1,606 @@ +% \iffalse meta-comment +% +% File: siunitx-table.dtx Copyright (C) 2016-2017 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} +% 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} +% +% \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_tl} +% Scratch space. +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Interface functions} +% +% \begin{variable}{\l_@@_parse_bool} +% One top-level setting applies to all number cells. +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + parse .bool_set:N = \l_@@_parse_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_cell_begin:, \siunitx_cell_end:} +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_cell_begin: + { + \bool_if:NTF \l_@@_parse_bool + { \@@_collect_begin: } + { \@@_direct_begin: } + } +\cs_new_protected:Npn \siunitx_cell_end: + { + \@@_collect_end: + } +% \end{macrocode} +% \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:} +% 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. Some issues +% with the way that the \texttt{peek} functions are currently set up in +% \pkg{expl3} mean that at present there is a need to do stuff by hand +% here. 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}.) Notice that +% as each cell forms a group there is no need to reset the definition of +% \cs{cr}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_begin: + { + \tl_clear:N \l_@@_collect_tl + \cs_set_protected:Npn \__peek_execute_branches: + { + \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token + \exp_after:wN \@@_collect_group:n + \else: + \exp_after:wN \@@_collect_token:N + \fi: + } + \if_false: { \fi: + \cs_set_protected:Npn \cr + { + \@@_collect_loop: + \tex_cr:D + } + \if_false: } \fi: + \@@_collect_loop: + } +% \end{macrocode} +% \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 |\tl_lower_case: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_after:Nw \__peek_ignore_spaces_execute_branches: } +\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 + { + \ignorespaces { \@@_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: + } + } +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \@maybe@unskip { \@@_collect_loop: } + \ignorespaces { \@@_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_@@_pre_tl, \l_@@_number_tl, \l_@@_post_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_pre_tl +\tl_new:N \l_@@_number_tl +\tl_new:N \l_@@_post_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_end:} +% At the end of the cell, expand all of the content as far as possible then +% split it up into numerical and non-numerical parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_end: + { + \protected@edef \l_@@_collect_tl + { \l_@@_collect_tl } + \tl_clear:N \l_@@_pre_tl + \tl_clear:N \l_@@_number_tl + \tl_clear:N \l_@@_post_tl + \cs_set_protected:Npn \__peek_execute_branches: + { + \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token + \exp_after:wN \@@_split_group:n + \else: + \exp_after:wN \@@_split_token:N + \fi: + } + \exp_after:wN \@@_split_loop: \l_@@_collect_tl + \q_recursion_tail \q_recursion_stop + \@@_split_tidy:N \l_@@_pre_tl + \@@_split_tidy:N \l_@@_post_tl + \tl_if_empty:NTF \l_@@_number_tl + { \@@_print_text:V \l_@@_pre_tl } + { + \@@_print:VVV + \l_@@_pre_tl + \l_@@_number_tl + \l_@@_post_tl + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_split_loop:} +% \begin{macro}{\@@_split_group:n} +% \begin{macro}{\@@_split_token:N} +% 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_loop: + { \peek_after:Nw \__peek_ignore_spaces_execute_branches: } +\cs_new_protected:Npn \@@_split_group:n #1 + { + \tl_if_empty:NTF \l_@@_number_tl + { \tl_put_right:Nn \l_@@_pre_tl { {#1} } } + { \tl_put_right:Nn \l_@@_post_tl { {#1} } } + \@@_split_loop: + } +\cs_new_protected:Npn \@@_split_token:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \tl_if_empty:NTF \l_@@_post_tl + { + \siunitx_if_number_token:NTF #1 + { \tl_put_right:Nn \l_@@_number_tl {#1} } + { + \tl_if_empty:NTF \l_@@_number_tl + { \tl_put_right \l_@@_pre_tl {#1} } + { \tl_put_right \l_@@_post_tl {#1} } + } + } + { \tl_put_right:Nn \l_@@_post_tl {#1} } + \@@_split_loop: + } +% \end{macrocode} +% \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_x:nnT + { \exp_not:n {#2} } + { { \exp_not:o { \use:n #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 , + 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 } {#1} } +\cs_new_protected:Npn \@@_align_left:n #1 + { \@@_align_auxi:nn {#1} { 0pt } {#1} } +\cs_new_protected:Npn \@@_align_right:n #1 + { \@@_align_auxi:nn {#1} { 0pt plus 1fill } {#1} } +\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 + { + \use:c { @@_align_ \l_@@_align_text_tl :n } {#1} + } +\cs_generate_variant:Nn \@@_print_text:n { V } +% \end{macrocode} +% \end{macro} +% +% \subsection{Reserving space: the table format} +% +% \begin{variable}{\l_@@_format_tl} +% \begin{macrocode} +\keys_define:nn { siunitx / table } + { + format .tl_set:N = \l_@@_format_tl + } +% \end{macrocode} +% \end{variable} +% +% \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_begin_aux:} +% After removing the |\ignorespaces| at the start of the cell, 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 \ignorespaces + { + \cs_set:Npn \__peek_execute_branches: + { + \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token + \exp_after:wN \@@_print_text:n + \else: + \m@th + \exp_after:wN \@@_direct_begin_aux: + \fi: + } + \peek_after:Nw \__peek_ignore_spaces_execute_branches: + } +\cs_new_protected:Npn \@@_direct_begin_aux: + { + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: main functions} +% +% \begin{variable} +% { +% \l_@@_align_comparator_bool , +% \l_@@_align_exponent_bool , +% \l_@@_align_uncertainty_bool , +% \l_@@_alignment_tl , +% \l_@@_parse_only_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 , + align-exponent .bool_set:N = + \l_@@_align_exponent_bool , + align-uncertainty .bool_set:N = + \l_@@_align_uncertainty_bool , + alignment .choices:nn = + { center , left , right } + { \tl_set:Nn \l_@@_alignment_tl {#1} } , + parse-only .bool_set:N = + \l_@@_parse_only_bool + } +\tl_new:N \l_@@_alignment_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print:nnn, \@@_print:VVV} +% \begin{macro}{\@@_print_non_aligned:nnn, \@@_print_aligned:nnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:nnn #1#2#3 + { + \use:c { @@_align_ \l_@@_alignment_tl :n } + { + \bool_if:NTF \l_@@_parse_only_bool + { \@@_print_non_aligned:nnn } + { \@@_print_aligned:nnn } + {#1} {#2} {#3} + } + } +\cs_generate_variant:Nn \@@_print:nnn { VVV } +\cs_new_protected:Npn \@@_print_non_aligned:nnn #1#2#3 + { + #1 + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print:nV { number } \l_@@_tmp_tl + #3 + } +\cs_new_protected:Npn \@@_print_aligned:nnn #1#2#3 + { + } +% \end{macrocode} +% \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 = false , + align-exponent = false , + align-uncertainty = false , + alignment = center , + column-width = 0pt , + fixed-width = false , + format = , + parse = true , + parse-only = false , + text-alignment = center + } +% \end{macrocode} +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file |