Detect beginning of a sentence in a macro for capitalization

Is it possible to make macros give different results at the beginning of a new sentence? Suppose that I want the macro "\secname" to write "Section" at the beginning of a new sentence, and "section" anywhere else. How can I do so?

-
If you would like to say "\secname~2 is about blah." and also "In \secname~2 we talk about blah", then "Section" should be capitalized in both cases. At least according to Strunk & White. – Matthew Leingang Nov 2 '10 at 15:37
@Matthew: This is a common in styles, but not universal. E.g., the CUP style guide expresses a preference for not capitalising these (see Butcher's Copy-editing, 2006, p.129). – Charles Stewart Nov 10 '10 at 9:05
The capitalisation difference is a red herring: there are other ways in which the output could be different. For example several journals require "Section" at the start of a sentence but "Sec." otherwise (both capitalised). – andybuckley May 6 '14 at 15:09

You could set the \sfcode of the "end of sentence" chars to something different and test for it:

 \documentclass[10pt]{report}
\sfcode\.=1001
\sfcode\?=1001
\sfcode\!=1001
\sfcode\:=1001
\newcommand\secname{\ifnum\spacefactor=1001 Secname\else secname\fi}
\begin{document}
abc. \secname\ is \secname.

e.g.\@ \secname
\end{document}


\nonfrenchspacing is also setting the \sfcodes. In this case you could use something like this:

 \documentclass[10pt]{report}
\nonfrenchspacing
\newcommand\secname{\ifnum\spacefactor>1900 Secname\else secname\fi}
\begin{document}
abc. \secname\ is \secname.
abc: \secname, \secname.
e.g.\@ \secname
\end{document}

-
Wow, using \sfcode is a cool idea. The only drawback is that you have to use \@  instead of \  if you want to say that no sentence is ended here. (I don't fully understand what's happening here.) By the way, I slightly modified your code so that \secname does not automatically print a space; hope that's OK. – Hendrik Vogt Nov 3 '10 at 14:11
Using the spacefactor is a good attempt. However, it will still not do proper sentence disambiguation. For example try \newcommand\secname{\ifnum\spacefactor=1001 (See Section) \else (see Section)\fi} Corporation ABC \secname issued a paper written by John et.al. \secname which was well received by the press. \secname'. Since TeX allocates an sfcode for capitals of 999 it will work well, with most abbreviations (except lower case or mixed cased abbreviations, such as Pty. Ltd. etc. ). – Yiannis Lazarides Nov 3 '10 at 14:27
\@ simply sets \spacefactor=1000, so it overwrites the \spacefactor set by the period. – Ulrike Fischer Nov 3 '10 at 14:29
@Ulrike: Thanks for adding this. (I had already looked that up, but probably not everybody else knows.) – Hendrik Vogt Nov 3 '10 at 15:23
Inserting \secname\ is \secname right after \begin{document} produces errors. – kiss my armpit Sep 13 '13 at 3:39

Easiest way is to define two macros:

\def\secname{section}
\def\Secname{Section}


It is a very difficult task to determine sentence boundaries and one of the hottest topics in Computational Linguistics. To do so properly you need to determine that in Dr. Who, for example, the period after the "Dr." does not end a sentence, so you need to parse for all abbreviations and when you think you test for the next letter to start with a capital letter, think of e.g. and all the Latin abbreviations we use.

-
LaTeX has a simple end-of-sentence detection: period, space (but not '\ ') and a capital letter. When this sequence appears, the spacing between the period and the next word is wider then usual. I'll settle for matching that. Btw, the proper LaTeXing is "Dr.\ Who", to avoid that behavior exactly. – Little Bobby Tables Nov 3 '10 at 8:54
+1 for the example! And also for the answer since it makes for cleaner source code. Compare And so to bed. \day~34; got up and had breakfast. with And so to bed. \Day~34; got up and had breakfast.. In the second, all the visual clues are correct in the source for delimiting the sentences. – Loop Space Nov 3 '10 at 12:30
@Little Bobby Tables: I would use "Dr.~Who" instead of "Dr.\ Who". IMO it's easier to read and type. The former will also not break a line between "Dr." and "Who". – Matthew Leingang Nov 3 '10 at 14:08
@Little: It's a bit more complicated than that. TeX doesn't do any end of sentence detection. The spacing is completely dependent on the space factor which is set by the \sfcode of a particular character (as well as a few others ways). I explained this elsewhere. – TH. Nov 3 '10 at 20:02
I don't think special cases really matters for capitalizing cross references. What would Dr. \secname mean? – gigabytes Jun 15 '15 at 12:35

Before Ulrike posted her nice answer that uses \spacefactor, I had thought this would be impossible in TeX without redefining .. Just for completeness: Here's my answer that does redefine . (after making it active, which probably is not such a good idea). Note that you do not have to use \@ as in Ulrike's solution.

\documentclass{article}
\let\period.
\catcode.=\active
\let\qwe\relax
\futurelet\myspace{ }
\newcommand.{\period\futurelet\nextchar\testspace}
\newcommand\testspace{\ifx\nextchar\myspace\expandafter\eatspace\expandafter.\fi}
\def\eatspace. { \futurelet\nextchar\testsec}
\newcommand\testsec{\ifx\nextchar\secname\def\qwe{ }\fi}
\newcommand\secname{\ifx\qwe\relax section\else Section\let\qwe\relax\fi}
\begin{document}
abc. \secname\ is \secname.
abc: \secname, e.g.\ \secname.
\end{document}


Yes, This looks as if I had I tried to make it as obscure as possible. Two interesting points: 1. Note the definition of \myspace (\space does not work!). 2. I didn't manage to use LaTeX's \ifnextchar to test if the next character is a space, so I used \futurelet.

-
I would certainly not redefine the period. Units will explode. Try e.g. \fontsize{1.2cm}{2cm}\selectfont abc. Regarding \@: \<space> is a primitive command, and I don't think that it would be a good idea to redefine it. But you could redefine \<tab>: \def\^^I{\spacefactor=1000\ }, then e.g.\<tab>\secname would work too. But one must be careful that the editor doesn't convert the tabs to spaces when saving the file. – Ulrike Fischer Nov 3 '10 at 16:21
@Ulrike: I could say: No problem, use "," instead of "." ;-) But seriously, that's very interesting; I didn't know that dimensions need an explicit period or comma for the decimals. (Anyway my answer shouldn't be taken too seriously). – Hendrik Vogt Nov 3 '10 at 17:17
Try this \begin{document} \secname\ is \secname. \end{document}. You will see it no longer works as expected. :-) – kiss my armpit Sep 13 '13 at 3:42

As an extension of the @YiannisLazarides answer, you can use mfirstuc which is included with TexLive 2014.

This will take care of the capitalisation for you, and you won't have to repeat yourself when defining the upper-case version of your command.

\documentclass{article}
\usepackage{mfirstuc}
\def\secname{fancy section}
\def\Secname{\expandafter\makefirstuc\expandafter{\secname}}

\begin{document}
Here's a new \secname{}. \Secname{} titles are good.
\end{document}


Which results in:

-