diff --git a/error-mode.fnl b/error-mode.fnl new file mode 100644 index 0000000..3aed9d5 --- /dev/null +++ b/error-mode.fnl @@ -0,0 +1,30 @@ +;; This mode has two purposes: +;; * display the stack trace that caused the error +;; * allow the user to decide whether to retry after reloading or quit + +;; Since we can't know which module needs to be reloaded, we rely on the user +;; doing a ,reload foo in the repl. + +(var state nil) + +(local explanation "Press escape to quit. +Press space to return to the previous mode after reloading in the repl.") + +(fn draw [] + (love.graphics.clear 0.34 0.61 0.86) + (love.graphics.setColor 0.9 0.9 0.9) + (love.graphics.print state.msg 10 10) + (love.graphics.print explanation 15 25) + (love.graphics.print state.traceback 15 50)) + +(fn keypressed [key set-mode] + (match key + :escape (love.event.quit) + :space (set-mode state.old-mode))) + +(fn activate [old-mode msg traceback] + (print msg) + (print traceback) + (set state {: old-mode : msg : traceback})) + +{: draw : keypressed : activate} diff --git a/wrap.fnl b/wrap.fnl index e76ac1f..51284ec 100644 --- a/wrap.fnl +++ b/wrap.fnl @@ -1,37 +1,44 @@ -(local repl (require "lib.stdio")) +(local fennel (require :lib.fennel)) +(local repl (require :lib.stdio)) (local canvas (let [(w h) (love.window.getMode)] (love.graphics.newCanvas w h))) (var scale 1) ;; set the first mode -(var mode (require "mode-intro")) +(var (mode mode-name) nil) -(fn set-mode [mode-name ...] - (set mode (require mode-name)) +(fn set-mode [new-mode-name ...] + (set (mode mode-name) (values (require new-mode-name) new-mode-name)) (when mode.activate - (mode.activate ...))) + (match (pcall mode.activate ...) + (false msg) (print mode-name "activate error" msg)))) (fn love.load [] + (set-mode :mode-intro) (canvas:setFilter "nearest" "nearest") (repl.start)) +(fn safely [f] + (xpcall f #(set-mode :error-mode mode-name $ (fennel.traceback)))) + (fn love.draw [] ;; the canvas allows you to get sharp pixel-art style scaling; if you ;; don't want that, just skip that and call mode.draw directly. (love.graphics.setCanvas canvas) (love.graphics.clear) (love.graphics.setColor 1 1 1) - (mode.draw) + (safely mode.draw) (love.graphics.setCanvas) (love.graphics.setColor 1 1 1) (love.graphics.draw canvas 0 0 0 scale scale)) (fn love.update [dt] - (mode.update dt set-mode)) + (when mode.update + (safely #(mode.update dt set-mode)))) (fn love.keypressed [key] (if (and (love.keyboard.isDown "lctrl" "rctrl" "capslock") (= key "q")) (love.event.quit) ;; add what each keypress should do in each mode - (mode.keypressed key set-mode))) + (safely #(mode.keypressed key set-mode))))