%20%D0%B2%20%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B5%20%D0%B0%D1%80%D0%B3%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2%20%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%B0%2C%20%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B7%D0%B0%D0%BF%D1%8F%D1%82%D1%8B%D0%BC%D0%B8.png)
Контекст:Я создал \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
]%
}