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 |