![根据逗号分隔列表调用命令](https://linux22.com/image/331749/%E6%A0%B9%E6%8D%AE%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%88%97%E8%A1%A8%E8%B0%83%E7%94%A8%E5%91%BD%E4%BB%A4.png)
我有几个命令,称为\cata
to \catd
。现在我需要一个命令,它循环遍历给定的逗号分隔列表,并调用相应的命令。我目前的方法是:
\documentclass[10pt,a4paper]{article}
\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{tikz}
\newcommand{\cata}{Hello a\newline}
\newcommand{\catb}{Hello b\newline}
\newcommand{\catc}{Hello c\newline}
\newcommand{\catd}{Hello d\newline}
\newcommand{\cat}[1]{%
\expandafter\newcommand\csname cat#1\endcsname%
}
\newcommand{\loopover}[1]{
\foreach \i in {#1}{
\cat\i}
}
\begin{document}
Hello World\\
\loopover{a, b, c, d}
\end{document}
我的预期输出是:
Hello World
Hello a
Hello b
Hello c
Hello d
如果我改为\loopover{a,b,c,d}
,\loopover{a,a,c}
我想得到这个
Hello World
Hello a
Hello a
Hello c
到目前为止,我得到了错误LaTeX Error: Command \cata already defined.
,这是有道理的。还有其他方法可以实现我的目的吗?
编辑:我想在之后扩展命令,因此当前的情况可能有点误导。我想让命令\cata
自行调用,而不是重写它。
最终的应用程序如下所示:
\documentclass[10pt,a4paper]{article}
\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{tocloft}
\newcommand{\lista}{List a}
\newcommand{\listb}{List b}
\newcommand{\listc}{List c}
\newcommand{\listd}{List d}
\newlistof{cata}{expa}{\lista}
\newlistof{catb}{expb}{\listb}
\newlistof{catc}{expc}{\listc}
\newlistof{catd}{expd}{\listd}
\newcommand{\cata}[1]{%
\refstepcounter{cata}
\par\noindent\textbf{cata \thecata. #1}
\addcontentsline{expa}{cata}
{\protect\numberline{\thechapter.\thecata}#1}\par
}
\newcommand{\catb}[1]{%
\refstepcounter{catb}
\par\noindent\textbf{catb \thecatb. #1}
\addcontentsline{expb}{catb}
{\protect\numberline{\thechapter.\thecatb}#1}\par
}
\newcommand{\catc}[1]{%
\refstepcounter{catc}
\par\noindent\textbf{catc \thecatc. #1}
\addcontentsline{expc}{catc}
{\protect\numberline{\thechapter.\thecatc}#1}\par
}
\newcommand{\catd}[1]{%
\refstepcounter{catd}
\par\noindent\textbf{catd \thecatd. #1}
\addcontentsline{expd}{catd}
{\protect\numberline{\thechapter.\thecatd}#1}\par
}
\newcommand{\cat}[2]{%
\expandafter\newcommand\csname cat#1\endcsname{#2}%
}
\newcommand{\loopover}[2]{
\foreach \i in {#1}{
\cat\i{#2}}
}
\begin{document}
\tableofcontents
\newpage
\lista\newline
\listb\newline
\listc\newline
\listd\newline
\chapter{TestA}
\cat{a,b}{Test}
\end{document}
我想循环给{a,b}
定的列表\cat
,并调用相应的命令以添加{Test}
到该内容表中。
答案1
目前还不清楚为什么\cat<x>
每次都要重新定义:
\documentclass[10pt,a4paper]{article}
\usepackage{tikz} % \foreach
\newcommand{\cata}{Hello a\newline}
\newcommand{\catb}{Hello b\newline}
\newcommand{\catc}{Hello c\newline}
\newcommand{\catd}{Hello d\newline}
\newcommand{\loopover}[1]{%
\foreach \i in {#1}{\csname cat\i\endcsname}%
}
\begin{document}
\noindent
Hello World\\
\loopover{a, b, c, d}
\loopover{a, a, c}
\end{document}
一个简单的实现xparse
:
\documentclass[10pt,a4paper]{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\loopover}{m}
{
\clist_map_inline:nn { #1 } { \use:c { cat ##1 } }
}
\ExplSyntaxOff
\newcommand{\cata}{Hello a\newline}
\newcommand{\catb}{Hello b\newline}
\newcommand{\catc}{Hello c\newline}
\newcommand{\catd}{Hello d\newline}
\begin{document}
\noindent
Hello World\\
\loopover{a, b, c, d}
\loopover{a, a, c}
\end{document}
这具有几个优点\foreach
:例如,它会自动修剪逗号分隔列表中项目周围的空格,并且不会隐藏组中的循环周期。
这\clist_map_inline:nn
是循环制作功能\use:c
及其expl3
术语\csname...\endcsname
。
更新
更复杂的代码属于同一解决方案。只需定义
\newcommand{\loopover}[2]{%
\foreach \x in {#1}{\csname cat\x\endcsname{#2}}%
}
这没有问题:如果\x
是a
,则\cata
标记形成并且它会{#2}
像往常一样吸收参数。
答案2
不确定您的示例是否只是一个更复杂用例的示例。但就您的问题而言,您可以使用xparse
和description
环境。
输出
代码
\documentclass{article}
\usepackage{enumitem}
\usepackage{xparse}
\setlist[description]{itemsep=.3\baselineskip, font=\normalfont}
\NewDocumentCommand\mylist{>{\SplitList{,}}m}
{
\begin{description}
\ProcessList{#1}{ \insertl }
\end{description}
}
\newcommand\insertl[1]{\item[Hello] #1}
\begin{document}
\noindent
Hello world \par
\mylist{
a, b, c, d
}%
\end{document}