(local default-port 5000)
(local socket (require :socket))
(local fennel (require :lib.fennel))
(local logging false)
(fn log [message]
(when logging
(let [naughty (require :naughty)]
(naughty.notify {:preset naughty.config.presets.info
:title "REPL"
:text (fennel.view message)}))))
(local state {:client nil :server nil :coro nil})
(set _G.__repl_debug state)
(fn read-chunk [{: stack-size}]
(state.client:send (if (> stack-size 0) ".. " ">> "))
(let [input (coroutine.yield)]
(log (.. :read-chunk: (fennel.view input)))
(.. (table.concat (case (type input) :table input _ [input]) "\t") "\n")))
(fn on-values [vals]
(log (.. :on-values: (table.concat vals "\t")))
(state.client:send (.. "" (table.concat vals "\t") "\n")))
(fn on-error [_errtype err]
(log (.. :on-error: err))
(state.client:send (tostring err)))
(local options {:readChunk read-chunk
:onValues on-values
:onError on-error
:moduleName :fennel
:env _G
:message (string.format
"Welcome to Fennel %s on %s!\nThis repl is running in Awesome %s."
fennel.version _VERSION awesome.version)
:pp fennel.view})
(fn once [fun ...]
(when (not _G.once-table) (set _G.once-table {}))
(when (not (. _G.once-table fun))
(fun ...)
(tset _G.once-table fun true)))
(fn print-in-loop []
(log "Entered loop and listening for server or client"))
(fn loop []
(once print-in-loop)
(local (s r reason) (socket.select [state.server state.client] [] 0))
(when (> (# s) 0)
(log {:send s :rec r :client state.client :reason reason}))
(var ret true)
(each [_ c (ipairs s)]
(match c
state.server
(do
(when state.client
(state.client:shutdown))
(log [:connecting])
(log "Starting Fennel REPL")
(set state.client (state.server:accept))
(set state.coro (coroutine.create (partial fennel.repl)))
(coroutine.resume state.coro options))
state.client
(let [str (state.client:receive :*line)]
(log [:incoming str])
(when str (coroutine.resume state.coro str)))))
true)
(fn start [port?]
(let [port (or port? default-port)]
(set state.server (socket.bind :localhost port))
(if (not state.server)
(log (.. "Couldn't connect to port: " port))
(log (.. "Waiting for Connection on port: " port "\n" (fennel.view state.server))))
(when state.server
(case (require :gears)
gears (do
(log "Starting main loop.")
(gears.timer.start_new (/ 1 60) loop))
nil (log "Couldn't load gears! Repl not starting.")))))
{: start}