如果句子中第一个单词为大写,则宏将单词大写

如果句子中第一个单词为大写,则宏将单词大写

在文档中,我想参数化代词,以便当我们改变人时文档更容易改变。

\newcommand\personname[0]{Joanna Smith}
\newcommand\personpronoun[0]{she}

这很棒,

如果 \personname{} 想要第二个 cookie,则 \personpronoun{} 可能会请求一个。

但在句首,它就变得很尴尬,因为我们希望它大写。

\personpronoun 应该用餐巾纸擦去手指上多余的巧克力。

有没有比定义两个命令更好的方法?

\newcommand\personpronounlc[0]{she}
\newcommand\personpronounuc[0]{She}

答案1

一些软件包中采用的合理解决方案确实是定义两个命令,但使用大写字母来区分它们,因此

\newcommand\personpronoun{she}
\newcommand\Personpronoun{She}

可以建立一种更自动化的方法\spacefactor

\everypar{\spacefactor3000\relax}% beginning of paragraphs
% normally after sentences, the spacefactor is 3000
\DeclareRobustCommand\personpronoun{\leavevmode\ifnum\spacefactor<3000 she\else She\fi} 

但我真的不推荐这样做,因为频繁出现的异常情况使它变得太不可靠,而且比在输入命令时简单地将字母大写要麻烦得多。

答案2

在以下情况下,您可以尝试稍微自动化一些事情:

  • 该宏\personpronoun仅用于普通文本段落。(即,游戏仅涉及(内部)垂直模式和水平模式。不涉及受限水平模式或任何数学模式。)
  • 标点符号., :, ?,!具有空格因子代码\sfcode,可以与\sfcode所有其他字符的 区别开来。因此:
    • \personpronoun在这种情况下,宏仅与字体/设置一起使用。
    • 该宏仅在有效\personpronoun时使用。\nonfrenchspacing

在这些条件下,您可以让 TeX 检查它是否在内\vmode,如果不在内,则检查当前空间因子是否等于\sfcode其中一个标点符号的。

但这种方法并不完全可靠。很多情况下,这种检查不够充分或被人利用。

\documentclass{article}

\makeatletter
\@ifdefinable\CheckVmodeOrPunctuationSpaceFactor{%
  \DeclareRobustCommand\CheckVmodeOrPunctuationSpaceFactor{%
    \ifvmode\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {\@secondoftwo}{%
      \ifnum\the\sfcode`\.=\spacefactor\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
      {\@secondoftwo}{%
        \ifnum\the\sfcode`\!=\spacefactor\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
        {\@secondoftwo}{%
          \ifnum\the\sfcode`\?=\spacefactor\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
          {\@secondoftwo}{%
            \ifnum\the\sfcode`\:=\spacefactor\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
            {\@secondoftwo}{\@firstoftwo}%
          }%
        }%
      }%
    }%
  }%
}%
\makeatother

\newcommand\personname{Joanna Smith}
\newcommand\personpronoun{\CheckVmodeOrPunctuationSpaceFactor{s}{S}he}

% \frenchspacing % <---Don't do this! 
\nonfrenchspacing

\begin{document}

If \personname{} wants a second cookie, \personpronoun{} may ask for one. \personpronoun{} is expected to use a napkin to wipe excess chocolate from fingers.

\personpronoun{} is expected to use a napkin to wipe excess chocolate from fingers.

\end{document}

由于这种方法固有的不可靠性,我更喜欢采用不同的方法:

由于\personpronoun后面跟着一个空组,为了正确获取控制字标记后面的间距,您可以定义\personpronoun一个强制参数,该参数可用于在小写和大写变体之间进行选择。

在以下示例中,如果的参数\personpronoun为空,则使用小写形式。否则,使用大写形式:

\documentclass{article}

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \CheckWhetherNull{<Argument which is to be checked>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is empty>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is not empty>}%
%%
%% If you don't have eTeX-extensions, then do:
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%%\newcommand\CheckWhetherNull[1]{%
%%  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
%%  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
%%  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
%%  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
%%  {\@firstoftwo\expandafter{} \@firstoftwo}%
%%}%
%% If you have eTeX-extensions, then do:
\newcommand\CheckWhetherNull[1]{%
  \romannumeral0\ifcat$\detokenize{#1}$%
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\@firstoftwo\expandafter{} \@firstoftwo}%
  {\@firstoftwo\expandafter{} \@secondoftwo}%
}%
\makeatother

\newcommand\personname{Joanna Smith}
\newcommand\personpronoun[1]{\CheckWhetherNull{#1}{s}{S}he}

\begin{document}

If \personname{} wants a second cookie, \personpronoun{} may ask for one. \personpronoun{UC} is expected to use a napkin to wipe excess chocolate from fingers.

\personpronoun{UC} is expected to use a napkin to wipe excess chocolate from fingers.

\end{document}

但这仍然很麻烦。

最好只是定义\personpronoun\Personpronoun按照建议唐纳德·阿瑟诺

您可能希望加载包空间并将一个附加\xspace到代词。在许多情况下,\xspace当需要空格标记时,可以正确地插入空格标记,但是相应的 .tex 输入文件中的空格字符在标记化过程中被吃掉,因为它发生在被标记为控制字标记的某些东西后面,这导致 TeX 将读取装置切换到状态 S(跳过空格)。

\documentclass{article}
\usepackage{xspace}


\newcommand\personname{Joanna Smith\xspace}
\newcommand\personpronoun{she\xspace}
\newcommand\Personpronoun{She\xspace}

\begin{document}

If \personname wants a second cookie, \personpronoun may ask for one. \Personpronoun is expected to use a napkin to wipe excess chocolate from fingers.

\Personpronoun is expected to use a napkin to wipe excess chocolate from fingers.

\end{document}

相关内容