Cannot use \textit or \url in \edef
There is a large group of TeX macros/commands that can't be used (as expected) in an \edef
context. Those macros are called not expandable. This aspect of TeX programming is one that creeps up on one sooner or later and is well worth reading up on if one intends to go a bit further in (La)TeX coding. There are a great many questions about issues like this on this site (for example What are the differences between \def, \edef, \gdef and \xdef?, When to use \edef, \noexpand, and \expandafter?, ...), but I don't know about a good systematic introduction except for the typical TeX references such as the TeX book or TeX by Topic (see for example What is the best way to learn TeX?, Should I read Donald Knuth's The TeXbook?).
In your particular case \textit
and \url
are not expandable and will thus break when used in \edef
.
If you want to retain the structure of your current approach you can replace the \edef
with \expandafter
s and 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}
While the \edef
would try to expand everything in its argument as far as possible, the \expandafter\def\expandafter\printnounattrs\expandafter{\printnounattrs
expands only the \printnounattrs
in the definition exactly once, which means that we can concatenate our list as expected. (The simple \def\printnounattrs{\printnounattrs...}
would lead to an infinite loop because that would to define the macro \printnounattrs
to expand to \printnounattrs
.)
Note that with this approach \url
suffers from its usual issues that the URL can't contain %
, #
, ^^
or end with \
since it is used as an argument to a command.
If I were to write a macro for a similar task from scratch I would probably look into using the powerful list macros of etoolbox
or LaTeX3/expl3
.
Here is a naive implementation with 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}
\edef
expands all commands to the fullest. However not all commands can be expanded, like e.g. \textit
because it doesn't know what to do with the text when it's not in "printing mode". If you still however want to expand other tokens while leaving e.g. \textit
untouched it you could use \noexpand
(or \unexpanded
if multple tokens) to prevent it from expanding (whilst all the others are):
\documentclass{article}
\def\a{alpha}
\edef\b{\noexpand\textit{\a}}
\show\b
\begin{document}
\b
\end{document}
Shows this in the log:
> \b=macro:
->\textit {alpha}.
l.4 \show\b
You can read more about \noexpand
(and the related \unexpanded
) at this answer