Manejo de _ (guiones bajos) en la lista de argumentos separados por comas de una macro

Manejo de _ (guiones bajos) en la lista de argumentos separados por comas de una macro

Contexto:Creé una \citepmacro "similar a". Lo uso en el cuerpo de mi documento para hacer referencia a algún código que se encuentra en el apéndice.

Mi macro toma una lista separada por comas como entrada e imprime cada elemento de la lista como un hyperrefenlace a la parte relevante del código. (Para facilitar las cosas, el texto del hyperrefenlace es la clave en sí y la sintaxis del ancla del enlace es code:<key>).

\documentclass{article}
    \usepackage{etoolbox}
    \usepackage{hyperref}
    \usepackage{lipsum}

    \newcommand{\codecitep}[1]{% cf. https://tex.stackexchange.com/a/87423/64454
        [%
        \def\nextitem{\def\nextitem{, }}% Separator
        \renewcommand*{\do}[1]{\nextitem{\hyperref[code:##1]{##1}}}% How to process each item
        \docsvlist{#1}% Process list
        ]%
    }   
\begin{document}
    \section{Body}
        A sentence with one code-citation only \codecitep{key1}.
        Another sentence with two code-citations and followed by dummy text \codecitep{key1, key2}.
%       A sentence with one code-citation only \codecitep{a_123}.
%       Another sentence with two code-citations and followed by dummy text \codecitep{a_123, bb_456}.

        \lipsum[1-2]

    \section{Appendix}
        \lipsum[3]

        \subsection{key1}
        \label{code:key1}
        \label{code:a_123}
        \lipsum[4]

        \subsection{key2}
        \label{code:key2}
        \label{code:bb_456}
        \lipsum[5]
\end{document}

Problema: El MWE anterior funciona muy bien. Sin embargo, mis claves del caso real tienen la siguiente estructura: a_123, bb_456, etc. (Es decir, hay un guión bajo en el medio de la clave y se desconoce el número de letras antes de él). Por supuesto, esto hace que la compilación falle ya que el guión bajo no es ninguno de los dos. escapado ni en un ambiente matemático.

Pregunta:¿Cómo manejar claves con guión bajo en mi lista de argumentos separados por comas de mi macro?

Respuesta1

Puedes usar\detokenize ; pero si quieres unimpresoguión bajo, debe cargar fontenccon la T1opción.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{etoolbox}
\usepackage{hyperref}
\usepackage{lipsum}

\newcommand{\codecitep}[1]{% cf. https://tex.stackexchange.com/a/87423/64454
  [%
  \def\nextitem{\def\nextitem{, }}% Separator
  % How to process each item
  \renewcommand*{\do}[1]{%
    \nextitem\hyperref[code:##1]{\detokenize{##1}}%
  }%
  \docsvlist{#1}% Process list
  ]%
}   
\begin{document}

\section{Body}
A sentence with one code-citation only \codecitep{key1}.
Another sentence with two code-citations and followed by dummy text \codecitep{key1, key2}.
A sentence with one code-citation only \codecitep{a_123}.
Another sentence with two code-citations and followed by dummy text \codecitep{a_123, bb_456}.

\lipsum[1-2]

\section{Appendix}
\lipsum[3]

\subsection{key1}
\label{code:key1}
\label{code:a_123}
\lipsum[4]

\subsection{key2}
\label{code:key2}
\label{code:bb_456}
\lipsum[5]
\end{document}

ingrese la descripción de la imagen aquí

Aquí hay una expl3versión que no necesita fontenc.

\documentclass{article}
\usepackage{xparse}
\usepackage{hyperref}
\usepackage{lipsum}

\ExplSyntaxOn

% define a token list containing an underscore
\tl_const:Nx \c_ebo_codecite_us_tl { \char_generate:nn { `_ } { 8 } }

% the main macro
\NewDocumentCommand{\codecitep}{m}
 {
  \ebo_codecite:n { #1 }
 }

% variables and variants of kernel functions
\tl_new:N \l__ebo_codecite_key_print_tl
\seq_new:N \l__ebo_codecite_refs_seq

\cs_generate_variant:Nn \tl_replace_all:Nnn { NV }

% functions

\cs_new_protected:Nn \ebo_codecite:n
 {
  [
   % clear the sequence
   \seq_clear:N \l__ebo_codecite_refs_seq
   % loop through the input
   \clist_map_inline:nn { #1 }
    {
     % for the "print part", change _ into \_
     \tl_set:Nn \l__ebo_codecite_key_print_tl { ##1 }
     \tl_replace_all:NVn \l__ebo_codecite_key_print_tl \c_ebo_codecite_us_tl { \_ }
     % add to the sequence
     \__ebo_codecitep_add:nV { ##1 } \l__ebo_codecite_key_print_tl
    }
   % use the sequence, items separated by "comma space"
   \seq_use:Nn \l__ebo_codecite_refs_seq { ,~ }
  ]
 }

% an auxiliary function, for expanding the second argument
\cs_new_protected:Nn \__ebo_codecitep_add:nn
 {
  \seq_put_right:Nn \l__ebo_codecite_refs_seq { \hyperref[code:#1]{#2} }
 }
\cs_generate_variant:Nn \__ebo_codecitep_add:nn { nV }

\ExplSyntaxOff

\begin{document}

\section{Body}
A sentence with one code-citation only \codecitep{key1}.
Another sentence with two code-citations and followed by dummy text \codecitep{key1, key2}.
A sentence with one code-citation only \codecitep{a_123}.
Another sentence with two code-citations and followed by dummy text \codecitep{a_123, bb_456}.

\lipsum[1-2]

\section{Appendix}
\lipsum[3]

\subsection{key1}
\label{code:key1}
\label{code:a_123}
\lipsum[4]

\subsection{key2}
\label{code:key2}
\label{code:bb_456}
\lipsum[5]
\end{document}

ingrese la descripción de la imagen aquí

Respuesta2

La forma más sencilla de hacer esto es cargar el urlpaquete y definir un comando de URL para formatear los nombres de referencia:

\usepackage{url}
\DeclareUrlCommand{\coderefname}{\urlstyle{rm}}

\newcommand{\codecitep}[1]{% cf. https://tex.stackexchange.com/a/87423/64454
    [%
    \def\nextitem{\def\nextitem{, }}% Separator
    \renewcommand*{\do}[1]{\nextitem{\hyperref[code:##1]{\coderefname{##1}}}}% How to process each item
    \docsvlist{#1}% Process list
    ]%
}

información relacionada