宏中的字符串 - 如何将其作为默认可选参数传递给另一个命令中定义的命令?

宏中的字符串 - 如何将其作为默认可选参数传递给另一个命令中定义的命令?

考虑以下代码

\documentclass{article}
\usepackage{xstring,etoolbox}
\usepackage[shortlabels]{enumitem}

\def\lists{%
    parts-a),
    items-1)
}
\renewcommand*{\do}[1]{%
    \StrCut{#1}{-}\csA\csB
    % the next line is the "crucial one"
    \expandafter\providecommand\csname my\csA\endcsname[1][\csB]{%
        \begin{enumerate}[##1]
            \item one
            \item two
        \end{enumerate}
    }
}
\expandafter\docsvlist\expandafter{\lists}

\begin{document}
\myparts[i)]
\myparts
\end{document}

它产生

i) one
ii) two
1) one
1) two

我应该如何修改“关键线”,以使其按预期工作,即产生

i) one
ii) two
a) one
b) two

据我所知,我需要传递 \csB“expanded”。但我玩了几个小时各种 edef 和 expandafter,我快要疯了,我已经没有主意了。

(以上是一个精简的最小示例 - 实际上它是一个更有用的代码,但我认为以上很好地解决了我的问题)

编辑:siracusa 的答案似乎有效,不幸的是我不知道如何通过以下修改来做一个更困难的例子

\begin{enumerate}[##1]
    \item one
    \item two
\end{enumerate}
The above list is of type \csB

如上所述,它将始终打印“以上列表属于类型 1)”,并且我不清楚如何修改 siracusa 的答案以正确扩展 \myparts 定义中的 \csB...

答案1

以下似乎就是您想要的:

\renewcommand*{\do}[1]{%
    \StrCut{#1}{-}\csA\csB
    % the next line is the "crucial one"
    \edef\temp{\noexpand\providecommand\expandafter\noexpand\csname my\csA\endcsname[1][\csB]}%
    \temp{%
        \begin{enumerate}[##1]
            \item one
            \item two
        \end{enumerate}
    }
}

我们首先定义一个临时命令\temp,该命令将参数完全展开\providecommand,除了\providecommand被 阻止的宏本身\noexpand。然后\temp执行 来实际执行命令定义。


这是有关扩展问题的新版本:

\renewcommand*{\do}[1]{%
    \StrCut{#1}{-}\csA\csB
    % the next line is the "crucial one"
    \edef\temp{\noexpand\providecommand\expandafter\noexpand\csname my\csA\endcsname[1][\csB]{%
        \noexpand\begin{enumerate}[####1]
            \noexpand\item one
            \noexpand\item two
        \noexpand\end{enumerate}
        The above list is of type \csB
    }%
    }\temp
}

now涵盖\edef整个定义,而不仅仅是参数。但是,这使得必须为所有不应被扩展的命令添加前缀\noexpand。不确定这在您的实际代码中是否可行。egregxparse建议的版本在这里更灵活。

答案2

您不应该使用\providecommand这个。此外,重新定义\do非常危险,因为多个包可以使用它。etoolbox您可以使用\forcsvlist,它接受不同的宏。

主要问题是传球\csB扩大。

\documentclass{article}
\usepackage{xstring,etoolbox}
\usepackage[shortlabels]{enumitem}

\newcommand\lists{%
    parts-a),
    items-1)
}

\newcommand*{\mydo}[1]{%
    \StrCut{#1}{-}\csA\csB
    % build \newcommand one step at a time
    \toks0=\expandafter{\expandafter\newcommand\csname my\csA\endcsname}%
    \toks2=\expandafter{\csB}%
    \begingroup\edef\x{\endgroup\the\toks0[1][\the\toks2]}\x{%
        \begin{enumerate}[##1]
            \item one
            \item two
        \end{enumerate}
    }%
}
\expandafter\forcsvlist\expandafter\mydo\expandafter{\lists}

\begin{document}
\myparts[i)]
\myparts
\end{document}

在此处输入图片描述

采用不同的方法,基于xparse

\documentclass{article}
\usepackage{xparse}
\usepackage[shortlabels]{enumitem}

\NewDocumentCommand{\parselists}{>{\SplitList{,}}m}{%
  \ProcessList{#1}{\makelist}%
}
\NewDocumentCommand{\makelist}{>{\SplitArgument{1}{-}}{m}}{%
  \makelistsdo#1%
}
\NewDocumentCommand{\makelistsdo}{mm}{%
  \NewDocumentNamedCommand{my#1}{O{#2}}{%
        \begin{enumerate}[##1]
            \item one
            \item two
        \end{enumerate}
  }%
}
\ExplSyntaxOn
\cs_new_protected:Npn \NewDocumentNamedCommand #1
 {
  \exp_args:Nc \NewDocumentCommand { #1 }
 }
\ExplSyntaxOff

\parselists{
  parts-a),
  items-1),
}

\begin{document}
\myparts[i)]
\myparts
\myitems[i)]
\myitems
\end{document}

在此处输入图片描述

相关内容