Switch based on whether or not an environment variable is set
When you execute a shell command, TeX sees it as if you had written the output of the command to a temporary (pseudo) file, and then read that file in. While reading that file, the usual rules apply: a line end is turned into a space, and an empty line is turned into a \par
token. When the output of the command is empty, it is as if the file had an empty line, and that is turned into a \par
. The usual trick is to set the \endlinechar
parameter to -1
, so that TeX doesn't insert anything at the end of a line, neither a \par
token.
The second argument in \sys_get_shell:nnN
is the <setup>
, in which you can change these types of parameters before the command is executed and the pseudo file is read in, so you can do:
\sys_get_shell:nnN { kpsewhich ~ --var-value ~ #2 }
{ \int_set:Nn \tex_endlinechar:D { -1 } }
\l_septatrix_env_tl
Putting that in egreg's \getenv
code:
\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}
You can define \ifenvsetTF
(this is a better name, in my opinion} by
\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 }
}
Full example:
\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}
However, note that variables set to empty value will trigger “unset” anyway (with this method and also with the \endlinechar
method).
How to define an expl3
conditional?
\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: }
}
Full code
\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}