答案1
\documentclass[a4paper]{article}
\usepackage[latin1]{inputenc}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\capitalize}{>{\SplitList{~}}m}{
\CapitalizeFirst#1\Capitalize\unskip
}
\ExplSyntaxOff
\def\Sentinel{\Capitalize}
\def\CapitalizeFirst#1{\MakeUppercase#1 \Capitalize}
\def\Capitalize#1{%
\def\next{#1}%
\ifx\next\Sentinel
\expandafter\unskip
\else
\CheckInList{#1}\space\expandafter\Capitalize
\fi}
\def\CheckInList#1{%
\ifcsname List@\detokenize{#1}\endcsname
#1%
\else
\MakeUppercase#1%
\fi}
\makeatletter
\def\AppendToList#1{%
\@for\next:=#1\do
{\expandafter\let\csname List@\detokenize\expandafter{\next}\endcsname\empty}}
\makeatother
\AppendToList{a,is,of}
\begin{document}
\capitalize{here is a list of words école}
\end{document}
不适用于 UTF-8(除非使用 XeLaTeX 或 LuaLaTeX)。
它不适用于 UTF-8,pdflatex
因为\MakeUppercase
仅适用于可能的两个、三个或四个字节组合的第一个字节(对于西方语言可能只有两个)。要使它起作用,必须将整个字节块输入\MakeUppercase
。
更清楚一点:当我们说 时\MakeUppercase
,LaTeX 会将参数大写;一般来说,调用是\MakeUppercase{word}
;这里我们改为说\MakeUppercase#1
(不带括号),因此只有第一个标记(通常是一个字符)会大写;这里它会在输入诸如 时失败\'ecole
:传递给 的标记\MakeUppercase
将是\'
,它不知道该怎么做。使用école
(和诸如 这样的单字节编码latin1
)\MakeUppercase
将处理é
并给出正确的结果。
使用 UTF-8 的话就会失败:看就像é
我们在屏幕上编写 LaTeX 文档时实际上两个字节(对于 C3 和 A9 é
)并且再次\MakeUppercase
只传递第一个。因此需要更复杂的例程。
为了使其与 UTF-8 兼容,上面pdflatex
的定义可以更改为以下内容\CheckInList
\CapitalizeFirst
\def\CapitalizeFirst#1{\expandafter\UC@next#1 \Capitalize}
\def\CheckInList#1{%
\ifcsname List@\detokenize{#1}\endcsname
#1%
\else
\expandafter\UC@next#1%
\fi}
\def\UC@next#1{%
\ifx#1\UTFviii@two@octets
\expandafter\@firstoffour
\else
\ifx#1\UTFviii@three@octets
\expandafter\expandafter\expandafter\@secondoffour
\else
\ifx#1\UTFviii@four@octets
\expandafter\expandafter\expandafter\expandafter\expandafter
\@thirdoffour
\else
\expandafter\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\@fourthoffour
\fi
\fi
\fi
{\UC@two}{\UC@three}{\UC@four}{\MakeUppercase}#1}
\def\UC@two#1#2#3{\MakeUppercase{#1#2#3}}
\def\UC@three#1#2#3#4{\MakeUppercase{#1#2#3#4}}
\def\UC@four#1#2#3#4#5{\MakeUppercase{#1#2#3#4#5}}
\providecommand\@firstoffour[4]{#1}
\providecommand\@secondoffour[4]{#2}
\providecommand\@thirdoffour[4]{#3}
\providecommand\@fourthoffour[4]{#4}
但是不允许使用重音命令(在其他版本中也不允许)。
更新
几年后,由于新expl3
功能的出现,我们有了更好的实现;它适用于所有引擎。
\documentclass[a4paper]{article}
\usepackage{ifxetex}
\ifxetex
\usepackage{fontspec}
\else
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\fi
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\capitalize}{>{\SplitList{~}}m}
{
\seq_clear:N \l_capitalize_words_seq
\ProcessList{#1}{\CapitalizeFirst}
\seq_use:Nn \l_capitalize_words_seq { ~ }
}
\NewDocumentCommand{\CapitalizeFirst}{m}
{
\capitalize_word:n { #1 }
}
\sys_if_engine_pdftex:TF
{
\cs_set_eq:Nc \capitalize_tl_set:Nn { protected@edef }
}
{
\cs_set_eq:NN \capitalize_tl_set:Nn \tl_set:Nn
}
\cs_new_protected:Nn \capitalize_word:n
{
\capitalize_tl_set:Nn \l_capitalize_word_tl { #1 }
\seq_if_in:NfTF \g_capitalize_exceptions_seq { \tl_to_str:n { #1 } }
% exception word
{ \seq_put_right:Nn \l_capitalize_words_seq { #1 } } % exception word
% to be uppercased
{ \seq_put_right:Nx \l_capitalize_words_seq { \tl_mixed_case:V \l_capitalize_word_tl } }
}
\cs_generate_variant:Nn \tl_mixed_case:n { V }
\NewDocumentCommand{\AppendToList}{m}
{
\clist_map_inline:nn { #1 }
{
\seq_gput_right:Nx \g_capitalize_exceptions_seq { \tl_to_str:n { ##1 } }
}
}
\cs_generate_variant:Nn \seq_if_in:NnTF { Nf }
\seq_new:N \l_capitalize_words_seq
\seq_new:N \g_capitalize_exceptions_seq
\ExplSyntaxOff
\AppendToList{a,is,of,óf}
\begin{document}
X\capitalize{here is a list of words óf école}X
\end{document}
答案2
ConTeXt 解决方案:
\applytosplitstringwordspaced
您可以使用以下命令:
\def\IgnoredWords
{a,is,to,of,or,and}
\define[1]\CapitalizeWithIgnoreWord
{\doifinsetelse{#1}\IgnoredWords{#1}{\Words{#1}}}
\def\CapitalizeWithIgnore
{\applytosplitstringwordspaced\CapitalizeWithIgnoreWord}
\starttext
\CapitalizeWithIgnore{This is some of my input or another and to the end.}
\stoptext
这使
该\applytosplitstringwordspaced
命令将输入分成单词,并将每个单词应用到宏\CapitalizeWithIgnoreWord
,该宏接受一个参数。然后我只需测试给定的单词是否是单词列表的成员,然后打印它,或者将其大写打印。
答案3
该titlecaps
包是新推出的,并在此处演示:大写标题。它将负责为变音符号(例如,变音符号等)和国家符号(例如,oe)添加标题,并与更改字体特征的命令兼容(即,可以包含在其参数中),例如\textit{}
,\scshape
和\footnotesize
。此外,它允许将单词指定为小写,例如介词和连词,这些单词将被筛选出来而不是标题。标点符号的存在不应影响包将单词大写或将其检测为预先指定的小写单词的能力。
答案4
使用 csplain 您可以通过几行基本宏来实现这一点(它们仅使用 TeX 原语):
\def\capitalize#1{\capitA#1 {} }
\def\capitA#1 {\capitW#1 \capitB}
\def\capitB#1 {\ifx\relax#1\relax \else \space
\isinlist\extrawords{ #1 }\iftrue #1\else \capitW#1 \fi
\expandafter \capitB \fi
}
\def\capitW#1#2 {\uppercase{#1}#2}
\def\isinlist#1#2#3{\begingroup \long\def\tmp##1#2##2\end{\def\tmp{##2}%
\ifx\tmp\empty \endgroup \csname iffalse\expandafter\endcsname \else
\endgroup \csname iftrue\expandafter\endcsname \fi}%
\expandafter\tmp#1\endlistsep#2\end
}
\def\extrawords{ a is of óf }
X\capitalize{here is a list of words óf école}X
\bye