Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm writing a long document, and I've written a little macro for keeping track of various things I want to come back to - for example if I want to continue writing but I know that something I've written needs a citation, I can just insert \needcite{Cite that paper from Smith et al.}. Then at the end of the document, I have a macro that enumerates all of these with links to the place in document where I put them.

I have two related and pressing problems with this. The first is that I'm having trouble getting the labels to work. I generate label names programmatically the same way when they are labeled as when they are referenced, but they never seem to be able to find one another. The labels are generated and referenced like this:

\newcommand{\gettextref}[2]{textref#2:#1} % Gets the name of the label of the 
                                          % #1-th item in the #2 reflist.

 \newcommand{\addtext}[2]{%                     Add item #1 to list #2.
    \refstepcounter{tlctr#2}\label{\gettextref{#1}{#2}}%
    \csdef{text#2\arabic{tlctr#2}}{#1 (pp. \arabic{page})}%
}

I've since fixed the label portion of the bug, here's the fixed code:

 \newcommand{\gettextref}[2]{textref#2:#1} % Gets the name of the label of the 
    % #1-th item in the #2 reflist.
     \newcommand{\addtext}[2]{%                     Add item #1 to list #2.
        \refstepcounter{tlctr#2}\label{\gettextref{\arabic{tlctr#2}}{#2}}%
        \csdef{text#2\arabic{tlctr#2}}{#1 (pp. \arabic{page})}%
    }

The second is that I've been saving the page number, so at least I'll have some idea where these things are, and so the text from the above example would generate the string "Cite that paper from Smith et al (pp. 104)". However, seems as if the macros defined inside the \csdef environment are executed when the text is retrieved using \csuse, not when the text is generated.

In practice, it is used this way:

% NeedCite - Keep track of places where you need to add citations.
\textlist{CitationsNeededList}
% \needcite{Note} - Adds the current location to the list of locations needing a citation, with
%                   the note Note. This can then be retrieved using \gettext
\newcommand{\needcite}[1] {%
    \addtext{#1}{CitationsNeededList}\hyperlink{todolist:CiteList}{{\scriptsize $^{\textit{[Cite]}}$}}
}
\newcommand{\listneededcitations} {%
    \label{todolist:CiteList}%
    \getalltextreferenced{CitationsNeededList}%
}

Because \label{todolist:CiteList} is used AFTER the other citations, I usually run xelatex twice so that the reference has already been defined, but to no avail. Neither the hyperlink to todolist:CiteList nor the hyperlinks back to \gettextref{n}{CitationsNeededList} are finding the references.

Below is a MWE. It generates a 4-page document with a single non-cited footnote on each page. The 4th page generates the list of citations needed. In my version at least, the references are not found, and so \ref{\gettextref{1}{CitationsNeededList}} returns (??).

\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage{etoolbox}

\newcommand{\textlist}[1]{ % Create a text list with name #1
    \newcounter{tlctr#1}
    \setcounter{tlctr#1}{0}
}

\newcommand{\gettextref}[2]{textref#2:#1} % Gets the name of the label of the 
                                          % #1-th item in the #2 reflist.

\newcommand{\addtext}[2]{%                  Add item #1 to list #2.
    \refstepcounter{tlctr#2}\label{\gettextref{\arabic{tlctr#2}}{#2}}%
    \csdef{text#2\arabic{tlctr#2}}{#1 (pp. \thepage)}%
}

\newcommand{\getnumstrings}[1]{% Check how many strings are in list #1
    \value{tlctr#1}%
}

\newcommand{\getnstrings}[1]{% Because \value is not human-readable.
    \arabic{tlctr#1}%
}

\newcommand{\gettext}[2]{% Gets the text of #1 from list #2.
    \csuse{text#2#1}%
}


\newcounter{tempcnti}   % A temporary counter, for use in \getalltextreferenced.
                        % Needs to be defined outside of the loop because
                        % LaTeX doesn't like it if you try to define the same counter twice.

\newcommand{\getalltextreferenced}[1]{%  Get all text in list #1 in a referenced list.
    \setcounter{tempcnti}{0}
    \begin{itemize}
    \whileboolexpr
    { test {\ifnumcomp{\thetempcnti}{<}{\value{tlctr#1}}}}%
    {\stepcounter{tempcnti}%
    \item[\hyperlink{\gettextref{\thetempcnti}{#1}}{\arabic{tempcnti}}]\gettext{\thetempcnti}{#1} (\ref{\gettextref{\thetempcnti}{#1}})}%
    \end{itemize}%
}

% NeedCite - Keep track of places where you need to add citations.
\textlist{CitationsNeededList}
% \needcite{Note} - Adds the current location to the list of locations needing a citation, with
%                   the note Note. This can then be retrieved using \gettext
\newcommand{\needcite}[1] {%
    \addtext{#1}{CitationsNeededList}\hyperref[todolist:CiteList]{{\scriptsize $^{\textit{[Cite]}}$}}
}
\newcommand{\listneededcitations} {%
    \label{todolist:CiteList}%
    \getalltextreferenced{CitationsNeededList}%
}

\begin{document}

This is an uncited statement.\needcite{Remember to cite this.}
\newpage
This is a cited statement\needcite{This is clearly a lie, or I'd have a citation here.}
\newpage
This is a third statement on a different page.\needcite{Third statement.}
\newpage
\listneededcitations
\end{document}

And in case you are interested, here's the part of the log about the references missing:

LaTeX Warning: Reference `textrefCitationsNeededList:1' on page 4 undefined on 
input line 66.


LaTeX Warning: Reference `textrefCitationsNeededList:2' on page 4 undefined on 
input line 66.


LaTeX Warning: Reference `textrefCitationsNeededList:3' on page 4 undefined on 
input line 66.

Edit: Switching from \hyperlink{}{} to \hyperref[]{} in \needcite{} seems to have allowed me to at least link to the list of references from the point where the reference is missing. \item[] doesn't seem to like having a \hyperref[]{} in it, for some reason.

Edit 2: I figured out what the problem was with the labels - in \addtext it sets the NOTE to be the label, not the counter value. Still unsure about the page thing

Final Edit: All issues have now been solved, plus one more. I thought I would update everyone in case they were planning on doing something similar later. The page number problem was solved by egreg's suggestion of switching from \csdef to csedef. I had also been experiencing another problem, which is that \needcite{} could not be placed within a \caption{} environment. I've since fixed this by switching from \newcommand{\needcite} to \DefineRobustCommand{\needcite}. Hopefully this is helpful to anyone in the future interested in this sort of system.

share|improve this question
    
The problem with the pages is due to \csdef instead of the necessary \csedef –  egreg Mar 26 '13 at 10:47
    
Thanks egreg! All my problems have now been solved! If you want to add that as an answer I can accept it. –  Paul Mar 26 '13 at 22:54
add comment

1 Answer

up vote 3 down vote accepted

The page number problem is due to

\newcommand{\addtext}[2]{%                  Add item #1 to list #2.
    \refstepcounter{tlctr#2}\label{\gettextref{\arabic{tlctr#2}}{#2}}%
    \csdef{text#2\arabic{tlctr#2}}{#1 (pp. \thepage)}%
}

because with \addtext{foo}{bar} you're basically doing (assuming the counter has value 2 before the \addtext

\expandafter\def\csname textbar3\endcsname{foo (pp. \thepage)

So the correct way is to do

\csedef{text#2\arabic{tlctr#2}}{#1 (pp. \thepage)}

that will put in the replacement text the current expansion of \thepage and not the macro \thepage.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.