如何创建枚举的本地命令

如何创建枚举的本地命令

我有一个自定义环境,用于在多个环境中重新创建特定布局,格式化可变数量的文本条目enumerate。到目前为止,我已经将多个名称相似的命令定义为可以在环境内设置的令牌,但我当前的方法需要大量\ithenelse开关,并且可扩展性不是很好。

\newcommand{\setName}[2][]{\ifthenelse{\equal{#1}{}}{\renewcommand{\tokenName}{#2}}{\renewcommand{\tokenName}{#2 1--#1}}}
\newcommand{\setEffect}[2][]{
    \ifthenelse{\equal{#1}{}}{\renewcommand{\tokenEffect}{\item[] #2}}{}
    \ifthenelse{\equal{#1}{1}}{\renewcommand{\tokenEffectI}{\item #2}}{}
    \ifthenelse{\equal{#1}{2}}{\renewcommand{\tokenEffectII}{\item #2}}{}
    \ifthenelse{\equal{#1}{3}}{\renewcommand{\tokenEffectIII}{\item #2}}{}
    \ifthenelse{\equal{#1}{X}}{\renewcommand{\tokenEffectX}{\item[each:] #2}}{}
}
\newcommand{\setRequirement}[2][]{
    \ifthenelse{\equal{#1}{}}{\renewcommand{\tokenEffect}{\item[] #2}}{}
    \ifthenelse{\equal{#1}{1}}{\renewcommand{\tokenRequirement}{\item #2}}{}
    \ifthenelse{\equal{#1}{2}}{\renewcommand{\tokenRequirementI}{\item #2}}{}
    \ifthenelse{\equal{#1}{3}}{\renewcommand{\tokenRequirementII}{\item #2}}{}
    \ifthenelse{\equal{#1}{X}}{\renewcommand{\tokenRequirementIII}{\item #2}}{}
}

\newenvironment{Description}{
    \newcommand{\tokenName}{}
    \newcommand{\tokenEffect}{}
    \newcommand{\tokenEffectI}{}
    \newcommand{\tokenEffectII}{}
    \newcommand{\tokenEffectIII}{}
    \newcommand{\tokenEffectX}{}

    \newcommand{\tokenRequirement}{}
    \newcommand{\tokenRequirementI}{}
    \newcommand{\tokenRequirementII}{}
    \newcommand{\tokenRequirementIII}{}
}{
    \section{\tokenName}
    \paragraph{Effects}
    \begin{enumerate}
        \tokenEffect
        \tokenEffectX
        \tokenEffectI
        \tokenEffectII
        \tokenEffectIII
    \end{enumerate}

    \paragraph{Requirements}
    \begin{enumerate}
        \tokenRequirement
        \tokenRequirementI
        \tokenRequirementII
        \tokenRequirementIII
    \end{enumerate} 
}

有没有更高效、更灵活的方法来替换 token 命令系统?我试过,xsavebox但无法让它与 savebox 名称中的参数一起正常工作。

答案1

我想你想要类似的东西

\makeatletter
\newcommand{\setEffect}[2][]{%
    \ifx\relax#1\relax
      \def\tokenEffect{\item[] #2}%
    \else\ifx X#1\relax
       \def\tokenEffectX{\item[each:] #2}%
    \else
       \expandafter\def\csname tokenEffect\@Roman{#1}\endcsname{\item #2}%
    \fi\fi}

答案2

您可以使用很多方法来定义和调用名称中也包含数字和/或空格和/或类似内容的宏 - 我在讨论中\name详细阐述了宏\name定义控制序列,之后留有空格

也许这样的东西适合您的需要?:

%%----------------------------------------------------------------------
%% \name{macro} -> \macro
%% \name\string{macro} -> \string\macro
%% \name\newcommand{macro}... -> \newcommand\macro...
%% (Instead of "macro" you can also use phrases that contain digits
%%  and/or spaces and/or the like.)
%%......................................................................
\newcommand\name{}%
\long\def\name#1#{\romannumeral0\innername{#1}}%
\newcommand\innername[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\newcommand\exchange[2]{#2#1}%
%%......................................................................
\newcommand\CheckWhetherUndefined{}%
\name\global\let\CheckWhetherUndefined={@ifundefined}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \CheckWhetherNull{<Argument which is to be checked>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is empty>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\firstoftwo[2]{#1}%
\newcommand\secondoftwo[2]{#2}%
\newcommand\CheckWhetherNull[1]{%
  \romannumeral0\expandafter\secondoftwo\string{\expandafter\secondoftwo
  \expandafter{\expandafter{\string#1}\expandafter\secondoftwo\string}%
  \expandafter\firstoftwo\expandafter{\expandafter\secondoftwo\string}%
  \expandafter\expandafter\firstoftwo{ }{}\secondoftwo}{\expandafter
  \expandafter\firstoftwo{ }{}\firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Maintaining local commands:
%%......................................................................
\newcommand\genericSet[1]{%
  \name\name{\CheckWhetherUndefined{#1}{}{re}newcommand}*{#1}%
}%
\newcommand{\setName}[2][]{%
  \CheckWhetherNull{#1}{\genericSet{tokenName}{#2}}{\genericSet{tokenName}{#2 1--#1}}%
  \ignorespaces
}%
\newcommand{\setEffect}[2][]{\genericSet{tokenEffect#1}{#2}\ignorespaces}%
\newcommand{\setRequirement}[2][]{\genericSet{tokenRequirement#1}{#2}\ignorespaces}%
% You must never define \UnDeFInED  ;-)
\newenvironment{Description}{\let\tokenName=\UnDeFInED\ignorespaces}{%
  \section{\tokenName}% <- This way you will get an undefined 
                      %    control-sequence-error in case of not 
                      %    having called \setName from within the environment.
  \paragraph{Effects}%
  \begin{enumerate}% At least one of the following should be defined!
    \CheckWhetherUndefined{tokenEffect}{}{\item[]\name{tokenEffect}}%
    \CheckWhetherUndefined{tokenEffectX}{}{\item[each:]\name{tokenEffectX}}%
    \CheckWhetherUndefined{tokenEffect1}{}{\item\name{tokenEffect1}}%
    \CheckWhetherUndefined{tokenEffect2}{}{\item\name{tokenEffect2}}%
    \CheckWhetherUndefined{tokenEffect3}{}{\item\name{tokenEffect3}}%
  \end{enumerate}%
  \paragraph{Requirements}%
  \begin{enumerate}% At least one of the following should be defined!
    \CheckWhetherUndefined{tokenRequirement}{}{\item[]\name{tokenRequirement}}%
    \CheckWhetherUndefined{tokenRequirement1}{}{\item\name{tokenRequirement1}}%
    \CheckWhetherUndefined{tokenRequirement2}{}{\item\name{tokenRequirement2}}%
    \CheckWhetherUndefined{tokenRequirement3}{}{\item\name{tokenRequirement3}}%
  \end{enumerate}%
}%

%% Usage:
% \begin{Description}
%   \setName[foo]{Bar}%
%   \setEffect{Token Effect}%
%   \setEffect[1]{Token Effect 1}%
%   \setEffect[2]{Token Effect 2}%
%   \setEffect[3]{Token Effect 3}%
%   \setEffect[X]{Token Effect X}%
%   \setRequirement{Token Requirement}%
%   \setRequirement[1]{Token Requirement 1}%
%   \setRequirement[2]{Token Requirement 2}%
%   \setRequirement[3]{Token Requirement 3}%
% \end{Description}

此外,仅当存在以下项目时,才可以添加\if..-switch 来启动和结束枚举环境:

%%----------------------------------------------------------------------
%% \name{macro} -> \macro
%% \name\string{macro} -> \string\macro
%% \name\newcommand{macro}... -> \newcommand\macro...
%% (Instead of "macro" you can also use phrases that contain digits
%%  and/or spaces and/or the like.)
%%......................................................................
\newcommand\name{}%
\long\def\name#1#{\romannumeral0\innername{#1}}%
\newcommand\innername[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\newcommand\exchange[2]{#2#1}%
%%......................................................................
\newcommand\CheckWhetherUndefined{}%
\name\global\let\CheckWhetherUndefined={@ifundefined}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \CheckWhetherNull{<Argument which is to be checked>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is empty>}%
%%                  {<Tokens to be delivered in case that argument
%%                    which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\firstoftwo[2]{#1}%
\newcommand\secondoftwo[2]{#2}%
\newcommand\CheckWhetherNull[1]{%
  \romannumeral0\expandafter\secondoftwo\string{\expandafter\secondoftwo
  \expandafter{\expandafter{\string#1}\expandafter\secondoftwo\string}%
  \expandafter\firstoftwo\expandafter{\expandafter\secondoftwo\string}%
  \expandafter\expandafter\firstoftwo{ }{}\secondoftwo}{\expandafter
  \expandafter\firstoftwo{ }{}\firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Starting and ending enumerate-environment:
%%......................................................................
\newif\ifThereAlreadyIsAnItem\ThereAlreadyIsAnItemfalse
\newcommand\ProbablyStartEnumerate[1]{%
  \ifThereAlreadyIsAnItem\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {}{\ThereAlreadyIsAnItemtrue#1\begin{enumerate}}%
}%
\newcommand\ProbablyStopEnumerate{%
  \ifThereAlreadyIsAnItem\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {\end{enumerate}\ThereAlreadyIsAnItemfalse}{}%
}%
%%----------------------------------------------------------------------
%% Maintaining local commands:
%%......................................................................
\newcommand\genericSet[1]{%
  \name\name{\CheckWhetherUndefined{#1}{}{re}newcommand}*{#1}%
}%
\newcommand{\setName}[2][]{%
  \CheckWhetherNull{#1}{\genericSet{tokenName}{#2}}{\genericSet{tokenName}{#2 1--#1}}%
  \ignorespaces
}%
\newcommand{\setEffect}[2][]{\genericSet{tokenEffect#1}{#2}\ignorespaces}%
\newcommand{\setRequirement}[2][]{\genericSet{tokenRequirement#1}{#2}\ignorespaces}%
% You must never define \UnDeFInED  ;-)
\newenvironment{Description}{%
  \ThereAlreadyIsAnItemfalse
  \let\tokenName=\UnDeFInED
  \ignorespaces
}{%
  \section{\tokenName}% <- This way you will get an undefined 
                      %    control-sequence-error in case of not 
                      %    having called \setName from within the environment.
  \CheckWhetherUndefined{tokenEffect}{}{\ProbablyStartEnumerate{\paragraph{Effects}}\item[]\name{tokenEffect}}%
  \CheckWhetherUndefined{tokenEffectX}{}{\ProbablyStartEnumerate{\paragraph{Effects}}\item[each:]\name{tokenEffectX}}%
  \CheckWhetherUndefined{tokenEffect1}{}{\ProbablyStartEnumerate{\paragraph{Effects}}\item\name{tokenEffect1}}%
  \CheckWhetherUndefined{tokenEffect2}{}{\ProbablyStartEnumerate{\paragraph{Effects}}\item\name{tokenEffect2}}%
  \CheckWhetherUndefined{tokenEffect3}{}{\ProbablyStartEnumerate{\paragraph{Effects}}\item\name{tokenEffect3}}%
  \ProbablyStopEnumerate
  \CheckWhetherUndefined{tokenRequirement}{}{\ProbablyStartEnumerate{\paragraph{Requirements}}\item[]\name{tokenRequirement}}%
  \CheckWhetherUndefined{tokenRequirement1}{}{\ProbablyStartEnumerate{\paragraph{Requirements}}\item\name{tokenRequirement1}}%
  \CheckWhetherUndefined{tokenRequirement2}{}{\ProbablyStartEnumerate{\paragraph{Requirements}}\item\name{tokenRequirement2}}%
  \CheckWhetherUndefined{tokenRequirement3}{}{\ProbablyStartEnumerate{\paragraph{Requirements}}\item\name{tokenRequirement3}}%
  \ProbablyStopEnumerate
}%

%% Usage:
% \begin{Description}
%   \setName[foo]{Bar}%
%   \setEffect{Token Effect}%
%   \setEffect[1]{Token Effect 1}%
%   \setEffect[2]{Token Effect 2}%
%   \setEffect[3]{Token Effect 3}%
%   \setEffect[X]{Token Effect X}%
%   \setRequirement{Token Requirement}%
%   \setRequirement[1]{Token Requirement 1}%
%   \setRequirement[2]{Token Requirement 2}%
%   \setRequirement[3]{Token Requirement 3}%
% \end{Description}

答案3

这是可扩展的(最多可提供 100 种效果和要求)。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\prop_new:N \l_lossner_token_prop
\tl_new:N \l_lossner_token_name_tl

\NewDocumentCommand{\setName}{om}
 {
  \IfNoValueTF { #1 }
   {
    \tl_set:Nn \l_lossner_token_name_tl { #2 }
   }
   {
    \tl_set:Nn \l_lossner_token_name_tl { #2 ~ 1--#1 }
   }
 }
\NewDocumentCommand{\setEffect}{om}
 {
  \IfNoValueTF { #1 }
   {
    \prop_put:Nnn \l_lossner_token_prop { effect@ } { \item[] #2 }
   }
   {
    \str_if_eq:nnTF { #1 } { X }
     {
      \prop_put:Nnn \l_lossner_token_prop { effect@#1 } { \item[each:] #2 }
     }
     {
      \prop_put:Nnn \l_lossner_token_prop { effect@#1 } { \item #2 }
     }
   }
 }
\NewDocumentCommand{\setRequirement}{om}
 {
  \IfNoValueTF { #1 }
   {
    \prop_put:Nnn \l_lossner_token_prop { effect@ } { \item[] #2 }
   }
   {
    \prop_put:Nnn \l_lossner_token_prop { requirement@#1 } { \item #2 }
   }
 }

\NewDocumentEnvironment{Description}{}
 {}
 {
\prop_show:N \l_lossner_token_prop
  \section{\l_lossner_token_name_tl}
  \paragraph{Effects}
  \begin{enumerate}
    \lossner_token:nn {effect}{}
    \lossner_token:nn {effect}{X}
    \int_step_inline:nn {100}
     {
      \lossner_token:nn {effect}{##1}
     }
  \end{enumerate}

  \paragraph{Requirements}
    \begin{enumerate}
    \lossner_token:nn {requirement}{X}
    \int_step_inline:nn {100}
     {
      \lossner_token:nn {requirement}{##1}
     }
    \end{enumerate} 
 }

\cs_new_protected:Nn \lossner_token:nn
 {
  \prop_item:Nn \l_lossner_token_prop { #1@#2 }
 }

\ExplSyntaxOff

\begin{document}

\begin{Description}
\setName{abc}
\setEffect{Main}
\setEffect[1]{Wow}
\setRequirement[3]{Whatever}
\end{Description}

\begin{Description}
\setName[A]{abc}
\setEffect{Wow}
\setEffect[X]{Plus}
\setRequirement[1]{Whatever}
\setRequirement[2]{Whatever}
\setRequirement[3]{Whatever}
\setRequirement[4]{Whatever}
\setRequirement[5]{Whatever}
\setRequirement[6]{Whatever}
\setRequirement[7]{Whatever}
\setRequirement[8]{Whatever}
\setRequirement[9]{Whatever}
\end{Description}

\end{document}

在此处输入图片描述

相关内容