Skip to content

Commit

Permalink
Improve require/import completion support
Browse files Browse the repository at this point in the history
Tutkain now also offers completions in these cases:

- (require 'c)
- (import 'j)
  • Loading branch information
eerohele committed Feb 20, 2024
1 parent 87ca18c commit 099933b
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Clojure (Tutkain).sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ contexts:
quote:
- match: '(''){{whitespace}}(?![\(\[\{])'
captures:
1: keyword.operator.macro.clojure
1: keyword.operator.macro.clojure meta.quote.clojure
push:
- include: forms
- match: ''
Expand Down
30 changes: 30 additions & 0 deletions clojure/repl/completions.repl
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,33 @@

(xr/check! (partial set/subset? #{{:trigger "Date" :type :class}
{:trigger "Deque" :type :class}}))

;; require without braces
(completions
{:prefix "c"
:ns "user"
:enclosing-sexp "(require )"
:start-line 1
:start-column 1
:line 1
:column 10})

(xr/check!
(spec/and
(prefixed-candidates ::specs/ns-completions "c")
(partial not-any? (comp #{:snippet} :completion-type))))

;; import without parens
(completions
{:prefix "j"
:ns "user"
:enclosing-sexp "(import )"
:start-line 1
:start-column 1
:line 1
:column 10})

(xr/check!
(spec/and
(prefixed-candidates ::specs/class-completions "j")
(partial not-any? (comp #{:snippet} :completion-type))))
18 changes: 16 additions & 2 deletions clojure/src/tutkain/completions.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -551,8 +551,15 @@
[loc prefix]
;; When e.g. [clojure.set :refer []], suggest vars in clojure.set.
(let [node (some-> loc zip/node)]
(if (= :refer (second node))
(cond
(and (sequential? node) (= :refer (second node)))
(candidates-for-prefix prefix (ns-public-var-candidates (first node)))

;; require without braces (e.g. (require 'foo.bar))
(= '(require) node)
(candidates-for-prefix prefix (ns-candidates))

:else
(map (fn [{:keys [trigger] :as candidate}]
(case trigger
"clojure.test"
Expand All @@ -569,10 +576,17 @@
(defn import-completions
[loc prefix]
(let [head (some-> loc zip/node first)]
(if (symbol? head)
(cond
;; import without parens (e.g. (import 'foo.bar.Baz))
(= 'import head)
(class-candidates prefix)

(symbol? head)
(map (fn [candidate]
(update candidate :trigger (fn [trigger] (-> trigger (string/split #"\.") (last)))))
(class-candidates (str (name head) "." prefix)))

:else
(map
(fn [{:keys [trigger] :as candidate}]
(let [parts (string/split trigger #"\.")
Expand Down
12 changes: 10 additions & 2 deletions src/completions.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,15 @@ def enclosing_sexp_sans_prefix(view, expr, prefix):
The prefix is unlikely to resolve, so we must remove it from the
S-expression to be able to analyze it on the server.
"""
before = sublime.Region(expr.open.region.begin(), prefix.begin())

# If the character preceding the prefix is a quote, strip it, because e.g.
# (require ') is a syntax error.
if view.match_selector(prefix.begin() - 1, "meta.quote.clojure"):
begin = prefix.begin() - 1
else:
begin = prefix.begin()

before = sublime.Region(expr.open.region.begin(), begin)
after = sublime.Region(prefix.end(), expr.close.region.end())
return view.substr(before) + view.substr(after)

Expand Down Expand Up @@ -122,7 +130,7 @@ def get_completions(view, prefix, point):
if (
view.match_selector(
preceding_point,
"source.clojure & (meta.symbol - meta.function.parameters - entity.name) | constant.other.keyword",
"source.clojure & (meta.symbol - meta.function.parameters - entity.name) | constant.other.keyword | keyword.operator.macro",
)
and (dialect := dialects.for_point(view, preceding_point))
and (client := state.get_client(view.window(), dialect))
Expand Down

0 comments on commit 099933b

Please sign in to comment.