1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28\startluacode
29 local newprivateslot = fonts.helpers.newprivateslot
30
31 newprivateslot("dirtree one yes")
32 newprivateslot("dirtree one nop")
33 newprivateslot("dirtree first yes")
34 newprivateslot("dirtree first nop")
35 newprivateslot("dirtree last yes")
36 newprivateslot("dirtree last nop")
37 newprivateslot("dirtree middle yes")
38 newprivateslot("dirtree middle nop")
39 newprivateslot("dirtree down yes")
40 newprivateslot("dirtree down nop")
41 newprivateslot("dirtree space yes")
42 newprivateslot("dirtree space nop")
43\stopluacode
44
45\startMPcalculation{simplefun}
46
47 path dirtree_glyphs[] ;
48
49 def InitializeDirTree =
50 dirtree_glyphs[1] := (1,2) -- (1,1) -- (5,1) && (3,1) -- (3,0) ;
51 dirtree_glyphs[2] := (1,2) -- (1,1) -- (5,1) ;
52 dirtree_glyphs[3] := (1,0) -- (1,2) && (1,1) -- (5,1) && (3,1) -- (3,0) ;
53 dirtree_glyphs[4] := (1,0) -- (1,2) && (1,1) -- (5,1) ;
54 dirtree_glyphs[5] := (1,2) -- (1,0) && (1,1) -- (5,1) ;
55 dirtree_glyphs[6] := (1,2) -- (1,0) ;
56 enddef ;
57
58
59 vardef DirTree(expr i, w, h) =
60 numeric u ; u := 1 ;
61 picture p ; p := image (
62 if i > 0 :
63 draw dirtree_glyphs[i]
64 xyscaled(u,3u2)
65 shifted (u2,u)
66 withpen pencircle scaled (u10)
67 ;
68 fi
69 ) ;
70 setbounds p to unitsquare xyscaled(wu,hu) ;
71 draw p ;
72 enddef ;
73
74 lmt_registerglyphs [
75 name = "dirtree",
76 units = 2,
77 usecolor = true,
78 width = 1,
79 height = 2,
80 depth = 1,
81 preamble = "InitializeDirTree"
82 ] ;
83
84 lmt_registerglyph [ category = "dirtree", private = "dirtree one yes" , code = "DirTree(1,5,3)", width = 5 ] ;
85 lmt_registerglyph [ category = "dirtree", private = "dirtree one nop" , code = "DirTree(2,5,3)", width = 5 ] ;
86 lmt_registerglyph [ category = "dirtree", private = "dirtree first yes" , code = "DirTree(3,5,3)", width = 5 ] ;
87 lmt_registerglyph [ category = "dirtree", private = "dirtree first nop" , code = "DirTree(4,5,3)", width = 5 ] ;
88 lmt_registerglyph [ category = "dirtree", private = "dirtree last yes" , code = "DirTree(1,5,3)", width = 5 ] ;
89 lmt_registerglyph [ category = "dirtree", private = "dirtree last nop" , code = "DirTree(2,5,3)", width = 5 ] ;
90 lmt_registerglyph [ category = "dirtree", private = "dirtree middle yes", code = "DirTree(3,5,3)", width = 5 ] ;
91 lmt_registerglyph [ category = "dirtree", private = "dirtree middle nop", code = "DirTree(5,5,3)", width = 5 ] ;
92 lmt_registerglyph [ category = "dirtree", private = "dirtree down yes" , code = "DirTree(6,2,3)", width = 2 ] ;
93 lmt_registerglyph [ category = "dirtree", private = "dirtree down nop" , code = "DirTree(0,2,3)", width = 2 ] ;
94 lmt_registerglyph [ category = "dirtree", private = "dirtree space yes" , code = "DirTree(0,1,3)", width = 1 ] ;
95 lmt_registerglyph [ category = "dirtree", private = "dirtree space nop" , code = "DirTree(0,1,3)", width = 1 ] ;
96
97\stopMPcalculation
98
99\definefontfeature
100 [default]
101 [default]
102 [metapost={category=dirtree,weight=2.0}]
103
104\definefontfeature
105 [none]
106 [none]
107 [metapost={category=dirtree,weight=2.0}]
108
109\startluacode
110 local gmatch = string.gmatch
111 local concat = table.concat
112 local insert = table.insert
113 local remove = table.remove
114 local sortedkeys = table.sortedkeys
115
116 local dirtree = utilities.dirtree or { }
117 utilities.dirtree = dirtree
118
119 local default = {
120 one = { " ", " " },
121 first = { " ", " " },
122 last = { " ", " " },
123 middle = { " ", " " },
124 down = { " ", " " },
125 space = { " ", " " },
126 }
127
128 local unicode = {
129 one = { "└─┬──", "└────" },
130 first = { "├─┬──", "├────" },
131 last = { "└─┬──", "└────" },
132 middle = { "├────", "├────" },
133 down = { "│ " , " " },
134 space = { " " , " " },
135 }
136
137 local simple = {
138 one = { " +", " +" },
139 first = { " +", " " },
140 last = { " +", " " },
141 middle = { " +", " " },
142 down = { " " , " " },
143 space = { " " , " " },
144 }
145
146 local private ; if buffers then
147
148 local ps = fonts.helpers.privateslot
149 local uc = utf.char
150
151 private = {
152 one = { uc(ps("dirtree one yes" )), uc(ps("dirtree one nop" )) },
153 first = { uc(ps("dirtree first yes" )), uc(ps("dirtree first nop" )) },
154 last = { uc(ps("dirtree last yes" )), uc(ps("dirtree last nop" )) },
155 middle = { uc(ps("dirtree middle yes")), uc(ps("dirtree middle nop")) },
156 down = { uc(ps("dirtree down yes" )), uc(ps("dirtree down nop" )) },
157 space = { uc(ps("dirtree space yes" )), uc(ps("dirtree space nop" )) },
158 }
159
160 end
161
162 dirtree.symbols = {
163 default = default,
164 unicode = unicode,
165 simple = simple,
166 private = private,
167 }
168
169
170
171
172 local nameonly, suffix = file.nameonly, file.suffix
173
174 dirtree.entries = {
175 default = function(str)
176 return str
177 end,
178 split = function(str)
179 return "\\dirtreeentry{" .. nameonly(str) .. "}{" .. suffix(str) .. "}"
180 end,
181 }
182
183 function dirtree.show(tree,symbolset,direntry)
184
185 if type(tree) == "string" then
186 tree = dir.glob(tree)
187 end
188
189 if type(tree) ~= "table" then
190 return
191 end
192
193 if not direntry then
194 direntry = "default"
195 end
196 direntry = dirtree.entries[direntry] or dirtree.entries.default
197
198 local result = { }
199 local output = { }
200
201 if not symbolset then
202 symbolset = "default"
203 end
204
205 local used = dirtree.symbols[symbolset] or dirtree.symbols.default
206
207 table.setmetatableindex(used,dirtree.symbols.default)
208
209 local yes_one = used.one [1] local nop_one = used.one [2]
210 local yes_first = used.first [1] local nop_first = used.first [2]
211 local yes_last = used.last [1] local nop_last = used.last [2]
212 local yes_else = used.middle[1] local nop_else = used.middle[2]
213 local yes_down = used.down [1] local nop_down = used.down [2]
214 local yes_space = used.space [1] local nop_space = used.space [2]
215
216 if #tree > 0 then
217 for i=1,#tree do
218 local d = false
219 local r = result
220 for s in gmatch(tree[i],"[^/]+") do
221 if d then
222 local rs = r[s]
223 if not rs then
224 rs = { }
225 r[s] = { }
226 end
227 r = rs
228 else
229 d = true
230 end
231 end
232 end
233 else
234
235 end
236
237 local level = 0
238 local con = { }
239
240 local function show(result,level)
241 local list = sortedkeys(result)
242 local size = #list
243 for i=1,size do
244 local l = list[i]
245 local r = result[l]
246 local sub = next(r)
247 if level == 1 then
248
249 elseif size == 1 then
250 insert(con,sub and yes_one or nop_one)
251 elseif i == 1 then
252 insert(con,sub and yes_first or nop_first)
253 elseif i == size then
254 insert(con,sub and yes_last or nop_last)
255 else
256 insert(con,sub and yes_else or nop_else)
257 end
258 if level == 1 then
259 output[#output+1] = direntry(l)
260 else
261 output[#output+1] = concat(con) .. (sub and yes_space or nop_space) .. direntry(l)
262 end
263 if sub then
264 if size == 1 then
265 con[#con] = nop_down
266 elseif i == size then
267 con[#con] = nop_down
268 else
269 con[#con] = yes_down
270 end
271 show(r,level+1)
272 end
273 if level > 1 then
274 remove(con)
275 end
276 end
277 end
278
279 show(result,1)
280
281 output = concat(output,"\r")
282
283 if buffers then
284 buffers.assign("dirtree",output)
285 end
286
287 return output
288
289 end
290
291\stopluacode
292
293
294
295
296
297
298
299
300
301
302
303
304
305\let\dirtreeentry\firstofoneargument
306
307\permanent\protected\def\showdirtree[#1]
308 {\begingroup
309 \ctxlua{utilities.dirtree.show("#1","private","split")}
310 \startlines
311 \getbuffer[dirtree]
312 \stoplines
313 \endgroup}
314
315\continueifinputfile{mdirtree.mkxl}
316
317\usemodule[articlebasic]
318
319\setuplayout[tight]
320
321\starttext
322
323 \definecolor[dirtree:lua] [darkred]
324 \definecolor[dirtree:lmt] [darkred]
325 \definecolor[dirtree:lfg] [darkblue]
326 \definecolor[dirtree:llg] [darkblue]
327
328
329
330
331 \protected\def\dirtreeentry#1#2
332 {\ifparameter#2\or
333 \color[dirtree:#2]{#1.#2}
334 \else
335 #1
336 \fi}
337
338 \startcolumns
339
340 \showdirtree[.**]
341 \stopcolumns
342
343 \startluacode
344
345 local list = dir.glob("./**")
346 local output = utilities.dirtree.show(list,"unicode","default")
347
348 inspect(output)
349 \stopluacode
350
351\stoptext
352 |