Last active
December 10, 2015 23:09
-
-
Save kingtim/4507824 to your computer and use it in GitHub Desktop.
Prototype nrepl middleware for eval-in-emacs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns org.kingtim.eval-in-emacs | |
(:require | |
[clojure.tools.nrepl.transport :as transport] | |
[clojure.tools.nrepl.middleware :refer [set-descriptor!]] | |
[clojure.tools.nrepl.middleware.session :refer [session]] | |
[clojure.tools.nrepl.misc :refer [response-for]]) | |
(:import clojure.tools.nrepl.transport.Transport)) | |
(def transports (atom {})) | |
(defn eval-in-emacs [form] | |
(if-let [t (first @transports)] | |
(do | |
(clojure.tools.nrepl.transport/send (val t) {:eval form}) | |
true))) | |
(defn init-eval-in-emacs [{:keys [session transport] :as msg}] | |
(let [id (-> session meta :id)] | |
(swap! transports assoc id transport) | |
(transport/send transport (response-for msg :status :done)))) | |
(defn eval-result [{:keys [session transport] :as msg}] | |
;; TODO: not implemented yet | |
(transport/send transport (response-for msg :status :done))) | |
(defn add-eval-in-emacs | |
"eval-in-emacs middleware. Returns a handler that supports eval-in-emacs." | |
[h] | |
(fn [{:keys [op] :as msg}] | |
(cond | |
(= op "init-eval") | |
(init-eval-in-emacs msg) | |
(= op "eval-result") | |
(eval-result msg) | |
:else | |
(h msg)))) | |
(set-descriptor! #'add-eval-in-emacs | |
{:requires #{#'session} | |
:handles {"init-eval" {:doc "Initialize eval in emacs"} | |
"eval-result" {:doc "Result from eval (not implemented yet)"}}}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Use nrepl.el from "eval-in-emacs" branch published on github. | |
2. Build the above middleware add add it into your local repository. | |
3. Add the middleware into you project dependencies like so: | |
... | |
:repl-options {:nrepl-middleware | |
[org.kingtim.eval-in-emacs/add-eval-in-emacs]} | |
:profiles {:dev {:dependencies [[org.kingtim/eval-in-emacs "0.1.0-SNAPSHOT"]]}} | |
... | |
4. Connect up to your nrepl server using nrepl-jack-in or your preferred method. | |
The server should now have the eval-in-emacs middleware. | |
You can verify this by evalulating in emacs (nrepl-op-supported-p "init-eval"). Should return t. | |
4. From emacs connected to nrepl mode: M-x nrepl-init-eval-in-emacs | |
This initializes the middleware with the correct transport for the current connection. This was the best way I could find | |
to get ahold of this with the current nrepl server. | |
5. Invoke (org.kingtim.eval-in-emacs/eval-in-emacs form) which will send the form to emacs to be evaled. | |
e.g. (org.kingtim.eval-in-emacs/eval-in-emacs "(with-current-buffer nrepl-nrepl-buffer (insert \"hi\"))") | |
TODO: | |
- Should be controlled on the client side by a variable e.g. nrepl-enable-evaluate-in-emacs | |
- Need to complete round trip so that server side can get results of the eval. I was thinking this could be modeled | |
like the need-input/stdin interactions that currently exist in the nrepl server, with some kind of promise/future that | |
that is fulfilled when the result is delivered. Reference current eval in emacs implementation in swank-clojure and | |
stdin handler in nrepl server. Depends on your use cases. | |
- Possibly need synchronous version as well on the client side. Again, not sure exactly what your use cases require. | |
- Would like a better way of getting a handle on the transport, but that may require changes to the core nrepl server. | |
The other way I was able to do it was by getting a handle on the server and grabbing the transport from there, which | |
I can provide an example of if you are interested. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ah, nice thanks.
Is there a way to inject this from nrepl.el itself?