% tabto.sty % % version 1.4 (Dec 2018) % % Tabbing to fixed positions in a paragraph. % % Copyright 2006,2009,2012,2013,2018 by % Donald Arseneau, Vancouver, Canada (asnd@triumf.ca) % Permission to use, distribute and modify this software is granted % under the conditions of the LaTeX Project Public License, either % version 1.3 or (at your option) any later version. The license is % found at http://www.latex-project.org/lppl.txt, and is part of all % recent distributions of LaTeX. % % This work has the LPPL maintenance status `maintained' (by author). % % Two new text positioning commands are defined: \tabto and \tab. % % \tabto{} % Tab to a position relative to the left margin in a paragraph (any % indentation due to a list or \leftskip is part of the `margin' in % this context). If the text on the line already goes past the desired % position, the tab starts a new line and moves to the requested % horizontal position. % % \tabto*{} % Similar to \tabto, except it will perform backspacing, and over- % print previous text on the line whenever that text is already % longer than the specified length (i.e., no linebreak is produced). % Line-breaks are suppressed immediately after \tabto or \tabto*. % % The length register "\CurrentLineWidth" will report the width % of the existing text on the line, and it may be used in the % argument (using calc.sty, for example). Also, there % is "\TabPrevPos" which gives the "\CurrentLineWidth" from the % previous tab command (the position where the tab command occurred, % not where it went to), and can be used to return to that position % if no line breaks have occurred in between, or directly below it, % if there were line breaks. % % \tab % Tab to the next tab-stop chosen from a list of tab positions, in % the traditional style of typewriters. A \tab will always move % to the next tab stop (or the next line), even if it is already % exactly at a tab stop. Thus, "\tab" at the beginning of a line, % or "\tab\tab" elsewhere skips a position. A linebreak is permitted % immediately following a \tab, in case the ensuing text does not % fit well in the remaining space. % % If you do not want to skip positions, use "\tabto{\NextTabStop}" % instead of "\tab". This is particularly useful when you want to % use \tab in some other command, but do not want to skip a column % for the first item. % % The tab-stop positions are declared using either \TabPositions % or \NumTabs: % % \TabPositions{, ,...} % Declares the tab stops as a comma-separated list of positions % relative to the left margin. A tab-stop at 0pt is implicit, and % need not be listed. % % \NumTabs{} % Declares a list of equally-spaced tabs, starting at the % left margin and spanning \linewidth. For example \NumTabs{2} % declares tab-stops at 0pt and 0.5\linewidth, the same as % \TabPositions{0pt, 0.5\linewidth} or \TabPositions{0.5\linewidth} % % After these declarations, the list of tab positions is saved in % \TabStopList, and the next tab position, relative to the current % position, is given by \NextTabStop. You do not normally need % to access them, but they are available. % % Problems: % % Tall objects after a tab stop may overlap the line above, rather % than forcing a greater separation between lines. \ProvidesPackage{tabto}[2018/12/28 \space v 1.4 \space Another tabbing mechanism]\relax \newdimen\CurrentLineWidth \newdimen\TabPrevPos \newcommand\tabto[1]{% \leavevmode \begingroup \def\@tempa{*}\def\@tempb{#1}% \ifx\@tempa\@tempb % \tab* \endgroup \TTo@overlaptrue % ... set a flag and re-issue \tabto to get argument \expandafter\tabto \else \ifinner % in a \hbox, so ignore \else % unrestricted horizontal mode \null% \predisplaysize will tell the position of this box (must be box) \parfillskip\fill \everydisplay{}\everymath{}% \predisplaypenalty\@M \postdisplaypenalty\@M $$% math display so we can test \predisplaysize \lineskiplimit=-999pt % so we get pure \baselineskip \abovedisplayskip=-\baselineskip \abovedisplayshortskip=-\baselineskip \belowdisplayskip\z@skip \belowdisplayshortskip\z@skip \halign{##\cr\noalign{% % get the width of the line above \ifdim\predisplaysize=\maxdimen %\message{Mixed R and L, so say the line is full. }% \CurrentLineWidth\linewidth \else \ifdim\predisplaysize=-\maxdimen % \message{Not in a paragraph, so call the line empty. }% \CurrentLineWidth\z@ \else \ifnum\TTo@Direction<\z@ \CurrentLineWidth\linewidth \advance\CurrentLineWidth\predisplaysize \else \CurrentLineWidth\predisplaysize \fi % Correct the 2em offset \advance\CurrentLineWidth -2em \advance\CurrentLineWidth -\displayindent \advance\CurrentLineWidth -\leftskip \fi\fi \ifdim\CurrentLineWidth<\z@ \CurrentLineWidth\z@\fi % Enshrine the tab-to position; #1 might reference \CurrentLineWidth \setlength\@tempdimb{#1}% allow calc.sty %\message{*** Tab to \the\@tempdimb, previous width is \the\CurrentLineWidth. ***}% % Save width for possible return use \global\TabPrevPos\CurrentLineWidth % Build the action to perform \protected@xdef\TTo@action{% \vrule\@width\z@\@depth\the\prevdepth \ifdim\CurrentLineWidth>\@tempdimb \ifTTo@overlap\else \protect\newline \protect\null \fi\fi \protect\nobreak \protect\hskip\the\@tempdimb\relax }% %\message{\string\TTo@action: \meaning \TTo@action. }% % get back to the baseline, regardless of its depth. \vskip-\prevdepth \prevdepth-99\p@ \vskip\prevdepth }}% $$ % Don't count the display as lines in the paragraph \count@\prevgraf \advance\count@-4 \prevgraf\count@ \TTo@action %% \penalty\@m % to allow a penalized line break \fi \endgroup \TTo@overlapfalse \ignorespaces \fi } % \tab -- to the next position % \hskip so \tab\tab moves two positions % Allow a (penalized but flexible) line-break right after the tab. % \newcommand\tab{\leavevmode\hskip2sp\tabto{\NextTabStop}% \nobreak\hskip\z@\@plus 30\p@\penalty4000\hskip\z@\@plus-30\p@\relax} % Expandable macro to select the next tab position from the list \newcommand\NextTabStop{% \expandafter \TTo@nexttabstop \TabStopList,\maxdimen,>% } \def\TTo@nexttabstop #1,{% \ifdim#1<\CurrentLineWidth \expandafter\TTo@nexttabstop \else \ifdim#1<0.9999\linewidth#1\else\z@\fi \expandafter\strip@prefix \fi } \def\TTo@foundtabstop#1>{} \newcommand\TabPositions[1]{\def\TabStopList{\z@,#1}} \newcommand\NumTabs[1]{% \def\TabStopList{}% \@tempdimb\linewidth \divide\@tempdimb by#1\relax \advance\@tempdimb 1sp % counteract rounding-down by \divide \CurrentLineWidth\z@ \@whiledim\CurrentLineWidth<\linewidth\do {% \edef\TabStopList{\TabStopList\the\CurrentLineWidth,}% \advance\CurrentLineWidth\@tempdimb }% \edef\TabStopList{\TabStopList\linewidth}% } % default setting of tab positions: \TabPositions{\parindent,.5\linewidth} \newif\ifTTo@overlap \TTo@overlapfalse \@ifundefined{predisplaydirection}{ \let\TTo@Direction\predisplaysize \let\predisplaydirection\@undefined }{ \let\TTo@Direction\predisplaydirection }