![如何用 xstring 定义宏并将它们传递给其他宏?](https://linux22.com/image/364845/%E5%A6%82%E4%BD%95%E7%94%A8%20xstring%20%E5%AE%9A%E4%B9%89%E5%AE%8F%E5%B9%B6%E5%B0%86%E5%AE%83%E4%BB%AC%E4%BC%A0%E9%80%92%E7%BB%99%E5%85%B6%E4%BB%96%E5%AE%8F%EF%BC%9F.png)
是否可以使用xstring
包将一个宏的结果传递到另一个宏的定义中?
如果不可能的话,是否有其他方法可以使用 LaTeX 来实现这一点?
具体来说,为什么这个最小工作示例可以起作用:
\documentclass{article} \usepackage{mathrsfs} \usepackage{xstring}
\newenvironment{axioms}[2]{
\StrMid{#1}{0}{1}[\firstletter]
\firstletter
\newcommand{\axiom}[1]{ \item[##1] }
#2 -- the \textbf{#1 Axioms}
\begin{itemize} }{\end{itemize}}
\title{} \author{} \date{} \begin{document}
\begin{axioms}{Matroid}{$\mathscr{M}$}
\axiom{1}
\end{axioms}
\end{document}
为什么这个最小的非工作示例不是能行吗?(区别就在于那一\newcommand
行。)
\documentclass{article} \usepackage{mathrsfs \usepackage{xstring}
\newenvironment{axioms}[2]{
\StrMid{#1}{0}{1}[\firstletter]
\newcommand{\axiom}[1]{ \firstletter \item[##1] }
#2 -- the \textbf{#1 Axioms}
\begin{itemize} }{\end{itemize}}
\title{} \author{} \date{} \begin{document}
\begin{axioms}{Matroid}{$\mathscr{M}$}
\axiom{1}
\end{axioms}
\end{document}
我发现我的 LaTeX 代码中通常有很多冗余,而且我对质量的要求比其他语言要低得多。为了开始改变这种情况,我尝试使用更多(嵌套)宏,但成败参半。
文档第 13 页对于xstring
说:
此包的宏不是纯可扩展的,即它们不能放在 \edef 的参数中。嵌套宏也是不可能的。因此,所有返回结果的宏(即除测试之外的所有宏)在最后位置都有一个可选参数。语法是 [〈name〉],其中 〈name〉 是将接收宏结果的控制序列的名称:使用 \edef 进行赋值,使宏 〈name〉 的结果纯可扩展。
考虑到这一点,我尝试使用文档中提到的东西将命令的结果用作a 中xstring
a 的定义的一部分。但是,我无法做到这一点,并收到错误:\newcommand
\newenvironment
[\result]
Something's wrong--perhaps a missing \item. \axiom{1}
我也在看第 17-19 页相同的文档寻找可能的解决方案,尽管现在我还不够了解它们。如果我能破译它们并找出一些有用的东西,我会尽量记得发布一些东西。
如果这些问题之一(1)(2)(3)(4)回答了我的问题,你能详细解释一下吗?我已经读过它们,但不明白如何将他们的答案应用到我的情况中。具体来说,我想捕捉仅限首字母然后使用该输入的第一个字母作为争论对于另一个宏,而不是创建另一个宏。
答案1
我并不完全清楚您要做什么,但出现错误是因为您的代码产生了以下内容:
\begin{itemize}
M \item
\end{itemize}
这显然是有问题的,因为 itemize 环境中的第一件事应该是\item
。我认为你想要的是:
\documentclass{article}
\usepackage{xstring}
\newenvironment{axioms}[2]{
\StrMid{#1}{0}{1}[\firstletter]
\firstletter
\newcommand{\axiom}[1]{ \item[\firstletter##1] }
#2 -- the \textbf{#1 Axioms}
\begin{itemize}
}{\end{itemize}}
\begin{document}
\begin{axioms}{Matroid}{$\mathscr{M}$}
\axiom{1}
\end{axioms}
\end{document}
我把它剪短了一点,这样它就更接近于最小工作示例。
答案2
您可以使用以下方式简化输入enumitem
:想法是提取第一个字母,然后在标签中使用它enumerate
。
\documentclass{article}
\usepackage{xstring}
\usepackage{enumitem}
\usepackage{mathrsfs}
\newenvironment{axioms}[2]
{%
% get the first letter
\StrMid{#1}{0}{1}[\firstaxiomletter]%
\par
\addvspace{\topsep}
#2 -- the \textbf{#1 Axioms}
% enumerate will use <first letter><number>
\begin{enumerate}[label=\firstaxiomletter\arabic*]
}
{\end{enumerate}}
\newcommand{\axiom}{\item}
\begin{document}
\begin{axioms}{Matroid}{$\mathscr{M}$}
\axiom $1+1=2$
\axiom $2+2=4$
\end{axioms}
\end{document}
xparse
使用和的等效(但可能更简单)的实现expl3
:
\documentclass{article}
\usepackage{xparse}
\usepackage{enumitem}
\usepackage{mathrsfs}
% a user interface to an internal function
\ExplSyntaxOn
\NewExpandableDocumentCommand{\firstletter}{m}
{
\tl_head:n { #1 }
}
\ExplSyntaxOff
\NewDocumentEnvironment{axioms}{mm}
{%
\par
\addvspace{\topsep}
#2 -- the \textbf{#1 Axioms}
\begin{enumerate}[label=\firstletter{#1}\arabic*]
}
{\end{enumerate}}
\newcommand{\axiom}{\item}
\begin{document}
\begin{axioms}{Matroid}{$\mathscr{M}$}
\axiom $1+1=2$
\axiom $2+2=4$
\end{axioms}
\end{document}