Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of git://github.com/jochu/swank-clojure

  • Loading branch information...
commit 6d3c19b851ce84297ec94580b969b695a0030ec5 2 parents 34e6921 + 6f92845
@technomancy technomancy authored
View
107 swank/commands/basic.clj
@@ -164,7 +164,7 @@
;;;; Documentation
(defn- briefly-describe-symbol-for-emacs [var]
- (let [lines (fn [s] (seq (.split s (System/getProperty "line.separator"))))
+ (let [lines (fn [s] (seq (.split #^String s (System/getProperty "line.separator"))))
[_ symbol-name arglists d1 d2 & __] (lines (describe-to-string var))
macro? (= d1 "Macro")]
(list :designator symbol-name
@@ -238,35 +238,6 @@ that symbols accessible in the current namespace go first."
;;;; Completions
-(defn- vars-with-prefix
- "Filters a coll of vars and returns only those that have a given
- prefix."
- ([#^String prefix vars]
- (filter #(.startsWith #^String % prefix) (map (comp name :name meta) vars))))
-
-(defn- maybe-alias [sym ns]
- (or (resolve-ns sym (maybe-ns ns))
- (maybe-ns ns)))
-
-(defslimefn simple-completions [symbol-string package]
- (try
- (let [[sym-ns sym-name] (symbol-name-parts symbol-string)
- ns (if sym-ns (maybe-alias (symbol sym-ns) package) (maybe-ns package))
- vars (if sym-ns (vals (ns-publics ns)) (filter var? (vals (ns-map ns))))
- matches (seq (sort (vars-with-prefix sym-name vars)))]
- (if sym-ns
- (list (map (partial str sym-ns "/") matches)
- (if matches
- (str sym-ns "/" (reduce largest-common-prefix matches))
- symbol-string))
- (list matches
- (if matches
- (reduce largest-common-prefix matches)
- symbol-string))))
- (catch java.lang.Throwable t
- (list nil symbol-string))))
-
-
(defslimefn list-all-package-names
([] (map (comp str ns-name) (all-ns)))
([nicknames?] (list-all-package-names)))
@@ -289,37 +260,23 @@ that symbols accessible in the current namespace go first."
;;;; meta dot find
-(defn- slime-find-file-in-dir [#^File file #^String dir]
- (let [file-name (. file (getPath))
- child (File. (File. dir) file-name)]
- (or (when (.exists child)
- `(:file ~(.getPath child)))
- (try
- (let [zipfile (ZipFile. dir)]
- (when (.getEntry zipfile file-name)
- `(:zip ~dir ~file-name)))
- (catch Throwable e false)))))
-
-(defn- slime-find-file-in-paths [#^String file paths]
- (let [f (File. file)]
- (if (.isAbsolute f)
- `(:file ~file)
- (first (filter identity (map #(slime-find-file-in-dir f %) paths))))))
-
-(defn- get-path-prop
- "Returns a coll of the paths represented in a system property"
- ([prop]
- (seq (-> (System/getProperty prop)
- (.split File/pathSeparator))))
- ([prop & props]
- (lazy-cat (get-path-prop prop) (mapcat get-path-prop props))))
-
-(defn- slime-search-paths []
- (concat (get-path-prop "user.dir" "java.class.path" "sun.boot.class.path")
- (let [loader (clojure.lang.RT/baseLoader)]
- (when (instance? java.net.URLClassLoader loader)
- (map #(.getPath #^java.net.URL %)
- (.getURLs #^java.net.URLClassLoader (cast java.net.URLClassLoader (clojure.lang.RT/baseLoader))))))))
+(defn- slime-zip-resource [#^java.net.URL resource]
+ (let [jar-connection #^java.net.JarURLConnection (.openConnection resource)]
+ (list :zip (.getFile (.getJarFileURL jar-connection)) (.getEntryName jar-connection))))
+
+(defn- slime-file-resource [#^java.net.URL resource]
+ (list :file (.getFile resource)))
+
+(defn- slime-find-resource [#^String file]
+ (let [resource (.getResource (clojure.lang.RT/baseLoader) file)]
+ (if (= (.getProtocol resource) "jar")
+ (slime-zip-resource resource)
+ (slime-file-resource resource))))
+
+(defn- slime-find-file [#^String file]
+ (if (.isAbsolute (File. file))
+ (list :file file)
+ (slime-find-resource file)))
(defn- namespace-to-path [ns]
(let [#^String ns-str (name (ns-name ns))]
@@ -328,30 +285,24 @@ that symbols accessible in the current namespace go first."
(.replace \- \_)
(.replace \. \/))))
-(defn source-location-for-frame [frame]
+(defn source-location-for-frame [#^StackTraceElement frame]
(let [line (.getLineNumber frame)
filename (if (.. frame getFileName (endsWith ".java"))
- (.. frame getClassName (replace \. \/)
- (substring 0 (.lastIndexOf (.getClassName frame) "."))
- (concat (str File/separator (.getFileName frame))))
- (str (namespace-to-path
- (symbol ((re-find #"(.*?)\$"
- (.getClassName frame)) 1)))
- File/separator (.getFileName frame)))
- path (slime-find-file-in-paths filename (slime-search-paths))]
+ (.. frame getClassName (replace \. \/)
+ (substring 0 (.lastIndexOf (.getClassName frame) "."))
+ (concat (str File/separator (.getFileName frame))))
+ (str (namespace-to-path
+ (symbol ((re-find #"(.*?)\$"
+ (.getClassName frame)) 1)))
+ File/separator (.getFileName frame)))
+ path (slime-find-file filename)]
`(:location ~path (:line ~line) nil)))
(defslimefn find-definitions-for-emacs [name]
(let [sym-name (read-from-string name)
sym-var (ns-resolve (maybe-ns *current-package*) sym-name)]
(when-let [meta (and sym-var (meta sym-var))]
- (if-let [path (or
- ;; Check first check using full namespace
- (slime-find-file-in-paths (str (namespace-to-path (:ns meta))
- File/separator
- (:file meta)) (slime-search-paths))
- ;; Otherwise check using just the filename
- (slime-find-file-in-paths (:file meta) (slime-search-paths)))]
+ (if-let [path (slime-find-file (:file meta))]
`((~(str "(defn " (:name meta) ")")
(:location
~path
@@ -388,4 +339,4 @@ that symbols accessible in the current namespace go first."
(source-location-for-frame
(nth (.getStackTrace *current-exception*) n)))
-(defslimefn create-repl [target] '("user" user))
+(defslimefn create-repl [target] '("user" "user"))
View
89 swank/commands/completion.clj
@@ -0,0 +1,89 @@
+(remove-ns 'swank.commands.completion)
+(ns swank.commands.completion
+ (:use (swank util core commands)
+ (swank.util string clojure java)))
+
+(defn potential-ns
+ "Returns a list of potential namespace completions for a given
+ namespace"
+ ([] (potential-ns *ns*))
+ ([ns]
+ (for [ns-sym (concat (keys (ns-aliases (ns-name ns)))
+ (map ns-name (all-ns)))]
+ (name ns-sym))))
+
+(defn potential-var-public
+ "Returns a list of potential public var name completions for a
+ given namespace"
+ ([] (potential-var-public *ns*))
+ ([ns]
+ (for [var-sym (keys (ns-publics ns))]
+ (name var-sym))))
+
+(defn potential-var
+ "Returns a list of all potential var name completions for a given
+ namespace"
+ ([] (potential-var *ns*))
+ ([ns]
+ (for [[key v] (ns-map ns)
+ :when (var? v)]
+ (name key))))
+
+(defn potential-classes
+ "Returns a list of potential class name completions for a given
+ namespace"
+ ([] (potential-classes *ns*))
+ ([ns]
+ (for [class-sym (keys (ns-imports ns))]
+ (name class-sym))))
+
+(defn potential-dot
+ "Returns a list of potential dot method name completions for a given
+ namespace"
+ ([] (potential-dot *ns*))
+ ([ns]
+ (map #(str "." %) (set (map method-name (mapcat instance-methods (vals (ns-imports ns))))))))
+
+(defn potential-static
+ "Returns a list of potential static methods for a given namespace"
+ ([#^Class class]
+ (map method-name (static-methods class))))
+
+(defn resolve-class
+ "Attempts to resolve a symbol into a java Class. Returns nil on
+ failure."
+ ([sym]
+ (try
+ (let [res (resolve sym)]
+ (when (class? res)
+ res))
+ (catch Throwable t
+ nil))))
+
+(defn potential-completions [symbol-ns ns]
+ (if symbol-ns
+ (map #(str symbol-ns "/" %)
+ (if-let [class (resolve-class symbol-ns)]
+ (potential-static class)
+ (potential-var-public symbol-ns)))
+ (concat (potential-var ns)
+ (when-not symbol-ns
+ (potential-ns))
+ (potential-classes ns)
+ (potential-dot ns))))
+
+(defn- maybe-alias [sym ns]
+ (or (resolve-ns sym (maybe-ns ns))
+ (maybe-ns ns)))
+
+(defslimefn simple-completions [symbol-string package]
+ (try
+ (let [[sym-ns sym-name] (symbol-name-parts symbol-string)
+ potential (potential-completions (when sym-ns (symbol sym-ns)) (ns-name (maybe-ns package)))
+ matches (seq (sort (filter #(.startsWith #^String % symbol-string) potential)))]
+ (list matches
+ (if matches
+ (reduce largest-common-prefix matches)
+ symbol-string)))
+ (catch java.lang.Throwable t
+ (list nil symbol-string))))
View
428 swank/commands/contrib/swank_fuzzy.clj
@@ -0,0 +1,428 @@
+;;; swank_fuzzy.clj --- fuzzy symbol completion, Clojure implementation.
+
+;; Original CL implementation authors (from swank-fuzzy.lisp) below,
+;; Authors: Brian Downing <bdowning@lavos.net>
+;; Tobias C. Rittweiler <tcr@freebits.de>
+;; and others
+
+;; This progam is based on the swank-fuzzy.lisp.
+;; Thanks the CL implementation authors for that useful software.
+
+(ns swank.commands.contrib.swank-fuzzy
+ (:use (swank util core commands))
+ (:use (swank.util clojure)))
+
+(def *fuzzy-recursion-soft-limit* 30)
+(defn- compute-most-completions [short full]
+ (let [collect-chunk (fn [[pcur [[pa va] ys]] [pb vb]]
+ (let [xs (if (= (dec pb) pcur)
+ [[pa (str va vb)]]
+ [[pb vb] [pa va]])]
+ [pb (if ys (conj xs ys) xs)]))
+ step (fn step [short full pos chunk seed limit?]
+ (cond
+ (and (empty? full) (not (empty? short)))
+ nil
+ (or (empty? short) limit?)
+ (if chunk
+ (conj seed
+ (second (reduce collect-chunk
+ [(ffirst chunk) [(first chunk)]]
+ (rest chunk))))
+ seed)
+ (= (first short) (first full))
+ (let [seed2
+ (step short (rest full) (inc pos) chunk seed
+ (< *fuzzy-recursion-soft-limit* (count seed)))]
+ (recur (rest short) (rest full) (inc pos)
+ (conj chunk [pos (str (first short))])
+ (if (and seed2 (not (empty? seed2)))
+ seed2
+ seed)
+ false))
+ :else
+ (recur short (rest full) (inc pos) chunk seed false)))]
+ (map reverse (step short full 0 [] () false))))
+
+(def *fuzzy-completion-symbol-prefixes* "*+-%&?<")
+(def *fuzzy-completion-word-separators* "-/.")
+(def *fuzzy-completion-symbol-suffixes* "*+->?!")
+(defn- score-completion [completion short full]
+ (let [find1
+ (fn [c s]
+ (re-find (re-pattern (java.util.regex.Pattern/quote (str c))) s))
+ at-beginning? zero?
+ after-prefix?
+ (fn [pos]
+ (and (= pos 1)
+ (find1 (nth full 0) *fuzzy-completion-symbol-prefixes*)))
+ word-separator?
+ (fn [pos]
+ (find1 (nth full pos) *fuzzy-completion-word-separators*))
+ after-word-separator?
+ (fn [pos]
+ (find1 (nth full (dec pos)) *fuzzy-completion-word-separators*))
+ at-end?
+ (fn [pos]
+ (= pos (dec (count full))))
+ before-suffix?
+ (fn [pos]
+ (and (= pos (- (count full) 2))
+ (find1 (nth full (dec (count full)))
+ *fuzzy-completion-symbol-suffixes*)))]
+ (letfn [(score-or-percentage-of-previous
+ [base-score pos chunk-pos]
+ (if (zero? chunk-pos)
+ base-score
+ (max base-score
+ (+ (* (score-char (dec pos) (dec chunk-pos)) 0.85)
+ (Math/pow 1.2 chunk-pos)))))
+ (score-char
+ [pos chunk-pos]
+ (score-or-percentage-of-previous
+ (cond (at-beginning? pos) 10
+ (after-prefix? pos) 10
+ (word-separator? pos) 1
+ (after-word-separator? pos) 8
+ (at-end? pos) 6
+ (before-suffix? pos) 6
+ :else 1)
+ pos chunk-pos))
+ (score-chunk
+ [chunk]
+ (let [chunk-len (count (second chunk))]
+ (apply +
+ (map score-char
+ (take chunk-len (iterate inc (first chunk)))
+ (reverse (take chunk-len
+ (iterate dec (dec chunk-len))))))))]
+ (let [chunk-scores (map score-chunk completion)
+ length-score (/ 10.0 (inc (- (count full) (count short))))]
+ [(+ (apply + chunk-scores) length-score)
+ (list (map list chunk-scores completion) length-score)]))))
+
+(defn- compute-highest-scoring-completion [short full]
+ (let [scored-results
+ (map (fn [result]
+ [(first (score-completion result short full))
+ result])
+ (compute-most-completions short full))
+ winner (first (sort (fn [[av _] [bv _]] (> av bv))
+ scored-results))]
+ [(second winner) (first winner)]))
+
+(defn- call-with-timeout [time-limit-in-msec proc]
+ "Create a thunk that returns true if given time-limit-in-msec has been
+ elapsed and calls proc with the thunk as an argument. Returns a 3 elements
+ vec: A proc result, given time-limit-in-msec has been elapsed or not,
+ elapsed time in millisecond."
+ (let [timed-out (atom false)
+ start! (fn []
+ (future (do
+ (Thread/sleep time-limit-in-msec)
+ (swap! timed-out (constantly true)))))
+ timed-out? (fn [] @timed-out)
+ started-at (System/nanoTime)]
+ (start!)
+ [(proc timed-out?)
+ @timed-out
+ (/ (double (- (System/nanoTime) started-at)) 1000000.0)]))
+
+(defmacro with-timeout
+ "Create a thunk that returns true if given time-limit-in-msec has been
+ elapsed and bind it to timed-out?. Then execute body."
+ #^{:private true}
+ [[timed-out? time-limit-in-msec] & body]
+ `(call-with-timeout ~time-limit-in-msec (fn [~timed-out?] ~@body)))
+
+(defstruct fuzzy-matching
+ :var :ns :symbol :ns-name :score :ns-chunks :var-chunks)
+
+(defn- fuzzy-extract-matching-info [matching string]
+ (let [[user-ns-name _] (symbol-name-parts string)]
+ (cond
+ (:var matching)
+ [(str (:symbol matching))
+ (cond (nil? user-ns-name) nil
+ :else (:ns-name matching))]
+ :else
+ [""
+ (str (:symbol matching))])))
+
+(defn- fuzzy-find-matching-vars
+ [string ns var-filter external-only?]
+ (let [compute (partial compute-highest-scoring-completion string)
+ ns-maps (cond
+ external-only? ns-publics
+ (= ns *ns*) ns-map
+ :else ns-interns)]
+ (map (fn [[match-result score var sym]]
+ (if (var? var)
+ (struct fuzzy-matching
+ var nil (or (:name ^var)
+ (symbol (pr-str var)))
+ nil
+ score nil match-result)
+ (struct fuzzy-matching
+ nil nil sym
+ nil
+ score nil match-result)))
+ (filter (fn [[match-result & _]]
+ (or (= string "")
+ (not-empty match-result)))
+ (map (fn [[k v]]
+ (if (= string "")
+ (conj [nil 0.0] v k)
+ (conj (compute (.toLowerCase (str k))) v k)))
+ (filter var-filter (seq (ns-maps ns))))))))
+(defn- fuzzy-find-matching-nss
+ [string]
+ (let [compute (partial compute-highest-scoring-completion string)]
+ (map (fn [[match-result score ns ns-sym]]
+ (struct fuzzy-matching nil ns ns-sym (str ns-sym)
+ score match-result nil))
+ (filter (fn [[match-result & _]] (not-empty match-result))
+ (map (fn [[ns-sym ns]]
+ (conj (compute (str ns-sym)) ns ns-sym))
+ (concat
+ (map (fn [ns] [(symbol (str ns)) ns]) (all-ns))
+ (ns-aliases *ns*)))))))
+
+(defn- fuzzy-generate-matchings
+ [string default-ns timed-out?]
+ (let [take* (partial take-while (fn [_] (not (timed-out?))))
+ [parsed-ns-name parsed-symbol-name] (symbol-name-parts string)
+ find-vars
+ (fn find-vars
+ ([designator ns]
+ (find-vars designator ns identity))
+ ([designator ns var-filter]
+ (find-vars designator ns var-filter nil))
+ ([designator ns var-filter external-only?]
+ (take* (fuzzy-find-matching-vars designator
+ ns
+ var-filter
+ external-only?))))
+ find-nss (comp take* fuzzy-find-matching-nss)
+ make-duplicate-var-filter
+ (fn [fuzzy-ns-matchings]
+ (let [nss (set (map :ns-name fuzzy-ns-matchings))]
+ (comp not nss str :ns meta second)))
+ matching-greater
+ (fn [a b]
+ (cond
+ (> (:score a) (:score b)) -1
+ (< (:score a) (:score b)) 1
+ :else (compare (:symbol a) (:symbol b))))
+ fix-up
+ (fn [matchings parent-package-matching]
+ (map (fn [m]
+ (assoc m
+ :ns-name (:ns-name parent-package-matching)
+ :ns-chunks (:ns-chunks parent-package-matching)
+ :score (if (= parsed-ns-name "")
+ (/ (:score parent-package-matching) 100)
+ (+ (:score parent-package-matching)
+ (:score m)))))
+ matchings))]
+ (sort matching-greater
+ (cond
+ (nil? parsed-ns-name)
+ (concat
+ (find-vars parsed-symbol-name (maybe-ns default-ns))
+ (find-nss parsed-symbol-name))
+ ;; (apply concat
+ ;; (let [ns *ns*]
+ ;; (pcalls #(binding [*ns* ns]
+ ;; (find-vars parsed-symbol-name
+ ;; (maybe-ns default-ns)))
+ ;; #(binding [*ns* ns]
+ ;; (find-nss parsed-symbol-name)))))
+ (= "" parsed-ns-name)
+ (find-vars parsed-symbol-name (maybe-ns default-ns))
+ :else
+ (let [found-nss (find-nss parsed-ns-name)
+ find-vars1 (fn [ns-matching]
+ (fix-up
+ (find-vars parsed-symbol-name
+ (:ns ns-matching)
+ (make-duplicate-var-filter
+ (filter (partial = ns-matching)
+ found-nss))
+ true)
+ ns-matching))]
+ (concat
+ (apply concat
+ (map find-vars1 (sort matching-greater found-nss)))
+ found-nss))))))
+
+(defn- fuzzy-format-matching [string matching]
+ (let [[symbol package] (fuzzy-extract-matching-info matching string)
+ result (str package (when package "/") symbol)]
+ [result (.indexOf #^String result #^String symbol)]))
+
+(defn- classify-matching [m]
+ (let [make-var-meta (fn [m]
+ (fn [key]
+ (when-let [var (:var m)]
+ (when-let [var-meta ^var]
+ (get var-meta key)))))
+ vm (make-var-meta m)]
+ (set
+ (filter
+ identity
+ [(when-not (or (vm :macro) (vm :arglists))
+ :boundp)
+ (when (vm :arglists) :fboundp)
+ ;; (:typespec)
+ ;; (:class)
+ (when (vm :macro) :macro)
+ (when (special-symbol? (:symbol m)) :special-operator)
+ (when (:ns-name m) :package)
+ (when (= clojure.lang.MultiFn (vm :tag))
+ :generic-function)]))))
+(defn- classification->string [flags]
+ (format (apply str (replicate 8 "%s"))
+ (if (or (:boundp flags)
+ (:constant flags)) "b" "-")
+ (if (:fboundp flags) "f" "-")
+ (if (:generic-function flags) "g" "-")
+ (if (:class flags) "c" "-")
+ (if (:typespec flags) "t" "-")
+ (if (:macro flags) "m" "-")
+ (if (:special-operator flags) "s" "-")
+ (if (:package flags) "p" "-")))
+
+(defn- fuzzy-convert-matching-for-emacs [string matching]
+ (let [[name added-length] (fuzzy-format-matching string matching)]
+ [name
+ (format "%.2f" (:score matching))
+ (concat (:ns-chunks matching)
+ (map (fn [[offset string]] [(+ added-length offset) string])
+ (:var-chunks matching)))
+ (classification->string (classify-matching matching))
+ ]))
+
+(defn- fuzzy-completion-set
+ [string default-ns limit time-limit-in-msec]
+ (let [[matchings interrupted? _]
+ (with-timeout [timed-out? time-limit-in-msec]
+ (vec (fuzzy-generate-matchings string default-ns timed-out?)))
+ subvec1 (if (and limit
+ (> limit 0)
+ (< limit (count matchings)))
+ (fn [v] (subvec v 0 limit))
+ identity)]
+ [(subvec1 (vec (map (partial fuzzy-convert-matching-for-emacs string)
+ matchings)))
+ interrupted?]))
+
+(defslimefn fuzzy-completions
+ [string default-package-name
+ _limit limit _time-limit-in-msec time-limit-in-msec]
+ (let [[xs x] (fuzzy-completion-set string default-package-name
+ limit time-limit-in-msec)]
+ (list
+ (map (fn [[symbol score chunks class]]
+ (list symbol score (map (partial apply list) chunks) class))
+ xs)
+ (when x 't))))
+
+(defslimefn fuzzy-completion-selected [_ _] nil)
+
+(comment
+ (do
+ (use '[clojure.test])
+
+ (is (= '(([0 "m"] [9 "v"] [15 "b"]))
+ (compute-most-completions "mvb" "multiple-value-bind")))
+ (is (= '(([0 "zz"]) ([0 "z"] [2 "z"]) ([1 "zz"]))
+ (compute-most-completions "zz" "zzz")))
+ (is (= 103
+ (binding [*fuzzy-recursion-soft-limit* 2]
+ (count
+ (compute-most-completions "ZZZZZZ" "ZZZZZZZZZZZZZZZZZZZZZZZ")))))
+
+ (are [x p s] (= x (score-completion [[p s]] s "*multiple-value+"))
+ '[10.625 (((10 [0 "*"])) 0.625)] 0 "*" ;; at-beginning
+ '[10.625 (((10 [1 "m"])) 0.625)] 1 "m" ;; after-prefix
+ '[1.625 (((1 [9 "-"])) 0.625)] 9 "-" ;; word-sep
+ '[8.625 (((8 [10 "v"])) 0.625)] 10 "v" ;; after-word-sep
+ '[6.625 (((6 [15 "+"])) 0.625)] 15 "+" ;; at-end
+ '[6.625 (((6 [14 "e"])) 0.625)] 14 "e" ;; before-suffix
+ '[1.625 (((1 [2 "u"])) 0.625)] 2 "u" ;; other
+ )
+ (is (= (+ 10 ;; m's score
+ (+ (* 10 0.85) (Math/pow 1.2 1))) ;; u's score
+ (let [[_ x]
+ (score-completion [[1 "mu"]] "mu" "*multiple-value+")]
+ ((comp first ffirst) x)))
+ "`m''s score + `u''s score (percentage of previous which is 'm''s)")
+
+ (is (= '[([0 "zz"]) 24.7]
+ (compute-highest-scoring-completion "zz" "zzz")))
+
+ (are [to? ret to proc] (= [ret to?]
+ (let [[x y _] (call-with-timeout to proc)]
+ [x y]))
+ false "r" 10 (fn [_] "r")
+ true nil 1 (fn [_] (Thread/sleep 10) nil))
+
+ (are [symbol package input] (= [symbol package]
+ (fuzzy-extract-matching-info
+ (struct fuzzy-matching
+ true nil
+ "symbol" "ns-name"
+ nil nil nil)
+ input))
+ "symbol" "ns-name" "p/*"
+ "symbol" nil "*")
+ (is (= ["" "ns-name"]
+ (fuzzy-extract-matching-info
+ (struct fuzzy-matching
+ nil nil
+ "ns-name" ""
+ nil nil nil)
+ "")))
+
+ (defmacro try! #^{:private true}
+ [& body]
+ `(do
+ ~@(map (fn [x] `(try ~x (catch Throwable ~'_ nil)))
+ body)))
+
+ (try
+ (def testing-testing0 't)
+ (def #^{:private true} testing-testing1 't)
+ (are [x external-only?] (= x
+ (vec
+ (sort
+ (map (comp str :symbol)
+ (fuzzy-find-matching-vars
+ "testing" *ns*
+ (fn [[k v]]
+ (and (= ((comp :ns meta) v) *ns*)
+ (re-find #"^testing-"
+ (str k))))
+ external-only?)))))
+ ["testing-testing0" "testing-testing1"] nil
+ ["testing-testing0"] true)
+ (finally
+ (try!
+ (ns-unmap *ns* 'testing-testing0)
+ (ns-unmap *ns* 'testing-testing1))))
+
+ (try
+ (create-ns 'testing-testing0)
+ (create-ns 'testing-testing1)
+ (is (= '["testing-testing0" "testing-testing1"]
+ (vec
+ (sort
+ (map (comp str :symbol)
+ (fuzzy-find-matching-nss "testing-"))))))
+ (finally
+ (try!
+ (remove-ns 'testing-testing0)
+ (remove-ns 'testing-testing1))))
+ )
+ )
View
3  swank/swank.clj
@@ -14,7 +14,8 @@
(swank.util.concurrent thread))
(:require (swank.util.concurrent [mbox :as mb])
(swank commands)
- (swank.commands basic indent contrib inspector import)))
+ (swank.commands basic indent completion
+ contrib inspector import)))
(defn ignore-protocol-version [version]
(dosync (ref-set *protocol-version* version)))
View
13 swank/util/java.clj
@@ -0,0 +1,13 @@
+(ns swank.util.java)
+
+(defn method-name [#^java.lang.reflect.Method method]
+ (.getName method))
+
+(defn method-static? [#^java.lang.reflect.Method method]
+ (java.lang.reflect.Modifier/isStatic (.getModifiers method)))
+
+(defn static-methods [#^Class class]
+ (filter method-static? (.getMethods class)))
+
+(defn instance-methods [#^Class class]
+ (remove method-static? (.getMethods class)))
Please sign in to comment.
Something went wrong with that request. Please try again.