(local Object (require :core.object)) (local nrepl (require :link.nrepl)) (local lume (require :lib.lume)) (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))))) (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] (if self.in-progress (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)))) Session