我希望简化和改进以下代码:
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{test.txt}
a an and the this by on of
\end{filecontents}
\begin{document}
\makeatletter
\in@false
\def\upfirst#1#2\upfirst{%
\in@{#1#2}{a and of that this}%
\ifin@{\LARGE#1#2}\else {\Huge\MakeUppercase#1}{\LARGE#2 }\fi
}
\def\smallcaps#1\upfirst{\textsc{#1} }
\def\boldfirst#1#2\upfirst{\textbf{\uppercase{#1}}#2 }
\def\everytoken#1#2{%
\def\everytoken@##1{%
\@tempcntb=0
\@tfor \i :=##1 \do{\expandafter#2\i\upfirst
}}
\everytoken@{#1}%
}
\everytoken {{the} {battle} {and} {the} {resistance} {of} {france}}{\upfirst}
\everytoken {{Life} {death} {and} {the} {Universe}}{\smallcaps}
\everytoken {{The} {battle} {and} {the} {Resistance} }{\boldfirst}
\makeatother
\end{document}
代码的作用是设置标题的样式,将首字母大写(如果该单词不在保留单词中),或者将标题设置为小写或粗体并将首字母大写。
我正在寻找界面上的改进(目前标题词必须用括号括起来)以及输入带有保留字的文件的方法,而不仅仅是直接输入它们。(请参阅周围的代码in@
。
答案1
当然还有一个 LaTeX3 版本等待。:)
\begin{filecontents*}{\jobname.dat}
that this
the
\end{filecontents*}
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\everytoken}{O{}mm}
{
\group_begin:
#1 % #1 are global formatting instructions
\yiannis_everytoken:Nn #2 { #3 }
\group_end:
}
\seq_new:N \l__yiannis_words_seq
\seq_new:N \l__yiannis_final_seq
\seq_new:N \g_yiannis_reserved_words_seq
\tl_new:N \l__yiannis_first_word_tl
\cs_generate_variant:Nn \seq_put_left:Nn { Nf }
\cs_new_protected:Npn \yiannis_everytoken:Nn #1 #2
{
\seq_set_split:Nnn \l__yiannis_words_seq { ~ } { #2 }
\seq_pop_left:NN \l__yiannis_words_seq \l__yiannis_first_word_tl
\seq_clear:N \l__yiannis_final_seq
\seq_map_inline:Nn \l__yiannis_words_seq
{
\yiannis_if_reserved:nTF { ##1 }
{ \seq_put_right:Nn \l__yiannis_final_seq { ##1 } }
{ \seq_put_right:Nn \l__yiannis_final_seq { #1 { ##1 } } }
}
\seq_put_left:Nf \l__yiannis_final_seq { \exp_args:NNV \exp_not:N #1 \l__yiannis_first_word_tl }
\seq_use:Nnnn \l__yiannis_final_seq { ~ } { ~ } { ~ }
}
\prg_new_conditional:Npnn \yiannis_if_reserved:n #1 { TF }
{
\seq_if_in:NnTF \g_yiannis_reserved_words_seq { #1 }
{ \prg_return_true: }
{ \prg_return_false: }
}
%%% Simple version
\NewDocumentCommand{\Hugeupfirst}{m}
{
\tl_to_uppercase:n { { \Huge \tl_head:n { #1 } } }
\tl_tail:n { #1 }
}
%%% Complex but more robust version (uncomment the following four lines)
%\RenewDocumentCommand{\Hugeupfirst}{m}
% {
% \yiannis_Hugeupfirst:n { #1 }
% }
\cs_new_protected:Npn \yiannis_hugeupfirst:n #1
{
\tl_set:Nn \l__yiannis_temp_tl { #1 }
\regex_replace_once:nnN
{ \A (.*? [A-Za-z]) }
{ \c{tl_to_uppercase:n} \cB\{ \cB\{ \c{Huge} \1 \cE\} \cE\} }
\l__yiannis_temp_tl
\tl_use:N \l__yiannis_temp_tl
}
%%% end of more complex version
%%% Simple version
\NewDocumentCommand{\upfirst}{m}
{
\tl_to_uppercase:n { \tl_head:n { #1 } }
\tl_tail:n { #1 }
}
%%% Complex but more robust version (uncomment the following four lines)
%\RenewDocumentCommand{\upfirst}{m}
% {
% \yiannis_upfirst:n { #1 }
% }
\cs_new_protected:Npn \yiannis_upfirst:n #1
{
\tl_set:Nn \l__yiannis_temp_tl { #1 }
\regex_replace_once:nnN
{ \A (.*? [A-Za-z]) }
{ \c{tl_to_uppercase:n} \cB\{ \1 \cE\} }
\l__yiannis_temp_tl
\tl_use:N \l__yiannis_temp_tl
}
%%% end of more complex version
\NewDocumentCommand{\setreservedwords}{m}
{
\clist_map_inline:nn { #1 }
{ \seq_gput_right:Nn \g_yiannis_reserved_words_seq { ##1 } }
}
\ior_new:N \l_yiannis_input_ior
\NewDocumentCommand{\readreservedwords}{m}
{
\yiannis_read_reserved_words:n { #1 }
}
\cs_new_protected:Npn \yiannis_read_reserved_words:n #1
{
\ior_open:Nn \l_yiannis_input_ior { #1 }
\tl_clear:N \l_tempa_tl
\ior_map_inline:Nn \l_yiannis_input_ior
{
\tl_put_right:Nn \l_tempa_tl { ##1 ~ }
}
\seq_set_split:NnV \l_tempa_seq { ~ } \l_tempa_tl
\seq_gconcat:NNN \g_yiannis_reserved_words_seq \l_tempa_seq \g_yiannis_reserved_words_seq
\seq_gremove_all:Nn \g_yiannis_reserved_words_seq { }
}
\ExplSyntaxOff
\setreservedwords{a, and, of}
\readreservedwords{\jobname.dat}
\begin{document}
\everytoken{\Hugeupfirst}{The battle and the resistance of France}
\everytoken[\scshape]{\Hugeupfirst}{the battle and the resistance of france}
\everytoken[\scshape]{\upfirst}{the battle and the resistance of france}
\everytoken{\upfirst}{the battle and the resistance of france}
\end{document}
有两种方法可以添加保留字列表:要么使用逗号分隔列表作为参数,\setreservedwords
要么使用文件作为参数,其中分隔符是空格或行尾\readreservedwords
。您可以按任何顺序使用它们,并且每个命令都会添加到最初为空的列表中。
语法\everytoken
是
\everytoken[<global formatting>]{<first letter>}{<words>}
在哪里
<global formatting>
是一组应用于所有字母的格式指令(例如,\bfseries
或\scshape
)<first letter>
是要应用于非保留字的第一个字母和第一个单词的宏<words>
是单词列表
我给出了“简单”版(无重音字符)和“复杂”版的示例\Hugeupfirst
。\upfirst
使用“复杂”版,您可以管理\'equipe de secours
简单版无法管理的内容。
答案2
这将从文件中读取单词,修复 in@ 测试中缺失的空格,并避免需要对每个单词进行括号。
输出并不像您显示的那样,因为文件中的单词列表版本包含the
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{test.txt}
a an and the this by on of
\end{filecontents*}
\begin{document}
\makeatletter
\newread\testtxt
\immediate\openin\testtxt test.txt
\immediate\read\testtxt to \foo
\def\upfirst#1#2 {%
\edef\tmp{\noexpand\in@{#1#2}{\foo}}\tmp%
\ifin@{\LARGE#1#2 }\else {\Huge\MakeUppercase#1}{\LARGE#2 }\fi
}
\def\smallcaps#1 {\textsc{#1} }
\def\boldfirst#1#2 {\textbf{\uppercase{#1}}#2 }
\def\everytoken#1#2{\xeverytoken#2#1 \relax}
\def\xeverytoken#1#2 #3{%
#1#2
\ifx\relax#3%
\else
\expandafter\xeverytoken\expandafter#1%
\fi
#3}
\everytoken {the battle and the resistance of france}{\upfirst}
\everytoken {Life death and the Universe}{\smallcaps}
\everytoken {The battle and the Resistance}{\boldfirst}
\makeatother
\end{document}
要强制始终处理第一个单词,请稍微更改一些宏
\def\upfirst#1#2 {%
\edef\tmp{\noexpand\in@{#1#2}{\foox}}\tmp%
\ifin@{\LARGE#1#2 }\else {\Huge\MakeUppercase#1}{\LARGE#2 }\fi
}
\def\everytoken#1#2{%
\let\foox\@empty
\xeverytoken#2#1 \relax}
\def\xeverytoken#1#2 #3{%
#1#2
\let\foox\foo
\ifx\relax#3%
\else
\expandafter\xeverytoken\expandafter#1%
\fi
#3}