Added error handling to lume.hotswap()

Changed lume.hotswap() to return an error and restore the global
environment if an error occurs when requiring the new package
This commit is contained in:
rxi 2014-03-02 17:13:18 +00:00
parent b3773ee57d
commit 3324bb013c
2 changed files with 26 additions and 16 deletions

View File

@ -5,8 +5,8 @@ A collection of functions for Lua, geared towards game development.
## Installation
The [lume.lua](lume.lua?raw=1) file should be dropped into an existing project and
required by it:
The [lume.lua](lume.lua?raw=1) file should be dropped into an existing project
and required by it:
```lua
lume = require "lume"
@ -205,12 +205,14 @@ lume.dostring("print('Hello!')") -- Prints "Hello!"
```
### lume.hotswap(modname)
Reloads an already loaded module in place; `modname` should be the same string
used when loading the module with require(). This function can be used to
immediatly see the effects of code changes without having to restart the
program.
Reloads an already loaded module in place, allowing you to immediatly see the
effects of code changes without having to restart the program. `modname` should
be the same string used when loading the module with require(). In the case of
an error the global environment is restored and `nil` plus an error message is
returned.
```lua
lume.hotswap("lume") -- Reloads the lume module
assert(lume.hotswap("inexistant_module")) -- Raises an error
```
### lume.rgba(color)

View File

@ -229,6 +229,7 @@ end
function lume.hotswap(modname)
local oldglobal = lume.clone(_G)
local updated = {}
local function update(old, new)
if updated[old] then return end
@ -239,18 +240,25 @@ function lume.hotswap(modname)
if type(v) == "table" then update(old[k], v) else old[k] = v end
end
end
local oldglobal = lume.clone(_G)
local oldmod = require(modname)
package.loaded[modname] = nil
local newmod = require(modname)
package.loaded[modname] = oldmod
if type(oldmod) == "table" then update(oldmod, newmod) end
for k, v in pairs(oldglobal) do
if v ~= _G[k] and type(v) == "table" then
update(v, _G[k])
_G[k] = v
end
local err = nil
local function onerror(e)
for k, v in pairs(_G) do _G[k] = oldglobal[k] end
err = lume.trim(e)
end
xpcall(function()
package.loaded[modname] = nil
local newmod = require(modname)
if type(oldmod) == "table" then update(oldmod, newmod) end
for k, v in pairs(oldglobal) do
if v ~= _G[k] and type(v) == "table" then
update(v, _G[k])
_G[k] = v
end
end
end, onerror)
package.loaded[modname] = oldmod
if err then return nil, err end
return oldmod
end