diff options
author | Karl Berry <karl@freefriends.org> | 2021-10-14 20:46:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-10-14 20:46:59 +0000 |
commit | 5ef1b4d6440f33c7a741a28d4e92856ecfe7f3a3 (patch) | |
tree | 0ef37d9cecc27ecd230827eb829279998f788fb5 /Master/texmf-dist | |
parent | 79461c4ffb0d2583167aaf280b689bcaac05d688 (diff) |
lutabulartools (14oct21)
git-svn-id: svn://tug.org/texlive/trunk@60764 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
4 files changed, 754 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/luatex/lutabulartools/README.md b/Master/texmf-dist/doc/luatex/lutabulartools/README.md new file mode 100644 index 00000000000..34da5ee1e5a --- /dev/null +++ b/Master/texmf-dist/doc/luatex/lutabulartools/README.md @@ -0,0 +1,29 @@ +# lutabulartools + +This LuaLaTeX package offers some useful macros for tabular matter. The `\MC` command it provides allows one to specify a multi-row and or multi-column cell with minimal syntax. The package loads `booktabs` and adds a gray midrule, and allows a user to specify multiple `\cmidrules` with one command. + + + +# License + +Copyright (C) 2021 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. diff --git a/Master/texmf-dist/doc/luatex/lutabulartools/lutabulartools.tex b/Master/texmf-dist/doc/luatex/lutabulartools/lutabulartools.tex new file mode 100644 index 00000000000..cc0aa0ea8a8 --- /dev/null +++ b/Master/texmf-dist/doc/luatex/lutabulartools/lutabulartools.tex @@ -0,0 +1,220 @@ +% Kale Ewasiuk (kalekje@gmail.com) +% 2021-10-13 +% +% Copyright (C) 2021 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. + +\documentclass{article} +\usepackage{lutabulartools} +\usepackage{url} +\setlength{\parindent}{0ex} +\setlength{\parskip}{0.75em} +\newcommand{\PARA}[1]{\leavevmode\llap{\texttt{#1}\ \ \ }} +\newcommand{\CMD}[1]{\texttt{\textbackslash #1}} +\newcommand{\tMC}{\CMD{MC}} +\newcommand{\ttt}[1]{``\texttt{#1}''} + +\newcommand{\Example}[1]{ + \texttt{\detokenize{#1}}\par +will produce:\par +#1 +} + +\begin{document} +\vspace*{-4em} + {\noindent\huge\bfseries lutabulartools \large -- some useful tabular tools\\(LuaLaTeX-based)}\\ + 2021-09-24, Kale Ewasiuk, \url{kalekje@gmail.com} + +lutabulartools is a package that contains a few useful macros to help with tables. +Most functions require LuaLaTeX. The following packages are loaded: +{\tt +{booktabs}, +{multirow}, +{makecell}, +{xparse}, +{array}, +{xcolor}, +{colortbl}, +{luacode}, +{penlight}, +} + +\section{\texttt{\textbackslash MC} -- Magic Cell} +\texttt{\textbackslash MC} (magic cell) combines the facilities of +\CMD{multirow} and \CMD{multicolumn} from the \texttt{multirow} package, and \CMD{makcell} from the titular package. +With the help of LuaLaTeX, it takes an easy-to-use cell specification and employs said commands as required. +Here is the usage: + +\texttt{\textbackslash MC * [cell spec] <cell format> (override multicolumn col) \{contents\} } + +\PARA{*}This will wrap the entire command in \{\}. This is necessary for \texttt{siunitx} single-column width columns. +However, the \tMC\ command attempts to detect this automatically. + +\PARA{[cell spec]}% +Any letters placed in this argument are used for cell alignment. +You can use one of three: \ttt{t}, \ttt{m}, \ttt{b} for top, middle, bottom (vertical alignment), +or \ttt{l}, \ttt{c}, \ttt{r} for horizontal alignment. +By default, \tMC\ will try to autodetect the horizontal alignment based on the current column. +If it can't, it will be left-aligned. +The default vertical alginment is top. + +This argument can also contain two integers, separated by a comma (if two are used). +\ttt{C,R}, \ttt{C}, or \ttt{,R} are a valid inputs, +where R=rows (int), and C=columns, (int). +If you want a 1 column wide, multirow cell, +you can pass \ttt{,R}. These numbers can be negative. +If no spec is passed, (argument empty), \tMC\ +acts like a \texttt{makecell}. +Additionally, you can pass \ttt{+} in place of C (number of columns wide), +and it will make the cell width fill until the end of the current row. + +Examples:\\ +\ttt{\textbackslash MC[2,2]} means two columns wide, two rows tall.\\ +\ttt{\textbackslash MC[2,1]} or \ttt{\textbackslash MC[2]} or means two columns wide, one row tall.\\ +\ttt{\textbackslash MC[1,2]} or \ttt{\textbackslash MC[,2]} means one column wide, two rows tall.\\ +In any of these examples, you can place the alignment letters anywhere. + + +\PARA{(override}% +You may want to adjust the column specification of a multicolumn cell,\\ +\PARA{multicolumn)}for example, using +\texttt{@\{\}c@\{\}} to remove padding between the cell. + +\PARA{<cell format>}% +You can place formatting like \CMD{bfseries} here. + +Here's an example. + +\Example{ +\begin{tabular}{| c | c | c | c | c | c |}\toprule + \MC[2,2cm]<\tt>{2,2cm} & \MC[2r]<\tt>{2r} & 5 & \MC[,2b]<\tt>{,2b}\\ + & & 3 & 4 & 5 & \\\midrule + 1 & 2 & \MC[2l](@{}l)<\tt>{2l (\@\{\}l)} & 5 & 6666\\\cmidrule{3-4} + 1 & \MC[+r]<\tt>{+r} \\ + \\ + 1 & 2 & 3 & 4 & 5 & \MC[,-2]<\tt>{,\\-2}\\ +\end{tabular} +} + +%%% https://tex.stackexchange.com/questions/287346/width-of-column-after-multicolumn-header + +%\textbackslash MC[<spec>]{<contents} + +\subsection{Notes} +This package redefines the {\tt tabular} and {\tt tabular*| environments. +It uses Lua pattern matching to parse the column specification of the table to know how many columns there are, +and what the current column type is. If you have defined a column that creates many, it will not work. +This will be worked out in later package revisions. +%But, to know how many columns there are you, you will have +%either have to manually set todo the lua variable before the table, or, +%in the last column of the first row, \texttt{get\_tab\_colnum ()}. +%The above Lua function can be used to get the current column number. +%You will also remove the ability for this package to know what the current column spec is + + + +\section{Some additional rules} +This package also redefines the \texttt{booktabs} midrules.\\ +\PARA{\textbackslash gmidrule}is a full gray midrule.\\ +By taking advantage of knowing how many columns there are (if you chose to redefine \texttt{tabular}), +you can specify individual column numbers (for a one column wide rule), +or reference with respect to the last column (blank, \texttt{+1}, \texttt{+0}, or \texttt{+} means last column, +\texttt{+2} means second last column, for example) +or omit the last number.\\ +\PARA{\textbackslash cmidrule}is a single partial rule, with the above features\\ +\PARA{\textbackslash gcmidrule}is a single partial gray rule, with the above features\\ +You can add multiple \ttt{cmidrule}'s with the \texttt{(g)cmidrules} command. Separate with a comma. +You can apply global trimming of the rules with the \ttt{()} optional argument, and then +override it for a specific rule by placing \ttt{r} or \ttt{l} with the span specification.\\ +\PARA{\textbackslash gcmidrules}Can produce multiple, light gray partial rules\\ +\PARA{\textbackslash cmidrules}Can produce multiple black partial rules.\\ +Here's an example: + +\Example{ +\begin{tabular}{c c c c c c}\toprule + 1 & 2 & 3 & 4 & 5 & 6\\ \cmidrule{+1} % rule on last column + 1 & 2 & 3 & 4 & 5 & 6\\ \cmidrules{1,3-+3,+} % rule on first col, third to third last col, and last col + 1 & 2 & 3 & 4 & 5 & 6\\ \cmidrules{1,3-+3rl,+} % same as above, but trim middle + 1 & 2 & 3 & 4 & 5 & 6\\ \cmidrules(l){1,r3-+3,+1}% trim left for all, but only trim right for middle rule +\end{tabular} +} + +\subsection{Midrule every X\textsuperscript{th} row} + +\PARA{\textbackslash midruleX}% +With this command, you can place a rule +every X rows. +You can change the step size and what kind of midrule you prefer. +\begin{verbatim} +\def\midruleXstep{5} +\def\midruleXrule{\gmidrule} +\end{verbatim} + + +Usage: Insert midrulex at the end of each row in the column spec. Before you want counting to beg +\begin{verbatim} + +\def\midruleXstep{4} +\def\midruleXrule{\cmidrules{1,3-4}} +\begin{tabular}{rclc@{\midruleX}} % inject midrule +\toprule +Num & . & . & . \\\midrule\resetmidruleX % reset to 0 +1 & & & \\ +2 & & & \\ +3 & & & \\ +4 & & & \\ +5 & & & \\ +6 & & & \\ +7 & & & \\ +8 & & & \\ +9 & & & \\ +10 & & & \\ +11 & & & \\\resetmidruleX % dont want a bottom rule +12 & & & \\ +\bottomrule +\end{tabular} +\end{verbatim} + + will produce + +\def\midruleXstep{4} +\def\midruleXrule{\cmidrules{1,3-4}} +\begin{tabular}{rclc@{\midruleX}} % inject midrule +\toprule +Num & . & . & . \\\midrule\resetmidruleX % reset to 0 +1 & & & \\ +2 & & & \\ +3 & & & \\ +4 & & & \\ +5 & & & \\ +6 & & & \\ +7 & & & \\ +8 & & & \\ +9 & & & \\ +10 & & & \\ +11 & & & \\\resetmidruleX % dont want a bottom rule +12 & & & \\ +\bottomrule +\end{tabular} + +\end{document} +
\ No newline at end of file diff --git a/Master/texmf-dist/tex/luatex/lutabulartools/lutabulartools.lua b/Master/texmf-dist/tex/luatex/lutabulartools/lutabulartools.lua new file mode 100644 index 00000000000..40f916e3bc1 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/lutabulartools/lutabulartools.lua @@ -0,0 +1,287 @@ +--% Kale Ewasiuk (kalekje@gmail.com) +--% 2021-10-13 +--% +--% Copyright (C) 2021 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. + +local ltt = {} + +--todo clean up the code, make some stuff local +--todo maybe add the penlight lua table to latex tabular? + +--integrate current cell +--todo check if S[] column cells work!!! +--todo might be smarter to just append this to tabular commands and read argument + +-- Initialize counter variable +ltt.NumTabCols = 0 +ltt.NumTabColsAbv = 0 -- num of tab columns if above 1 +ltt.TabColSpec = '' +ltt.TabColSpecAbv = '' -- tab column spec if above 1 +ltt.CurTabColAbv = '' -- current tab column spec if above 1 +ltt.TabColNum = 0 +ltt.NumBkts = 0 +ltt.NumTabColsMX = 0 + + +--todo re=enable +local glue_t, unset_t, tabskip_st = node.id'glue', node.id'unset' +local tabskip_st = table.swapped(node.subtypes'glue').tabskip +assert(tabskip_st) + + +function ltt.get_TabColNum() + local nest + for i = tex.nest.ptr, 1, -1 do + local tail = tex.nest[i].tail + if tail.id == glue_t and tail.subtype == tabskip_st then + nest = tex.nest[i] + break + end + end + if nest then + local col = 1 + for _, sub in node.traverse_id(unset_t, nest.head) do + col = col + sub + 1 + end + ltt.TabColNum = col + else + ltt.TabColNum = 1 + end + ltt.CurTabColAbv = ltt.TabColSpecAbv:sub(ltt.TabColNum,ltt.TabColNum) + ltt.NumTabColsMX = math.max(ltt.NumTabColsMX, ltt.TabColNum) -- a different way to calculate total cols + return ltt.TabColNum +end + + +function ltt.get_TabRowNum() + return tex.count['c@RowNumCnt'] -- access latex counter +end + +-- The next function computes the number of columns from +-- contents of string 'zz' +function ltt.calc_NumTabCols( zz ) + --help_wrt(zz, 'col spec OG') + -- -- NOT NEEDED: zz = zz:gsub ( "^.-(%b{}).-$", "%1" ) -- retain the first "{....}" substring + zz = zz:gsub ( "%*%s-{(%d-)}%s-(%b{})" , -- expand expressions such as "*{5}{l}" to "lllll" + function(y, z ) z = z:sub (2 , -2) return string.rep (z, y) end ) -- + zz = zz:gsub ( "%b{}" , "" ) -- omit all stuff in curly braces and square + zz = zz:gsub ( "%b[]" , "" ) + zz = zz:gsub ( "[@!|><%s%*\']" , "" ) -- some more characters to ignore + -- todo: any columns defined that break into more than one column should be expanded here + --help_wrt(zz, 'col spec CLEAN') + ltt.TabColSpec = zz -- stripped column spec with no {} or < + ltt.NumTabCols = string.len(ltt.TabColSpec) + if ltt.NumTabCols > 1 then + ltt.TabColSpecAbv = ltt.TabColSpec + ltt.NumTabColsAbv = ltt.NumTabCols + end +end + +--todo fix square brackets after letters, expand multiple +--calc_NumTabCols('ss') +--calc_NumTabCols('*{6}{s}') +--calc_NumTabCols('l*{6}{l}') +--calc_NumTabCols('lll') +--calc_NumTabCols('ll[]') +--calc_NumTabCols('ll[]*{6}{l}') +--calc_NumTabCols('*{6}{l}') +--calc_NumTabCols('y*{6}{sq}x') +--print(_TabColSpec.. '<---Column spec') + +--http://ctan.mirror.rafal.ca/macros/latex/contrib/multirow/multirow.pdf +--http://ctan.mirror.colo-serv.net/macros/latex/contrib/makecell/makecell.pdf +-- todo CONSIDER THIS +-- https://tex.stackexchange.com/questions/331716/newline-in-multirow-environment + + + +--todo +-- if p{} column, and multirow is 1, use {=} instead of {*} +-- but note, makecell will not work. So you may want to skip it.multicolumn +-- this case should be considered in this code. +-- for example: \multirow{2}{=} + +function ltt.MagicCell(s0,spec,mcspec,pre,content) + -- + local STR = '' + reset_bkt_cnt() + + local v, h, r, c, mrowsym, skipmakecell = ltt.parse_MagicCell_spec(spec) -- get v/h align, number rows/columns + + local mcspec = mcspec or '' + + h, mcspec, c = ltt.get_HColSpec(h, mcspec, c) -- infer horizontal alignment, num columns + + --help_wrt(_CurTabColAbv,'current column') + if s0 == _xTrue or (pl.List({'S', 'Q', 'L', 'R'}):contains(ltt.CurTabColAbv) -- special columns for SI + and c == '') then -- multicolumn cannot have {} around it todo test with siunitx, num rows, num columns + STR = STR .. '{' -- multirow and makcell must have {} around it S column is used + add_bkt_cnt() + end + + if c ~= '' then + STR = STR .. "\\multicolumn{"..c.."}{"..mcspec.."}{" + add_bkt_cnt() + end + + if r ~= '' then + STR = STR .."\\multirow["..v.."]{"..r.."}{"..mrowsym.."}{" -- optional arg here + add_bkt_cnt() + end + + if not skipmakecell then + if pre ~= '' then + STR = STR.."\\renewcommand{\\cellset}{"..pre.."}" + end + + STR = STR.."\\makecell[{"..v.."}{"..h.."}]{" + add_bkt_cnt() + else + content = content:gsub('\\\\', '\\newline') + end + + STR = STR..content..close_bkt_cnt() + --Troubleshooting + --help_wrt(STR..' <<< magic cell string') + tex.sprint(STR)--tex print the STR +end + + +function ltt.parse_MagicCell_spec(spec) + local mrowsym = '*' + local skipmakecell = false + if string.find(spec, '=') then + spec = spec:gsub('=', '') + mrowsym = '=' + skipmakecell = true + end + + spec = spec:lower():gsub('%s','') -- take lower case and remove + local vh, rc = spec:gextract('%a') -- extract characters + local v = vh:gfirst({'t', 'm', 'b'}) or 't' + local h = vh:gfirst({'l', 'c', 'r'}) or '' + v = v:gsub('m', 'c') + + local rc_ = (rc):split(',') + local c = rc_[1] or '' --num columns, width + local r = rc_[2] or '' --num rows, height + if c == '0' or c == '1' then c = '' end + if r == '0' or r == '1' then r = '' end + + return v, h, r, c, mrowsym, skipmakecell +end + + +ltt.TabColMapping = { -- horizontal cell alignment that multicolumn should use if () or [hori] not passed to func + l = 'l', + c = 'c', + r = 'r', + p = 'p', + P = 'c', + X = 'l', + Y = 'c', + Z = 'l', + N = 'c', + L = 'l', + R = 'r', + C = 'c', +} + +function ltt.get_HColSpec(h, mcspec, c) -- take horizontal alignment + -- c is num columns, h is horizontal alginment, + --Assumes _TabColNum was calculated previosly + ltt.get_TabColNum() + if c == '+' then -- fill row to end + c = tostring(ltt.NumTabColsAbv - ltt.TabColNum + 1) + end + if h == '' then -- if horizontal not provided, use declared column + h = ltt.TabColMapping[ltt.CurTabColAbv] or 'l' + end + if c ~= '' then -- only make new mcspec if column nums > 0 + if mcspec == '' then -- and if no mcspec was passed + mcspec = h + if ltt.TabColNum == 1 then -- if first column, auto detect padding + mcspec = '@{}'..mcspec + end + if (ltt.TabColNum + tonumber(c) - 1) == ltt.NumTabColsAbv then -- if end on last column + mcspec = mcspec..'@{}' + end + else -- if mcspec if given, extract the alignment + ltt.calc_NumTabCols(mcspec) + h = ltt.TabColSpec -- get 1 character column spec from mcspec and override h + end + end + return h, mcspec, c +end + + +-- midrule stuff + +function ltt.get_midrule_col(s) + if string.find(s, '+') then + s = s:gsub('+', '') + if (s == '') or (s == '0') then + s = 1 + end + s = tostring(ltt.NumTabColsAbv - tonumber(s) + 1) -- use number of tabular columns above 0, + end + return s +end + +--todo if comma present, create multiple according to spec. Also allow LR in [] + +--- midrule stuff --- + +function ltt.make1cmidrule(s, r, c, cmd) -- s=square r=round c=curly + cmd = '\\'..cmd + if s ~= '' then + cmd = cmd..'['..s..']' + end + if r ~= '' then + cmd = cmd..'('..r..')' + end + t = string.split(c, '-') + if t[2] == '' then + t[2] = '+' + end + if t[2] == nil then + t[2] = t[1] + end + c = ltt.get_midrule_col(t[1])..'-'..ltt.get_midrule_col(t[2]) + cmd = cmd..'{'..c..'}' + --help_wrt(cmd) + tex.print(cmd) +end + +function ltt.makecmidrules(s, r, c, cmd) + for k, c1 in pairs(string.split(c, ',')) do + r1, c2 = c1:gextract('%a') + if r1 == '' then -- if nothing passed in with the column + r1 = r -- set to the global value passed in round brackets + end + ltt.make1cmidrule(s, r1:strip(), c2:strip(), cmd) + end +end + + +return ltt -- lutabulartools
\ No newline at end of file diff --git a/Master/texmf-dist/tex/luatex/lutabulartools/lutabulartools.sty b/Master/texmf-dist/tex/luatex/lutabulartools/lutabulartools.sty new file mode 100644 index 00000000000..450a0d0cbef --- /dev/null +++ b/Master/texmf-dist/tex/luatex/lutabulartools/lutabulartools.sty @@ -0,0 +1,218 @@ +% Kale Ewasiuk (kalekje@gmail.com) +% 2021-10-13 +% +% Copyright (C) 2021 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}[2021-10-13] + +\RequirePackage{booktabs} +\RequirePackage{multirow} +\RequirePackage{makecell} +\RequirePackage{xparse} +\RequirePackage{array} +\RequirePackage{xcolor} +\RequirePackage{colortbl} +\RequirePackage{luacode} +\RequirePackage[pl,extras]{penlight} % NEEDED + +\luadirect{lutabt = require('lutabulartools')} + + + +% DOES NOT WORK WITH colortbl package ??? + + +%% adapted from +% https://tex.stackexchange.com/questions/182953/add-midrule-every-5-lines-automatically +\def\midruleXstep{5} +\def\midruleXrule{\gmidrule} + +\newcounter{midruleX} +\newcommand*{\midruleX}{% + \aftergroup\aftergroup\aftergroup\midruleXaux +} +\newif\ifmidruleX +\makeatletter +\newcommand*{\midruleXaux}{% + \noalign{% + \stepcounter{midruleX}% + \ifnum\value{midruleX}=\midruleXstep % + \global\midruleXtrue + \resetmidruleX% + \else + \global\midruleXfalse + \fi + } + \ifmidruleX\midruleXrule\fi +} +\newcommand*{\resetmidruleX}{\setcounter{midruleX}{0}} %%% todo maybe put noalign in here +\makeatother + +\resetmidruleX + +%% https://tex.stackexchange.com/questions/145084/what-is-the-function-of-noalign +%\begin{tabular}{rclc@{\midruleX}} % inject midrule +%\toprule +%Number & Student Id & Name & Score\\\midrule\resetmidruleX % reset to 0 +%1 & 14-001 & Andy & 75 \\ +%2 & & & \\ +%3 & & & \\ +%4 & & & \\ +%5 & & & \\ +%6 & & & \\ +%7 & & & \\ +%8 & & & \\ +%9 & & & \\\resetmidruleX +%10 & & & \\%\noalign{\resetmidruleX} % noalig required to not cause error with bottomrule, but that's oka because it should be used on row 9 anyway +%\bottomrule +%\end{tabular} + + +%%%% + +%%% gray midrule and gray cmidrule + +\providecommand{\gmidrule}{\arrayrulecolor{lightgray}\specialrule{\lightrulewidth}{0.4\aboverulesep}{0.6\belowrulesep}\arrayrulecolor{black}} + +%%% 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 +\makeatletter +\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.4\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.6\belowrulesep + \global\@lastruleclass=\z@ + \fi\fi + \ifnum0=`{\fi} + \arrayrulecolor{black}}% Switch colour back to black +\makeatother + +%%% + +\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') + }% +} + + + + + +%%% tabular commands + +\newcommand{\TabColNum}{\luadirect{tex.print(lutabt.get_TabColNum())}} % prints the current column number of tabular +\newcommand{\NumTabCols}{\luadirect{tex.print(lutabt.NumTabCols)}} % prints the total num columns of tabular +\newcounter{RowNumCnt} +\setcounter{RowNumCnt}{1} + +\let\oldtabular\tabular +\RenewExpandableDocumentCommand{\tabular}{ O{c} m }{% + \setcounter{RowNumCnt}{1}% + \luadirect{lutabt.calc_NumTabCols(\luastringN{#2})}% + \luadirect{lutabt.NumTabColsMX = 0}% fall back if calc doesnt work for some reason + \oldtabular[#1]{@{\stepcounter{RowNumCnt}}#2@{\luadirect{lutabt.get_TabColNum()}}}% +} + +\expandafter\let\expandafter\oldtabulars\csname tabular*\endcsname +\expandafter\let\expandafter\endoldtabulars\csname endtabular*\endcsname +\RenewDocumentEnvironment{tabular*}{ m O{c} m }{% + \setcounter{RowNumCnt}{1}% + \luadirect{lutabt.calc_NumTabCols(\luastringN{#3})}% + \luadirect{lutabt.NumTabColsMX = 0}% fall back if calc doesnt work for some reason + \begin{oldtabulars}{#1}[#2]{@{\stepcounter{RowNumCnt}}#3@{\luadirect{lutabt.get_TabColNum()}}} +}{% + \end{oldtabulars}% +} +%%% NOTE tabularx uses tabular*, NO NEED TO CHANGE TABULARX! + + +%s0,spec,mcspec,pre,content +% Magic Cell +\NewExpandableDocumentCommand{\MC}{ s O{} D(){} D<>{} m }{% +% Magic cell *wraps with {} but automatically checks for SI column, + % [column spec] (mult-column spec override) <pre-cell stuff> {cell content} +\luadirect{lutabt.MagicCell( + \luastring{#1}, + \luastring{#2}, + \luastringN{#3}, + \luastringN{#4}, + \luastringN{#5} +)}} + + + + +\ProcessOptions + |