How to emphasize some author names using BibTeX?
Here is an application of the l3regex
package, combined with a previous idea
\begin{filecontents*}{\jobname.bib}
@article{a,
author={Studenta A. and Foo B.},
title={Title},
journal={Journal},
year={2012},
}
@article{b,
author={Studentb A. and Studentc B.},
title={Title},
journal={Journal},
year={2012},
}
@article{c,
author={Foo B. and Baz B.},
title={Title},
journal={Journal},
year={2012},
}
\end{filecontents*}
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\regex_new:N \g_hl_students_regex
\seq_new:N \l_hl_students_seq
\tl_new:N \l_hl_data_tl
\NewDocumentCommand{\studentslist}{m}
{
\seq_set_split:Nnn \l_hl_students_seq { , } { #1 }
\regex_gset:Nx \g_hl_students_regex
{ ( \seq_use:Nnnn \l_hl_students_seq { | } { | } { | } ) }
}
\cs_generate_variant:Nn \regex_gset:Nn { Nx }
\cs_set_eq:NN \hl_bibitem:w \bibitem
\cs_set:Npn \bibitem #1#2\par
{
\hl_bibitem:w { #1 }
\tl_set:Nn \l_hl_data_tl { #2 }
\regex_replace_all:NnN \g_hl_students_regex { \c{emph}\cB\{ \1 \cE\} } \l_hl_data_tl
\tl_use:N \l_hl_data_tl \par
}
\ExplSyntaxOff
\studentslist{Studenta, Studentb, Studentc}
\begin{document}
abc
\nocite{*}
\bibliographystyle{plain}
\bibliography{\jobname}
\end{document}
As usual, filecontents*
is used only for making the example self consistent, one can use any .bib
file.
The comma separated list of students names is given in the preamble.
My solution works by hacking the bibliography style, similar to what @Katuyci proposed, but conforming more to your example.
- Make a copy of your style file. I use
plain.bst
here, but it works with any other style, too. Insert
usera
to theENTRY
field:ENTRY { ... year usera %% added }
Add the following functions to your style file, after
FUNCTION {not}
(or afterFUNCTION {or} if using natbib). The
multand
str.to.int` functions are taken from Tame the Beast, with a small bug fix.INTEGERS {length i a b} STRINGS {chr} FUNCTION {mult} {'a := %% we store the first value 'b := %% we store the second value b #0 < %% We remember the sign of b, and {#-1 #0 b - 'b :=} %% then consider its absolute value. {#1} %% if$ %% #0 %% Put 0 on the stack. {b #0 >} %% While b is strictly positive, { %% we add a to the value on the stack a + %% and decrement b. b #1 - 'b := %% } %% while$ %% swap$ %% Last, we take the opposite 'skip$ %% if b was negative. {#0 swap$ -} %% if$ %% } FUNCTION {chr.to.value} %% The ASCII code of a character { chr.to.int$ #48 - %% ASCII value of "0" -> 48 duplicate$ duplicate$ %% "1" -> 49 #0 < swap$ #9 > or %% ... { %% "9" -> 57 #48 + int.to.chr$ " is not a number..." * warning$ %% Return 0 if it is not a number #0 %% here we removed the pop$ before #0, %% opposed to what is written in Tame The Beast } {} if$ } FUNCTION {str.to.int.aux} %% The auxiliary function { {duplicate$ empty$ not} %% While the string is not empty { %% consider its first char swap$ #10 mult 'a := %% and ‘‘add’’ it at the end of duplicate$ #1 #1 substring$ %% the result. chr.to.value a + swap$ #2 global.max$ substring$ } while$ pop$ } FUNCTION {str.to.int} { %% Handling negative values duplicate$ #1 #1 substring$ "-" = {#1 swap$ #2 global.max$ substring$} %% the first integer here indicates whether we have to %% multiply by -1, i.e., it is consumed by the following if$ {#0 swap$} if$ %% Initialization, and then #0 swap$ str.to.int.aux %% call to the aux. funtion swap$ {#0 swap$ -} %% And handle the sign. {} if$ } %% takes a string literal from the stack and returns %% the position of the first " " (space) in the string; %% returns -1 if no space is contained FUNCTION {first.space}{ duplicate$ text.length$ #1 + 'length := #1 'i := { i length < { duplicate$ i #1 substring$ 'chr := chr " " = { #0 } { #1 } if$ } { #-1 } if$ } { #1 i + 'i := } while$ i length = { #-1 'i := } {} if$ %% finally take the string from the stack pop$ %% space position we identified i } %% takes a string literal from the stack, %% and returns the first number in the string, and the remaining string; %% returns -1 and the original string if no number is found STRINGS { tmpstr } FUNCTION {chop.number} { 'tmpstr := tmpstr first.space 'i := i #0 > { tmpstr i #1 + global.max$ substring$ %% remaining string tmpstr #1 i #1 - substring$ str.to.int %% number duplicate$ #0 = { pop$ #-1 } {} if$ } { "" tmpstr str.to.int duplicate$ #0 = { pop$ #-1 } {} if$ } if$ }
Now locate
FUNCTION {format.names}
, and putINTEGERS { hlauthor hlauthorold } STRINGS { hlstr }
before that.
format.names
has to be modified. I indicated all lines that I added. Your function might look a little different when you are not working withplain.bst
, but pretty similar.FUNCTION {format.names} { 's := #1 'nameptr := s num.names$ 'numnames := numnames 'namesleft := usera 'hlstr := %% added hlstr chop.number 'hlauthor := 'hlstr := %% added { namesleft #0 > } { s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ 't := nameptr hlauthor = %% added { %% added "\hlauthor{" t * "}" * 't := %% added hlauthor 'hlauthorold := %% added hlstr chop.number 'hlauthor := 'hlstr := %% added hlauthor #0 > %% added { hlauthor hlauthorold > %% added {} %% added { "Highlighted authors not sorted for " %% added cite$ * ": " * hlauthorold int.to.str$ * %% added " >= " * hlauthor int.to.str$ * warning$ %% added } %% added if$ %% added } %% added {} %% added if$ %% added } %% added {} %% added if$ %% added nameptr #1 > { namesleft #1 > { ", " * t * } { numnames #2 > { "," * } 'skip$ if$ t "others" = { " et~al." * } { " and " * t * } if$ } if$ } 't if$ nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$ %% Sanity checks: hlstr should be empty, %% added %% and hlauthor should be -1 %% added hlstr "" = %% added {} %% added { "There are remaining authors to be highlighted for " %% added cite$ * ": " * hlstr * warning$ %% added } %% added if$ %% added hlauthor #-1 = %% added {} %% added { "Unable to highlight author number " hlauthor %% added int.to.str$ * " for " * cite$ * warning$ %% added } %% added if$ %% added }
Finally, we provide a default style for highlighting authors, here we use bold. This is to be injected into the
begin.bib
function:FUNCTION {begin.bib} { preamble$ empty$ 'skip$ { preamble$ write$ newline$ } if$ "\begin{thebibliography}{" longest.label * "}" * write$ newline$ "\providecommand*{\hlauthor}[1]{\textbf{#1}}" write$ newline$ %% added }
That's it! Let's test it:
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{hltest.bib}
@book{a,
author = {A. First and B. Second and C. Third and D. Forth and E. Fifth and F. Sixth and G. Seventh},
usera = {1 3 5 4},
title = {My book title},
year = 2013,
publisher = {Inhouse}
}
@book{b,
author = {A. One and B. Two and C. Three},
usera = {1 4},
title = {My book title},
year = 2013,
publisher = {Inhouse}
}
@book{c,
author = {A. Uno and B. Due and C. Tre},
usera = {4 5},
title = {My book title},
year = 2013,
publisher = {Inhouse}
}
@book{d,
author = {A. Eins and B. Zwei and C. Drei},
usera = { 2},
title = {My book title},
year = 2013,
publisher = {Inhouse}
}
\end{filecontents}
\begin{document}
\nocite{*}
% \providecommand{\hlauthor}[1]{\emph{#1}} % if you want to change the style of emphasis
\bibliographystyle{hlplain}
\bibliography{hltest}
\end{document}
Note that authors to be emphasized should be given in increasing order, e.g.
usera = {10 13 15}, OK
usera = {9 1 2}, NOT OK
separated by spaces. Otherwise you will get warnings as in the test code.
Perphaps you can try the idea of a previous post. I will suggest some adjustments to your method and how to do it.
Instead of using numbers in the usera = { ...} field perhaps you can use the author's name you want to highlight. I believe it would be as easy as inserting the rank. Be sure that if you use full names or short names for the first name you do the same in usera
Declare usera in ENTRY {... usera ...}
and create a new function before FUNCTION{format.names}
as follows:
FUNCTION {student.author}
{
usera empty$
{ "" }
{ usera nameptr STYLE format.name$ }
if$
}
NOTE change the above style to whatever style your current .bst file uses. You can find, and copy it, in FUNCTION{format.names}
. Should be something similar to "{ff~}{vv~}{ll}{, jj}"
.
Create the function to highlight:
FUNCTION {highlight}
{ duplicate$ empty$
{ pop$ "" }
{ "\emph{" swap$ * "}" * }
if$
}
and call this function whenever the author being parsed is your student author:
FUNCTION {highlight.if.student.author}
{ duplicate$ purify$ student.author purify$ =
{ highlight }
'skip$
if$
}
Finally, call the highlight.if.student.author
after format.name$
in FUNCTION{format.names)
as follows:
FUNCTION{format.names}
{...
format.names$ highlight.if.student.author
...
}