Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I like to create a macro which processes a following brace group as "argument" using \halign. After it has been processed a token (a macro) should be executed. With an \hbox I can use \aftergroup\mytoken direct after the opening brace to execute something after the closing brace. However, this doesn't work with \halign because every cell it is own group and \aftergroup would place something in the next cell. I also had the idea to have some recursive \aftergroup macro which places itself always in the next cell until the last cell is reached. But this would break any \noalign code added after a \cr (or \\ in LaTeX), beside being tricky in the first place.

Is there any way to use \afterassignment, \aftergroup or any other way to execute a macro after the } of \halign? Alternatively placing a \egroup before it and use the } as end of an outer group would also be fine.

\documentclass{article}

\def\mytab{%
    \afterassignment\dotab
    \let\dummy=%
}
\def\dotab{%
    \AFTERHALIGN\dosomethingafterwards
    \halign\bgroup
        \hfil\ignorespaces##\unskip\cr
}
\def\dosomethingafterwards{...}

\begin{document}

\mytab{%
    A \cr
    B \cr
    C \cr
}

\end{document}
share|improve this question

1 Answer 1

up vote 5 down vote accepted

Short answer: it's tough, and perhaps impossible to provide a fully robust solution since finding out whether a given cr is the last one is very difficult: after a \cr, TeX scans ahead, ignoring spaces (at least plain (32,10) ones) and \crcr, and expanding everything else, except eTeX's protected control sequences, until finding a non-expandable token. TeX then inserts the template, except in the following cases:

  • \noalign starts a new group inserted between lines of the tabular
  • \omit starts the cell normally, but without inserting the template
  • a catcode 2 token (closing brace or \egroup) ends the \halign.

Two more things I can think of which interact with what TeX is doing there are \aftergroup and \everycr. After a \cr (or a non-redundant \crcr, i.e., one that is not ignored by TeX scanning ahead after a \cr), the content of \everycr are inserted, immediately followed by \aftergroup-ed tokens, and then the following characters in the file. The resulting token list is read by TeX as I explained, expanding as it goes, ignoring spaces and \crcr.

We thus need to detect closing braces after any \cr. This requires a non-expandable \futurelet, which as you say breaks the \noalign mechanism. The solution is along the lines of \everycr{\noalign\bgroup\test}, where \test checks what the next token is, then closes the \noalign group (it will insert a height-zero vertical box in the page, but I think that that changes nothing to the output.

Code. The easiest way I can think of is to use the \everycr token parameter. I'm using eTeX's \currentgrouplevel to only insert the special bit of \noalign for \cr which appear in the outer table, not nested tables. The external group is not really needed either (just to keep changes to \everycr local). The main idea is that after each \cr, a \noalign\bgroup\futurelet... is inserted to check if that was the last cr (it was if we find a closing brace). This probably has bad interactions with redundant/non-redundant \crcr, and also has other drawbacks, I would guess. I commented out the \romannumeral-\`0: it is useful if you fear that the last \cr won't be immediately followed by the closing brace.

\def\mytab{%
    \begingroup
    \everycr\expandafter{%
        \expandafter\mytabcr
        \the\expandafter\currentgrouplevel\expandafter;%
        \the\everycr}%
    \afterassignment\dotab
    \let\dummy=%
}
\def\dotab{%
    \halign\bgroup
        \hfil\ignorespaces##\unskip\cr
}
\def\mytabcr#1;{%
    \ifnum\numexpr#1-2=\currentgrouplevel %not sure about that 2
        \noalign\bgroup
            \expandafter\mytabcrX %\romannumeral-`0%
    \fi}
\def\mytabcrX{\futurelet\mytabcrtoken\mytabcrtest}
\def\mytabcrtest{%
    \ifcat\noexpand\mytabcrtoken\egroup
        \aftergroup\mytabcrend
    \else
        \egroup
    \fi}
\def\mytabcrend{\egroup\dosomethingafter\endgroup}
share|improve this answer
    
Thanks Bruno, the idea to detect the } after the line break seems to be the way to go. I now implemented something like this for my collectbox package. I decided to go with LaTeX tabular style instead and redefined \\ accordantly. To avoid issues with inner tabulars I redefine \ialign to reset \\. See the code for details if you are interested. Now, adjustbox has a tabular, tabular* and array keys for both environment and macro-mode. –  Martin Scharrer Aug 23 '11 at 20:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.