命令将句子中每个单词的首字母大写

命令将句子中每个单词的首字母大写

我正在用乳胶写一个文本框,里面有类似的东西

\textit{some definition}\index{Some Definition}

到处都是。我想把它们组合成类似

\define{some definition}

并让它自动扩展。这样我就可以拥有

\newcommand{\define}[2]{\textit{#1}\index{#2}}

它可以工作,但迫使我同时包含两个参数。第二个参数几乎总是第一个参数,每个单词的第一个字母都大写。我如何编写一个命令将每个单词的第一个字符大写?

我们也欢迎有关更好的索引最佳实践的建议。

答案1

\documentclass{article}
\usepackage{makeidx}\makeindex
\newcommand*{\formatfirst}[1]{\MakeUppercase{#1}}
\makeatletter
\newcommand*{\mymacro}[1]{%
  \expandafter\formatfirst\expandafter{\@car #1\@empty\@nil}%
  \@cdr #1\@empty\@nil}
\newcommand*\myMakeUpperCase[1]{%
  \def\@myuppercasewords{\myuppercase@i#1 \@nil}%
    {\itshape\@myuppercasewords}\index{#1@\@myuppercasewords}}
\def\myuppercase@i#1 #2\@nil{%
  \mymacro{#1}%
  \ifx\\#2\\%
  \else
    \@ReturnAfterFi{%
      \space
      \myuppercase@i#2\@nil
    }%
  \fi} 
\long\def\@ReturnAfterFi#1\fi{\fi#1} 
\makeatother

\begin{document}
foo
\myMakeUpperCase{capital letter} bar
\myMakeUpperCase{Next one} baz
\myMakeUpperCase{two words}

\printindex

\end{document} 

替代文本

答案2

mfirstuc来自的包裹glossaries提供了\capitalisewords可以在这里使用的方便的命令。我改编了赫伯特的示例,输出相同:

\documentclass{article}

\usepackage{mfirstuc}
\usepackage{makeidx}\makeindex

\makeatletter
\newcommand*\define[1]{%
  \textit{#1}%
  \index{#1@\protect\capitalisewords{#1}}%
   }
\makeatother

\begin{document}
foo
\define{capital letter} bar
\define{Next one} baz
\define{two words}

\printindex

\end{document}

答案3

我不确定我是否正确理解了您的问题,但如下所示的简短宏将把您输入的第一个单词大写并将其放在索引中。

\documentclass[11pt]{article} 
\usepackage{index}
\makeindex
\begin{document}
\def\Index#1{\def\x##1##2{\MakeUppercase{##1}{##2}}\textit{\x#1} \index{\x#1}} 
\Index{alpha}

\def\indeX#1#2{\def\x##1##2{\MakeUppercase{##1}{##2}}\x#1 \index{\x#2}} 
\Index{alpha}

\indeX{test}{this}

\printindex
\end{document}

答案4

我的纯 LaTex3 解决方案:

\documentclass{minimal}
\usepackage{xparse}
\usepackage[T1]{fontenc}

\ExplSyntaxOn

\NewDocumentCommand{\ucFirst}{m} {
  \sphakka_ucfirst:f {#1}
}
\cs_new_protected:Npn \sphakka_ucfirst:f #1 {
  \exp_last_unbraced:Nx \tl_to_uppercase:n {\tl_head:f {#1}}
  % notice the ~ to put back blank padding
  \tl_tail:f {#1}~
}

\NewDocumentCommand{\ucFirstMore}{m} {
  \sphakka_ucfirstmore:f {#1}
}
\cs_new_protected:Npn \sphakka_ucfirstmore:n #1 {
  % must convert the TL into a SEQ
  \seq_set_split:Nnn \l_sphakka_seq {~} {#1}
  \seq_map_function:NN \l_sphakka_seq \sphakka_ucfirst:f
}
\cs_generate_variant:Nn \sphakka_ucfirstmore:n {f}

\ExplSyntaxOff

\begin{document}

\def\word{bar}
\def\sentence{foo bar baz}

[Plain word] quux => \ucFirst{quux}\par
[Word via macro]~\word~=> \ucFirst{\word}\par
[Plain sentence] foo bar baz => \ucFirstMore{foo bar baz}\par
[Sentence via macro]~\sentence~=> \ucFirstMore \sentence \par

\end{document}

虽然简单,但上述解决方案留下了一个尾随的不可中断空格,这很难消除。因此,我编写了一个变体,将大写标记存储到另一个序列中,然后用空格将它们粘合在一起:

\documentclass{minimal}
\usepackage{xparse}
\usepackage[T1]{fontenc}

\ExplSyntaxOn

\NewDocumentCommand \ucFirst {>{\TrimSpaces}m} {
  % Won't trim explicit trailing `\space's... why?
  \sphakka_ucfirst:f {#1}
}
\cs_new_protected:Npn \sphakka_ucfirst:f #1 {
  \exp_last_unbraced:Nf \tl_to_uppercase:n {\tl_head:f {#1}}
  \tl_tail:f {#1}
}

\NewDocumentCommand \ucFirstMore {>{\TrimSpaces}m} {
  \sphakka_ucfirstmore:f {#1}
}
\seq_new:N \l_out_seq
\cs_new_protected:Npn \sphakka_ucfirstmore:n #1 {
  % split by blanks. Can anybody tell me why `\space` doesn't work?
  \seq_set_split:Nnn \l_in_seq {~} {#1}
  % remove empty/blank items
  \seq_remove_all:Nn \l_in_seq {}
  \seq_remove_all:Nn \l_in_seq {\space}
  % capitalize each token and store it into another seq
  \seq_map_inline:Nn \l_in_seq {
    \seq_put_right:Nn \l_out_seq {\sphakka_ucfirst:f {##1}}
  }
  \seq_use:Nnnn \l_out_seq {\space}{\space}{\space}
  \seq_clear:N \l_out_seq
}
\cs_generate_variant:Nn \sphakka_ucfirstmore:n {f}


\ExplSyntaxOff

\begin{document}

\edef\word{\space  quux\space }
\edef\sentence{  \space  foo  bar baz \space }

\begin{tabular}[c]{p{.6\linewidth}l}
  \verb|\word|                                          & \verb|`\space  quux\space '|\\
  \verb|\sentence|                                      & \verb|`\space  foo  bar baz \space '|\\
  \\
  \verb|\ucFirst{\space  quux\space }|                  & `\ucFirst{\space  quux\space }'\\
  \verb|\ucFirst{\word}|                                & `\ucFirst{\word}' \\
  \verb|\ucFirstMore{\word}|                            & `\ucFirstMore{\word}' \\
  \verb|\ucFirstMore{  \space  foo  bar baz \space }|   & `\ucFirstMore{  \space  foo  bar baz \space }'\\
  \verb|\ucFirstMore{\sentence}|                        & `\ucFirstMore{\sentence}'\\
\end{tabular}

\end{document}

lualatex 输出

只有几个小问题我无法解决(可能是因为我缺乏经验......):

  • 为什么\TrimSpaces(或\tl_trim_spaces) 不删除明确的尾随\spaces?

  • 为什么\seq_set_split不能分开\space

相关内容