node-shp.lua /size: 7317 b    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
node-shp
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to node-ini.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
nodes
,
node
=
nodes
,
node
10 11
local
next
,
type
=
next
,
type
12
local
format
=
string
.
format
13
local
concat
,
sortedpairs
=
table
.
concat
,
table
.
sortedpairs
14
local
setmetatableindex
=
table
.
setmetatableindex
15 16
local
nodecodes
=
nodes
.
nodecodes
17
local
whatsitcodes
=
nodes
.
whatsitcodes
18
local
disccodes
=
nodes
.
disccodes
19 20
local
tasks
=
nodes
.
tasks
21
local
handlers
=
nodes
.
handlers
22 23
local
hlist_code
=
nodecodes
.
hlist
24
local
vlist_code
=
nodecodes
.
vlist
25
local
disc_code
=
nodecodes
.
disc
26
local
whatsit_code
=
nodecodes
.
whatsit
27 28
local
discretionarydisc_code
=
disccodes
.
discretionary
29 30
local
implement
=
interfaces
.
implement
31 32
local
nuts
=
nodes
.
nuts
33
local
tonut
=
nuts
.
tonut
34
local
tonode
=
nuts
.
tonode
35
local
remove_node
=
nuts
.
remove
36 37
local
nextnode
=
nuts
.
traversers
.
node
38 39
local
setfield
=
nuts
.
setfield
40
local
setlink
=
nuts
.
setlink
41
local
setprev
=
nuts
.
setprev
42
local
setnext
=
nuts
.
setnext
43
local
getid
=
nuts
.
getid
44
local
getdisc
=
nuts
.
getdisc
45
local
getboth
=
nuts
.
getboth
46
local
getnext
=
nuts
.
getnext
47
local
getlist
=
nuts
.
getlist
48
local
getsubtype
=
nuts
.
getsubtype
49 50
local
setlist
=
nuts
.
setlist
51 52
local
getbox
=
nuts
.
getbox
53 54
local
removables
=
{
55
[
whatsitcodes
.
open
]
=
true
,
56
[
whatsitcodes
.
close
]
=
true
,
57
[
whatsitcodes
.
write
]
=
true
,
58
[
whatsitcodes
.
savepos
]
=
true
,
59
[
whatsitcodes
.
latelua
]
=
true
,
60
-- [whatsitcodes.pdfdest] = true,
61
}
62 63
-- About 10% of the nodes make no sense for the backend. By (at least)
64
-- removing the replace disc nodes, we can omit extensive checking in
65
-- the finalizer code (e.g. colors in disc nodes). Removing more nodes
66
-- (like marks) is not saving much and removing empty boxes is even
67
-- dangerous because we can rely on dimensions (e.g. in references).
68 69
local
wipedisc
=
false
-- we can use them in the export ... can be option
70 71
local
function
cleanup_redundant
(
head
)
-- better name is: flatten_page
72
local
start
=
head
73
while
start
do
74
local
id
=
getid
(
start
)
75
if
id
=
=
disc_code
then
76
if
getsubtype
(
start
)
=
=
discretionarydisc_code
then
77
local
_
,
_
,
replace
,
_
,
_
tail
=
getdisc
(
start
,
true
)
78
if
replace
then
79
local
prev
,
next
=
getboth
(
start
)
80
setfield
(
start
,
"
replace
"
,
nil
)
81
if
start
=
=
head
then
82
remove_node
(
head
,
start
,
true
)
83
head
=
replace
84
else
85
remove_node
(
head
,
start
,
true
)
86
end
87
if
next
then
88
setlink
(
tail
,
next
)
89
end
90
if
prev
then
91
setlink
(
prev
,
replace
)
92
else
93
setprev
(
replace
)
-- to be sure
94
end
95
start
=
next
96
elseif
wipedisc
then
97
-- pre and post can have values
98
head
,
start
=
remove_node
(
head
,
start
,
true
)
99
else
100
start
=
getnext
(
start
)
101
end
102
else
103
start
=
getnext
(
start
)
104
end
105
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
106
local
sl
=
getlist
(
start
)
107
if
sl
then
108
local
rl
=
cleanup_redundant
(
sl
)
109
if
rl
~
=
sl
then
110
setlist
(
start
,
rl
)
111
end
112
end
113
start
=
getnext
(
start
)
114
else
115
start
=
getnext
(
start
)
116
end
117
end
118
return
head
119
end
120 121
handlers
.
cleanuppage
=
cleanup_redundant
-- nut
122 123
local
function
cleanup_flushed
(
head
)
-- rough
124
local
start
=
head
125
while
start
do
126
local
id
=
getid
(
start
)
127
if
id
=
=
whatsit_code
then
128
if
removables
[
getsubtype
(
start
)
]
then
129
head
,
start
=
remove_node
(
head
,
start
,
true
)
130
else
131
start
=
getnext
(
start
)
132
end
133
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
134
local
sl
=
getlist
(
start
)
135
if
sl
then
136
local
rl
=
cleanup_flushed
(
sl
)
137
if
rl
~
=
sl
then
138
setlist
(
start
,
rl
)
139
end
140
end
141
start
=
getnext
(
start
)
142
else
143
start
=
getnext
(
start
)
144
end
145
end
146
return
head
147
end
148 149
function
handlers
.
cleanupbox
(
box
)
150
cleanup_flushed
(
getbox
(
box
)
)
151
end
152 153
local
actions
=
tasks
.
actions
(
"
shipouts
"
)
154 155
function
handlers
.
finalizebox
(
box
)
156
actions
(
getbox
(
box
)
)
-- nut
157
end
158 159
-- interface
160 161
implement
{
name
=
"
cleanupbox
"
,
actions
=
handlers
.
cleanupbox
,
arguments
=
"
integer
"
}
162
implement
{
name
=
"
finalizebox
"
,
actions
=
handlers
.
finalizebox
,
arguments
=
"
integer
"
}
163 164
-- just in case we want to optimize lookups:
165 166
local
frequencies
=
{
}
167 168
nodes
.
tracers
.
frequencies
=
frequencies
169 170
local
data
=
{
}
171
local
done
=
false
172 173
setmetatableindex
(
data
,
function
(
t
,
k
)
174
local
v
=
{
}
175
setmetatableindex
(
v
,
function
(
t
,
k
)
176
local
v
=
{
}
177
t
[
k
]
=
v
178
setmetatableindex
(
v
,
function
(
t
,
k
)
179
t
[
k
]
=
0
180
return
0
181
end
)
182
return
v
183
end
)
184
t
[
k
]
=
v
185
return
v
186
end
)
187 188
local
function
count
(
head
,
data
,
subcategory
)
189
-- no components, pre, post, replace .. can maybe an option .. but
190
-- we use this for optimization so it makes sense to look the the
191
-- main node only
192
for
n
,
id
in
nextnode
,
tonut
(
head
)
do
193
local
dn
=
data
[
nodecodes
[
id
]
]
-- we could use id and then later convert to nodecodes
194
dn
[
subcategory
]
=
dn
[
subcategory
]
+
1
195
if
id
=
=
hlist_code
or
id
=
=
vlist_code
then
196
count
(
getlist
(
n
)
,
data
,
subcategory
)
197
end
198
end
199
end
200 201
local
function
register
(
category
,
subcategory
)
202
return
function
(
head
)
203
done
=
true
204
count
(
head
,
data
[
category
]
,
subcategory
)
205
return
head
,
false
206
end
207
end
208 209
frequencies
.
register
=
register
210
frequencies
.
filename
=
nil
211 212
trackers
.
register
(
"
nodes.frequencies
"
,
function
(
v
)
213
if
type
(
v
)
=
=
"
string
"
then
214
frequencies
.
filename
=
v
215
end
216
handlers
.
frequencies_shipouts_before
=
register
(
"
shipouts
"
,
"
begin
"
)
217
handlers
.
frequencies_shipouts_after
=
register
(
"
shipouts
"
,
"
end
"
)
218
handlers
.
frequencies_processors_before
=
register
(
"
processors
"
,
"
begin
"
)
219
handlers
.
frequencies_processors_after
=
register
(
"
processors
"
,
"
end
"
)
220
tasks
.
prependaction
(
"
shipouts
"
,
"
before
"
,
"
nodes.handlers.frequencies_shipouts_before
"
)
221
tasks
.
appendaction
(
"
shipouts
"
,
"
after
"
,
"
nodes.handlers.frequencies_shipouts_after
"
)
222
tasks
.
prependaction
(
"
processors
"
,
"
before
"
,
"
nodes.handlers.frequencies_processors_before
"
)
223
tasks
.
appendaction
(
"
processors
"
,
"
after
"
,
"
nodes.handlers.frequencies_processors_after
"
)
224
end
)
225 226
statistics
.
register
(
"
node frequencies
"
,
function
(
)
227
if
done
then
228
local
filename
=
frequencies
.
filename
or
(
tex
.
jobname
.
.
"
-frequencies.lua
"
)
229
io
.
savedata
(
filename
,
table
.
serialize
(
data
,
true
)
)
230
return
format
(
"
saved in %q
"
,
filename
)
231
end
232
end
)
233