From 856d6400f5d0802f4b75881e019be2de3cbecfc6 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 11 Apr 2021 14:08:57 -0400 Subject: [PATCH] Refactor inspector to use multimethods, generalize picking best one --- editor/repl.fnl | 45 +++--------------------------- inspector/init.fnl | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 41 deletions(-) create mode 100644 inspector/init.fnl diff --git a/editor/repl.fnl b/editor/repl.fnl index 36eef94..90cd3f1 100644 --- a/editor/repl.fnl +++ b/editor/repl.fnl @@ -3,50 +3,13 @@ (local style (require :core.style)) (local lume (require :lib.lume)) (local {: textbutton} (util.require :editor.imstate)) - +(local {: inspect} (util.require :inspector)) (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) - (if (and (= (type v) :table) (not= (next v) nil)) - (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] +(fn repl.inspector [{: vals : states} 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)))) + (set h (+ h (inspect (. states i) v view x (+ y h) view.size.x)))) (+ h style.padding.y)) (fn repl.notify [listeners line] @@ -55,7 +18,7 @@ (fn repl.mk-result [vals] (local inspector #(repl.inspector $...)) - {:draw inspector : vals :state {}}) + {:draw inspector : vals :states (icollect [_ (ipairs vals)] {})}) (fn repl.run [{: listeners}] (fennel.repl {:readChunk coroutine.yield diff --git a/inspector/init.fnl b/inspector/init.fnl new file mode 100644 index 0000000..9d83900 --- /dev/null +++ b/inspector/init.fnl @@ -0,0 +1,68 @@ +(local util (require :lib.util)) +(local style (require :core.style)) +(local {: defmulti : defmethod} (util.require :lib.multimethod)) +(local {: textbutton} (util.require :editor.imstate)) + +(local inspector (util.hot-table ...)) + +(fn inspector.best-inspector [v] + (var best-inspector nil) + (var best-priority -1) + (each [inspector {: priority : predicate} (pairs inspector.inspectors)] + (when (and (> priority best-priority) (predicate v)) + (set best-inspector inspector) + (set best-priority priority))) + best-inspector) + +(set inspector.inspect + (defmulti (fn [state value view x y w] + (when (= state.inspector nil) + (set state.inspector (inspector.best-inspector value))) + state.inspector) :inspect ...)) + +(fn inspector.register [name priority predicate inspect-func] + (when (= inspector.inspectors nil) + (set inspector.inspectors {})) + (tset inspector.inspectors name {: predicate : priority :inspector inspect-func}) + (defmethod inspector.inspect name inspect-func)) + +(fn inspector.text-height [text ?font] + (let [font (or ?font style.code_font) + (_ newlines) (text:gsub "\n" "\n")] + (* (font:get_height) (+ newlines 1)))) + +(fn inspector.draw-text [font text x y color] + (renderer.draw_text font text x y color) + (inspector.text-height text)) + +(inspector.register :default 0 #true (fn [state value view x y w] + (inspector.draw-text style.code_font (fv value) x y style.text))) + +(inspector.register :table 10 + #(and (= (type $1) :table) (not= (next $1) nil)) + (fn [state tbl view x y w] + (local font style.code_font) + (var h 0) + ; todo: state assumes an .inspector key + ; todo: inspector swapping + ; todo: edit in place? + (fn get-kstate [tbl k state] + (when (= nil state.keys) (set state.keys {})) + (when (= nil (?. state.keys k)) + (util.nested-tset state [:keys k] {:collapsed (= (type (. tbl k)) :table) :children {}})) + (. state.keys k)) + (each [k v (pairs tbl)] + (let [kstate (get-kstate tbl k 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 + (inspector.draw-text font "..." (+ x xoffset) (+ y h) style.syntax.comment) + (inspector.inspect kstate.children v view (+ x xoffset) (+ y h) (- w xoffset)))] + (when toggle-collapse (set kstate.collapsed (not kstate.collapsed))) + (set h (+ h hv style.padding.y)))) + h)) + +inspector.hot +