util-env.lua /size: 9738 b    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
util-env
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to luat-lib.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
local
allocate
,
mark
=
utilities
.
storage
.
allocate
,
utilities
.
storage
.
mark
10 11
local
format
,
sub
,
match
,
gsub
,
find
=
string
.
format
,
string
.
sub
,
string
.
match
,
string
.
gsub
,
string
.
find
12
local
unquoted
,
quoted
,
optionalquoted
=
string
.
unquoted
,
string
.
quoted
,
string
.
optionalquoted
13
local
concat
,
insert
,
remove
=
table
.
concat
,
table
.
insert
,
table
.
remove
14 15
environment
=
environment
or
{
}
16
local
environment
=
environment
17 18
-- locales are a useless feature in and even dangerous for luatex
19 20
local
setlocale
=
os
.
setlocale
21 22
setlocale
(
nil
,
nil
)
-- setlocale("all","C")
23 24
-- function os.resetlocale()
25
-- setlocale(nil,nil)
26
-- end
27
--
28
-- function os.pushlocale(l,...)
29
-- insert(stack, {
30
-- collate = setlocale(nil,"collate"),
31
-- ctype = setlocale(nil,"ctype"),
32
-- monetary = setlocale(nil,"monetary"),
33
-- numeric = setlocale(nil,"numeric"),
34
-- time = setlocale(nil,"time"),
35
-- })
36
-- if l then
37
-- setlocale(l,...)
38
-- else
39
-- setlocale(status.lc_collate ,"collate"),
40
-- setlocale(status.lc_ctype ,"ctype"),
41
-- setlocale(status.lc_monetary,"monetary"),
42
-- setlocale(status.lc_numeric ,"numeric"),
43
-- setlocale(status.lc_time ,"time"),
44
-- end
45
-- end
46
--
47
-- function os.poplocale()
48
-- local l = remove(stack)
49
-- if l then
50
-- setlocale(unpack(l))
51
-- else
52
-- resetlocale()
53
-- end
54
-- end
55 56
local
report
=
logs
.
reporter
(
"
system
"
)
57 58
function
os
.
setlocale
(
a
,
b
)
59
if
a
or
b
then
60
if
report
then
61
report
(
)
62
report
(
"
You're messing with os.locale in a supposedly locale neutral enviroment. From
"
)
63
report
(
"
now on are on your own and without support. Crashes or unexpected side effects
"
)
64
report
(
"
can happen but don't bother the luatex and context developer team with it.
"
)
65
report
(
)
66
report
=
nil
67
end
68
setlocale
(
a
,
b
)
69
end
70
end
71 72
-- dirty tricks (we will replace the texlua call by luatex --luaonly)
73 74
local
validengines
=
allocate
{
75
[
"
luatex
"
]
=
true
,
76
[
"
luajittex
"
]
=
true
,
77
}
78 79
local
basicengines
=
allocate
{
80
[
"
luatex
"
]
=
"
luatex
"
,
81
[
"
texlua
"
]
=
"
luatex
"
,
-- obsolete
82
[
"
texluac
"
]
=
"
luatex
"
,
-- obsolete
83
[
"
luajittex
"
]
=
"
luajittex
"
,
84
[
"
texluajit
"
]
=
"
luajittex
"
,
-- obsolete
85
}
86 87
local
luaengines
=
allocate
{
88
[
"
lua
"
]
=
true
,
89
[
"
luajit
"
]
=
true
,
90
}
91 92
environment
.
validengines
=
validengines
93
environment
.
basicengines
=
basicengines
94 95
-- [-1] = binary
96
-- [ 0] = self
97
-- [ 1] = argument 1 ...
98 99
-- instead we could set ranges
100 101
if
not
arg
then
102
environment
.
used_as_library
=
true
103
-- used as library
104
elseif
luaengines
[
file
.
removesuffix
(
arg
[
-1
]
)
]
then
105
-- arg[-1] = arg[0]
106
-- arg[ 0] = arg[1]
107
-- for k=2,#arg do
108
-- arg[k-1] = arg[k]
109
-- end
110
-- remove(arg) -- last
111
--
112
-- environment.used_as_library = true
113
elseif
validengines
[
file
.
removesuffix
(
arg
[
0
]
)
]
then
114
if
arg
[
1
]
=
=
"
--luaonly
"
then
115
arg
[
-1
]
=
arg
[
0
]
116
arg
[
0
]
=
arg
[
2
]
117
for
k
=
3
,
#
arg
do
118
arg
[
k
-2
]
=
arg
[
k
]
119
end
120
remove
(
arg
)
-- last
121
remove
(
arg
)
-- pre-last
122
else
123
-- tex run
124
end
125 126
-- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in:
127
--
128
-- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context
129
--
130
-- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base'
131
-- but it's unlikely that there will be more of this
132 133
local
originalzero
=
file
.
basename
(
arg
[
0
]
)
134
local
specialmapping
=
{
luatools
=
=
"
base
"
}
135 136
if
originalzero
~
=
"
mtxrun
"
and
originalzero
~
=
"
mtxrun.lua
"
then
137
arg
[
0
]
=
specialmapping
[
originalzero
]
or
originalzero
138
insert
(
arg
,
0
,
"
--script
"
)
139
insert
(
arg
,
0
,
"
mtxrun
"
)
140
end
141 142
end
143 144
-- environment
145 146
environment
.
arguments
=
allocate
(
)
147
environment
.
files
=
allocate
(
)
148
environment
.
sortedflags
=
nil
149 150
-- context specific arguments (in order not to confuse the engine)
151 152
function
environment
.
initializearguments
(
arg
)
153
local
arguments
=
{
}
154
local
files
=
{
}
155
environment
.
arguments
=
arguments
156
environment
.
files
=
files
157
environment
.
sortedflags
=
nil
158
for
index
=
1
,
#
arg
do
159
local
argument
=
arg
[
index
]
160
if
index
>
0
then
161
local
flag
,
value
=
match
(
argument
,
"
^%-+(.-)=(.-)$
"
)
162
if
flag
then
163
flag
=
gsub
(
flag
,
"
^c:
"
,
"
"
)
164
arguments
[
flag
]
=
unquoted
(
value
or
"
"
)
165
else
166
flag
=
match
(
argument
,
"
^%-+(.+)
"
)
167
if
flag
then
168
flag
=
gsub
(
flag
,
"
^c:
"
,
"
"
)
169
arguments
[
flag
]
=
true
170
else
171
files
[
#
files
+
1
]
=
argument
172
end
173
end
174
end
175
end
176
if
not
environment
.
ownname
then
177
if
os
.
selfpath
and
os
.
selfname
then
178
environment
.
ownname
=
file
.
addsuffix
(
file
.
join
(
os
.
selfpath
,
os
.
selfname
)
,
"
lua
"
)
179
end
180
end
181
environment
.
ownname
=
file
.
reslash
(
environment
.
ownname
or
arg
[
0
]
or
'
unknown.lua
'
)
182
end
183 184
function
environment
.
setargument
(
name
,
value
)
185
environment
.
arguments
[
name
]
=
value
186
end
187 188
-- todo: defaults, better checks e.g on type (boolean versus string)
189
--
190
-- tricky: too many hits when we support partials unless we add
191
-- a registration of arguments so from now on we have 'partial'
192 193
function
environment
.
getargument
(
name
,
partial
)
194
local
arguments
,
sortedflags
=
environment
.
arguments
,
environment
.
sortedflags
195
if
arguments
[
name
]
then
196
return
arguments
[
name
]
197
elseif
partial
then
198
if
not
sortedflags
then
199
sortedflags
=
allocate
(
table
.
sortedkeys
(
arguments
)
)
200
for
k
=
1
,
#
sortedflags
do
201
sortedflags
[
k
]
=
"
^
"
.
.
sortedflags
[
k
]
202
end
203
environment
.
sortedflags
=
sortedflags
204
end
205
-- example of potential clash: ^mode ^modefile
206
for
k
=
1
,
#
sortedflags
do
207
local
v
=
sortedflags
[
k
]
208
if
find
(
name
,
v
)
then
209
return
arguments
[
sub
(
v
,
2
,
#
v
)
]
210
end
211
end
212
end
213
return
nil
214
end
215 216
environment
.
argument
=
environment
.
getargument
217 218
function
environment
.
splitarguments
(
separator
)
-- rather special, cut-off before separator
219
local
done
,
before
,
after
=
false
,
{
}
,
{
}
220
local
originalarguments
=
environment
.
originalarguments
221
for
k
=
1
,
#
originalarguments
do
222
local
v
=
originalarguments
[
k
]
223
if
not
done
and
v
=
=
separator
then
224
done
=
true
225
elseif
done
then
226
after
[
#
after
+
1
]
=
v
227
else
228
before
[
#
before
+
1
]
=
v
229
end
230
end
231
return
before
,
after
232
end
233 234
function
environment
.
reconstructcommandline
(
arg
,
noquote
)
235
local
resolveprefix
=
resolvers
.
resolve
-- something rather special
236
arg
=
arg
or
environment
.
originalarguments
237
if
noquote
and
#
arg
=
=
1
then
238
return
unquoted
(
resolveprefix
and
resolveprefix
(
arg
[
1
]
)
or
arg
[
1
]
)
239
elseif
#
arg
>
0
then
240
local
result
=
{
}
241
for
i
=
1
,
#
arg
do
242
result
[
i
]
=
optionalquoted
(
resolveprefix
and
resolveprefix
(
arg
[
i
]
)
or
resolveprefix
)
243
end
244
return
concat
(
result
,
"
"
)
245
else
246
return
"
"
247
end
248
end
249 250
-- handy in e.g. package.addluapath(environment.relativepath("scripts"))
251 252
function
environment
.
relativepath
(
path
,
root
)
253
if
not
path
then
254
path
=
"
"
255
end
256
if
not
file
.
is_rootbased_path
(
path
)
then
257
if
not
root
then
258
root
=
file
.
pathpart
(
environment
.
ownscript
or
environment
.
ownname
or
"
.
"
)
259
end
260
if
root
=
=
"
"
then
261
root
=
"
.
"
262
end
263
path
=
root
.
.
"
/
"
.
.
path
264
end
265
return
file
.
collapsepath
(
path
,
true
)
266
end
267 268
-- -- when script lives on e:/tmp we get this:
269
--
270
-- print(environment.relativepath("x/y/z","c:/w")) -- c:/w/x/y/z
271
-- print(environment.relativepath("x")) -- e:/tmp/x
272
-- print(environment.relativepath("../x")) -- e:/x
273
-- print(environment.relativepath("./x")) -- e:/tmp/x
274
-- print(environment.relativepath("/x")) -- /x
275
-- print(environment.relativepath("c:/x")) -- c:/x
276
-- print(environment.relativepath("//x")) -- //x
277
-- print(environment.relativepath()) -- e:/tmp
278 279
if
arg
then
280 281
-- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
282 283
local
newarg
,
instring
=
{
}
,
false
284 285
for
index
=
1
,
#
arg
do
286
local
argument
=
arg
[
index
]
287
if
find
(
argument
,
"
^\"
"
)
then
288
if
find
(
argument
,
"
\"$
"
)
then
289
newarg
[
#
newarg
+
1
]
=
gsub
(
argument
,
"
^\"(.-)\"$
"
,
"
%1
"
)
290
instring
=
false
291
else
292
newarg
[
#
newarg
+
1
]
=
gsub
(
argument
,
"
^\"
"
,
"
"
)
293
instring
=
true
294
end
295
elseif
find
(
argument
,
"
\"$
"
)
then
296
if
instring
then
297
newarg
[
#
newarg
]
=
newarg
[
#
newarg
]
.
.
"
"
.
.
gsub
(
argument
,
"
\"$
"
,
"
"
)
298
instring
=
false
299
else
300
newarg
[
#
newarg
+
1
]
=
argument
301
end
302
elseif
instring
then
303
newarg
[
#
newarg
]
=
newarg
[
#
newarg
]
.
.
"
"
.
.
argument
304
else
305
newarg
[
#
newarg
+
1
]
=
argument
306
end
307
end
308
for
i
=
1
,
-5
,
-1
do
309
newarg
[
i
]
=
arg
[
i
]
310
end
311 312
environment
.
initializearguments
(
newarg
)
313 314
environment
.
originalarguments
=
mark
(
newarg
)
315
environment
.
rawarguments
=
mark
(
arg
)
316 317
arg
=
{
}
-- prevent duplicate handling
318 319
end
320