The collcell Package
Martin Scharrer
martin@scharrer-online.de http://www.ctan.org/pkg/collcell/Version v0.5 – 2011/02/27
AbstractThis package provides macros which collect the cell content of a tab-ular and provide it to a macro as argument. It was inspired by the \collect@body macro defined by the amsmath or the environ package, which can be used to collect the body of an environment. Special care is taken to remove all aligning macros inserted by tabular from the cell content. The macros also work in the last column of a tabular. They do not support verbatim material inside the cells, except of a special almost-verbatim version of \verb.
This package is relatively new and might still not work in all possible situations which can arise in a tabular. The implementation might change in future versions. Please do not hesitate to contact the author about any issue and suggestions.
1
Usage
This package provides the macros\collectcelland \endcollectcellwhich are supposed to be used with the >{ } and <{ } tabular column declarations of the array package. This can be done either in the argument of tabular or using\newcolumntype.
The following code defines a ‘E’ column which passes the contents of its cell to\usermacroas an argument. The macro can the process the content as usual.
% Preamble: \usepackage{array} \usepackage{collcell} % Preamble or document: \newcolumntype{E}{>{\collectcell\usermacro}c<{\endcollectcell}} % Document: \begin{tabular}{lE}
For example \usermacro could be \fbox and wrap the cell content in a frame box. More complicated macros are also supported as long they take one argument. This package was originally programmed to be used with the
\tikztimingmacro of the tikz-timing package. This macro takes some com-plex user input and draws a timing diagram from it
Note that if such a cell contains a tabular environment by itself, the envi-ronment must be wrapped in braces ‘{ }’ to ensure proper operation.
1.1
Options
The following options are supported:
verb
noverb (Default noverb) Enables or disables the definition of a special almost-verbatim version of \verb. At the moment the one defined by the tabularx package is used, which is therefore loaded when this feature is enabled. Future versions of collcell might provide this macro in a different way, so the visual result might be different. The tabularx should be loaded explicitly if it is used. This version of \verb will read the content first nor-mally, i.e. non-verbatim, and then print the included tokens in a verbatim format. The content must include a balanced number of { } and must not be end with \. Macros inside the content will be followed by a space. See the manual of tabularx (page 8 in the version from 1999/01/07) for a more detailed description.
robustcr
norobustcr (Default robustcr) This options enable or disable the redefinition of \\ to a robust version, i.e. this macro will be prefixed with eTeX’s \protected to ensure that it isn’t expanded by the underlying \halign. If this feature disabled the last cell of a tabular must not be empty or only hold empty macros (like \empty).
1.2
Limitations
\ccunskipThe macro \unskip should not be included inside the cell directly, but only inside a { } group or a macro. Otherwise it will be taken as part of the internal cell code and ignored. Leading spaces will however be removed. This macro can be used as a replacement of \unskip inside the cells.
The content of every cell is expanded by TeX itself until the first non-expandable token (macro, character, . . . ) is found. This happens to check if a \noalign follows with e.g. is used inside \hrule and other rule drawing macros. There is nothing what collcell could do about this. If this expansion is unwanted the non-expandable token\ccishould be placed at the beginning of the cell. This macro will be ignored (discarded) by collcell and will not be provided to the user macro (cci = collect cell; ignore).
2
Tests and Examples
F¿l¡M¿l¡T¿l¡@M@ @T @ ABHLDZ2HZLZAZ5DT EST ZZ5DT EST ZAZ5DT EST ZZ5DT EST Z a b c AA5+5CABB3ttz
1 \ m a k e a t l e t t e r 2 \ n e w c o m m a n d *\ M e a n i n g [1] 3 {\ def \ C O D E { # 1 } \ t e x t t t {\ e x p a n d a f t e r \ s t r i p @ p r e f i x \ m e a n i n g \ C O D E }} % 4 \ n e w c o l u m n t y p e { F }{ >{\ c o l l e c t c e l l \ f b o x } l <{\ e n d c o l l e c t c e l l }} % 5 \ n e w c o l u m n t y p e { M }{ >{\ c o l l e c t c e l l \ M e a n i n g } l <{\ e n d c o l l e c t c e l l }} % 6 \ n e w c o l u m n t y p e { T }{ >{\ c o l l e c t c e l l \ t e x t t i m i n g } l <{\ e n d c o l l e c t c e l l }} % 7 \ b e g i n { t a b u l a r }{ @ {} F@ {}| @ {} M@ {}| @ {} T@ {}} 8 A & B & H L D Z 2{ H Z L Z } \\ 9 A & \ e m p t y \ r e l a x Z 5 D { T E S T } Z & Z 5 D { T E S T } Z \\ 10 A & \ cci \ e m p t y Z 5 D { T E S T } Z & Z 5 D { T E S T } Z \\
11 {\ b e g i n { t a b u l a r }{ cFc } a & b & c \ end { t a b u l a r }} & 12 \ r e l a x \ b e g i n { q u o t e } AA \ end { q u o t e } & $ 5 + 5 $ { C } \\ 13 A & B \ c c u n s k i p B & 3{ ttz } \\ 14 \ end { t a b u l a r } %
Example 1: Framebox, texttiming, expanded tokens, sub-tabular M¿
l¡ F¿ l¡
Multi single
A B C
1 \ def \ abc { \ e m p t y A & \ e m p t y B & \ e m p t y C } 2 \ b e g i n { t a b u l a r }{ MMM }
3 \ m u l t i c o l u m n { 2 } { M }{\ e m p t y M u l t i } & \ e m p t y s i n g l e \\ 4 \ abc \\
5 \ end { t a b u l a r }
F F F AABABABCBBBCCABC 1 \ b e g i n { t a b u l a r }{| F | F | F |} 2 \\ 3 A & \\ 4 A & B \\ 5 A & B & \\ 6 A & B & C \\ 7 & \\ 8 & B \\ 9 & B & \\ 10 & B & C \\ 11 & & \\ 12 & & C \\ 13 A & B & C 14 \ end { t a b u l a r }
3
Implementation
15 \ R e q u i r e P a c k a g e { a r r a y } 16 \ def \ c o l l c e l l @ b e f o r e u s e r {\ i g n o r e s p a c e s } 17 \ def \ c o l l c e l l @ a f t e r u s e r {\ u n s k i p } 18 19 \ n e w i f \ i f @ c o l l c e l l @ v e r b 20 \ n e w i f \ i f @ c o l l c e l l @ r o b u s t c r 21 \ @ c o l l c e l l @ r o b u s t c r t r u e3.1
Options
22 \ D e c l a r e O p t i o n { v e r b }{\ @ c o l l c e l l @ v e r b t r u e } 23 \ D e c l a r e O p t i o n { n o v e r b }{\ @ c o l l c e l l @ v e r b f a l s e } 24 \ D e c l a r e O p t i o n { r o b u s t c r }{\ @ c o l l c e l l @ r o b u s t c r t r u e } % 25 \ D e c l a r e O p t i o n { n o r o b u s t c r }{\ @ c o l l c e l l @ r o b u s t c r f a l s e } % 26 \ P r o c e s s O p t i o n s \ r e l a x 27 \ i f @ c o l l c e l l @ v e r b 28 \ R e q u i r e P a c k a g e { t a b u l a r x } 29 \ def \ c o l l c e l l @ b e f o r e u s e r { % 30 \ let \ c o l l c e l l @ s a v e d v e r b \ v e r b 31 \ let \ v e r b \ T X @ v e r b 32 \ let \ T X @ v w a r n \ c o l l c e l l @ v w a r n 33 \ i g n o r e s p a c e s 34 } % 35 \ def \ c o l l c e l l @ a f t e r u s e r {\ u n s k i p \ let \ v e r b \. c o l l c e l l @ s a v e d v e r b } % 36 \ def \ c o l l c e l l @ v w a r n { % 37 \ P a c k a g e W a r n i n g { c o l l c e l l }{\ n o e x p a n d \ v e r b may be . u n r e l i a b l e i n s i d e a c o l l e c t e d c e l l } % 38 } % 39 \ fi 40 \ i f @ c o l l c e l l @ r o b u s t c r 41 \ R e q u i r e P a c k a g e { e t o o l b o x } 42 \ r o b u s t i f y \ @ a r r a y c r 43 \ fi3.2
Collect cell content
44 \ let \ c o l l e c t @ c e l l @ t o k s \ @ t e m p t o k e n a 45 \ n e w c o u n t \ c o l l e c t @ c e l l @ c o u n t
#1: user macro(s)
#2: ignored tokens, possible empty
46 \ n e w e n v i r o n m e n t { c o l l e c t c e l l } { } { } 47 \ def \ c o l l e c t c e l l # 1 # 2 \ i g n o r e s p a c e s { % 48 \ b e g i n g r o u p 49 \ c o l l e c t @ c e l l @ c o u n t \ z@ 50 \ c o l l e c t @ c e l l @ t o k s {} % 51 \ let \ c o l l e c t @ c e l l @ s p a c e s \ e m p t y 52 \ def \ c o l l e c t @ c e l l @ e n d { % 53 \ e x p a n d a f t e r \ e n d g r o u p 54 \ e x p a n d a f t e r \ c o l l c e l l @ b e f o r e u s e r 55 \ e x p a n d a f t e r \ c c e l l @ s w a p \ e x p a n d a f t e r {\ the \. c o l l e c t @ c e l l @ t o k s } { # 1 } % 56 \ c o l l c e l l @ a f t e r u s e r 57 } % 58 \ c o l l e c t @ c e l l @ l o o k #2 % 59 } \ccell@swap
Swaps the two arguments. The second one (user macro(s)) is added without braces.
60 \ def \ c c e l l @ s w a p # 1 # 2 { # 2 { # 1 } }
\endcollectcell
Holds unique signature which will expand to nothing.
61 \ def \ e n d c o l l e c t c e l l {\ @ g o b b l e { e n d c o l l e c t c e l l }}
\collect@cell@look
Looks ahead to the next token and call the next macro to handle it.
62 \ def \ c o l l e c t @ c e l l @ l o o k { %
63 \ f u t u r e l e t \ c o l l e c t @ c e l l @ l e t t o k e n \ c o l l e c t @ c e l l @ l o o k @ 64 }
\collect@cell@eatspace
65 \ @ f i r s t o f o n e {\ def \ c o l l e c t @ c e l l @ e a t s p a c e } {\.
c o l l e c t @ c e l l @ l o o k }
\collect@cell@look@
Handles special tokens which should not be read as argument. All other are handled by\collect@cell@arg. 66 \ def \ c o l l e c t @ c e l l @ l o o k @ { % 67 \ c c @ c a s e 68 \ @ s p t o k e n { % 69 \ e d e f \ c o l l e c t @ c e l l @ s p a c e s {\ c o l l e c t @ c e l l @ s p a c e s \. s p a c e } % 70 \ c o l l e c t @ c e l l @ e a t s p a c e 71 } % 72 \ b g r o u p {\ c o l l e c t @ c e l l @ g r o u p } % 73 \ d e f a u l t {\ c o l l e c t @ c e l l @ a r g } % 74 \ e n d c c @ c a s e 75 } \collect@cell@group
Tests if the previous discovered begin-group character { token was a \bgroup or a {. In the first case the command sequence is simply added but in the sec-ond case the surrounding braces must be added again. The use of \unexpanded allows # in the cells, e.g. for in-cell macro definitions.
76 \ def \ c o l l e c t @ c e l l @ g r o u p #1{ % 77 \ b e g i n g r o u p 78 \ e d e f \ @ t e m p a {\ u n e x p a n d e d { # 1 } } % 79 \ def \ @ t e m p b {\ b g r o u p } % 80 \ ifx \ @ t e m p a \ @ t e m p b 81 \ e n d g r o u p 82 \ c o l l e c t @ c e l l @ a d d a r g { # 1 } % 83 \ e l s e 84 \ e n d g r o u p 85 \ c o l l e c t @ c e l l @ a d d a r g { { # 1 } } % 86 \ fi 87 \ c o l l e c t @ c e l l @ l o o k 88 } \collect@cell@addarg
89 \ def \ c o l l e c t @ c e l l @ a d d a r g #1{ % 90 \ e x p a n d a f t e r \ e x p a n d a f t e r \ e x p a n d a f t e r \. c o l l e c t @ c e l l @ t o k s 91 \ e x p a n d a f t e r \ e x p a n d a f t e r \ e x p a n d a f t e r 92 {\ e x p a n d a f t e r \ the \ e x p a n d a f t e r \ c o l l e c t @ c e l l @ t o k s \. c o l l e c t @ c e l l @ s p a c e s #1} % 93 \ let \ c o l l e c t @ c e l l @ s p a c e s \ e m p t y 94 } \collect@cell@addcc
This macro is called when another \collectcell is found in the preamble (at the moment also inside the cell). The argument of it is placed into the token register and all following tokens are placed in an own token list which content is then added with surrounding braces in the outer token list once the \endcollectcell is found. TeX scoping mechanism is used for this so only one token register is required.
95 \ def \ c o l l e c t @ c e l l @ a d d c c #1{ % 96 \ c o l l e c t @ c e l l @ a d d a r g { # 1 } % 97 \ b e g i n g r o u p 98 \ c o l l e c t @ c e l l @ t o k s {} % 99 \ c o l l e c t @ c e l l @ l o o k 100 } \collect@cell@checkcsname
For support of \end{tabularx} without trailing \\.
\collect@cell@checkend
#1: The argument of an “end macro
Reads the argument of \end and checks if it is identical to the current environ-ment (tabular, array, tabularx, ...). If so the collecting of token is ended, otherwise the \end and its argument are added to the
116 \ def \ c o l l e c t @ c e l l @ c h e c k e n d #1{ % 117 \ b e g i n g r o u p 118 \ def \ @ t e m p a { # 1 } % 119 \ ifx \ @ t e m p a \ @ c u r r e n v i r 120 \ e n d g r o u p 121 \ e x p a n d a f t e r \ @ f i r s t o f t w o 122 \ e l s e 123 \ e n d g r o u p 124 \ e x p a n d a f t e r \ @ s e c o n d o f t w o 125 \ fi 126 {\ c o l l e c t @ c e l l @ c r \\\ end { # 1 } } % 127 {\ c o l l e c t @ c e l l @ a d d a r g {\ end { # 1 } } \ c o l l e c t @ c e l l @ l o o k. } % 128 } \cc@iftoken
Compares the \collect@cell@lettoken with the token given as argument.
129 \ def \ c c @ i f t o k e n #1{ % 130 \ ifx #1\ c o l l e c t @ c e l l @ l e t t o k e n 131 \ e x p a n d a f t e r \ @ f i r s t o f t w o 132 \ e l s e 133 \ e x p a n d a f t e r \ @ s e c o n d o f t w o 134 \ fi 135 } \cc@case
Case statement over \collect@cell@lettoken.
143 \ e x p a n d a f t e r \ c c @ @ t r u e c a s e 144 \ e l s e 145 \ e x p a n d a f t e r \ c c @ @ f a l s e c a s e 146 \ fi 147 } 148 \ def \ c c @ @ t r u e c a s e # 1 # 2 \ e n d c c @ c a s e {\ e n d g r o u p #1} 149 \ def \ c c @ @ f a l s e c a s e # 1 { \ c c @ @ c a s e } \collcell@unskip
Wrapper around \unskip to protect it from the eyes of the token scanner. It is protected to avoid trouble if the user wrongly uses it at the beginning of the cell. The macro is first defined using \newcommand to warn the user about name collisions.
150 \ n e w c o m m a n d *\ c c u n s k i p {}
151 \ p r o t e c t e d \ def \ c c u n s k i p {\ u n s k i p }
\cci
Protected empty macro usable to stop the expansion of tokens at the beginning of the cell. It is ignored (gobbled) by the token scanner. The macro is first defined using \newcommand to warn the user about name collisions.
152 \ n e w c o m m a n d *\ cci {} 153 \ p r o t e c t e d \ def \ cci {}
\collect@cell@cr
Redefines the table line/row end macro \cr so that token collection is restarted after the real \cr is expanded and the end material defined by ‘¡‘ is inserted.
This redefinition must be done around some dirty tricks otherwise the \cr will be wrongly taken as end of the row.
Because the redefinition is done just at the end of a cell inside the group opened by collcell it will only be locally.
\collect@cell@arg
Handles the arguments. The first token of the argument is still in the lettoken macro which is compared against a list of possible end tokens. Then either the cell end is handled or the argument is added to the token register and the rest of the cell is processed.