
我想動態定義一些本質上創建\ref
s 列表的巨集。我似乎能夠定義這些宏,但無法列印它們。
這是我的 M(非)WE:
\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
\ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
\else\def\DP@tmp{\@currentlabel}
\fi
\expandafter\edef\csname DP@#1\endcsname{\DP@tmp}
\typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{#1: \csname DP@#1\endcsname}
\typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}
\item Strawberries \Assign{julie}
\end{enumerate}
\Assigned{fred} % should print 1,3
\Assigned{julie} % should print 2,4,5
\end{document}
我希望\Assigned{}
巨集列印出「已指派」給該人的項目編號。也就是說,在itemise
上述環境之後我應該會得到:
fred: 1,3
julie: 2,4,5
不幸的是,我遺失了商品編號,我只得到:
fred:
julie:
M(非)WE 乳膠沒有任何問題,但由於我不明白的原因,\Assigned
巨集沒有擴展。我已經使用\expandafter
1 次或多次嘗試了許多變體,\edef
...但似乎沒有任何效果。
在日誌檔案中,\typeout{}
上面的呼叫正在產生:
ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: `\DP@fred`
ASSIGNED: `\DP@julie`
因此,看起來好像\DP@#1
bing 創建正確,但\Assigned{}
巨集不起作用,這可能是擴展問題。使用\edef
不起作用......但事實上,擴展問題發生在內部,這表明\typeout
我正在做一些更根本上錯誤的事情。
誰能告訴我如何解決這個問題?
例如,我的願望清單上的下一步是讓它列印「1,3-6,8」而不是「1,3,4,5,6,8」。但首先要說的是!
答案1
環境enumerate
新增了一個群組,因此對 的變更\DP@#1
是本地的,並且在環境關閉後會遺失。因此,該範例使定義成為全局的:
\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
\ifcsname DP@#1\endcsname
\edef\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}%
\else
\edef\DP@tmp{\@currentlabel}%
\fi
\global\expandafter\let\csname DP@#1\endcsname\DP@tmp
\typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
% \expandafter\def\csname Assigned#1\endcsname{\csname DP@#1\endcsname}
\typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}
\item Strawberries \Assign{julie}
\end{enumerate}
\Assigned{fred} % should print 1,3
\Assigned{julie} % should print 2,4,5
\end{document}
結果:
ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: 1,3
ASSIGNED: 2,4,5
範圍壓縮更新
此範例解析逗號清單\DP@#1
並定義\Assign#1
連續條目的壓縮範圍:
\documentclass{article}
\usepackage{kvoptions}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
\ifcsname DP@#1\endcsname
\edef\DPx@tmp{\csname DP@#1\endcsname,\@currentlabel}%
\else
\edef\DPx@tmp{\@currentlabel}%
\fi
\global\expandafter\let\csname DP@#1\endcsname\DPx@tmp
\typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
\begingroup
\let\DPx@curr\@empty
\let\DPx@tmp\@empty
\expandafter\expandafter\expandafter\comma@parse
\expandafter\expandafter\expandafter{\csname DP@#1\endcsname}%
\AssignedAux
\ifx\DPx@curr\@empty
\else
\edef\DPx@tmp{\DPx@tmp-\DPx@curr}%
\fi
\global\expandafter\let\csname Assigned#1\endcsname\DPx@tmp
\endgroup
\typeout{ASSIGNED: \csname Assigned#1\endcsname}
}
\def\AssignedAux#1{%
\ifx\DPx@tmp\@empty
\def\DPx@tmp{#1}%
\count@=#1\relax
\else
\advance\count@\@ne
\ifnum#1=\count@
\def\DPx@curr{#1}%
\else
\count@=#1\relax
\ifx\DPx@curr\@empty
\edef\DPx@tmp{\DPx@tmp,#1}%
\else
\edef\DPx@tmp{\DPx@tmp-\DPx@curr,#1}%
\let\DPx@curr\@empty
\fi
\fi
\fi
}
\makeatother
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}\Assign{fred}
\item Strawberries \Assign{julie}
\item Pears \Assign{julie}
\item Lemons \Assign{fred}
\end{enumerate}
\Assigned{fred} % should print 1,3
\Assigned{julie} % should print 2,4,5
\end{document}
結果:
ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 1,3,4
ASSIGN: 2,4,5
ASSIGN: 2,4,5,6
ASSIGN: 1,3,4,7
ASSIGNED: 1,3-4,7
ASSIGNED: 2,4-6
答案2
語法\def\Assigned#1{}
不正確。正確的做法是\expandafter\def\csname Assigned#1\endcsname{}
。這允許您的程式碼編譯。此外,它\edef
是本地化的,無法在更高層級存取。改變它來\xdef
補救。
\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
\ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
\else\def\DP@tmp{\@currentlabel}
\fi
\expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
\typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{\expandafter\def\csname Assigned#1\endcsname{\csname DP@#1\endcsname}
\typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}
\item Strawberries \Assign{julie}
\end{enumerate}
\Assigned{fred} % should print 1,3
\Assigned{julie} % should print 2,4,5
\end{document}
日誌檔包含:
ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: 1,3
ASSIGNED: 2,4,5
答案3
\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
\ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
\else\def\DP@tmp{\@currentlabel}
\fi
\expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
\typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
\csname DP@#1\endcsname
\typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}
\item Strawberries \Assign{julie}
\end{enumerate}
\Assigned{fred} % should print 1,3
\Assigned{julie} % should print 2,4,5
\end{document}
對更新問題的回复
若要取得名稱和項目編號:
\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
\ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
\else\def\DP@tmp{\@currentlabel}
\fi
\expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
\typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
#1: \csname DP@#1\endcsname
\typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}
\item Strawberries \Assign{julie}
\end{enumerate}
\Assigned{fred} % should print 1,3
\Assigned{julie} % should print 2,4,5
\end{document}
答案4
您可能會喜歡 LaTeX3 版本;
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\Assign}{m}
{
\andrew_assign:n { #1 }
}
\NewDocumentCommand{\Assigned}{m}
{
\andrew_assigned:n { #2 }
}
% syntactic sugar for shortening code
\cs_new:Npn \__andrew_seq:n #1
{
g_andrew_assignee_#1_seq
}
\cs_new_protected:Npn \andrew_assign:n #1
{% if the assignee is not yet defined, create a sequence
\seq_if_exist:cF { \__andrew_seq:n { #1 } }
{
\seq_new:c { \__andrew_seq:n { #1 } }
}
% globally add the item to the assignee's sequence
\seq_gput_right:cv { \__andrew_seq:n { #1 } } { @currentlabel }
}
\cs_new:Npn \andrew_assigned:n #1
{% print the assignee's items separated by a comma
\seq_use:cn { \__andrew_seq:n { #1 } } { ,~ }
}
\cs_generate_variant:Nn \seq_gput_right:Nn { cv }
\cs_generate_variant:Nn \seq_use:Nn { c }
\ExplSyntaxOff
\begin{document}
\begin{enumerate}
\item Apples \Assign{fred}
\item Oranges \Assign{julie}
\item Bananas \Assign{fred}
\item Mangos \Assign{julie}
\item Strawberries \Assign{julie}
\end{enumerate}
Fred has \Assigned{fred} % should print 1,3
Julie has \Assigned{julie} % should print 2,4,5
\end{document}