|
2 | 2 |
|
3 | 3 | (ns clj-mcp.repl-tools |
4 | 4 | "Namespace containing helper functions for REPL-driven development" |
5 | | - (:require [clojure.string :as str] |
6 | | - [clojure.pprint :as pprint])) |
| 5 | + (:require [clojure.pprint :as pprint] |
| 6 | + [clojure.spec.alpha :as s] |
| 7 | + [clojure.string :as str])) |
7 | 8 |
|
8 | 9 | ;; Namespace exploration |
9 | 10 | (defn list-ns |
|
52 | 53 | (println (str " Arguments: " arglists))) |
53 | 54 | (when-let [added (:added m)] |
54 | 55 | (println (str " Added in: " added))) |
| 56 | + (when-let [fn-spec (s/get-spec (symbol v))] |
| 57 | + (println " Function Spec: " (with-out-str (pprint/pprint (s/describe fn-spec))))) |
55 | 58 | (when-let [deprecated (:deprecated m)] |
56 | 59 | (println (str " DEPRECATED: " deprecated))) |
57 | 60 | (println (str "-------------------------"))) |
58 | 61 | (println (str "Error: Symbol not found: " sym))) |
59 | 62 | nil) |
60 | 63 |
|
| 64 | +(defn doc-namespace |
| 65 | + "Show documentation for a namespace. Accepts symbol or string." |
| 66 | + [sym] |
| 67 | + (if-let [ns (find-ns (if (symbol? sym) sym (symbol sym)))] |
| 68 | + (let [m (meta ns)] |
| 69 | + (println (str "-------------------------")) |
| 70 | + (println (str (name sym) " - " (or (:doc m) "No documentation"))) |
| 71 | + (println (str "-------------------------"))) |
| 72 | + (println (str "Error: Namespace not found: " sym))) |
| 73 | + nil) |
| 74 | + |
61 | 75 | (defn source-symbol |
62 | 76 | "Show source code for a var. Accepts symbol or string." |
63 | 77 | [sym] |
64 | 78 | (if-let [v (resolve (if (symbol? sym) sym (symbol sym)))] |
65 | 79 | (if-let [source-fn (resolve 'clojure.repl/source-fn)] |
66 | | - (source-fn (symbol (str (-> v meta :ns)) (str (-> v meta :name)))) |
| 80 | + (println (source-fn (symbol v))) |
67 | 81 | (println "Error: clojure.repl/source-fn not available")) |
68 | 82 | (println (str "Error: Symbol not found: " sym))) |
69 | 83 | nil) |
70 | 84 |
|
| 85 | +(defn describe-spec |
| 86 | + "Show detailed information about a keyword/symbol/var `spec`." |
| 87 | + [spec] |
| 88 | + (if-let [spec-form (s/get-spec spec)] |
| 89 | + (do |
| 90 | + (println (str "-------------------------")) |
| 91 | + (println (str "Spec: " spec)) |
| 92 | + (pprint/pprint (s/describe spec-form)) |
| 93 | + (println (str "-------------------------"))) |
| 94 | + (println (str "Error: Spec not found: " spec))) |
| 95 | + nil) |
| 96 | + |
71 | 97 | (defn find-symbols |
72 | | - "Find symbols matching the given pattern across all namespaces." |
| 98 | + "Find symbols matching the given pattern across all namespaces. |
| 99 | + Pattern can be a string (for substring matching) or a regex pattern. |
| 100 | + Matches against both namespace and symbol name in the format 'namespace/symbol'." |
73 | 101 | [pattern] |
74 | | - (let [matches (sort (map str (clojure.repl/apropos pattern)))] |
| 102 | + (let [match-fn (cond |
| 103 | + (instance? java.util.regex.Pattern pattern) |
| 104 | + #(re-find pattern %) |
| 105 | + :else |
| 106 | + #(str/includes? % (str pattern))) |
| 107 | + |
| 108 | + matches (sort (for [ns (all-ns) |
| 109 | + :let [ns-name (str (ns-name ns))] |
| 110 | + [sym-name] (ns-publics ns) |
| 111 | + :let [qualified-name (str ns-name "/" (name sym-name))] |
| 112 | + :when (match-fn qualified-name)] |
| 113 | + qualified-name))] |
75 | 114 | (println (str "Symbols matching '" pattern "':")) |
76 | 115 | (doseq [sym matches] |
77 | 116 | (println (str " " sym))) |
|
127 | 166 | (println " clj-mcp.repl-tools/list-ns - List all available namespaces") |
128 | 167 | (println " clj-mcp.repl-tools/list-vars - List all vars in namespace") |
129 | 168 | (println " clj-mcp.repl-tools/doc-symbol - Show documentation for symbol") |
| 169 | + (println " clj-mcp.repl-tools/doc-namespace - Show documentation for a namespace") |
130 | 170 | (println " clj-mcp.repl-tools/source-symbol - Show source code for symbol") |
| 171 | + (println " clj-mcp.repl-tools/describe-spec - Show detailed information about spec") |
131 | 172 | (println " clj-mcp.repl-tools/find-symbols - Find symbols matching pattern") |
132 | 173 | (println " clj-mcp.repl-tools/complete - Find completions for prefix") |
133 | 174 | (println " clj-mcp.repl-tools/help - Show this help message") |
|
136 | 177 | (println " (clj-mcp.repl-tools/list-ns) ; List all namespaces") |
137 | 178 | (println " (clj-mcp.repl-tools/list-vars 'clojure.string) ; List functions in clojure.string") |
138 | 179 | (println " (clj-mcp.repl-tools/doc-symbol 'map) ; Show documentation for map") |
| 180 | + (println " (clj-mcp.repl-tools/doc-namespace 'clojure.repl) ; Show documentation for map") |
139 | 181 | (println " (clj-mcp.repl-tools/source-symbol 'map) ; Show source code for map") |
140 | | - (println " (clj-mcp.repl-tools/find-symbols \"seq\") ; Find symbols containing \"seq\"") |
| 182 | + (println " (clj-mcp.repl-tools/describe-spec :my/spec) ; Show detailed information about a clojure spec") |
| 183 | + (println " (clj-mcp.repl-tools/find-symbols \"seq\") ; Find symbols containing \"seq\" (namespace/symbol)") |
| 184 | + (println " (clj-mcp.repl-tools/find-symbols #\".*math.*\") ; Find symbols matching regex pattern") |
141 | 185 | (println " (clj-mcp.repl-tools/complete \"clojure.string/j\") ; Find completions for prefix") |
142 | 186 | (println) |
143 | 187 | (println "For convenience, you can require the namespace with an alias:") |
|
0 commit comments