TransWikia.com

Format reference and subref of subcaption

TeX - LaTeX Asked on July 10, 2021

Is it possible to format the ref and subref of a subcaption completely independently?

The manual suggests changing thesubfigure to change the the label of a subfigure and hence the output of ref, but then this affect subref as well.

For example, the following MWE

documentclass{article}
usepackage{subcaption}
usepackage{cleveref}
usepackage{tikz}

% and example figure
defexfigure#1#2{
  begin{subfigure}[b]{0.3linewidth}
    centering
    begin{tikzpicture}path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);end{tikzpicture}
    renewcommand{thesubfigure}{#1}%
    phantomsubcaption%
    label{#2}%
  end{subfigure}hfill}

DeclareCaptionLabelFormat{subreffig}{(emph{#2})}
captionsetup{subrefformat=subreffig}

begin{document}
begin{figure}
  exfigure{red}{subfig1}
  exfigure{green}{subfig2}
  exfigure{blue}{subfig3}
  caption{Three squares. Left: subref{subfig1}. Center: subref{subfig2}.
    Right: subref{subfig3}.}
  label{fig:all}
end{figure}

In cref{fig:all}, we have three subfigures cref{subfig1}
cref{subfig2} and cref{subfig3}.
end{document}

The figure has the following caption

Figure 1: Three squares. Left: (red). Center: (green). Right: (blue).

This is the output I am after. However, the text afterwards has

In fig. 1, we have three subfigures fig. 1red fig. 1green and fig. 1blue.

Is it possible to change it to

In fig. 1, we have three subfigures fig. 1-[red] fig. 1-[green] and fig. 1-[blue].

Changing the definition of thesubfigure to

renewcommand{thesubfigure}{-[#1]}%

gives the correct output in text, but the wrong output in the caption.

2 Answers

I was able to get it to work without cleveref. Both subcaption and cleveref (not to mention hyperref) modify label in many ways, producing a legion of newlabel commands in the aux file. So I went back to basics and used protected@write instead.

documentclass{article}
usepackage{subcaption}
%usepackage{cleveref}
usepackage{tikz}

makeatletter
newcommand{sublabel}[1]{refstepcounter{subfigure}%
  protected@write@auxout{}{stringnewlabel{sub@#1}{{(stringemph{thesubfigure})}{thepage}}}%
  protected@write@auxout{}{stringnewlabel{#1}{{thefigure-[thesubfigure]}{thepage}}}}
makeatother

% and example figure
defexfigure#1#2{
  begin{subfigure}[b]{0.3linewidth}
    centering
    begin{tikzpicture}path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);end{tikzpicture}
    renewcommand{thesubfigure}{#1}%
    sublabel{#2}%
  end{subfigure}hfill}

begin{document}
begin{figure}
  exfigure{red}{subfig1}
  exfigure{green}{subfig2}
  exfigure{blue}{subfig3}
  caption{Three squares. Left: subref{subfig1}. Center: subref{subfig2}.
    Right: subref{subfig3}.}
  label{fig:all}
end{figure}

In ref{fig:all}, we have three subfigures ref{subfig1}
ref{subfig2} and ref{subfig3}.
end{document}

This version is compatible to both cleveref and hyperref. The key is to format thesubfigure for cref and @currentlabel for ref and subref.

documentclass{article}
usepackage{tikz}
usepackage{subcaption}
usepackage{hyperref}
usepackage{cleveref}

makeatletter
newcommand{sublabel}[2]{% #1 = color, #2 = label
  refstepcounter{subfigure}%
  edef@currentlabel{(noexpandemph{#1})}nosublabel{sub@#2}%
  edef@currentlabel{thefigure-[#1]}nosublabel{#2}%
  ignorespaces}
makeatother

% and example figure
defexfigure#1#2{letnosublabel=label
  begin{subfigure}[b]{0.3linewidth}
    centering
    begin{tikzpicture}path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);end{tikzpicture}
    renewcommand{thesubfigure}{-[#1]}% for cref
    sublabel{#1}{#2}
  end{subfigure}hfill}

begin{document}
begin{figure}
  exfigure{red}{subfig1}
  exfigure{green}{subfig2}
  exfigure{blue}{subfig3}
  caption{Three squares. Left: subref{subfig1}. Center: subref{subfig2}.
    Right: subref{subfig3}.}
  label{fig:all}
end{figure}

In cref{fig:all}, we have three subfigures cref{subfig1}
cref{subfig2} and cref{subfig3}.
end{document}

begin{document}
begin{figure}
  exfigure{red}{subfig1}
  exfigure{green}{subfig2}
  exfigure{blue}{subfig3}
  caption{Three squares. Left: subref{subfig1}. Center: subref{subfig2}.
    Right: subref{subfig3}.}
  label{fig:all}
end{figure}

In cref{fig:all}, we have three subfigures cref{subfig1}
cref{subfig2} and cref{subfig3}.
end{document}

Correct answer by John Kormylo on July 10, 2021

A possible solution based on the internals of subcaption

documentclass{article}
usepackage{subcaption}
usepackage{cleveref}
usepackage{tikz}

newcommand{thesubreffigure}{thesubfigure}

makeatletter
renewcommand*subcaption@@label[2]{%
  @bsphackbegingroup
    subcaption@ORI@label#1{#2}%
    letSK@@gobbletwo
    protected@edef@currentlabel{csname thesubref@captypeendcsname}%
    subcaption@ORI@label#1{sub@#2}%
  endgroup@esphack}
makeatother

% and example figure
defexfigure#1#2{
  begin{subfigure}[b]{0.3linewidth}
    centering
    begin{tikzpicture}path[draw=#1,fill=#1!20] (0,0) rectangle
      (4,4);end{tikzpicture}
    % renewcommand{thesubfigure}{#1}
    %
    renewcommand{thesubfigure}{-[#1]}%
    renewcommand{thesubreffigure}{#1}%
    phantomsubcaption%
    label{#2}%
  end{subfigure}hfill}

DeclareCaptionLabelFormat{subreffig}{(emph{#2})}
captionsetup{subrefformat=subreffig}

begin{document}
begin{figure}
  exfigure{red}{subfig1}
  exfigure{green}{subfig2}
  exfigure{blue}{subfig3}
  caption{Three squares. Left: subref{subfig1}. Center: subref{subfig2}.
    Right: subref{subfig3}.}
  label{fig:all}
end{figure}

In cref{fig:all}, we have three subfigures cref{subfig1}
cref{subfig2} and cref{subfig3}.
end{document}

Produces the correct output for both cref and subref. Unfortunately does not produce the correct label when setting a caption instead of using phantomsubcaption.

Answered by Tohiko on July 10, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP