What is the LaTeX 3 equivalent to \write18
if there is one? I want to call lilypond
from within my TeX document.
2 Answers
UPDATE
Things have changed since 2013 and shell escape is now fully supported by expl3
. The relevant section in the manual (as of 2021) is currently 10.7.
Getting the output from a command
\sys_get_shell:nnN
\sys_get_shell:nnNTF
For both functions the first n
argument is an unquoted shell command ("
quotes around it will be automatically supplied; the standard restrictions apply, namely that "
cannot appear in this argument). The second argument is for “setup” (category code changes, for instance) that is applied to the tokens in the shell command. The third argument should be a token list variable. In the second function the T
argument is returned if the command is well-formed and shell escape is enabled; otherwise the F
argument is returned. The usual conventions for TF
apply. The token list variable will contain the output of the shell command. If shell escape is disabled, the variable will contain \q_no_value
.
This is the interface to `\input{|"..."}
Checking the shell escape status
\c_sys_shell_escape_int
is set to 0
, 1
or 2
at the beginning of the job, with the usual meaning: 0
means shell escape is disabled; 1
that it is unrestricted;
2` means it is restricted.
\sys_if_shell_p:
\sys_if_shell:TF
\sys_if_shell_unrestricted_p:
\sys_if_shell_unrestricted:TF
\sys_if_shell_restricted_p:
\sys_if_shell_restricted:TF
are the predicates and the conditionals for testing the shell escape status.
Executing shell commands
\sys_shell_now:n
\sys_shell_now:x
will execute the command passed as argument, the x
version will do full expansion of the argument. The execution is immediate.
This is the interface to \immediate\write18{...}
\sys_shell_shipout:n
\sys_shell_shipout:x
will execute the shell command at the next shipout (useful if the command to be executed needs as input the page number, for example).
This is the interface to \write18
.
ORIGINAL ANSWER
There is no function in LaTeX3, at the moment, dealing with \write18
; it can be obtained by
\RequirePackage{expl3,pdftexcmds}
\ExplSyntaxOn
\int_const:Nn \c_tobi_eighteen_int { 18 }
\int_const:Nn \c_tobi_shell_escape_int { \int_eval:n { \use:c { pdf@shellescape } } }
\cs_new_protected:Npn \tobi_system_exec_now:n #1
{
\int_compare:nT { \c_tobi_shell_escape_int > 0 }
{ \iow_now:Nn \c_tobi_eighteen_int { #1 } }
}
\cs_new_protected:Npn \tobi_system_exec_shipout:n #1
{
\int_compare:nT { \c_tobi_shell_escape_int > 0 }
{ \iow_shipout:Nn \c_tobi_eighteen_int { #1 } }
}
\cs_generate_variant:Nn \tobi_system_exec_now:n { x }
\cs_generate_variant:Nn \tobi_system_exec_shipout:n { x }
%% Examples
\tobi_system_exec_now:n { ls }
\tl_set:Nn \l_tmpa_tl { ls }
\tobi_system_exec_now:x { \l_tmpa_tl }
You probably would want to add messages telling that things went wrong when shell escape is disabled; or just remove the \int_compare:nT
thing.
I used the tobi
prefix because using \system
is probably a bad idea (I don't want to get slapped by Joseph on chat, you know).
-
Indeed, a good question here is what does and doesn't make sense interface-wise for this. As the team have not needed
\write18
we've not worried out it. Notable of course is that catcodes might be an issue.– Joseph Wright ♦Commented Sep 14, 2013 at 19:55 -
@JosephWright Catcodes can surely be an issue; but I guess the function will be called with its argument coming from "user space". Otherwise, spaces must be
~
, as usual. Setting up a good diagnostic system might be tricky, because of restricted shell.– egregCommented Sep 14, 2013 at 20:01 -
1@JosephWright: don't you guys dare including a
\write18
equivalent function in LaTeX3, I already printedinterface3.pdf
today!:)
Commented Sep 14, 2013 at 20:05
Since this question was answered, LaTeX3 has evolved.
See section 10.7 Access to the shell, on interface3.pdf
.
In particular,
\immediate\write18
is replaced by
\sys_shell_now:n
and its :x
variant.
\tex_write:D
? But:D
means "Do not use it".\int_const:Nn \c_eighteen
and then\iow_now:Nn \c_eighteen{...}
is equivalent to\immediate\write18{\unexpanded{...}}
; but probably one should define some new function based on this.