% Kale Ewasiuk (kalekje@gmail.com) % 2023-07-22 % Copyright (C) 2021-2023 Kale Ewasiuk % % Permission is hereby granted, free of charge, to any person obtaining a copy % of this software and associated documentation files (the "Software"), to deal % in the Software without restriction, including without limitation the rights % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell % copies of the Software, and to permit persons to whom the Software is % furnished to do so, subject to the following conditions: % % The above copyright notice and this permission notice shall be included in % all copies or substantial portions of the Software. % % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF % ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED % TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A % PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT % SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR % ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN % ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE % OR OTHER DEALINGS IN THE SOFTWARE. \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{lutabulartools}[2023-07-22] \RequirePackage{booktabs} \RequirePackage{multirow} \RequirePackage{longtable} \RequirePackage{makecell} \RequirePackage{xparse} \RequirePackage{array} \RequirePackage{xcolor} \RequirePackage{colortbl} \RequirePackage{luacode} \RequirePackage{penlightplus} % NEEDED, extras option must be used so penlight should be loaded before this... \luadirect{lutabt = require('lutabulartools')} \newcommand{\lttdebugON}{\luadirect{lutabt.debug = true}} \newcommand{\lttdebugOFF}{\luadirect{lutabt.debug = true}} \newcommand{\lttdebugprt}{\luadirect{__lutabt__debugprtall()}} \newcolumntype{\lttltrim}{} \newcolumntype{\lttrtrim}{} %%% midrule every X rows % NO LONGER NEEDED %%% this was used for @{\midruleX} in colspec, but I made a better way %\def\midruleX{\aftergroup\aftergroup\aftergroup\midruleX@aux} %\def\midruleX@aux{\luadirect{lutabt.mrX.midruleX('')}} % %%% \NewDocumentCommand{\midruleX}{s O{N} m}{% \MakeluastringCommands[N]{#2}% \luadirect{lutabt.mrX.set_midruleX(\plluastringA{#3}, \luastring{#1})}% } \NewDocumentCommand{\resetmidruleX}{O{0}}{\luadirect{lutabt.mrX.reset_midruleX(\luastring{#1})}} \NewDocumentCommand{\settabular}{s m}{\luadirect{lutabt.set_tabular(\luastring{#2})}} % \def\ltt@resetrownum{\luadirect{lutabt.reset_rows()}} \def\ltt@resetrownumhard{\luadirect{lutabt.row_num = 0}} \def\ltt@autotoprule{\luadirect{lutabt.process_auto_topbot_rule('top')}} \def\ltt@autobotrule{\luadirect{lutabt.process_auto_topbot_rule('bottom')}} \def\ltt@storeautotbandfalse{\luadirect{ lutabt.auto_topbot_old = lutabt.auto_topbot lutabt.auto_topbot = false}} \def\ltt@restoreautotb{\luadirect{lutabt.auto_topbot = lutabt.auto_topbot_old}} \def\ltt@inctablelevel{\luadirect{lutabt.tablelevel = lutabt.tablelevel + 1}} \def\ltt@dectablelevel{\luadirect{lutabt.tablelevel = lutabt.tablelevel - 1}} \def\ltt@midruleXoff{\luadirect{lutabt.mrX.off()}} \def\ltt@actlevelreset{\luadirect{lutabt.actlvl = 1}} \apptocmd{\@arraycr}{\luadirect{lutabt.process_auto_rules()}}{}{} \NewDocumentCommand{\midrulesat}{m}{\luadirect{lutabt.add_auto_midrules(\luastring{#1})}} %%%% %%% gray midrule and gray cmidrule \aboverulesep=0.0ex \belowrulesep=0.5ex \providecommand{\gmidrule}{\arrayrulecolor{lightgray}\specialrule{\lightrulewidth}{0.5\aboverulesep}{0.5\belowrulesep}\arrayrulecolor{black}} \cmidrulewidth=\lightrulewidth %%% use gcmidrule for a gray "c" midrule % Copy \cmidrule from % http://mirrors.ctan.org/macros/latex/contrib/booktabs/booktabs.dtx % and modify it for insertion of \arrayrulecolor{lightgray} at the start, % and \arrayrulecolor{black} at the end \def\oldgcmidrule{\arrayrulecolor{lightgray}% Switch colour to lightgray \noalign{\ifnum0=`}\fi \@ifnextchar[{\@gcmidrule}{\@gcmidrule[\cmidrulewidth]}} \def\@gcmidrule[#1]{\@ifnextchar({\@@gcmidrule[#1]}{\@@gcmidrule[#1]()}} \def\@@gcmidrule[#1](#2)#3{\@@@gcmidrule[#3]{#1}{#2}} \def\@@@gcmidrule[#1-#2]#3#4{\global\@cmidla#1\relax \global\advance\@cmidla\m@ne \ifnum\@cmidla>0\global\let\@gtempa\@cmidrulea\else \global\let\@gtempa\@cmidruleb\fi \global\@cmidlb#2\relax \global\advance\@cmidlb-\@cmidla \global\@thisrulewidth=#3 \@setrulekerning{#4} \ifnum\@lastruleclass=\z@\vskip 0.5\aboverulesep\fi \ifnum0=`{\fi}\@gtempa \noalign{\ifnum0=`}\fi\futurenonspacelet\@tempa\@xgcmidrule} \def\@xgcmidrule{% \ifx\@tempa\gcmidrule \vskip-\@thisrulewidth \global\@lastruleclass=\@ne \else \ifx\@tempa\morecmidrules \vskip \cmidrulesep \global\@lastruleclass=\@ne\else \vskip 0.5\belowrulesep \global\@lastruleclass=\z@ \fi\fi \ifnum0=`{\fi} \arrayrulecolor{black}}% Switch colour back to black %%% \let\oldcmidrule\cmidrule % improve cmidrule. Can reference column number from back with a +, eg, {3+-2+} means third to second last \RenewExpandableDocumentCommand{\cmidrule}{ O{} D(){} m }{% \luadirect{lutabt.make1cmidrule( \luastringN{#1}, \luastring{#2}, \luastring{#3}, 'oldcmidrule') }% } \NewExpandableDocumentCommand{\cmidrules}{ O{} D(){} m }{% supports comma in {} \luadirect{lutabt.makecmidrules( \luastringN{#1}, \luastring{#2}, \luastring{#3}, 'cmidrule') }% } \NewExpandableDocumentCommand{\gcmidrule}{ O{} D(){} m }{% \luadirect{lutabt.make1cmidrule( \luastringN{#1}, \luastring{#2}, \luastring{#3}, 'oldgcmidrule') }% } \NewExpandableDocumentCommand{\gcmidrules}{ O{} D(){} m }{% supports comma in {}, rl can be passed as well \luadirect{lutabt.makecmidrules( \luastringN{#1}, \luastring{#2}, \luastring{#3}, 'gcmidrule') }% } \apptocmd{\LTXtable}{\ltt@actlevelreset\ltt@resetrownumhard\luadirect{lutabt.tablelevel=0}}{}{} \let\oldtabular\tabular \let\oldendtabular\endtabular \RenewExpandableDocumentCommand{\tabular}{ O{l} m }{% \luadirect{lutabt.set_col_spec(\luastringN{#2})}% \oldtabular[#1]{\lttltrim#2\lttrtrim}\ltt@inctablelevel\ltt@resetrownum\ltt@autotoprule% } \def\endtabular{\ltt@autobotrule\ltt@midruleXoff\ltt@dectablelevel\oldendtabular} \expandafter\let\expandafter\oldtabulars\csname tabular*\endcsname \expandafter\let\expandafter\endoldtabulars\csname endtabular*\endcsname \RenewDocumentEnvironment{tabular*}{ m O{l} m }{% \luadirect{lutabt.set_col_spec(\luastringN{#3})}% \begin{oldtabulars}{#1}[#2]{\lttltrim#3\lttrtrim}\ltt@inctablelevel\ltt@resetrownum\ltt@autotoprule% }{% \ltt@autobotrule\ltt@midruleXoff\ltt@dectablelevel\end{oldtabulars}% } %%% NOTE tabularx uses tabular*, NO NEED TO CHANGE TABULARX! \let\oldlongtable\longtable \RenewExpandableDocumentCommand{\longtable}{ O{l} m }{% \ltt@storeautotbandfalse% \luadirect{lutabt.set_col_spec(\luastringN{#2})}% \oldlongtable[#1]{\lttltrim#2\lttrtrim}\ltt@inctablelevel\ltt@resetrownum% } \let\oldendlongtable\endlongtable \def\endlongtable{\ltt@restoreautotb\ltt@midruleXoff\ltt@dectablelevel\oldendlongtable}% restore status of auto topbot rule %s0,spec,mcspec,pre,content % Magic Cell \NewExpandableDocumentCommand{\MC}{ s O{} O{} D<>{} D(){x} m }{% % Magic cell *wraps with {} but automatically checks for SI column, % [column spec] [mult-column spec override] (add rule) {cell content} \luadirect{lutabt.MagicCell( \luastring{#1}, \luastring{#2}, \luastringN{#3}, \luastringN{#4}, \luastringN{#6}, \luastring{#5} )}} \NewDocumentCommand{\setMCrepl}{m m}{\luadirect{ lutabt.col_replaces.#1 = '#2' }} \NewDocumentCommand{\setMChordef}{ m m}{\luadirect{ lutabt.col_hor_repl.#1 = '#2' }} \NewDocumentCommand{\setMCverdef}{ m m}{\luadirect{ lutabt.col_ver_repl.#1 = '#2' }} \NewDocumentCommand{\addMCsicol}{ m }{\luadirect{ lutabt.SI_cols[\string##lutabt.SI_cols+1] = '#1' }} \NewDocumentCommand{\forcecolspec}{ m }{\luadirect{ lutabt.col_spec = (\luastring{#1}):totable() }} \ProcessOptions