我正在尝试编写一个 Tex 命令,自动打印出我在文档中使用的图像的归属信息。我创建了 2 个不同的命令。第一个命令是\nounattr
(带有 3 个参数),它接受图像的名称、作者和图像的链接。第二个命令是\printnounattrs
没有参数,但应该只打印在使用之前添加的所有归属的列表\nounattr
。我能够执行这些命令并获得一个简单的列表,但我无法向列表添加任何样式。
这是我目前所拥有的:
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{nounattr}[2018/01/03 The noun project attribution]
\RequirePackage{svg}
\RequirePackage{url}
\newcommand\printnounattrs{}
\newcommand\nounattr[3]{\edef\printnounattrs{\printnounattrs#1 pictogram werd ontworpen door #2 van The Noun Project, onder de Creative Commons license (CC BY 3.0). Zie #3. }}
MWE 如下:
\documentclass{report}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry}
\usepackage[parfill]{parskip}
\usepackage{nounattr}
\begin{document}
\nounattr{Protein}{Ben Markoch}{https://thenounproject.com/search/?q=protein\&i=54837}
\nounattr{Peptides}{Fredrik Edfors}{https://thenounproject.com/search/?q=peptide\&i=66903}
\printnounattrs
\end{document}
不过,我想在 edef 中添加一些样式,以便以#1 pictogram
斜体打印,并且使用 正确定义 url 为 url \url{#3}
。我将其更改\nounattr
为:
\newcommand\nounattr[3]{\edef\printnounattrs{\printnounattrs\textit{#1 pictogram} werd ontworpen door #2 van The Noun Project, onder de Creative Commons license (CC BY 3.0). Zie \url{#3}. }}
但这给了我一个undefined control sequence
错误。我不明白发生了什么,我该如何解决这个问题?
答案1
有大量的 TeX 宏/命令无法(按预期)在\edef
。这些宏称为不可扩展。TeX 编程的这个方面迟早会逐渐出现,如果想在 (La)TeX 编码方面更进一步,那么值得一读。这个网站上有很多关于此类问题的问题(例如\def、\edef、\gdef 和 \xdef 之间有什么区别?,何时使用 \edef、\noexpand 和 \expandafter?, ...),但除了典型的 TeX 参考书(如 TeX 书或 TeX by Topic)之外,我不知道有什么好的系统介绍(例如参见学习 TeX 的最佳方法是什么?,我应该读 Donald Knuth 的《The TeXbook》吗?)。
在您的特定情况下\textit
,并且\url
不可扩展,因此在使用时会中断\edef
。
如果你想保留当前方法的结构,你可以用\edef
s\expandafter
和 a替换\def
\documentclass{report}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry}
\usepackage[parfill]{parskip}
\RequirePackage{url}
\newcommand\printnounattrs{}
\newcommand\nounattr[3]{%
\expandafter\def\expandafter\printnounattrs\expandafter{%
\printnounattrs
\textit{#1 pictogram} werd ontworpen door #2 van The Noun Project,
onder de Creative Commons license (CC BY 3.0).
Zie \url{#3}. }%
}
\begin{document}
\nounattr{Protein}{Ben Markoch}{https://thenounproject.com/search/?q=protein&i=54837}
\nounattr{Peptides}{Fredrik Edfors}{https://thenounproject.com/search/?q=peptide&i=66903}
\nounattr{Peptides}{Schmeptides}{https://thenounproject.com/search/?q=peptide&i=123&pq=v_w20w}
\printnounattrs
\end{document}
虽然\edef
会尝试尽可能地扩展其参数中的所有内容,但\expandafter\def\expandafter\printnounattrs\expandafter{\printnounattrs
只会\printnounattrs
在定义中扩展一次,这意味着我们可以按预期连接列表。(简单的\def\printnounattrs{\printnounattrs...}
会导致无限循环,因为这将定义\printnounattrs
要扩展为的宏\printnounattrs
。)
请注意,这种方法\url
存在常见的问题,即 URL 不能包含%
、#
或者^^
以 结尾,\
因为它被用作命令的参数。
如果我要从头开始编写一个用于类似任务的宏,我可能会考虑使用etoolbox
或 LaTeX3/的强大列表宏expl3
。
以下是一个简单的实现etoolbox
\documentclass{report}
\usepackage{etoolbox}
\usepackage{url}
\newcommand\mylist{}
\newcommand\nounattr[3]{%
\listadd{\mylist}{{#1}{#2}{#3}}}
\newcommand*{\printnounattr}[3]{%
\textit{#1 pictogram} werd ontworpen door #2 van The Noun Project,
onder de Creative Commons license (CC BY 3.0).
Zie \url{#3}.
}
\makeatletter
\newcommand*{\printnounattr@i}[1]{%
\printnounattr#1}
\newcommand*{\printnounattrs}{%
\forlistloop{\printnounattr@i}{\mylist}}
\makeatother
\begin{document}
\nounattr{Protein}{Ben Markoch}{https://thenounproject.com/search/?q=protein&i=54837}
\nounattr{Peptides}{Fredrik Edfors}{https://thenounproject.com/search/?q=peptide&i=66903}
\nounattr{Peptides}{Schmeptides}{https://thenounproject.com/search/?q=peptide&i=123&pq=v_w20w}
\printnounattrs
\end{document}
答案2
\edef
将所有命令完全展开。但是,并非所有命令都可以展开,例如 eg,\textit
因为当它不处于“打印模式”时,它不知道如何处理文本。如果您仍然想展开其他标记,而 eg 保持\textit
不变,则可以使用\noexpand
(或\unexpanded
多个标记)来阻止它展开(而所有其他标记都展开):
\documentclass{article}
\def\a{alpha}
\edef\b{\noexpand\textit{\a}}
\show\b
\begin{document}
\b
\end{document}
在日志中显示这一点:
> \b=macro:
->\textit {alpha}.
l.4 \show\b
您可以在以下网址阅读更多相关信息\noexpand
(及相关内容\unexpanded
)这个答案