我有以下命令\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
答案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}