![处理宏的逗号分隔参数列表中的 _(下划线)](https://linux22.com/image/354039/%E5%A4%84%E7%90%86%E5%AE%8F%E7%9A%84%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8%E4%B8%AD%E7%9A%84%20_%EF%BC%88%E4%B8%8B%E5%88%92%E7%BA%BF%EF%BC%89.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 命令来格式化 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
]%
}