|
9 | 9 | [cljs.analyzer :as ana]) |
10 | 10 | (:import java.net.URL java.io.File)) |
11 | 11 |
|
12 | | -(defn clean-meta [m] |
| 12 | +(defn- next-row |
| 13 | + "Computes the value of the next row of the distance matrix, based on the |
| 14 | + values from the previous row." |
| 15 | + [pre-row char1 str2] |
| 16 | + (let [init-val [(inc (first pre-row))] |
| 17 | + row (fn [crow [diagonal above char2]] |
| 18 | + (let [dist (if (= char2 char1) diagonal |
| 19 | + (inc (min diagonal above (peek crow))))] |
| 20 | + (conj crow dist)))] |
| 21 | + (reduce row init-val (map vector pre-row (rest pre-row) str2)))) |
| 22 | + |
| 23 | + |
| 24 | +;; Author: PLIQUE Guillaume (Yomguithereal) |
| 25 | +;; Source: https://gist.github.com/vishnuvyas/958488 |
| 26 | +(defn levenshtein |
| 27 | + "Compute the levenshtein distance (a.k.a edit distance) between two strings. |
| 28 | + Informally, the Levenshtein distance between two words is the minimum number |
| 29 | + of single-character edits (i.e. insertions, deletions or substitutions) |
| 30 | + required to change one word into the other" |
| 31 | + [str1 str2] |
| 32 | + (let [first-row (range (inc (count str2)))] |
| 33 | + (peek (reduce #(next-row %1 %2 str2) first-row str1)))) |
| 34 | + |
| 35 | +(defn clean-meta |
| 36 | + "returns a hash-map with only these keys: :ns :name :doc :arglists |
| 37 | + :file :line :macro and updates :ns to a string" |
| 38 | + [m] |
13 | 39 | (when m |
14 | 40 | (-> m |
15 | 41 | (select-keys [:ns :name :doc :arglists :file :line :macro]) |
|
19 | 45 | (defn str-contains? [orig search] |
20 | 46 | (> (.indexOf orig search) -1)) |
21 | 47 |
|
22 | | -(defn format-result [m] |
| 48 | +(defn format-result |
| 49 | + "Returns a hash-map with `:args` as the original `:arglists` value. `:args` is converted to |
| 50 | + a string and dissociated from `:arglists`." |
| 51 | + [m] |
23 | 52 | (when m |
24 | 53 | (-> m |
25 | 54 | (assoc :args (-> m :arglists str)) |
|
34 | 63 | (dissoc :arglists) |
35 | 64 | ))) |
36 | 65 |
|
37 | | -(defn find-doc [search] |
38 | | - (let [ms (concat (mapcat #(sort-by :name (map meta (vals (ns-interns %)))) |
39 | | - (all-ns)))] |
40 | | - (for [m ms |
41 | | - :when (and (:doc m) |
42 | | - (not (:private m)) |
43 | | - (or (str-contains? (:doc m) search) |
44 | | - (str-contains? (str (:ns m)) search) |
45 | | - (str-contains? (str (:name m)) search)))] |
46 | | - (format-result (clean-meta m))))) |
| 66 | +(defn find-doc |
| 67 | + "Look for a var with name `search` among all namespaces. Only public |
| 68 | + vars with docstring are returned. |
| 69 | +
|
| 70 | + Returns a list of metadata (max 30) hash-maps sorted by their levenshtein |
| 71 | + distance with the `search` input." |
| 72 | + [search] |
| 73 | + (let [with-dist #(hash-map :dist (levenshtein search (str (:name %))) |
| 74 | + :meta %) |
| 75 | + all-vars (vals (apply merge (map ns-interns (all-ns)))) |
| 76 | + dist-metas (into [] (comp (map meta) (filter :doc) (remove :private) |
| 77 | + (map clean-meta) (map format-result) |
| 78 | + (map with-dist)) |
| 79 | + all-vars)] |
| 80 | + (take 30 (map :meta (sort-by :dist dist-metas))))) |
47 | 81 |
|
48 | 82 | (def jar-temp-files |
49 | 83 | "Maps jar-url paths to temp files" |
|
0 commit comments