6

I have written the following two \newcommand for inserting figures with or without a caption, respectively.

% for fig with caption: #1: width/size; #2: fig file; #3: fig caption
\newcommand{\figwithcaption}[3]{
  \begin{figure}[htp]
    \centering
      \includegraphics[#1]{#2}
      \caption{#3}
  \end{figure}
}

% for fig without caption: #1: width/size; #2: fig file
\newcommand{\fignocaption}[2]{
  \begin{figure}[htp]
    \centering
    \includegraphics[#1]{#2}
  \end{figure}
}

How to unify them into one \newcommand called, say, \fig which differentiates the two cases above according to the actual number of arguments it receives?

\fig{width = 0.50\textwidth}{fig/duck.pdf} % for fig without caption
\fig{width = 0.50\textwidth}{fig/duck.pdf}{A duck.} % for fig with caption
  • 2
    I would not recommend this as it makes the code very hard to read (better to make editor templates/shortcuts). But this can be done using the xparse package (it uses a different syntax), it can do optional arguments in {}'s (I think it is the g specifier), then you can test of #3 has a value, and if it has add a caption. – daleif Mar 16 '17 at 13:38
  • @daleif I would prefer \NewDocumentCommand\fig{mmo}{..\includegraphics[{#1}]{#2}..\IfValueT{#3}{\caption{#3}}..}. That way it still has the usual LaTeX way for optional arguments \fig{..}{..}[optional caption]. – Manuel Mar 16 '17 at 13:57
  • @Manuel that would still work with the g modifier, and it is still safe as long as there is a space after the argument. But I still agree with David, users should not do this – daleif Mar 16 '17 at 14:06
7

Really I wouldn't use a command at all, it is better to use the enviornment syntax (for example it helps editors to syntax highlight or give context sensitive help if you don't hide the standard syntax)

If you do use a command beware adding extra white space (your definitions add several space tokens).

That said, \newcommand supports defining commands with an optional argument.

\newcommand{\fig}[3][\relax]{%
  \begin{figure}[htp]%
    \centering
      \includegraphics[#2]{#3}%
      \ifx\relax#1\else\caption{#1}\fi
  \end{figure}%
}

\fig{width = 0.50\textwidth}{fig/duck.pdf} % for fig without caption
\fig[Zzzzz]{width = 0.50\textwidth}{fig/duck.pdf} % for fig without caption
  • I have to upvote, because your macro is identical to the one I was about to post, even down to the \relax. – Steven B. Segletes Mar 16 '17 at 13:57
  • Really great and simple answer. I had a similar need and implemented the method described in that thread. Are there any significant differences in efficiency? Would you say that your approach is "better"? – Florian Mar 16 '17 at 14:01
  • 1
    @StevenB.Segletes sorry I couldn't squeeze stackengine in. – David Carlisle Mar 16 '17 at 15:03
  • 1
    @Florian The newcommand version is easier to read so in human efficiency it wins. Possibly the lower level version takes a couple of expansions less, but if you can time the difference you have a very slow computer or several million instances of this in the document. But as I say, I recommend doing neither. – David Carlisle Mar 16 '17 at 15:06
3

I don't think you gain too much with this approach. Anyway, here's a possible implementation.

\documentclass{article}
\usepackage{graphicx,xparse}

\ExplSyntaxOn
\NewDocumentCommand{\hfig}{O{}mO{}}
 {
  \group_begin:
  \keys_set:nn { hengxin/fig } { #3 }
  \use:x { \exp_not:N \begin{figure}[\l_hengxin_hfig_pos_tl] }
  \centering
  \includegraphics[#1]{#2}
  \tl_if_empty:NF \l_hengxin_hfig_caption_tl
   {
    \tl_if_empty:NTF \l_hengxin_hfig_shortcaption_tl
     {
      \caption{\l_hengxin_hfig_caption_tl}
     }
     {
      \caption[\l_hengxin_hfig_shortcaption_tl]{\l_hengxin_hfig_caption_tl}
     }
   }
  \end{figure}
  \group_end:
 }
\keys_define:nn { hengxin/fig }
 {
  caption .tl_set:N = \l_hengxin_hfig_caption_tl,
  shortcaption .tl_set:N = \l_hengxin_hfig_shortcaption_tl,
  pos .tl_set:N = \l_hengxin_hfig_pos_tl,
  pos .initial:n = htp,
 }
\ExplSyntaxOff

\begin{document}

\hfig[width=.3\textwidth]{example-image-a}

\hfig[width=.3\textwidth]{example-image-b}[
  caption=This is a caption\label{aaa},
  pos=bp
]

\end{document}

You can also specify a shortcaption key, for the case \caption[Short]{Long}.

enter image description here

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.