[Tex/LaTex] Reversing the effect of a \newline with the next command

harvard-styleline-breakingmacrosspacing

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

Best Answer

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.

Related Question