2

I want to underline whole bibitem when using biblatex. I tried \AtEveryBibitem{\uline} but failed.

What I want to do:

underline

  • 5
    It is quite difficult to underline paragraphs, and if they contain complicated commands like the biblatex code or even url's even more. So better avoid it. If you really need it your best bets are probably tikz or lualatex. – Ulrike Fischer Jun 11 '18 at 12:21
9

This is going to be very hard with biblatex because \uline can not deal with complicated macros in its argument. But due to the way biblatex works we would inevitably end up feeding extremely complicated macros to \uline. Simple things like \uline{\printtext{foo}} seem to work fine, but \uline{\printfield{title}} already broke when the title was to be typeset in quotation marks. All hell broke lose and line breaking failed (because of grouping) even with \uline{\printnames{author}\setunit{\addspace}\printfield[emph]{title}}. The "real" argument to \uline would be much more complex.

So I guess this is one of these situations where BibTeX can do better. The way .bst files work means that \uline can operate almost directly on the raw text. If we additionally avoid grouping and other font formatting commands, we can get quite a pleasant result.

The general idea will be similar for most .bst files, but the actual implementation of course differs. Under https://gist.github.com/moewew/4a4beb11a35ed43541cc8f238f7deca8 you can find a modified version of plain.bst that underlines entire entries.

The major work was done by replacing the function output.bibitem with

FUNCTION {output.bibitem}
{ newline$
  "\bibitem{" write$
  cite$ write$
  "}" write$
  newline$
  "\uline{" write$
  ""
  before.all 'output.state :=
}

the new line was just "\uline{" write$.

The function fin.entry was changed to

FUNCTION {fin.entry}
{ add.period$
  write$
  "}" write$
  newline$
}

here, the "}" write$ is new.

In the linked file the emphasize function is turned into a no-op and all other references to \em have been removed as well. This avoids grouping and allows ulem to break lines properly.

Save the new file as plain-ul.bst and use it as follows

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[normalem]{ulem}

%\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@book{appleby,
  author  = {Humphrey Appleby},
  title   = {On the Importance of the Civil Service and a very very very very long subtitle that hopefully shows us a line break},
  year    = {1980},
  publisher = {BBC},
}
\end{filecontents}

\begin{document}
\cite{appleby}
\bibliographystyle{plain-ul}
\bibliography{\jobname}
\end{document}

enter image description here


If you want to continue using biblatex you might want to looking into alternative ways to produce underlining. I would guess that an approach with ulem is doomed to failure (at least if you don't rewrite the bibliography drivers with low-level commands).

As suggested by Ulrike in the comments, LuaLaTeX may be able to help you here. Paul Isambert's TUGboat article Three things you can do with LuaTeX that would be extremely painful otherwise implements an underline that is also usable for us here. With a few modifications the eight-year-old code still works and gives us

\documentclass[british]{article}
\usepackage{fontspec}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[style=authoryear, backend=biber]{biblatex}

\addbibresource{biblatex-examples.bib}

\newattribute{\ulattr}

\usepackage{luacode}
\begin{luacode}
local HLIST = node.id("hlist")
local RULE = node.id("rule")
local GLUE = node.id("glue")
local KERN = node.id("kern")
local ULATTR = luatexbase.attributes["ulattr"]

function get_lines(head)
  for line in node.traverse_id(HLIST, head) do
    underline(line.list, line.glue_order,
      line.glue_set, line.glue_sign)
  end
  luatexbase.remove_from_callback("post_linebreak_filter",
                                  "get_lines")
  return head
end

local function good_item(item)
  if item.id == GLUE and
    (item.subtype == node.subtype("leftskip")
     or item.subtype == node.subtype("rightskip")
     or item.subtype == node.subtype("parfillskip")) then
      return false
  else
    return true
  end
end

function underline(head, order, ratio, sign)
  local item = head
  while item do
    if node.has_attribute(item, ULATTR)
      and good_item(item) then
        local item_line = node.new(RULE)
        item_line.depth = tex.sp("1.4pt")
        item_line.height = tex.sp("-1pt")
        local end_node = item
        while end_node.next and
          good_item(end_node.next) and
          node.has_attribute(end_node.next, ULATTR) do
            end_node = end_node.next
        end
        item_line.width = node.dimensions
          (ratio, sign, order, item, end_node.next)
        local item_kern = node.new(KERN, 1)
        item_kern.kern = -item_line.width
        node.insert_after(head, end_node,        
                          item_kern)
        node.insert_after(head, item_kern,
                          item_line)
        item = end_node.next
    else
      item = item.next
    end
  end
end
\end{luacode}

\newcommand{\luaunderline}[1]{%
  \quitvmode
  \setattribute{\ulattr}{1}%
  #1%
  \unsetattribute{\ulattr}%
  \directlua{%
    luatexbase.add_to_callback("post_linebreak_filter",
                               get_lines, "get_lines")}%
}

\newcommand{\luaunderlineswitch}{%
  \quitvmode\setattribute{\ulattr}{1}%
  \directlua{%
    luatexbase.add_to_callback("post_linebreak_filter",
                               get_lines, "get_lines")}%
}

\renewbibmacro{begentry}{\begingroup\luaunderlineswitch}
\renewbibmacro{finentry}{\finentrypunct\endgroup}

\begin{document}
\luaunderline{Lorem} ipsum {\luaunderlineswitch dolor} sit amet.
\cite{sigfridsson,worman,nussbaum,geer}
\printbibliography
\end{document}

enter image description here

A big thank you to Ulrike Fischer for suggesting many improvements in the comments and helping me understand the code a bit better through these improvements.


Many people (especially on this site) consider underlining to be a relic of the type writer age and would suggest other ways to highlight text. Try bold or add a symbol to highlight an entry...

  • Thank you very much for your answer. I also think that the underline is outdated, and I will not use it if it is not the school's request. I don't have to use ulem, but it would be better to use biblatex. Is there any alternative ways to produce underlining in biblatex? – Genkun Abe Jun 11 '18 at 14:49
  • @GenkunAbe The question is how badly does your school want underlining? Can't you persuade them to accept an alternative (bold face)? The three standard solution for underlining are \underline (does not break across lines and so can't be used for long stretches of text, i.e. not usable here), ulem's \uline which can't deal with complex arguments and soul's \ul which is similarly bad at handling complex arguments (in fact ulem fared better than soul, but is still not usable). So these standard way's can't get you anywhere. ... – moewe Jun 11 '18 at 14:57
  • 2
    For luatex there is some code here tug.org/TUGboat/tb31-3/tb99isambert.pdf. But it is from 2010 and would need some adaption - some things have changed in the mean time. – Ulrike Fischer Jun 11 '18 at 15:10
  • 1
    But it would be better to replace the hardcoded attribute register number 100 by one allocated with \newattribute. – Ulrike Fischer Jun 11 '18 at 16:55
  • 1
    looks good. One could also replace the subtype numbers 8,9 and 15 by node.subtype("leftskip") , node.subtype("rightskip") and node.subtype("parfillskip") – Ulrike Fischer Jun 11 '18 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.