Wrap mode handlers in xpcall+error-mode.
When an error occurs in a mode handler, change to error-mode. Within error-mode, display the traceback and allow the user to exit, (which the default love error handler does) but also allows returning back to the previous mode. The assumption is that this would be done after using the repl to ,reload the module containing the bug which caused the error.
This commit is contained in:
parent
0b04501302
commit
c257139d17
30
error-mode.fnl
Normal file
30
error-mode.fnl
Normal file
|
@ -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}
|
23
wrap.fnl
23
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)]
|
(local canvas (let [(w h) (love.window.getMode)]
|
||||||
(love.graphics.newCanvas w h)))
|
(love.graphics.newCanvas w h)))
|
||||||
|
|
||||||
(var scale 1)
|
(var scale 1)
|
||||||
|
|
||||||
;; set the first mode
|
;; set the first mode
|
||||||
(var mode (require "mode-intro"))
|
(var (mode mode-name) nil)
|
||||||
|
|
||||||
(fn set-mode [mode-name ...]
|
(fn set-mode [new-mode-name ...]
|
||||||
(set mode (require mode-name))
|
(set (mode mode-name) (values (require new-mode-name) new-mode-name))
|
||||||
(when mode.activate
|
(when mode.activate
|
||||||
(mode.activate ...)))
|
(match (pcall mode.activate ...)
|
||||||
|
(false msg) (print mode-name "activate error" msg))))
|
||||||
|
|
||||||
(fn love.load []
|
(fn love.load []
|
||||||
|
(set-mode :mode-intro)
|
||||||
(canvas:setFilter "nearest" "nearest")
|
(canvas:setFilter "nearest" "nearest")
|
||||||
(repl.start))
|
(repl.start))
|
||||||
|
|
||||||
|
(fn safely [f]
|
||||||
|
(xpcall f #(set-mode :error-mode mode-name $ (fennel.traceback))))
|
||||||
|
|
||||||
(fn love.draw []
|
(fn love.draw []
|
||||||
;; the canvas allows you to get sharp pixel-art style scaling; if you
|
;; 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.
|
;; don't want that, just skip that and call mode.draw directly.
|
||||||
(love.graphics.setCanvas canvas)
|
(love.graphics.setCanvas canvas)
|
||||||
(love.graphics.clear)
|
(love.graphics.clear)
|
||||||
(love.graphics.setColor 1 1 1)
|
(love.graphics.setColor 1 1 1)
|
||||||
(mode.draw)
|
(safely mode.draw)
|
||||||
(love.graphics.setCanvas)
|
(love.graphics.setCanvas)
|
||||||
(love.graphics.setColor 1 1 1)
|
(love.graphics.setColor 1 1 1)
|
||||||
(love.graphics.draw canvas 0 0 0 scale scale))
|
(love.graphics.draw canvas 0 0 0 scale scale))
|
||||||
|
|
||||||
(fn love.update [dt]
|
(fn love.update [dt]
|
||||||
(mode.update dt set-mode))
|
(when mode.update
|
||||||
|
(safely #(mode.update dt set-mode))))
|
||||||
|
|
||||||
(fn love.keypressed [key]
|
(fn love.keypressed [key]
|
||||||
(if (and (love.keyboard.isDown "lctrl" "rctrl" "capslock") (= key "q"))
|
(if (and (love.keyboard.isDown "lctrl" "rctrl" "capslock") (= key "q"))
|
||||||
(love.event.quit)
|
(love.event.quit)
|
||||||
;; add what each keypress should do in each mode
|
;; add what each keypress should do in each mode
|
||||||
(mode.keypressed key set-mode)))
|
(safely #(mode.keypressed key set-mode))))
|
||||||
|
|
Loading…
Reference in a new issue