根据是否设置环境变量进行切换

根据是否设置环境变量进行切换

结论:问题:未设置的环境变量的kpsewhich输出\par,我不知道如何剥离它。

我受到了这个问题的启发我可以从 LaTeX 访问系统/环境变量吗?例如 $HOME在发现kpsewhich没有环境变量的情况下也可以工作后--shell-escape,我尝试创建一个基于是否设置了给定环境变量的开关。然后我可以检查 eg 是否DARK已设置并交换文本和背景颜色。

然而,问题出现了,即使未设置环境变量,也kpsewhich似乎会输出换行符,这导致捕获的输出不为空。我已经尝试使用\tl_trim_spaces:N(链接的答案中已经是这种情况)来剥离它,但无济于事。

是否有可能(a)指示kpsewhich不要为未设置的环境变量打印换行符,(b)如果未设置变量,则读取失败的返回代码sys_get_shell:nnNkpsewhich非零退出代码,或(c)剥离\par变量的结果?

感谢@Phelype Oleinik,查看他的回答以获得解释,并查看@egreg 的回答以获得无需更改的解决方案\endlinechar
我现在可以使用以下代码实现我想要的功能:

\documentclass{article}
\usepackage{fontspec}
\usepackage{xparse}
\usepackage{xcolor}

\ExplSyntaxOn
\NewDocumentCommand{\ifenvset}{m m}
{
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #1 }
    { \int_set:Nn \tex_endlinechar:D { -1 } }
    \l_tmpa_tl
  \tl_if_empty:NTF { \l_tmpa_tl } {} { #2 }
}
\ExplSyntaxOff

\ifenvset{DARK}{
  \pagecolor{black!90}
  \color{white!90}
}

\begin{document}
\noindent
\verb|lualatex darkmode.tex|\\
\verb|env DARK=1 lualatex darkmode.tex|\\
\end{document}

答案1

当你执行 shell 命令时,TeX 会认为你已将命令的输出写入临时(伪)文件,然后读取该文件。读取该文件时,通常的规则适用:行尾转换为空格,空行转换为标记\par。当命令的输出为空时,就好像文件有一个空行,然后将其转换为\par。通常的技巧是将参数设置\endlinechar-1,这样 TeX 就不会在行尾插入任何内容,也不会插入标记\par

中的第二个参数\sys_get_shell:nnN<setup>,您可以在执行命令和读入伪文件之前更改这些类型的参数,因此您可以执行以下操作:

\sys_get_shell:nnN { kpsewhich ~ --var-value ~ #2 }
  { \int_set:Nn \tex_endlinechar:D { -1 } }
  \l_septatrix_env_tl

将其放入 egreg 的\getenv代码中:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_septatrix_env_tl
\NewDocumentCommand \getenv { o m }
  {
    \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #2 }
      { \int_set:Nn \tex_endlinechar:D { -1 } }
      \l_septatrix_env_tl
    \IfNoValueTF {#1}
      { \tl_use:N \l_septatrix_env_tl }
      { \tl_set_eq:NN #1 \l_septatrix_env_tl }
  }
\ExplSyntaxOff

\begin{document}

\getenv[\HOME]{HOME}\show\HOME

\getenv[\HOMER]{HOMER}\show\HOMER

\end{document}

答案2

您可以定义\ifenvsetTF(我认为这是一个更好的名称}

\tl_const:Nn \c_getenv_par_tl { \par }

\NewDocumentCommand{\ifenvsetTF}{mmm}
 {
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #1 } { } \l_tmpa_tl
  \tl_if_eq:NNTF \l_tmpa_tl \c_getenv_par_tl { #3 } { #2 }
 }

完整示例:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\getenv}{om}
 {
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #2 } { } \l_tmpa_tl
  \tl_trim_spaces:N \l_tmpa_tl
  \IfNoValueTF { #1 }
   {
    \tl_use:N \l_tmpa_tl
   }
   {
    \tl_set_eq:NN #1 \l_tmpa_tl
   }
 }

\tl_const:Nn \c_getenv_par_tl { \par }

\NewDocumentCommand{\ifenvsetTF}{mmm}
 {
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #1 } { } \l_tmpa_tl
  \tl_if_eq:NNTF \l_tmpa_tl \c_getenv_par_tl { #3 } { #2 }
 }

\ExplSyntaxOff

\begin{document}

\getenv{LC_CTYPE}

\ifenvsetTF{LC_CTYPE}{SET}{UNSET}

\ifenvsetTF{BOZO}{SET}{UNSET}

\end{document}

在此处输入图片描述

但是,请注意,设置为空值的变量无论如何都会触发“取消设置”(使用此方法以及该\endlinechar方法)。

如何定义expl3条件?

\prg_new_protected_conditional:Nnn \septatrix_if_setenv:n {T,F,TF}
 {
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #1 } { } \l_tmpa_tl
  \tl_if_eq:NNTF \l_tmpa_tl \c_getenv_par_tl
   { \prg_return_false: }
   { \prg_return_true: }
 }

完整代码

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\getenv}{om}
 {
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #2 } { } \l_tmpa_tl
  \tl_trim_spaces:N \l_tmpa_tl
  \IfNoValueTF { #1 }
   {
    \tl_use:N \l_tmpa_tl
   }
   {
    \tl_set_eq:NN #1 \l_tmpa_tl
   }
 }

\tl_const:Nn \c_getenv_par_tl { \par }
\prg_new_protected_conditional:Nnn \septatrix_if_setenv:n {T,F,TF}
 {
  \sys_get_shell:nnN { kpsewhich ~ --var-value ~ #1 } { } \l_tmpa_tl
  \tl_if_eq:NNTF \l_tmpa_tl \c_getenv_par_tl
   { \prg_return_false: }
   { \prg_return_true: }
 }

\NewDocumentCommand{\ifenvsetTF}{mmm}
 {
  \septatrix_if_setenv:nTF { #1 } { #2 } { #3 }
 }

\ExplSyntaxOff

\begin{document}

\getenv{LC_CTYPE}

\ifenvsetTF{LC_CTYPE}{SET}{UNSET}

\ifenvsetTF{BOZO}{SET}{UNSET}

\end{document}

相关内容