|
1 | 1 | (ns vim-clojure-highlight
|
2 |
| - (:require [clojure.string :as string])) |
| 2 | + (:require [clojure.set :as set] |
| 3 | + [clojure.string :as string]) |
| 4 | + (:import (clojure.lang MultiFn))) |
3 | 5 |
|
4 |
| -(def ^:private TYPE->SYNTAX-GROUP |
5 |
| - {:macro "clojureMacro" |
6 |
| - :fn "clojureFunc" |
7 |
| - :def "clojureVariable"}) |
| 6 | +;;;;;;;;;;;;;;;;;;;; Copied from vim-clojure-static.generate ;;;;;;;;;;;;;;;;;;; |
8 | 7 |
|
9 |
| -(defn- external-refs [ns] |
10 |
| - (remove #(= "clojure.core" (-> % peek meta :ns str)) (ns-refers ns))) |
| 8 | +(defn- fn-var? [v] |
| 9 | + (let [f @v] |
| 10 | + (or (contains? (meta v) :arglists) |
| 11 | + (fn? f) |
| 12 | + (instance? MultiFn f)))) |
11 | 13 |
|
12 |
| -(defn- aliased-refs [ns] |
| 14 | +(def special-forms |
| 15 | + "http://clojure.org/special_forms" |
| 16 | + '#{def if do let quote var fn loop recur throw try catch finally |
| 17 | + monitor-enter monitor-exit . new set!}) |
| 18 | + |
| 19 | +(def keyword-groups |
| 20 | + "Special forms, constants, and every public var in clojure.core keyed by |
| 21 | + syntax group name." |
| 22 | + (let [exceptions '#{throw try catch finally} |
| 23 | + builtins {"clojureConstant" '#{nil} |
| 24 | + "clojureBoolean" '#{true false} |
| 25 | + "clojureSpecial" (apply disj special-forms exceptions) |
| 26 | + "clojureException" exceptions |
| 27 | + "clojureCond" '#{case cond cond-> cond->> condp if-let |
| 28 | + if-not if-some when when-first when-let |
| 29 | + when-not when-some} |
| 30 | + ;; Imperative looping constructs (not sequence functions) |
| 31 | + "clojureRepeat" '#{doseq dotimes while}} |
| 32 | + coresyms (set/difference (set (keys (ns-publics 'clojure.core))) |
| 33 | + (set (mapcat peek builtins))) |
| 34 | + group-preds [["clojureDefine" #(re-seq #"\Adef(?!ault)" (str %))] |
| 35 | + ["clojureMacro" #(:macro (meta (ns-resolve 'clojure.core %)))] |
| 36 | + ["clojureFunc" #(fn-var? (ns-resolve 'clojure.core %))] |
| 37 | + ["clojureVariable" identity]]] |
| 38 | + (first |
| 39 | + (reduce |
| 40 | + (fn [[m syms] [group pred]] |
| 41 | + (let [group-syms (set (filterv pred syms))] |
| 42 | + [(assoc m group group-syms) |
| 43 | + (set/difference syms group-syms)])) |
| 44 | + [builtins coresyms] group-preds)))) |
| 45 | + |
| 46 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 47 | + |
| 48 | +(def core-symbol->syntax-group |
| 49 | + "A map of symbols from clojure.core mapped to syntax group name." |
| 50 | + (reduce |
| 51 | + (fn [m [group syms]] |
| 52 | + (reduce |
| 53 | + (fn [m sym] |
| 54 | + (assoc m sym group)) |
| 55 | + m syms)) |
| 56 | + {} keyword-groups)) |
| 57 | + |
| 58 | +(defn clojure-core? |
| 59 | + "Is this var from clojure.core?" |
| 60 | + [var] |
| 61 | + (= "clojure.core" (-> var meta :ns str))) |
| 62 | + |
| 63 | +(defn refers [ns include-clojure-core?] |
| 64 | + (if include-clojure-core? |
| 65 | + (ns-refers ns) |
| 66 | + (remove (comp clojure-core? peek) (ns-refers ns)))) |
| 67 | + |
| 68 | +(defn aliased-refers [ns] |
13 | 69 | (mapcat
|
14 | 70 | (fn [[alias alias-ns]]
|
15 | 71 | (mapv #(vector (symbol (str alias \/ (first %))) (peek %))
|
16 | 72 | (ns-publics alias-ns)))
|
17 | 73 | (ns-aliases ns)))
|
18 | 74 |
|
19 |
| -(defn- var-type [v] |
| 75 | +(defn var-type [v] |
20 | 76 | (let [f @v m (meta v)]
|
21 |
| - (cond (:macro m) :macro |
22 |
| - (or (contains? m :arglists) |
23 |
| - (fn? f) |
24 |
| - (instance? clojure.lang.MultiFn f)) :fn |
25 |
| - :else :def))) |
| 77 | + (cond (clojure-core? v) (core-symbol->syntax-group (:name m)) |
| 78 | + (:macro m) "clojureMacro" |
| 79 | + (fn-var? v) "clojureFunc" |
| 80 | + :else "clojureVariable"))) |
26 | 81 |
|
27 |
| -(defn- syntax-keyword-dictionary [ns-refs] |
| 82 | +(defn syntax-keyword-dictionary [ns-refs] |
28 | 83 | (->> ns-refs
|
29 | 84 | (group-by (comp var-type peek))
|
30 |
| - (mapv (fn [[type sym->vars]] |
31 |
| - (->> sym->vars |
| 85 | + (mapv (fn [[type sym->var]] |
| 86 | + (->> sym->var |
32 | 87 | (mapv (comp pr-str str first))
|
33 | 88 | (string/join \,)
|
34 |
| - (format "'%s': [%s]" (TYPE->SYNTAX-GROUP type))))) |
| 89 | + (format "'%s': [%s]" type)))) |
35 | 90 | (string/join \,)
|
36 | 91 | (format "let b:clojure_syntax_keywords = { %s }")))
|
37 | 92 |
|
38 |
| -(defn ns-syntax-command [ns hi-locals?] |
39 |
| - (syntax-keyword-dictionary (concat (external-refs ns) |
40 |
| - (aliased-refs ns) |
41 |
| - (when hi-locals? (ns-publics ns))))) |
| 93 | +(defn ns-syntax-command [ns & opts] |
| 94 | + (let [{:keys [local-vars clojure-core] |
| 95 | + :or {local-vars true clojure-core true}} (apply hash-map opts) |
| 96 | + refs (refers ns clojure-core) |
| 97 | + dict (syntax-keyword-dictionary (concat refs |
| 98 | + (aliased-refers ns) |
| 99 | + (when local-vars (ns-publics ns))))] |
| 100 | + (str "let b:clojure_syntax_without_core_keywords = " (if clojure-core 1 0) |
| 101 | + " | " dict))) |
0 commit comments