commit 798dd9ed5c9d46f7e7a21bc68182a4c9562d6d25
parent 03b32ffa7e11e1f65ce197a2b3083bb7b761f0d4
Author: Daniel Barlow <dan@telent.net>
Date: Fri, 1 Jul 2022 22:28:41 +0100
fennel repl on a unix socket
Diffstat:
4 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
@@ -25,6 +25,13 @@ As of 2022 these principles are more aspirational than actual.
is suboptimally hairy, at least for the moment: Nix makes a wrapper
script for the Lua executable that has appropriate `LUA_PATH` and
`LUA_CPATH` settings, but it doesn't do the same for kiwmi.
+## Connecting to the repl
+
+If you are using the example rc.fnl, it opens a Unix socket that you
+can connect to and interact with a Fennel REPL. I use
+[socat](http://www.dest-unreach.org/socat/) for this purpose:
+
+ $ socat - unix-connect:${XDG_RUNTIME_DIR}/kiwmi-repl.wayland-1.socket
# TODO
diff --git a/rc.fnl b/rc.fnl
@@ -1,7 +1,16 @@
(local { : GdkPixbuf } (require :lgi))
(local { : view } (require :fennel))
+(local socket-repl (require :socket-repl))
+(let [repl-socket-name
+ (..
+ (: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "")
+ "/kiwmi-repl."
+ (os.getenv "WAYLAND_DISPLAY")
+ ".socket"
+ )]
+ (socket-repl.start repl-socket-name))
(fn texture-from-file [renderer filename]
diff --git a/shell.nix b/shell.nix
@@ -1,7 +1,7 @@
with import <nixpkgs> {} ;
let p = callPackage ./. {};
in (p.overrideAttrs (o:{
- nativeBuildInputs = [pkgs.gdb];
+ nativeBuildInputs = with pkgs; [gdb socat];
shellHook = ''
export LUA_PATH=`lua -e 'print(package.path)'`
export LUA_CPATH=`lua -e 'print(package.cpath)'`
diff --git a/socket-repl.fnl b/socket-repl.fnl
@@ -0,0 +1,52 @@
+(local { : fdopen } (require "posix.stdio"))
+(local fcntl (require "posix.fcntl"))
+(local unistd (require "posix.unistd"))
+(local socket (require "posix.sys.socket"))
+(local { : repl } (require :fennel))
+
+(fn watch-fd [fd mode handler]
+ (kiwmi:event_loop_add_fd fd mode handler))
+
+(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 start [pathname]
+ (print pathname)
+ (unistd.unlink pathname)
+ (unix-socket-listener
+ pathname
+ (fn [fd]
+ (let [sock (fdopen fd "w+")
+ repl-coro (coroutine.create repl)]
+ (print :fd fd :sock sock)
+ (watch-fd fd fcntl.O_RDONLY
+ #(coroutine.resume repl-coro (unistd.read $1 1024)))
+ (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 }