使用 \tl_show、\str_show、\int_show 等时未生成输出 PDF 文件

使用 \tl_show、\str_show、\int_show 等时未生成输出 PDF 文件

编译 Latex 源文件时

\documentclass{article}

\ExplSyntaxOn
\tl_new:N \l_test_value_tl
\tl_set:Nn \l_test_value_tl {It's~a~test~value}
\tl_show:N \l_test_value_tl
\ExplSyntaxOff

\begin{document}
    It's an example.
\end{document}

我收到一个没有任何详细信息的错误

pdflatex -interaction=nonstopmode -halt-on-error temp.tex
This is pdfTeX, Version 3.141592653-2.6-1.40.25 (MiKTeX 23.12) (preloaded format=pdflatex.fmt)
 restricted \write18 enabled.
entering extended mode
(temp.tex
LaTeX2e <2023-11-01> patch level 1
L3 programming layer <2024-01-04>
(C:\Users\User\AppData\Local\Programs\MiKTeX\tex/latex/base\article.cls
Document Class: article 2023/05/17 v1.4n Standard LaTeX document class
(C:\Users\User\AppData\Local\Programs\MiKTeX\tex/latex/base\size10.clo))
> \l_test_value_tl=It's a test value.
<recently read> }

l.6 \tl_show:N \l_test_value_tl

!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on temp.log.```

但如果注释掉 \tl_show 宏

\documentclass{article}

\ExplSyntaxOn
\tl_new:N \l_test_value_tl
\tl_set:Nn \l_test_value_tl {It's~a~test~value}
%\tl_show:N \l_test_value_tl
\ExplSyntaxOff

\begin{document}
    It's an example.
\end{document}

文件编译无误,并生成 pdf

pdflatex -interaction=nonstopmode -halt-on-error temp.tex
This is pdfTeX, Version 3.141592653-2.6-1.40.25 (MiKTeX 23.12) (preloaded format=pdflatex.fmt)
 restricted \write18 enabled.
entering extended mode
(temp.tex
LaTeX2e <2023-11-01> patch level 1
L3 programming layer <2024-01-04>
(C:\Users\User\AppData\Local\Programs\MiKTeX\tex/latex/base\article.cls
Document Class: article 2023/05/17 v1.4n Standard LaTeX document class
(C:\Users\User\AppData\Local\Programs\MiKTeX\tex/latex/base\size10.clo))
(C:\Users\User\AppData\Local\Programs\MiKTeX\tex/latex/l3backend\l3backend-pd
ftex.def)
No file temp.aux.
[1{C:/Users/User/AppData/Local/MiKTeX/fonts/map/pdftex/pdftex.map}] (temp.aux
) )<C:/Users/User/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/c
m/cmr10.pfb>
Output written on temp.pdf (1 page, 14234 bytes).
Transcript written on temp.log.

其他类似的宏 \str_show、\int_show 等也存在同样的问题。

这是预期的行为还是我做错了什么?有人知道这个错误的原因是什么吗?

答案1

经过一番调查,我发现了上述问题的原因,并且可以自己回答我的问题:-)。

结果是将变量值输出到终端和日志文件的宏(\tl_显示\str_显示\int_显示等)是使用 TeX 错误消息机制实现的。这意味着 pdflatex(即使没有-halt-on-error选项)仍会返回非零退出代码,并且任何调用 pdflatex 的构建实用程序(latexmk)或 IDE 都会通知构建错误。例如,在 VSCode + LaTeX-Workshop 的情况下,它如下所示

在此处输入图片描述

关于它的更多详细信息可以阅读这里在非停止模式下使用 \show 会导致 TeXmaker 发出错误警报。有什么解决办法吗?。 这里我怎样才能让 TeX 在第一次错误时停止,但不在 \show (或 \tl_show:n)上停止?建议如何避免此类行为。

对我来说最合适的方法是重新实现将变量值输出到终端的宏。经过一番努力,我得到了以下包

\RequirePackage{expl3}
\ProvidesExplPackage{DebugTools}{}{}{}

\cs_new:Npn \__start_label: {
    [DEBUG~INFO]:[line= \int_use:N \inputlineno]:~
}

%--------------------------------------------------------------------------------------------------
% Functions for output debug info in terminal and log
%--------------------------------------------------------------------------------------------------

\cs_new_protected:Npn \show:n #1 {
    \iow_term:e {#1}
}

\cs_new_protected:Npn \show_sep: {
    \iow_term:n {----------------------------------------------------------------------------------------------------}
}

\cs_new_protected:Npn \show_head:n #1 {
    \show_sep:
    \show:n {#1}
    \show_sep:
}

\cs_new_protected:Npn \show_val:n #1 {
    \iow_term:e {\__start_label: #1}
}

\cs_new_protected:Npn \show_tl:N #1 {
    \iow_term:e {\__start_label: \exp_not:N #1 =~ \tl_use:N #1}
}

\cs_new_protected:Npn \show_str:N #1 {
    \iow_term:e {\__start_label: \exp_not:N #1 =~ \str_use:N #1}
}

\cs_new_protected:Npn \show_bool:N #1 {
    \iow_term:e {\__start_label: \exp_not:N #1 =~ \bool_to_str:N #1}
}

\cs_new_protected:Npn \show_int:N #1 {
    \iow_term:e {\__start_label: \exp_not:N #1 =~ \int_use:N #1}
}

\cs_new_protected:Npn \show_dim:N #1 {
    \iow_term:e {\__start_label: \exp_not:N #1 =~ \dim_use:N #1}
}

\cs_new_protected:Npn \show_clist:N #1 {
    \iow_term:e {\__start_label: \exp_not:N #1 =~ {\clist_use:Nn #1 {,}}}
}

%--------------------------------------------------------------------------------------------------
% Functions for output debug info in log
%--------------------------------------------------------------------------------------------------

\cs_new_protected:Npn \log:n #1 {
    \iow_log:e {#1}
}

\cs_new_protected:Npn \log_sep: {
    \iow_log:n {----------------------------------------------------------------------------------------------------}
}

\cs_new_protected:Npn \log_head:n #1 {
    \log_sep:
    \log:n {#1}
    \log_sep:
}

\cs_new_protected:Npn \log_val:n #1 {
    \iow_log:e {\__start_label: #1}
}

\cs_new_protected:Npn \log_tl:N #1 {
    \iow_log:e {\__start_label: \exp_not:N #1 =~ \tl_use:N #1}
}

\cs_new_protected:Npn \log_str:N #1 {
    \iow_log:e {\__start_label: \exp_not:N #1 =~ \str_use:N #1}
}

\cs_new_protected:Npn \log_bool:N #1 {
    \iow_log:e {\__start_label: \exp_not:N #1 =~ \bool_to_str:N #1}
}

\cs_new_protected:Npn \log_int:N #1 {
    \iow_log:e {\__start_label: \exp_not:N #1 =~ \int_use:N #1}
}

\cs_new_protected:Npn \log_dim:N #1 {
    \iow_log:e {\__start_label: \exp_not:N #1 =~ \dim_use:N #1}
}

\cs_new_protected:Npn \log_clist:N #1 {
    \iow_log:e {\__start_label: \exp_not:N #1 =~ {\clist_use:Nn #1 {,}}}
}

\endinput

带有演示 LaTeX 源文件

\documentclass{article}
\usepackage{DebugTools}

\ExplSyntaxOn
\tl_new:N    \l_test_value_tl    \tl_set:Nn       \l_test_value_tl    {It's~a~test~value}
\str_new:N   \l_test_value_str   \str_set:Nn      \l_test_value_str   {It's~a~test~value}
\bool_new:N  \l_test_value_bool  \bool_set_true:N \l_test_value_bool
\int_new:N   \l_test_value_int   \int_set:Nn      \l_test_value_int   {101}
\dim_new:N   \l_test_value_dim   \dim_set:Nn      \l_test_value_dim   {-2.5pt}
\clist_new:N \l_test_value_clist \clist_set:Nn    \l_test_value_clist {a,b,3,c,5}

\show_head:n  {DEBUG~INFO~FOR~TERMINAL~AND~LOG}
\show_val:n   {It's~a~test~value}
\show_tl:N    \l_test_value_tl
\show_str:N   \l_test_value_str
\show_bool:N  \l_test_value_bool
\show_int:N   \l_test_value_int
\show_dim:N   \l_test_value_dim
\show_clist:N \l_test_value_clist
\show_sep:

\log_head:n  {DEBUG~INFO~FOR~LOG}
\log_val:n   {It's~a~test~value}
\log_tl:N    \l_test_value_tl
\log_str:N   \l_test_value_str
\log_bool:N  \l_test_value_bool
\log_int:N   \l_test_value_int
\log_dim:N   \l_test_value_dim
\log_clist:N \l_test_value_clist
\log_sep:
\ExplSyntaxOff

\begin{document}
    It's an example.
\end{document}

现在它编译时没有任何错误通知,并且看起来符合我的目标

在此处输入图片描述

更新

在回答评论中的问题时,我想更详细地解释为什么标准对我来说\..._show:N并不\...log:N好。

\..._show:N在终端和日志文件中产生以下输出

> \l_test_value_tl=It's a test value.
<recently read> }
                 
l.6 \tl_show:N \l_test_value_tl

并具有以下优点和缺点:

优点

  • 输出足够详细,并包含行号,以便轻松搜索源文件中产生此输出的位置。

缺点

  • 该宏强制 pdflatex 返回非零退出代码,从而导致 IDE 中出现构建错误通知。

\..._log:N仅在日志文件中产生以下输出

> \l_test_value_tl=It's a test value.

并具有以下优点和缺点:

优点

  • 该宏不会导致 IDE 中出现构建错误通知

缺点

  • 输出不包含任何行号。

除此之外,我更喜欢\..._show:N立即在终端输出中查看调试信息,而不是每次构建后打开日志文件(这有点烦人)。

因此,我重新实现了宏以实现以下目标:

  • 避免 IDE 中的任何构建错误通知\..._show:N
  • 使输出格式\..._show:N相同\..._log:N,除了变量及其值之外,还包含一些标签(以便在构建输出中轻松搜索调试信息)和行号(以便在源文件中轻松搜索生成此调试信息的位置)。

相关内容