7

I'd like to open an environment, passing the content of a macro to the optional arguments. Up to now I tried different approaches using \expandafter, however I could not get the expected behaviour.

\RequirePackage{graphicx}
\RequirePackage{xkeyval}

% In my original code I've got some key definition
% for [myStyle]{floating} at this place, I guess the real
% definition does not matter but would distract.

% Place an image within a floating environment and add caption
% and label automatically
\newcommand{\img}[2][]{
    \setkeys*{Gin}{#1}
    \setkeys[myStyle]{floating}{\XKV@rm}

    \begin{figure}[\XKV@myStyle@floating@placement@value]
        \includegraphics{#2}
        \caption{\XKV@myStyle@floating@caption@value}
        \label{fig:\XKV@myStyle@floating@label@value}
    \end{figure}
}

Now, when I'll try to use that \img command like:

\img[caption = A picture, label = TheLabel, placement = h!]{mm-01-01}

The picture get's inserted, it has the label and the caption, but the placement option seems to be ignored.

Why? And how do I solve this without defining a new environment?

Below you'll find the complete code:

\documentclass[
     paper = a4,
     fontsize = 11pt,
     index = totoc,
     listof = totoc,
     parskip
]{scrartcl}



\usepackage{xkeyval}
\usepackage{graphicx}
\usepackage{lipsum}



\makeatletter
% \parameter caption The caption of the item within the floating environment.
% If caption is empty, no caption will be placed.
\define@key[myStyle]{floating}{caption}[]{
    \PackageInfo{myStyle}{Setting caption to "#1"}
}

% \parameter label The label of the item within the floating environment.
% If label is empty, no label will be placed.
\define@key[myStyle]{floating}{label}[]{
     \PackageInfo{myStyle}{Setting label to "#1"}
}

% \parameter placement Can be used in the same way as the optional placement
% argumants of floating environments
\define@key[myStyle]{floating}{placement}[]{
    \PackageInfo{myStyle}{Setting placement to "#1"}
}

% Setting default values.
\savekeys[myStyle]{floating}{caption,label,placement}
\presetkeys[myStyle]{floating}{caption, label, placement=htbp}{}



\newcommand{\img}[2][]{
     \setkeys*{Gin}{#1}
     \setrmkeys[myStyle]{floating}
     \begin{figure}
         \centering
         \includegraphics{#2}
         \caption{\XKV@myStyle@floating@caption@value}
         \label{fig:\XKV@myStyle@floating@label@value}
     \end{figure}
}
\makeatother



\begin{document}
\lipsum[2]

The picture \ref{fig:APicture} shall be located exactly after this line,
however it goes on the top of the page
\img[
    label = APicture,
    caption = Witwe Bolte,
    placement = h!,
    width = 0.3\textwidth
]{mm-01-01}

\lipsum[3]
\end{document}
  • 1
    Welcome to TeX.SX! Can you add complete compilable code? As the question stands now, it's quite difficult to say something, because probably the answer depends on how you actually set up the keys. – egreg Sep 9 '13 at 12:34
  • The syntax of \newcommand is \newcommand{\img}{something} or \newcommand{\img}[3]{something with #1,#2,#3}, so here I don't understand what you are trying to achieve. – Bruno Le Floch Sep 9 '13 at 12:34
  • Thank you Bruno, this was a copy-and-paste issue. I corrected the code example – Ralf Sep 9 '13 at 12:37
  • Thank you @egreg for the hint. I've added the complete example – Ralf Sep 9 '13 at 13:56
  • @Ralf I've modified my code to reflect yours. – egreg Sep 9 '13 at 14:04
6

For figure you can use

\begin{figure}

with no option but before that set the default value:

\let\fps@figure\XKV@myStyle@floating@placement@value

in general you can

\def\zz{\begin{figure}[}
\expandafter\zz\XKV@myStyle@floating@placement@value]
  • Thank you, both solutions are working fine. Now I'm not really sure which solution to use: Does the \let\fps@figure variant affect all future use \begin{figure}? (until the next \let\fps@figure) And what is the scope of the zz in your second example? Is this only valid within the img command? – Ralf Sep 9 '13 at 13:35
  • both are local definitions so have scope determined by {} or \begingroup \endgroup or latex \begin \end so to make them local you place an additional \begingroup \endgroup around all the content of you \img definition. – David Carlisle Sep 9 '13 at 13:47
4

There's no \XKV@myStyle@floating@placement@value defined when you do

\define@cmdkey[myStyle]{floating}{placement}{}

The macro that stores the value is instead \cmdmyStyle@floating@placement. So here's what you probably want to do:

\documentclass{article}
\usepackage{xkeyval}
\usepackage[demo]{graphicx}
\usepackage{lipsum}

\makeatletter
\define@cmdkey[myStyle]{floating}{caption}[]{\PackageInfo{myStyle}{Setting caption to "#1"}}
\define@cmdkey[myStyle]{floating}{label}[]{\PackageInfo{myStyle}{Setting label to "#1"}}
\define@cmdkey[myStyle]{floating}{placement}[]{\PackageInfo{myStyle}{Setting caption to "#1"}}
\newcommand{\img}[2][]{%
  \begingroup % don't clutter the key values for the following \img commands
  \setkeys*{Gin}{#1}%
  \setrmkeys[myStyle]{floating}%
  \begingroup\edef\x{\endgroup\noexpand\begin{figure}[\cmdmyStyle@floating@placement]}\x
    \includegraphics{#2}
    \caption{\cmdmyStyle@floating@caption}
    \label{fig:\cmdmyStyle@floating@label}
  \end{figure}
  \endgroup
}
% Setting default values.
\savekeys[myStyle]{floating}{caption,label,placement}
\presetkeys[myStyle]{floating}{caption, label, placement=htbp}{}
\makeatother

\begin{document}
First the references: \ref{fig:TheLabel1} and \ref{fig:TheLabel2}

\lipsum[1]

\img[
  caption = A picture,
  label = TheLabel1,
  placement = h!,
  width=\textwidth,
]{mm-01-01}

\lipsum[2-4]

\img[
  caption = A picture,
  label = TheLabel2,
  placement = t,
  width=\textwidth,
]{mm-01-01}

\lipsum[3]

\end{document}

enter image description here

  • 1
    I believe it's the line \begingroup\edef\x{\endgroup\noexpand\begin{figure}[\cmdmyStyle@floating@placement]}\x that makes it working. It seems to be almost the same as the second solution posted by David Carlisle. What is the difference in functionality? – Ralf Sep 9 '13 at 14:08
  • 1
    @Ralf It's indeed similar. This is the sledgehammer version. – egreg Sep 9 '13 at 14:12

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.