2

I continue forth with my saga to expand stuff in LaTeX using etoolbox.

This time I have the following piece of code.

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

\newcount\infoCounter

\newcommand{\addInfoRef}[1]{
\unexpanded{\nameref{\csuse{info#1Label}}}
\cseappto{info#1Ref}{Mentioned in %
                    \unexpanded{\unexpanded{\nameref}}{\csuse{info\currentname Label}}%
                    \unexpanded{\unexpanded{\\}}
                    }
}


\newcommand{\newInfon}[3][]{
\listxadd\listInfo{#2}
\edef\currentname{#2}
\csedef{info#2Label}{infoKey\the\infoCounter}
\advance\infoCounter by 1
\ifstrempty{#1}{}{\csedef{info#2Img}{#1}}
\csedef{info#2Cnt}{#3}
\nullfont#3\normalfont
}

\newcommand{\printInfo}[1]{%
\edef\currentName{#1}
\section{#1}\label{\expandafter\csuse{info#1Label}}%
\csuse{info#1Cnt}
\ifcsname info#1Ref\endcsname
\\\begin{tabular}{p{9cm}}
  \csuse{info#1Ref}
\end{tabular}
\fi}

\begin{document}

\chapter{Tests Result}

\newInfon{Test Case 1}{%
The result was inconclusive.}

\newInfon{Test Case 2}{%
The result was more conclusive than in \addInfoRef{Test Case 1}, but was still inconclusive.}

\newInfon{Test Case 3}{%
The result less conclusive than in \addInfoRef{Test Case 2}, but was still more conclusive than in \addInfoRef{Test Case 1}.}

\printInfo{Test Case 1}
\printInfo{Test Case 2}
\printInfo{Test Case 3}

\end{document}

The desired output is... well, ALMOST what is generated:

enter image description here

The two red dots atop show that something is being referenced before the time. If you try reordering \printInfo{Test Case X} and you'll notice that then the "Mentions" are not printed properly anymore. For instance, if I reorder:

\printInfo{Test Case 3}
\printInfo{Test Case 2}
\printInfo{Test Case 1}

I get

enter image description here

That is, some "Mention" entries are duplicated! I've considering doing something like

\ifcsname info\currentname#2Switch\endcsname{\relax}{%
  \cseappto{info#2Ref}{Mentioned in...}
}
\csedef{info\currentname#2Switch}{1}

in \addInfoRef, but that didn't work and I couldn't figure out why.

Any help is appreciated! Thanks in advance!

  • I am not sure I understand what you want to do here actually. Besides that you're missing several % at the end of the opening { bracket of the code section of your commands. – user31729 Apr 17 '17 at 13:10
  • Added more images to make it clearer. In any case, I don't think that the % have anything to do with the fact that the expansion is not being done the way I would like it to be. – Benedict Apr 17 '17 at 13:29
  • @Benedict they don't but they tend to add unwanted spaces. – Skillmon Apr 17 '17 at 14:05
  • Thanks for the heads up. This is not my real code, this is just a simplified version I am posting here. – Benedict Apr 17 '17 at 14:12
  • @Benedict: The comment about the % was an extra gift, because that's why I wrote besides ;-) – user31729 Apr 17 '17 at 15:46
2

Here is an implementation with expl3 (via xparse). The \newInfon command has an optional argument to be used if the first mandatory argument contains non ASCII characters (I made an example): the optional argument is just a key to be used wherever a reference to the case is made.

The trick is to make \addInfoRef do two different things and to execute it when \newInfon is performed inside a box, so the output is eventually discarded.

\documentclass{book}
\usepackage[utf8]{inputenc}
\usepackage[greek,english]{babel}
\usepackage{xparse}
\usepackage{etoolbox}
\usepackage[unicode]{hyperref}

\pdfstringdefDisableCommands{\let\textgreek\relax}

\ExplSyntaxOn

\prop_new:N \g_benedict_info_items_prop
\bool_new:N \l_benedict_info_add_bool

\NewDocumentCommand{\newInfon}{O{#2}mm}
 {
  \prop_gput:Nnn \g_benedict_info_items_prop
   { #1 key }  % key
   { #2 }
  \prop_gput:Nnx \g_benedict_info_items_prop
   { #1 text } % text
   { \tl_trim_spaces:n { #3 } }
  \tl_set:Nn \l__benedict_info_temp_tl { #1 }
  \hbox_set:Nn \l_tmpa_box
   {
    \bool_set_true:N \l_benedict_info_add_bool #3
   }
 }

\NewDocumentCommand{\addInfoRef}{m}
 {
  \bool_if:NTF \l_benedict_info_add_bool
   {
    \seq_if_exist:cF { g_benedict_info_#1_seq }
     {
      \seq_new:c { g_benedict_info_#1_seq }
     }
    \seq_gput_right:cx { g_benedict_info_#1_seq }
     {
      Mentioned ~ in ~ \exp_not:N \nameref{\l__benedict_info_temp_tl label}
     }
   }
   {
    \prop_item:Nn \g_benedict_info_items_prop { #1 key }
   }
 }

\NewDocumentCommand{\printInfo}{m}
 {
  \exp_args:Nx \section {\prop_item:Nn \g_benedict_info_items_prop { #1 key }}\label{#1label}
  \prop_item:Nn \g_benedict_info_items_prop { #1 text }
  \seq_if_exist:cT { g_benedict_info_#1_seq }
   {
    \\*[\medskipamount]
    \begin{tabular}{@{} p{9cm} @{}}
    \seq_use:cn { g_benedict_info_#1_seq } { \\ }
    \end{tabular}
    \par\addvspace{\medskipamount}
   }
 }
\ExplSyntaxOff

\begin{document}

\chapter{Tests Result}

\newInfon[TC1]{Test Case (\textgreek{δοκιμή}) 1}{
  The result was inconclusive.
}

\newInfon{Test Case 2}{
  The result was more conclusive than in \addInfoRef{TC1},
  but was still inconclusive.
}

\newInfon{Test Case 3}{
  The result less conclusive than in \addInfoRef{Test Case 2},
  but was still more conclusive than in \addInfoRef{TC1}.
}

\printInfo{TC1}
\printInfo{Test Case 2}
\printInfo{Test Case 3}

\end{document}

enter image description here

  • Woa, it works even with greek characters! However, expl3 notation is a total mystery to me, I cannot bring myself to comprehend it (at least yet). Moreover the rest of the package is written purely with etoolbox, so if I could stay there it would be better. In any case, I've tried the box trick (more precisely with savebox), but went nowhere, or ended up with 2 copies of some of the "Mentions". Which lines of your code are responsible for this boxing? – Benedict Apr 17 '17 at 14:43
  • @Benedict \hbox_set:Nn is the key you're looking for, but there's also the conditional in the definition of \addInfoRef. – egreg Apr 17 '17 at 14:45
  • Well, yeah, I have no idea how to your your solution, @egreg. My actual package is much more complicated than this (I just simplified it here to show the core of the problem) and I am completely oblivious to expl3 notation so I cannot translate it. Thank anyway. I will be waiting for a pure-etoolbox solution, or just give up LaTeX all together since debugging it is close to impossible. – Benedict Apr 17 '17 at 16:07
2

I answered my own question through extensive trial-and-error. Basically I've created a printingInfo variable, set it to 0, and only set it to 1 during printInfo. Then the addInfoRef function only performs the cseappto if this printingInfo=0.

This is the working solution:

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

\newcount\infoCounter

\edef\printingInfo{0}%
\newcommand{\addInfoRef}[1]{%
\ifstrequal{\printingInfo}{0}{\unexpanded{\nameref{\csuse{info#1Label}}}}{%
\cseappto{info#1Ref}{Mentioned in %
\unexpanded{\unexpanded{\nameref}}{\csuse{info\currentname Label}}%
\unexpanded{\unexpanded{\\}}}%
}%
}


\newcommand{\newInfon}[3][]{
\edef\printingInfo{0}%
\edef\currentname{#2}
\csedef{info#2Label}{infoKey\the\infoCounter}
\advance\infoCounter by 1
\ifstrempty{#1}{}{\csedef{info#2Img}{#1}}
\csedef{info#2Cnt}{#3}
\nullfont#3\normalfont
}

\newcommand{\printInfo}[1]{%
\edef\printingInfo{1}%
\edef\currentname{#1}
\section{#1}\label{\expandafter\csuse{info#1Label}}%
\csuse{info#1Cnt}
\ifcsname info#1Ref\endcsname
\\\begin{tabular}{p{9cm}}
  \csuse{info#1Ref}
\end{tabular}
\fi}

\begin{document}

\chapter{Tests Result}

\newInfon{Test Case 1}{%
The result was inconclusive.}

\newInfon{Test Case 2}{%
The result was more conclusive than in \addInfoRef{Test Case 1}, but was still inconclusive.}

\newInfon{Test Case 3}{%
The result less conclusive than in \addInfoRef{Test Case 2}, but was still more conclusive than in \addInfoRef{Test Case 1}.}

\printInfo{Test Case 1}
\printInfo{Test Case 2}
\printInfo{Test Case 3}

\end{document}

The only remaining problem now is the leftover spacing in-between "chapter 1" and the sections.

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.