2

The core of my question is how to define a macro that does something different the first time it is called with a given argument. And further, have the ability to reset that so that that first time behaviour can be restored.

I want to use this to cause citations to show the cited work's title the first time they are used, in the margin.

This is what I have come up with, using etoolbox flags.

\documentclass[]{article}
\usepackage{etoolbox}
\usepackage[style=authoryear, backend=biber]{biblatex}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%Arguments: namespace,key,if first-action, if-not-first action
\newcommand{\iffirstuse}[4]{%
    \global\providetoggle{#1#2}%
    \global\nottoggle{#1#2}{#3}{#4}%
    \global\toggletrue{#1#2}%
}

\let\oldcite\cite
\def\citenamespace{citeA}
\renewcommand{\cite}[1]{%
    \iffirstuse{\citenamespace}{#1}%
    {%
        \oldcite{#1}%
        \marginpar{\citetitle{#1}}%
    }{%
    \oldcite{#1}%
    }%
}

\newcommand{\resetcitescount}{%
    \xdef\citenamespace{{\citenamespace}A}
}

%%%%%%%%%%%%%%%%%%%%%%


\begin{filecontents}{\jobname.bib}
    @book{Labov1972,
        Address = {Philadelphia},
        Author = {William Labov},
        Publisher = {University of Pennsylvania Press},
        Title = {Sociolinguistic Patterns},
        Year = {1972}}

    @book{Chomsky1957,
        Address = {The Hague},
        Author = {Noam Chomsky},
        Publisher = {Mouton},
        Title = {Syntactic Structures},
        Year = {1957}}
\end{filecontents}

\addbibresource{\jobname.bib}


\begin{document}
It was said that there were patterns (\cite{Labov1972}.)\\
\cite{Labov1972} speaks of patterns in language based on society.\\
This can be contrasted with the earlier work of \cite{Chomsky1957}.\\
\cite{Labov1972} is newer than \cite{Chomsky1957}\\
With all that said\\
and all that done\\
\resetcitescount{} 
Do not forget \cite{Chomsky1957}

\end{document}

Demo screenshot

This works, but I am not sure if it is the best way.

Further I don't know how well it would scale to all the complexities of the different cite commands in biblatex, like \parencite{refone,reftwo,refthree}.

Is there a smarter way to do this?

  • 1
    There is \ifciteseen to check whether the current citation key has been seen before. It must be activated with the citetracker option. The tracker can be reset with \citereset. – moewe Aug 27 '18 at 11:47
  • @moewe that sounds like the basis of an answer. Care to make it one? – Frames Catherine White Aug 27 '18 at 11:48

1 Answers1

1

The test \ifciteseen checks if the current entry was seen/cited before. It must be enabled with the citetracker option.

In the example below I patched the cite bibmacro with xpatch to include the title in the margin if needed.

\documentclass[]{article}
\usepackage{etoolbox}
\usepackage[style=authoryear, backend=biber, citetracker=true]{biblatex}

\usepackage{xpatch}

\makeatletter
\xapptobibmacro{cite}{%
  \ifciteseen
    {}
    {\scbx@savepunctstate
     \marginpar{%
       \scbx@resetpunctstate
       \printfield[citetitle]{labeltitle}}%
     \scbx@restorepunctstate}%
}{}{}

\newcommand*{\scbx@savepunctstate}{%
  \let\scbx@saved@unitpunct\blx@unitpunct
  \let\scbx@saved@tgl@unit\etb@tgl@blx@unit
  \let\scbx@saved@tgl@block\etb@tgl@blx@block
  \let\scbx@saved@tgl@insert\etb@tgl@blx@insert
  \let\scbx@saved@tgl@lastins\etb@tgl@blx@lastins
  \let\scbx@saved@tgl@keepunit\etb@tgl@blx@keepunit
}

\newcommand*{\scbx@restorepunctstate}{%
  \global\let\blx@unitpunct\scbx@saved@unitpunct
  \global\let\etb@tgl@blx@unit\scbx@saved@tgl@unit
  \global\let\etb@tgl@blx@block\scbx@saved@tgl@block
  \global\let\etb@tgl@blx@insert\scbx@saved@tgl@insert
  \global\let\etb@tgl@blx@lastins\scbx@saved@tgl@lastins
  \global\let\etb@tgl@blx@keepunit\scbx@saved@tgl@keepunit
}

\newcommand*{\scbx@resetpunctstate}{%
  \let\blx@unitpunct\@empty
  \global\togglefalse{blx@block}%
  \global\togglefalse{blx@unit}%
  \global\togglefalse{blx@insert}%
  \global\togglefalse{blx@lastins}%
  \global\togglefalse{blx@keepunit}%
}
\makeatletter


\begin{filecontents}{\jobname.bib}
@book{Labov1972,
  address   = {Philadelphia},
  author    = {William Labov},
  publisher = {University of Pennsylvania Press},
  title     = {Sociolinguistic Patterns},
  year      = {1972},
}

@book{Chomsky1957,
  address   = {The Hague},
  author    = {Noam Chomsky},
  publisher = {Mouton},
  title     = {Syntactic Structures},
  year      = {1957},
}
\end{filecontents}

\addbibresource{\jobname.bib}


\begin{document}
It was said that there were patterns \parencite{Labov1972,Chomsky1957}.

\cite{Labov1972} speaks of patterns in language based on society.

This can be contrasted with the earlier work of \cite{Chomsky1957}.

\cite{Labov1972} is newer than \cite{Chomsky1957}

With all that said
and all that done

\citereset
Do not forget \cite{Chomsky1957}
\end{document}

\scbx@savepunctstate and friends are just to avoid unwanted side-effects of two different tracking levels for punctuation, see Sidecite only once per page.

Three margin entries. One for <code>Labov1972</code>, then for <code>Chomsky1957</code> and after the reset again for <code>Chomsky1957</code>.

moewe
  • 175,683
  • Cool. Could you add an example of this working for say \parencite{Labov1972,Chomsky1957}} ? Or does that require something separate? (I am guessing there is common code for all the \*cite commands, that you patch there? – Frames Catherine White Aug 27 '18 at 13:03
  • @LyndonWhite I changed the example code to show that this works for multiple \parencite as well. Since the answer patches the cite bibmacro it works for all commands except \textcite for which you have the same thing (\xapptobibmcaro) just with textcite, so that is left as an exercise. – moewe Aug 27 '18 at 14:52