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 use brackets to fill out missing information in the bibliography. But when I include this information in citations in the text, these brackets should not appear. In the example below, the text should read

As John Lennon wrote in 1970 ...

The bibliography should nevertheless still retain the brackets. (The custom \citeauthorfullname macro is something I found here).

\documentclass{article}
\usepackage[style = authoryear]{biblatex}
\DeclareCiteCommand{\citeauthorfullname}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \DeclareNameAlias{labelname}{first-last}%
   \usebibmacro{prenote}}
  {\ifciteindex
     {\indexnames{labelname}}
     {}%
   \printnames{labelname}}
  {\multicitedelim}
  {\usebibmacro{postnote}}
\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@book{lennon1970,
    AUTHOR = "J[ohn] Lennon",
    TITLE = "This book was released with my Imagine album",
    YEAR = "[1970]"}
\end{filecontents}
\addbibresource{\jobname.bib}
\begin{document}
As \citeauthorfullname{lennon1970} wrote in \citeyear{lennon1970} \ldots
\printbibliography
\end{document}

enter image description here

share|improve this question
1  
Turns out the album Imagine was released in 1971 ... Oops! –  Sverre Apr 1 at 18:38
    
Shouldn't you have just 1971 etc. in the bib entry and use appropriate bib macros to format the list of references appropriately? (Rather than trying to take that stuff out in the text.) Apart from anything else, your current approach is inflexible - it is hard to change the style of the bibliography because you need to rewrite the bib entries. –  cfr Apr 1 at 20:39
1  
Do you really want '([YYYY])'? –  cfr Apr 1 at 21:20
    
Maybe you could use the sortname and sortyear fields (in which, of course you give the year/name without brackets) and print those in \citeauthorfullname and \citeyear? Another approach (that is probably not applicable to names or more complex situations) is to input all data normally but add a flag guessedyear which causes biblatex to wrap the guessed year into brackets in the bibliography (this could be extended to other fields as well, it will fail for Lennon, J[ohn] and other partial insertions, though). –  moewe Apr 2 at 8:24
    
You should have a sortyear field for entries with a guessed year anyway; as it stands now they are sorted before all the other works by the same author. But printing the sortyear might have adverse effect - after all the sortyear might contains something like 1970-1 or worse things that one would not want to see in the document itself, the same goes for sortname. We could of course define a new field bareyear that gets the year without brackets and the like (it could even be populated via Biber's sourcemapping). –  moewe Apr 2 at 8:32

3 Answers 3

The following shows how to implement a bareyear field that contains just the year with no additional brackets and can be used in \citeyear as well as a bareauthor field.

First, we have to make biblatex aware of our new fields via a datamodel file (save the following as barefields.dbx and locate it somewhere it can be found by LaTeX)

\ProvidesFile{barefields.dbx}[2014/04/02 allow for bracket-less fields]
\RequireBiber[3]

\DeclareDatamodelFields[type=field,datatype=literal]{bareyear}
\DeclareDatamodelEntryfields{bareyear}
\DeclareDatamodelFields[type=list,datatype=name]{bareauthor}
\DeclareDatamodelEntryfields{bareauthor}
\endinput

We simply define a literal field bareyear that is valid for all entry types, as well as a name list bareauthor.

We populate the fields via

\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map{
      \step[fieldsource=year,
            match=\regexp{\A\[(.+)\]\z},
            final]
      \step[fieldset=bareyear, fieldvalue={$1}]
      \step[fieldset=sortyear, fieldvalue={$1}]
    }
    \map[overwrite]{
      \step[fieldsource=author, match=\regexp{\[(.+)\]}, final]
      \step[fieldset=bareauthor, origfieldval]
      \step[fieldsource=bareauthor, match=\regexp{\[(.+)\]}, replace=\regexp{$1}]
    }
  }
}

just in the same manner as described by PLK in Ordering references with bracketed years in biblatex 2.7. (The second part might be more buggy and break in some situations, the year thing should work fine though.)

What remains is to make \citeyear use bareyear and \citeauthorfullname use bareauthor if available

\DeclareCiteCommand{\citeyear}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\iffieldundef{bareyear}
    {\printfield{year}}
    {\printfield{bareyear}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citeauthorfullname}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \DeclareNameAlias{labelname}{first-last}%
   \usebibmacro{prenote}}
  {\ifnameundef{bareauthor}
    {\printnames{labelname}}
    {\printnames{bareauthor}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

You will notice that this will always print the author even if the labelname is actually set to the editor, but I think you will have to live with that. (I could not access labelname in the sourcemapping process because [presumably] at that point biblatex is not yet sure which name field to take as the labelname. Just an idea: You could create bareauthor and bareeditor fields and list them before the author and editor fields in the \DeclareLabelname command, thus biblatex would prefer the bare... versions to the "normal" names - then there would be no need to modify the cite commands.)

MWE

\documentclass{article}
\usepackage[style = authoryear,datamodel=barefields]{biblatex}
\DeclareSourcemap{
  \maps[datatype=bibtex]{
    \map{
      \step[fieldsource=year,
            match=\regexp{\A\[(.+)\]\z},
            final]
      \step[fieldset=bareyear, fieldvalue={$1}]
      \step[fieldset=sortyear, fieldvalue={$1}]
    }
    \map[overwrite]{
      \step[fieldsource=author, match=\regexp{\[(.+)\]}, final]
      \step[fieldset=bareauthor, origfieldval]
      \step[fieldsource=bareauthor, match=\regexp{\[(.+)\]}, replace=\regexp{$1}]
    }
  }
}
\DeclareCiteCommand{\citeauthorfullname}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \DeclareNameAlias{labelname}{first-last}%
   \usebibmacro{prenote}}
  {\ifnameundef{bareauthor}
    {\printnames{labelname}}
    {\printnames{bareauthor}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}
\DeclareCiteCommand{\citeyear}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\iffieldundef{bareyear}
    {\printfield{year}}
    {\printfield{bareyear}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@book{lennon1969,
  author  = {J[ohn] Lennon},
  title   = {Some work from 69 -- maybe Summer of},
  year    = {1969},
}
@book{lennon1970,
  author    = {J[ohn] Lennon},
  title     = {This book was released with my Imagine album},
  year      = {[1970]},
}
@book{lennon1971,
  author  = {J[ohn] Lennon},
  title   = {This is from 71},
  year    = {1971},
}
@book{lennon1972,
  author  = {John Lennon},
  title   = {This Really is by John Lennon},
  year    = {1972},
}
\end{filecontents*}
\begin{filecontents*}{barefields.dbx}
\ProvidesFile{barefields.dbx}[2014/04/02 allow for bracket-less fields]
\RequireBiber[3]

\DeclareDatamodelFields[type=field,datatype=literal]{bareyear}
\DeclareDatamodelEntryfields{bareyear}

\DeclareDatamodelFields[type=list,datatype=name]{bareauthor}
\DeclareDatamodelEntryfields{bareauthor}
\endinput
\end{filecontents*}

\addbibresource{\jobname.bib}
\nocite{*}
\begin{document}
As \citeauthorfullname{lennon1970} wrote in \citeyear{lennon1970} \ldots\ and in \citeyear{lennon1972}.
\printbibliography
\end{document}

enter image description here

share|improve this answer
    
In an attempt to simplify this, could I include that barefields.dbx file you suggested in the preamble with filecontents? –  Sverre Apr 2 at 18:36
1  
@Sverre You can include it with filecontents as I did in the MWE above. You however cannot use the datamodel commands in the preamble themselves (while it might work with version 2.8, this is not supported with the upcoming version 2.9). But if you plan on using this more often, placing barefields.dbx in an accessible location is the way to go. –  moewe Apr 2 at 18:41

This is only a partial answer but I wanted to elaborate on my comment.

To format the name, for example, you might try something like:

\documentclass{article}
\usepackage[style = authoryear]{biblatex}
\DeclareCiteCommand{\citeauthorfullname}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \DeclareNameAlias{labelname}{first-last}%
   \usebibmacro{prenote}}
  {\ifciteindex
     {\indexnames{labelname}}
     {}%
   \printnames{labelname}}
  {\multicitedelim}
  {\usebibmacro{postnote}}
\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@book{lennon1970,
    AUTHOR = {Lennon, John},
    TITLE = {This book was released with my Imagine album},
    YEAR = 1971}
\end{filecontents}
\addbibresource{\jobname.bib}
\makeatletter
\def\mybrack#1#2\@nil{#1[#2]}
\AtBeginBibliography{%
  \renewcommand*\mkbibnamefirst[1]{%
    \mybrack#1\@nil}}
\makeatother
\begin{document}
As \citeauthorfullname{lennon1970} wrote in \citeyear{lennon1970} \ldots
\printbibliography
\end{document}

Lennon, J[ohn] with standard bib entry

share|improve this answer
    
This won't do the trick, I'm afraid, because this will put brackets in all first names in the bibliography. But as pointed out in my question, brackets are for filling out information that's literally missing in the source. In this case, the book would be published under the name J. Lennon. Your suggested code will, however, also change the name to Lennon, J[ohn] when the source has the full name John Lennon. –  Sverre Apr 2 at 11:14

You can try to write a macro with the package xstring. I tried it for a while, but I couldn't get it work. Maybe someone else here is able to...

It's the function \strDel, with it you can remove a substring from your string:

\StrDel{Hello there J[ohn]}{[}[\result]%remove [ and save in \result
\StrDel{\result}{]}[\result]%remove ] and save in \result

The code above works, but sadly the following macro does not. It just prints out the content of \citeyear{#1}:

\newcommand{\citeyearp}[1]{%
\StrDel{\citeyear{#1}}{[}[\result]%
\StrDel{\result}{]}[\result]%
\result%
}
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.