forked from babashka/babashka
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tree.clj
executable file
·77 lines (63 loc) · 2.02 KB
/
tree.clj
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/env bb
;; to run with clojure: clojure -Sdeps '{:deps {org.clojure/tools.cli {:mvn/version "0.4.2"}}}' examples/tree.clj src
;; to run with babashka: examples/tree.clj src
(ns tree
"Tree command, inspired by https://github.com/lambdaisland/birch."
(:require [clojure.java.io :as io]
[clojure.tools.cli :refer [parse-opts]]))
(def I-branch "│ ")
(def T-branch "├── ")
(def L-branch "└── ")
(def SPACER " ")
(defn file-tree
[^java.io.File path]
(let [children (.listFiles path)
dir? (.isDirectory path)]
(cond->
{:name (.getName path)
:type (if dir? "directory" "file")}
dir? (assoc :contents
(map file-tree children)))))
(defn render-tree
[{:keys [:name :contents]}]
(cons name
(mapcat
(fn [child index]
(let [subtree (render-tree child)
last? (= index (dec (count contents)))
prefix-first (if last? L-branch T-branch)
prefix-rest (if last? SPACER I-branch)]
(cons (str prefix-first (first subtree))
(map #(str prefix-rest %) (next subtree)))))
contents
(range))))
(defn stats
[file-tree]
(apply merge-with +
{:total 1
:directories (case (:type file-tree)
"directory" 1
0)}
(map stats (:contents file-tree))))
(def cli-options [["-E" "--edn" "Output tree as EDN"]])
(defn -main [& args]
(let [{:keys [options arguments]}
(parse-opts args cli-options)
path (io/file
(or (first arguments)
"."))
tree (file-tree path)
{:keys [total directories]}
(stats tree)]
(if (:edn options)
(prn tree)
(do
(doseq [l (render-tree tree)]
(println l))
(println)
(println
(str directories " directories, " (- total directories) " files"))))))
(apply -main *command-line-args*)
;;;; Scratch
(comment
(-main "src" "-e" "-c"))