我可以制作一个 LaTeX 宏“返回”吗?文件名?
我正在写我的论文/论文,由于它是一项正在进行的工作,我并不总是为我放入文档中的图形准备好实际图像,但由于各种原因希望自动用它代替虚拟图形当包含的图形文件不存在时。例如,我可以执行类似 \includegraphics[width=8cm]{\chapdir/figures/fluxcapacitor}
的操作(其中 \chapdir
是我的“当前”章节目录的宏,例如 \def\chapdir{./ch_timetravel}
如果没有 ./ch_timetravel/figures/fluxcapacitor.jpg
它将插入 ./commands/dummy。 。
我已经构造了我的宏(也许很天真?),以便我有一个宏(\figFileOrDummy
),它通过检查是否提供给它的参数来确定要包含的适当文件 存在,这样我就可以调用 \includegraphics[properties]{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}
,但根据我尝试调用它的方式,我会收到各种错误。就“良好的 LaTeX 编程”而言,我正在以一种根本上有缺陷的方式解决这个问题。
这是检查文件是否存在的宏(并“返回”文件名或虚拟文件名):
\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
命令似乎是在他们试图定义的宏扩展之后处理的,所以它最终被\def {commands/dummy}...
(注意 \def
后面的空格)并且明显抱怨。
此外,它似乎将宏的文字内容视为 \includegraphics
的文件名,而不是首先解析/扩展它,因此抱怨文件 '\def {commands/dummy}. .. .png'
不存在..
我也尝试过做类似的事情 \edef\figfilename{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}
尝试强制它使 \figfilename
仅保存值而不是完整的宏,但我收到一个 未定义的控制序列
错误,抱怨我试图在 \figFileOrDummy
宏中 \def
的变量未定义。
所以我的问题是
- 如何使这个宏正确扩展? 或
- 如果这是构造我的宏的错误方式,我实际上应该如何构造这样的宏,以便能够自动插入虚拟/真实图形? 或者
- 是否有一个包已经可以很好地处理我忽略的此类事情?
我觉得我在这里错过了一些非常基本的东西......
I'm writing my thesis/dissertation and since its an on-going work I don't always have the actual images ready for the figures I put into my document, but for various reasons want to automatically have it substitute a dummy figure in place when the included graphics file doesn't exist. E.g. I can do something like \includegraphics[width=8cm]{\chapdir/figures/fluxcapacitor}
(where \chapdir
is a macro for my 'current' chapter directory, e.g. \def\chapdir{./ch_timetravel}
and if there's no ./ch_timetravel/figures/fluxcapacitor.jpg
it'll insert ./commands/dummy.jpg
instead.
I've structured my macros (perhaps naïvely?) so that I have a macro (\figFileOrDummy
) that determines the appropriate file to include by checking if the argument provided to it exists, so that I can call \includegraphics[properties]{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}
. Except I'm getting various errors depending on how I try to call this, which seem to suggest that I'm approaching the problem in a fundamentally flawed way as far as 'good LaTeX programming' goes.
Here's the macro to check if the file exists (and 'return' either filename or the dummy filename):
\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%
}%
Alternatively, here's a much simpler version which seems to have similar problems:
\newcommand{\figFileOrDummy}[1]{%
\def\dummyfig{commands/dummy}%
\dummyfig%
}
The \def
commands seems to be processed after the expansion of the macro they're trying to define, so it ends up being \def {commands/dummy}...
(note the space after \def
) and obviously complains.
Also it seems to treat the literal contents of the macro as the filename for \includegraphics
, rather than resolving/expanding it first, so complains that the file '\def {commands/dummy}... .png'
doesn't exist..
I've tried also doing something like\edef\figfilename{\figFileOrDummy{\chapdir/figures/fluxcapacitor}}
to try to force it to make \figfilename
hold just the value rather than the full macro, but I get an Undefined control sequence
error complaining the variables I'm trying to \def
in the \figFileOrDummy
macro are undefined.
So my question is either
- How do I make this macro expand properly?; or
- If this is the wrong way of structuring my macros, how should I actually structure such a macro, in order to be able to insert dummy/real figures automatically?; or
- Is there a package that already handles this type of thing nicely that I've overlooked?
I feel like I'm missing something pretty fundamental here...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为重点是 \expandafter 只对其参数作为表示文件名的字符串感兴趣,因此不会评估它 - 宏语言是懒惰的!尝试
\expandafter {\includegraphics[width=8cm]}{\chapdir/figures/fluxcapacitor}
。两点风格:
\def\newcs{abc}
和\def \newcs {abc}
是相同的:它们是完全相同的序列的代币。清理代码
我首先认为问题出在其他地方,所以写了一些更漂亮的东西:
I think the point is that \expandafter is only interested in its arguments as a string representing a filename, so doesn't evaluate it — macro languages are lazy! Try
\expandafter {\includegraphics[width=8cm]}{\chapdir/figures/fluxcapacitor}
.Two points of style:
\def\newcs{abc}
and\def \newcs {abc}
are identical: they are exactly the same sequence of tokens.Cleaned-up code
I first thought the problem lay elsewhere, so wrote something prettier:
对 #3 的回答:为此目的,我发现
todonotes
包非常有用。它没有提供您的代码旨在提供的自动化级别,但它有一个非常好的\missingfigure
命令,可以让您为(您猜对了)缺失的图形放置一个虚拟框。Answer to #3: For this purpose, I find very useful the
todonotes
package. It does not provide the level of automation that your code is aiming to offer, but it has a very nice\missingfigure
command that lets you put a dummy box for, you guess it, a missing figure.好吧,所以我已经找到了问题 2 的可能答案,通过重组宏的工作方式(并使用了 Charles Stewart 答案中的一些建议 - 我承认我不喜欢看起来的“外观”)虽然我被广泛认为是优秀的 LaTeX 代码,但我的 C/C++ 方式可能太根深蒂固,无法成为一名真正的 LaTeX 程序员)。
无论如何,我的答案...
不要尝试在宏中生成文件名以将传递给
\includegraphics
宏,而是创建一个包装\includegraphics 的宏
并向其传递真实或虚拟文件名。这似乎避免了传递(作为参数)长脚本/宏,尽管我没有看到任何好的理由为什么必须这样编写。但它确实有效...这允许人们按预期使用它:
同样,我想认为有一种方法可以使最初的想法发挥作用,而不必为现有函数制作包装器,但现在就这样了......
Alright, so I've found a possible answer to #2, by restructuring the way the macros work (and sort of using some suggestions from Charles Stewart's answer — I'll admit I don't like the 'look' of what seems to be widely considered good LaTeX code, I'm perhaps too ingrained in my C/C++ ways to be a real LaTeX programmer).
Anyway, my answer...
Instead of trying to produce the file name in a macro to pass to the
\includegraphics
macro, make a macro that wraps\includegraphics
and passes it the real or dummy file name. This seems to avoid passing (as an argument) a long script/macro, though I don't see any good reason why it should have to be written this way. But it does work...This allows one to use it as intended:
Again, I'd like to think there's a way to make the original idea work rather than having to make a wrapper for existing functions, but this will do for now...