我正在尝试将其收集到一个名为“调用 TikZ 的\drawtasks
一系列\drawtask
命令”的命令中。每次我调用时\wptask
,该命令都应增加一个计数器,并将当前值计数器附加到\drawtasks
对的调用中\drawtask
。不幸的是,当我最终调用时\drawtasks
,我总是得到最后一个计数器值。我已经尝试过此处类似问题中提出的解决方案(例如,这里,但它就是不起作用:似乎我的问题不同,因为我想附加对另一个不应扩展的命令的调用。以下是一个例子:
\documentclass{article}
\usepackage{tikz}
\newcommand{\drawtask}[4]{
\node[anchor=west] at (-2,-0.5 * #1 - 0.25) {Task #2} ;
\filldraw[fill=green!20,draw=green!50!black] (#3 / 3,-0.5 * #1 - 0.15) rectangle (#4 / 3,-0.5 * #1 - 0.35) ;
}
\newcounter{wptaskcounter}
\setcounter{wptaskcounter}{0}
\newcommand{\drawtasks}{}
\makeatletter
\newcommand{\appendwptask}[4]{%
\protected@edef\@tempa{#1}%
\expandafter\g@addto@macro\expandafter\drawtasks\expandafter{%
\drawtask{\@tempa}{#2}{#3}{#4}%
}%
}
\makeatother
\newcommand{\wptask}[3]{%
\appendwptask{\thewptaskcounter}{#1}{#2}{#3}%
\stepcounter{wptaskcounter}%
}
\wptask{1.1}{0}{3}
\wptask{1.2}{3}{6}
\wptask{1.3}{6}{9}
\begin{document}
\begin{tikzpicture}
\drawtasks
\end{tikzpicture}
\end{document}
我对 LaTeX 的扩展规则感到很困惑,非常希望得到一些帮助!提前致谢。
答案1
根据 egreg 对您在问题中链接的答案的评论,您可以这样做。
我总是读到\expandafter<token 1><token 2>
这样的意思<token 1>
扩展后再返回并扩展<token 2>
即,在紧接着的事物之后扩展下一个事物。
然而,这似乎意味着展开<token 2>
下一步然后返回<token 1>
即,在下一个事物之后扩展该事物。
在这种情况下,您希望TeX在查看 之后才\drawtasks
考虑。因此您可以尝试\drawtask
\@tempa
\expandafter\drawtask\expandafter{\@tempa ...
意思是只有在扩展之后才查看(只有在扩展之后才\drawtask
查看)。\{
\@tempa
……呃,我想是的。然而,我几乎肯定是错的。
尽管如此,
\newcommand{\appendwptask}[4]{%
\protected@edef\@tempa{#1}%
\expandafter\g@addto@macro\expandafter\drawtasks\expandafter{%
\expandafter\drawtask\expandafter{\@tempa}{#2}{#3}{#4}%
}%
}
我觉得这似乎有效。
\documentclass{article}
\usepackage{tikz}
\newcommand{\drawtask}[4]{
\node[anchor=west] at (-2,-0.5 * #1 - 0.25) {Task #2} ;
\filldraw[fill=green!20,draw=green!50!black] (#3 / 3,-0.5 * #1 - 0.15) rectangle (#4 / 3,-0.5 * #1 - 0.35) ;
}
\newcounter{wptaskcounter}
\setcounter{wptaskcounter}{0}
\newcommand{\drawtasks}{}
\makeatletter
\newcommand{\appendwptask}[4]{%
\protected@edef\@tempa{#1}%
\expandafter\g@addto@macro\expandafter\drawtasks\expandafter{%
\expandafter\drawtask\expandafter{\@tempa}{#2}{#3}{#4}%
}%
}
\makeatother
\newcommand{\wptask}[3]{%
\appendwptask{\thewptaskcounter}{#1}{#2}{#3}%
\stepcounter{wptaskcounter}%
}
\wptask{1.1}{0}{3}
\wptask{1.2}{3}{6}
\wptask{1.3}{6}{9}
\begin{document}
\begin{tikzpicture}
\drawtasks
\end{tikzpicture}
\end{document}
答案2
我不会这样做,而是\wptask
生成一个逗号分隔的列表,然后\drawtasks
使用循环遍历列表tikz/pgf的\foreach
命令。
通过这种方式,你的 MWE 会产生:
代码如下:
\documentclass{article}
\usepackage{tikz}
\let\wptasklist\relax% will become a comma separate list of the task parameters
\newcommand{\wptask}[3]{% \addtask might be a better name:)
\ifx\wptasklist\relax\def\wptasklist{#1/#2/#3}% first task
\else\xdef\wptasklist{\wptasklist,#1/#2/#3}% add a task
\fi%
}
\newcommand\drawtasks{% loop over \wptasklist and draw the tasks
\begin{tikzpicture}
\foreach \a/\b/\c [count=\n] in \wptasklist {% loop over task list
\node[anchor=west] at (-2,-0.5 * \n - 0.25) {Task \a};
\filldraw[fill=green!20,draw=green!50!black]
(\b/3,-0.5*\n-0.15) rectangle (\c/3,-0.5*\n-0.35);
}
\end{tikzpicture}
}
\wptask{1.1}{0}{3}
\wptask{1.2}{3}{6}
\wptask{1.3}{6}{9}
\begin{document}
\drawtasks
\end{document}
希望代码相当清晰易懂。请注意,除了使用\xdef
添加到任务列表之外,没有扩展问题,并且不需要计数器,因为您可以将其用作循环[count=\n]
的一部分\foreach
来确定“任务编号”。
有一个警告,它似乎不适用于您的用例:任何包含\wptask
斜杠的参数/
都需要放在括号内{.../...}
。
编辑
这是第二个更接近 OP 的 MWE 的解决方案。它使用\eappto
了电子工具箱\appendwptask
包,它是问题中宏的强大且通用的实现,以及\noexpand
。至少对我来说,这提供了一种更直观的方式来应对这些扩展问题。输出与上面相同。
\documentclass{article}
\usepackage{etoolbox}
\usepackage{tikz}
\newcommand{\drawtask}[4]{
\node[anchor=west] at (-2,-0.5 * #1 - 0.25) {Task #2} ;
\filldraw[fill=green!20,draw=green!50!black] (#3 / 3,-0.5 * #1 - 0.15) rectangle (#4 / 3,-0.5 * #1 - 0.35) ;
}
\newcounter{wptaskcounter}% set to 0 by default
\newcommand{\drawtasks}{}
\newcommand{\wptask}[3]{%
\eappto\drawtasks{\noexpand\drawtask{\thewptaskcounter}{#1}{#2}{#3}}% append to \drawtasks
\stepcounter{wptaskcounter}%
}
\wptask{1.1}{0}{3}
\wptask{1.2}{3}{6}
\wptask{1.3}{6}{9}
\begin{document}
\begin{tikzpicture}
\drawtasks
\end{tikzpicture}
\end{document}
如果你想“积累很多东西”,那么使用像这样的 key-val 系统鍵盤可能是更好的选择...嗯,除了最初的学习曲线:)
答案3
您可以使用\unexpanded
:
\documentclass{article}
\usepackage{tikz}
\providecommand{\expandonce}[1]{%
\unexpanded\expandafter{#1}%
} % etoolbox already provides this
\newcommand{\drawtask}[4]{
\node[anchor=west] at (-2,-0.5 * #1 - 0.25) {Task #2} ;
\filldraw[fill=green!20,draw=green!50!black]
(#3 / 3,-0.5 * #1 - 0.15) rectangle (#4 / 3,-0.5 * #1 - 0.35) ;
}
\newcounter{wptaskcounter}
\setcounter{wptaskcounter}{0}
\newcommand{\drawtasks}{}
\newcommand{\appendwptask}[4]{%
\edef\drawtasks{%
\expandonce{\drawtasks}%
\expandonce{\drawtask{#1}{#2}{#3}{#4}}%
}%
}
\newcommand{\wptask}[3]{%
\expandafter\appendwptask\expandafter{\the\value{wptaskcounter}}{#1}{#2}{#3}%
\stepcounter{wptaskcounter}%
}
\wptask{1.1}{0}{3}
\wptask{1.2}{3}{6}
\wptask{1.3}{6}{9}
\begin{document}
\begin{tikzpicture}
\drawtasks
\end{tikzpicture}
\end{document}
这样,\expandonce{\drawtasks}
只会扩展一次\drawtasks
,从而获取其先前的值;同样,\expandonce{\drawtask{...}{...}{...}{...}}
将执行 的第一级扩展\drawtask
,留下替换文本(将参数替换为参数)。您还需要扩展计数器的值。
expl3
通过使用(通过xparse
接口)可以获得更简洁的版本:
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\newcommand{\drawtask}[4]{
\node[anchor=west] at (-2,-0.5 * #1 - 0.25) {Task #2} ;
\filldraw[fill=green!20,draw=green!50!black]
(#3 / 3,-0.5 * #1 - 0.15) rectangle (#4 / 3,-0.5 * #1 - 0.35) ;
}
\ExplSyntaxOn
\tl_new:N \g_boris_drawtasks_tl
\int_new:N \g_boris_wptask_int
\NewDocumentCommand{\drawtasks}{}
{
\tl_use:N \g_boris_drawtasks_tl
}
\NewDocumentCommand{\wptask}{mmm}
{
\boris_append_wptask:fnnn
{ \int_to_arabic:n { \g_boris_wptask_int } }
{ #1 }
{ #2 }
{ #3 }
\int_gincr:N \g_boris_wptask_int
}
\cs_new_protected:Nn \boris_append_wptask:nnnn
{
\tl_gput_right:No \g_boris_drawtasks_tl
{
\drawtask{#1}{#2}{#3}{#4}
}
}
\cs_generate_variant:Nn \boris_append_wptask:nnnn { f }
\ExplSyntaxOff
\wptask{1.1}{0}{3}
\wptask{1.2}{3}{6}
\wptask{1.3}{6}{9}
\begin{document}
\begin{tikzpicture}
\drawtasks
\end{tikzpicture}
\end{document}
f
我们通过定义变量(完全扩展)来获取计数器值的扩展版本。