add socket repl
This commit is contained in:
parent
512e8cad2f
commit
4cb82c8ca6
|
@ -0,0 +1,2 @@
|
|||
((fennel-mode .
|
||||
((inferior-lisp-program . "./repl.sh"))))
|
|
@ -28,9 +28,19 @@
|
|||
nix-shell$ overmind connect
|
||||
</pre>
|
||||
|
||||
This starts a fennel interpreter and a test runner in tmux windows.
|
||||
This starts a Fennel interpreter and a test runner in tmux windows.
|
||||
Use <pre>C-b n</pre> to switch between them or <pre>C-b d</pre>
|
||||
to detach.
|
||||
|
||||
<pre>
|
||||
$ fennel dunlin.fnl &
|
||||
$ ./repl.sh
|
||||
</pre>
|
||||
|
||||
Dunlin will open a socket in <tt>$XDG_RUNTIME_DIR</tt> to allow
|
||||
communication with a Fennel REPL. The <tt>repl.sh</tt> script
|
||||
uses <a href="http://www.dest-unreach.org/socat/">socat</a>
|
||||
to connect to it.
|
||||
|
||||
|
||||
</html>
|
||||
|
|
|
@ -10,4 +10,8 @@
|
|||
(f:show-buffer b)
|
||||
(b:visit (.. "file://" (lfs.currentdir) "/doc/index.html")))
|
||||
|
||||
(let [socketdir (or (os.getenv "XDG_RUNTIME_DIR") (os.getenv "HOME"))]
|
||||
((. (require :socket-repl) :start)
|
||||
(.. socketdir "/dunlin.sock")))
|
||||
|
||||
(Gtk.main)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env nix-shell
|
||||
#! nix-shell -p socat --run "socat - unix-connect:${XDG_RUNTIME_DIR-$HOME}/dunlin.sock"
|
|
@ -0,0 +1,71 @@
|
|||
(local { : fdopen } (require "posix.stdio"))
|
||||
(local fcntl (require "posix.fcntl"))
|
||||
(local unistd (require "posix.unistd"))
|
||||
(local socket (require "posix.sys.socket"))
|
||||
(local lgi (require :lgi))
|
||||
|
||||
(local { : GLib } lgi)
|
||||
|
||||
(local { : repl } (require :fennel))
|
||||
|
||||
|
||||
(fn watch-fd [fd mode handler]
|
||||
(let [events [ GLib.IOCondition.IN GLib.IOCondition.HUP]
|
||||
channel (GLib.IOChannel.unix_new fd)]
|
||||
(GLib.io_add_watch channel 0 events #(handler fd))))
|
||||
|
||||
(fn unix-socket-listener [pathname on-connected]
|
||||
(let [sa {:family socket.AF_UNIX
|
||||
:path pathname
|
||||
}
|
||||
fd (socket.socket socket.AF_UNIX socket.SOCK_STREAM 0)]
|
||||
(socket.bind fd sa)
|
||||
(socket.listen fd 5)
|
||||
(watch-fd
|
||||
fd fcntl.O_RDWR
|
||||
#(let [connected-fd (socket.accept $1)]
|
||||
(on-connected connected-fd)))
|
||||
))
|
||||
|
||||
(fn get-input [fd]
|
||||
(let [buf (unistd.read fd 1024)]
|
||||
(if (and buf (> (# buf) 0))
|
||||
buf
|
||||
"\n,exit")))
|
||||
|
||||
(fn start [pathname]
|
||||
(unistd.unlink pathname)
|
||||
(unix-socket-listener
|
||||
pathname
|
||||
(fn [fd]
|
||||
(let [sock (fdopen fd "w+")
|
||||
repl-coro (coroutine.create repl)]
|
||||
(watch-fd fd fcntl.O_RDONLY
|
||||
(fn [fd]
|
||||
(coroutine.resume repl-coro (get-input fd))
|
||||
(if (= (coroutine.status repl-coro) :dead)
|
||||
(do
|
||||
(sock:write "bye!\n")
|
||||
(sock:close)
|
||||
false)
|
||||
true
|
||||
)))
|
||||
(coroutine.resume repl-coro
|
||||
{:readChunk
|
||||
(fn [{: stack-size}]
|
||||
(sock:write
|
||||
(if (> stack-size 0) ".." ">> "))
|
||||
(sock:flush)
|
||||
(coroutine.yield))
|
||||
:onValues
|
||||
(fn [vals]
|
||||
(sock:write (table.concat vals "\t"))
|
||||
(sock:write "\n"))
|
||||
:onError
|
||||
(fn [errtype err]
|
||||
(sock:write
|
||||
(.. errtype " error: " (tostring err) "\n")))
|
||||
})))))
|
||||
|
||||
|
||||
{ : start }
|
Loading…
Reference in New Issue