/
completion_snippet.clj
95 lines (91 loc) · 3.62 KB
/
completion_snippet.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
(ns clojure-lsp.feature.completion-snippet
(:require
[clojure-lsp.shared :as shared]
[clojure.string :as string]
[rewrite-clj.zip :as z]
[taoensso.timbre :as log]))
(set! *warn-on-reflection* true)
(defn known-snippets [settings]
[{:label "comment"
:detail "Create comment block"
:insert-text "(comment\n ${0:body}\n )"}
{:label "condp"
:detail "Create condp"
:insert-text "(condp ${1:pred} ${2:expr}\n ${0:clauses})"}
{:label "def"
:insert-text "(def ${1:name} ${0:value})"
:detail "Create def"}
{:label "defmethod"
:detail "Create defmethod"
:insert-text "(defmethod ${1:name} ${2:match}\n [${3:args}]\n $0)"}
{:label "defmulti"
:detail "Create defmulti"
:insert-text "(defmulti ${1:name} ${2:dispatch-fn})"}
{:label "defn-"
:detail "Create private function"
:insert-text (format "(defn%s ${1:name} [$2]\n ${0:body})"
(if (:use-metadata-for-privacy? settings)
" ^:private"
"-"))}
{:label "defn"
:insert-text "(defn ${1:name} [$2]\n ${0:body})"
:detail "Create public function"}
{:label "defprotocol"
:detail "Create defprotocol"
:insert-text "(defprotocol ${1:Name}\n ${0:body})"}
{:label "defrecord"
:detail "Create defrecord"
:insert-text "(defrecord ${1:Name} [${2:fields}]\n ${3:Protocol}\n ${0:body})"}
{:label "deftype"
:detail "Create deftype"
:insert-text "(deftype ${1:Name} [${2:fields}]\n ${3:Protocol}\n ${0:body})"}
{:label "fn"
:detail "Create fn"
:insert-text "(fn [${1:arg-list}] ${0:body})"}
{:label "if"
:detail "Create if"
:insert-text "(if ${1:test-expr}\n ${2:then-expr}\n ${3:else-expr})"}
{:label "import"
:detail "Create import"
:insert-text "(:import [${1:package}])"}
{:label "kwargs"
:detail "Create keyword args"
:insert-text "& {:keys [${1:keys}] :or {${2:defaults}}}"}
{:label "let"
:detail "Create let"
:insert-text "(let [${1:binding} ${2:value}])"}
{:label "letfn"
:detail "Create letfn"
:insert-text "(letfn [(${1:name} [${2:args}]\n ${0:body})])"}
{:label "ns"
:detail "Create ns"
:insert-text "(ns ${1:name}\n ${0:references})"}
{:label "require"
:detail "Create require"
:insert-text "(:require [${1:namespace} :as ${0:alias}])"}
{:label "use"
:detail "Create use"
:insert-text "(:use [${1:namespace} :only [$0]])"}])
(defn ^:private replace-snippets-vars [snippet next-loc]
(let [current-sexpr (or (some-> next-loc z/string)
"")]
(string/replace snippet "$current-form" current-sexpr)))
(defn build-additional-snippets [cursor-loc next-loc settings]
(if (and next-loc (meta (z/node next-loc)))
(->> (get settings :additional-snippets [])
(filter #(or (not (string/includes? (:snippet %) "$current-form"))
(and cursor-loc
next-loc)))
(map (fn [{:keys [name detail snippet]}]
(if (string/includes? snippet "$current-form")
(let [range (shared/->range (meta (z/node next-loc)))]
{:label name
:detail detail
:text-edit {:range (if (= :token (z/tag cursor-loc))
(update-in range [:start :character] - (count (z/string cursor-loc)))
range)
:new-text (replace-snippets-vars snippet next-loc)}})
{:label name
:detail detail
:insert-text (replace-snippets-vars snippet next-loc)}))))
[]))