Обработка _ (подчеркиваний) в списке аргументов макроса, разделенных запятыми

Обработка _ (подчеркиваний) в списке аргументов макроса, разделенных запятыми

Контекст:Я создал \citepмакрос "-like". Я использую его в теле моего документа, чтобы ссылаться на некоторый код, найденный в приложении.

Мой макрос принимает в качестве входных данных список, разделенный запятыми, и выводит каждый элемент списка как hyperrefссылку на соответствующую часть кода. (Для простоты текст ссылки hyperref— это сам ключ, а синтаксис привязки ссылки — 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}

Проблема: MWE выше работает отлично. Однако мои реальные ключи имеют следующую структуру: a_123, bb_456, и т. д. (Т. е. в середине ключа есть подчеркивание, а количество букв перед ним неизвестно.) Конечно, это делает компиляцию неудачной, поскольку подчеркивание не экранировано и не находится в математической среде.

Вопрос:Как обрабатывать ключи с подчеркиванием в списке аргументов макроса, разделенных запятыми?

решение1

Вы можете использовать \detokenize; но если вы хотитенапечатаноподчеркивание, вам необходимо загрузить fontencс T1опцией.

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

введите описание изображения здесь

Вот expl3версия, которая не нуждается в 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}

введите описание изображения здесь

решение2

Самый простой способ сделать это — загрузить пакет urlи определить команду URL для форматирования имен ссылок:

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

Связанный контент