1if not modules then modules = { } end modules ['strc-blk'] = {
2 version = 1.001,
3 comment = "companion to strc-blk.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
11local type, next = type, next
12local find, formatters, validstring = string.find, string.formatters, string.valid
13local settings_to_set, settings_to_array = utilities.parsers.settings_to_set, utilities.parsers.settings_to_array
14local allocate = utilities.storage.allocate
15
16local context = context
17local commands = commands
18
19local implement = interfaces.implement
20
21local structures = structures
22
23structures.blocks = structures.blocks or { }
24
25local blocks = structures.blocks
26local sections = structures.sections
27local lists = structures.lists
28local helpers = structures.helpers
29
30local collected = allocate()
31local tobesaved = allocate()
32local states = allocate()
33
34blocks.collected = collected
35blocks.tobesaved = tobesaved
36blocks.states = states
37
38local function initializer()
39 collected = blocks.collected
40 tobesaved = blocks.tobesaved
41end
42
43job.register('structures.blocks.collected', tobesaved, initializer)
44
45local listitem = utilities.parsers.listitem
46local f_block = formatters["block.%s"]
47
48function blocks.uservariable(index,key,default)
49 local c = collected[index]
50 if c then
51 local u = c.userdata
52 if u then
53 local v = u[key] or default
54 if v then
55 context(v)
56 end
57 end
58 end
59end
60
61local function printblock(index,name,data,hide)
62 if hide then
63 context.dostarthiddenblock(index,name)
64 else
65 context.dostartnormalblock(index,name)
66 end
67 context.viafile(data,f_block(validstring(name,"noname")))
68 if hide then
69 context.dostophiddenblock()
70 else
71 context.dostopnormalblock()
72 end
73end
74
75blocks.print = printblock
76
77function blocks.define(name)
78 states[name] = { all = "hide" }
79end
80
81function blocks.setstate(state,name,tag)
82 local all = tag == ""
83 local tags = not all and settings_to_array(tag)
84 for n in listitem(name) do
85 local sn = states[n]
86 if not sn then
87
88 elseif all then
89 sn.all = state
90 else
91 for _, tag in next, tags do
92 sn[tag] = state
93 end
94 end
95 end
96end
97
98
99local function selectblocks(state,name,tag,criterium,action)
100 if not criterium or criterium == "" then
101 criterium = "text"
102 end
103 if find(tag,"=",1,true) then
104 tag = ""
105 end
106 local names = settings_to_set(name)
107 local all = tag == ""
108 local tags = not all and settings_to_set(tag)
109 local hide = state == "process"
110 local result = lists.filter {
111 names = "all",
112 criterium = criterium,
113 number = sections.numberatdepth(criterium),
114 collected = collected,
115 }
116 for i=1,#result do
117 local ri = result[i]
118 local metadata = ri.metadata
119 if names[metadata.name] then
120 if all then
121 if action(ri.index,name,ri.data,hide) then
122 return
123 end
124 else
125 local mtags = metadata.tags
126 if mtags then
127 for tag, sta in next, tags do
128 if mtags[tag] then
129 if action(ri.index,name,ri.data,hide) then
130 return
131 else
132 break
133 end
134 end
135 end
136 end
137 end
138 end
139 end
140end
141
142function blocks.select(state,name,tag,criterium)
143 selectblocks(state,name,tag,criterium,printblock)
144end
145
146function blocks.empty(state,name,tag,criterium)
147 local found = false
148 local function checkempty(_,_,data)
149 found = type(data) == "string" and find(data,"%S")
150 return found
151 end
152 selectblocks(state,name,tag,criterium,checkempty)
153 return not found
154end
155
156function blocks.save(name,tag,userdata,buffer)
157 local data = buffers.getcontent(buffer)
158 local tags = settings_to_set(tag)
159 local plus = false
160 local minus = false
161 local last = #tobesaved + 1
162 local all = states[name].all
163 if tags['+'] then
164 plus = true
165 tags['+'] = nil
166 end
167 if tags['-'] then
168 minus = true
169 tags['-'] = nil
170 end
171 tobesaved[last] = helpers.simplify {
172 metadata = {
173 name = name,
174 tags = tags,
175 plus = plus,
176 minus = minus,
177 },
178 index = last,
179 data = data or "error",
180 userdata = userdata and type(userdata) == "string" and helpers.touserdata(userdata),
181 references = {
182 section = sections.currentid(),
183 },
184 }
185 if not next(tags) then
186 if all ~= "hide" then
187 printblock(last,name,data)
188 elseif plus then
189 printblock(last,name,data,true)
190 end
191 else
192 local sn = states[name]
193 for tag, _ in next, tags do
194 if sn[tag] == nil then
195 if all ~= "hide" then
196 printblock(last,name,data)
197 break
198 end
199 elseif sn[tag] ~= "hide" then
200 printblock(last,name,data)
201 break
202 end
203 end
204 end
205 buffers.erase(buffer)
206end
207
208
209
210
211implement { name = "definestructureblock", actions = blocks.define, arguments = "string" }
212implement { name = "savestructureblock", actions = blocks.save, arguments = "4 strings" }
213implement { name = "selectstructureblock", actions = blocks.select, arguments = "4 strings" }
214implement { name = "setstructureblockstate", actions = blocks.setstate, arguments = "3 strings" }
215implement { name = "structureblockuservariable", actions = blocks.uservariable, arguments = { "integer", "string" } }
216
217implement {
218 name = "doifelsestructureblocksempty",
219 arguments = "3 strings",
220 actions = function(name,tag,criterium)
221 commands.doifelse(blocks.empty(false,name,tag,criterium))
222 end,
223}
224 |