Skip to content

Commit

Permalink
[c.s.keywords] Improved support for ns-qualified keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-yakushev committed Jul 18, 2015
1 parent a727de4 commit 7a4a8f6
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
38 changes: 32 additions & 6 deletions src/compliment/sources/keywords.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns compliment.sources.keywords
"Completion for keywords interned globally across the application"
(:require [compliment.sources :refer [defsource]]
[compliment.utils :refer [defmemoized]])
[compliment.utils :refer [defmemoized resolve-namespace]])
(:import java.lang.reflect.Field))

(defmemoized ^:private keywords-table
Expand All @@ -10,12 +10,38 @@
(.setAccessible field true)
(.get field nil)))

(defn candidates
[prefix _ _]
(when (= (first prefix) \:)
(defn qualified-candidates
"Returns a list of namespace-qualified double-colon keywords (like ::foo)
resolved for the given namespace."
[prefix ns]
(let [prefix (subs prefix 2)
ns-name (str ns)]
(for [[kw _] (keywords-table)
:when (= (namespace kw) ns-name)
:when (.startsWith (name kw) prefix)]
(str "::" (name kw)))))

(defn aliased-candidates
"Returns a list of alias-qualified double-colon keywords (like ::str/foo),
where alias has to be registered in the given namespace."
[prefix ns]
(let [[_ alias prefix] (re-matches #"::([^/]+)/(.*)" prefix)
alias-ns-name (str (resolve-namespace (symbol alias) ns))]
(for [[kw _] (keywords-table)
:when (.startsWith (str kw) (subs prefix 1))]
(str ":" kw))))
:when (= (namespace kw) alias-ns-name)
:when (.startsWith (name kw) prefix)]
(str "::" alias "/" (name kw)))))

(defn candidates
[^String prefix, ns _]
(let [single-colon? (.startsWith prefix ":")
double-colon? (.startsWith prefix "::")
has-slash? (> (.indexOf prefix "/") -1)]
(cond (and double-colon? has-slash?) (aliased-candidates prefix ns)
double-colon? (qualified-candidates prefix ns)
single-colon? (for [[kw _] (keywords-table)
:when (.startsWith (str kw) (subs prefix 1))]
(str ":" kw)))))

(defsource ::keywords
:candidates #'candidates
Expand Down
13 changes: 12 additions & 1 deletion test/compliment/sources/t_keywords.clj
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@
=> (contains #{":compliment.sources.t-keywords/bar"
":compliment.sources.t-keywords/baz"
":compliment.sources.t-keywords/foo"}
:gaps-ok)))
:gaps-ok))

(fact "namespace-qualified keywords can be completed in the same namespace"
(do (str ::foo ::bar ::baz)
(src/candidates "::ba" *ns* nil))
=> (contains #{"::bar" "::baz"} :gaps-ok))

(fact "namespace-qualified keywords can be completed with an ns alias"
(do (str :compliment.core/aliased-one :compliment.core/aliased-two)
(require '[compliment.core :as core])
(src/candidates "::core/ali" *ns* nil))
=> (contains #{"::core/aliased-two" "::core/aliased-one"} :gaps-ok)))

2 comments on commit 7a4a8f6

@bbatsov
Copy link
Collaborator

@bbatsov bbatsov commented on 7a4a8f6 Sep 2, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess we can cut a new release for this.

@alexander-yakushev
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enjoy;)

Please sign in to comment.