[latex3-commits] [latex3/latex2e] develop: Re-work \MakeTitlecase implementation (#1547) (c849b8dcd)
github at latex-project.org
github at latex-project.org
Tue Nov 12 15:15:05 CET 2024
Repository : https://github.com/latex3/latex2e
On branch : develop
Link : https://github.com/latex3/latex2e/commit/c849b8dcd1274cca8d24e76bd9ddea4e609421e1
>---------------------------------------------------------------
commit c849b8dcd1274cca8d24e76bd9ddea4e609421e1
Author: Joseph Wright <joseph at texdev.net>
Date: Tue Nov 12 14:15:05 2024 +0000
Re-work \MakeTitlecase implementation (#1547)
* Re-work \MakeTitlecase implementation
Fixes latex3/latex3#1316
* Reword a sentence
* Correct a typo
* Extend titlecasing to first/all words
>---------------------------------------------------------------
c849b8dcd1274cca8d24e76bd9ddea4e609421e1
base/changes.txt | 7 +++
base/doc/ltnews41.tex | 24 +++++++++
base/doc/usrguide.tex | 14 ++++++
base/ltfinal.dtx | 25 +++++++---
base/testfiles/github-1545.lvt | 33 +++++++++++++
base/testfiles/github-1545.tlg | 110 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 207 insertions(+), 6 deletions(-)
diff --git a/base/changes.txt b/base/changes.txt
index e0258170d..75821971e 100644
--- a/base/changes.txt
+++ b/base/changes.txt
@@ -6,6 +6,13 @@ to completeness or accuracy and it contains some references to files that are
not part of the distribution.
================================================================================
+2024-11-12 Joseph Wright <Joseph.Wright at latex-project.org>
+ * ltfinal.dtx (subsection{Case changing}):
+ Use \text_titlecase_...:nn for titlecasing
+ Introduce option to titlecase first or all words
+ * usrguide.tex:
+ Document new key for titlecasing
+
2024-11-06 Joseph Wright <Joseph.Wright at latex-project.org>
* ltoutenc.dtx
Add support for \={i} to OT1 and T1
diff --git a/base/doc/ltnews41.tex b/base/doc/ltnews41.tex
index 0c9751704..eef1f26fe 100644
--- a/base/doc/ltnews41.tex
+++ b/base/doc/ltnews41.tex
@@ -149,6 +149,30 @@
\section{Code improvements}
+\subsection{Refinement of \cs{MakeTitlecase}}
+
+We introduced \cs{MakeTitlecase} as a late addition to the June
+2022 release, making use of the improved case code in
+\pkg{expl3}. Unlike upper and lowercasing, making text
+titlecased is more tricky to get right: this can apply either to
+the whole text or on a word-by-word basis.
+
+A subtle issue was reported against the \pkg{expl3} repository
+(\url{https://github.com/latex3/latex3/issues/1316}) which links
+to how we deal with the question of case changing
+\enquote{words} but shows up if you titlecase text stored in a
+command.
+
+We have looked again at how to implement \cs{MakeTitlecase} to
+be as predictable as possible, and have made a change in this
+release. The command no longer tries to lowercase text before
+applying titlecasing, and gives the correct result for text
+stored in commands.
+
+We have also added an additional key to the optional argument to
+\cs{MakeTitlecase} which allows the user to decide if this will
+apply only to the first word (the default) or to all words.
+
\section{Bug fixes}
%\subsection{A fix}
diff --git a/base/doc/usrguide.tex b/base/doc/usrguide.tex
index abf128361..21b15fb68 100644
--- a/base/doc/usrguide.tex
+++ b/base/doc/usrguide.tex
@@ -1282,6 +1282,20 @@ available under the alias \texttt{lang}, which can be used to give a language
identifier in BCP-47 format. This is then applied to select language-specific
features during case-changing.
+For titlecasing, the key \texttt{words} may also be used: this
+takes a choice of \texttt{first} or \texttt{all}. The standard
+setting is \texttt{first}, and means that only the very first
+\enquote{letter} is (broadly) uppercased. The alternative,
+\texttt{all}, means that the input is divided at each space, and
+for each word that results, the first letter is uppercased. For
+example
+\begin{verbatim}
+ \MakeTitlecase[words = first]{some words}
+ \MakeTitlecase[words = all]{some words}
+\end{verbatim}
+gives \enquote{\MakeTitlecase[words = first]{some words}
+\MakeTitlecase[words = all]{some words}}.
+
The input given to these commands is \enquote{expanded} before case changing is
applied. This means that any commands within the input that convert to pure
text will be case changed. Mathematical content is automatically excluded, as
diff --git a/base/ltfinal.dtx b/base/ltfinal.dtx
index 2c6b96049..7be7c033b 100644
--- a/base/ltfinal.dtx
+++ b/base/ltfinal.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfinal.dtx}
- [2024/07/08 v2.3c LaTeX Kernel (Final Settings)]
+ [2024/11/12 v2.3d LaTeX Kernel (Final Settings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfinal.dtx}
@@ -1080,6 +1080,8 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Case changing}
+%
% \begin{macro}{\MakeUppercase}
% \begin{macro}{\MakeLowercase}
% \begin{macro}{\MakeTitlecase}
@@ -1110,6 +1112,8 @@
% \changes{v2.2x}{2022/10/26}{Make case changing commands language-aware}
% \changes{v2.2x}{2022/10/26}{Auto-detect \pkg{babel} locale}
% \changes{v2.3a}{2023/04/11}{Use new generic mechanism to detect locale}
+% \changes{v2.3d}{2024/11/12}{Use updated titlecase-first function in \pkg{expl3}}
+% \changes{v2.3d}{2024/11/12}{Add option to titlecase first or all words}
% Wrappers around the L3 case changing functions.
% |\protected| to make them mostly safe as replacements for |uppercase|
% and |\lowercase|.
@@ -1137,11 +1141,15 @@
\keys_define:nn { __kernel }
{
lang .str_set:N = \reserved at a ,
- locale .str_set:N = \reserved at a
+ locale .str_set:N = \reserved at a ,
+ words .choices:nn =
+ { all , first }
+ { \str_set:Nn \reserved at b {#1} }
}
\cs_new_protected:Npn \@@text at case@aux #1#2#3
{
\cs_set_nopar:Npn \reserved at a { }
+ \cs_set_nopar:Npn \reserved at b { }
\tl_if_blank:nTF {#2}
{
\str_set:Nx \reserved at a
@@ -1153,7 +1161,7 @@
}
}
{ \keys_set:nn { __kernel } {#2} }
- \use:c { text_ #1 case:Vn } \reserved at a {#3}
+ \use:c { text_ #1 :Vn } \reserved at a {#3}
}
% \end{macrocode}
% The odd use of \emph{three} spaces here is needed as \pkg{ltcmd} uses the
@@ -1173,6 +1181,11 @@
\reserved at a { Lower }
\reserved at a { Title }
% \end{macrocode}
+% These don't get covered above so we do them manually.
+% \begin{macrocode}
+\cs_generate_variant:Nn \text_titlecase_all:nn { V }
+\cs_generate_variant:Nn \text_titlecase_first:nn { V }
+% \end{macrocode}
% \changes{v2.2y}{2022/11/30}{Set \cs{oe}/\cs{OE} equal to act as a marker for \pkg{babel}}
% \changes{v2.2z}{2023/03/28}{Use groups for gh/1021}
% Currently, \pkg{babel} uses the equivalence of \cs{oe} and \cs{OE} to force casing of
@@ -1183,17 +1196,17 @@
\cs_new_protected:cpn { MakeLowercase \c_space_tl \c_space_tl \c_space_tl } [#1] #2
{{
\let \OE \oe
- \@@text at case@aux { lower } {#1} {#2}
+ \@@text at case@aux { lowercase } {#1} {#2}
}}
\cs_new_protected:cpn { MakeUppercase \c_space_tl \c_space_tl \c_space_tl } [#1] #2
{{
\let \oe \OE
- \@@text at case@aux { upper } {#1} {#2}
+ \@@text at case@aux { uppercase } {#1} {#2}
}}
\cs_new_protected:cpn { MakeTitlecase \c_space_tl \c_space_tl \c_space_tl } [#1] #2
{{
\let \oe \OE
- \@@text at case@aux { title } {#1} {#2}
+ \@@text at case@aux { titlecase_ \reserved at b } {#1} {#2}
}}
% \end{macrocode}
%
diff --git a/base/testfiles/github-1545.lvt b/base/testfiles/github-1545.lvt
new file mode 100644
index 000000000..fe263d8e7
--- /dev/null
+++ b/base/testfiles/github-1545.lvt
@@ -0,0 +1,33 @@
+\documentclass{article}
+
+\input{test2e}
+
+\NewDocumentCommand\hello{}{hello}
+\NewDocumentCommand\helloA{}{helloA}
+\NewDocumentCommand\helloB{}{helloB}
+\NewDocumentCommand\helloC{}{helloC}
+\NewDocumentCommand\helloD{}{helloD}
+\DeclareCaseChangeEquivalent{\hello}{%
+ \CaseSwitch
+ {\helloA}
+ {\helloB}
+ {\helloC}
+ {\helloD}}
+
+\showoutput
+
+\begin{document}
+
+\START
+
+\MakeLowercase{\hello}
+
+\MakeUppercase{\hello}
+
+\MakeTitlecase{\hello}
+
+\MakeTitlecase{some words}
+\MakeTitlecase[words = first]{some words}
+\MakeTitlecase[words = all]{some words}
+
+\end{document}
diff --git a/base/testfiles/github-1545.tlg b/base/testfiles/github-1545.tlg
new file mode 100644
index 000000000..bcca128a7
--- /dev/null
+++ b/base/testfiles/github-1545.tlg
@@ -0,0 +1,110 @@
+This is a generated file for the LaTeX2e validation system.
+Don't change this file in any respect.
+Completed box being shipped out [1]
+\vbox(633.0+0.0)x407.0
+.\glue 16.0
+.\vbox(617.0+0.0)x345.0, shifted 62.0
+..\vbox(12.0+0.0)x345.0, glue set 12.0fil
+...\glue 0.0 plus 1.0fil
+...\hbox(0.0+0.0)x345.0
+....\hbox(0.0+0.0)x345.0
+..\glue 25.0
+..\glue(\lineskip) 0.0
+..\vbox(550.0+0.0)x345.0, glue set 503.94617fil
+...\write-{}
+...\glue(\topskip) 3.05556
+...\hbox(6.94444+0.0)x345.0, glue set 302.22217fil
+....\hbox(0.0+0.0)x15.0
+....\OT1/cmr/m/n/10 h
+....\OT1/cmr/m/n/10 e
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 C
+....\penalty 10000
+....\glue(\parfillskip) 0.0 plus 1.0fil
+....\glue(\rightskip) 0.0
+...\glue(\parskip) 0.0 plus 1.0
+...\glue(\parskip) 0.0
+...\glue(\baselineskip) 5.05556
+...\hbox(6.94444+0.0)x345.0, glue set 302.36104fil
+....\hbox(0.0+0.0)x15.0
+....\OT1/cmr/m/n/10 h
+....\OT1/cmr/m/n/10 e
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 B
+....\penalty 10000
+....\glue(\parfillskip) 0.0 plus 1.0fil
+....\glue(\rightskip) 0.0
+...\glue(\parskip) 0.0 plus 1.0
+...\glue(\parskip) 0.0
+...\glue(\baselineskip) 5.05556
+...\hbox(6.94444+0.0)x345.0, glue set 299.44438fil
+....\hbox(0.0+0.0)x15.0
+....\OT1/cmr/m/n/10 e
+....\OT1/cmr/m/n/10 n
+....\OT1/cmr/m/n/10 h
+....\OT1/cmr/m/n/10 e
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 l
+....\OT1/cmr/m/n/10 o
+....\penalty 10000
+....\glue(\parfillskip) 0.0 plus 1.0fil
+....\glue(\rightskip) 0.0
+...\glue(\parskip) 0.0 plus 1.0
+...\glue(\parskip) 0.0
+...\glue(\baselineskip) 5.05556
+...\hbox(6.94444+0.0)x345.0, glue set 156.36086fil
+....\hbox(0.0+0.0)x15.0
+....\OT1/cmr/m/n/10 e
+....\OT1/cmr/m/n/10 n
+....\OT1/cmr/m/n/10 s
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 m
+....\OT1/cmr/m/n/10 e
+....\glue 3.33333 plus 1.66666 minus 1.11111
+....\OT1/cmr/m/n/10 w
+....\kern-0.27779
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 r
+....\OT1/cmr/m/n/10 d
+....\OT1/cmr/m/n/10 s
+....\glue 3.33333 plus 1.66666 minus 1.11111
+....\OT1/cmr/m/n/10 S
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 m
+....\OT1/cmr/m/n/10 e
+....\glue 3.33333 plus 1.66666 minus 1.11111
+....\OT1/cmr/m/n/10 w
+....\kern-0.27779
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 r
+....\OT1/cmr/m/n/10 d
+....\OT1/cmr/m/n/10 s
+....\glue 3.33333 plus 1.66666 minus 1.11111
+....\OT1/cmr/m/n/10 S
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 m
+....\OT1/cmr/m/n/10 e
+....\glue 3.33333 plus 1.66666 minus 1.11111
+....\OT1/cmr/m/n/10 W
+....\kern-0.83334
+....\OT1/cmr/m/n/10 o
+....\OT1/cmr/m/n/10 r
+....\OT1/cmr/m/n/10 d
+....\OT1/cmr/m/n/10 s
+....\penalty 10000
+....\glue(\parfillskip) 0.0 plus 1.0fil
+....\glue(\rightskip) 0.0
+...\glue 0.0 plus 1.0fil
+...\glue 0.0
+...\glue 0.0 plus 0.0001fil
+..\glue(\baselineskip) 23.55556
+..\hbox(6.44444+0.0)x345.0
+...\hbox(6.44444+0.0)x345.0, glue set 170.0fil
+....\glue 0.0 plus 1.0fil
+....\OT1/cmr/m/n/10 1
+....\glue 0.0 plus 1.0fil
+(github-1545.aux)
More information about the latex3-commits
mailing list.