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 require two new commands, \createreference and \citereference, to work with. They should work as shown in the following examples:

\createreference{john}{John Q. Citizen} should write the text “John Q. Citizen” into the file myreferences.aux. The text should be somehow associated with the corresponding entry john.

\citereference{john} should print out “??” if no john entry can be found in myreferences.aux (or if the file doesn’t exist). However, it should print out the corresponding text (in this case “John Q. Citizen”) if the entry is found.

This should work even if \createreference appears after \citereference in the code.

I don’t have enough low-level expertise to be able to do this. Does someone else?

share|improve this question

3 Answers 3

up vote 12 down vote accepted

I did not understand where do you want to put the text: in the main file jobname.aux or in the separate file. If the former, this works (basically modelled after the standard \ref-\label mechanism):

\documentclass{article}
\makeatletter
% The command reference writes \newreference into the aux file
\def\createreference#1#2{\@bsphack
  \protected@write\@mainaux{}%
         {\string\newreference{#1}{#2}}%
  \@esphack}
% The command \newreference defines new command named after the first
% argument that produces the second one
\def\newreference#1#2{%
  \expandafter\xdef\csname rfr@#1\endcsname{#2}}
% And using the reference
\def\citereference#1{%
  \expandafter\ifx\csname rfr@#1\endcsname\relax??\else
  \csname rfr@#1\endcsname\fi}
% LaTeX checks at the end of document whether references have 
% been changed.  If any reference is changed, 
% \tempswa is set to true.  Here we add \newreference commands
% to the list to be checked.
\AtEndDocument{\def\newreference#1#2{%
    \edef\reserved@a{#2}%
    \expandafter\ifx\csname rfr@#1\endcsname\reserved@a\else
    \@tempswatrue\fi}}
\makeatother
\begin{document}
\createreference{john}{John Q. Citizen}
\citereference{john} and \citereference{george}
\end{document}

Update Added checking whether the references have been changed.

Update 2 Changed \def to \edef to handle accents

share|improve this answer
    
Sweet, this is exactly what I want and it works. Is there any chance you could add into this the feature that puts out a compilation warning "things may have changed. please recompile" if required? I hope it's not too much of a hassle to add. –  Enchilada Mar 22 '12 at 21:34
    
Ok, see update. –  Boris Mar 22 '12 at 22:08
    
@Boris: The \createreference command does not seem be entirely compatible with non-latin characters, e.g. \createreference{john}{John Q. Staatsbürger}. No errors, but I do get the following: LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. The source of this is the use of the character ü (or \"u). Do you know what could be the problem? I’m using both \usepackage[T1]{fontenc} and \usepackage[utf8]{inputenc}. (The references come out correctly, though.) –  The Third Man Oct 30 '12 at 10:31
    
@TheStochasticLiberal Try changing \def\reserved@a{#2}% to \edef\reserved@a{#2}% as in the update –  Boris Oct 30 '12 at 15:54
    
@Boris: It works! Many thanks. –  The Third Man Oct 30 '12 at 22:25

You can use (or rather abuse?) the standard mechanism:

\makeatletter
\newcommand{\createreference}[2]{%
  \def\@currentlabel{\unexpanded{#2}}\label{#1}}
\newcommand{\citereference}[1]{\ref{#1}}
\makeatother

but I have some doubts whether this is the right thing to do. If you load also hyperref it's probably better to use \ref* instead of \ref, so that no link is created.

Since this uses the standard mechanism, when a new reference is created, the message Label(s) may have changed will be issued.

The .aux file's job is to record information that may change from one run to the other. Declaring a fixed association between john and John Q. Citizen is better done in the preamble, so that all such associations are easily under control:

%%% in the preamble
\newcommand{\createassociation}[2]{%
  \expandafter\newcommand\csname association@#1\endcsname{#2}}
\newcommand{\citeassociation}[1]{\csname association@#1\endcsname}
\createassociation{john}{John Q. Citizen}

%%% in the document

This is the name: \citeassociation{john}
share|improve this answer

zref provides this functionality by default. Here's a minimal example that fulfils your request (lipsum only provides dummy text, Lorem Ipsum style):

enter image description here

\documentclass{article}
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\usepackage{zref}% http://ctan.org/pkg/zref

\makeatletter
\newcommand{\createreference}[2]{%
  \def\@reftext{#2}% Store contents of reference (#2)
  \zref@labelbylist{#1}{special}% Special label writes to .aux
}
\newcommand{\citereference}[1]{%
  \zref@extractdefault{#1}{reftext}{\textbf{??}}% Extract reference, or print ??
}
\zref@newlist{special}% Create a new reference list called special
\zref@newprop{reftext}{\@reftext}% Create property reftext that holds \@reftext
\zref@addprop{special}{reftext}% Special reference list holds reftext
\makeatother

\begin{document}

\createreference{john}{John~Q.\ Citizen}
Do you know \citereference{john} or \citereference{susan}?

\lipsum[7]

\createreference{susan}{\textbf{Suzie}~$\textrm{Q}^2$}
Yes, I know \citereference{john} and \citereference{susan}.

\end{document}

You'll note that formatting is preserved within the referenced text. Here's part of the \jobname.aux file containing the zref labels, showing how the information and formatting is stored:

\zref@newlabel{john}{\reftext{John\nobreakspace  {}Q.\ Citizen}}
\zref@newlabel{susan}{\reftext{\textbf  {Suzie}\nobreakspace  {}$\textrm  {Q}^2$}}
share|improve this answer

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.