Manipulando _ (sublinhados) na lista de argumentos separados por vírgula de uma macro

Manipulando _ (sublinhados) na lista de argumentos separados por vírgula de uma macro

Contexto:Eu criei uma \citepmacro "-like". Eu o uso no corpo do meu documento para me referir a algum código encontrado no apêndice.

Minha macro recebe uma lista separada por vírgula como entrada e imprime cada elemento da lista como um hyperreflink para a parte relevante do código. (Para facilitar as coisas, o texto do hyperreflink é a própria chave e a sintaxe da âncora do link é 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: O MWE acima funciona muito bem. No entanto, minhas chaves de caso real têm a seguinte estrutura: a_123, bb_456, etc. (ou seja, há um sublinhado no meio da chave e o número de letras antes dele é desconhecido.) É claro que isso faz com que a compilação falhe, pois o sublinhado não é nem escapou nem em um ambiente matemático.

Pergunta:Como lidar com chaves com sublinhado na minha lista de argumentos separados por vírgula da minha macro?

Responder1

Você pode usar \detokenize; mas se você quiser umimpressosublinhado, você precisa carregar fontenccom a T1opção.

\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}

insira a descrição da imagem aqui

Aqui está uma expl3versão que não precisa do 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}

insira a descrição da imagem aqui

Responder2

A maneira mais simples de fazer isso é carregar o urlpacote e definir um comando url para formatar os refnames:

\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
    ]%
}

informação relacionada