From e9545833590f7542f3bb6a60c16e4dc647f3fe8b Mon Sep 17 00:00:00 2001 From: Antonin Hildebrand Date: Fri, 7 Oct 2016 18:06:14 +0200 Subject: [PATCH] nrepl: implement Figwheel REPL API bridge --- src/nrepl/dirac/nrepl/controls.clj | 17 +++++++++++++++-- src/nrepl/dirac/nrepl/figwheel.clj | 29 ++++++++++++++++++++--------- src/nrepl/dirac/nrepl/messages.clj | 9 +++++++++ src/nrepl/dirac/nrepl/usage.clj | 26 +++++++++++++++++++++++++- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/nrepl/dirac/nrepl/controls.clj b/src/nrepl/dirac/nrepl/controls.clj index c0dc344713..1961432720 100644 --- a/src/nrepl/dirac/nrepl/controls.clj +++ b/src/nrepl/dirac/nrepl/controls.clj @@ -6,13 +6,15 @@ [dirac.nrepl.compilers :as compilers] [dirac.nrepl.state :as state] [dirac.nrepl.utils :as utils] - [dirac.nrepl.messages :as messages]) + [dirac.nrepl.messages :as messages] + [dirac.nrepl.figwheel :as figwheel]) (:import (java.util.regex Pattern))) ; note: this namespace defines the context where special dirac commands are eval'd (defn error-println [& args] - (apply helpers/error-println args)) + (apply helpers/error-println args) + ::no-result) (defn ^:dynamic warn-about-retargeting-if-needed [session] (if (not= session (state/get-current-session)) @@ -192,6 +194,17 @@ (error-println (messages/make-report-invalid-compilers-not-killed-msg user-input invalid-compiler-ids))))))) ::no-result) +; -- (dirac! :fig) ---------------------------------------------------------------------------------------------------------- + +(defmethod dirac! :fig [_ & [fn-name & args]] + (let [result (apply figwheel/call-repl-api! (or fn-name :fig-status) args)] + (let [response (case result + ::figwheel/not-found (error-println (messages/make-figwheel-api-not-found-msg)) + ::figwheel/not-fn (error-println (messages/make-figwheel-bad-api-msg)) + result)] + (state/send-response! (utils/prepare-current-env-info-response)) + response))) + ; -- default handler -------------------------------------------------------------------------------------------------------- (defmethod dirac! :default [command & _] diff --git a/src/nrepl/dirac/nrepl/figwheel.clj b/src/nrepl/dirac/nrepl/figwheel.clj index 524fe1c6b5..36e5403a83 100644 --- a/src/nrepl/dirac/nrepl/figwheel.clj +++ b/src/nrepl/dirac/nrepl/figwheel.clj @@ -1,19 +1,23 @@ (ns dirac.nrepl.figwheel - "We are friends with Figwheel") + "We are friends with Figwheel" + (:require [clojure.tools.logging :as log])) -(defn try-get-figwheel-api-var [] +; TODO: would be nice to have some version checking (for sanity) + +(defn try-resolve-figwheel-repl-api-symbol [sym] (try - (ns-resolve 'figwheel-sidecar.repl-api '*repl-api-system*) - (catch Throwable _e + (ns-resolve 'figwheel-sidecar.repl-api sym) + (catch Throwable e + (log/trace e) nil))) -(defn get-figwheel-repl-api [] - (when-let [fig-api-var (try-get-figwheel-api-var)] - (assert (var? fig-api-var)) - (var-get fig-api-var))) +(defn try-resolve-figwheel-repl-api [sym] + (let [v (try-resolve-figwheel-repl-api-symbol sym)] + (if (var? v) + (var-get v)))) (defn get-figwheel-system [] - (if-let [api (get-figwheel-repl-api)] + (if-let [api (try-resolve-figwheel-repl-api '*repl-api-system*)] (:figwheel-system api))) (defn get-figwheel-data [] @@ -38,3 +42,10 @@ (defn collect-available-compiler-descriptors [] (let [builds (get-figwheel-builds)] (keep (fn [[_id build]] (make-compiler-descriptor build)) builds))) + +(defn call-repl-api! [fn-name & args] + (if-let [f (try-resolve-figwheel-repl-api (symbol (name fn-name)))] + (if (fn? f) + (apply f args) + ::not-fn) + ::not-found)) diff --git a/src/nrepl/dirac/nrepl/messages.clj b/src/nrepl/dirac/nrepl/messages.clj index 0a5deeaa66..e6a0d77cfe 100644 --- a/src/nrepl/dirac/nrepl/messages.clj +++ b/src/nrepl/dirac/nrepl/messages.clj @@ -102,6 +102,15 @@ (defn ^:dynamic make-retargeting-warning-msg [] (str "You are in a joined Dirac session. This command is being executed as if it was entered in the target session.")) +(defn ^:dynamic make-figwheel-api-not-found-msg [] + (str "Figwheel API not found. Please make sure you have figwheel-sidecar properly installed in your nREPL server:\n" + "=> https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl")) + +(defn ^:dynamic make-figwheel-bad-api-msg [] + (str "Figwheel API found but resolved symbol is not a function.\n" + "Please make sure you are loading the latest Figwheel in your nREPL server.\n" + "=> https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl")) + ; -- joined session --------------------------------------------------------------------------------------------------------- (defn ^:dynamic make-missing-nrepl-message-msg [] diff --git a/src/nrepl/dirac/nrepl/usage.clj b/src/nrepl/dirac/nrepl/usage.clj index af3d043024..23cbccf51c 100644 --- a/src/nrepl/dirac/nrepl/usage.clj +++ b/src/nrepl/dirac/nrepl/usage.clj @@ -23,6 +23,8 @@ " :disjoin -> disjoin Dirac session" " :match -> list matching Dirac sessions" "" + " :fig -> Figwheel REPL API bridge" + "" " :version -> print version info" " :help -> print usage help" "" @@ -154,6 +156,27 @@ don't allow killing them via `(dirac! :kill ...)`. You have to use Figwheel's own interface to manipulate its" " compilers."]) +(def ^:dynamic fig-usage + ["Usage forms:" + "" + " 1. `(dirac! :fig)`" + " 2. `(dirac! :fig api-fn & args)`" + "" + "Call Figwheel REPL API (if present)." + "" + "This is a bridge provided for convenince to allow controlling Figwheel directly from Dirac REPL." + "" + "You may provide api-fn as a string, keyword or symbol. Figwheel API function is resolved dynamically." + "Function arguments must be specified precisely as expected by Figwheel API." + "" + " Examples:" + " `(dirac! :fig :fig-status)` ; <= this is equivalent to `(dirac! :fig)`" + " `(dirac! :fig :print-config)`" + " `(dirac! :fig :build-once \"my-build-id\")`" + "" + "Please refer to Figwheel docs for full list of control functions:" + " => https://github.com/bhauman/lein-figwheel#repl-figwheel-control-functions"]) + ; -- public docs map -------------------------------------------------------------------------------------------------------- (defn render-usage [lines] @@ -170,4 +193,5 @@ :match (render-usage match-usage) :switch (render-usage switch-usage) :spawn (render-usage spawn-usage) - :kill (render-usage kill-usage)}) + :kill (render-usage kill-usage) + :fig (render-usage fig-usage)})