Created
March 24, 2025 08:27
-
-
Save esshka/233b8ab03496e5063b720c330373514d to your computer and use it in GitHub Desktop.
Clear, hierarchical representation of both the file structure and namespaces
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns tree-generator | |
(:require [clojure.java.io :as io] | |
[clojure.string :as str])) | |
(defn relative-path | |
"Computes the relative path of a file with respect to a base directory." | |
[base file] | |
(let [base-path (.getCanonicalPath base) | |
file-path (.getCanonicalPath file) | |
prefix (str base-path "/")] | |
(if (.startsWith file-path prefix) | |
(.substring file-path (.length prefix)) | |
(throw (Exception. "File not under base directory"))))) | |
(defn path-to-namespace | |
"Converts a relative file path to a Clojure namespace by replacing underscores with hyphens | |
and slashes with dots, and removing the .clj extension." | |
[rel-path] | |
(let [segments (str/split rel-path #"/") | |
ns-segments (vec (map #(str/replace % "_" "-") segments)) | |
ns-segments (update ns-segments (dec (count ns-segments)) #(subs % 0 (- (count %) 4)))] | |
(str/join "." ns-segments))) | |
(defn tree-lines | |
"Generates a sequence of lines representing the directory tree under dir with the given prefix." | |
[dir prefix] | |
(let [children (vec (sort-by #(.getName %) (.listFiles dir))) | |
n (count children) | |
lines (for [i (range n) | |
:let [child (children i) | |
is-last (= i (dec n)) | |
child-name (.getName child) | |
line-prefix (if is-last "└── " "├── ") | |
child-prefix (if is-last " " "│ ")] | |
:when (or (.isDirectory child) (.endsWith child-name ".clj"))] | |
(if (.isDirectory child) | |
(cons (str prefix line-prefix child-name) | |
(tree-lines child (str prefix child-prefix))) | |
(let [rel-path (relative-path (io/file "src") child) | |
namespace (path-to-namespace rel-path)] | |
[(str prefix line-prefix child-name " (" namespace ")")])))] | |
(apply concat lines))) | |
(defn generate-tree-md | |
"Generates a namespace and files tree under the src directory and writes it to TREE.md." | |
[] | |
(let [src (io/file "src") | |
tree-lines (concat ["src"] (tree-lines src ""))] | |
(spit "TREE.md" (str/join "\n" tree-lines)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment