Skip to content

Instantly share code, notes, and snippets.

@esshka
Created March 24, 2025 08:27
Show Gist options
  • Save esshka/233b8ab03496e5063b720c330373514d to your computer and use it in GitHub Desktop.
Save esshka/233b8ab03496e5063b720c330373514d to your computer and use it in GitHub Desktop.
Clear, hierarchical representation of both the file structure and namespaces
(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