-- love.run: main entrypoint function for LÖVE -- -- Most apps can just use the default shown in https://love2d.org/wiki/love.run, -- but we need to override it to: -- * recover from errors (by switching to the source editor) -- * run all tests (functions starting with 'test_') on startup, and -- * save some state that makes it possible to switch between the main app -- and a source editor, while giving each the illusion of complete -- control. function love.run() Version, Major_version = App.love_version() App.snapshot_love() -- Tests always run at the start. App.run_tests_and_initialize() --? print('==') love.timer.step() local dt = 0 return function() if love.event then love.event.pump() for name, a,b,c,d,e,f in love.event.poll() do if name == "quit" then if not love.quit or not love.quit() then return a or 0 end end xpcall(function() love.handlers[name](a,b,c,d,e,f) end, handle_error) end end dt = love.timer.step() xpcall(function() App.update(dt) end, handle_error) love.graphics.origin() love.graphics.clear(love.graphics.getBackgroundColor()) xpcall(App.draw, handle_error) love.graphics.present() love.timer.sleep(0.001) end end function handle_error(err) local callstack = debug.traceback('', --[[stack frame]]2) Error_message = 'Error: ' .. tostring(err)..'\n'..cleaned_up_callstack(callstack) print(Error_message) if Current_app == 'run' then Settings.current_app = 'source' love.filesystem.write('config', json.encode(Settings)) load_file_from_source_or_save_directory('main.lua') App.undo_initialize() App.run_tests_and_initialize() else -- abort without running love.quit handler Disable_all_quit_handlers = true love.event.quit() end end -- I tend to read code from files myself (say using love.filesystem calls) -- rather than offload that to load(). -- Functions compiled in this manner have ugly filenames of the form [string "filename"] -- This function cleans out this cruft from error callstacks. function cleaned_up_callstack(callstack) local frames = {} for frame in string.gmatch(callstack, '[^\n]+\n*') do local line = frame:gsub('^%s*(.-)\n?$', '%1') local filename, rest = line:match('([^:]*):(.*)') local core_filename = filename:match('^%[string "(.*)"%]$') -- pass through frames that don't match this format -- this includes the initial line "stack traceback:" local new_frame = (core_filename or filename)..':'..rest table.insert(frames, new_frame) end -- the initial "stack traceback:" line was unindented and remains so return table.concat(frames, '\n\t') end -- The rest of this file wraps around various LÖVE primitives to support -- automated tests. Often tests will run with a fake version of a primitive -- that redirects to the real love.* version once we're done with tests. -- -- Not everything is so wrapped yet. Sometimes you still have to use love.* -- primitives directly. App = {} function App.love_version() local major_version, minor_version = love.getVersion() local version
Copyright (c) 2020, Andinus <andinus@nand.sh>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.