(ns scittle.nrepl (:require [clojure.edn :as edn] [sci.nrepl.completions :refer [completions]] [scittle.core :refer [!last-ns eval-string !sci-ctx]])) (defn nrepl-websocket [] (.-ws_nrepl js/window)) (defn nrepl-reply [{:keys [id session]} payload] (.send (nrepl-websocket) (str (assoc payload :id id :session session :ns (str @!last-ns))))) (defn handle-nrepl-eval [{:keys [code] :as msg}] (let [[kind val] (try [::success (eval-string code)] (catch :default e [::error (str e)]))] (case kind ::success (do (nrepl-reply msg {:value (pr-str val)}) (nrepl-reply msg {:status ["done"]})) ::error (do (nrepl-reply msg {:err (pr-str val)}) (nrepl-reply msg {:ex (pr-str val) :status ["error" "done"]}))))) (defn handle-nrepl-message [msg] (case (:op msg) :eval (handle-nrepl-eval msg) :complete (let [completions (completions (assoc msg :ctx @!sci-ctx))] (nrepl-reply msg completions)))) (defn ws-url [host port path] (str "ws://" host ":" port "/" path)) (let [ws-port (or (.-SCITTLE_NREPL_WEBSOCKET_PORT js/window) 1340)] (set! (.-ws_nrepl js/window) (new js/WebSocket (ws-url "localhost" ws-port "_nrepl")))) (when-let [ws (nrepl-websocket)] (prn :ws ws) (set! (.-onmessage ws) (fn [event] (handle-nrepl-message (edn/read-string (.-data event))))) (set! (.-onerror ws) (fn [event] (js/console.log event))))