2

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

Sverre
  • 20,729
  • 1
    Turns out the album Imagine was released in 1971 ... Oops! – Sverre Apr 01 '14 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 01 '14 at 20:39
  • 1
    Do you really want '([YYYY])'? – cfr Apr 01 '14 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 02 '14 at 08: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 02 '14 at 08:32
  • @moewe The fix for correctly sorting years within brackets is addressed here: http://tex.stackexchange.com/questions/126511/ordering-references-with-bracketed-years-in-biblatex-2-7 – Sverre Apr 02 '14 at 11:11
  • Ahhh, I thought you had asked a question like that before, but I could not find it. What about the other ideas though? You could combine the answer there with a new bareyear field for example. – moewe Apr 02 '14 at 11:14
  • @moewe I didn't quite understand your suggestion on that point. But moreover, I'm usually at a loss what to do with suggestions, however good they might be, if they're not accompanied by a MWE. I'm a perpetual novice when it comes to LaTeX coding :) – Sverre Apr 02 '14 at 11:21
  • Mhh, the idea was to create a new field bareyear that takes the year without brackets (while you would add brackets to the year field if need be) that could be used for in-text \citeyear. (In fact, you would not even have to populate that field yourself, just use the fix you linked to above) I hesitate to answer (with a MWE) though because I realise that this fix is only applicable to a specific field (year for example), one would have to create a new bare... field of each field one needs this functionality for. – moewe Apr 02 '14 at 11:39
  • @moewe Wouldn't it be sufficient to let \citeyear refer to the field sortyear instead? As I understood the solution to the question I link to, everything in the field year is copied into sortyear anyway, with possible brackets removed. – Sverre Apr 02 '14 at 11:41
  • I thought about that as well (in my comment above), but the sortyear might contain more than just the year. In biblatex-examples.bib, for example, knuth:ct:a's sortyear is 1984-1. You would not want to have that printed. So you would have to restrict your (correct) usage of the sortyear field – moewe Apr 02 '14 at 11:45
  • @moewe I certainly don't have anything but actual years in my fields. So I would be happy to see a suggestion that does refer \citeyear to sortyear. It's at least better than what I have now ... – Sverre Apr 02 '14 at 11:50
  • OK, If you like, I can try to compose an answer, but it will only be able to deal with years (and very easy cases of other fields). It will not be applicable to all the fields where you might supplement information in brackets, or only with heavy work. – moewe Apr 02 '14 at 11:56
  • @moewe I do use brackets in various fields, but I can't think of any other fields than author and year (i.e. sortyear in our case) where it is relevant now, since only \citeauthor (or my workaround \citeauthorfullname) and \citeyear exist as cite commands. – Sverre Apr 02 '14 at 12:01
  • Well, I just had to find out that there is no way to print the sortyear information from within biblatex. So your best bet is a bareyear field. – moewe Apr 02 '14 at 12:07

3 Answers3

1

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

cfr
  • 198,882
  • 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 02 '14 at 11:14
1

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

moewe
  • 175,683
  • In an attempt to simplify this, could I include that barefields.dbx file you suggested in the preamble with filecontents? – Sverre Apr 02 '14 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 02 '14 at 18:41
0

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%
}
musicman
  • 3,559