5

This is a spinoff of another question I posted here.

\documentclass[8pt]{book}
\usepackage{etoolbox}
\usepackage{hyperref}

\newcommand{\mychapter}[1]{\chapter{#1} \hypertarget{chapter::\theHchapter}{}}
\newcommand{\refChapter}{\hyperlink{chapter::\theHchapter}{\thechapter}}

\newcommand{\addTimeline}[2]{%
  \ifcsname timeLine#1\endcsname
    \csappto{timeLine#1}{\unexpanded{\\& #2 & } \thechapter}%
  \else
    \csdef{timeLine#1}{\unexpanded{\\\textbf{#1} & #2 & } \thechapter}%
  \fi
}

\newcount\timelineCounter
\newcommand{\printTimeline}[2]{%
  \def\timelineData{}%
  \timelineCounter=#1\relax
  \loop \ifnum \timelineCounter<#2
    \edef\timelineData{\expandonce{\timelineData}\csuse{timeLine\the\timelineCounter}}%
    \advance \timelineCounter 1
  \repeat
\begin{tabular}{c p{7cm} c}
  \timelineData
\end{tabular}
}


\begin{document}

\mychapter{First}
 \addTimeline{4}{Event1}
 \addTimeline{19}{Event2}
 \addTimeline{2}{Event3}

\mychapter{Second} 
 \addTimeline{29}{Event4}
 \addTimeline{15}{Event5}
 \addTimeline{19}{Event6}

\mychapter{Timeline}
  \printTimeline{1}{30}


\end{document}

I expected it to print two empty chapters followed by a Chapter 3, called Timeline with

  2 Event3        1
  4 Event1        1
 15 Event5        2
 19 Event2        1
    Event6        2
 29 Event4        2

but instead in the third column I get all "3". In the ideal scenario I'd use \refChapter command that I created, instead of the \thechapter, but the former doesn't compile. I am a bit clueless as how to expand this kind of expression. Any guidance would be appreciated.

2

You have to use \cseappto and \csedef, but this requires another \unexpanded around the part you don't want to expand:

\documentclass{book}
\usepackage{etoolbox}
\usepackage{hyperref}

\newcommand{\mychapter}[1]{\chapter{#1} \hypertarget{chapter::\theHchapter}{}}
\newcommand{\refChapter}{\hyperlink{chapter::\theHchapter}{\thechapter}}

\newcommand{\addTimeline}[2]{%
  \ifcsname timeLine#1\endcsname
    \cseappto{timeLine#1}{\unexpanded{\unexpanded{\\& #2 & }} \thechapter}%
  \else
    \csedef{timeLine#1}{\unexpanded{\unexpanded{\\\textbf{#1} & #2 & }} \thechapter}%
  \fi
}

\newcount\timelineCounter
\newcommand{\printTimeline}[2]{%
  \def\timelineData{}%
  \timelineCounter=#1\relax
  \loop \ifnum \timelineCounter<#2
    \edef\timelineData{\expandonce{\timelineData}\csuse{timeLine\the\timelineCounter}}%
    \advance \timelineCounter 1
  \repeat
\begin{tabular}{c p{7cm} c}
  \timelineData
\end{tabular}
}


\begin{document}

\mychapter{First}
 \addTimeline{4}{Event1}
 \addTimeline{19}{Event2}
 \addTimeline{2}{Event3}

\mychapter{Second} 
 \addTimeline{29}{Event4}
 \addTimeline{15}{Event5}
 \addTimeline{19}{Event6}

\mychapter{Timeline}
  \printTimeline{1}{30}


\end{document}

enter image description here

The same with expl3, but with less problems with expansion, because we can expand \theHchapter and \thechapter when the main macro is being called.

\documentclass{book}
\usepackage{xparse}
\usepackage{hyperref}

\ExplSyntaxOn
\cs_set_eq:NN \latexchapter \chapter

% modify \chapter to add a hypertarget
\RenewDocumentCommand{\chapter}{sO{#3}m}
 {
  \IfBooleanTF{#1}
   {
    \latexchapter*{#3}
   }
   {
    \latexchapter[#2]{\hypertarget{chapter::\theHchapter}{#3}}
   }
 }

\NewDocumentCommand{\addTimeline}{smm}
 { % here \theHchapter and \thechapter are expanded prior to doing the hard work
  \benedict_timeline_add:xxnn { \IfBooleanF{#1}{\theHchapter} } { \thechapter } { #2 } { #3 }
 }

\cs_new_protected:Nn \benedict_timeline_add:nnnn
 {
  \tl_if_exist:cTF { l_benedict_timeline_#3_tl }
   { % the header has already appeared
    \tl_put_right:cn { l_benedict_timeline_#3_tl } { & #4 }
   }
   { % the header is new
    \tl_new:c { l_benedict_timeline_#3_tl }
    \tl_put_right:cn { l_benedict_timeline_#3_tl } { \textbf{#3} & #4 }
   }
  % now add the reference; #3 is the header
  % #1 and #2 are \theHchapter and \thechapter (expanded)
  \benedict_timeline_add_ref:nnn { #3 } { #1 } { #2 }
 }
\cs_generate_variant:Nn \benedict_timeline_add:nnnn { xx }

\cs_new_protected:Nn \benedict_timeline_add_ref:nnn
 {
  \tl_if_empty:nTF { #2 } % \theHchapter
   {% modify here for the formatting
    \tl_put_right:cn { l_benedict_timeline_#1_tl } { & \S #3 \\ }
   }
   {
    \tl_put_right:cn { l_benedict_timeline_#1_tl } { & \S \hyperlink{chapter::#2}{#3} \\ }
   }
 }

\NewDocumentCommand{\printTimeline}{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 }
     }
   }
  \begin{tabular}{c p{7cm} c}
  \tl_use:N \l__benedict_timeline_body_tl
  \end{tabular}
 }

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

\begin{document}

\chapter{First}

\addTimeline{4}{Event1}
\addTimeline{19}{Event2}
\addTimeline{2}{Event3}

\chapter{Second} 

\addTimeline{29}{Event4}
\addTimeline{15}{Event5}
\addTimeline{19}{Event6}

\chapter{Timeline}

\printTimeline{1}{30}

\end{document}
  • Thanks, I'd never guess you have to nest those unexpanded. This works perfectly for the \thechapter case, but it fails to compile for \refChapter. Do you have any idea why? – Benedict Apr 12 '17 at 20:31
  • 1
    @Benedict \refChapter is not fully expandable – egreg Apr 12 '17 at 20:38
  • My main problem with latex right now is that it feels pretty much a trail-and-error effort, as I have never heard of a latex debugger. I've just found out that \S\thechapter cannot go in there either for whatever reason, and \thepart.\thechapter works for this small sample, but not at all in my real document. The error messages are more confusing than helpful as they do not reflect the true nature of the error in most cases. Is there any way in which a mere mortal can debug this kind of behaviour without having to annoy people in StackExchange? – Benedict Apr 13 '17 at 8:56
  • @Benedict I think you are approaching the problem from the wrong point of view. Anyway, \S cannot go unprotected in an \edef so you should use \noexpand\S. – egreg Apr 13 '17 at 8:59
  • 1
    @Benedict Since it should be unexpanded twice, the same strategy applies: \noexpand\noexpand\noexpand\S. – egreg Apr 13 '17 at 9:11

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.