Skip to content

Instantly share code, notes, and snippets.

@timothypratley
Last active December 14, 2024 07:00
Show Gist options
  • Save timothypratley/100697670eacde2ad429fddb795fdcb9 to your computer and use it in GitHub Desktop.
Save timothypratley/100697670eacde2ad429fddb795fdcb9 to your computer and use it in GitHub Desktop.
(ns scicloj.kindly-render.nrepl.cursive-kindly-render-middleware
(:require [nrepl.middleware :as middleware]
[nrepl.transport :as t]
[nrepl.middleware.interruptible-eval :as eval]
[nrepl.middleware.print :as print])
(:import (nrepl.transport Transport)))
(defn eval*
"Returns a wrapping map with metadata information"
[form]
(let [value (clojure.core/eval form)]
{:value value
:meta (meta value)
:print-meta (boolean *print-meta*)
:form-meta (meta form)
::print/keys #{:value :meta :print-meta :form-meta}}))
(defn unwrap-value
"Collapses the extra fields into msg"
[msg]
(if (and (contains? msg :value)
(map? (:value msg))
(contains? (:value msg) ::print/keys))
(merge msg (:value msg))
msg))
(defn unwrapping-transport [transport]
(reify Transport
(recv [this] (t/recv transport))
(recv [this timeout] (t/recv transport timeout))
(send [this msg] (t/send transport (unwrap-value msg)))))
(defn eval-with-meta
"A handler that adds metadata information into the msg result of eval ops"
[{:as req :keys [transport]}]
(assoc req
:eval `eval*
:transport (unwrapping-transport transport)))
;; the middleware
(defn wrap-with-meta
[handle]
(fn [msg]
(handle (eval-with-meta msg))))
;; It's important that we wrap in the right place
;; The transport wrapping trick has to wrap transport before print/wrap-print
;; :eval needs to be added before interruptible-eval.
(middleware/set-descriptor! #'wrap-with-meta
{:requires #{#'print/wrap-print}
:expects #{#'eval/interruptible-eval}
:handles {}})
;; Testing middleware mayhem
(comment
(require '[nrepl.server :as server])
(def server (server/start-server :port 7888
:handler (server/default-handler #'wrap-with-meta)))
(require '[nrepl.core :as nrepl])
(with-open [conn (nrepl/connect :port 7888)]
(-> (nrepl/client conn 1000)
(nrepl/message {:op "eval"
:code "^{:kindly/kind :kind/map}{:hi 'there}"})
(vec)))
(server/stop-server server))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment