(local util (require :lib.util)) (local fennel (require :lib.fennel)) (local style (require :core.style)) (local lume (require :lib.lume)) (local {: textbutton} (util.require :editor.imstate)) (local repl (util.hot-table ...)) (fn repl.text-height [text ?font] (let [font (or ?font style.code_font) (_ newlines) (text:gsub "\n" "\n")] (* (font:get_height) (+ newlines 1)))) (fn get-state [tbl k depth state] (when (= nil (. state k)) (tset state k {:collapsed (= (type (. tbl k)) :table) :children {}})) (. state k)) (fn repl.inspect-table [tbl view x y w depth state] (local font style.code_font) (var h 0) (each [k v (pairs tbl)] (let [kstate (get-state tbl k depth state) kstr (fv k) wk (font:get_width kstr) xoffset (+ wk style.padding.x) toggle-collapse (textbutton view kstr x (+ y h)) hv (if kstate.collapsed (do (renderer.draw_text font "..." (+ x xoffset) (+ y h) style.syntax.comment) (font:get_height)) (repl.inspect v view (+ x xoffset) (+ y h) (- w xoffset) (+ depth 1) kstate.children))] (when toggle-collapse (tset (. state k) :collapsed (not kstate.collapsed))) (set h (+ h hv style.padding.y)))) h) (fn repl.inspect-default [v view x y w depth state] (renderer.draw_text style.code_font (fv v) x y style.text) (repl.text-height (fv v))) (fn repl.inspect [v view x y w depth state] (if (> w 0) (match (type v) :table (repl.inspect-table v view x y w depth state) _ (repl.inspect-default v view x y w depth state)) 0)) (fn repl.inspector [{: vals : state} view x y] (var h 0) (each [i v (ipairs vals)] (set h (+ h (repl.inspect v view x (+ y h) view.size.x 1 state)))) (+ h style.padding.y)) (fn repl.notify [listeners line] (each [_ listener (ipairs listeners)] (listener:append line))) (fn repl.mk-result [vals] (local inspector #(repl.inspector $...)) {:draw inspector : vals :state {}}) (fn repl.run [{: listeners}] (fennel.repl {:readChunk coroutine.yield :onValues #(repl.notify listeners (repl.mk-result $1)) :onError (fn [errType err luaSource] (repl.notify listeners (repl.mk-result [err]))) :pp #$1 :env (lume.clone _G)})) (fn repl.listen [{: listeners} listener] (table.insert listeners listener)) (fn repl.unlisten [{: listeners} listener] (lume.remove listeners listener)) (fn repl.submit [{: coro} chunk] (coroutine.resume coro (.. chunk "\n"))) (fn repl.new [] (local result {:listeners [] :listen #(repl.listen $...) :unlisten #(repl.unlisten $...) :submit #(repl.submit $...) :coro (coroutine.create repl.run)}) (coroutine.resume result.coro result) result) repl.hot