summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-03-05 22:11:19 +0000
committerKarl Berry <karl@freefriends.org>2018-03-05 22:11:19 +0000
commitbb7ef4b993327dd47fb8f1848e1603f93f12eb64 (patch)
tree444d575b3e1dfe4ab62a4e7a9f1a51bad8b2835c
parent5be9113099c0cd49e0f0702753be415abdac12b0 (diff)
tabstackengine (5mar18)
git-svn-id: svn://tug.org/texlive/trunk@46848 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.pdfbin569190 -> 598495 bytes
-rw-r--r--Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.tex208
-rw-r--r--Master/texmf-dist/tex/latex/tabstackengine/tabstackengine.sty204
3 files changed, 361 insertions, 51 deletions
diff --git a/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.pdf b/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.pdf
index c288ddfd20f..66dd8ba232b 100644
--- a/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.pdf
+++ b/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.tex b/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.tex
index fa4be38a47b..02e3bf02bb4 100644
--- a/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.tex
+++ b/Master/texmf-dist/doc/latex/tabstackengine/tabstackengine.tex
@@ -1,7 +1,7 @@
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
-\usepackage{tabstackengine}
+\usepackage[TABcline]{tabstackengine}
\usepackage{verbatimbox}
\usepackage{xcolor}
\parindent 0in\parskip 1em \newlength\dotscale
@@ -20,12 +20,16 @@
\catcode`<=\active %
\catcode`!=\active %
\def\vbspecial#1>{\textit{\rmfamily#1}}
-\def\vbdelim{\catcode`<=\active \catcode`>=\active \catcode`!=\active \def<{\vbspecial}\def>{}\def!{\textrm{(provided by \ste)}}}
+\def\vbdelim{\catcode`<=\active \catcode`>=\active \catcode`!=\active \def<{\vbspecial}\def>{}\def!{\stringrms}}
\catcode`!=12 %
\catcode`>=12 %
\catcode`<=12 %
\def\endvbdelim{\catcode`>=12 \catcode`<=12 }
+\def\stringrms#1{%
+ \ifx1#1\relax\textrm{(provided by \ste)}\fi%
+ \ifx2#1\relax\textrm{(only with \texttt{TABcline} package option)}\fi%
+}
\begin{document}
\begin{center} \LARGE The {\tst} Package\\ \rule{0em}{.7em}\small
@@ -45,12 +49,12 @@ such a way that the end-of-line (EOL)
character in certain stacking arguments will be taken, by default,
as \vb|\\|, rather
than a space (which is the default EOL separator in \ste).
-The EOL separator can be changed using \ste{}'s \vb|\setstackEOL| macro.
+The EOL separator can be changed using \ste{}'s \cmd{setstackEOL} macro.
With \tst, command variations are introduced to allow several variants
of tabbing within the macro arguments. The default tabbing character is
the ampersand (\vb|&|); however, the tabbing character can be reset to
-other tokens using the \verb|\setstackTAB| macro.
+other tokens using the \vb|\setstackTAB| macro.
\begin{sloppypar}
In most cases (where it makes sense), a {\ste} macro name may be
@@ -145,6 +149,99 @@ Note that these \cmd{setstack...gap} macros are for setting horizontal
gaps between columns of a stack. They should not be confused with
the \cmd{setstackgap} macro of {\ste} that sets the vertical gap
for long and short stacks.
+
+\section{Horizontal Rules}\label{s:hr}
+
+As of version 2.10, \tst{} provides the facility to lay down horizontal rules
+ that fill up the TABstack cell width.
+There are two ways that this may be accomplished.
+First, the macro \vb|\TABrule[<|\textit{vertical shift}\vb|>]|%
+\margcmd{TABrule}
+ may be specified as the entry in a cell, in order to place a horizontal
+ rule, of thickness \vb|\fboxrule| across the width of the cell.%
+\footnote{The width of the \cmd{TABrule} will actually be the width of
+ the widest data in that column. This has implications when the
+ \cmd{fixTABwidth} switch is set true, in that some columns will
+ be typeset wider than their widest data.}
+The optional argument specifies the vertical shift of the rule.
+The default vertical shift, initially 0pt, may also be specified in the
+ length \cmd{TABruleshift}.\margcmd{TABruleshift}
+
+So, for example,
+
+\vb|\tabbedstackon{a&bb&CCC&dddd}{&\TABrule&&\TABrule}|
+
+ will yield this result:
+ \tabbedstackon{a&bb&CCC&dddd}{&\TABrule&&\TABrule}.
+Note that the vertical spacing around the \vb|\TABrule| will conform
+ to the stackengine rules set by \vb|\setstackgap|, for both ``short'' and
+ ``long'' stacks.
+In essence, the \vb|\TABrule|s literally constitute their own row in the stack.
+
+A \vb|\TABrule| may also constitute a cell that contains actual [non-rule]
+ data elsewhere on the row.
+So, for example,
+
+\vb|\tabbedLongstack{aa&\TABrule\\\TABrule&bbb}|
+
+produces the result \tabbedLongstack{aa&\TABrule\\\TABrule&bbb}.
+
+If a row of the TABstack is to be composed solely of rules, then these rules
+ can also be achieved in a second way.
+
+\subsection{The \texttt{TABcline} Package Option}\label{s:rtx}
+
+There is also introduced in version 2.10, a package option \vb|TABcline|,
+ invoked in the standard way via \vb|\usepackage[TABcline]{tabstackengine}|.
+This option reduces the efficiency of the package slightly, but provides
+ two macros that can enhance convenience.
+The two macros that are activated with this package option are \vb|\TABcline{}|%
+\margcmd{TABcline}
+ and \vb|\relaxTABsyntax|.
+The macro
+
+\vb|\TABcline{<|\textit{col1}\vb|>,<|\textit{col2}\vb|>,<|%
+ \textit{col3--col4}\vb|>,...}|
+
+provides a shorthand notation for creating a row of \vb|\TABrule|s.
+For example, in a five-column TABstack, the shorthand
+
+\vb|\TABcline{1,3-4}|
+
+is equivalent to (assuming column separator as \vb|&|, spaces
+inserted for clarity)
+
+\vb|\TABrule & & \TABrule & \TABrule &|
+
+Furthermore, if the \vb|\TABcline| occurs prior to the last row of the
+ TABstack, an end-of-line (EOL) token (\textit{e.g.}, \vb|\\|) is also
+ suffixed to the replacement.
+Thus,
+
+\vb|\tabbedShortstack{\TABcline{2-3}\TABcline{1,3-4}a&bb&CCC&dddd}|
+
+produces \tabbedShortstack{\TABcline{2-3}\TABcline{1,3-4}a&bb&CCC&dddd}.
+
+When the \texttt{TABcline} package option is selected,
+ the \vb|\relaxTABsyntax|%
+\margcmd{relaxTABsyntax}
+ switch may also be invoked to address an issue of
+ bad syntax.
+Some users have a tendency to tack a trailing stack-EOL to the end of
+ an input argument, in the manner of \vb|\tabbedLongstack{a&bb\\cc&d\\}|.
+This rightfully provokes a \loi{} invalid-index error in \tst{}, because
+ the syntax implies the creation of a third row of a 2-column TABstack,
+ for which no column separators have been specified.
+
+However, some may find the error message difficult to understand, especially
+ because similar syntax is benign in the \texttt{tabular} environment and
+ non-fatal in the \texttt{align} family of environments.
+If the switch \vb|\relaxTABsyntax| is in force, the compilation will instead
+ succeed, with the trailing row of the TABstack left blank, in the manner
+ of {\relaxTABsyntax\tabbedLongstack{a&bb\\cc&d\\}}.
+Such syntax is still considered bad form, but by compiling without error,
+ the visual result may make the source of the problem more obvious to the
+ user.
\clearpage
\section{Command Summary}
@@ -200,15 +297,20 @@ In the syntax shown below, when there are multiple commands delimited by
\rmfamily\normalsize
-The macro\margcmd{ensureTABstackMath}
+The ``\textit{tabbed EOL separated string}'' can contain not only regular
+ \LaTeX{} content, but
+ it may also contain \cmd{TABrule}s and/or \cmd{TABcline}s as discussed
+ in section~\ref{s:hr}.
+The macro\margcmd{ensureTABstackMath}\vspace{-8pt}
\begin{verbnobox}[\footnotesize\vbdelim]
\ensureTABstackMath{<commands involving TABstacks>}
\end{verbnobox}
+\vspace{-8pt}
will force any \tst{} stacks within its argument to be
processed in math mode, even
if the prevailing mode is otherwise \vb|\TABstackText|.
The package also provides a set of declarations that can be used to define the
- manner in which subsequent TABstacks will be processed:
+ manner in which subsequent TABstacks will be processed:\vspace{-8pt}
\begin{verbnobox}[\footnotesize\vbdelim]
\fixTABwidth{T <or> F}
\TABstackMath
@@ -216,15 +318,17 @@ The package also provides a set of declarations that can be used to define the
\TABstackMathstyle{<directive>}
\TABstackTextstyle{<directive>}
\clearTABstyle
-\setstackEOL{<end-of-line character>} !
+\setstackEOL{<end-of-line character>} !1
\setstackTAB{<tabbing character>}
\TABunaryLeft (\TABbinaryRight)
\TABunaryRight (\TABbinaryLeft)
\TABbinary
+\relaxTABsyntax !2
\end{verbnobox}
The following macros can be used for parsing tabbed data outside of a
TABstack and also provide various stack metrics for the most recently
parsed \tst{} data.
+\vspace{-6pt}
\begin{verbnobox}[\footnotesize\vbdelim]
\readTABstack{<tabbed EOL-separated string>}
\TABcellRaw[<row>,<column>]
@@ -237,6 +341,7 @@ The following macros can be used for parsing tabbed data outside of a
\TABht{<row>}
\TABdp{<row>}
\end{verbnobox}
+\vspace{-12pt}
\subsection{Command Examples}
@@ -249,10 +354,12 @@ Here, the optional argument \vb|[l]| defines the alignment of \textit{all} the
columns as ``left.'' The default alignment is \vb|[c]|.
\vb|\TABstackTextstyle{\scshape}|\\
-\vb|\tabbedShortunderstack[l]{This& Is &The\\Time & Of&Man's\\ Great&Dis&content}|
+\vb|\tabbedShortunderstack[l]{This& Is &The\\Time & Of&Man's\\ |\\
+\vb| Great&Dis&content}|
{\small\TABstackTextstyle{\scshape}%
- \tabbedShortunderstack[l]{This& Is &The\\Time & Of&Man's\\ Great&Dis&content}}
+ \tabbedShortunderstack[l]{This& Is &The\\Time & Of&Man's\\
+ Great&Dis&content}}
Note that spaces around the arguments are absorbed and discarded. Furthermore, the
text style has been set to \vb|\scshape|.
@@ -310,26 +417,25 @@ This is for stacking two items with \texttt{rlrl...} alignment pattern.
\subsection*{Tabular Stack}
-This is for stacking two items with specifiable alignment pattern.
+This is for stacking items with specifiable alignment pattern.
+
+\vb|\TABbinary\TABstackMath\setstackgap{S}{0pt}\fboxrule=1pt\relax|\\
+\vb|\tabularShortstack{lcr}{1 + 2(4-3) &=& 6 - 6/2\\|\\
+\vb| \TABcline{1-3}\kern6em & \triangle & \kern6em}|
-\vb|\TABbinary\TABstackMath\setstacktabulargap{1ex}%|\\
-\vb| \tabularstackanchor[-1pt]{rcl}%|\\
-\vb| {\rule{7ex}{1pt}&\belowbaseline[0pt]{$\triangle$}%|\\
-\vb| &\rule{7ex}{1pt}}{1 + 3(4-3) &=& 7 - 6/2}|\vspace{1ex}
-{\small\TABbinary\TABstackMath\setstacktabulargap{1ex}
-\tabularstackanchor[-1pt]{rcl}{\rule{7ex}{1pt}&\belowbaseline[0pt]{%
-$\triangle$}&\rule{7ex}{1pt}}{1 + 2(4-3) &=& 6 - 6/2}}
+{\small\TABbinary\TABstackMath\setstackgap{S}{0pt}\fboxrule=1pt\relax
+\tabularShortstack{lcr}{1 + 2(4-3) &=& 6 - 6/2\\
+ \TABcline{1-3}\kern6em & \triangle & \kern6em}}
Note the use of \vb|\TABbinary|, which applies a group to the beginning and
end of each cell, in the event a binary treatment of leading/trailing
operators is desired.
So, in this case, a cell containing \vb|=| will be set as \vb|{}={}|.
In the absence of that declaration, the cell containing
-the equal sign would have to have been explicitly defined as \vb|{}=|
- in order to override the \vb|\unaryLeft| default setting of the package,
- which only places a group at the end of each cell.
-Note also the use of a negative stacking gap, which is a perfectly
+the equal sign would have to have been explicitly defined as \vb|={}|
+ (in accordance with the \vb|\TABunaryLeft| default setting of the package).
+Negative vertical stacking gap, while not used here, is a perfectly
acceptable syntax and can be used to achieve overlap, if desired.
\subsection*{Fixed Tab Width (equal width columns, based on largest)}
@@ -356,22 +462,32 @@ By default, for the parsing of columns within a given row, this package employs
This value can be changed via \vb|\setstackTAB{|<tabbing character>\vb|}|,%
\margcmd{setstackTAB}
where the argument is the newly desired tabbing token.
-It can be any of various tokens, including a space token, if one wishes to
+It can be any of various tokens\footnote{%
+Since \tst{} uses the \loi{} package for parsing rows and columns,
+ see the \loi{} package documentation for limitations on the tokens that
+ can be used as a valid parsing separator.}
+, including a space token, if one wishes to
parse a space-separated list of columns.
\end{sloppypar}
-\subsection*{TABstacks Inside the \texttt{tabular} Environment}
+\subsection*{TABstacks Inside the \texttt{tabular} or \texttt{align}
+ Environments}
When invoking a TABstack inside another tabbed environment, such as
- \vb|tabular|, \vb|align|, or other similar environments, one must group
- the TABstacks in their own braces \vb|{}|:
+ \vb|tabular|, \vb|align|, or other similar environments, one
+ \textbf{no longer}\footnote{%
+ As of version 2.10, the problem of properly scoping TABstack argument
+ was resolved with the use of ``brace hacks'' described on p.\,385 of the
+ \TeX book, and suggested to the author by Prof. Enrico Gregorio.
+}
+ needs to group the TABstacks in their own braces \vb|{}|:
\begin{verbnobox}[\footnotesize\vbdelim]
\ensureTABstackMath{%
\begin{tabular}{c|c}
Left Eqn. & Right Eqn.\\
\hline
-{\tabularCenterstack{lr}{a_1 & 12\\c & 1234}} & \
-{\tabularCenterstack{rl}{a_1 & 12\\c & 1234}}\\
+\tabularCenterstack{lr}{a_1 & 12\\c & 1234} & \
+\tabularCenterstack{rl}{a_1 & 12\\c & 1234}\\
\hline
\end{tabular}
}
@@ -381,8 +497,8 @@ Left Eqn. & Right Eqn.\\
\begin{tabular}{c|c}
Left Eqn. & Right Eqn.\\
\hline
-{\tabularCenterstack{lr}{a_1 & 12\\c & 1234}} &
-{\tabularCenterstack{rl}{a_1 & 12\\c & 1234}}\\
+\tabularCenterstack{lr}{a_1 & 12\\c & 1234} &
+\tabularCenterstack{rl}{a_1 & 12\\c & 1234}\\
\hline
\end{tabular}
}
@@ -540,7 +656,7 @@ Since the \vb|\readTABstack| macro, itself, neither knows nor determines the
Therefore, if \vb|\TABcellBox| is called following an independent
invocation of \vb|\readTABstack|, center alignment
of the cell content will be provided, by default, which can be overridden
- with the optional argment to \vb|\TABcellBox|.
+ with the optional argument to \vb|\TABcellBox|.
Note that the height/depth of the \vb|\TABcellBox| reflects the height and
depth of the row content of the TABstack.
@@ -624,15 +740,13 @@ However, in that case, \vb|\TABcells{2}| would still, in fact, yield
\section{Absent Features/Tricky Syntax}
-\textbf{1. Nothing Equivalent to} \vb|\hline| or \vb`|`
+\textbf{1. Nothing Equivalent to} \vb`|`
This is not a bug, but rather a notation of a missing feature. Currently
-there is nothing equivalent to \vb|\hline| available for use in
-\tst{} arguments.
-Furthermore, vertical lines may \textbf{not} be added to a tabular stack
+vertical lines may \textbf{not} be added to a tabular stack
with the use of \vb`|` elements in the column specifier.
-\textbf{2. Empty Items Are Not Ignored (by Default)}
+\textbf{2. Trailing Row Separator/Empty Items Are Not Ignored (by Default)}
The \loi{} package used to parse TABstack input, does not, by default,
ignore empty items.
@@ -641,12 +755,12 @@ Take, for example, the well formed TABstack invocation,
\vb|\tabularLongstack{rc}{11&12\\21&22\\31&32}|.
-Adding a trailing \vb|\\| to the input, as in:
+Adding a trailing \vb|\\| row separator to the input, as in:
\vb|\tabularLongstack{rc}{11&12\\21&22\\31&32\\}|,
however, breaks the parsing because 2 columns of data are expected
- following the final \vb|\\| (even though such syntax is accepted
+ following the final \vb|\\| (even though such syntax is benign
in, for example, the \texttt{tabular} environment).
This syntax can be immediately made acceptable by
invoking the \loi{} declaration \cmd{ignoreemptyitems}, in which case
@@ -663,11 +777,22 @@ To make this latter case work, when empty items are ignored, an
\vb|\tabularLongstack{rc}{11&12\\21&{}\\31&32\\}|.
-These problems can be wholly avoided if care is used in the
- construction of TABstack input.
+As of V2.1, the case of the trailing row separator can also be addressed
+ in a 2nd way, if the \texttt{TABcline} package option has been
+ declared.
+In that case, the switch \cmd{relaxTABsyntax} will automatically
+ add the necessary column separators to \tst{} macro input, in
+ order to avoid compilation error for the case of a trailing row
+ separator.
+See section~\ref{s:rtx} for more details.
+
+These problems arising from syntax can be wholly avoided,
+ without the need to resort to
+ \cmd{ignoreemptyitems} or \cmd{relaxTABsyntax}, if care is used in the
+ construction of the TABstack input.
\endvbdelim
-\section*{Acknowledgements}
+\section*{Acknowledgments}
I would like to thank Christian Tellechea for his development of the
\loi{} package (which was directly inspired by my deficient
@@ -681,6 +806,9 @@ helping me to understand some of the details of the \textsf{etoolbox} package:
\vb|http://tex.stackexchange.com/questions/140372/|\\
\vb|loop-multi-contingency-using-etoolbox|
+Professor Enrico Gregorio is a constant source of knowledge and assistance
+ for which I am very grateful.
+
\section{Code Listing}
\verbfilenobox[\footnotesize]{tabstackengine.sty}
diff --git a/Master/texmf-dist/tex/latex/tabstackengine/tabstackengine.sty b/Master/texmf-dist/tex/latex/tabstackengine/tabstackengine.sty
index 977bc1bca08..f559b7ab87b 100644
--- a/Master/texmf-dist/tex/latex/tabstackengine/tabstackengine.sty
+++ b/Master/texmf-dist/tex/latex/tabstackengine/tabstackengine.sty
@@ -1,4 +1,4 @@
-\def\tabstackengineversionnumber{V2.01}
+\def\tabstackengineversionnumber{V2.10}
%
% THIS MATERIAL IS SUBJECT TO THE LaTeX Project Public License
%
@@ -34,8 +34,11 @@
% -\TABcell and \TABcellBox modified to remember recent use of
% \ensureTABstackMath, which otherwise changes temporarily the
% prevailing mode and style of the TABstack.
+% V2.10 -Introduces \TABrule and [optionally] \TABcline{}
+% -Allows tabbed nesting within other tabbed environments (achieved via
+% replacing select \bgroup and \egroup with \ifnum brace hacks (TeXbook p.385)
\ProvidesPackage{tabstackengine}
-[2016/11/30 (\tabstackengineversionnumber) tabbed stacking]
+[2018/03/05 (\tabstackengineversionnumber) tabbed stacking]
\RequirePackage{stackengine}[2016-10-04]
\RequirePackage{listofitems}[2016/11/18]
\RequirePackage{etoolbox}
@@ -48,6 +51,8 @@
\newtoks\TABcoltoks
\newtoks\LstrutTABtoks
\newtoks\RstrutTABtoks
+\newtoks\TAB@toks
+\newlength\TABruleshift
\def\getTABcelltoks[#1,#2]{%
\TABcelltoks=\expandafter\expandafter\expandafter{\TABcellRaw[#1,#2]}}
@@ -68,7 +73,7 @@
\newcommand\setstackTAB[1]{\ifstrempty{#1}{\def\TAB@char{ }}{\def\TAB@char{#1}}}
-\newcommand\readTABstack[1]{%
+\newcommand\readTABstack@ORIG[1]{%
\expandafter\expandafter\expandafter\setsepchar\expandafter\expandafter%
\expandafter{\expandafter\SEP@char\expandafter/\TAB@char}%
\greadlist*\TABcellRaw{#1}%
@@ -106,7 +111,9 @@
\newcommand\TABstrut[1]{\ifnum#1<1\relax{}\else%
\protect\rule[-\TABdp{#1}]{0pt}{\dimexpr\TABdp{#1}+\TABht{#1}\relax}\fi}
-\newcommand\TABcell[2]{\stack@delim\recent@TAB@delim{\TABcellRaw[#1,#2]}\stack@delim}
+\newcommand\TABcell[2]{%
+ \setTABrulecolumn{#2}% THIS LINE ADDED TO SET COLUMN FOR POSSIBLE \TABrule
+ \stack@delim\recent@TAB@delim{\TABcellRaw[#1,#2]}\stack@delim}
\newcommand\TABcellBox[3][\relax]{\ifx\relax#1\relax%
\TABcellBox@aux{\csuse{col#3TAB@stackalignment}}{#2}{#3}\else
@@ -202,7 +209,8 @@
\newcommand\vertMatrixstack[2][\stackalignment]{%
\ensureTABstackMath{\left|\@TAB@stack{#1}{#2}{D}{\Vectorstack}\right|}}
-\newcommand\@TAB@stack[4]{\bgroup%
+\newcommand\@TAB@stack[4]{{\ifnum`}=\z@\fi%
+ \set@TABrule@gap{#3}%
\readTABstack{#2}%
\edef\stackalignment{#1}%
\setcounter{TABcolindex@}{0}%
@@ -227,7 +235,7 @@
\expandafter#4\expandafter{\the\TABcoltoks}}}%
{\expandafter#4\expandafter{\the\TABcoltoks}}%
}%
-\egroup}
+\ifnum`{=\z@\fi}}
\newcommand\tabbedstackon[3][\stackgap]{%
\@TABstackonunder{#1}{#2}{#3}{D}{\stackon}}
@@ -256,10 +264,14 @@
\newcommand\tabularstackanchor[4][\stackgap]{%
\@TABstackonunder{#1}{#3}{#4}{#2}{\stackanchor}}
-\newcommand\@TABstackonunder[5]{\bgroup%
+\newcommand\@TABstackonunder[5]{{\ifnum`}=\z@\fi%
+ \set@TABrule@gap{#4}%
\def\TAB@tmp{#2}%
- \expandafter\g@addto@macro\expandafter\TAB@tmp\expandafter{\SEP@char#3}%
- \readTABstack{\TAB@tmp}%
+ \ifnum\TAB@testcline#2\relax=0\relax
+ \expandafter\g@addto@macro\expandafter\TAB@tmp\expandafter{\SEP@char}%
+ \fi%
+ \g@addto@macro\TAB@tmp{#3}%
+ \expandafter\readTABstack\expandafter{\TAB@tmp}%
\setcounter{TABcolindex@}{0}%
\whileboolexpr{test {\ifnumless{\theTABcolindex@}{\TABstack@cols}}}{% COL LOOP
\stepcounter{TABcolindex@}%
@@ -275,7 +287,9 @@
{\TAB@delim{\TAB@strutL{1}\TABcellRaw[1,\theTABcolindex@]\TAB@strutR{1}}}%
{\TAB@delim{\TAB@strutL{1}\TABcellRaw[2,\theTABcolindex@]\TAB@strutR{2}}}}%
}%
-\egroup}
+\ifnum`{=\z@\fi}}
+
+\def\TAB@testcline#1#2\relax{\ifx\TABcline#1 1\else0\fi}
\newcommand\@getTABalignment[2]{%
\ifstrequal{#1}{D}{}{% T, DO NOTHING (USE \stackalignment)
@@ -325,6 +339,160 @@
\newcommand\ensureTABstackMath[1]{%
\let\sv@TABmode\TAB@delim\TABstackMath#1\let\TAB@delim\sv@TABmode}
+%%% \TABrule
+
+\newcommand\TABrule[1][\TABruleshift]{%
+ \ifnum1=\value{TABcolindex@}\relax%
+ \makebox[\TABwd{\theTABcolindex@}][l]{%
+ \rule[\TABruleshift]{%
+ \dimexpr\TABwd{\theTABcolindex@}+.5\dimexpr\TAB@gap\relax}{\fboxrule}}%
+ \else%
+ \ifnum\TABcells{1}=\value{TABcolindex@}\relax%
+ \makebox[\TABwd{\theTABcolindex@}][r]{%
+ \rule[\TABruleshift]{%
+ \dimexpr\TABwd{\theTABcolindex@}+.5\dimexpr\TAB@gap\relax}{\fboxrule}}%
+ \else%
+ \makebox[\TABwd{\theTABcolindex@}][c]{%
+ \rule[\TABruleshift]{%
+ \dimexpr\TABwd{\theTABcolindex@}+1.\dimexpr\TAB@gap\relax}{\fboxrule}}%
+ \fi%
+ \fi%
+}
+
+\newcommand\set@TABrule@gap[1]{%
+ \ifstrequal{#1}{D}{\gdef\TAB@gap{\tabbed@gap}}{%
+ \ifstrequal{#1}{A}{\gdef\TAB@gap{0pt}}{\gdef\TAB@gap{\tabular@gap}}%
+ }%
+}
+
+\newcommand\setTABrulecolumn[1]{\setcounter{TABcolindex@}{#1}}
+
+%% \TABcline
+
+\newcommand\readTABstack@cline[1]{%
+ \expandafter\expandafter\expandafter\setsepchar\expandafter\expandafter%
+ \expandafter{\expandafter\SEP@char\expandafter/\TAB@char}%
+% REMEMBER # COLUMNS IN ADVANCE
+ \greadlist*\TABcellRaw{#1}%
+ \edef\TABstack@cols{\listlen\TABcellRaw[1]}%[\TABstack@cols]%
+ \TAB@toks={}%
+ \setcounter{TABrowindex@}{0}%
+ \TAB@preread#1\relax\TABcline\relax\TAB@end%
+ \expandafter\expandafter\expandafter\setsepchar\expandafter\expandafter%
+ \expandafter{\expandafter\SEP@char\expandafter/\TAB@char}%
+% THE FOLLOWING WILL FIX LINES ENDING IN EOL SEPARATOR (SHOULDN'T DO THAT!)
+ \pad@cols%
+%%
+ \expandafter\greadlist\expandafter*\expandafter\TABcellRaw\expandafter{\the\TAB@toks}%
+ \edef\TABstack@rows{\TABcellRawlen}%
+ \def\maxTABwd{0pt}%
+ \setcounter{TABrowindex@}{0}%
+ \whileboolexpr{test {\ifnumless{\theTABrowindex@}{\TABstack@rows}}}{% ROW LOOP
+ \def\@accumulatedTAB{}%
+ \stepcounter{TABrowindex@}%
+ \setcounter{TABcolindex@}{0}%
+ \whileboolexpr{test {\ifnumless{\theTABcolindex@}{\TABstack@cols}}}{% COL LOOP
+ \stepcounter{TABcolindex@}%
+ \ifnum\value{TABrowindex@}=1\relax\csxdef{col\theTABcolindex@ TAB@wd}{0pt}\fi%
+ \getTABcelltoks[\theTABrowindex@,\theTABcolindex@]%
+ \expandafter\g@addto@macro\expandafter\@accumulatedTAB\expandafter{%
+ \the\TABcelltoks{}}%
+ \setbox0=\hbox{\stack@delim\TAB@delim{%
+ \TAB@strutL{0}\the\TABcelltoks\TAB@strutR{0}}\stack@delim}%
+ \ifdim\wd0>\csuse{col\theTABcolindex@ TAB@wd}\relax%
+ \csxdef{col\theTABcolindex@ TAB@wd}{\the\wd0}%
+ \ifdim\wd0>\maxTABwd\relax\xdef\maxTABwd{\the\wd0}\fi\fi%
+ \csxdef{col\theTABcolindex@ TAB@stackalignment}{c}% DEFAULT, LATER CHANGED
+ }%
+ \setbox0=\hbox{\stack@delim\TAB@delim{\@accumulatedTAB}\stack@delim}%
+ \csxdef{row\theTABrowindex@ TAB@ht}{\the\ht0}%
+ \csxdef{row\theTABrowindex@ TAB@dp}{\the\dp0}%
+ \global\let\recent@TAB@delim\TAB@delim%
+ }%
+}
+
+\def\TAB@preread#1\TABcline#2#3\TAB@end{\TAB@toks=\expandafter{\the\TAB@toks#1}%
+ \stepcounter{TABrowindex@}%
+ \ifx\relax#2\relax%
+ \TAB@toks=\expandafter{\the\TAB@toks\unskip}%
+ \let\next\relax%
+ \else%
+ \discern@TABlines{#2}%
+ \setcounter{TABcolindex@}{0}%
+ \whileboolexpr{test {\ifnumless{\theTABcolindex@}{\TABline@colcount}}}{% COLUMN LOOP
+ \stepcounter{TABcolindex@}%
+ \ifnum\theTABcolindex@=1\relax\else%
+ \TAB@toks=\expandafter\expandafter\expandafter{%
+ \expandafter\the\expandafter\TAB@toks\TAB@char}%
+ \fi
+ \TAB@toks=\expandafter\expandafter\expandafter\expandafter\expandafter%
+ \expandafter\expandafter{\expandafter\expandafter\expandafter%
+ \the\expandafter\expandafter\expandafter\TAB@toks%
+ \csname TABline@[\theTABcolindex@]\endcsname}%
+ }%
+ \ifnum0=\TAB@testend#3\relax\relax%
+ \TAB@toks=\expandafter\expandafter\expandafter{%
+ \expandafter\the\expandafter\TAB@toks\SEP@char}%
+ \fi%
+ \def\next{\TAB@preread#3\TAB@end}%
+ \fi%
+ \next%
+}
+
+\newcommand\discern@TABlines[1]{%
+ \setcounter{TABcolindex@}{0}%
+ \whileboolexpr{test {\ifnumless{\theTABcolindex@}{\TABstack@cols}}}{% COLUMN LOOP
+ \stepcounter{TABcolindex@}%
+ \expandafter\def\csname TABline@[\theTABcolindex@]\endcsname{\relax}%
+ }%
+ \setsepchar{,/-}%
+ \readlist\TABline@cols{#1}%
+ \def\TAB@endindex{0}%
+ \foreachitem\@TABindex\in\TABline@cols{%
+ \edef\TAB@startindex{\TABline@cols[\@TABindexcnt,1]}%
+ \ifnum\listlen\TABline@cols[\@TABindexcnt]=2\relax%
+ \edef\TAB@endindex{\TABline@cols[\@TABindexcnt,2]}%
+ \else
+ \edef\TAB@endindex{\TABline@cols[\@TABindexcnt,1]}%
+ \fi
+ \setcounter{TABcolindex@}{\numexpr\TAB@startindex-1\relax}%
+ \whileboolexpr{test {\ifnumless{\theTABcolindex@}{\TAB@endindex}}}{% COLUMN LOOP
+ \stepcounter{TABcolindex@}%
+ \expandafter\def\csname TABline@[\theTABcolindex@]\endcsname{%
+ \TABrule}%
+ }%
+ }%
+ \edef\TABline@colcount{\TABstack@cols}%
+}
+
+
+\def\TAB@testend#1#2\relax{\ifx\relax#1 1\else0\fi}
+
+\newcommand\relaxTABsyntax{%
+ \def\pad@cols{%
+ \setcounter{TABcolindex@}{1}%
+ \whileboolexpr{test {\ifnumless{\theTABcolindex@}{\TABstack@cols}}}{% COLUMN LOOP
+ \stepcounter{TABcolindex@}%
+ \TAB@toks=\expandafter\expandafter\expandafter{%
+ \expandafter\the\expandafter\TAB@toks\TAB@char}%
+ }%
+ }%
+}
+
+\newcommand\@strictTABsyntax{\let\pad@cols\relax}
+
+\newcommand\TABcline@off{%
+ \def\TABcline##1{\ignorespaces}%
+ \let\readTABstack\readTABstack@ORIG%
+}
+
+\newcommand\TABcline@on{%
+ \def\TABcline{}%
+ \let\readTABstack\readTABstack@cline%
+}
+
+%% INITIALIZATIONS
+
\setstackEOL{\\}% DEFAULT ROW SEP
\setstackTAB{&}% DEFAULT COL SEP
\def\TAB@mathstyle{}% NOTHING ADDED TO DEFAULT TAB MATH STYLE
@@ -335,5 +503,19 @@
\def\align@gap{1em}% DEFAULT ALIGN COL GAP
\def\tabular@gap{\tabcolsep}% DEFAULT TABULAR COL GAP
\fixTABwidth{F}% DEFAULT NON-FIXED WIDTH COLUMNS
-
+\setlength\TABruleshift{-0pt}% RELATIVE VERTICAL SHIFT OF \TABrule
+\@strictTABsyntax% WITH \relaxTABsyntax, ADDS NCOL-1 COLUMN SEPARATORS TO END
+% OF INPUT TOKEN LIST, TO AVOID ERROR ENDING INPUT WITH EOL.
+% BASICALLY, ALLOWS BAD CODING STYLE WITH NEW \readTABstack
+
+% PROCESS PACKAGE OPTIONS
+\newif\iftabstackengine@TABcline
+\DeclareOption{TABcline}{\tabstackengine@TABclinetrue}
+\ProcessOptions\relax
+\iftabstackengine@TABcline%
+ \TABcline@on% ALLOW USE OF \TABcline
+\else
+ \TABcline@off% DISALLOW USE OF \TABcline
+\fi
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput