1if not modules then modules = { } end modules ['buff-par'] = {
2 version = 1.001,
3 comment = "companion to buff-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
9local tonumber = tonumber
10local insert, remove, find, gmatch, match = table.insert, table.remove, string.find, string.gmatch, string.match
11local fullstrip, formatters = string.fullstrip, string.formatters
12
13local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end)
14
15local report_parallel = logs.reporter("buffers","parallel")
16
17local variables = interfaces.variables
18local v_all = variables.all
19
20local parallel = buffers.parallel or { }
21buffers.parallel = parallel
22
23local settings_to_array = utilities.parsers.settings_to_array
24
25local context = context
26local implement = interfaces.implement
27
28local data = { }
29
30function parallel.define(category,tags)
31 local tags = settings_to_array(tags)
32 local entries = { }
33 data[category] = {
34 tags = tags,
35 entries = entries,
36 }
37 for i=1,#tags do
38 entries[tags[i]] = {
39 lines = { },
40 number = 0,
41 }
42 end
43end
44
45function parallel.reset(category,tags)
46 if not tags or tags == "" or tags == v_all then
47 tags = table.keys(entries)
48 else
49 tags = settings_to_array(tags)
50 end
51 for i=1,#tags do
52 entries[tags[i]] = {
53 lines = { },
54 number = 0,
55 }
56 end
57end
58
59function parallel.next(category)
60 local dc = data[category]
61 local tags = dc.tags
62 local entries = dc.entries
63 for i=1,#tags do
64 insert(entries[tags[i]].lines, { })
65 end
66end
67
68function parallel.save(category,tag,content,frombuffer)
69 if frombuffer then
70 content = buffers.raw(content)
71 end
72 local dc = data[category]
73 if not dc then
74 report_parallel("unknown category %a",category)
75 return
76 end
77 local entries = dc.entries[tag]
78 if not entries then
79 report_parallel("unknown entry %a",tag)
80 return
81 end
82 local lines = entries.lines
83 if not lines then
84 return
85 end
86 local line = lines[#lines]
87 if not line then
88 return
89 end
90
91
92 if find(content,"%s*%[") then
93 local done = false
94
95 local function flush(content,label)
96 if done then
97 line = { }
98 insert(lines,line)
99 else
100 done = true
101 end
102 line.content = fullstrip(content)
103 line.label = label
104 end
105
106
107 local leading, rest = match(content,"^%s*([^%[]+)(.*)$")
108 if leading then
109 if leading ~= "" then
110 flush(leading)
111 end
112 content = rest
113 end
114 for label, content in gmatch(content,"%s*%[(.-)%]%s*([^%[]+)") do
115 if trace_parallel and label ~= "" then
116 report_parallel("reference found of category %a, tag %a, label %a",category,tag,label)
117 end
118 flush(content,label)
119 end
120 else
121 line.content = fullstrip(content)
122 line.label = ""
123 end
124
125end
126
127function parallel.hassomecontent(category,tags)
128 local dc = data[category]
129 if not dc then
130 return false
131 end
132 local entries = dc.entries
133 if not tags or tags == "" or tags == v_all then
134 tags = table.keys(entries)
135 else
136 tags = utilities.parsers.settings_to_array(tags)
137 end
138 for t=1,#tags do
139 local tag = tags[t]
140 local lines = entries[tag].lines
141 for i=1,#lines do
142 local content = lines[i].content
143 if content and content ~= "" then
144 return true
145 end
146 end
147 end
148 return false
149end
150
151local ctx_doflushparallel = context.doflushparallel
152local f_content = formatters["\\input{%s}"]
153local save_byscheme = resolvers.savers.byscheme
154
155function parallel.place(category,tags,options)
156 local dc = data[category]
157 if not dc then
158 return
159 end
160 local entries = dc.entries
161 local tags = utilities.parsers.settings_to_array(tags)
162 local options = utilities.parsers.settings_to_hash(options)
163 local start = tonumber(options.start)
164 local n = tonumber(options.n)
165 local criterium = options.criterium
166 local max = 1
167 if n then
168 max = n
169 elseif criterium == v_all then
170 max = 0
171 for t=1,#tags do
172 local tag = tags[t]
173 local lines = entries[tag].lines
174 if #lines > max then
175 max = #lines
176 end
177 end
178 end
179 for i=1,max do
180 for t=1,#tags do
181 local tag = tags[t]
182 local entry = entries[tag]
183 if entry then
184 local lines = entry.lines
185 local number = entry.number + 1
186 entry.number = number
187 local line = remove(lines,1)
188 local content = line and line.content
189 local label = line and line.label or ""
190 if content then
191 local virtual = save_byscheme("virtual","parallel",content)
192 ctx_doflushparallel(tag,1,number,label,f_content(virtual))
193 else
194 ctx_doflushparallel(tag,0,number,"","")
195 end
196 end
197 end
198 end
199end
200
201
202
203implement {
204 name = "defineparallel",
205 actions = parallel.define,
206 arguments = "2 strings",
207}
208
209implement {
210 name = "nextparallel",
211 actions = parallel.next,
212 arguments = "string"
213}
214
215implement {
216 name = "saveparallel",
217 actions = parallel.save,
218 arguments = { "string", "string", "string", true },
219}
220
221implement {
222 name = "placeparallel",
223 actions = parallel.place,
224 arguments = {
225 "string",
226 "string",
227 {
228 { "start" },
229 { "n" },
230 { "criterium" },
231 { "setups" },
232 }
233 }
234}
235
236implement {
237 name = "resetparallel",
238 actions = parallel.reset,
239 arguments = "2 strings",
240}
241
242implement {
243 name = "doifelseparallel",
244 actions = { parallel.hassomecontent, commands.doifelse } ,
245 arguments = "2 strings",
246}
247 |