Continúo con mi saga para ampliar cosas en LaTeX usando etoolbox
.
Esta vez tengo el siguiente código.
\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}
El resultado deseado es... bueno, CASI lo que se genera:
Los dos puntos rojos en la parte superior muestran que se hace referencia a algo antes de tiempo. Si intenta reordenar \printInfo{Test Case X}
y notará que las "Menciones" ya no se imprimen correctamente. Por ejemplo, si reordeno:
\printInfo{Test Case 3}
\printInfo{Test Case 2}
\printInfo{Test Case 1}
yo obtengo
Es decir, ¡algunas entradas de "Mención" están duplicadas! He considerado hacer algo como
\ifcsname info\currentname#2Switch\endcsname{\relax}{%
\cseappto{info#2Ref}{Mentioned in...}
}
\csedef{info\currentname#2Switch}{1}
en \addInfoRef
, pero eso no funcionó y no pude entender por qué.
¡Cualquier ayuda es apreciada! ¡Gracias de antemano!
Respuesta1
Aquí hay una implementación con expl3
(a través de xparse
). El \newInfon
comando tiene un argumento opcional que se usará si el primer argumento obligatorio contiene caracteres que no son ASCII (hice un ejemplo): el argumento opcional es solo una clave que se usará siempre que se haga una referencia al caso.
El truco consiste en hacer \addInfoRef
dos cosas diferentes y ejecutarlas cuando \newInfon
se realiza dentro de un cuadro, de modo que la salida finalmente se descarte.
\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}
Respuesta2
Respondí mi propia pregunta mediante una extensa prueba y error. Básicamente, creé una printingInfo
variable, la configuré en 0 y solo la configuré en 1 durante printInfo. Entonces la función addInfoRef solo realiza cseappto si esta impresiónInfo = 0.
Esta es la solución de trabajo:
\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}
El único problema que queda ahora es el espacio sobrante entre el "capítulo 1" y las secciones.