1if not modules then modules = { } end modules ['typo-chr'] = {
2 version = 1.001,
3 comment = "companion to typo-bld.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
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
84local insert, remove = table.insert, table.remove
85
86local context = context
87local ctx_doifelse = commands.doifelse
88
89local nodecodes = nodes.nodecodes
90local boundarycodes = nodes.boundarycodes
91local subtypes = nodes.subtypes
92
93local glyph_code = nodecodes.glyph
94local par_code = nodecodes.par
95local boundary_code = nodecodes.boundary
96
97local wordboundary_code = boundarycodes.word
98
99local texgetnest = tex.getnest
100local texsetcount = tex.setcount
101
102local flushnode = nodes.flushnode
103local flushlist = nodes.flushlist
104
105local settexattribute = tex.setattribute
106local punctuation = characters.is_punctuation
107
108local variables = interfaces.variables
109local v_all = variables.all
110local v_reset = variables.reset
111
112local stack = { }
113
114local a_marked = attributes.numbers['marked']
115local lastmarked = 0
116local marked = {
117 [v_all] = 1,
118 [""] = 1,
119 [v_reset] = attributes.unsetvalue,
120}
121
122local function pickup()
123 local list = texgetnest()
124 if list then
125 local tail = list.tail
126 if tail and tail.id == glyph_code and punctuation[tail.char] then
127 local prev = tail.prev
128 list.tail = prev
129 if prev then
130 prev.next = nil
131 end
132 list.tail = prev
133 tail.prev = nil
134 return tail
135 end
136 end
137end
138
139local actions = {
140 remove = function(specification)
141 local n = pickup()
142 if n then
143 flushnode(n)
144 end
145 end,
146 push = function(specification)
147 local n = pickup()
148 if n then
149 insert(stack,n or false)
150 end
151 end,
152 pop = function(specification)
153 local n = remove(stack)
154 if n then
155 context(n)
156 end
157 end,
158}
159
160local function pickuppunctuation(specification)
161 local action = actions[specification.action or "remove"]
162 if action then
163 action(specification)
164 end
165end
166
167
168
169
170local function pickup(head,tail,str)
171 local attr = marked[str]
172 local last = tail
173 if last[a_marked] == attr then
174 local first = last
175 while true do
176 local prev = first.prev
177 if prev and prev[a_marked] == attr then
178 if prev.id == par_code then
179 break
180 else
181 first = prev
182 end
183 else
184 break
185 end
186 end
187 return first, last
188 end
189end
190
191local function found(str)
192 local list = texgetnest()
193 if list then
194 local tail = list.tail
195 return tail and tail[a_marked] == marked[str]
196 end
197end
198
199local actions = {
200 remove = function(specification)
201 local list = texgetnest()
202 if list then
203 local head = list.head
204 local tail = list.tail
205 local first, last = pickup(head,tail,specification.mark)
206 if first then
207 if first == head then
208 list.head = nil
209 list.tail = nil
210 else
211 local prev = first.prev
212 list.tail = prev
213 prev.next = nil
214 end
215 flushlist(first)
216 end
217 end
218 end,
219}
220
221local function pickupmarkedcontent(specification)
222 local action = actions[specification.action or "remove"]
223 if action then
224 action(specification)
225 end
226end
227
228local function markcontent(str)
229 local currentmarked = marked[str or v_all]
230 if not currentmarked then
231 lastmarked = lastmarked + 1
232 currentmarked = lastmarked
233 marked[str] = currentmarked
234 end
235 settexattribute(a_marked,currentmarked)
236end
237
238interfaces.implement {
239 name = "pickuppunctuation",
240 actions = pickuppunctuation,
241 arguments = {
242 {
243 { "action" }
244 }
245 }
246}
247
248interfaces.implement {
249 name = "pickupmarkedcontent",
250 actions = pickupmarkedcontent,
251 arguments = {
252 {
253 { "action" },
254 { "mark" }
255 }
256 }
257}
258
259interfaces.implement {
260 name = "markcontent",
261 actions = markcontent,
262 arguments = "string",
263}
264
265interfaces.implement {
266 name = "doifelsemarkedcontent",
267 actions = function(str) ctx_doifelse(found(str)) end,
268 arguments = "string",
269}
270
271
272
273interfaces.implement {
274 name = "lastnodeidstring",
275 public = true,
276 actions = function()
277 local list = texgetnest()
278 local okay = false
279 if list then
280 local tail = list.tail
281 if tail then
282 okay = nodecodes[tail.id]
283 end
284 end
285 context(okay or "")
286 end,
287}
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303interfaces.implement {
304 name = "lastnodeid",
305 actions = function()
306 local list = texgetnest()
307 local okay = -1
308 if list then
309 local tail = list.tail
310 if tail then
311 okay = tail.id
312 end
313 end
314 texsetcount("c_syst_last_node_id",okay)
315 end,
316}
317
318interfaces.implement {
319 name = "lastnodesubtypestring",
320 public = true,
321 actions = function()
322 local list = texgetnest()
323 local okay = false
324 if list then
325 local tail = list.tail
326 if head then
327 okay = subtypes[tail.id][tail.subtype]
328 end
329 end
330 context(okay or "")
331 end,
332}
333
334local function lastnodeequals(id,subtype)
335 local list = texgetnest()
336 local okay = false
337 if list then
338 local tail = list.tail
339 if tail then
340 local i = tail.id
341 okay = i == id or i == nodecodes[id]
342 if subtype then
343 local s = tail.subtype
344 okay = s == subtype or s == subtypes[i][subtype]
345 end
346 end
347 end
348 ctx_doifelse(okay)
349end
350
351interfaces.implement {
352 name = "lastnodeequals",
353 arguments = "2 strings",
354 actions = lastnodeequals,
355}
356
357interfaces.implement {
358 name = "atwordboundary",
359 actions = function()
360 lastnodeequals(boundary_code,wordboundary_code)
361 end,
362}
363
364 |