5

I want to wrap a macro around figure-env to make my document more readable. Here is minimal example of how it is now:

\documentclass[10pt,a4paper]{article}
\usepackage{keyval}

\makeatletter

\define@key{image}{pos}{\def\i@pos{#1}} % define key-val
\setkeys{image}{pos=!htbp} % set default
\newcommand{\image}[2][]{%
  \begingroup%
  \setkeys{image}{#1}% set passed key-vals
  \begin{figure}[\i@pos] % use positon
    \centerline{\includegraphics[width=\textwidth]{#2}}
  \end{figure}
  \endgroup%}

\makeatother
\begin{document}
\end{document}

but it seems that the default position !htbp is not set, because if i set it directly in \begin{figure}[!htbp] it works perfectly fine and the images are positioned correctly.

Edit: I added \begin{document} and \end{document} as suggested in the comments to make it compileable.

I appreciate you help.

  • Welcome to TeX.SX! Please make your code compilable (if possible), or at least complete it with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem tedious to you, but think of the extra work it represents for TeX.SX users willing to give you a hand. Help them help you: remove that one hurdle between you and a solution to your problem. – cfr Aug 16 '14 at 21:57
  • 2
    \centerline shouldn't usually be used in latex (it is a relic of the plain tex base) and it does nothing with an image that is \textwidth wide. – David Carlisle Aug 16 '14 at 21:59
  • @cfr: Thank you for the advice I added the two lines. @DavidCarlisle: I did not know that but actually \textwidth her is only because I usually provide more parameters where the images are scaled down if it looks better. Is there a better way to center it? – satanik Aug 16 '14 at 22:54
5

\begin{figure} doesn't expand the optional argument; when expansion happens it's too late.

\documentclass[10pt,a4paper]{article}
\usepackage{keyval}
\usepackage[demo]{graphicx}% draft is just for the example

\makeatletter

\define@key{image}{pos}{\def\i@pos{#1}} % define key-val
\setkeys{image}{pos=!htbp} % set default
\newcommand{\image}[2][]{%
  \begingroup
  \setkeys{image}{#1}% set passed key-vals
  \def\@temp{\begin{figure}}%
  \expandafter\@temp\expandafter[\i@pos]% use position
  \centering
  \includegraphics[width=\textwidth]{#2}
  \end{figure}
  \endgroup}

\makeatother

\begin{document}
Some text

\image[pos=!htbp]{foo}

Some other text
\end{document}

Alternatively, since the value given to pos is formed by unexpandable tokens,

\newcommand{\image}[2][]{%
  \begingroup
  \setkeys{image}{#1}% set passed key-vals
  \begingroup\edef\x{\endgroup
    \noexpand\begin{figure}[\i@pos]}\x % use position
  \centering
  \includegraphics[width=\textwidth]{#2}
  \end{figure}
  \endgroup}

enter image description here

  • This works perfecly. I came across those expanding stuff quite often but did not understand it, can you first explain how it works and secondly what the exact difference between the first and the second solution is? – satanik Aug 16 '14 at 23:03
  • I just came across another question, why is it only this argument I have to treat differently? – satanik Aug 16 '14 at 23:19
  • @satanik In the first definition of \image, \@temp becomes \begin{figure} after [\i@pos] has become [!htbp] (it's a common trick for jumping over many tokens without needing a hord of \expandafter. The second definition fully expands (but \begin is left intact); choosing which one depends on the nature of the macro we want to expand and whether we want full expansion rather than one level only. Why this is needed for \begin{figure} depends on the implementation of the \@xfloat command. – egreg Aug 17 '14 at 8:35

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.