我利用 def 定义了一个含有可选参数的自定义宏:
\makeatletter
\def\@dnode[#1]#2#3#4{\node(#2)at(#3){#4}}
\def\dnode{\@ifnextchar[{\@dnode}{\@dnode[inner sep=2pt,fill=yellow]}}
\makeatother
目的是在 tikz 中输入一个 node,它的默认可选参数是
inner sep=2pt,fill=yellow
但我发现虽然代码没有报错,但这个默认参数无效,而且整个可选选项都无效,就是我输入其他的可选参数也无效。
请问这是怎么回事?或者还可以通过什么方法自定义一个具有可选参数的自定义宏 def ?谢谢!
\def\@dnode[#1]#2#3#4{\node(#2)at(#3){#4};}
的问题,#1
没有传进去,改为\def\@dnode[#1]#2#3#4{\node[#1](#2)at(#3){#4};}
\newcommand
命令可以定义一个带可选参数的命令,此外可以看看 xparse
宏包,其基于 LaTeX3
更加灵活\makeatletter
\def\@dnode[#1]#2#3#4{\node[#1](#2)at(#3){#4};}
\def\dnode{\@ifnextchar[{\@dnode}{\@dnode[inner sep=2pt,fill=yellow]}}
\makeatother
\begin{tikzpicture}
\dnode{a}{1,2}{\LaTeX}
\dnode[draw,fill=red]{b}{3,2}{hello!}
\end{tikzpicture}
典型宏展开问题
报错信息如下
Package pgfkeys: I do not know the key '/tikz/\inns {2}' and I am going to ignore it. Perhaps you misspelled it.
也就是说 tikz
将 \inns{2}
(还没展开成 inner sep=2pt
) 当作了键值, 但是它无法识别,为此我们必须改变 \node
和 \inns
两个命令的展开顺序,做如下修改
\NewDocumentCommand
来定义要展开的命令,使用 \def
或者 \newcommand
\newcommand{\inns}[1]{inner sep=#1pt}
\expandafter\node\expandafter[\inns{2}](b)at(1,0){B};
mwe
\documentclass{article}
\usepackage{tikz}
\begin{document}
\NewDocumentCommand\tik{m}{
\begin{tikzpicture}
#1
\end{tikzpicture}
}
\newcommand{\inns}[1]{inner sep=#1pt}
\tik{
\node(a)at(0,0){A};
\expandafter\node\expandafter[\inns{2}](b)at(1,0){B};
\draw(a)--(b);
}
\end{document}
另外 \NewDocumentCommand
命令定义的命令是受保护的,但是 xparse 包也提供了 \NewExpandableDocumentCommand
,但经过测试失败,不知为何
谢谢您
您好,我尝试用了一下 xparse 宏包所提供的自定义宏,但发现在当一些宏嵌套时会出错,比如下面的情况
当我把宏inns 赋值为 2 然后嵌套到宏tik 中时会报错,请问这是怎么回事?
@u26254 已经更新答案
@u19850 谢谢,我试试
使用
\...ExpandableDocumentCommand
定义的,需要完全展开(\use:e
),而不是展开一次:\inns
的参数可能还需\unexpanded
(\exp_not:n
)保护,使其不被展开。@u10307 好的,谢谢