Replace underscore in macro implementation?

I'm working on a document that contains a set of sections describing some technical objects. The object names contain underscores (very common in that programming environment), so I've loaded the package underscore.

Now I want to link from other parts of the document to the reference section. Underscores in labels (e. g. \label{sec:ref-struct-FOO_BAR}) seem to cause all kinds of trouble, so I've simply replaced the underscores with dashes in the labels: \label{sec:ref-struct-FOO-BAR}. This works so far.

As a next step, I would like to provide a custom macro that is called with the object name (containing an underscore) and then both typesets that name (with an underscore) and places a link (where all underscores are replaced by dashes). An example:

\documentclass{article}
\usepackage{fancyref}
\usepackage{hyperref}
\usepackage{underscore}

\newcommand{\componentname}[1]{\texttt{#1}}
\newcommand{\structurename}[1]{\texttt{#1}}

\newcommand{\componentref}[2]{\hyperref[sec:ref-comp-#1]{\componentname{#2}}}
\newcommand{\structureref}[2]{\hyperref[sec:ref-struct-#1]{\structurename{#2}}}

\begin{document}

\tableofcontents

\clearpage

\section{Text}

% Where I came from:
We use component \componentname{AB_CD} (see \fref{sec:ref-comp-AB-CD}) to generate
structure \structurename{FOO_BAR} (see \fref{sec:ref-struct-FOO-BAR}).

% How far I got:
We use component \componentref{AB-CD}{AB_CD} to generate structure \structureref{FOO-BAR}{FOO_BAR}.

% What I really want:
% We use component \componentref{AB_CD} to generate structure \structureref{FOO_BAR}.

\section{Reference}

\subsection{Structures}

\subsubsection{Structure \structurename{FOO_BAR}}
\label{sec:ref-struct-FOO-BAR}

Text

\subsubsection{Structure \structurename{BOO_FAR}}
\label{sec:ref-struct-BOO-FAR}

Text

\subsection{Components}

\subsubsection{Component \componentname{AB_CD}}
\label{sec:ref-comp-AB-CD}

Text

\subsubsection{Component \componentname{EFG_HIJ}}
\label{sec:ref-comp-EFG-HIJ}

Text

\end{document}


I'd like to use something like

\usepackage{xstring}
% ...
\newcommand{\fancycomponentref}[1]{\hyperref[sec:ref-comp-\StrSubstitute{#1}{_}{-}]{\componentname{#1}}}


but that doesn't work, and I haven't found a viable solution yet. What options do I have to implement this?

You don't need the underscore package:

\documentclass{article}
\usepackage{fancyref}
\usepackage{hyperref}

\newcommand{\componentname}[1]{\texttt{#1}}
\newcommand{\structurename}[1]{\texttt{#1}}

\newcommand{\componentref}[1]{\hyperref[sec:ref-comp-#1]{\componentname{#1}}}
\newcommand{\structureref}[1]{\hyperref[sec:ref-struct-#1]{\structurename{#1}}}

\begingroup\lccode~=_ \lowercase{\endgroup\let~}_
\catcode_=12

\begin{document}

\tableofcontents

\clearpage

\section{Text}

% Where I came from:
We use component \componentname{AB_CD} (see \fref{sec:ref-comp-AB_CD}) to generate
structure \structurename{FOO_BAR} (see \fref{sec:ref-struct-FOO_BAR}).

% How far I got:
We use component \componentref{AB_CD} to generate structure \structureref{FOO_BAR}.

\section{Reference}

\subsection{Structures}

\subsubsection{Structure \structurename{FOO_BAR}}
\label{sec:ref-struct-FOO_BAR}

Text and math $a_1$

\subsubsection{Structure \structurename{BOO_FAR}}
\label{sec:ref-struct-BOO_FAR}

Text

\subsection{Components}

\subsubsection{Component \componentname{AB_CD}}
\label{sec:ref-comp-AB_CD}

Text

\subsubsection{Component \componentname{EFG_HIJ}}
\label{sec:ref-comp-EFG_HIJ}

Text

\end{document}


• The "real" application is a 480+-page document with a lot of stuff in it. I've tried to replace the underscore package with your catcode enchantments, but I get "missing \$ inserted" errors all over the place. I don't even know where I should start to find out where that comes from... :-( – vwegert Feb 4 '15 at 9:40
• @vwegert Sorry, but without a minimal example it's impossible to say more. – egreg Feb 4 '15 at 9:42
• I understand that. While I got the message that in this particular minimal example, I don't need the underscore package, is there a way to get this working without removing the package? – vwegert Feb 4 '15 at 9:48
• @vwegert underscore makes the underscore active, with a non expandable definition, so _ can't be used in labels. – egreg Feb 4 '15 at 9:51
• @Alberto for such an application I’d do differently. Look for \detokenize` – egreg Jun 3 at 15:16