How do I \write18 a koma var?
As Ulrike said, \usekomavar
is not expandable, but a functionally-equivalent expandable version can be easily created. Being non-expandable means that the command does assignments as part of its processing, so it fails when used inside an \edef
or a \write
. The command below uses only expandable commands, so that inside the \write
it expands to the value of the variable.
\documentclass{scrlttr2}
\newcommand\x[1]{hello #1}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand\xusekomavar{sO{\use:n}m}
{
\IfBooleanTF{#1}%
{ \__bitmask_usekomathing:nnn {name} }
{ \__bitmask_usekomathing:nnn {var} }
{#2} {#3}
}
\cs_new:Npn \__bitmask_usekomathing:nnn #1 #2 #3
{
\cs_if_exist:cTF { scr@#3@var }
{ \exp_args:Nnc \use:n {#2} { scr@#3@#1 } }
{ \msg_expandable_error:nnn { bitmask } { undefined-komavar } {#3} }
}
\msg_new:nnn { bitmask } { undefined-komavar }
{ KOMA-Script~variable~`#1'~not~defined. }
\ExplSyntaxOff
\begin{document}
\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}
\immediate\write18{echo 'none' > \jobname-none.txt} % fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt} % fine
\immediate\write18{echo '\xusekomavar{toname}' > \jobname-toname.txt} % error
\closing{Closing}
\end{letter}
\end{document}
It is also possible to use the optional argument of \usekomavar
. Therefore I have to define a new macro which will take the content for the file as its last argument.
\newcommand\writetofile[2]{% \writetofile{<file>}{<content>}
\immediate\write18{echo '#2' > #1}%
}
Then it is possible to use
\usekomavar[\writetofile{\jobname-toname.txt}]{toname}
to get the desired result.
Example:
\documentclass{scrlttr2}
\newcommand\x[1]{hello #1}
\newcommand\writetofile[2]{% \writetofile{<file>}{<content>}
\immediate\write18{echo '#2' > #1}%
}
\begin{document}
\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}
\immediate\write18{echo 'none' > \jobname-none.txt}% fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt}% fine
\usekomavar[\writetofile{\jobname-toname.txt}]{toname}%
\closing{Closing}
\end{letter}
\end{document}
or
\documentclass{scrlttr2}
\newcommand\x[1]{hello #1}
\newcommand\writetofile[2]{% writetofile{<file>}{<content>}
\immediate\write18{echo '#2' > #1}%
}
\newcommand\writekomavar[2]{% \writekomavar{<file>}{<variable>}
\usekomavar[\writetofile{#1}]{#2}%
}
\begin{document}
\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}
\immediate\write18{echo 'none' > \jobname-none.txt}% fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt}% fine
\writekomavar{\jobname-toname.txt}{toname}%
\closing{Closing}
\end{letter}
\end{document}
KoMa variables are basically macros saved under the name \scr@VARNAME@var
. \usekomavar
is a robust macro that checks whether the variable is defined and whether a star follows, in which case it does something else. If you are ready to give up these checks you can just use \csname scr@VARNAME@var\endcsname
. Worst case: the KoMa var is undefined and nothing happens.
\immediate\write18{echo '\csname scr@toname@var\endcsname' > \jobname-toname.txt}