1
0
errors/errors.lua

106 lines
3.3 KiB
Lua

local string_dist
do
local thispath = ... and select('1', ...):match('.+%.') or ''
local function import (name, ignore_failure)
local was_loaded, lib_or_error = pcall(require, thispath..name)
if not was_loaded then
if ignore_failure then return nil end
error('['..thispath..']: Could not load vital library: '..name..'.lua:\n\t'..lib_or_error)
end
return lib_or_error
end
string_dist = import 'string_distance'
end
assert(debug and debug.getinfo)
--------------------------------------------------------------------------------
-- Util
local function format_probable_strings (probable_strings, amount)
assert(type(probable_strings) == 'table')
assert(type(amount) == 'number')
assert(#probable_strings > 0)
local l = {}
for i = 1, math.min(amount, #probable_strings) do
l[#l+1] = probable_strings[i]
l[#l+1] = ', '
end
if l[#l] == ', ' then l[#l] = nil end
if #l >= 3 then l[#l-1] = ' or ' end
return table.concat(l, '')
end
--------------------------------------------------------------------------------
-- Error handler
local ErrorHandler = setmetatable({}, {__call = function (c, ...) return c.new(...) end})
ErrorHandler.__index = ErrorHandler
function ErrorHandler.new (module_name)
return setmetatable({module_name = module_name, registered = {}}, ErrorHandler)
end
function ErrorHandler:register (f)
assert(type(self) == 'table')
assert(type(f) == 'function')
self.registered[f] = true
end
local ERROR_MODES = { ['internal'] = true, ['external'] = true }
function ErrorHandler:getErrorFunc (mode, name)
-- Parameter fixing
local mode = mode or 'internal'
local name = name or (mode == 'external' and '') or mode
if name ~= '' then name = '/'..name end
-- Error checking
assert(ERROR_MODES[mode])
assert(type(name) == 'string')
-- Create error funcs.
if mode == 'internal' then
return function (format_msg, ...)
assert(type(format_msg) == 'string')
return error(('[%s%s]: '..format_msg):format(self.module_name, name, ...), 2)
end
elseif mode == 'external' then
return function (format_msg, ...)
assert(type(format_msg) == 'string')
local level = 2
while self.registered[debug.getinfo(level, 'f').func] do
level = level + 1
end
return error(('[%s%s]: '..format_msg):format(self.module_name, name, ...), level)
end
end
assert(false)
end
function ErrorHandler:attemptCorrection (format_msg, gotten_string, probable_strings)
assert(type(self) == 'table', 'Wow, mister, remember to call with OO notation.')
assert(type(format_msg) == 'string')
assert(type(gotten_string) == 'string')
assert(type(probable_strings) == 'table')
local probable_strings = string_dist.strings_with_highest_similarity(gotten_string, probable_strings)
local list_string = format_probable_strings(probable_strings, 3)
return self:getErrorFunc('internal', '')(format_msg, gotten_string, list_string)
end
function ErrorHandler:__call (format_msg, ...)
return self:getErrorFunc('internal')(format_msg, ...)
end
--------------------------------------------------------------------------------
return {
ErrorHandler = ErrorHandler
}