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

1 Answer 1

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}
9
  • 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?
    – user131051
    Apr 12, 2017 at 20:31
  • 1
    @Benedict \refChapter is not fully expandable
    – egreg
    Apr 12, 2017 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?
    – user131051
    Apr 13, 2017 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, 2017 at 8:59
  • 1
    @Benedict Since it should be unexpanded twice, the same strategy applies: \noexpand\noexpand\noexpand\S.
    – egreg
    Apr 13, 2017 at 9:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .