Cleveref 和基于标题的命令 - 错误引用

Cleveref 和基于标题的命令 - 错误引用

我正在尝试创建一个标题命令,该命令突出显示第一个句子,并使用第一个句子作为 * 表格的简短标题。我们称之为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.]

相关内容