Why is escaped # breaking my command?
You can't generally use \#
in a label, because it doesn't expand to a character. However, in this particular situation a workaround is possible:
\documentclass{article}
\usepackage{hyperref}
\newcommand{\termExplanation}[1]{%
\item[#1]%
\begingroup
% locally disable \#
\def\#{?hashmark?}%
\phantomsection\label{#1}%
\endgroup
}
\newcommand{\newTerm}[1]{%
\begingroup
% locally disable \#
\def\#{?hashmark?}%
\edef\x{\endgroup\noexpand\hyperref[#1]}\x{\emph{#1}}%
}
\begin{document}
\begin{description}
\termExplanation{C\#} Hello, World!
\termExplanation{lorem} Lorem Ipsum!
\end{description}
\newTerm{C\#} \newTerm{lorem}
\end{document}
The trick is to tell LaTeX that \#
in a label writes ?hashmark?
; the same trick is used to retrieve the label before \hyperref
does its job.
Don't forget \phantomsection
that creates a suitable anchor.
The problem is that the content of \label
doesn't handle these special characters well. The easiest alternative would be to simply not use the special characters and define variants of your commands that allow an arbitrary label in such case:
\documentclass{article}
\usepackage{hyperref}
\makeatletter
\def\termExplanation{%
\@ifnextchar[{\termExplanation@opt}{\termExplanation@noopt}
}
\def\termExplanation@opt[#1]#2{%
\item[#2]\label{#1}%
}
\def\termExplanation@noopt#1{\termExplanation@opt[#1]{#1}}
\def\newTerm{%
\@ifnextchar[{\newTerm@opt}{\newTerm@noopt}%
}
\def\newTerm@opt[#1]#2{%
\hyperref[#1]{\emph{#2}}%
}
\def\newTerm@noopt#1{\newTerm@opt[#1]{#1}}
\makeatother
\begin{document}
\begin{description}
\termExplanation[chash]{C\#} Hello, World!
\termExplanation{lorem} Lorem Ipsum!
\end{description}
\newTerm[chash]{C\#} \newTerm{lorem}
\end{document}
To understand what this bit of code those, I recommend you have a look at:
- What do \makeatletter and \makeatother do?
- Understanding \@ifnextchar
as they provide very comprehensive answers. Otherwise, the \def
command is the TeX primitive behind \newcommand
and offers a little more flexibility in the way arguments can be given, though definitely in most cases use \newcommand
.
A better option alternative, as suggested by egreg in the comments, is:
\makeatletter
\newcommand\termExplanation{\@dblarg\termExplanation@opt}
\def\termExplanation@opt[#1]#2{\item[#2]\label{#1}}
\newcommand\newTerm{\@dblarg\newTerm@opt}
\def\newTerm@opt[#1]#2{\hyperref[#1]{\emph{#2}}}
\makeatother
As a last note, it really seems to me like you are creating a glossary. If so, then you should also have a look at the glossaries
package. I provide a small MWE of the glossaries
package below:
Main file:
\documentclass{article}
\usepackage{hyperref}
\usepackage[toc]{glossaries}
\renewcommand*{\glstextformat}[1]{\emph{#1}}
\loadglsentries{glossary}
\makeglossaries
\begin{document}
You can now refer to glossary terms with \gls{permittivity} and
\gls{permeability}. You can even get the plural with \glspl{permittivity} and
get the capitalized version with \Gls{permittivity} and \Glspl{permeability}.
\clearpage
\printglossaries
\end{document}
and glossary.tex
:
\newglossaryentry{permeability}{
name={permeability},
plural={permeabilities},
symbol={\(\mu\)},
parent={},
description={A measure of how easy it is to form a magnetic field in a medium.}
}
\newglossaryentry{permittivity}{
name={permittivity},
plural={permittivities},
symbol={\(\varepsilon\)},
parent={},
description={A measure of the resistance encountered when forming an electric field in a medium}
}
and the output:
Note that the glossaries
package requires an additional run of makeglossaries
in order to process the glossary entries.