間違いはどこにあるのでしょうか? #1 \caption 内

間違いはどこにあるのでしょうか? #1 \caption 内

\caption{...\label{...}...}自動的に に変換しようとしています\caption{...}\label{...}。試したことは次のとおりです:

\documentclass{article}
\usepackage{showlabels}
\newcommand{\storelabel}[1]{\gdef\storedlabel{#1}}
\let\oldcaption\caption
\renewcommand{\caption}[1]{%
    \let\storedlabel\undefined
    \oldcaption{%
        \def\label##1{%
            \protect\storelabel{##1}%
        }%
        #1%
    }%
    \ifdefined\storedlabel%
        \label{\storedlabel}%
    \else%
    \fi%
}
\begin{document}
    \begin{table}
        \caption{no label}
        foo
    \end{table}
    \begin{table}
        \caption{\label{mylabel}label inside caption (front)}
        foo
    \end{table}
    \begin{table}
        \caption{label inside caption (back) \label{mylabel}}
        foo
    \end{table}
    \begin{table}
        \caption{label directly after caption}
        \label{mylabel}
        foo
    \end{table}
    \begin{table}
        \caption{label at end of table (I'm OK with that one)}
        foo
        \label{mylabel}
    \end{table}
\end{document}

pdf ファイルも正しいように見えますが、次のエラー メッセージが表示されます ( の呼び出しごとに 1 回ずつ、合計 5 回\caption)。

! Illegal parameter number in definition of \reserved@a.
<to be read again> 
                   1
l.20        \caption{no label}

You meant to type ## instead of #, right?
Or maybe a } was forgotten somewhere earlier, and things
are all screwed up? I'm going to assume that you meant ##.

\storelabel{##1}を に置き換えると\storelabel{mylabel}、pdf ファイルは同じように表示され、エラー メッセージは表示されなくなります。しかし、明らかにこれは私が望んでいることではありません。

アップデート: このMWEは同じエラーをうまく表示します。\labelこれは、ラベルから抜け出し\captionshowlabelsラベルを移動させるという私の当初の目標とは関係ありませんが、

\documentclass{article}
\begin{document}
\begin{table}
    \caption{\def\foo[#1]{#1}}
\end{table}
\end{document}

答え1

私の見解では、 をキャッチして\labelにラベル名を格納し\storedlabel、が発行された後に\caption実数\labelを の末尾にシフトする方が適切です。\@caption\@makecaption

の再定義がのスタイル\labelを打ち破ります!cleveref\label[...]{foo}

\documentclass{article}
\usepackage{showlabels}
\usepackage{xparse}
\usepackage{letltxmacro}

\usepackage{xpatch}

\usepackage{cleveref} % Just for testing!

\makeatletter

\LetLtxMacro\latex@@origlabel\label

\xpatchcmd{%
  \caption
}{%
  \refstepcounter\@captype%
}{%
  \let\storedlabel\undefined%
  \refstepcounter\@captype
  \begingroup
  \renewcommand{\label}[1]{%
     \gdef\storedlabel{##1}%  Catch the  the label but doing nothing except of storing it!
   }
   \endgroup
 }{\typeout{Successfully patched caption}}{\typeout{Failed in patching caption}}


\xpatchcmd{\@caption}{%
  \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
  \endgroup}{%
  \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
  \endgroup%
  \@ifundefined{storedlabel}{}{%  Transfer the label to this place
    \label@@origlabel{\storedlabel}}%
}{\typeout{Success}}{\typeout{Failure!}}
\makeatother

\begin{document}
  \begin{table}
        \caption{no label}
        foo
    \end{table}
    \begin{table}
        \caption{\label{othermylabel}label inside caption (front)}
        foo
    \end{table}
    \begin{table}
        \caption{label inside caption (back) \label{mylabel}}
        foo
    \end{table}
    \begin{table}
        \caption{label directly after caption}
        \label{mylabelfoo}
        foo
    \end{table}
    \begin{table}
      \caption{label at end of table (I'm OK with that one)}
      foo
      \label{mylabelfoobar}
    \end{table}

Now some referencing: \cref{othermylabel} and \ref{mylabel} and \ref{mylabelfoo} and \ref{mylabelfoobar}
\end{document}

ここに画像の説明を入力してください

答え2

これは機能します:

\documentclass{article}
%\usepackage{caption}
\usepackage{showlabels}
\usepackage{xpatch}
\def\storelabel#1{\gdef\storedlabel{#1}}
\makeatletter
\patchcmd{\@caption}{#3}{\global\let\storedlabel\undefined\let\label\storelabel#3}{}{err}
\apptocmd{\@caption}{\ifdefined\storedlabel\label{\storedlabel}\else\fi}{}{err}
\makeatother
\begin{document}
    \listoftables
    \clearpage
    \begin{table}
        \caption{no label}
        foo
    \end{table}
    \begin{table}
        \caption{\label{mylabel}label inside caption (front)}
        foo
    \end{table}
    \begin{table}
        \caption{label inside caption (back) \label{mylabel}}
        foo
    \end{table}
    \begin{table}
        \caption{label directly after caption}
        \label{mylabel}
        foo
    \end{table}
    \begin{table}
        \caption{label at end of table (I'm OK with that one)}
        foo
        \label{mylabel}
    \end{table}
\end{document}

主な違いは

  • \def\label##1{...}-> 、内部の\let\label\storelabel引数の使用を避ける##1\caption
  • @ChristianHupfer に触発され、感謝の意を表して、を再定義する代わりにxpatchを選択してパッチを適用します。 は、パッケージ および でも機能するようになりました。\@caption\captioncaption\listoftables

彼のコメントは依然として有効です。\labelオプションの引数を使用すると失敗します。しかし、私にはそれは必要ありません。

関連情報