Merge luaML.love
This commit is contained in:
commit
912506614c
|
@ -154,6 +154,94 @@ robust to apps changing out from under it.
|
|||
```
|
||||
Hit F4. The error disappears.
|
||||
|
||||
Driver can connect to app on errors in on.initialize (and `on.load_settings`).
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, define `on.initialize` with a run-time error:
|
||||
```
|
||||
on.initialize = function()
|
||||
foo = bar+1
|
||||
end
|
||||
```
|
||||
Hit F4.
|
||||
Quit the client app and restart. App shows an error.
|
||||
Edit `on.initialize` in the driver and remove the error:
|
||||
```
|
||||
on.initialize = function()
|
||||
end
|
||||
```
|
||||
Hit F4. The error disappears from the app and driver.
|
||||
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, define `on.initialize` with a run-time error:
|
||||
```
|
||||
on.initialize = function()
|
||||
foo = bar+1
|
||||
end
|
||||
```
|
||||
Hit F4.
|
||||
Quit the client app and restart. App shows an error.
|
||||
Hit F4 again in the driver (without fixing the error).
|
||||
The client app continues to show the error.
|
||||
|
||||
Driver can connect to app on errors in `on.quit` (and `on.save_settings`).
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, define `on.quit` with a run-time error:
|
||||
```
|
||||
on.quit = function()
|
||||
foo = bar+1
|
||||
end
|
||||
```
|
||||
Hit F4.
|
||||
Try to quit the client app. It shows an error and refuses to quit.
|
||||
Edit `on.quit` in the driver and remove the error:
|
||||
```
|
||||
on.quit = function()
|
||||
end
|
||||
```
|
||||
Hit F4. The error disappears from the app and driver.
|
||||
Try to quit the client app. Now the quit succeeds.
|
||||
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, define `on.quit` with a run-time error:
|
||||
```
|
||||
on.quit = function()
|
||||
foo = bar+1
|
||||
end
|
||||
```
|
||||
Hit F4.
|
||||
Try to quit the client app. It shows an error and refuses to quit.
|
||||
Hit F4 again in the driver (without fixing the error).
|
||||
Try to quit the client app again. It continues to show the error.
|
||||
|
||||
Driver can connect to app that contains test failures on startup.
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, define a new test with an invalid assertion:
|
||||
```
|
||||
test_foo = function()
|
||||
check(nil, 'foo')
|
||||
end
|
||||
```
|
||||
Hit F4. The test fails.
|
||||
Quit the client app and restart. App shows an error.
|
||||
Edit `test_foo` in the driver and remove the error:
|
||||
```
|
||||
test_foo = function()
|
||||
end
|
||||
```
|
||||
Hit F4. The error disappears from the app and driver.
|
||||
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, define a new test with an invalid assertion:
|
||||
```
|
||||
test_foo = function()
|
||||
check(nil, 'foo')
|
||||
end
|
||||
```
|
||||
Hit F4.
|
||||
Quit the client app and restart. App shows an error.
|
||||
Hit F4 again in the driver (without fixing the error).
|
||||
The client app continues to show the error.
|
||||
|
||||
* clone this repo to a new client app, clear its save dir, run it, run the
|
||||
driver, add a definition containing invalid Lua:
|
||||
```
|
||||
|
|
28
app.lua
28
app.lua
|
@ -14,6 +14,7 @@ local Keys_down = {}
|
|||
function love.run()
|
||||
App.version_check()
|
||||
App.snapshot_love()
|
||||
live.load()
|
||||
-- have LÖVE delegate all handlers to App if they exist
|
||||
for name in pairs(love.handlers) do
|
||||
if App[name] then
|
||||
|
@ -35,15 +36,17 @@ function love.run()
|
|||
end
|
||||
end
|
||||
|
||||
-- Stash current state of App for tests
|
||||
App_for_tests = {}
|
||||
for k,v in pairs(App) do
|
||||
App_for_tests[k] = v
|
||||
end
|
||||
-- there's one nested table
|
||||
App_for_tests.screen = {}
|
||||
for k,v in pairs(App.screen) do
|
||||
App_for_tests.screen[k] = v
|
||||
-- Stash initial state of App (right after loading files) for tests
|
||||
if App_for_tests == nil then
|
||||
App_for_tests = {}
|
||||
for k,v in pairs(App) do
|
||||
App_for_tests[k] = v
|
||||
end
|
||||
-- there's one nested table
|
||||
App_for_tests.screen = {}
|
||||
for k,v in pairs(App.screen) do
|
||||
App_for_tests.screen[k] = v
|
||||
end
|
||||
end
|
||||
-- Mutate App for the real app
|
||||
-- disable test methods
|
||||
|
@ -136,11 +139,14 @@ function love.run()
|
|||
App.run_tests(record_error)
|
||||
-- example handler
|
||||
if #Test_errors > 0 then
|
||||
error('There were test failures:\n\n'..table.concat(Test_errors, '\n'))
|
||||
Mode = 'error'
|
||||
Redo_initialization = true
|
||||
Error_message = 'There were test failures:\n\n'..table.concat(Test_errors, '\n')
|
||||
live.send_run_time_error_to_driver(Error_message)
|
||||
end
|
||||
|
||||
App.initialize_globals()
|
||||
App.initialize(love.arg.parseGameArguments(arg), arg)
|
||||
xpcall(function() App.initialize(love.arg.parseGameArguments(arg), arg) end, live.handle_initialization_error)
|
||||
|
||||
love.timer.step()
|
||||
local dt = 0
|
||||
|
|
32
live.lua
32
live.lua
|
@ -32,8 +32,10 @@ on = {}
|
|||
|
||||
-- === on startup, load all files with numeric prefix
|
||||
|
||||
function live.initialize(arg)
|
||||
live.freeze_all_existing_definitions()
|
||||
function live.load()
|
||||
if Live.frozen_definitions == nil then -- a second run due to initialization errors will contain definitions we don't want to freeze
|
||||
live.freeze_all_existing_definitions()
|
||||
end
|
||||
|
||||
-- version control
|
||||
Live.filenames_to_load = {} -- filenames in order of numeric prefix
|
||||
|
@ -44,8 +46,6 @@ function live.initialize(arg)
|
|||
-- some hysteresis
|
||||
Live.previous_read = 0
|
||||
Live.previous_run_time_error_check_time = 0
|
||||
|
||||
if on.load then on.load() end
|
||||
end
|
||||
|
||||
function live.load_files_so_far()
|
||||
|
@ -80,8 +80,15 @@ function live.update(dt)
|
|||
if Current_time - Live.previous_read > 0.1 then
|
||||
local buf = live.receive_from_driver()
|
||||
if buf then
|
||||
live.run(buf)
|
||||
Mode = 'run'
|
||||
local possibly_mutated = live.run(buf)
|
||||
if possibly_mutated then
|
||||
Mode = 'run'
|
||||
if Redo_initialization then
|
||||
Redo_initialization = nil
|
||||
love.run() -- won't actually replace the event loop;
|
||||
-- we're just running it for its initialization side-effects
|
||||
end
|
||||
end
|
||||
if on.code_change then on.code_change() end
|
||||
end
|
||||
Live.previous_read = Current_time
|
||||
|
@ -137,7 +144,7 @@ function reset_terminal()
|
|||
return '\027[m'
|
||||
end
|
||||
|
||||
-- define or undefine top-level bindings
|
||||
-- returns true if we might have mutated the app, by either creating or deleting a definition
|
||||
function live.run(buf)
|
||||
local cmd = live.get_cmd_from_buffer(buf)
|
||||
assert(cmd)
|
||||
|
@ -166,6 +173,7 @@ function live.run(buf)
|
|||
Live.filename[definition_name] = nil
|
||||
end
|
||||
live.send_to_driver('{}')
|
||||
return true
|
||||
elseif cmd == 'GET' then
|
||||
local definition_name = buf:match('^%s*%S+%s+(%S+)')
|
||||
local val, _ = live.get_binding(definition_name)
|
||||
|
@ -222,17 +230,18 @@ function live.run(buf)
|
|||
if err then
|
||||
-- not possible; perhaps it's a .love file
|
||||
-- try to write to save dir
|
||||
local status, err2 = App.write_file(App.save_dir..filename, buf)
|
||||
local status, err2 = love.filesystem.write(filename, buf)
|
||||
if err2 then
|
||||
-- throw an error
|
||||
live.send_to_driver('ERROR '..tostring(err..'\n\n'..err2))
|
||||
return
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- run all tests
|
||||
Test_errors = {}
|
||||
App.run_tests(record_error_by_test)
|
||||
live.send_to_driver(json.encode(Test_errors))
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -395,6 +404,11 @@ function live.handle_error(err)
|
|||
print(Error_message)
|
||||
end
|
||||
|
||||
function live.handle_initialization_error(err)
|
||||
Redo_initialization = true
|
||||
live.handle_error(err)
|
||||
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"]
|
||||
|
|
10
main.lua
10
main.lua
|
@ -76,8 +76,6 @@ function App.initialize(arg)
|
|||
love.graphics.setBackgroundColor(1,1,1)
|
||||
HUD_font = love.graphics.newFont(HUD_font_height)
|
||||
|
||||
live.initialize(arg)
|
||||
|
||||
if love.filesystem.getInfo('config') then
|
||||
load_settings()
|
||||
else
|
||||
|
@ -264,7 +262,13 @@ end
|
|||
|
||||
function App.keyreleased(key, scancode)
|
||||
if Mode == 'error' then
|
||||
Mode = 'run'
|
||||
if Redo_initialization then
|
||||
Redo_initialization = nil
|
||||
love.run() -- won't actually replace the event loop;
|
||||
-- we're just running it for its initialization side-effects
|
||||
else
|
||||
Mode = 'run'
|
||||
end
|
||||
return
|
||||
end
|
||||
-- ignore events for some time after window in focus (mostly alt-tab)
|
||||
|
|
Loading…
Reference in New Issue