1if not modules then modules = { } end modules ['lxml-sor'] = {
2 version = 1.001,
3 comment = "companion to lxml-sor.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 format, concat, rep = string.format, table.concat, string.rep
10local lpegmatch = lpeg.match
11local next = next
12
13local xml = xml
14local lxml = lxml
15local context = context
16
17local lxmlsorters = lxml.sorters or { }
18lxml.sorters = lxmlsorters
19
20if not lxml.splitid then
21 local splitter = lpeg.C((1-lpeg.P(":"))^1) * lpeg.P("::") * lpeg.C(lpeg.P(1)^1)
22 function lxml.splitid(id)
23 local d, i = lpegmatch(splitter,id)
24 if d then
25 return d, i
26 else
27 return "", id
28 end
29 end
30end
31
32local lists = { }
33
34function lxmlsorters.reset(name)
35 lists[name] = {
36 sorted = false,
37 entries = { },
38 reverse = { },
39 results = { },
40 }
41end
42
43function lxmlsorters.add(name,n,key)
44 local list = lists[name]
45 if list.sorted then
46
47 else
48 local entries = list and list.entries
49 if entries then
50 local reverse = list.reverse
51 local e = reverse[n]
52 if e then
53 local keys = entries[e][2]
54 keys[#keys+1] = key
55 else
56 entries[#entries+1] = { n, { key } }
57 reverse[n] = #entries
58 end
59 end
60 end
61end
62
63function lxmlsorters.show(name)
64 local list = lists[name]
65 local entries = list and list.entries
66 local NC, NR, bold = context.NC, context.NR, context.bold
67 if entries then
68 local maxn = 1
69 for i=1,#entries do
70 if #entries[i][2] > maxn then maxn = #entries[i][2] end
71 end
72 context.starttabulate { "|Tr|Tr|" .. rep("Tlp|",maxn) }
73 NC() bold("n")
74 NC() bold("id")
75 if maxn > 1 then
76 for i=1,maxn do
77 NC() bold("entry " .. i)
78 end
79 else
80 NC() bold("entry")
81 end
82 NC() NR()
83 context.HL()
84 for i=1,#entries do
85 local entry = entries[i]
86 local document, node = lxml.splitid(entry[1])
87 NC() context(i)
88 NC() context(node)
89 local e = entry[2]
90 for i=1,#e do
91 NC() context.detokenize(e[i])
92 end
93 NC() NR()
94 end
95 context.stoptabulate()
96 end
97end
98
99lxmlsorters.compare = sorters.comparers.basic
100
101function lxmlsorters.sort(name)
102 local list = lists[name]
103 local entries = list and list.entries
104 if entries then
105
106 local results = { }
107 list.results = results
108 for i=1,#entries do
109 local entry = entries[i]
110 results[i] = {
111 entry = entry[1],
112 key = concat(entry[2], " "),
113 }
114 end
115
116 local strip = sorters.strip
117 local splitter = sorters.splitters.utf
118 local firstofsplit = sorters.firstofsplit
119 for i=1, #results do
120 local r = results[i]
121 r.split = splitter(strip(r.key))
122 end
123
124 sorters.sort(results,lxmlsorters.compare)
125
126 list.nofsorted = #results
127 local split = { }
128 for k=1,#results do
129 local v = results[k]
130 local entry, tag = firstofsplit(v)
131 local s = split[entry]
132 if not s then
133 s = { tag = tag, data = { } }
134 split[entry] = s
135 end
136 s.data[#s.data+1] = v
137 end
138 list.results = split
139
140 list.sorted = true
141 end
142end
143
144function lxmlsorters.flush(name,setup)
145 local list = lists[name]
146 local results = list and list.results
147 local xmlw = context.xmlw
148 if results and next(results) then
149 for key, result in next, results do
150 local tag, data = result.tag, result.data
151 for d=1,#data do
152 xmlw(setup,data[d].entry)
153 end
154 end
155 else
156 local entries = list and list.entries
157 if entries then
158 for i=1,#entries do
159 xmlw(setup,entries[i][1])
160 end
161 end
162 end
163end
164 |