问题的答案很可能就埋藏在该站点的某个地方——我对宏扩展的理解有限,这似乎阻碍了我的搜索……
我正在尝试定义可以像这样使用的宏:
\begin{document}
\AimTaskDef{1}{task 1}
\AimTaskAdd{1}{task 2}
\AimTaskDef{2}{task 3}
\AimTaskAdd{2}{task 4}
...
% later, in some table
\AimTaskGet{1}
\AimTaskGet{2}
这将导致如下输出
\begin{itemize}
\item task 1
\item task 2
\end{itemize}
\begin{itemize}
\item task 3
\item task 4
\end{itemize}
我已设置以下宏:
\def\AimTaskDef#1#2{%
\expandafter\def\csname AimTask#1\endcsname{ \item #2}
}
\def\AimTaskAdd#1#2{%
\expandafter\def\tmp{\expandafter\csname AimTask#1\endcsname}
\expandafter\def\csname AimTask#1\endcsname{ \tmp \item #2}
}
\def\AimTaskGet#1{ \begin{itemize} \csname AimTask#1\endcsname \end{itemize} }
我对“tmp”的定义/使用存在错误,因为我看到以下错误:
\AimTaskAdd #1#2->\expandafter \def \tmp
{\expandafter \csname AimTask#1\end...
l.28 \AimTaskAdd{1}{task 2}
?
! Missing control sequence inserted.
<inserted text>
\inaccessible
l.28 \AimTaskAdd{1}{task 2}
?
结果仅包含最后指定的任务。如果您能对 \tmp 发生了什么有任何见解,我将不胜感激。
非常感谢,安德烈。
答案1
下面的操作可以实现你想要的效果(但需要 e-TeX;也可以修改为不使用 e-TeX 也可以工作):
\documentclass{article}
\makeatletter
\def\AimTaskDef#1#2{%
\expandafter\def\csname AimTask#1\endcsname{ \item #2}%
}
\def\AimTaskAdd#1#2{%
\ifcsname AimTask#1\endcsname
% Check for repeated entries (AM):
\@expandtwoargs\in@
{\detokenize{\item #2}}
{\detokenize\expandafter\expandafter\expandafter{\csname AimTask#1\endcsname}}%
\ifin@\else
\expandafter\g@addto@macro\csname AimTask#1\endcsname{\item #2}%
\fi
\else
\AimTaskDef{#1}{#2}%
\fi%
}
\def\AimTaskGet#1{\begin{itemize}\csname AimTask#1\endcsname\end{itemize}}
\makeatother
\begin{document}
Explicit definition:
\begin{itemize}
\item task 1
\item task 2
\end{itemize}
\begin{itemize}
\item task 3
\item task 4
\end{itemize}
\ldots
Macro definition:
\AimTaskAdd{1}{task 1}
\AimTaskAdd{1}{task 2}
\AimTaskDef{2}{task 3}
\AimTaskAdd{2}{task 4}
\AimTaskAdd{2}{task 4} % Repeated (AM)
\AimTaskGet{1}
\AimTaskGet{2}
\end{document}
为了将内容附加到现有宏,使用 就足够了\g@addto@macro{<macro>}{<stuff>}
。此外,我已更新\AimTaskAdd
为检查 是否存在AimTask#1
,如果不存在则创建它。这样您就可以这样做
\AimTaskAdd{1}{task 1}
\AimTaskAdd{1}{task 2}
而不必担心AimTask1
已经存在(我也在我的例子中使用了这一点作为说明)。
答案2
具有设施的实施expl3
。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\AimTaskDef}{ m m }{ \andre_task_def:nn { #1 } { #2 } }
\NewDocumentCommand{\AimTaskAdd}{ m m }{ \andre_task_add:nn { #1 } { #2 } }
\NewDocumentCommand{\AimTaskGet}{ m }
{
\begin{itemize} \prop_get:Nn \g_andre_tasks_prop { #1 } \end{itemize}
}
\prop_new:N \g_andre_tasks_prop
\msg_new:nnn { andre } { task-exist }
{
Task~#1~already~exists:~I'm~overwriting~it
}
\msg_new:nnn { andre } { task-not-exist }
{
Task~#1~doesn't~exist~yet:~I'm~defining~it
}
\cs_new_protected:Npn \andre_task_def:nn #1 #2
{
\prop_if_in:NnT \g_andre_tasks_prop { #1 }
{
\msg_warning:nnx { andre } { task-exist } { #1 }
}
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
\cs_new_protected:Npn \andre_task_add:nn #1 #2
{
\prop_if_in:NnTF \g_andre_tasks_prop { #1 }
{
\prop_gput:Nnx \g_andre_tasks_prop { #1 }
{
\prop_get:Nn \g_andre_tasks_prop { #1 } \exp_not:n { \item #2 }
}
}
{
\msg_warning:nnx { andre } { task-not-exist } { #1 }
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
}
\ExplSyntaxOff
\begin{document}
\AimTaskDef{1}{task 1}
\AimTaskAdd{1}{task 2}
\AimTaskDef{2}{task 3}
\AimTaskAdd{2}{task 4}
\AimTaskGet{1}
\AimTaskGet{2}
\AimTaskDef{1}{task 1}
\AimTaskAdd{3}{task !}
\end{document}
如果宏\AimTaskDef
用于已定义的任务,则会发出警告,在这种情况下,会覆盖它(这可以更改);如果宏\AimTaskAdd
用于尚未定义的任务,它们也会发出警告(并定义它)。
一个可能更有效的版本(感谢 Bruno Le Floch):
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\AimTaskDef}{ m m }{ \andre_task_def:nn { #1 } { #2 } }
\NewDocumentCommand{\AimTaskAdd}{ m m }{ \andre_task_add:nn { #1 } { #2 } }
\NewDocumentCommand{\AimTaskGet}{ m }
{
\begin{itemize} \prop_get:Nn \g_andre_tasks_prop { #1 } \end{itemize}
}
% Variables
\prop_new:N \g_andre_tasks_prop
\tl_new:N \l_andre_temp_tl
% Messages
\msg_new:nnn { andre } { task-exists }
{
Task~#1~already~exists:~I'm~overwriting~it
}
\msg_new:nnn { andre } { task-exists-not }
{
Task~#1~doesn't~exist~yet:~I'm~defining~it
}
% Functions
\cs_new_protected:Npn \andre_task_def:nn #1 #2
{
\prop_if_in:NnT \g_andre_tasks_prop { #1 }
{
\msg_warning:nnx { andre } { task-exists } { #1 }
}
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
\cs_new_protected:Npn \andre_task_add:nn #1 #2
{
\prop_get:NnNTF \g_andre_tasks_prop { #1 } \l_andre_temp_tl
{
\tl_put_right:Nn \l_andre_temp_tl { \item #2 }
\prop_gput:NnV \g_andre_tasks_prop { #1 } \l_tmpa_tl
}
{
\msg_warning:nnx { andre } { task-exists-not } { #1 }
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
}
\ExplSyntaxOff
\begin{document}
\AimTaskDef{1}{task 1}
\AimTaskAdd{1}{task 2}
\AimTaskDef{2}{task 3}
\AimTaskAdd{2}{task 4}
\AimTaskGet{1}
\AimTaskGet{2}
\AimTaskDef{1}{task 1}
\AimTaskAdd{3}{task !}
\end{document}