我正在尝试创建一个标题命令,该命令突出显示第一个句子,并使用第一个句子作为 * 表格的简短标题。我们称之为kaption
。这是使用listofitems
包根据点拆分图形/表格/列表的标题来完成的。这有效,但与 cleveref 结合使用时,cleveref 无法生成正确的引用,而是使用当前层次结构的标签(例如部分)。
为什么 cleveref 无法找到正确的引用?我该如何解决这个问题?
由于我的书有 100 多张图片和表格,所以手动更改标题不是一个可行的解决方案,因此,我想使用一种自动化的方式。
梅威瑟:
\documentclass{article}
\usepackage{cleveref}
\usepackage{graphicx}
\usepackage{ifthen}
\usepackage{listofitems}
\newcommand*{\kaption}[1]{
\setsepchar{.}\readlist*\pdots{#1}{
\caption[{\pdots[1]}]
{%
\foreachitem\sentence\in\pdots{
\ifnum \sentencecnt = 1
{\textbf{\pdots[\sentencecnt].}}
\else
{\pdots[\sentencecnt]\pdotssep[\sentencecnt]}
\fi
}}
}
}
\begin{document}
\section{With caption}
Reference fig 1 before: \cref{fig1}
\begin{figure}[h]
\centering
\includegraphics[height=2cm]{example-image-a}
\caption{Caption with one sentence. And another sentence of course.}
\label{fig1}
\end{figure}
Reference fig 1 after: \cref{fig1}
\section{With kaption}
Reference fig 2 before: \cref{fig2}
\begin{figure}[h]
\centering
\includegraphics[height=2cm]{example-image-a}
\kaption{Caption with one sentence. And another sentence of course.}
\label{fig2}
\end{figure}
Reference fig 2 after: \cref{fig2}
\end{document}
答案1
您遇到的问题不仅限于:它也\cref
出现在基本宏中。\ref
@daleif 已经确定了这个问题:材料\readlist*\pdots{#1}{...}
形成一个组,而该组内的内容对指令来说是不可见的\label
。在这种情况下,LaTeX 唯一能做的就是将的参数\label
与最近增加的可见的柜台,正好是section
柜台。不好。
A笨拙的修复将会改变
\newcommand*{\kaption}[1]{
\setsepchar{.}\readlist*\pdots{#1}{
到
\newcommand*{\kaption}[1]{\refstepcounter{figure}
\setsepchar{.}\readlist*\pdots{#1}{\addtocounter{figure}{-1}
如果您还计划将其应用于\kaption
环境table
,那么您还需要创建一个单独的宏(例如,\kaptiont
仅用于表)。正如我所说,这是一个临时解决方案。
A非笨拙的解决方案如果您可以自由地使用 LuaLaTeX 编译文档,则可以使用:创建一个 Lua 函数,该函数会\caption{First. Last.}
自动将所有的实例修改为\caption[First.]{\textbf{First.} Last.}
。要实现此设置,必须将此函数分配给 LuaTeX 的process_input_buffer
回调,以便它可以充当输入材料的预处理器,前TeX 开始其常规处理。
和其参数之间允许有空格\caption
。如果标题中只有一个句子,则整个标题在文档正文中以粗体显示。唯一的限制性输入要求是,在的参数中\caption{ ... }
或\caption
和其参数之间不允许有换行符。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{graphicx}
\usepackage[colorlinks,allcolors=blue,linktocpage]{hyperref} % optional
\usepackage[nameinlink]{cleveref}
\usepackage{luacode} % for 'luacode' environment
\begin{luacode}
function modify_captions ( s )
s = s:gsub ('\\caption%s*(%b{})' , function ( x )
-- strip off opening and closing curly braces:
x = x:sub ( 2 , -2 )
-- find location of first 'dot' followed by space:
dot = x:find ( '%.%s' )
if dot then
first = x:sub ( 1 , dot )
last = x:sub ( dot+1 )
return ( '\\caption[' .. first .. ']{\\textbf{' .. first .. '}' .. last ..'}' )
else
return ( '\\caption[' .. x .. ']{\\textbf{' .. x .. '}}' )
end
end )
return ( s )
end
\end{luacode}
% assign 'modify_captions' to the 'process_input_buffer' callback:
\AtBeginEnvironment{\directlua{luatexbase.add_to_callback (
'process_input_buffer', modify_captions, 'modify_captions' )}}
\begin{document}
\listoffigures
\medskip\hrule
\addtocounter{figure}{5} % just for this example
\begin{figure}[h]
\centering
\includegraphics[height=2cm]{example-image-a}
\caption{Caption with one sentence. And another sentence.}
\label{figA}
\end{figure}
\noindent
Cross-references: \cref{figA}\quad\ref{figA}
\end{document}
答案2
我不确定你是否想这样做。然而,主要问题不是错误的引用,而是在句点处拆分可能非常危险。
因此我检查文本中是否有句点后面跟着一个空格和其他内容。在这种情况下,第一个句号后面跟着一个空格的部分将更改为粗体,并且也用于可选参数。否则所有内容都设置为粗体(但不是可选参数)。
不需要任何组,所以标签就可以了。
\documentclass{article}
\usepackage{cleveref}
\usepackage{graphicx}
\ExplSyntaxOn
\NewDocumentCommand{\kaption}{m}
{
% we don't want to split at every period!
\regex_match:nnTF { .*?\.\s .+ } { #1 }
{% we have a period followed by a space plus something else
\tl_set:Nn \l_tmpa_tl { #1 }
\regex_replace_once:nnN { (.*?)\.\s(.*) }
{
\c{caption}
\[\1\]
\cB\{
\c{textbf}\cB\{\1.\cE\}\c{space}
\2
\cE\}
} \l_tmpa_tl
\tl_use:N \l_tmpa_tl
}
{\caption[#1]{\textbf{#1}}}
}
\ExplSyntaxOff
\begin{document}
\listoffigures
\section{Short caption}
Reference fig 1 before: \cref{fig1}
\begin{figure}[h]
\centering
\includegraphics[height=1cm]{example-image-a}
\kaption{Caption with one sentence.}
\label{fig1}
\end{figure}
Reference fig 1 after: \cref{fig1}
\section{Long caption}
Reference fig 2 before: \cref{fig2}
\begin{figure}[h]
\centering
\includegraphics[height=1cm]{example-image-a}
\kaption{Caption with one sentence. And another sentence of course.}
\label{fig2}
\end{figure}
Reference fig 2 after: \cref{fig2}
\section{Long caption with periods}
Reference fig 2 before: \cref{fig2}
\begin{figure}[h]
\centering
\includegraphics[height=1cm]{example-image-a}
\kaption{Caption with $1.1$ sentence. And another sentence of course.}
\label{fig3}
\end{figure}
Reference fig 3 after: \cref{fig3}
\end{document}
然而,我会采取不同的做法:
\NewDocumentCommand{\kaption}{mo}{%
\caption[#1]{\textbf{#1\IfValueT{#2}{.}}\IfValueT{#2}{ #2}}
}
所以你可以打电话
\kaption{Caption with one sentence}
\kaption{Caption with one sentence}[And another sentence of course.]