8

I'm using the harvard package and the agsm bibliography style. I'm aware that there are alternatives, e.g., natbib plus har2nat, and I will be looking into those in the not-too-distant future, but at the present I'm just trying to tidy up a bibliography that I've already got.

When the entry in the bibtex file contains a URL field, it's included in the bibliography entry in the document using \newline\harvardurl{...}, e.g.:

\harvarditem[Baader et~al.]{Baader, Calvanese, McGuinness, Nardi \harvardand\
  Patel-Schneider}{2003}{DLH:2003}
Baader, F., Calvanese, D., McGuinness, D.~L., Nardi, D. \harvardand\
  Patel-Schneider, P.~F., eds  \harvardyearleft 2003\harvardyearright , {\em
  The Description Logic Handbook: Theory, Implementation and Applications},
  Cambridge University Press, New York, NY, USA.
\newline\harvardurl{http://dx.doi.org/10.2277/0521781760}

Now, I've often redefined the \harvardurl command in order to format the URL differently. Now I want to remove all the URLs from the bibliography entirely. I can remove all lines matching \newline\harvardurl{...} from the .bbl file, but I'd have to do that after every bibtex run. The \newline is actually getting inserted by agsm.bst:

FUNCTION {write.url}                                                                                                                   
{ URL empty$                                                                                                                           
    { skip$ }                                                                                                                          
    { "\newline\harvardurl{" URL * "}" * write$ newline$ }                                                                             
  if$                                                                                                                                  
}

It looks like the only way I could avoid the \newline is by making URL somehow be empty. So, as the quick workaround, is there something I can do with the definition of \harvardurl to remove the effect of \newline?

As a minimal example that doesn't require the harvard package, here's a list with two entries and a \newline\harvardurl{...} in each one:

\documentclass{article}

% Don't display the URL text.  How 
% can we also counteract the previous
% \newline?
\newcommand{\harvardurl}[1]{}

\begin{document}

\begin{list}{}{}
\item Baader, F., Calvanese, D., McGuinness, D.~L., Nardi, D. \&
Patel-Schneider, P.~F., eds (2003) , {\em The Description Logic
  Handbook: Theory, Implementation and Applications}, Cambridge
University Press, New York, NY, USA.
\newline\harvardurl{http://dx.doi.org/10.2277/0521781760}

\item Baader, F., Calvanese, D., McGuinness, D.~L., Nardi, D. \&
Patel-Schneider, P.~F., eds (2003) , {\em The Description Logic
  Handbook: Theory, Implementation and Applications}, Cambridge
University Press, New York, NY, USA.
\newline\harvardurl{http://dx.doi.org/10.2277/0521781760}
\end{list}

\end{document}

bibliography with too much space

One quick approach that produces initially acceptable results is to define as \\[-2\baselineskip], but this feels pretty hacky:

\newcommand{\harvardurl}[1]{\\[-2\baselineskip]}

It looks OK, at least intially; I'm not confident that this doesn't have some edge case where things break.

better using a negative baselineskip

6
  • You might try doing \renewcommand\harvardurl[1]{\unpenalty\unskip\unpenalty}
    – egreg
    Jan 25 '14 at 22:12
  • Of course @egreg's answer is great but just for completeness, you may also want to consider editing the .bst file (so the newline never gets inserted). You only need to do this once and you can even just put the modified version in your working dir so it replaces the globally installed one only for that project. Another workaround is using a different field for the url e.g. note
    – Bordaigorl
    Nov 15 '14 at 16:23
  • @Bordaigorl Those are certainly alternatives (and I quoted the bst in the question), though I don't really like having to maintain custom versions of other people's code. But the bounty isn't for the solution; it's for the explanation of the process of getting it. (La)TeX, to many (myself included) often feels like a very-hard-to-debug language, and the answer that explains that process (using \show, \xshowcmd, etc.) is very useful. Cf. "give a man a fish … teach a man to fish …." Nov 15 '14 at 16:30
  • Sure! just mentioning alternatives to undoing the spacing after the fact =) egreg's answer is stellar as always, can't beat that!
    – Bordaigorl
    Nov 15 '14 at 22:54
  • there's also an unnecessary space after the year. you might want to look at that too. Nov 17 '14 at 13:35
11
+50

The final effect of \newline, when used in horizontal mode (which is the case here) is to issue

\nobreak\hfil\break

Since \nobreak and \break are \penalty10000 and \penalty-10000 respectively, you should be able to remove the three items by

\renewcommand{\harvardurl}[1]{\unpenalty\unskip\unpenalty}

At least this works in the example you gave.


How can you find what's the effect of \newline? There are a few ways. Here's what I did. I run LaTeX from the terminal on this unfinished file

\documentclass{article}
\usepackage{xpatch}
\begin{document}
\makeatletter
\show\newline

This opens an interactive session; the first answer is

> \newline=macro:
->\protect \newline  .
l.5 \show\newline

I hit return and at the prompt typed

\xshowcmd\newline

because the answer made it clear that \newline is a robust command; the answer was

> \newline =\long macro:
->\@normalcr \relax .
<recently read> \newline  

Then again return and \show\@normalcr, getting

> \@normalcr=\long macro:
->\let \reserved@e \relax \let \reserved@f \relax \@ifstar {\let \reserved@e 
\vadjust \let \reserved@f \nobreak \@xnewline }\@xnewline .
<*> \show\@normalcr

OK, \@normalcr looks for a *, which we don't have. In any case, the next command we want to look at is \@xnewline; so \show\@xnewline gives

> \@xnewline=macro:
->\@ifnextchar [\@newline {\@gnewline \relax }.
<*> \show\@xnewline

Good; we don't have a [, so I did \show\@gnewline:

> \@gnewline=macro:
#1->\ifvmode \@nolnerr \else \unskip \reserved@e {\reserved@f #1}\nobreak \hfil
 \break \fi .
<*> \show\@gnewline

This is a bit complicated, but we're not in vertical mode, so LaTeX executes

\unskip\reserved@e{\reserved@f\relax}\nobreak\hfil\break

Now we go back and look at how \reserved@e and \reserved@f had been defined by \@normalcr: nothing strange, they're \relax. So the effect is to remove a space \unskip (and this is good for our purposes) and insert

\nobreak\hfil\break

The commands \unpenalty and \unskip are TeX primitives, you find a description in the TeXbook or in TeX by Topic (texdoc texbytopic). Basically, \unpenalty removes the last item if it is a penalty, \unskip removes the last item if it is a skip. With the proposed redefinition of \harvardurl TeX is left with

\nobreak\hfil\break\unpenalty\unskip\unpenalty

Actually it has already executed the first three commands, appending a penalty item, a glue item and another penalty item to the current list; so the first \unpenalty removes the penalty due to \break, then the last item is the result from \hfil that's removed by \unskip and then the last item in the list is again a penalty: hurray, \unpenalty gets rid of it.

7
  • Thanks! This looks like the proper way of doing this, and it seems to work in my real document as well. I'm going to read more about \unpenalty and \unskip, but I wonder if you could, for the sake of increasing my latex-debugging-fu, give a word or two about how you determined that the final effect of \newline in this context is \nobreak\hfil\break? Jan 25 '14 at 22:27
  • I don't need the whole breakdown either; I'm just curious. An answer along the lines of "take a look at \debugcommand" would be fine. :) Jan 25 '14 at 22:30
  • @JoshuaTaylor Why not making the story complete? ;-)
    – egreg
    Jan 25 '14 at 22:46
  • so this happens in the dragon's den....
    – percusse
    Jan 25 '14 at 22:58
  • @percusse This was easy. ;-)
    – egreg
    Jan 25 '14 at 23:11

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.