我认为这个 MWE 说明了一切。\cite
可以忽略其参数中的空格,而\cref
不能。我想知道是否\cref
可以通过这种方式进行改进。
\documentclass{article}
\usepackage{cleveref}
\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@misc{1, author="One Author", year=2000}
@misc{2, author="Another Writer", year=2010}
\end{filecontents}
\begin{document}
We can use \cite{1,2} AND \cite{1, 2}!
Yet, we can use \cref{1,2}, but not \cref{1, 2}!
\section{Section 1}
\label{1}
\section{Section 2}
\label{2}
\bibliographystyle{apalike}
\bibliography{\jobname}
\end{document}
为什么这很重要?因为有些文本编辑器(TeXstudio 就是其中之一)在实现逗号处换行时遇到困难,因为后面没有空格。
答案1
规范化,删除标签名称前后的空格并删除空条目。
以下示例使用 package 的逗号解析器kvsetkeys
来解析 package 的引用命令的标签名称列表。为此,第二个参数中包含列表的cleveref
内部函数被重新定义:\@cref
\documentclass{article}
\usepackage{cleveref}
\usepackage{kvsetkeys}
\makeatletter
\let\org@@cref\@cref
\renewcommand*{\@cref}[2]{%
\begingroup
\toks@={}%
\comma@parse{#2}\add@cref@item
\edef\process@me{\endgroup
\noexpand\org@@cref{#1}{\the\toks@}%
}\process@me
}
\newcommand*{\add@cref@item}[1]{%
\expandafter\ifx\expandafter\\\the\toks@\\%
\toks@{#1}%
\else
\toks@\expandafter{\the\toks@,#1}%
\fi
}
\makeatother
\begin{document}
\noindent
We can use \cref{1,2}, and now \cref{1, 2},\\
and even with a leading or trailing comma: \Cref{ , 1 , 2 ,}.
\section{Section 1}
\label{1}
\section{Section 2}
\label{2}
\end{document}
删除空格并保留逗号
消除所有空白的解决方案。如果标签包含空格,则必须将标签放在花括号中。:
\documentclass{article}
\usepackage{cleveref}
\usepackage{kvsetkeys}
\makeatletter
\let\org@@cref\@cref
\renewcommand*{\@cref}[2]{%
\edef\process@me{%
\noexpand\org@@cref{#1}{\zap@space#2 \@empty}%
}\process@me
}
\makeatother
\begin{document}
\noindent
We can use \cref{1,2}, and now \cref{1, 2}.
\section{Section 1}
\label{1}
\section{Section 2}
\label{2}
\end{document}
\zap@space
在 LaTeX 内核中定义,例如用于规范化类和包的选项列表。
答案2
几乎不言自明的代码:
\begin{filecontents}{\jobname.bib}
@misc{1, author="One Author", year=2000}
@misc{2, author="Another Writer", year=2010}
\end{filecontents}
\documentclass{article}
\usepackage{xparse}
\usepackage{cleveref}
\ExplSyntaxOn
\cs_set_eq:Nc \bers_cref:nn { @cref }
\cs_generate_variant:Nn \bers_cref:nn { nx }
\cs_set_protected:cpn { @cref } #1 #2
{
\seq_set_split:Nnn \l_bers_cref_seq { , } { #2 }
\bers_cref:nx { #1 } { \seq_use:Nn \l_bers_cref_seq { , } }
}
\seq_new:N \l_bers_cref_seq
\ExplSyntaxOff
\begin{document}
We can use \cite{1,2} AND \cite{1, 2}!
Yet, we can use \cref{1 space,2}, but also \cref{1 space, 2}!
Also \cref{1 space,2 , 3,, 4}
Also \Cref{1 space, 2, 3 , , 4}
\section{Section 1}
\label{1 space}
\section{Section 2}
\label{2}
\section{Section 3}
\label{3}
\section{Section 4}
\label{4}
\bibliographystyle{apalike}
\bibliography{\jobname}
\end{document}
我重新定义了内部命令\@cref
,首先将其第二个参数拆分为逗号,这样可以删除前导空格和尾随空格,但保留内部空格。原始命令\@cref
保存在 中\bers_cref:nn
,然后\@cref
重新定义为使用\bers_cref:nx
,这是一种完全扩展其第二个参数的变体,我们\seq_use:Nn
在条目之间使用逗号。
请注意,也会\Cref
自动修改。空条目也有效。
答案3
\cref
这是一个基于 LuaLaTeX 的解决方案。它允许在、\Cref
和的参数中使用空格(空格、制表符、换行符)\labelcref
。请注意,此解决方案中采用的方法不会cleveref
以任何方式修改宏。
\documentclass{article}
\usepackage{cleveref}
\usepackage{luacode}
\begin{luacode}
function nospace ( t ) -- remove all whitespace characters from string "t"
return ( t:gsub ( "%s", "" ) )
end
function crefnospace ( s )
return ( s:gsub ( "\\.-[cC]ref%s-%b{}" , nospace ) )
end
\end{luacode}
\AtBeginDocument{\directlua{luatexbase.add_to_callback (
"process_input_buffer", crefnospace, "crefnospace" )}}
\begin{document}
We may use \cref{a,b}, \Cref{a, b}, \cref{a ,b}, and \Cref{{ a }, b }.
``\labelcref{ b , {a }}'' works too.
\section{Section 1}\label{a}
\section{Section 2}\label{b}
\end{document}