3

I like to define a custom figure command with multiple sub-labels and references in the caption:

\documentclass[varwidth=100pt]{standalone}
\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{pgf}
\pgfkeys{/myfigure/.is family, /myfigure,
label a/.initial=a,
label a/.store in =\labelA,
label b/.initial=b,
label b/.store in =\labelB,
caption a/.initial={},
caption b/.initial={},
}

\pgfkeys{myfigure,#1}
\newcommand\myfigure[1]{
\begin{figure}
    {\phantomsubcaption\label{\labelA}
    \phantomsubcaption\label{\labelB}}
    \includegraphics[width=100pt]{example-image-a}
    \caption{
        (\subref{\labelA}) \pgfkeysvalueof{/myfigure/caption a} 
        (\subref{\labelB}) \pgfkeysvalueof{/myfigure/caption b} 
    }
\end{figure}
}

\begin{document}

\myfigure{
    label a = figa,
    caption a = caption 1,
    label b = figb,
    caption  b = caption 2,
}

\end{document}

The result should look like

enter image description here

Is it possible to define \myfigure{...} such that don't need to define a variable for each sub-label/sub-caption? E.g.:

\myfigure{
    label = figa,
    caption = caption 1,
    label = figb
    caption = caption 2,
}

Here is a failed attempt of my idea:

\documentclass[varwidth=100pt]{standalone}
\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{pgf}

\pgfkeys{/myfigure/.is family, /myfigure,
sublabels/.initial = {},
fullcaption/.initial = {},
label/.initial=a,
label/.store in=\mylabel,
label/.style={sublabels/.append={\phantomsubcaption\label{subfig:#1}}},
caption/.initial={},
caption/.style={fullcaption/.append={(\subref{subfig:\mylabel}) #1}},
}

\newcommand\myfigure[1]{
\pgfkeys{/myfigure,#1}
\begin{figure}
    \pgfkeys{/myfigure, sublabels}
    \includegraphics[width=100pt]{example-image-a}
    \pgfkeys{/myfigure, fullcaption}
\end{figure}
}

\begin{document}

\myfigure{
    label = figa,
    caption = caption 1,
    label = figb,
    caption = caption 2,
}

\ref{subfig:figa}

\end{document}

Here, I just get the error message

! Undefined control sequence. sub@subfig:\mylabel

enter image description here

Somehow \mylabel does not get expanded inside fullcaption/.style

  • Why exactly are you loading subcaption? You don't seem to be using it. – cfr Dec 11 '16 at 21:15
  • @cfr I am using the \phantomsubcaption and \subref command. – grbl Dec 11 '16 at 22:27
  • I guess what I really mean is, why not just use sub-captions if these are sub-0captions? Why roll your own? – cfr Dec 12 '16 at 0:51
4

The basic idea is to store the label/caption pairs as \mysubcap{label}{caption} in a macro \mysubcaps. After processing the pgfkeys in your example, \mysubcaps will contain

\mysubcap{figa}{caption 1}\mysubcap{figb}{caption 2}

Now you can process these pairs by \letting \mysubcap to a command with two arguments and then executing \mysubcaps. By \leting \mysubcap to different commands, you can process the pairs in different ways.

To be able to specify the pairs in the form

\myfigure{subcaption={figa}{caption 1},subcaption={figb}{caption 2}}

we set up the pgf key subcaption as

\pgfkeys
  {/myfigure/subcaption/.code 2 args=
    {\expandafter\def\expandafter\mysubcaps\expandafter
       {\mysubcaps\mysubcap{#1}{#2}%
       }%
    }%
  }

To process the options, we have to clear the macro \mysubcaps and then call \pgfkeys with the options.

\def\mysubcaps{}%
\pgfkeys{/myfigure/.cd,subcaption={figa}{caption 1},subcaption={figb}{caption 2}}%

Below is the complete code that integrates the fragments into the definition of your command \myfigure. One caveat: Using fancy macros in a \caption command may result in all kinds of strange errors, since \caption writes its argument in expanded form to the aux file. At least for the testing phase I recommend to use \caption[]{...} instead of \caption{...}; then the empty optional argument is written to the aux file.

enter image description here

\documentclass{article}
\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{pgfkeys}
\pgfkeys
  {/myfigure/subcaption/.code 2 args=
    {\expandafter\def\expandafter\mysubcaps\expandafter
       {\mysubcaps\mysubcap{#1}{#2}%
       }%
    }%
  }
\newcommand\mysubcap{}% make sure \mysubcap is not in use
\newcommand\mysubcaps{}% make sure \mysubcaps is not in use
\newcommand\mysubcapphantom[2]{{\phantomsubcaption\label{#1}}}
\newcommand\mysubcapsubref[2]{ (\subref{#1}) #2}
\newcommand\myfigure[1]%
  {\def\mysubcaps{}% clear \mysubcaps
   \pgfkeys{/myfigure/.cd,#1}% store subcaption={X}{Y} as \mysubcap{X}{Y} in \mysubcaps
   \begin{figure}
   \centering
   \let\mysubcap\mysubcapphantom
   \mysubcaps
   \includegraphics[width=100pt]{example-image-a}%
   \let\mysubcap\mysubcapsubref
   \caption{\mysubcaps}%
   \end{figure}
  }
\begin{document}
\myfigure
  {subcaption={figa}{caption 1},
   subcaption={figb}{caption 2}
  }

\end{document}
  • Thank you @gernot! I will take a look into this \expandafter socery. – grbl Dec 11 '16 at 21:47
  • @grbl There is no sorcery involved. Basically we do \def\list{\list\newitem} to append the new item to the list. For this to work we have to expand the \list in the body of the macro before redefining \list. This is done by inserting an \expandafter between any two tokens up to the \list that should be expanded first. – gernot Dec 11 '16 at 21:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.