我可以让LaTeX宏'返回'文件名吗?

时间:2010-05-18 09:55:24

标签: latex macros return-value tex

我正在撰写我的论文/论文,由于它正在进行的工作,我并不总是准备好实际的图像为我放入文档的数字做好准备,但出于各种原因希望自动用它替代虚拟当包含的图形文件不存在时图。例如。我可以执行\includegraphics[width=8cm]{\chapdir/figures/fluxcapacitor}之类的操作(其中\chapdir是我的“当前”章节目录的宏,例如\def\chapdir{./ch_timetravel},如果没有./ch_timetravel/figures/fluxcapacitor.jpg则会插入./commands/dummy.jpg相反。

我构建了我的宏(也许是天真的?),所以我有一个宏(\figFileOrDummy)通过检查提供给它的参数是否存在来确定要包含的相应文件,以便我可以调用{ {1}}。除了我遇到各种各样的错误,这取决于我如何调用它,这似乎表明我正在以一种根本上有缺陷的方式解决问题,就像“好的LaTeX编程”一样。

这是检查文件是否存在的宏(并且'返回'文件名或虚拟文件名):

\includegraphics[properties]{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}

或者,这是一个更简单的版本,似乎有类似的问题:


\newcommand{\figFileOrDummy}[1]{%
    % Figure base name (no extension) to be used if the file exists
    \def\fodname{#1}%
    \def\dummyfig{commands/dummy}%
    % Check if output is PS (.EPS) or PDF (.JPG/.PDF/.PNG/...) figures
    \ifx\pdfoutput\undefined%
        % EPS figures only
        \IfFileExists{\fodname.eps}{}{\def\fodname{\dummyfig}}%
    \else%
        % Check existence of various extensions: PDF, TIF, TIFF, JPG, JPEG, PNG, MPS
        \def\figtest{0}% flag below compared to this value
        \IfFileExists{\fodname.pdf}{\def\figfilenamefound{1}}{\def\figfilenamefound{0}}%
        \IfFileExists{\fodname.jpg}{\def\figfilenamefound{1}}{}%
        \IfFileExists{\fodname.png}{\def\figfilenamefound{1}}{}%
        % and so on...
        % If no files found matching the filename (flag is 0) then use the dummy figure
        \ifx\figfilenamefound\figtest%
            \def\fodname{\dummyfig}%
        \fi%
    \fi%
    % 'return' the filename
    \fodname%
}%

在扩展他们试图定义的宏之后,\newcommand{\figFileOrDummy}[1]{% \def\dummyfig{commands/dummy}% \dummyfig% } 命令似乎被处理,因此它最终成为\def(注意{之后的空格} {1}})并且明显抱怨。

此外,它似乎将宏的文字内容视为\def {commands/dummy}...的文件名,而不是先解析/扩展它,所以抱怨文件\def不存在..

我也尝试过做类似的事情 \includegraphics尝试强制它使'\def {commands/dummy}... .png'只保留而不是完整的宏,但我收到\edef\figfilename{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}错误抱怨变量我是在\figfilename宏中尝试Undefined control sequence未定义。

所以我的问题是

  1. 如何正确展开此宏?
  2. 如果这是构造我的宏的错误方法,我应该如何实际构造这样一个宏,以便能够自动插入虚拟/真实数字?
  3. 是否有一个包已经很好地处理了这种类型的东西我忽略了?
  4. 我觉得我错过了一些非常基本的东西......

3 个答案:

答案 0 :(得分:3)

我认为重点是\ expandafter只对其参数感兴趣,因为它是一个表示文件名的字符串,所以不评估它 - 宏语言是懒惰的!试试\expandafter {\includegraphics[width=8cm]}{\chapdir/figures/fluxcapacitor}

两点风格:

  1. 如果行以控制序列结束,则不需要在行的末尾放置%来停止虚假空格:控制序列吞噬所有后续空格,包括行尾。根据我的口味,这使得代码更具可读性。请注意,特别是对于Tex的“嘴”,\def\newcs{abc}\def \newcs {abc}都是相同的:它们与令牌序列完全相同。
  2. 我删除了代码\ figtest:如果使用\ newif原语(使用\ newif \ figexists创建新测试,使用\ figexiststrue设置/重置,\ figexistsfalse),您可以获得更好的错误报告 - 与Tex一样高价 - ,并使用\ iffigexists ...)或Latex ifthenelse包测试(以保持正统)。
  3. 清理代码

    我首先想到问题出在其他地方,所以写了一些更漂亮的东西:

    \def\dummypath{commands/dummy}%
    \ifx\pdfoutput\undefined
    \def\figFileOrDummy#1{\IfFileExists
        {#1.eps}{#1}\dummypath}
    \else
    \def\figFileOrDummy#1{\IfFileExists
        {#1.pdf}{#1}{\IfFileExists
          {#1.jpg}{#1}{\IfFileExists
            {#1.png}{#1}\dummypath}}} %or have more graphics types, if you like.
    \fi
    

答案 1 :(得分:2)

好吧,所以我找到了#2的可能答案,通过重组宏的工作方式(并且使用Charles Stewart的回答中的一些建议 - 我承认我不喜欢'外观'什么似乎被广泛认为是好的LaTeX代码,我可能在我的C / C ++方式中根深蒂固地成为一名真正的LaTeX程序员。)

无论如何,我的回答......

不要尝试在宏中生成文件名以将传递给 \includegraphics宏,而是创建一个包裹\includegraphics的宏并将其传递给真实或虚拟文件名称。这似乎避免传递(作为参数)一个长脚本/宏,虽然我没有看到任何好的理由为什么它应该以这种方式编写。但它确实工作 ......

% Dummy figure file
\def\dummyfigure{commands/dummy}%

% Includegraphics wrapper macro to include either dummy or real figure
\ifx\pdfoutput\undefined
\newcommand{\incgfx}[2]{%
    \def\testfile{\chapdir/fig/#2}%
    \IfFileExists{\testfile.eps}%
        {\includegraphics[#1]{\testfile}}% test file found
        {\includegraphics[#1]{\dummyfigure}}% test file not found
}
\else
\newcommand{\incgfx}[2]{%
    \def\figfilename{\dummyfigure}
    \def\testfile{\chapdir/fig/#2}
    \IfFileExists{\testfile.jpg}{\def\figfilename{\testfile}}{}
    \IfFileExists{\testfile.png}{\def\figfilename{\testfile}}{}
    \IfFileExists{\testfile.pdf}{\def\figfilename{\testfile}}{}
    \IfFileExists{\testfile.jpeg}{\def\figfilename{\testfile}}{}
    \IfFileExists{\testfile.tif}{\def\figfilename{\testfile}}{}
    \IfFileExists{\testfile.tiff}{\def\figfilename{\testfile}}{}
    \includegraphics[#1]{\figfilename}
}
\fi

这允许人们按预期使用它:

\begin{figure}
    \begin{center}
        \incgfx{height=3cm}{\chapdir/fig/fluxcapacitor}
        \caption{...}\label{fig:...}
    \end{center}
\end{figure}

同样,我想有一种方法可以使原始想法发挥作用,而不是为现有功能制作包装器,但现在这样做......

答案 2 :(得分:1)

回答#3:为此,我发现todonotes包非常有用。它没有提供代码所要提供的自动化级别,但是它有一个非常好的\missingfigure命令,可以让你设置一个虚拟框,你猜它是一个缺失的数字。