I want to underline whole bibitem when using biblatex. I tried \AtEveryBibitem{\uline} but failed.
What I want to do:
I want to underline whole bibitem when using biblatex. I tried \AtEveryBibitem{\uline} but failed.
What I want to do:
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}
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.
Update
Things are much easier now with Marcel Krüger's lua-ul package.
\documentclass[british]{article}
\usepackage{fontspec}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[style=authoryear, backend=biber]{biblatex}
\usepackage{lua-ul}
\makeatletter
% internal name from lua-ul
\AtEveryBibitem{\@underLine}
\makeatother
\addbibresource{biblatex-examples.bib}
\begin{document}
\underLine{Lorem} ipsum \underLine{dolor} sit amet.
\cite{sigfridsson,worman,nussbaum,geer}
\printbibliography
\end{document}
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}
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...
\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
ltluatex.dtx and http://www.luatex.org/svn/trunk/manual/luatex.pdf open, but I still had to piece things together from several other sources as well.
– moewe
Jun 11 '18 at 19:12
node.subtype("leftskip") , node.subtype("rightskip") and node.subtype("parfillskip")
– Ulrike Fischer
Jun 11 '18 at 19:32