(local Object (require :core.object)) (local nrepl (require :plugins.fennel-xl.nrepl)) (local lume (require :plugins.fennel-xl.lume)) (local {: defmethod} (require :plugins.fennel-xl.multimethod)) (local {: restart : submit} (require :plugins.fennel-xl.replsession)) (local Session (Object:extend)) (fn Session.new [self ?handlers] (set self.queue []) (set self.in-progress false) (set self.handlers ?handlers)) (fn Session.init-session [self] (when (nrepl:connected?) (self:do #(nrepl:new-session #(do (set self.session $2) (self:done-msg)) (self:make-handlers)) true))) (fn Session.shutdown-session [self] (set self.queue []) (set self.in-progress false) (set self.session nil)) (fn Session.cleanup-handlers [self] {:status/done #(self:done-msg) :status/interrupted #(self:done-msg)}) (fn Session.make-handlers [self] (lume.merge (or self.handlers {}) (nrepl:chain-handlers [:status/done :status/interrupted] (or self.handlers {}) (self:cleanup-handlers)))) (fn Session.coro-handlers [self coro ?handlers] (lume.merge (or ?handlers {}) (nrepl:chain-handlers [:status/done :status/interrupted] (self:cleanup-handlers) {:status/done #(coroutine.resume coro) :status/interrupted #(coroutine.resume coro)}))) (fn Session.do [self f ?init] (if (or self.in-progress (and (not ?init) (= self.session nil)) ) (table.insert self.queue f) (do (set self.in-progress true) (f)))) (fn Session.done-msg [self] (if (> (length self.queue) 0) ((table.remove self.queue 1)) (set self.in-progress false))) (fn Session.send [self message ?handlers] (self:do #(nrepl:send message ?handlers self.session))) (fn Session.send-oob [self message ?handlers] (local handlers (lume.merge (nrepl:chain-handlers [:status/done :status/interrupted] (or self.handlers {})) (or ?handlers {}))) (nrepl:send message handlers self.session)) (fn Session.eval [self code ?handlers] (self:send {:op :eval : code} ?handlers)) (fn Session.input-handler [self input] {:status/need-input #(self:send-oob {:op :stdin :stdin input})}) (fn Session.eval-input [self code input ?handlers] (self:send {:op :eval : code} (lume.merge (or ?handlers {}) (self:input-handler input)))) (local fennel (require :plugins.fennel-xl.fennel)) (fn parse-vals [s] [s]) ; (let [parser (fennel.parser s)] ; (icollect [ok ast (fennel.parser s)] (if ok ast s)))) (defmethod restart :nrepl (fn [session] (when session.conn (session.conn:shutdown-session)) (set session.conn (Session)) (if (not (nrepl:connected?)) (nrepl:connect {:host session.host :port session.port :on-connect #(session.conn:init-session)}) (session.conn:init-session)) session)) (defmethod submit :nrepl (fn [session chunk callback ?suppress-crash] (session.conn:eval chunk {:out #(callback {:vals [$2]}) :value #(callback {:vals (parse-vals $2)}) :ex #(callback {:err $2})}))) Session