% \iffalse
%<*driver>
\documentclass{l3doc}
\usepackage[override=global]{booktabstabular}
\usepackage[T1]{fontenc}
\EnableCrossrefs%
\CodelineIndex%
\RecordChanges%
\newenvironment{publicmacro}[1]{\DescribeMacro{#1}}{}
\begin{document}
  \DocInput{booktabstabular.dtx}
\end{document}
%</driver>
% \fi
%
% \ProvidesFile{booktabstabular.dtx}
%   [2026/06/26 v1.1.1 tabular and tabular* wrappers with booktabs rules]
%
% \CheckSum{69}
%
% \changes{v1.0.0}{2026/03/27}{Initial release.}
% \changes{v1.1.0}{2026/04/10}{Added the \texttt{override} package option.}
% \changes{v1.1.1}{2026/06/26}{Delegate wrapper closing to the saved original tabular end code.}
%
% \GetFileInfo{booktabstabular.dtx}
%
% \title{Automatic booktabs rules for tabular/tabular*}
% \author{Moritz R. Schäfer}
% \date{\filedate\space \fileversion}
%
% \maketitle
%
% \tableofcontents
%
% \section{Introduction}
% The \textsf{booktabstabular} package provides wrapper environments around
% |tabular| and |tabular*| that insert \cs{toprule} at the beginning,
% \cs{bottomrule} at the end, and locally remap the legacy |\hline| and |\cline|
% commands to their booktabs equivalents \cs{midrule} and \cs{cmidrule}.
% It also provides commands and options to temporarily override the standard
% |tabular| and |tabular*| environments so that existing documents can opt into
% this behaviour without rewriting each table.
%
% \subsection{Example}
% A typical opt-in workflow is:
%
% \begin{verbatim}
% \usepackage[override=global]{booktabstabular}
% 
% \begin{tabular}{lll}
%   First  & Second & Third \\
%   \hline % mapped to \midrule
%   Alpha  & Beta   & Gamma
% \end{tabular}
% \end{verbatim}
%
% Alternatively, the wrapper environments can be used directly:
%
% \begin{verbatim}
% \begin{booktabstabular}{lll}
%   First  & Second & Third \\
%   \hline
%   Alpha  & Beta   & Gamma
% \end{booktabstabular}
% \end{verbatim}
%
% Both should yield the following output:
% \begin{tabular}{lll}
%   First  & Second & Third \\
%   \hline
%   Alpha  & Beta   & Gamma
% \end{tabular}
% As you can see, |\toprule| and |\bottomrule| are automatically inserted, and
% |\hline| is remapped to |\midrule|, so the table is typeset according to
% booktabs guidelines. The same applies to |tabular*| when using the
% |booktabstabular*| environment or the overridden |tabular*| name.
% \begin{verbatim}
% \begin{booktabstabular*}{\textwidth}{l@{\extracolsep{\fill}}l}
%   First  & Second \\
%   \hline
%   Alpha  & Beta
% \end{booktabstabular*}
% \end{verbatim}
% which produces the slightly wider table
% \begin{booktabstabular*}{.4\textwidth}{l@{\extracolsep{\fill}}l}
%   First  & Second \\
%   \hline
%   Alpha  & Beta
% \end{booktabstabular*}.
%
% \subsection{Notes}
% This package deliberately does not insert any intermediate rule such as
% \cs{midrule} automatically; that remains the author's responsibility.
%
% The end wrapper inserts \cs{bottomrule} at the legal alignment boundary,
% so the final row may be written either with or without a trailing |\\|.
%
% The package does not attempt to remap the legacy |\hline| and |\cline| outside
% of the wrapper environments, so they will continue to work as normal in
% documents that only use the wrappers for a subset of tables.
%
% The package affects only |tabular| and |tabular*|. It does not modify
% |array|, |longtable|, or any other alignment environment.
%
% \StopEventually{\PrintChanges\PrintIndex}
%
% \section{Interface and Implementation}
% Since the package is rather small, we will present the interface and
% implementation together in the following subsections.
%    \begin{macrocode}
%<*package>
\RequirePackage{booktabs}
\ProvidesExplPackage
  {booktabstabular}
  {2026-06-26}
  {1.1.1}
  {tabular/tabular* wrappers with booktabs rules}
%    \end{macrocode}
% \subsection{Environments}
% \begin{environment}{origtabular}
% \begin{environment}{origtabular*}
% The |origtabular| and |origtabular*| environments are copies of the original
% |tabular| and |tabular*| environments. They are used internally but also made
% available for users who want to call the original versions if they have
% overridden the standard names.
%    \begin{macrocode}
\NewEnvironmentCopy { origtabular } { tabular } 
\NewEnvironmentCopy { origtabular* } { tabular* } 
%    \end{macrocode}
% \end{environment}
% \end{environment}
%
% \begin{environment}{booktabstabular}
% The |booktabstabular| environment is a drop-in wrapper for |tabular|. It
% accepts the same arguments as |tabular|: an optional position specifier
% |[t]| or |[b]|, followed by the column specification.
%
% It calls the copied begin macro directly rather than nesting a separate
% environment, which keeps LaTeX's environment stack balanced when the
% custom end code is used.
%    \begin{macrocode}
\NewDocumentEnvironment { booktabstabular } { o m }
  {
    \__booktabstabular_begin:n
      {
        \IfNoValueTF { #1 } 
          { \origtabular { #2 } }
          { \origtabular [ #1 ] { #2 } }
      }
  }
  { \__booktabstabular_end:n { \endorigtabular } }
%    \end{macrocode}
% \end{environment}
%
% \begin{environment}{booktabstabular*}
% The |booktabstabular*| environment is a drop-in wrapper for |tabular*|.
% It accepts the width, an optional position specifier, and the column
% specification.
%    \begin{macrocode}
\NewDocumentEnvironment { booktabstabular* } { m o m }
  {
    \__booktabstabular_begin:n
      {
        \IfNoValueTF { #2 } 
          { \use:c { origtabular* } { #1 } { #3 } }
          { \use:c { origtabular* } { #1 } [ #2 ] { #3 } }
      }
  }
  { \__booktabstabular_end:n { \use:c { endorigtabular* } } }
%    \end{macrocode}
% \end{environment}
%
% \subsection{Public commands}
% \begin{publicmacro}{\overridetabular}
% After calling \cs{overridetabular}, the public |tabular| and |tabular*|
% environments are rebound to the wrapper environments provided by this
% package. Note that many classes, including the standard classes, use a
% tabular in unexpected places, \textit{i.e.}, to typeset the list of authors.
% if you don't want that to be affected, you should use the |override| package
% option.
%
%    \begin{macrocode}
\NewDocumentCommand \overridetabular {}
  {
    \RenewEnvironmentCopy { tabular } { booktabstabular }
    \RenewEnvironmentCopy { tabular* } { booktabstabular* }
  }
%    \end{macrocode}
% \end{publicmacro}
%
% \begin{publicmacro}{\restoretabular}
% The command \cs{restoretabular} restores the original definitions of
% |tabular| and |tabular*|.
%
%    \begin{macrocode}
\NewDocumentCommand \restoretabular {}
  {
    \RenewEnvironmentCopy { tabular } { origtabular }
    \RenewEnvironmentCopy { tabular* } { origtabular* }
  }
%    \end{macrocode}
% \end{publicmacro}
%
% \subsection{Options}
% We offer an option to automatically override the standard |tabular| and |tabular*|
% environments.
%
% \DescribeOption{override}
% The |override| option selects how |tabular| and |tabular*| are rebound.
% The full syntax is \texttt{\detokenize{override=none|table|global}}.
% \begin{description}
%   \item[|none|] Do not override the standard environments.
%   \item[|global|] This has almost the same effect as calling
%     \cs{overridetabular} after loading the package. The difference is that
%     the package option automatically disables the override around
%     \cs{maketitle} to avoid affecting the title page, while the command does
%     not.
%   \item[|table|] Override |tabular| and |tabular*| only inside
%     |table| and |table*| environments. This is the safest and \textbf{recommended}
%     option.
% \end{description}
%    \begin{macrocode}
\str_new:N \l__booktabstabular_override_str
\DeclareKeys [ booktabstabular ]
  {
    override .choices:nn =
      { none , table , global }
      { \str_set_eq:NN \l__booktabstabular_override_str \l_keys_choice_str } ,
    override .initial:n = none ,
%    \end{macrocode}
%
% \begin{publicmacro}{overridetabular}
% The |overridetabular| option is a legacy alias for |override=global|, and is
% provided for backwards compatibility.
%    \begin{macrocode}
    overridetabular .meta:n        = { override = global } ,
  }

\ProcessKeyOptions [ booktabstabular ]
%    \end{macrocode}
% \end{publicmacro}
%
% \section{Internal Helpers}
% \begin{macro}{\__booktabstabular_rulesetup:}
% Called at the beginning of the wrapper environments. Maps legacy horizontal
% rules to booktabs-style rules inside the wrappers and inserts |\toprule| at
% the beginning of the table. Note that we need to open a group here to keep
% the redefinitions local to the table. This group needs to be closed in the
% end code.
%    \begin{macrocode}
\cs_new_protected:Nn \__booktabstabular_begin:n
  {
    \group_begin:
    \cs_set_eq:NN \hline \midrule
    \cs_set_eq:NN \cline \cmidrule
    #1
    \toprule
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__booktabstabular_end:n}
% Called at the end of the wrapper environments. It ends the current alignment
% row, inserts |\bottomrule| at the legal alignment boundary, then delegates the
% remaining close sequence to the saved original end code. This avoids copying
% kernel or package internals such as tagging sockets. Close the group that was
% opened in the begin code afterwards.
%    \begin{macrocode}
\cs_new_protected:Nn \__booktabstabular_end:n
  {
    \crcr
    \bottomrule
    #1
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__booktabstabular_apply_override:}
% Applies the override according to the value of the |override| option. 
%    \begin{macrocode}
\cs_new_protected:Nn \__booktabstabular_apply_override:
  {
    \str_case:Vn \l__booktabstabular_override_str
      {
        { none }   { }
        { global } { \__booktabstabular_activate_global: }
        { table }  { \__booktabstabular_activate_float: }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__booktabstabular_activate_global:}
% The function called if the |override| option is set to |global|.
%    \begin{macrocode}
\cs_new_protected:Nn \__booktabstabular_activate_global:
  {
    \hook_gput_code:nnn { cmd/maketitle/before } { . } { \restoretabular }
    \hook_gput_code:nnn { cmd/maketitle/after }  { . } { \overridetabular }
    \overridetabular
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\__booktabstabular_activate_float:}
% The function called if the |override| option is set to |table|.
%    \begin{macrocode}
\cs_new_protected:Nn \__booktabstabular_activate_float:
  {
    \hook_gput_code:nnn { env/table/begin }  { . } { \overridetabular }
    \hook_gput_code:nnn { env/table*/begin } { . } { \overridetabular }
  }
%    \end{macrocode}
% \end{macro}
%
% Finally, we call the function at the end of the package to apply the override
% if requested.
%    \begin{macrocode}
\__booktabstabular_apply_override:
%</package>
%    \end{macrocode}
%
\endinput
