定义命令以定义星号命令

定义命令以定义星号命令

我有以下命令\defmeta,它定义了另外两个命令(一个带星号,一个不带星号)

\documentclass{article}
\usepackage{suffix}
\newcommand{\genericcmd}[3]{#1 #3 #2 }
\newcommand{\genericcmdstarred}[3]{ #1 starred, #3 #2}
\newcommand{\defmeta}[3]{
\expandafter\newcommand\csname #1\endcsname[1]{\genericcmd{#2}{#3}{##1}}
\WithSuffix\expandafter\newcommand\csname #1\endcsname *[1]{\genericcmdstarred{#2}{#3}{##1}}
}

\defmeta{mynewcommand}{Hello}{world}

\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}

这很完美。但是,我想知道是否有办法删除对 的依赖suffix?我不想使用该suffix包,因为我不想有不必要的依赖,并且作为一种学习更多 LaTeX 魔法的方式。

答案1

不依赖于包,只依赖于 LaTeX 内核。

\documentclass{article}

\newcommand{\genericcmd}[3]{#1 #3 #2}
\newcommand{\genericcmdstarred}[3]{#1 starred, #3 #2}

\makeatletter
\newcommand\metadef[3]{%
  \DeclareRobustCommand#1{%
    \@ifstar{\csname s\string#1\endcsname}{\csname n\string#1\endcsname}%
  }%
  \@namedef{s\string#1}##1{\genericcmdstarred{#2}{#3}{##1}}%
  \@namedef{n\string#1}##1{\genericcmd{#2}{#3}{##1}}%
}
\makeatother

\metadef{\mynewcommand}{Hello}{world}

\begin{document}

\mynewcommand{big}.

\mynewcommand*{big}.

\end{document}

在此处输入图片描述

也许更有趣的是无需定义\genericcmd和的定义\genericcmdstarred。该命令\metadef具有与相同的语法\newcommand(但没有*版本,可以通过一些技巧添加),但带有一个参数 more:

\metadef{<macro name>}[<args>]{<code for normal version>}{<code for starred version>}

不允许使用定义的宏的可选参数,请使用以下xparse基于代码来添加所需的任何参数列表。

\documentclass{article}

\makeatletter
\newcommand{\metadef}[1]{%
  \DeclareRobustCommand#1{%
    \@ifstar{\csname s\string#1\endcsname}{\csname n\string#1\endcsname}%
  }%
  \edef\meta@def@name{\string#1}%
  \meta@def
}
\newcommand\meta@def[3][0]{%
  \expandafter\newcommand\csname n\meta@def@name\endcsname[#1]{#2}%
  \expandafter\newcommand\csname s\meta@def@name\endcsname[#1]{#3}%
}
\makeatother

\metadef{\mynewcommand}[1]{Hello #1 world}{Hello starred, #1 world}

\begin{document}

\mynewcommand{big}.

\mynewcommand*{big}.

\end{document}

相同之处suffix

\documentclass{article}
\usepackage{suffix}

\makeatletter
\newcommand{\metadef}[1]{%
  \def\meta@def@name{#1}%
  \meta@def
}
\newcommand\meta@def[3][0]{%
  \expandafter\newcommand\meta@def@name[#1]{#2}%
  \WithSuffix\expandafter\newcommand\meta@def@name*[#1]{#3}%
}
\makeatother

\metadef{\mynewcommand}[1]{Hello #1 world}{Hello starred, #1 world}

\begin{document}

\mynewcommand{big}.

\mynewcommand*{big}.

\end{document}

与 相同xparse,您只需记住将参数数量移动一位,因为#1是可能的。当然,*“元定义”宏的参数必须以语法表达。xparse

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\metadef}{mmmm}{%
  \NewDocumentCommand{#1}{s#2}{%
    \IfBooleanTF{##1}{#4}{#3}%
  }%
}

\metadef{\mynewcommand}{m}{Hello #2 world}{Hello starred, #2 world}

\begin{document}

\mynewcommand{big}.

\mynewcommand*{big}.

\end{document}

答案2

我建议使用xparseLaTeX 3 项目开发人员工作的一部分。

下面模拟了问题中的代码,只是它消除了由无星号版本的命令引起的虚假空间。

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand \mynewcommand { s m }
{%
  Hello
  \IfBooleanT {#1}
  {%
    starred,
  }%
  #2 world%
}

\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}

星空世界

答案3

不依赖任何包,不依赖任何 LaTeX 内核:)。

\def\isnextchar#1#2#3{\toks0={#2}\toks1={#3}%
   \let\tmp=#1\futurelet\next\isnextcharA}
\def\isnextcharA{\the\toks\ifx\tmp\next0\else1\fi\space}

\def\metadef#1#2#3{\def#1{\isnextchar*{\metadefA{#3}}{\metadefB{#2}}}}
\def\metadefA#1*{\def\tmp##1{#1}\tmp}
\def\metadefB#1{\def\tmp##1{#1}\tmp}

\metadef \mynewcommand {Hello ##1 world} {Hello starred, ##1 world}

\mynewcommand{big}.

\mynewcommand*{big}.

答案4

这是一个没有任何包的版本,使用\@ifstar并依赖于移动参数,即#1命令序列没有真正的参数,但\@ifstar会查找*字符并分支到执行此版本或其他版本的相关命令。

\documentclass{article}

\newcommand{\genericcmdunstarred}[3]{#1 #3 #2 }
\newcommand{\genericcmdstarred}[3]{ #1 starred, #3 #2}
\makeatletter
\newcommand{\defmeta}[3]{%
  \expandafter\newcommand\csname #1\endcsname{%
    \@ifstar{%
      \genericcmdstarred{#2}{#3}%
    }{%
      \genericcmdunstarred{#2}{#3}%
    }%
  }%      
}

\defmeta{mynewcommand}{Hello}{world}

\defmeta{foo}{And now for something}{different}

\begin{document}
\mynewcommand{big}.

\mynewcommand*{big}.

\foo{completely}

\foo*{completely}

\end{document}

在此处输入图片描述

相关内容