112 lines
3.6 KiB
Fennel
112 lines
3.6 KiB
Fennel
(local core (require :core))
|
|
(local socket (require :socket))
|
|
(local bencode (require :lib.bencode))
|
|
(local lume (require :lib.lume))
|
|
|
|
(fn contains? [tbl item]
|
|
(or (= tbl item) (lume.find tbl item)))
|
|
|
|
(local nrepl
|
|
{:active-requests {}
|
|
:session-handlers {}
|
|
:default-handlers
|
|
{:out #(core.log $2)
|
|
:value #(core.log $2)
|
|
:ex #(core.err $2)
|
|
:status/interrupted #($1:done $3.id)
|
|
:status/done #($1:done $3.id)}
|
|
:merge-handlers
|
|
(fn [self message]
|
|
(lume.merge self.default-handlers
|
|
(or (. self.session-handlers message.session) {})
|
|
(or (. self.active-requests message.id) {})))
|
|
:chain-handlers
|
|
(fn [self keys ...]
|
|
(local new-handlers {})
|
|
(each [_ key (ipairs keys)]
|
|
(each [_ handlers (ipairs [self.default-handlers ...])]
|
|
(local next-handler (. handlers key))
|
|
(local prev-handler (. new-handlers key))
|
|
(if (and next-handler prev-handler)
|
|
(tset new-handlers key
|
|
#(do (prev-handler $1 $2 $3) (next-handler $1 $2 $3)))
|
|
next-handler
|
|
(tset new-handlers key next-handler))))
|
|
new-handlers)
|
|
:counter 1
|
|
:input ""
|
|
:parse-input
|
|
(fn [self]
|
|
(match (pcall #(bencode.decode self.input))
|
|
(true val len)
|
|
(do (set self.input (self.input:sub (+ len 1)))
|
|
val)
|
|
(false :Incomplete) nil
|
|
(false _)
|
|
(do (set self.input "")
|
|
nil)))
|
|
:receive
|
|
(fn [self]
|
|
(when self.connection
|
|
(local (data err part) (self.connection:receive "*a"))
|
|
(local response (or data part))
|
|
(when (> (response:len) 0)
|
|
(set self.input (.. self.input response)))
|
|
(match (self:parse-input) nil nil
|
|
input (self:handle input))
|
|
(when (= err :closed)
|
|
(self:disconnect))))
|
|
:send
|
|
(fn [self msg ?handlers ?session]
|
|
(when self.connection
|
|
(when (not msg.id)
|
|
(set msg.id self.counter)
|
|
(set self.counter (+ self.counter 1)))
|
|
(when (not msg.session)
|
|
(set msg.session (or ?session self.default-session)))
|
|
(when ?handlers
|
|
(tset self.active-requests msg.id ?handlers))
|
|
(self.connection:send (bencode.encode msg))))
|
|
:done
|
|
(fn [self msg-id]
|
|
(tset self.active-requests msg-id nil))
|
|
:handle
|
|
(fn [self response]
|
|
(pp response)
|
|
(local handlers (self:merge-handlers response))
|
|
(each [prop handler (pairs handlers)]
|
|
(local idiv (prop:find :/))
|
|
(local key (if idiv (prop:sub 1 (- idiv 1)) prop))
|
|
(when (and (. response key)
|
|
(or (= idiv nil)
|
|
(contains? (. response key) (prop:sub (+ idiv 1)))))
|
|
(handler self (. response key) response))))
|
|
:disconnect
|
|
(fn [self]
|
|
(when self.connection
|
|
(self.connection:close)
|
|
(set self.connection nil)
|
|
(set self.default-session nil)
|
|
(set self.active-requests {})
|
|
(set self.session-handlers {})))
|
|
:connect
|
|
(fn [self ?port ?host]
|
|
(when (not self.connection)
|
|
(local (port host) (values (or ?port 7888) (or ?host :localhost)))
|
|
(set self.connection (assert (socket.connect host port)))
|
|
(self.connection:settimeout 0)
|
|
(core.add_thread #(while true (self:receive) (coroutine.yield)) self)
|
|
(self:send {:op :clone}
|
|
{:new-session #(set self.default-session $2)})))
|
|
:connected?
|
|
(fn [self] (not= self.default-session nil))
|
|
:new-session
|
|
(fn [self callback ?handler]
|
|
(self:send {:op :clone}
|
|
{:new-session
|
|
(fn [self session message]
|
|
(tset self.session-handlers session ?handler)
|
|
(callback self session message))}))})
|
|
|
|
nrepl
|