summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/tools/shellesc.dtx
blob: ebc436ad96e4f607cb96e78b8ebc903f8b30456c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
% \iffalse
%% Source File: shellesc.dtx
%% Copyright 2015-2016 LaTeX3 project
%%
%% This file may be distributed under the terms of the LPPL.
%% See README for details.
%
%<*dtx>
          \ProvidesFile{shellesc.dtx}
%</dtx>
%<package>\ifx\ProvidesPackage\undefined
%<package>\def\next#1#2[#3]{\wlog{#2 #3}}
%<package>\ifx\PackageInfo\undefined\def\PackageInfo#1#2{\wlog{#1: #2}}\fi
%<package>\ifx\PackageWarning\undefined\def\PackageWarning#1#2{\wlog{#1: #2}}\fi
%<package>\expandafter\next\fi
%<package>\ProvidesPackage{shellesc}
%<driver> \ProvidesFile{shellesc.drv}
% \fi
%         \ProvidesFile{shellesc.dtx}
       [2016/06/07 v0.02a unified shell escape interface for LaTeX]
%
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\begin{document}
\DocInput{shellesc.dtx}
\end{document}
%</driver>
% \fi
%
% \GetFileInfo{shellesc.dtx}
%
% \title{The \textsf{shellesc} Package\thanks{This file
%        has version number \fileversion, last
%        revised \filedate.}}
% \author{LaTeX3 project}
% \date{\filedate}
% \maketitle
%
% \changes{v0.1b}{2016/02/02}{Doc typo fixes (JB)}
% \changes{v0.2a}{2016/06/07}{Improve use with plain TeX}
% \section{Introduction}
%
% 
% For many years web2c based \TeX\ implementations have used the syntax
% of the \verb|\write| command to access  system commands by using a
% special stream 18 (streams above 15 can not be allocated to files in
% classical \TeX\ so stream 18 would otherwise just print to the
% terminal).
%
% This is a useful extension that did not break the strict rules on
% extensions in classical \TeX.  This package provides a simple
% macro level interface hiding the \verb|write18| implementation
% so a command to remove a file on a unix-like system could be
% specified  using \verb|\ShellEscape{rm file.txt}| (or \verb|del| in
% windows). Note that by default system access is not allowed and
% latex will typically need to be called with the \verb|--shell-escape|
% command line option.
%
% The package may be used with standard \texttt{latex} or
% \texttt{pdflatex} or \texttt{xetex}, however it is mostly motivated by
% \texttt{lualatex} as from Lua\TeX~0.87 onwards Lua\TeX\ does \emph{not}
% support the \verb|\write18| syntax to access system commands: it has
% 256 write streams and stream 18 can be associated to a file and
% (without this package) has no special significance. This packge
% defines the same \verb|\ShellEscape| syntax in Lua\LaTeX, but the
% implementation is via Lua and the \verb|os.execute| function.
%
% \verb|\ShellEscape| in fact corresponds to \verb|\immediate\write18|
% (or \verb|\directlua|). Very rarely you may need to delay a system
% command until the current page is output (when page numbers are
% known) for this classically you could use \verb|\write18| (or
% (\verb|\latelua|). This package provides \verb|\DelayedShellEscape|
% as a common syntax for this use.
%
% To aid porting existing documents to Lua\TeX~0.87 this package does
% overload the \verb|\write| command so that
% \verb|\write18{rm file.txt}|
% will work with Lua\TeX. Note that the redefinition of \verb|\write|
% can not detect whether \verb|\immediate| has been used,
% \verb|\immediate| will work as normal when writing to file streams
% or the terminal but the special case of stream 18 which is defined to
% use \verb|os.execute| always uses \verb|\directlua| (so corresponds
% to \verb|\immediate\write18|. In the rare situations that you need
% non-immediate \verb|\write18| in a document being ported to current
% Lua\TeX, you will need to change to use the
% \verb|DelayedShellescape| command.
% 
% \section{Implementation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% \subsection{Status Check}
%
%
% \changes{v0.2a}{2016/06/07}{spelling in messages}
%    \begin{macrocode}
\ifcase
  \ifx\pdfshellescape\@undefined
    \ifx\shellescape\@undefined
      \ifx\directlua\@undefined
        \z@
      \else
        \directlua{%
          tex.sprint((status.shell_escape or os.execute()) .. " ")}
      \fi
    \else
      \shellescape
    \fi
  \else
    \pdfshellescape
  \fi
  \PackageWarning{shellesc}{Shell escape disabled}
\or
  \PackageInfo   {shellesc}{Unrestricted shell escape enabled}
\else
  \PackageInfo   {shellesc}{Restricted shell escape enabled}
\fi
%    \end{macrocode}
%
% \subsection{The shellesc package interface}
%
% \begin{macro}{\ShellEscape}
% Execute the supplied tokens as a system dependent command, assuming 
% such execution is allowed.
%    \begin{macrocode}
\ifx\lastsavedimageresourcepages\@undefined
  \protected\def\ShellEscape{\immediate\write18 }
%    \end{macrocode}
%
%    \begin{macrocode}
\else
  \protected\def\ShellEscape#1{%
    \directlua{os.execute("\luaescapestring{#1}")}}
\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DelayedShellEscape}
% \changes{v0.1c}{2016/04/29}{Define \cs{DelayedShellEscape} not \cs{ShellEscape}(UF)}
% Execute the supplied tokens as a system dependent command, when this
% node is shipped out with the completed page, assuming 
% such execution is allowed.
%    \begin{macrocode}
\ifx\lastsavedimageresourcepages\@undefined
  \protected\def\DelayedShellEscape{\relax\write18 }
%    \end{macrocode}
%
%    \begin{macrocode}
\else
  \protected\def\DelayedShellEscape#1{%
    \latelua{os.execute("\luaescapestring{#1}")}}
\fi
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{The write18 package interface}
%
% In web2c based engines other than Lua\TeX, |\write18| may be used
% directly.  The same was true in older LuaTeX, but from version 0.85
% onwards that is not available.
%
% The above |shellesc| package interface is recommended for new code,
% however for ease of porting existing documents and packages to newer
% Lua\TeX\ releases, a |\write18| interface is provided here via a
% call to Lua's |os.execute|.
%
% Note that as currently written this always does an \emph{immediate}
% call to the system.
%
% |\immediate| is supported but ignored, |\immediate\write18| and
% |\write18| both execute immediately. To use a delayed execution at
% the next shipout, use the |\DelayedShellEscape| command defined
% above.
%
% Note that it would be easy to make |\wriete18| defined here use
% delayed execution, just use |\DelayedShellEscape| instead of
% |ShellEscape| in the definition below. However detecting
% |\immediate| is tricky so the choice here is to always use the
% immediate form, which is overwhelmingly more commonly used with
% |\write18|.
%
% Stop at this point if not a recent Lua\TeX.
%    \begin{macrocode}
\ifx\lastsavedimageresourcepages\@undefined\expandafter\endinput\fi
%    \end{macrocode}
%
%    \begin{macrocode}
\directlua{%
%    \end{macrocode}
%
%    \begin{macrocode}
shellesc = shellesc or {}
%    \end{macrocode}
%
% Lua function to use the token scanner to grab the following \TeX\
% number, and then test if stream 18 is being used, and then insert an
% appropriate \TeX\ command to handle the following brace group in
% each case.
%    \begin{macrocode}
local function write_or_execute()
  local s = token.scan_int()
  if (s==18) then
     tex.sprint(\the\numexpr\catcodetable@atletter\relax,
                "\string\\ShellEscape ")
  else
     tex.sprint(\the\numexpr\catcodetable@atletter\relax,
                "\string\\shellesc@write " .. s)
  end
end
%    \end{macrocode}
%
%    \begin{macrocode}
shellesc.write_or_execute=write_or_execute
%    \end{macrocode}
%
%    \begin{macrocode}
}
%    \end{macrocode}
%
%    \begin{macrocode}
\let\shellesc@write\write
%    \end{macrocode}
%
%    \begin{macrocode}
\protected\def\write{\directlua{shellesc.write_or_execute()}}
%    \end{macrocode}
%
%
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \Finale
%