I need to use non-breaking spaces in proper name initials, e.g.
J.~W.~Bush
Any way to make LaTeX replace regular spaces with non-breaking ones for such cases? Or would I better preprocess my tex files with some regexp/script?
I added support for initials to my package luavlna. This package uses luatex
node processing callbacks for language dependent insertion of non-breaking spaces after one letter words and initials.
Example:
\documentclass{article}
\usepackage{fontspec}
\usepackage[czech, english]{babel}
\usepackage{luavlna}
\preventsinglelang{czech}
\begin{document}
\preventsingledebugon
D. E. Knuth, Ch. Somebody. \selectlanguage{czech} A. Dvořák,
name in horizontal box \hbox{Č. Zíbrt}, Ř. Jelen \preventsingleoff C. Někdo,
\preventsingleon Ř. Jelen, Ch. Josef, CH. Thisworkstoo
\end{document}
You can see that Ch
is used as one letter in Czech. If you don't want language sensitive processing, set default language with \preventsinglelang{languagename}
and rules for given language will be used in the whole document.
You can turn off the processing with \preventsingleoff
and resume it latter with \preventsingleon
luavlna
isn't on CTAN yet, I have to make language detection more robust, so you can download it from github and install in to your local TEXMFHOME
dir if you want to use it.
\mbox{one two}
when dealing with hyphenation?
\preventsinglelang
for using only one language settings for whole document, if one wants this behaviour
Apr 9, 2014 at 11:13
EDITED to catch more cases (and examine failure modes)
I concur with David's recommendation not to make the space active. So the approach I take here is to make the dot active, with the ability to turn the feature on (\initialsON
) and off (\initialsOFF
) as needed, if it is found to interfere with something else.
The choice of an active dot will bring with it a severe limitation, we will find, in that an active dot occurs after the initialed letter, and so it becomes impossible to definitively know if an initial preceded the active dot. But we can nonetheless make interesting progress towards that goal.
With my original solution (the path that follows \specdothelper
), the detection scheme was only triggered on initials typed without spaces, such as J.W.Bush
, such that it converted a sequence .X
into .~X
if there was no space between the .
and the X
, where X
represents any capital letter. This compressed syntax may take a little getting used to or even be outright unacceptable to many users.
With this latest REVISION (and my first successful use of \futurelet
, yippee), I now also can search for the syntax . X.
, where there is a space after the first dot, then a capital letter followed by a dot. If this sequence is found, it is converted into .~X.
And if and only if initials have been lately found, the sequence . Xx
will assume the last name has been located and convert it to .~Xx
. Thus, in a sequence like J. Z. A. Bush
, it will catch all three spaces, converting them into hard spaces.
By using the dot as the active character, however, I am prevented from knowing whether the character prior to the dot was an initial, and can only try to discern it by looking forward in the input stream. In the example given by G. Washington
, the problem with the first dot is that, without a pattern of initials already being established, the forward-looking . Wa
set of characters could be the beginning of a sentence rather than a name following the initial. And so this important case is missed.
In this EDIT, I've reduced the discussion hereafter on the guts of the logic. I'll only summarize and say that the challenge areas were spaces, \par
s, and repeated dots ..
(since dots are active characters), which required special treatment. Also, the new logic with this revision follows the \foundspace
macro.
Places where the compressed (no-space) syntax will fail are shown in my MWE. If a last name does not begin with a capital is one case, such as C.deLune. Also, if a url has a dot followed by a capital letter, this would cause a space to be inserted (though \initialsOFF
should be used before setting such unconventional text as url's).
When employing the revised syntax where spaces remain between the initials in your LaTeX file, there are three known failure modes (one of them crucial). The first, discussed above at some length, is the case of a single initial followed by a last name. The second failure is when a sentence starts with an initial (though this is bad grammar). The third case of failure is when a sentence ends in what looks like initials, such as U. S. A.
In this case, the first word of the next sentence is perceived as the last name, and a hard space is inserted.
When using the compressed syntax, the requirement to enter initials without spaces in your document may be wholly unacceptable to many users. And in the normal expanded syntax, the inabilty to detect a lone initial in a sequence greatly limits the usefulness of this approach.
In the MWE that follows, I have purposely defined my hard space \HS
as a \rule
to make it visible. To use this code in its intended way, that definition should be replaced with the one that defines it as a hard space (or a skinny space).
\documentclass{article}
\usepackage{ifnextok}
\def\HS{\rule{.66ex}{1ex}}% TO DEMONSTRATE WHERE ACTIVE
%\def\HS{\,}% FOR NARROW SPACE
%\def\HS{~}% FOR NORMAL HARD SPACE
\let\svdot.
\def\knowninit{F}
\makeatletter
\def\specdot{\svdot\IfNextToken\@sptoken{\foundspace}%
{\gdef\knowninit{F}\specdothelper}}
\long\def\foundspace#1{\IfNextToken\@sptoken{ #1\gdef\knowninit{F}}%
{\def\savefirst{#1}\lookatsecond}}
\def\lookatsecond{\futurelet\secondchar\processsecond}
\long\def\specdothelper#1{%
\if\svdot#1%
\svdot%
\else%
\ifx#1\par%
\par%
\else%
\ifnum`#1>`@\ifnum`#1<`[\HS\fi\fi#1%
\fi%
\fi%
}
\makeatother
\catcode`.=\active
\def\processsecond{%
\ifx\secondchar.%
\HS\gdef\knowninit{T}%
\else%
\if T\knowninit%
\ifnum\expandafter`\savefirst>`@\ifnum\expandafter`\savefirst<`[\HS\else%
{ }\fi\else{ }\fi%
\else%
{ }%
\fi%
\gdef\knowninit{F}%
\fi%
\savefirst%
}
\def\initialsON{\catcode`.=\active\def.{\specdot}}
\def\initialsOFF{\catcode`.=12\let.\svdot}
\catcode`.=12
\parskip 1ex
\begin{document}
\footnotesize
\noindent ON\initialsON
Fully spaced initials J. Z. A. Bush being tested, and here we check double and single initials:
J. Q. Adams and G. Washington. A single initial cannot be discerned because the dot after
the G cannot know if the prior letter is an initial and no other initials follow the dot.
U. S. A. is OK, since ``is'' is not capitalized.
We can be fooled by U. S. Olympic Team, in that it considers ``Olympic'' to be the last name.
Can also be fooled if sentence ends in the U. S. A. The new sentence starts with a hard-space,
with ``The'' as the last name. Leaving out the spaces will fix U.S.A. If no spaces are wanted,
\initialsOFF U.S.A. \initialsON
can be gotten by temporarily turning initials OFF.
Compressed or uncompressed C.deLune and C. de Lune fail to insert a hard space, because
``d'' is not a capital letter.
Unspaced combinations: 3.2, a.b, J.Z.A.Bush, and G.Washington being successfully tested
here, with non-capital letters screened out.
Testing.. successive... dots is OK... Unless the sentence ends with odd number of dots, then
a space immediately followed by a dotted initial... S. Segletes would never start a sentence
with an initial. It is poor grammar in the first place.
\noindent\hrulefill\\
OFF\initialsOFF (This was the raw text being processed)
Fully spaced initials J. Z. A. Bush being tested, and here we check double and single initials:
J. Q. Adams and G. Washington. A single initial cannot be discerned because the dot after
the G cannot know if the prior letter is an initial and no other initials follow the dot.
U. S. A. is OK, since ``is'' is not capitalized.
We can be fooled by U. S. Olympic Team, in that it considers ``Olympic'' to be the last name.
Can also be fooled if sentence ends in the U. S. A. The new sentence starts with a hard-space,
with ``The'' as the last name. Leaving out the spaces will fix U.S.A. If no spaces are wanted,
U.S.A.
can be gotten by temporarily turning initials OFF.
Compressed or uncompressed C.deLune and C. de Lune fail to insert a hard space, because
``d'' is not a capital letter.
Unspaced combinations: 3.2, a.b, J.Z.A.Bush, and G.Washington being successfully tested
here, with non-capital letters screened out.
Testing.. successive... dots is OK... Unless the sentence ends with odd number of dots, then
a space immediately followed by a dotted initial... S. Segletes would never start a sentence
with an initial. It is poor grammar in the first place.
\end{document}
as seen in the U. S. The next sentence
or sentence is done. S. Segletes starts the next sentence
or C. deLune
or U. S. Olympic Team
?
Apr 10, 2014 at 0:51
V. van Gogh
, L. van Beethoven
, J. von Mises
, Ch. A. J. M. de Gaulle
, L. da Vinci
. I believe that processing TeX/Bib file externally (as program vlna
does) is the best way. We would not touch the original file (then we could process HTML/JS or other files by changing one letter ~
->
) and there would be a chance to make a backup.
bibtex
orbiblatex
?