summaryrefslogtreecommitdiff
path: root/vim/bundle/slimv/swank-clojure/swank/loader.clj
blob: 27466f66fb0687dd2112d5668b886b821cfb1b87 (plain)
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
(ns swank.loader
  (:require [swank.util.sys :as sys]
            [swank.util.clojure :as clj])
  (:import [java.io File]))

(defonce #^File *swank-source-path*
  (if-let [resource (.getResource (clojure.lang.RT/baseLoader)
                                  #^String *file*)]
    (.getParentFile (File. (.getFile resource)))))

(defonce #^File *swank-compile-path*
  (File. (str (sys/user-home-path)
              File/separator
              ".slime"
              File/separator
              "cljclass")))

(defn file-directory? [#^File f]
  (.isDirectory f))

(defn file-last-modified [#^File f]
  (.lastModified f))

(defn all-files-in-directory [#^File f]
  (let [list-files  (.listFiles f)
        files       (remove file-directory? list-files)
        directories (filter file-directory? list-files)]
    (concat files (mapcat all-files-in-directory directories))))

(defn clj-file? [#^File f]
  (.endsWith (str f) ".clj"))

(defn swank-source-files [#^File path]
  (filter clj-file? (all-files-in-directory path)))

(defn relative-path-name [#^File parent #^File file]
  (let [file-name (str file)
        parent-name (str parent)]
    (when (.startsWith file-name parent-name)
      (.substring file-name (inc (.length parent-name))))))

(defn file-name-to-swank-package-sym [#^String file-name]
  (assert (clj-file? file-name))
  (symbol
   (str "swank."
        (clj/unmunge
         (.replaceAll (.substring file-name 0 (- (.length file-name) 4))
                      File/separator
                      ".")))))

(defn swank-packages []
  (map #(file-name-to-swank-package-sym (relative-path-name *swank-source-path* %))
       (swank-source-files *swank-source-path*)))

(defn swank-version
  "A likely bad way of calculating a version number for swank clojure"
  ([]
     (str (reduce + (map file-last-modified (swank-source-files *swank-source-path*)))
	  "+" (clojure-version))))

(defn delete-file-recursive [& paths]
  (when-not (empty? paths)
    (let [f #^File (first paths)]
      (if (and f (.exists f))
        (if (.isDirectory f)
          (if-let [files (seq (.listFiles f))]
            (recur (concat files paths))
            (do
              (.delete f)
              (recur (rest paths))))
          (do
            (.delete f)
            (recur (rest paths))))
        (recur (rest paths))))))

(defn clean-up []
  (let [current-path (File. *swank-compile-path* (str (swank-version)))]
    (doseq [compiled-path (.listFiles *swank-compile-path*)
            :when (not= current-path compiled-path)]
      (delete-file-recursive compiled-path))))

(defn swank-ns? [ns]
  (.startsWith (name (ns-name ns)) "swank."))

(defn all-swank-ns []
  (filter swank-ns? (all-ns)))

(defn compile-swank [#^String path]
  (binding [*compile-path* path]
    (doseq [sym (swank-packages)]
      (println "Compiling" (name sym))
      (compile sym))))

(defn init []
  (let [path (File. *swank-compile-path* (str (swank-version)))
        path-already-exists? (.exists path)]
    (when-not path-already-exists?
      (.mkdirs path))
    (add-classpath (-> path .toURI .toURL))
    (when-not path-already-exists?
      (compile-swank (str path)))))