dunlin

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

socket-repl.fnl (2234B)


      1 (local { : fdopen } (require "posix.stdio"))
      2 (local fcntl (require "posix.fcntl"))
      3 (local unistd (require "posix.unistd"))
      4 (local socket (require "posix.sys.socket"))
      5 (local lgi (require :lgi))
      6 
      7 (local { : GLib } lgi)
      8 
      9 (local { : repl } (require :fennel))
     10 
     11 
     12 (fn watch-fd [fd mode handler]
     13   (let [events [ GLib.IOCondition.IN GLib.IOCondition.HUP]
     14         channel (GLib.IOChannel.unix_new fd)]
     15     (GLib.io_add_watch channel 0 events #(handler fd))))
     16 
     17 (fn unix-socket-listener [pathname on-connected]
     18   (let [sa {:family socket.AF_UNIX
     19             :path pathname
     20             }
     21         fd (socket.socket socket.AF_UNIX socket.SOCK_STREAM 0)]
     22     (socket.bind fd sa)
     23     (socket.listen fd 5)
     24     (watch-fd
     25      fd fcntl.O_RDWR
     26      #(let [connected-fd (socket.accept $1)]
     27         (on-connected connected-fd)))
     28     ))
     29 
     30 (fn get-input [fd]
     31   (let [buf (unistd.read fd 1024)]
     32     (if (and buf (> (# buf) 0))
     33         buf
     34         "\n,exit")))
     35 
     36 (fn start [pathname]
     37   (unistd.unlink pathname)
     38   (unix-socket-listener
     39    pathname
     40    (fn [fd]
     41      (let [sock (fdopen fd "w+")
     42            repl-coro (coroutine.create repl)]
     43        (watch-fd fd fcntl.O_RDONLY
     44                  (fn [fd]
     45                    (coroutine.resume repl-coro (get-input  fd))
     46                    (if (= (coroutine.status repl-coro) :dead)
     47                        (do
     48                          (sock:write "bye!\n")
     49                          (sock:close)
     50                          false)
     51                        true
     52                        )))
     53        (coroutine.resume repl-coro
     54                          {:readChunk
     55                           (fn [{: stack-size}]
     56                             (sock:write
     57                              (if (> stack-size 0) ".." ">> "))
     58                             (sock:flush)
     59                             (coroutine.yield))
     60                           :onValues
     61                           (fn [vals]
     62                             (sock:write (table.concat vals "\t"))
     63                             (sock:write "\n"))
     64                           :onError
     65                           (fn [errtype err]
     66                             (sock:write
     67                              (.. errtype " error: " (tostring err) "\n")))
     68                           })))))
     69 
     70 
     71 { : start }