write18测试成功

write18测试成功

对于我的包和类的新版本,standalone我喜欢调用外部程序:进一步(pdf)latex运行以选择性地编译包含的standalone文件,并将生成的 PDF 转换为 PNG(取决于上次运行创建的 PDF 至少在\begin{document}第一页被刷新之前不会被覆盖)。

我当然知道这可以通过使用来完成\immediate\write18{<command> <arguments>},这需要将命令添加到shell_escape_commands变量中texmf.cnfshell_escape设置为p,或者用户使用该-shell-escape参数。

现在我喜欢在代码中测试调用是否write18成功,即是否允许执行。我知道这\ifeof18将返回错误的如果write18特征是完全地已禁用(shell_escape = 0texmf.cnf或当-no-shell-escape使用参数时),但它返回真的如果受限制的 write18模式已激活,这是默认模式。

有没有办法测试最后的 write18 调用是否被阻止?(我知道我可以手动测试该调用应生成的文件是否write18已创建或更新。)


更新

文件中.log为每个 write18 调用显示以下行之一,具体取决于此功能是否被禁用、启用或在限制模式下运行并且是否允许执行命令:

runsystem(<command>)...disabled.
runsystem(<command>)...executed.
runsystem(<command>)...executed safely (allowed).
runsystem(<command>)...disabled (restricted).

那么,如何才能在 LaTeX 文件中获取这些信息(无需实际读取文件.log)?

答案1

似乎除了和之外,pdflatex没有提供任何其他状态变量。这在\ifeof18\pgfshellescape中远海运Heiko Oberdiek 撰写。他还建议为 pdfTeX(和/或其他 TeX 引擎)打开功能请求,我就是这么做的

以下是我想到的解决方案:

正如两个答案中提到的,检查的一个好方法write18\pdfshellescape宏,自 pdftex 1.30.0 起可用。如果\write18启用,则为 1,如果受限,则为 2,否则为 0。它在 XeTeX 或 LuaTeX 中不可用。但是,Heiko Oberdiek 的软件包pdftexcmds将其添加到 LuaTeX 中,还会为您检查 pdfTeX >=1.30.0。然后以 的形式提供宏\pdf@shellescape

在我的例子中,我想检查转换命令是否成功。我想使用\pdffilemoddate\pdf@filemoddatepdftexcmds)来检查要生成的文件是否更新。结合\IfFileExists这一点可以进行非常合理的测试,该测试适用于 pdfLaTeX 和 LuaLaTeX。对于 XeLaTeX,只能实施非常有限的测试。

以下宏等待输出文件的名称和命令:

 \writesuccess{<output file>}{<command line>}{<success>}{<failure>}

但是,如果调用的命令执行失败,并在过程中更新文件修改日期,则宏会将其报告为成功。目前没有办法检查这一点。

完整代码及示例:将生成的 PDF 转换为 PNG,需要运行两次,其中至少第二次需要-shell-escape

\documentclass{standalone}

% Use `pdftexcmds` to support LuaTeX and take advantage of
% the included checks like version of pdflatex, existence of \ifeof18, etc.:
\usepackage{pdftexcmds}
\makeatletter
\ifx\pdf@filemoddate\@undefined

% Without filemoddate (e.g. XeLaTeX) only the existence of the file can be tested:
\newcommand{\writesuccess}[2]{%
    \immediate\write18{#2}%
    \IfFileExists{#1}%
}

\else

% Real version:
% Check if to-be-generated file exists afterwards and is newer:
\newcommand{\writesuccess}[2]{%
    \begingroup
    \edef\filemodbefore{\pdf@filemoddate{#1}}%
    \immediate\write18{#2}%
    \IfFileExists{#1}{%
        \edef\filemodafter{\pdf@filemoddate{#1}}%
        \ifx\filemodbefore\filemodafter
            \let\next\@secondoftwo
        \else
            \let\next\@firstoftwo
        \fi
    }{%
        \let\next\@secondoftwo
    }%
    \expandafter
    \endgroup
    \next
}

\fi
\makeatother


\writesuccess{\jobname.png}{convert -density 600 \jobname.pdf \jobname.png}{%
    \message{^^JYes^^J}%
}{%
    \message{^^JNo^^J}%
}

\begin{document}
Test
\end{document}

答案2

为了解决同样的任务,我使用了

\ifnum\pdfshellescape=1
% Yes, enabled
\else
% No, disabled
\fi

控制序列\pdfshellescape(仅?)在 中可用pdftex,即您还需要检查它是否存在。

答案3

bashful包可能对您的目的有用。它确实管理\write18错误,尽管我不确定它是否完全按照您要求的方式。这是一个小演示:

\documentclass[a6paper]{article}
\usepackage[verbose]{bashful}
\usepackage{graphicx}

\begin{document}
Here I create a small \LaTeX{} file:
\bash[script]
cat > delme.tex << EOF
\documentclass{standalone}
\begin{document}
Lorem ipsum dolor sit amet!
\end{document}
EOF
\END
Now I shall run the file I just created through \LaTeX{},
\bash[script]
pdflatex -shell-escape delme.tex
\END
obtaining the following output

\begin{center}
  \fbox{\includegraphics{delme.pdf}}
\end{center}

\end{document}

生成以下输出:使用 LaTeX 中的 <code>standalone</code> 包

答案4

您可以实现\ifwritexviii条件。这直接取自泽佩斯安(这也是从 Heiko 的一个包裹中截取的):

\def\xepersian@cmds@temp#1{%
  \begingroup\expandafter\expandafter\expandafter\endgroup
  \expandafter\ifx\csname xepersian@#1\endcsname\relax
    \begingroup
      \escapechar=-1 %
      \edef\x{\expandafter\meaning\csname#1\endcsname}%
      \def\y{#1}%
      \def\z##1->{}%
      \edef\y{\expandafter\z\meaning\y}%
    \expandafter\endgroup
    \ifx\x\y
      \expandafter\def\csname xepersian@#1\expandafter\endcsname
      \expandafter{%
        \csname#1\endcsname
      }%
    \fi
  \fi
}%
\xepersian@cmds@temp{shellescape}
\newif\ifwritexviii
\ifnum\xepersian@shellescape=1\relax
  \writexviiitrue
\else
\writexviiifalse
\fi

你可以使用它作为:

\ifwritexviii
   % material if shell scape is enabled
\else
   % material if shell escape is disabled
\fi

相关内容