diff --git a/project.clj b/project.clj index f62d905..51de889 100644 --- a/project.clj +++ b/project.clj @@ -5,9 +5,10 @@ :url "http://unlicense.org/UNLICENSE" :distribution :repo} - :dependencies [[org.clojure/clojure "1.5.1"] - [org.clojure/clojurescript "0.0-2202" :scope "provided"] - [org.clojure/google-closure-library "0.0-20140226-71326067" :scope "provided"] + :dependencies [[org.clojure/clojure "1.6.0"] + [org.clojure/clojurescript "0.0-2261" :scope "provided"] + ;;[org.clojure/google-closure-library "0.0-20140226-71326067" :scope "provided"] + ;;[org.clojure/google-closure-library "0.0-20130212-95c19e7f0f5f"] [http-kit "2.1.18"]] :profiles {:dev {:dependencies [[com.cemerick/piggieback "0.1.3"]]}} diff --git a/src/clj/weasel/repl/websocket.clj b/src/clj/weasel/repl/websocket.clj index 3d2c53c..8f9f574 100644 --- a/src/clj/weasel/repl/websocket.clj +++ b/src/clj/weasel/repl/websocket.clj @@ -81,7 +81,7 @@ (binding [*out* (or @repl-out *out*)] (send-for-eval! (cljsc/compile-form-seq '[(ns cljs.user) - (set-print-fn! weasel.repl/repl-print)]))))) + (set-print-fn! @weasel.impls.print/print-fn)]))))) (defn- websocket-setup-env [this] diff --git a/src/cljs/weasel/impls/print.cljs b/src/cljs/weasel/impls/print.cljs new file mode 100644 index 0000000..261defc --- /dev/null +++ b/src/cljs/weasel/impls/print.cljs @@ -0,0 +1,3 @@ +(ns weasel.impls.print) + +(def print-fn (atom (constantly nil))) diff --git a/src/cljs/weasel/repl.cljs b/src/cljs/weasel/repl.cljs index 4ccef67..da91a35 100644 --- a/src/cljs/weasel/repl.cljs +++ b/src/cljs/weasel/repl.cljs @@ -2,7 +2,8 @@ (:require [clojure.browser.event :as event :refer [event-types]] [clojure.browser.net :as net] [cljs.reader :as reader :refer [read-string]] - [weasel.impls.websocket :as ws])) + [weasel.impls.websocket :as ws] + [weasel.impls.print :as wp])) (def ^:private ws-connection (atom nil)) @@ -45,6 +46,7 @@ [repl-server-url & {:keys [verbose on-open on-error on-close] :or {verbose true}}] (let [repl-connection (ws/websocket-connection)] (swap! ws-connection (constantly repl-connection)) + (swap! wp/print-fn (constantly repl-print)) (event/listen repl-connection :opened (fn [evt] diff --git a/src/cljs/weasel/repl/qml.cljs b/src/cljs/weasel/repl/qml.cljs new file mode 100644 index 0000000..25ff028 --- /dev/null +++ b/src/cljs/weasel/repl/qml.cljs @@ -0,0 +1,91 @@ +(ns weasel.repl.qml + (:require + [cljs.reader :as reader :refer [read-string]] + [weasel.impls.print :as wp])) + +(def ^:private ws-connection (atom nil)) + +(defn alive? [] + "Returns truthy value if the REPL is attempting to connect or is + connected, or falsy value otherwise." + (not (nil? @ws-connection))) + +(defmulti process-message :op) + +(defmethod process-message + :error + [message] + (.error js/console (str "Websocket REPL error " (:type message)))) + +(defmethod process-message + :eval-js + [message] + (let [code (:code message)] + {:op :result + :value (try + {:status :success, :value (str (js* "eval(~{code})"))} + (catch js/Error e + {:status :exception + :value (pr-str e) + :stacktrace (if (.hasOwnProperty e "stack") + (.-stack e) + "No stacktrace available.")}) + (catch :default e + {:status :exception + :value (pr-str e) + :stacktrace "No stacktrace available."}))})) + +(defn repl-print + [x] + (if-let [conn @ws-connection] + (.sendTextMessage @ws-connection (pr-str {:op :print :value (pr-str x)})))) + +(def ws-status + {0 :Connecting + 1 :Open + 2 :Closing + 3 :Closed + 4 :Error}) + +(defn connect [qml-parent repl-server-url & {:keys [verbose on-open on-error on-close]}] + "Connects to a Weasel REPL socket at the provided repl-server-url. The underlying implementation +depends on Qt.WebSockets (found in Qt 5.3 or higher). Because this is a Qml object it requires +a non-nil parent object passed in as qml-parent." + (let [repl-connection + (.createQmlObject + js/Qt + (str "import Qt.WebSockets 1.0; WebSocket {url: \"" repl-server-url "\"}") + ;;"import Qt.WebSockets 1.0; WebSocket {}" + qml-parent + "weasel.repl.qml.websocket")] + (swap! ws-connection (constantly repl-connection)) + (swap! wp/print-fn (constantly repl-print)) + (.connect (.-onStatusChanged repl-connection) + (fn [status] + (let [status (ws-status status)] + (cond + (= status :Open) + (do + (.sendTextMessage repl-connection (pr-str {:op :ready})) + (when verbose (.info js/console "Opened Websocket REPL connection")) + (when (fn? on-open) (on-open))) + + (= status :Closed) + (do + (reset! ws-connection nil) + (when verbose (.info js/console "Closed Websocket REPL connection")) + (when (fn? on-close) (on-close))) + + (= status :Error) + (do + (.error js/console "WebSocket error" (.-errorString repl-connection)) + (when (fn? on-error) (on-error (.-errorString repl-connection)))))))) + (.connect (.-onTextMessageReceived repl-connection) + (fn [msg] + (when verbose (.log js/console (str "Received: " msg))) + (let [{:keys [op] :as message} (read-string msg) + response (-> message process-message pr-str)] + (when verbose (.log js/console (str "Sending: " response))) + (.sendTextMessage repl-connection response)))) + (set! (.-active repl-connection) true) + repl-connection))