定义一个接受多个但参数总数不确定的命令

定义一个接受多个但参数总数不确定的命令

我在枚举项目中有相当规律和大量的描述。

\begin{enumerate}
\item Producers
  \begin{description}
    \item[ Vision: ] abc ... 
    \item[ Contribution:]  def ... 
    ...
  \end{description}
\end{enumerate}

我期望有一个可以myitem接受多个但参数总数不确定的命令,如下所示:

\begin{enumerate}
  \myitem{Producers}
    {Vision:}{abc ...}
    {Contribution:}{def ...}
    {...}{...}
    ...
\end{enumerate}

在这种情况下我该如何定义命令?

\renewcommand{myitem}{...}

答案1

对 cgnieder 的修改,也能够捕捉孤独者。

\documentclass{article}
\makeatletter
\newcommand\myitem[1]{%
  \item #1
  \@ifnextchar\bgroup{\begin{description}\@myitem@desc}{}
}
\newcommand{\@myitem@desc}[1]{%
  \item[#1]
  \@ifnextchar\bgroup{\@myitem@desc@item}{\@myitem@warning\end{description}}
}
\newcommand{\@myitem@desc@item}[1]{%
  #1
  \@ifnextchar\bgroup{\@myitem@desc}{\end{description}}
}
\newcommand\@myitem@warning{\@latex@warning{Lonely label without text}}
\makeatother
\begin{document}

\begin{enumerate}
  \myitem{Producers}
    {Vision:}{abc ...}
    {Contribution:}{def ...}
    {...}{...}
  \myitem{Example}
    {A}{a}
    {B}{b}
    {C}{c}
    {D}{d}
  \myitem{Example}
    {A loner}
  \myitem{Example}
    {A}{a}
\end{enumerate}

\end{document}

不过,我最好看到不同的语法:

\documentclass{article}
\newcommand{\myitem}[2]{%
  \item #1
  \begin{description}
  #2
  \end{description}
}
\newcommand{\II}[2]{%
  \item[#1] #2
}

\begin{document}

\begin{enumerate}
  \myitem{Producers}{
    \II{Vision:}{abc ...}
    \II{Contribution:}{def ...}
    \II{...}{...}
  }
  \myitem{Example}{
    \II{A}{a}
    \II{B}{b}
    \II{C}{c}
    \II{D}{d}
  }
  \myitem{Example}{
    \II{A}{a}
  }
\end{enumerate}

\end{document}

输入起来并没有那么困难,而且肯定更干净、更结构化。

答案2

(编辑) 2017:因为xint 1.1 (2014/10/28)这里需要\usepackage{xinttools}。代码已更新,以替换\usepackage{xint}初始答案。

这段代码很短,但不适合胆小的人(1)\xintApplyUnbraced. 其关键工具是来自包的命令信特它将给定的宏应用于此类支撑事物列表的每个连续支撑事物,例如{stuff}{more}{yet}{other}

(1) 但编辑过的版本更简单更好。

这里的唯一作用\xintApplyUnbraced是在各处插入\myitemhelpera命令;并且这个宏被定义(感谢TeX分隔宏)来2个2个地获取数据,生成一个具有标题和描述内容的描述项。

\documentclass{article}
\usepackage{xinttools}

% The space in \myitemhelper will be swallowed during
% the action of \xintApplyUnbraced, and prevents further
% expansion (at a too premature time)

% edited. This is simpler and moreover allows use of [ and ] in the 
% contents of the description texts
\def\myitemhelper #1{ \myitemhelpera {#1}}
\def\myitemhelpera #1\myitemhelpera #2{\item [#1]#2}

% earlier, more complicated and less efficient method:
% \def\myitemhelper #1{ \myitemhelpera[#1]}
% \def\myitemhelpera {\let\myitemhelpera\myitemhelperb \item}
% \def\myitemhelperb [#1]{#1\let\myitemhelpera\myitemhelperA}
% \let\myitemhelperA\myitemhelpera


% \xintApplyUnbraced just has the effect here to insert
%  \myitemhelpera in-between all the braced pairs

\newcommand{\myitem}[2]{\item #1
  \begin{description}
  \xintApplyUnbraced\myitemhelper {#2}
  \end{description}}

\begin{document}
\begin{enumerate}
\myitem{Producers}{% This percent sign is optional
    {Vision:}{abc ...}
    {Contribution:}{def ...}
    {Anticipation:}{g[h]k ...}
    {Participation:}{lmn ...}
    {Conclusion:}{not [yet].}% This percent sign is optional
  }
    \myitem{Example}{%
    {A}{a}
    {B}{b}
    {C}{c}
    {D}{d}%
  }
  \myitem{Example}{%
    {A}{a}%
  }
 \end{enumerate}
\end{document}

参数的可变数目

答案3

没有保证,但这适用于问题中概述的语法:

\documentclass{article}
\makeatletter
% place \item and check if a description follows:
\newcommand\myitem[1]{%
  \item #1\@myitem@check@description
}
% if an opening brace follows start description:
\def\@myitem@check@description{%
  \@ifnextchar\bgroup
    {\@myitem@startdescription}
    {}%
}
% start description environment, place the first item
% and see if another item follows:
\def\@myitem@startdescription#1#2{%
  \begin{description}%
  \item[#1] #2%
  \@myitem@check@description@item
}
% end description environment:
\def\@myitem@enddescription{%
  \end{description}%
}
% if an item follows place it and check if there is
% another one; else end the description
\def\@myitem@check@description@item{%
  \@ifnextchar\bgroup
    {\@myitem@description@item}
    {\@myitem@enddescription}%
}
% place item and check for the next one:
\def\@myitem@description@item#1#2{%
  \item[#1] #2%
  \@myitem@check@description@item
}

\makeatother
\begin{document}

\begin{enumerate}
  \myitem{Producers}
    {Vision:}{abc ...}
    {Contribution:}{def ...}
    {...}{...}
  \myitem{Example}
    {A}{a}
    {B}{b}
    {C}{c}
    {D}{d}
  \myitem{Example}
  \myitem{Example}
    {A}{a}
\end{enumerate}

\end{document}

在此处输入图片描述

答案4

readarray包有一个\getargsC宏,它从空格分隔的列表中获取每个项目,并将它们放入\argi、、等\argii\argiii,并将参数总数放入\narg。这可以用来解决您的问题。

编辑后\myitem有两个参数,第一个是enumerate项目,其余是description项目。

\documentclass{article}
\usepackage{readarray}
\usepackage{ifthen}
\newcounter{index}
\newcommand\myitem[2]{%
  \getargsC{#2}%
  \setcounter{index}{0}%
  \begin{enumerate}%
    \item #1%
    \begin{description}%
    \whiledo{\theindex<\narg}{%
      \stepcounter{index}%
      \item[\csname arg\roman{index}\endcsname]%
      \stepcounter{index}%
      \csname arg\roman{index}\endcsname%
    }%
    \end{description}%
  \end{enumerate}%
}
\begin{document}
\myitem{Producers}{{Vision:} {abc...} {Contribution:} {def} {...} {...}}
\end{document}

在此处输入图片描述

相关内容