3

Help me please redefine & command inside a table. When I try to do it, I get an error:

! Misplaced alignment tab character &.

Probably problem with catcodes, but I dont know how to solve it.

\documentclass{article}
\usepackage{expl3,etoolbox}
\ExplSyntaxOn
\makeatletter
\cs_set_eq:NN \orig@& &
\AtBeginEnvironment{table}{
\cs_new_protected:npn{&}{\orig@&\message{amp command}}
}
%return original &
\AtEndEnvironment{table}{\cs_gset_protected:npn{&}{\orig@&}
\ExplSyntaxOff
\begin{document}
\begin{table}
test&new test\\
\end{table}
\end{document}
  • What are you trying to do in your table? I can't tell if it's so far beyond me that I don't understand, or if you're just getting started in TeX and want to end up with \begin{table}\begin{tabular}{cc}test&new test\end{tabular}\end{table} with no crazy hijinks. – Teepeemm Apr 7 at 0:25
5

There are a couple of problems with your code:

  • \cs_set_eq:NN \orig@& & doesn't work because & isn't a letter (catcode 11) token, but an alignment tab (catcode 4) token, so that line makes \orig@ equal to (the first) &, and the second & is seen by TeX out of an alignment (tabular) context, thus the ! Misplaced alignment tab character & error, which is the same as if you just use & out of a table.
    To make this line work, you'd need something like \cs_set_eq:cN { orig@& } &. But it would be also hard to use \orig@& later.

  • The environment you want is tabular, not table. table is the floating environment, and tabular is the one for alignments.

  • You better not put \message (or \iow_term:n or anything non-expandable) after the alignment tab, or \multicolumn won't work in your table. The tokens at the beginning of a table cell must be expandable so that TeX can find a possible \omit or \span (see Donald's comment)

  • \cs_new_protected:npn doesn't exist: you'd need \cs_new_protected:Npn (first N capital), but that wouldn't work either because & is not a valid command. You'd need to use \char_set_catcode_active:N \& first, but it would be a pain to handle a catcode-4, a catcode-11, and a catcode-13 & in the same chunk of code. Not impossible, but not necessary either.

That said, a much easier way is to use \char_set_active_eq:NN <char> <macro> to make the active character <char> equal to the <macro>, and then make <char> active using \char_set_catcode_active:N. In your case, <char> is \&. Also you don't need to reset & at the end of the environment, as this is done by the group formed by \begin/\end. Here's the code:

\documentclass{article}
\usepackage{expl3,etoolbox}
\ExplSyntaxOn
% Define the desired behaviour of &
\cs_new_protected:Npn \kozlovskiy_tab_char:
  {
    \iow_term:n {amp~command}
    \c_alignment_token % same as &
    % Anything after this line must be expandable, or \multicolumn won't work
  }
% Make active-& equal to the macro above, and make & active:
\AtBeginEnvironment{tabular}
  {
    \char_set_active_eq:NN \& \kozlovskiy_tab_char:
    \char_set_catcode_active:N \&
  }
\ExplSyntaxOff
\begin{document}
\begin{tabular}{ccc}
  test&new test\\
  test&\multicolumn{2}{r}{new test}\\
\end{tabular}
\end{document}
| improve this answer | |
  • How to understood,that token will be expandable? – Aleksandr Kozlovskiy Apr 7 at 1:22
  • @AleksandrKozlovskiy It depends. There is a very limited set of expandable commands. If you stick to expl3, the expandable commands are marked with a ★ in interface3. If you are using TeX primitives, all the expandable ones are in this list (so \message, for example, is not expandable). If it is any other macro, it depends on its implementation. If you want to check, just do \edef\test{<command to test here>}, and if it breaks it is not expandable. – Phelype Oleinik Apr 7 at 1:30
6

You don't, at least not like that, because & is not a "command", but an "alignment tab character", just as the error message says. You can choose (an) other character(s) to be alignment characters by declaring, say,

\catcode`\|=\catcode`\&

but this will likely break other parts of LaTeX in your document.

You can turn & into a command character ("active") by declaring and defining, say,

\let\aligamp=&
\catcode`\&=\catcode`\~
\def &{\aligamp\message{amp command}}

(I suspect \protection can interfere with the functioning as expandable alignment character; both \cs_new_protected:Npn and \DeclareRobustCommand make a mess.)

But again, this will likely break other parts of LaTeX in your document. Changing catcodes on the fly also leads to big trouble because environments tend to look ahead, perhaps collecting their entire body text, before doing anything, so the characters are frozen with the wrong category.

For the example you've shown, it makes more sense to use the >{} declaration in the tabular template argument.

| improve this answer | |
  • In “usual alignments” TeX doesn't look for & with expansion only, like it does for \omit and the like, so \protected shouldn't be a problem, right? Or am I missing something? – Phelype Oleinik Apr 7 at 0:33
  • 1
    I think you are probably right. A \relax after & would ruin \multicolumn, but a \relax from \protect before & should be benign. I suspect my trouble with \cs_new_protected:Npn was the expl-syntax treating ~ differently, whereas \DeclareRobustCommand can't define an active character -- it redefines \ ! – Donald Arseneau Apr 7 at 0:55
  • Cool, I never realised \DeclareRobustCommand doesn't work with an active token... Also your comment pointed a bug in my answer: the \message should go before the & as well. Thanks :-) – Phelype Oleinik Apr 7 at 1:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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