From dd418aa196228735a350c507cc886c65ec1a6c1b Mon Sep 17 00:00:00 2001 From: Ram Krishnan Date: Sat, 10 Nov 2018 19:50:10 -0800 Subject: [PATCH] Adds support for entering multi-line sexprs in REPL --- lib/stdio.fnl | 38 +++++++++++++++++++++++++++++++------- lib/stdio.lua | 51 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/lib/stdio.fnl b/lib/stdio.fnl index ebccbca..3d2bb67 100644 --- a/lib/stdio.fnl +++ b/lib/stdio.fnl @@ -1,4 +1,5 @@ (require "love.event") +(local fennel (require "lib.fennel")) (local view (require "lib.fennelview")) ;; This module exists in order to expose stdio over a channel so that it @@ -6,14 +7,37 @@ (local (event channel) ...) +(defn display [s] + (io.write s) + (io.flush)) + +(defn prompt [] + (display "\n>> ")) + +(defn read-chunk [] + (let [input (io.read)] + (when input + (.. input "\n")))) + +(var input "") (when channel - (let [prompt (fn [] (io.write "> ") (io.flush) (io.read "*l"))] - ((fn looper [input] - (when input - ;; This is consumed by love.handlers[event] - (love.event.push event input) - (print (: channel :demand)) - (looper (prompt)))) (prompt)))) + (let [(bytestream clearstream) (fennel.granulate read-chunk) + read (fennel.parser + (fn [] + (let [c (or (bytestream) 10)] + (set input (.. input (string.char c))) + c)))] + (while true + (prompt) + (set input "") + (let [(ok ast) (read)] + (if (not ok) + (do + (display (.. "Error:" (view ast) "\n")) + (clearstream)) + (do + (love.event.push event input) + (display (: channel :demand)))))))) {:start (fn start-repl [] (let [code (love.filesystem.read "stdio.fnl") diff --git a/lib/stdio.lua b/lib/stdio.lua index 4640809..633a6a0 100644 --- a/lib/stdio.lua +++ b/lib/stdio.lua @@ -1,22 +1,51 @@ require("love.event") +local fennel = require("lib.fennel") local view = require("lib.fennelview") local event, channel = ... +local function display(s) + io.write(s) + return io.flush() +end +do local _ = display end +local function prompt() + return display("\n>> ") +end +do local _ = prompt end +local function read_chunk() + local input = io.read() + if input then + return (input .. "\n") + end +end +do local _ = read_chunk end +local input = "" local function _0_(...) if channel then + local bytestream, clearstream = fennel.granulate(read_chunk) local function _0_() - io.write("> ") - io.flush() - return io.read("*l") + local c = (bytestream() or 10) + input = (input .. string.char(c)) + return c end - local prompt = _0_ - local function looper(input) - if input then - love.event.push(event, input) - print(channel:demand()) - return looper(prompt()) + local read = fennel.parser(_0_) + while true do + prompt() + input = "" + do + local ok, ast = read() + local function _1_(...) + if not ok then + display(("Error:" .. view(ast) .. "\n")) + return clearstream() + else + love.event.push(event, input) + return display(channel:demand()) + end + end + _1_(...) end end - return looper(prompt()) + return nil end end _0_(...) @@ -47,4 +76,4 @@ local function start_repl() love.handlers.eval = _2_ return nil end -return ({start = start_repl}) +return {start = start_repl}