summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Cargo.lock804
-rw-r--r--Cargo.toml6
-rw-r--r--flake.lock87
-rw-r--r--flake.nix68
-rw-r--r--tree-viz/.gitignore1
-rw-r--r--tree-viz/Cargo.toml19
-rw-r--r--tree-viz/src/app.rs230
-rw-r--r--tree-viz/src/config.rs24
-rw-r--r--tree-viz/src/main.rs96
10 files changed, 1339 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fcdcb15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
1target
2scope-viz
3.direnv
4test-files
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..338a791
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,804 @@
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
3version = 3
4
5[[package]]
6name = "ahash"
7version = "0.4.7"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
10
11[[package]]
12name = "aho-corasick"
13version = "0.7.19"
14source = "registry+https://github.com/rust-lang/crates.io-index"
15checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
16dependencies = [
17 "memchr",
18]
19
20[[package]]
21name = "ansi_term"
22version = "0.12.1"
23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
25dependencies = [
26 "winapi",
27]
28
29[[package]]
30name = "anyhow"
31version = "1.0.65"
32source = "registry+https://github.com/rust-lang/crates.io-index"
33checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
34
35[[package]]
36name = "autocfg"
37version = "1.1.0"
38source = "registry+https://github.com/rust-lang/crates.io-index"
39checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
40
41[[package]]
42name = "bitflags"
43version = "1.3.2"
44source = "registry+https://github.com/rust-lang/crates.io-index"
45checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
46
47[[package]]
48name = "bitvec"
49version = "0.22.3"
50source = "registry+https://github.com/rust-lang/crates.io-index"
51checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
52dependencies = [
53 "funty",
54 "radium",
55 "tap",
56 "wyz",
57]
58
59[[package]]
60name = "byteorder"
61version = "1.4.3"
62source = "registry+https://github.com/rust-lang/crates.io-index"
63checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
64
65[[package]]
66name = "cc"
67version = "1.0.73"
68source = "registry+https://github.com/rust-lang/crates.io-index"
69checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
70
71[[package]]
72name = "cfg-if"
73version = "1.0.0"
74source = "registry+https://github.com/rust-lang/crates.io-index"
75checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
76
77[[package]]
78name = "console"
79version = "0.15.1"
80source = "registry+https://github.com/rust-lang/crates.io-index"
81checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847"
82dependencies = [
83 "encode_unicode",
84 "libc",
85 "once_cell",
86 "terminal_size",
87 "unicode-width",
88 "winapi",
89]
90
91[[package]]
92name = "controlled-option"
93version = "0.4.1"
94source = "registry+https://github.com/rust-lang/crates.io-index"
95checksum = "95abc95db25411571f40a8b0af30a3c386f3927fe6f1460c70e1f49f01bac3ac"
96dependencies = [
97 "controlled-option-macros",
98]
99
100[[package]]
101name = "controlled-option-macros"
102version = "0.2.2"
103source = "registry+https://github.com/rust-lang/crates.io-index"
104checksum = "305024255a6c456333e130da2559b7aedd5c2e15388f51dae69f7507517cfbfb"
105dependencies = [
106 "proc-macro2",
107 "quote",
108 "syn",
109]
110
111[[package]]
112name = "dirs"
113version = "3.0.2"
114source = "registry+https://github.com/rust-lang/crates.io-index"
115checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"
116dependencies = [
117 "dirs-sys",
118]
119
120[[package]]
121name = "dirs-sys"
122version = "0.3.7"
123source = "registry+https://github.com/rust-lang/crates.io-index"
124checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
125dependencies = [
126 "libc",
127 "redox_users",
128 "winapi",
129]
130
131[[package]]
132name = "either"
133version = "1.8.0"
134source = "registry+https://github.com/rust-lang/crates.io-index"
135checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
136
137[[package]]
138name = "encode_unicode"
139version = "0.3.6"
140source = "registry+https://github.com/rust-lang/crates.io-index"
141checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
142
143[[package]]
144name = "filetime"
145version = "0.2.17"
146source = "registry+https://github.com/rust-lang/crates.io-index"
147checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c"
148dependencies = [
149 "cfg-if",
150 "libc",
151 "redox_syscall",
152 "windows-sys",
153]
154
155[[package]]
156name = "funty"
157version = "1.2.0"
158source = "registry+https://github.com/rust-lang/crates.io-index"
159checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
160
161[[package]]
162name = "fxhash"
163version = "0.2.1"
164source = "registry+https://github.com/rust-lang/crates.io-index"
165checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
166dependencies = [
167 "byteorder",
168]
169
170[[package]]
171name = "getrandom"
172version = "0.2.7"
173source = "registry+https://github.com/rust-lang/crates.io-index"
174checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
175dependencies = [
176 "cfg-if",
177 "libc",
178 "wasi",
179]
180
181[[package]]
182name = "hashbrown"
183version = "0.9.1"
184source = "registry+https://github.com/rust-lang/crates.io-index"
185checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
186dependencies = [
187 "ahash",
188]
189
190[[package]]
191name = "hashbrown"
192version = "0.12.3"
193source = "registry+https://github.com/rust-lang/crates.io-index"
194checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
195
196[[package]]
197name = "indexmap"
198version = "1.9.1"
199source = "registry+https://github.com/rust-lang/crates.io-index"
200checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
201dependencies = [
202 "autocfg",
203 "hashbrown 0.12.3",
204]
205
206[[package]]
207name = "inotify"
208version = "0.9.6"
209source = "registry+https://github.com/rust-lang/crates.io-index"
210checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
211dependencies = [
212 "bitflags",
213 "inotify-sys",
214 "libc",
215]
216
217[[package]]
218name = "inotify-sys"
219version = "0.1.5"
220source = "registry+https://github.com/rust-lang/crates.io-index"
221checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
222dependencies = [
223 "libc",
224]
225
226[[package]]
227name = "itertools"
228version = "0.10.4"
229source = "registry+https://github.com/rust-lang/crates.io-index"
230checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0"
231dependencies = [
232 "either",
233]
234
235[[package]]
236name = "itoa"
237version = "1.0.3"
238source = "registry+https://github.com/rust-lang/crates.io-index"
239checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
240
241[[package]]
242name = "kqueue"
243version = "1.0.6"
244source = "registry+https://github.com/rust-lang/crates.io-index"
245checksum = "4d6112e8f37b59803ac47a42d14f1f3a59bbf72fc6857ffc5be455e28a691f8e"
246dependencies = [
247 "kqueue-sys",
248 "libc",
249]
250
251[[package]]
252name = "kqueue-sys"
253version = "1.0.3"
254source = "registry+https://github.com/rust-lang/crates.io-index"
255checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
256dependencies = [
257 "bitflags",
258 "libc",
259]
260
261[[package]]
262name = "lazy_static"
263version = "1.4.0"
264source = "registry+https://github.com/rust-lang/crates.io-index"
265checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
266
267[[package]]
268name = "libc"
269version = "0.2.132"
270source = "registry+https://github.com/rust-lang/crates.io-index"
271checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
272
273[[package]]
274name = "libloading"
275version = "0.7.3"
276source = "registry+https://github.com/rust-lang/crates.io-index"
277checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
278dependencies = [
279 "cfg-if",
280 "winapi",
281]
282
283[[package]]
284name = "log"
285version = "0.4.17"
286source = "registry+https://github.com/rust-lang/crates.io-index"
287checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
288dependencies = [
289 "cfg-if",
290]
291
292[[package]]
293name = "lsp-positions"
294version = "0.3.1"
295source = "registry+https://github.com/rust-lang/crates.io-index"
296checksum = "6ce95baee2c4668ed42b67ae7f931abe06169fcef8e853815ffaf53b56ac7f0c"
297dependencies = [
298 "memchr",
299 "tree-sitter",
300 "unicode-segmentation",
301]
302
303[[package]]
304name = "memchr"
305version = "2.5.0"
306source = "registry+https://github.com/rust-lang/crates.io-index"
307checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
308
309[[package]]
310name = "mio"
311version = "0.8.4"
312source = "registry+https://github.com/rust-lang/crates.io-index"
313checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
314dependencies = [
315 "libc",
316 "log",
317 "wasi",
318 "windows-sys",
319]
320
321[[package]]
322name = "notify"
323version = "5.0.0"
324source = "registry+https://github.com/rust-lang/crates.io-index"
325checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a"
326dependencies = [
327 "bitflags",
328 "filetime",
329 "inotify",
330 "kqueue",
331 "libc",
332 "mio",
333 "walkdir",
334 "winapi",
335]
336
337[[package]]
338name = "once_cell"
339version = "1.14.0"
340source = "registry+https://github.com/rust-lang/crates.io-index"
341checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
342
343[[package]]
344name = "proc-macro2"
345version = "1.0.43"
346source = "registry+https://github.com/rust-lang/crates.io-index"
347checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
348dependencies = [
349 "unicode-ident",
350]
351
352[[package]]
353name = "quote"
354version = "1.0.21"
355source = "registry+https://github.com/rust-lang/crates.io-index"
356checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
357dependencies = [
358 "proc-macro2",
359]
360
361[[package]]
362name = "radium"
363version = "0.6.2"
364source = "registry+https://github.com/rust-lang/crates.io-index"
365checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
366
367[[package]]
368name = "redox_syscall"
369version = "0.2.16"
370source = "registry+https://github.com/rust-lang/crates.io-index"
371checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
372dependencies = [
373 "bitflags",
374]
375
376[[package]]
377name = "redox_users"
378version = "0.4.3"
379source = "registry+https://github.com/rust-lang/crates.io-index"
380checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
381dependencies = [
382 "getrandom",
383 "redox_syscall",
384 "thiserror",
385]
386
387[[package]]
388name = "regex"
389version = "1.6.0"
390source = "registry+https://github.com/rust-lang/crates.io-index"
391checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
392dependencies = [
393 "aho-corasick",
394 "memchr",
395 "regex-syntax",
396]
397
398[[package]]
399name = "regex-syntax"
400version = "0.6.27"
401source = "registry+https://github.com/rust-lang/crates.io-index"
402checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
403
404[[package]]
405name = "ryu"
406version = "1.0.11"
407source = "registry+https://github.com/rust-lang/crates.io-index"
408checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
409
410[[package]]
411name = "same-file"
412version = "1.0.6"
413source = "registry+https://github.com/rust-lang/crates.io-index"
414checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
415dependencies = [
416 "winapi-util",
417]
418
419[[package]]
420name = "scope-viz"
421version = "0.1.0"
422dependencies = [
423 "stack-graphs",
424 "tree-sitter",
425 "tree-sitter-elm",
426 "tree-sitter-graph",
427 "tree-sitter-rust",
428 "tree-sitter-stack-graphs",
429]
430
431[[package]]
432name = "serde"
433version = "1.0.144"
434source = "registry+https://github.com/rust-lang/crates.io-index"
435checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
436dependencies = [
437 "serde_derive",
438]
439
440[[package]]
441name = "serde_derive"
442version = "1.0.144"
443source = "registry+https://github.com/rust-lang/crates.io-index"
444checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
445dependencies = [
446 "proc-macro2",
447 "quote",
448 "syn",
449]
450
451[[package]]
452name = "serde_json"
453version = "1.0.85"
454source = "registry+https://github.com/rust-lang/crates.io-index"
455checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
456dependencies = [
457 "indexmap",
458 "itoa",
459 "ryu",
460 "serde",
461]
462
463[[package]]
464name = "smallvec"
465version = "1.9.0"
466source = "registry+https://github.com/rust-lang/crates.io-index"
467checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
468
469[[package]]
470name = "stack-graphs"
471version = "0.10.1"
472source = "registry+https://github.com/rust-lang/crates.io-index"
473checksum = "9c4fdc37ccc4f64bea4bc3ffa3f94be605342e7e8b9b928e203bbd4bfd313949"
474dependencies = [
475 "bitvec",
476 "controlled-option",
477 "either",
478 "fxhash",
479 "itertools",
480 "libc",
481 "lsp-positions",
482 "serde",
483 "serde_json",
484 "smallvec",
485 "thiserror",
486]
487
488[[package]]
489name = "string-interner"
490version = "0.12.2"
491source = "registry+https://github.com/rust-lang/crates.io-index"
492checksum = "383196d1876517ee6f9f0864d1fc1070331b803335d3c6daaa04bbcccd823c08"
493dependencies = [
494 "cfg-if",
495 "hashbrown 0.9.1",
496]
497
498[[package]]
499name = "syn"
500version = "1.0.100"
501source = "registry+https://github.com/rust-lang/crates.io-index"
502checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
503dependencies = [
504 "proc-macro2",
505 "quote",
506 "unicode-ident",
507]
508
509[[package]]
510name = "tap"
511version = "1.0.1"
512source = "registry+https://github.com/rust-lang/crates.io-index"
513checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
514
515[[package]]
516name = "terminal_size"
517version = "0.1.17"
518source = "registry+https://github.com/rust-lang/crates.io-index"
519checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
520dependencies = [
521 "libc",
522 "winapi",
523]
524
525[[package]]
526name = "thiserror"
527version = "1.0.35"
528source = "registry+https://github.com/rust-lang/crates.io-index"
529checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85"
530dependencies = [
531 "thiserror-impl",
532]
533
534[[package]]
535name = "thiserror-impl"
536version = "1.0.35"
537source = "registry+https://github.com/rust-lang/crates.io-index"
538checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783"
539dependencies = [
540 "proc-macro2",
541 "quote",
542 "syn",
543]
544
545[[package]]
546name = "tree-sitter"
547version = "0.20.9"
548source = "registry+https://github.com/rust-lang/crates.io-index"
549checksum = "d4423c784fe11398ca91e505cdc71356b07b1a924fc8735cfab5333afe3e18bc"
550dependencies = [
551 "cc",
552 "regex",
553]
554
555[[package]]
556name = "tree-sitter-elm"
557version = "5.6.3"
558source = "registry+https://github.com/rust-lang/crates.io-index"
559checksum = "22b9408ad250aa27774132baf20c4f107faad16841aa45568c6900a27895093b"
560dependencies = [
561 "cc",
562 "tree-sitter",
563]
564
565[[package]]
566name = "tree-sitter-go"
567version = "0.19.1"
568source = "registry+https://github.com/rust-lang/crates.io-index"
569checksum = "71967701c8214be4aa77e0260e98361e6fd71ceec1d9d03abb37a22c9f60d0ff"
570dependencies = [
571 "cc",
572 "tree-sitter",
573]
574
575[[package]]
576name = "tree-sitter-graph"
577version = "0.6.1"
578source = "registry+https://github.com/rust-lang/crates.io-index"
579checksum = "18a4875525d5bbb4a27716eac5469f91370b2acb985c6a984c359abb19732e02"
580dependencies = [
581 "ansi_term",
582 "log",
583 "regex",
584 "serde",
585 "serde_json",
586 "smallvec",
587 "string-interner",
588 "thiserror",
589 "tree-sitter",
590]
591
592[[package]]
593name = "tree-sitter-highlight"
594version = "0.20.1"
595source = "registry+https://github.com/rust-lang/crates.io-index"
596checksum = "042342584c5a7a0b833d9fc4e2bdab3f9868ddc6c4b339a1e01451c6720868bc"
597dependencies = [
598 "regex",
599 "thiserror",
600 "tree-sitter",
601]
602
603[[package]]
604name = "tree-sitter-loader"
605version = "0.20.0"
606source = "registry+https://github.com/rust-lang/crates.io-index"
607checksum = "d0b17eef4833c7c139abed66d562dfa23228e97e647597baf246fd56c21bbfaf"
608dependencies = [
609 "anyhow",
610 "cc",
611 "dirs",
612 "libloading",
613 "once_cell",
614 "regex",
615 "serde",
616 "serde_json",
617 "tree-sitter",
618 "tree-sitter-highlight",
619 "tree-sitter-tags",
620]
621
622[[package]]
623name = "tree-sitter-rust"
624version = "0.20.1"
625source = "registry+https://github.com/rust-lang/crates.io-index"
626checksum = "13470fafb7327a3acf96f5bc1013b5539a899a182f01c59b5af53f6b93195717"
627dependencies = [
628 "cc",
629 "tree-sitter",
630]
631
632[[package]]
633name = "tree-sitter-stack-graphs"
634version = "0.3.1"
635source = "registry+https://github.com/rust-lang/crates.io-index"
636checksum = "510004b313ced434bf04faa5d8e6e12e7cd80bb34231c6b132b0284966244f25"
637dependencies = [
638 "anyhow",
639 "controlled-option",
640 "itertools",
641 "lazy_static",
642 "log",
643 "lsp-positions",
644 "regex",
645 "stack-graphs",
646 "thiserror",
647 "tree-sitter",
648 "tree-sitter-graph",
649 "tree-sitter-loader",
650]
651
652[[package]]
653name = "tree-sitter-tags"
654version = "0.20.2"
655source = "registry+https://github.com/rust-lang/crates.io-index"
656checksum = "ccb3f1376219530a37a809751ecf65aa35fd8b9c1c4ab6d4faf5f6a9eeda2c05"
657dependencies = [
658 "memchr",
659 "regex",
660 "thiserror",
661 "tree-sitter",
662]
663
664[[package]]
665name = "tree-sitter-typescript"
666version = "0.20.1"
667source = "registry+https://github.com/rust-lang/crates.io-index"
668checksum = "4e8ed0ecb931cdff13c6a13f45ccd615156e2779d9ffb0395864e05505e6e86d"
669dependencies = [
670 "cc",
671 "tree-sitter",
672]
673
674[[package]]
675name = "tree-viz"
676version = "0.1.0"
677dependencies = [
678 "console",
679 "notify",
680 "once_cell",
681 "tree-sitter",
682 "tree-sitter-elm",
683 "tree-sitter-go",
684 "tree-sitter-rust",
685 "tree-sitter-typescript",
686]
687
688[[package]]
689name = "unicode-ident"
690version = "1.0.4"
691source = "registry+https://github.com/rust-lang/crates.io-index"
692checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
693
694[[package]]
695name = "unicode-segmentation"
696version = "1.10.0"
697source = "registry+https://github.com/rust-lang/crates.io-index"
698checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
699
700[[package]]
701name = "unicode-width"
702version = "0.1.10"
703source = "registry+https://github.com/rust-lang/crates.io-index"
704checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
705
706[[package]]
707name = "walkdir"
708version = "2.3.2"
709source = "registry+https://github.com/rust-lang/crates.io-index"
710checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
711dependencies = [
712 "same-file",
713 "winapi",
714 "winapi-util",
715]
716
717[[package]]
718name = "wasi"
719version = "0.11.0+wasi-snapshot-preview1"
720source = "registry+https://github.com/rust-lang/crates.io-index"
721checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
722
723[[package]]
724name = "winapi"
725version = "0.3.9"
726source = "registry+https://github.com/rust-lang/crates.io-index"
727checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
728dependencies = [
729 "winapi-i686-pc-windows-gnu",
730 "winapi-x86_64-pc-windows-gnu",
731]
732
733[[package]]
734name = "winapi-i686-pc-windows-gnu"
735version = "0.4.0"
736source = "registry+https://github.com/rust-lang/crates.io-index"
737checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
738
739[[package]]
740name = "winapi-util"
741version = "0.1.5"
742source = "registry+https://github.com/rust-lang/crates.io-index"
743checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
744dependencies = [
745 "winapi",
746]
747
748[[package]]
749name = "winapi-x86_64-pc-windows-gnu"
750version = "0.4.0"
751source = "registry+https://github.com/rust-lang/crates.io-index"
752checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
753
754[[package]]
755name = "windows-sys"
756version = "0.36.1"
757source = "registry+https://github.com/rust-lang/crates.io-index"
758checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
759dependencies = [
760 "windows_aarch64_msvc",
761 "windows_i686_gnu",
762 "windows_i686_msvc",
763 "windows_x86_64_gnu",
764 "windows_x86_64_msvc",
765]
766
767[[package]]
768name = "windows_aarch64_msvc"
769version = "0.36.1"
770source = "registry+https://github.com/rust-lang/crates.io-index"
771checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
772
773[[package]]
774name = "windows_i686_gnu"
775version = "0.36.1"
776source = "registry+https://github.com/rust-lang/crates.io-index"
777checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
778
779[[package]]
780name = "windows_i686_msvc"
781version = "0.36.1"
782source = "registry+https://github.com/rust-lang/crates.io-index"
783checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
784
785[[package]]
786name = "windows_x86_64_gnu"
787version = "0.36.1"
788source = "registry+https://github.com/rust-lang/crates.io-index"
789checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
790
791[[package]]
792name = "windows_x86_64_msvc"
793version = "0.36.1"
794source = "registry+https://github.com/rust-lang/crates.io-index"
795checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
796
797[[package]]
798name = "wyz"
799version = "0.4.0"
800source = "registry+https://github.com/rust-lang/crates.io-index"
801checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188"
802dependencies = [
803 "tap",
804]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..b7d2e20
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
1[workspace]
2
3members = [
4 "scope-viz",
5 "tree-viz"
6]
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..a7c083f
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,87 @@
1{
2 "nodes": {
3 "fenix": {
4 "inputs": {
5 "nixpkgs": [
6 "nixpkgs"
7 ],
8 "rust-analyzer-src": "rust-analyzer-src"
9 },
10 "locked": {
11 "lastModified": 1645251813,
12 "narHash": "sha256-cQ66tGjnZclBCS3nD26mZ5fUH+3/HnysGffBiWXUSHk=",
13 "owner": "nix-community",
14 "repo": "fenix",
15 "rev": "9892337b588c38ec59466a1c89befce464aae7f8",
16 "type": "github"
17 },
18 "original": {
19 "owner": "nix-community",
20 "repo": "fenix",
21 "type": "github"
22 }
23 },
24 "gitignore": {
25 "inputs": {
26 "nixpkgs": [
27 "nixpkgs"
28 ]
29 },
30 "locked": {
31 "lastModified": 1635165013,
32 "narHash": "sha256-o/BdVjNwcB6jOmzZjOH703BesSkkS5O7ej3xhyO8hAY=",
33 "owner": "hercules-ci",
34 "repo": "gitignore.nix",
35 "rev": "5b9e0ff9d3b551234b4f3eb3983744fa354b17f1",
36 "type": "github"
37 },
38 "original": {
39 "owner": "hercules-ci",
40 "repo": "gitignore.nix",
41 "type": "github"
42 }
43 },
44 "nixpkgs": {
45 "locked": {
46 "lastModified": 1645013224,
47 "narHash": "sha256-b7OEC8vwzJv3rsz9pwnTX2LQDkeOWz2DbKypkVvNHXc=",
48 "owner": "nixos",
49 "repo": "nixpkgs",
50 "rev": "b66b39216b1fef2d8c33cc7a5c72d8da80b79970",
51 "type": "github"
52 },
53 "original": {
54 "owner": "nixos",
55 "ref": "nixpkgs-unstable",
56 "repo": "nixpkgs",
57 "type": "github"
58 }
59 },
60 "root": {
61 "inputs": {
62 "fenix": "fenix",
63 "gitignore": "gitignore",
64 "nixpkgs": "nixpkgs"
65 }
66 },
67 "rust-analyzer-src": {
68 "flake": false,
69 "locked": {
70 "lastModified": 1645205556,
71 "narHash": "sha256-e4lZW3qRyOEJ+vLKFQP7m2Dxh5P44NrnekZYLxlucww=",
72 "owner": "rust-analyzer",
73 "repo": "rust-analyzer",
74 "rev": "acf5874b39f3dc5262317a6074d9fc7285081161",
75 "type": "github"
76 },
77 "original": {
78 "owner": "rust-analyzer",
79 "ref": "nightly",
80 "repo": "rust-analyzer",
81 "type": "github"
82 }
83 }
84 },
85 "root": "root",
86 "version": 7
87}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..861792b
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,68 @@
1{
2 inputs = {
3
4 nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
5
6 fenix = {
7 url = "github:nix-community/fenix";
8 inputs.nixpkgs.follows = "nixpkgs";
9 };
10
11 gitignore = {
12 url = "github:hercules-ci/gitignore.nix";
13 inputs.nixpkgs.follows = "nixpkgs";
14 };
15
16 };
17
18 outputs =
19 { self
20 , nixpkgs
21 , fenix
22 , gitignore
23 }:
24 let
25 inherit (gitignore.lib) gitignoreSource;
26
27 supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
28 forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
29 nixpkgsFor = forAllSystems (system:
30 import nixpkgs { inherit system; });
31
32 chanspec = {
33 date = "2022-09-01";
34 channel = "nightly";
35 sha256 = "tS2IHsewoaEMHn9x8DfcEJefShcW85iDrfBWXOZJa9c="; # set zeros after modifying channel or date
36 };
37 rustChannel = p: (fenix.overlay p p).fenix.toolchainOf chanspec;
38
39 in
40 {
41
42
43 devShell = forAllSystems (system:
44 let
45 pkgs = nixpkgsFor."${system}";
46 toolchain = (rustChannel pkgs).withComponents [
47 "rustc"
48 "cargo"
49 "rust-std"
50 "rustfmt"
51 "clippy"
52 "rust-src"
53 ];
54 inherit (fenix.packages."${system}") rust-analyzer;
55 in
56 pkgs.mkShell {
57 nativeBuildInputs = [
58 pkgs.cargo-watch
59 pkgs.bacon
60 pkgs.cargo-insta
61 rust-analyzer
62 toolchain
63 ];
64 RUST_LOG = "info";
65 RUST_BACKTRACE = 1;
66 });
67 };
68}
diff --git a/tree-viz/.gitignore b/tree-viz/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/tree-viz/.gitignore
@@ -0,0 +1 @@
/target
diff --git a/tree-viz/Cargo.toml b/tree-viz/Cargo.toml
new file mode 100644
index 0000000..04107d3
--- /dev/null
+++ b/tree-viz/Cargo.toml
@@ -0,0 +1,19 @@
1[package]
2name = "tree-viz"
3version = "0.1.0"
4edition = "2021"
5
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
8[dependencies]
9tree-sitter-elm = "5.6.3"
10tree-sitter-rust = "0.20.1"
11tree-sitter = "^0.20.8"
12console = "^0.15"
13once_cell = "1.14.0"
14tree-sitter-go = "0.19.1"
15tree-sitter-typescript = "0.20.1"
16
17[dependencies.notify]
18version = "5.0.0"
19default-features = false
diff --git a/tree-viz/src/app.rs b/tree-viz/src/app.rs
new file mode 100644
index 0000000..68d3641
--- /dev/null
+++ b/tree-viz/src/app.rs
@@ -0,0 +1,230 @@
1use crate::{config::Config, LANGUAGE};
2
3use std::{
4 collections::HashMap,
5 fmt::Write,
6 path::{Path, PathBuf},
7};
8
9use console::{style, Style, Term};
10use tree_sitter::{Node, Parser, Query, QueryCursor, Range, Tree};
11
12pub struct App {
13 config: Config,
14 path: PathBuf,
15 query: Option<Query>,
16 query_path: Option<PathBuf>,
17 src: Vec<u8>,
18 tree: Tree,
19}
20
21impl App {
22 pub fn new<'a, P: AsRef<Path>>(src: &'a [u8], path: P, query_path: Option<P>) -> Self {
23 let path = path.as_ref().to_owned();
24
25 let mut parser = Parser::new();
26 parser.set_language(*LANGUAGE).unwrap();
27
28 let tree = parser.parse(&src, None).unwrap();
29 let query_path = query_path.map(|q| q.as_ref().to_owned());
30 let query = query_path.as_ref().map(|p| {
31 let query_src = std::fs::read_to_string(&p).expect("unable to read query");
32 Query::new(*LANGUAGE, &query_src).expect("query parse error")
33 });
34
35 Self {
36 config: Default::default(),
37 path,
38 query,
39 query_path,
40 src: src.to_owned(),
41 tree,
42 }
43 }
44
45 pub fn draw(&self) {
46 let term = Term::stdout();
47 term.clear_screen().unwrap();
48 let mut done = false;
49 let mut depth = 0;
50 let mut in_capture: Option<Range> = None;
51 let mut cursor = self.tree.walk();
52
53 let capture_names = self
54 .query
55 .as_ref()
56 .map(|q| q.capture_names())
57 .unwrap_or_default();
58 let capture_map = self
59 .query
60 .as_ref()
61 .map(|query| {
62 QueryCursor::new()
63 .matches(&query, self.tree.root_node(), self.src.as_slice())
64 .flat_map(|match_| match_.captures)
65 .fold(
66 HashMap::new(),
67 |mut map: HashMap<Node, Vec<u32>>, capture| {
68 map.entry(capture.node)
69 .and_modify(|idxs| idxs.push(capture.index))
70 .or_insert_with(|| vec![capture.index]);
71 map
72 },
73 )
74 })
75 .unwrap_or_default();
76
77 while !done {
78 let node = cursor.node();
79 let mut tree_string = String::new();
80 in_capture = match in_capture {
81 Some(range)
82 if !contains(&range, &node.range()) && capture_map.contains_key(&node) =>
83 {
84 Some(node.range())
85 }
86 Some(range) if !contains(&range, &node.range()) => None,
87 None if capture_map.contains_key(&node) => Some(node.range()),
88 i => i,
89 };
90
91 write!(
92 tree_string,
93 "{}",
94 (if in_capture.is_some() {
95 Style::new().on_yellow().on_bright()
96 } else {
97 Style::new()
98 })
99 .bright()
100 .black()
101 .apply_to(
102 format!("{}{}", "|", " ".repeat(self.config.indent_level))
103 .repeat(depth as usize)
104 )
105 )
106 .unwrap();
107
108 write!(
109 tree_string,
110 "{} ",
111 if node.is_error() {
112 Style::new().red()
113 } else if in_capture.is_some() {
114 Style::new().on_yellow().on_bright()
115 } else {
116 Style::new()
117 }
118 .apply_to(node.kind()),
119 )
120 .unwrap();
121
122 if let Some(idxs) = capture_map.get(&node) {
123 for index in idxs {
124 write!(
125 tree_string,
126 "@{} ",
127 style(capture_names[*index as usize].as_str()).magenta()
128 )
129 .unwrap();
130 }
131 }
132
133 if self.config.show_ranges {
134 let range = node.range();
135 write!(
136 tree_string,
137 " {}",
138 style(format!("{:?}..{:?}", range.start_byte, range.end_byte,))
139 .bright()
140 .black()
141 )
142 .unwrap();
143 }
144
145 if self.config.show_src {
146 write!(
147 tree_string,
148 " {:.?}",
149 style(node.utf8_text(&self.src).unwrap()).cyan()
150 )
151 .unwrap();
152 }
153
154 term.write_line(&tree_string).unwrap();
155 term.clear_to_end_of_screen().unwrap();
156
157 if cursor.goto_first_child() {
158 depth += 1;
159 continue;
160 }
161 if cursor.goto_next_sibling() {
162 continue;
163 }
164
165 loop {
166 if !cursor.goto_parent() {
167 done = true;
168 break;
169 } else {
170 depth -= 1;
171 }
172
173 if cursor.goto_next_sibling() {
174 break;
175 }
176 }
177 }
178
179 // see https://github.com/console-rs/console/issues/36#issuecomment-624731432
180 // for the reasoning behing this hackjob
181
182 term.write_line("\n(>) increase indent").unwrap();
183 term.clear_to_end_of_screen().unwrap();
184
185 term.write_line("(<) decrease indent ").unwrap();
186 term.clear_to_end_of_screen().unwrap();
187
188 term.write_line("(n) toggle ranges").unwrap();
189 term.clear_to_end_of_screen().unwrap();
190
191 term.write_line("(s) toggle source text").unwrap();
192 term.clear_to_end_of_screen().unwrap();
193
194 term.write_line("(r) reload from disk").unwrap();
195 term.clear_to_end_of_screen().unwrap();
196
197 term.write_line("(C-c) quit").unwrap();
198 term.clear_to_end_of_screen().unwrap();
199 }
200
201 pub fn increase_indent(&mut self) {
202 self.config.indent_level = self.config.indent_level.saturating_add(1);
203 }
204
205 pub fn decrease_indent(&mut self) {
206 self.config.indent_level = self.config.indent_level.saturating_sub(1);
207 }
208
209 pub fn toggle_ranges(&mut self) {
210 self.config.show_ranges = !self.config.show_ranges;
211 }
212
213 pub fn toggle_source(&mut self) {
214 self.config.show_src = !self.config.show_src;
215 }
216
217 pub fn reload(&mut self) {
218 let src = std::fs::read_to_string(&self.path).unwrap();
219 let new = Self::new(src.as_bytes(), &self.path, self.query_path.as_ref());
220 *self = Self {
221 config: self.config,
222 ..new
223 };
224 }
225}
226
227// does a encompass b
228fn contains(a: &Range, b: &Range) -> bool {
229 a.start_byte <= b.start_byte && a.end_byte >= b.end_byte
230}
diff --git a/tree-viz/src/config.rs b/tree-viz/src/config.rs
new file mode 100644
index 0000000..6f34291
--- /dev/null
+++ b/tree-viz/src/config.rs
@@ -0,0 +1,24 @@
1use std::default::Default;
2
3#[derive(Clone, Copy)]
4pub struct Config {
5 pub indent_level: usize,
6 pub show_ranges: bool,
7 pub show_src: bool,
8}
9
10impl Default for Config {
11 fn default() -> Self {
12 Config::new()
13 }
14}
15
16impl Config {
17 fn new() -> Self {
18 Self {
19 indent_level: 2,
20 show_ranges: true,
21 show_src: true,
22 }
23 }
24}
diff --git a/tree-viz/src/main.rs b/tree-viz/src/main.rs
new file mode 100644
index 0000000..79964cb
--- /dev/null
+++ b/tree-viz/src/main.rs
@@ -0,0 +1,96 @@
1mod app;
2mod config;
3
4use std::{
5 env, fs,
6 path::Path,
7 sync::{mpsc, Arc, RwLock},
8 thread,
9 time::Duration,
10};
11
12use app::App;
13use console::{Key, Term};
14use notify::{Event as WatchEvent, EventKind as WatchEventKind, RecursiveMode, Watcher};
15use once_cell::sync::Lazy;
16use tree_sitter::Language;
17
18//pub static LANGUAGE: Lazy<Language> = Lazy::new(tree_sitter_rust::language);
19pub static LANGUAGE: Lazy<Language> = Lazy::new(tree_sitter_typescript::language_typescript);
20
21fn main() {
22 let mut args = env::args();
23 let _ = args.next();
24
25 let path = args.next().expect("no arg passed");
26 let query_path = args.next();
27 let src = fs::read_to_string(&path).expect("unable to read file");
28
29 let app = Arc::new(RwLock::new(App::new(
30 src.as_bytes(),
31 &path,
32 query_path.as_ref(),
33 )));
34
35 let watch_fn = |watcher_app: Arc<RwLock<App>>| {
36 move |ev| {
37 if let Ok(WatchEvent {
38 kind: WatchEventKind::Modify(..),
39 ..
40 }) = ev
41 {
42 if let Ok(mut locked) = watcher_app.try_write() {
43 locked.reload();
44 locked.draw();
45 };
46 }
47 }
48 };
49
50 let mut watcher1 = notify::recommended_watcher(watch_fn(Arc::clone(&app))).unwrap();
51 watcher1
52 .watch(Path::new(&path), RecursiveMode::NonRecursive)
53 .unwrap();
54
55 let mut watcher2 = notify::recommended_watcher(watch_fn(Arc::clone(&app))).unwrap();
56 if let Some(query_path) = query_path {
57 watcher2
58 .watch(Path::new(&query_path), RecursiveMode::NonRecursive)
59 .unwrap();
60 }
61
62 let (tx, rx) = mpsc::channel();
63 let tx0 = tx.clone();
64 thread::spawn(move || {
65 let term = Term::stdout();
66 loop {
67 if let Ok(Key::Char(ev)) = term.read_key() {
68 tx0.send(ev).unwrap();
69 }
70 }
71 });
72
73 if let Ok(locked) = app.try_read() {
74 locked.draw();
75 }
76
77 loop {
78 match rx.try_recv() {
79 Ok(ev) => {
80 if let Ok(mut locked) = app.try_write() {
81 match ev {
82 '>' => locked.increase_indent(),
83 '<' => locked.decrease_indent(),
84 'n' => locked.toggle_ranges(),
85 's' => locked.toggle_source(),
86 'r' => locked.reload(),
87 _ => (),
88 }
89 locked.draw();
90 }
91 }
92 _ => (),
93 }
94 thread::sleep(Duration::from_millis(10));
95 }
96}