Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next release #14

Merged
merged 9 commits into from
Dec 20, 2024
Merged
6 changes: 5 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: release
on: workflow_dispatch
on:
pull_request:
branches:
- main
types: [closed]

jobs:
tag_and_release:
Expand Down
2 changes: 1 addition & 1 deletion dev/analysis.edn

Large diffs are not rendered by default.

29 changes: 28 additions & 1 deletion doc/elin.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
*elin.txt* A Clojure development environment for Vim/Neovim

Version: 0.0.1
Author : Masashi Iizuka <[email protected]>
License: MIT LICENSE

Expand All @@ -10,6 +9,34 @@ CONTENTS *elin-contents*
Commands |elin-commands|
Mappings |elin-mappings|
Default mappings |elin-default-mappings|
Customizing |elin-customizing|

==============================================================================
CUSTOMIZING *elin-customizing*

*g:elin_auto_connect*
g:elin_server_auto_connect
If `v:true`, automatically connect to Elin server.
Default value is `v:true`.

*g:elin_server_port*
g:elin_server_port
Elin server port number.
If `v:null`, automatically assing a empty port number.
Default value is `v:null`.

*g:elin_enable_default_key_mappings*
g:elin_enable_default_key_mappings
If `v:true`, enable default key mappings.

*g:elin_default_key_mapping_leader*
g:elin_default_key_mapping_leader
Default value is `'<Leader>'`.

*g:elin_enable_omni_completion*
g:elin_enable_omni_completion
If `v:true`, enable omni completion.
Default value is `v:true`.

==============================================================================
vim:tw=78:ts=8:ft=help:norl:noet:fen:fdl=0:
9 changes: 6 additions & 3 deletions plugin/elin.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ endif
let g:loaded_vim_elin = 1

let g:elin_home = expand('<sfile>:p:h:h')
let g:elin_auto_connect = get(g:, 'elin_auto_connect', v:true)
let g:elin_server_auto_connect = get(g:, 'elin_server_auto_connect', v:true)
let g:elin_server_port = get(g:, 'elin_server_port', v:null)
let g:elin_enable_omni_completion = get(g:, 'elin_enable_omni_completion', v:true)

if !exists('g:elin_default_key_mapping_leader')
let g:elin_default_key_mapping_leader = '<Leader>'
Expand All @@ -31,7 +32,7 @@ function! s:init() abort
call elin#server#start()
endif

if g:elin_auto_connect is v:true
if g:elin_server_auto_connect is v:true
call elin#server#connect(g:elin_server_port)
endif

Expand All @@ -40,7 +41,9 @@ function! s:init() abort

aug elin_autocmd_group
au!
au FileType clojure setl omnifunc=elin#complete#omni
if g:elin_enable_omni_completion
au FileType clojure setl omnifunc=elin#complete#omni
endif
au BufEnter *.clj,*.cljs,*.cljc,*.cljd call elin#intercept_notify('BufEnter')
au BufNewFile *.clj,*.cljs,*.cljc,*.cljd call elin#intercept_notify('BufNewFile')
au BufRead *.clj,*.cljs,*.cljc,*.cljd call elin#intercept_notify('BufRead')
Expand Down
8 changes: 7 additions & 1 deletion src/elin/interceptor/connect/shadow_cljs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
:port (some->> file slurp Long/parseLong)})))

(def detect-shadow-cljs-port
"Detect available `shadow-cljs` ports.
If there are multiple port candidates, prompt the user to select one.

When a `shadow-cljs` port is selected and there are multiple build IDs in `shadow-cljs`, prompt the user to select a build ID as well.
The selected build ID will be watched on `shadow-cljs`."
{:kind e.c.interceptor/connect
:enter (-> (fn [{:as ctx :component/keys [host] :keys [hostname port-file]}]
(let [{:keys [default-hostname]} (e.u.interceptor/config ctx #'detect-shadow-cljs-port)
Expand Down Expand Up @@ -64,10 +69,11 @@

:leave (-> (fn [{:as ctx :component/keys [nrepl]}]
(let [{:keys [language port-file]} (e.p.nrepl/current-client nrepl)]
;; When shadow-cljs port is selected
(when (and (= e.c.nrepl/lang-clojurescript language)
(string? port-file)
(str/includes? port-file "shadow-cljs"))

;; Select the build ID
(let [build-id (-> (e.f.evaluate/evaluate-code ctx shadow-cljs-build-ids-code)
(get-in [:response :value])
(edn/read-string)
Expand Down
8 changes: 5 additions & 3 deletions src/elin/interceptor/test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@
[s]
(when s
(try
(with-out-str
(-> (read-string s)
(pp/pprint)))
(let [v (read-string s)]
(if (symbol? v)
s
(with-out-str
(pp/pprint v))))
(catch Exception _
s))))

Expand Down
61 changes: 31 additions & 30 deletions test/elin/function/namespace_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[clojure.test :as t]
[elin.function.clj-kondo :as e.f.clj-kondo]
[elin.function.namespace :as sut]
[elin.function.sexpr :as e.f.sexpr]
[elin.test-helper :as h]))

(t/use-fixtures :once h/malli-instrument-fixture)
Expand All @@ -15,38 +16,38 @@
(sut/get-namespaces elin))))))

(t/deftest missing-candidates-test
(let [elin (-> (h/host-get-namespace-sexpr!-config "(ns test.namespace)")
(h/test-elin))]
(t/testing "missing require"
(t/testing "favorites"
(t/is (= [{:name 'foo.bar.baz :type :ns}]
(->> {:code "foo/bar"
:requiring-favorites '{foo.bar.baz foo}
:java-classes {}}
(sut/missing-candidates elin)))))

(t/testing "non favorites"
(t/testing "clj-kondo"
(t/is (= [{:name 'elin.util.id :type :ns}]
(->> {:code "e.u.id/next-id"
:requiring-favorites {}
(let [elin (h/test-elin)]
(with-redefs [e.f.sexpr/get-namespace (constantly "test.namespace")]
(t/testing "missing require"
(t/testing "favorites"
(t/is (= [{:name 'foo.bar.baz :type :ns}]
(->> {:code "foo/bar"
:requiring-favorites '{foo.bar.baz foo}
:java-classes {}}
(sut/missing-candidates elin)))))

(t/testing "clj-kondo"
(t/is (empty? (->> {:code "unknown/function"
:requiring-favorites {}
:java-classes {}}
(sut/missing-candidates elin)))))))
(t/testing "non favorites"
(t/testing "clj-kondo"
(t/is (= [{:name 'elin.util.id :type :ns}]
(->> {:code "e.u.id/next-id"
:requiring-favorites {}
:java-classes {}}
(sut/missing-candidates elin)))))

(t/testing "clj-kondo"
(t/is (empty? (->> {:code "unknown/function"
:requiring-favorites {}
:java-classes {}}
(sut/missing-candidates elin)))))))

(t/testing "missing import"
(t/is (= [{:name 'clojure.lang.ExceptionInfo :type :class}]
(->> {:code "ExceptionInfo"
:requiring-favorites {}
:java-classes {:clojure.lang #{'ExceptionInfo}}}
(sut/missing-candidates elin))))
(t/testing "missing import"
(t/is (= [{:name 'clojure.lang.ExceptionInfo :type :class}]
(->> {:code "ExceptionInfo"
:requiring-favorites {}
:java-classes {:clojure.lang #{'ExceptionInfo}}}
(sut/missing-candidates elin))))

(t/is (empty? (->> {:code "ExceptionInfo"
:requiring-favorites {}
:java-classes {}}
(sut/missing-candidates elin)))))))
(t/is (empty? (->> {:code "ExceptionInfo"
:requiring-favorites {}
:java-classes {}}
(sut/missing-candidates elin))))))))
47 changes: 29 additions & 18 deletions test/elin/function/sexpr_test.clj
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
(ns elin.function.sexpr-test
(:require
[clojure.core.async :as async]
[clojure.test :as t]
[elin.error :as e]
[elin.function.sexpr :as sut]
[elin.protocol.host :as e.p.host]
[elin.test-helper :as h]
[elin.test-helper.host]))

(t/use-fixtures :once h/malli-instrument-fixture)

(defn- get-namespace-elin
(defn- mock-get-namespace-sexpr!
[ns-form]
(h/test-elin {:host {:get-namespace-sexpr! {:code ns-form :lnum 0 :col 0}}}))
(fn [& _]
(async/go
{:code ns-form :lnum 0 :col 0})))

(t/deftest get-namespace-test
(t/testing "no metadata"
(t/is (= "foo.bar"
(sut/get-namespace (get-namespace-elin "(ns foo.bar)")))))
(let [test-elin (h/test-elin)]
(t/testing "no metadata"
(with-redefs [e.p.host/get-namespace-sexpr! (mock-get-namespace-sexpr! "(ns foo.bar)")]
(t/is (= "foo.bar"
(sut/get-namespace test-elin)))))

(t/testing "with metadata"
(t/is (= "foo.bar"
(sut/get-namespace (get-namespace-elin "(ns ^:meta foo.bar)"))))
(t/is (= "foo.bar"
(sut/get-namespace (get-namespace-elin "(ns ^{:meta true} foo.bar)")))))
(t/testing "with metadata"
(with-redefs [e.p.host/get-namespace-sexpr! (mock-get-namespace-sexpr! "(ns ^:meta foo.bar)")]
(t/is (= "foo.bar"
(sut/get-namespace test-elin))))
(with-redefs [e.p.host/get-namespace-sexpr! (mock-get-namespace-sexpr! "(ns ^{:meta true} foo.bar)")]
(t/is (= "foo.bar"
(sut/get-namespace test-elin)))))

(t/testing "in-ns"
(t/is (= "foo.bar"
(sut/get-namespace (get-namespace-elin "(in-ns 'foo.bar)")))))
(t/testing "in-ns"
(with-redefs [e.p.host/get-namespace-sexpr! (mock-get-namespace-sexpr! "(in-ns 'foo.bar)")]
(t/is (= "foo.bar"
(sut/get-namespace test-elin)))))

(t/testing "no namespace"
(t/is (e/not-found?
(sut/get-namespace (get-namespace-elin "(foo)"))))
(t/is (e/not-found?
(sut/get-namespace (get-namespace-elin ""))))))
(t/testing "no namespace"
(with-redefs [e.p.host/get-namespace-sexpr! (mock-get-namespace-sexpr! "(foo)")]
(t/is (e/not-found?
(sut/get-namespace test-elin))))
(with-redefs [e.p.host/get-namespace-sexpr! (mock-get-namespace-sexpr! "")]
(t/is (e/not-found?
(sut/get-namespace test-elin)))))))
49 changes: 49 additions & 0 deletions test/elin/interceptor/connect/shadow_cljs_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(ns elin.interceptor.connect.shadow-cljs-test
(:require
[clojure.core.async :as async]
[clojure.java.io :as io]
[clojure.test :as t]
[elin.function.select :as e.f.select]
[elin.interceptor.connect.shadow-cljs :as sut]
[elin.protocol.host :as e.p.host]
[elin.test-helper :as h]
[elin.util.file :as e.u.file]))

(t/use-fixtures :once h/malli-instrument-fixture)
(t/use-fixtures :once h/warn-log-level-fixture)

(def ^:private detect-shadow-cljs-port-enter
(:enter sut/detect-shadow-cljs-port))

;; (def ^:private detect-shadow-cljs-port-leave
;; (:leave sut/detect-shadow-cljs-port))

(t/deftest detect-shadow-cljs-port-enter-test
(let [cwd (.getAbsolutePath (io/file "."))
test-elin (h/test-elin)
detect-shadow-cljs-port-enter-test (fn [hostname port-file]
(-> test-elin
(assoc :hostname hostname
:port-file port-file)
(detect-shadow-cljs-port-enter)
(select-keys [:hostname port-file])))]
(t/testing "Positive"
(t/testing "No shadow-cljs port file"
(with-redefs [e.p.host/get-current-working-directory! (fn [& _]
(async/go cwd))
e.f.select/select-from-candidates (fn [_ candidates]
(first candidates))]
(t/is (= {:hostname nil}
(detect-shadow-cljs-port-enter-test nil nil)))))

(t/testing "Exists shadow-cljs port file, but not selected")
(t/testing "Exists shadow-cljs port file, and selected")

(t/testing "Failed to fetch project root directory"
(with-redefs [e.p.host/get-current-working-directory! (fn [& _]
(async/go cwd))
e.u.file/get-project-root-directory (constantly nil)]
(t/is (= {:hostname nil}
(detect-shadow-cljs-port-enter-test nil nil))))))

(t/testing "Negative")))
10 changes: 4 additions & 6 deletions test/elin/test_helper.clj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
(def test-interceptor #'h.interceptor/test-interceptor)

(defn test-elin
"Create a test elin request

e.g. (-> (nrepl-eval-config (constantly 1))
(test-elin))"
([]
(test-elin {}))
([option]
Expand All @@ -69,12 +73,6 @@
(assoc-in config [:nrepl :client :handler] #(when (= "eval" (:op %))
[{:value (f %)}]))))

(defn host-get-namespace-sexpr!-config
([code]
(host-get-namespace-sexpr!-config {} code))
([config code]
(assoc-in config [:host :get-namespace-sexpr!] {:code code :lnum 0 :col 0})))

(defn rand-str
[n]
(let [coll (range 97 123)]
Expand Down
13 changes: 0 additions & 13 deletions test/elin/test_helper/host.clj
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,6 @@
(input! [_ _prompt _default]
nil)

e.p.host/ISexpr
(get-top-list-sexpr! [_ _lnum _col]
(async/go (:get-top-list-sexpr! option)))
(get-list-sexpr! [_ _lnum _col]
(async/go (:get-list-sexpr! option)))
(get-single-sexpr! [_ _lnum _col]
(async/go (:get-single-sexpr! option)))
(get-namespace-sexpr! [_]
(async/go (:get-namespace-sexpr! option)))
(get-namespace-sexpr! [_ _path]
(async/go (:get-namespace-sexpr! option)))
(replace-list-sexpr! [_ _lnum _col _new-sexpr] (async/go nil))

e.p.host/IQuickfix
(set-quickfix-list [_ _qf-list]
(async/go nil))
Expand Down
Loading