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.

enter image description here


My solution works by hacking the bibliography style, similar to what @Katuyci proposed, but conforming more to your example.

  1. Make a copy of your style file. I use plain.bst here, but it works with any other style, too.
  2. Insert usera to the ENTRY field:

    ENTRY {
      ...
      year
      usera      %% added
    }
    
  3. Add the following functions to your style file, after FUNCTION {not} (or after FUNCTION {or} if using natbib). Themultandstr.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$
    }
    
  4. Now locate FUNCTION {format.names}, and put

    INTEGERS { hlauthor hlauthorold }
    STRINGS { hlstr }
    

    before that.

  5. 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 with plain.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
    }
    
  6. 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}

sample output

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  
...  
}