% \iffalse meta-comment
%
% File: siunitx-command.dtx Copyright (C) 2019,2021,2023,2024 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}
% Additional commands needed in this source
\ProvideDocumentCommand\email{m}{\href{mailto:#1}{\nolinkurl{#1}}}
\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-command} -- Units as document command^^A
%   \thanks{This file describes \fileversion,
%     last revised \filedate.}^^A
% }
%
% \author{^^A
%  Joseph Wright^^A
%  \thanks{^^A
%    E-mail:
%    \email{joseph@texdev.net}^^A
%   }^^A
% }
%
% \date{Released \filedate}
%
% \maketitle
%
% \begin{documentation}
%
% This submodule provides support for creating free-standing document commands
% for unit macros.
%
% \section{Creating units as document commands}
%
% \begin{function}{\siunitx_command_create:}
%   \begin{syntax}
%     \cs{siunitx_command_create:}
%   \end{syntax}
%   Maps over the list of know unit commands and creates the appropriate
%   document command to support them, as controlled by the options below.
% \end{function}
%
% \subsection{Key--value options}
%
% The options defined by this submodule are available within the \pkg{l3keys}
% |siunitx| tree.
%
% These options are all preamble-only.
%
% \begin{function}{free-standing-units}
%   \begin{syntax}
%     |free-standing-units| = |true|\verb"|"|false|
%   \end{syntax}
%   Switch to determine whether free standing document commands are created
%   for symbolic units. This will include not only units themselves but also
%   prefixes, \foreign{etc.} The standard setting is |false|.
% \end{function}
%
% \begin{function}{overwrite-commands}
%   \begin{syntax}
%     |overwrite-commands| = |true|\verb"|"|false|
%   \end{syntax}
%   Switch to determine whether when creating free standing document commands,
%   any existing document commands are overwritten. The standard setting is
%   |false|.
% \end{function}
%
% \begin{function}{space-before-unit}
%   \begin{syntax}
%     |space-before-unit| = |true|\verb"|"|false|
%   \end{syntax}
%   Switch to determine whether a space is inserted before free standing
%   document commands. The standard setting is |false|.
% \end{function}
%
% \begin{function}{unit-optional-argument}
%   \begin{syntax}
%     |unit-optional-argument| = |true|\verb"|"|false|
%   \end{syntax}
%   Switch to determine whether free standing document commands take an
%   optional argument (a number). The standard setting is |false|.
% \end{function}
%
% \begin{function}{use-xspace}
%   \begin{syntax}
%     |use-xspace| = |true|\verb"|"|false|
%   \end{syntax}
%   Switch to determine whether free standing document commands use the
%   \pkg{xparse} package to insert space after the command names. The standard
%   setting is |false|. When set |true|, the \pkg{xparse} package will be
%   loaded at the start of the document if not already available.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{siunitx-command} 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_command>
%    \end{macrocode}
%
% \begin{macro}{\l_@@_tmp_tl}
%    \begin{macrocode}
\tl_new:N \l_@@_tmp_tl
%    \end{macrocode}
% \end{macro}
%
% \subsection{Options}
%
% \begin{variable}
%   {
%     \l_@@_create_bool    ,
%     \l_@@_overwrite_bool ,
%     \l_@@_prespace_bool  ,
%     \l_@@_optarg_bool    ,
%     \l_@@_xspace_bool
%   }
%    \begin{macrocode}
\keys_define:nn { siunitx }
  {
    free-standing-units .bool_set:N =
      \l_@@_create_bool ,
    overwrite-commands .bool_set:N =
      \l_@@_overwrite_bool ,
    space-before-unit .bool_set:N =
      \l_@@_prespace_bool ,
    unit-optional-argument .bool_set:N =
      \l_@@_optarg_bool ,
    use-xspace .bool_set:N =
      \l_@@_xspace_bool
  }
%    \end{macrocode}
% \end{variable}
%
% These preamble-only options are all disabled at the start of the document.
%    \begin{macrocode}
\AtBeginDocument
  {
    \clist_map_inline:nn
      {
        free-standing-units    ,
        overwrite-commands     ,
        space-before-unit      ,
        unit-optional-argument ,
        use-xspace
      }
      {
        \keys_define:nn { siunitx }
          {
            #1 .code:n =
              { \msg_warning:nnn { siunitx } { option-preamble-only } {#1} }
          }
      }
  }
\msg_new:nnn { siunitx } { option-preamble-only }
  { Option~'#1'~only~available~in~the~preamble. }
%    \end{macrocode}
%
% \subsection{Creation of unit document commands}
%
% \begin{macro}{\siunitx_command_create:, \@@_create:}
% \begin{macro}{\@@_create:N}
%   Creating document commands is all done by a single function which is
%   set up using expansion: that way the tests are only run once. Other than
%   that, this is all just a question of picking up all the various routes.
%    \begin{macrocode}
\cs_new_protected:Npn \siunitx_command_create:
  {
    \bool_if:NT \l_@@_create_bool
      { \@@_create: }
%    \end{macrocode}
%   At the beginning of table cells and inside \texttt{x}-type expansion,
%   all symbolic units need to have \emph{some} definition. 
%    \begin{macrocode}
    \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq
      {
        \cs_if_free:NT ##1
          { \cs_set_protected:Npn ##1 { \ERROR } }
      }
%    \end{macrocode}
%   Where the \pkg{soulpos} package is loaded \emph{after} \pkg{siunitx}, the
%   commands \cs{hl} and \cs{ul} will be created only after the hook is used.
%   The \pkg{soul} package creates those using \tn{newcommand}, so we have to
%   avoid an issue.
%    \begin{macrocode}
    \@ifpackageloaded { soulpos }
      {
        \@ifpackageloaded { soul }
          { }
          {
            \cs_undefine:N \hl
            \cs_undefine:N \ul
          }
      }
      { }
  }
\AtBeginDocument { \siunitx_command_create: }
\cs_new_protected:Npn \@@_create:
  {
    \bool_if:NT \l_@@_xspace_bool
      { \RequirePackage { xspace } }
    \bool_if:NT \l_@@_overwrite_bool
      {
        \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq
          { \cs_undefine:N ##1 }
      }
    \cs_set_protected:Npx \@@_create:N ##1
      {
        \ProvideDocumentCommand ##1 { \bool_if:NT \l_@@_optarg_bool { o } }
          {
            \mode_leave_vertical:
            \group_begin:
              \bool_if:NTF \l_@@_optarg_bool
                { \exp_not:N \IfNoValueTF {####1} }
                { \use_i:nn }
                {
                  \siunitx_unit_options_apply:n {##1}
                  \siunitx_unit_format:nN {##1}
                    \exp_not:N \l_@@_tmp_tl
                  \bool_if:NTF \l_@@_prespace_bool
                    { \siunitx_quantity_print:nV { } }
                    { \siunitx_print_unit:V }
                      \exp_not:N \l_@@_tmp_tl
                }
                { \siunitx_quantity:nn {####1} {##1} }
            \group_end:
            \bool_if:NT \l_@@_xspace_bool { \exp_not:N \xspace }
          }
      }
    \seq_map_function:NN \l_siunitx_unit_seq \@@_create:N
  }
\cs_new_protected:Npn \@@_create:N #1 { }
%    \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 }
  {
    free-standing-units    = false ,
    overwrite-commands     = false ,
    space-before-unit      = false ,
    unit-optional-argument = false ,
    use-xspace             = false
  }
%    \end{macrocode}
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex