我想编写一个\createTheorem
创建两个环境的宏:一个普通环境和一个“大写”环境。
例如,\createTheorem{defi}{Definition}
将创建:
- 一个环境
\begin{defi}...\end{defi}
- 和一个环境
\begin{Defi}...\end{Defi}
。
你会怎么做?我想知道为什么我的代码不起作用。
我的代码
这是我尝试过的。它不起作用,错误是
缺少 \endcsname 插入。\protect l.13 \documentclass{article}
\usepackage{amsmath}
\newtheorem{theoremForCounter}{theoremForCounter}
\newcommand{\createTheorem}[2]
{
\def\nameNewTheoremCapitalized{\MakeUppercase{#1}}
\newtheorem{#1}[theoremForCounter]{#2}
\newtheorem{\nameNewTheoremCapitalized}[theoremForCounter]{#2}
}
\createTheorem{defi}{Definition}
\begin{document}
\begin{defi}
This is a test.
\end{defi}
\begin{Defi}
This is a test.
\end{Defi}
\end{document}
答案1
我不确定这样做有什么用:拥有两个环境defi
并且Defi
做完全相同的事情是没用的,而且可能会造成混淆。
无论如何,您都可以使用\text_titlecase:n
(使用 2020 年 3 月之后发布的 LaTeX)。
\documentclass{article}
\usepackage{amsthm} % probably you wanted this one
\newcounter{counterForTheorem}
\ExplSyntaxOn
\cs_new:Npn \uppercasefirst #1
{
\str_uppercase:f { \tl_head:n { #1 } }
\tl_tail:n { #1 }
}
\ExplSyntaxOff
\newcommand{\createTheorem}[2]{%
\newtheorem{#1}[counterForTheorem]{#2}%
\newtheorem{\uppercasefirst{#1}}[counterForTheorem]{#2}%
}
\createTheorem{defi}{Definition}
\begin{document}
\begin{defi}
This is a test.
\end{defi}
\begin{Defi}
This is a test.
\end{Defi}
\end{document}
替代实施方案:
\documentclass{article}
\usepackage{amsthm} % probably you wanted this one
\newcounter{counterForTheorem}
\makeatletter
\newcommand{\createTheorem}[2]{%
\newtheorem{#1}[counterForTheorem]{#2}%
\begingroup
\edef\temp@a{\@car#1\@nil}%
\edef\temp@b{\@cdr#1\@nil}%
\begingroup\edef\x{\endgroup\uppercase{\def\noexpand\temp@a{\temp@a}}}\x
\edef\temp@a{\temp@a\temp@b}%
\expandafter\endgroup\expandafter\newtheorem\expandafter{\temp@a}[counterForTheorem]{#2}%
}
\makeatother
\createTheorem{defi}{Definition}
\begin{document}
\begin{defi}
This is a test.
\end{defi}
\begin{Defi}
This is a test.
\end{Defi}
\end{document}
答案2
如上所述,MakeUppercase
不可扩展。您可以改用str_uppercase:f
可扩展的 expl3 函数:
%! TEX program = lualatex
\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\newcommand{\createTheorem}[2]
{
\def\nameNewTheoremCapitalized{\str_uppercase:f{\tl_head:n{#1}}\tl_tail:n{#1}}
\newtheorem{#1}{#2}
\exp_args:Nx\newtheorem{\nameNewTheoremCapitalized}{#2}
}
\ExplSyntaxOff
\createTheorem{defi}{Definition}
\begin{document}
\begin{defi}
This is a test.
\end{defi}
\begin{Defi}
This is a test.
\end{Defi}
\end{document}
评论:
- 在 pdflatex 中将
\tl_head
采用名称的第一个字节而不是第一个字符,所以我不知道如果第一个字符不是简单的 ASCII 字符会发生什么。 - 如果第一个字符不是小写字符,
newtheorem
则会引发错误,因为两个名称相同。 - 你的宏定义有虚假空间. 并非如此
\ExplSyntaxOn
。 - 在这种情况下,实现
newtheorem
恰好已经扩展了内部的参数,因此在传递给它之前无需扩展参数……尽管如此,我不确定这种行为是否能保证……所以我\exp_args:Nx
以防万一添加。
答案3
您可以直接使用 TeX 原语\uppercase
,但这仍然不可扩展,因此我们必须使用一些技巧。\createTheorem@a
用于获取第一个字符,并\createTheorem@b
在第一个字符已经大写后调用,并将名称重新组合在一起。
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\long\def\createTheorem@a#1#2\end
{\uppercase{\createTheorem@b{#1}}{#2}}
\newcommand\createTheorem@b[2]{\newtheorem{#1#2}}
\newcommand{\createTheorem}[2]
{%
\newtheorem{#1}{#2}%
\createTheorem@a#1\end{#2}%
}
\makeatother
\createTheorem{defi}{Definition}
\begin{document}
\begin{defi}
This is a test.
\end{defi}
\begin{Defi}
This is a test.
\end{Defi}
\end{document}