2 %% Source File: shellesc.dtx
3 %% Copyright 2015-2016 LaTeX3 project
5 %% This file may be distributed under the terms of the LPPL.
6 %% See README for details.
9 \ProvidesFile{shellesc.dtx}
11 %<package>\ifx\ProvidesPackage\undefined
12 %<package>\def\next#1#2[#3]{\wlog{#2 #3}}
13 %<package>\ifx\PackageInfo\undefined\def\PackageInfo#1#2{\wlog{#1: #2}}\fi
14 %<package>\ifx\PackageWarning\undefined\def\PackageWarning#1#2{\wlog{#1: #2}}\fi
15 %<package>\expandafter\next\fi
16 %<package>\ProvidesPackage{shellesc}
17 %<driver> \ProvidesFile{shellesc.drv}
19 % \ProvidesFile{shellesc.dtx}
20 [2016/06/07 v0.02a unified shell escape interface for LaTeX]
24 \documentclass{ltxdoc}
26 \DocInput{shellesc.dtx}
31 % \GetFileInfo{shellesc.dtx}
33 % \title{The \textsf{shellesc} Package\thanks{This file
34 % has version number \fileversion, last
35 % revised \filedate.}}
36 % \author{LaTeX3 project}
40 % \changes{v0.1b}{2016/02/02}{Doc typo fixes (JB)}
41 % \changes{v0.2a}{2016/06/07}{Improve use with plain TeX}
42 % \section{Introduction}
45 % For many years web2c based \TeX\ implementations have used the syntax
46 % of the \verb|\write| command to access system commands by using a
47 % special stream 18 (streams above 15 can not be allocated to files in
48 % classical \TeX\ so stream 18 would otherwise just print to the
51 % This is a useful extension that did not break the strict rules on
52 % extensions in classical \TeX. This package provides a simple
53 % macro level interface hiding the \verb|write18| implementation
54 % so a command to remove a file on a unix-like system could be
55 % specified using \verb|\ShellEscape{rm file.txt}| (or \verb|del| in
56 % windows). Note that by default system access is not allowed and
57 % latex will typically need to be called with the \verb|--shell-escape|
58 % command line option.
60 % The package may be used with standard \texttt{latex} or
61 % \texttt{pdflatex} or \texttt{xetex}, however it is mostly motivated by
62 % \texttt{lualatex} as from Lua\TeX~0.87 onwards Lua\TeX\ does \emph{not}
63 % support the \verb|\write18| syntax to access system commands: it has
64 % 256 write streams and stream 18 can be associated to a file and
65 % (without this package) has no special significance. This packge
66 % defines the same \verb|\ShellEscape| syntax in Lua\LaTeX, but the
67 % implementation is via Lua and the \verb|os.execute| function.
69 % \verb|\ShellEscape| in fact corresponds to \verb|\immediate\write18|
70 % (or \verb|\directlua|). Very rarely you may need to delay a system
71 % command until the current page is output (when page numbers are
72 % known) for this classically you could use \verb|\write18| (or
73 % (\verb|\latelua|). This package provides \verb|\DelayedShellEscape|
74 % as a common syntax for this use.
76 % To aid porting existing documents to Lua\TeX~0.87 this package does
77 % overload the \verb|\write| command so that
78 % \verb|\write18{rm file.txt}|
79 % will work with Lua\TeX. Note that the redefinition of \verb|\write|
80 % can not detect whether \verb|\immediate| has been used,
81 % \verb|\immediate| will work as normal when writing to file streams
82 % or the terminal but the special case of stream 18 which is defined to
83 % use \verb|os.execute| always uses \verb|\directlua| (so corresponds
84 % to \verb|\immediate\write18|. In the rare situations that you need
85 % non-immediate \verb|\write18| in a document being ported to current
86 % Lua\TeX, you will need to change to use the
87 % \verb|DelayedShellescape| command.
89 % \section{Implementation}
95 % \subsection{Status Check}
98 % \changes{v0.2a}{2016/06/07}{spelling in messages}
101 \ifx\pdfshellescape\@undefined
102 \ifx\shellescape\@undefined
103 \ifx\directlua\@undefined
107 tex.sprint((status.shell_escape or os.execute()) .. " ")}
115 \PackageWarning{shellesc}{Shell escape disabled}
117 \PackageInfo {shellesc}{Unrestricted shell escape enabled}
119 \PackageInfo {shellesc}{Restricted shell escape enabled}
123 % \subsection{The shellesc package interface}
125 % \begin{macro}{\ShellEscape}
126 % Execute the supplied tokens as a system dependent command, assuming
127 % such execution is allowed.
129 \ifx\lastsavedimageresourcepages\@undefined
130 \protected\def\ShellEscape{\immediate\write18 }
135 \protected\def\ShellEscape#1{%
136 \directlua{os.execute("\luaescapestring{#1}")}}
141 % \begin{macro}{\DelayedShellEscape}
142 % \changes{v0.1c}{2016/04/29}{Define \cs{DelayedShellEscape} not \cs{ShellEscape}(UF)}
143 % Execute the supplied tokens as a system dependent command, when this
144 % node is shipped out with the completed page, assuming
145 % such execution is allowed.
147 \ifx\lastsavedimageresourcepages\@undefined
148 \protected\def\DelayedShellEscape{\relax\write18 }
153 \protected\def\DelayedShellEscape#1{%
154 \latelua{os.execute("\luaescapestring{#1}")}}
161 % \subsection{The write18 package interface}
163 % In web2c based engines other than Lua\TeX, |\write18| may be used
164 % directly. The same was true in older LuaTeX, but from version 0.85
165 % onwards that is not available.
167 % The above |shellesc| package interface is recommended for new code,
168 % however for ease of porting existing documents and packages to newer
169 % Lua\TeX\ releases, a |\write18| interface is provided here via a
170 % call to Lua's |os.execute|.
172 % Note that as currently written this always does an \emph{immediate}
173 % call to the system.
175 % |\immediate| is supported but ignored, |\immediate\write18| and
176 % |\write18| both execute immediately. To use a delayed execution at
177 % the next shipout, use the |\DelayedShellEscape| command defined
180 % Note that it would be easy to make |\wriete18| defined here use
181 % delayed execution, just use |\DelayedShellEscape| instead of
182 % |ShellEscape| in the definition below. However detecting
183 % |\immediate| is tricky so the choice here is to always use the
184 % immediate form, which is overwhelmingly more commonly used with
187 % Stop at this point if not a recent Lua\TeX.
189 \ifx\lastsavedimageresourcepages\@undefined\expandafter\endinput\fi
197 shellesc = shellesc or {}
200 % Lua function to use the token scanner to grab the following \TeX\
201 % number, and then test if stream 18 is being used, and then insert an
202 % appropriate \TeX\ command to handle the following brace group in
205 local function write_or_execute()
206 local s = token.scan_int()
208 tex.sprint(\the\numexpr\catcodetable@atletter\relax,
209 "\string\\ShellEscape ")
211 tex.sprint(\the\numexpr\catcodetable@atletter\relax,
212 "\string\\shellesc@write " .. s)
218 shellesc.write_or_execute=write_or_execute
226 \let\shellesc@write\write
230 \protected\def\write{\directlua{shellesc.write_or_execute()}}