3

I'm trying to get this "timeline" thing going for a document I'm writing. Follows the code I've got so far:

\documentclass{article}
\usepackage{etoolbox}
\newcommand{\addTimeline}[3][]{%
\ifcsname timeLine#2\endcsname
  \expandafter\appto\csname timeLine#2\endcsname{ #3 #1\\}
\else
  \expandafter\csdef{timeLine#2}{{\bf #2}  #3  #1\\}
\fi
}

\newcommand{\gentimeLine}[2]{
\newcount\tmpc
\def\tabledata{}
\tmpc=#1
\loop \ifnum \tmpc<#2 
   \expandafter\csuse{timeLine\the\tmpc}
   \advance \tmpc 1
\repeat 
}

\begin{document}

\addTimeline{10}{Test1}
\addTimeline{20}{Test2}
\addTimeline{13}{Test3}
\addTimeline{25}{Test4}

\def\tabData{\gentimeLine{1}{26}}
\tabData

-

\begin{tabular}{c}\hline   
  \tabData
\end{tabular}

\end{document}

Naturally, in \addTimeline command I intend to have #2 & #3 & #1 and {c c c} in tabular instead, but for testing purposes I am keeping it in one column one.

The expected output was

10 Test1
13 Test3
20 Test2
25 Test4

followed by the table with those entries, each in a respective row.

But instead I get a table with only one row, containing the first entry 10 Test1. The 4 items are correctly printed in normal text, however.

Any suggestions on how to fix?

  • welcome to tex.sx. please add to your code the \documentclass and anything else that would be needed for it to be compiled for experimentation. otherwise, we'd have to guess, and if we make the wrong choice, that's effort wasted. – barbara beeton Apr 12 '17 at 12:26
3

You can't start the loop in one table cell and end it in another one. Thus I use \tabledata as a container that's filled and then delivers the table body all at once.

\documentclass{article}
\usepackage{etoolbox}

\newcommand{\addTimeline}[3][]{%
  \csappto{timeLine#2}{\unexpanded{\textbf{#2}  #3  #1\\}}%
}

\newcount\tmpc
\newcommand{\gentimeLine}[2]{%
  \def\tabledata{}%
  \tmpc=#1\relax
  \loop \ifnum \tmpc<#2
    \edef\tabledata{\expandonce{\tabledata}\csuse{timeLine\the\tmpc}}%
    \advance \tmpc 1
  \repeat
  \tabledata
}

\begin{document}

\addTimeline{10}{Test1}
\addTimeline{20}{Test2}
\addTimeline{13}{Test3}
\addTimeline{25}{Test4}

\def\tabData{\gentimeLine{1}{26}}

\begin{tabular}{c}\hline
  \tabData
\end{tabular}

\end{document}

Notes

  1. etoolbox already offers \csappto that will create the macro if not existing

  2. \newcount must go outside the macro using the counter, or it will create a new one at each call

  3. the \unexpanded in the definition of \addTimeline might be bad for other uses of timeLine<number>

Here's the output:

enter image description here

An implementation in expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\addTimeline}{omm}
 {
  \tl_clear_new:c { l_benedict_timeline_#2_tl }
  \tl_put_right:cn { l_benedict_timeline_#2_tl } { \textbf{#2}~#3 }
  \IfValueT{#1}
   {
    \tl_put_right:cn { l_benedict_timeline_#2_tl } { ~#1 }
   }
  \tl_put_right:cn { l_benedict_timeline_#2_tl } { \\ }
 }

\NewDocumentCommand{\genTimeline}{mm}
 {
  \tl_clear:N \l__benedict_timeline_body_tl
  \int_step_inline:nnnn { #1 } { 1 } { #2 }
   {
    \tl_if_exist:cT { l_benedict_timeline_##1_tl }
     {
      \tl_put_right:Nv \l__benedict_timeline_body_tl { l_benedict_timeline_##1_tl }
     }
   }
  \tl_use:N \l__benedict_timeline_body_tl
 }

\tl_new:N \l__benedict_timeline_body_tl
\cs_generate_variant:Nn \tl_put_right:Nn { Nv }
\ExplSyntaxOff

\begin{document}

\addTimeline{10}{Test1}
\addTimeline{20}{Test2}
\addTimeline[again]{20}{Test2}
\addTimeline{13}{Test3}
\addTimeline{25}{Test4}

\begin{tabular}{c}
\hline
\genTimeline{1}{26}
\hline
\end{tabular}

\end{document}

enter image description here

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.