2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
-- Check for possible loading errors
|
|
|
|
|
2017-06-11 16:09:24 +00:00
|
|
|
local string_dist
|
|
|
|
do
|
2017-06-27 11:50:27 +00:00
|
|
|
local thispath = ... and (...):match('.+%.') or ''
|
2017-06-11 16:09:24 +00:00
|
|
|
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
|
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
if not debug then
|
|
|
|
error('[errors/loading]: Expected the debug library to be available in _G.')
|
|
|
|
elseif not debug.getinfo then
|
|
|
|
error('[errors/loading]: Expected debug.getinfo to be available in the debug library.')
|
|
|
|
end
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Constants
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
local DEFAULT_ERROR_MSG_NORMAL = 'Unknown error occured'
|
|
|
|
local DEFAULT_ERROR_MSG_INTERNAL = 'Unknown internal error occured'
|
|
|
|
local DEFAULT_ERROR_MSG_CORRECT = 'Unexpected input "%s", maybe you meant %s?'
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-11 16:09:24 +00:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Util
|
|
|
|
|
|
|
|
local function format_probable_strings (probable_strings, amount)
|
|
|
|
assert(type(probable_strings) == 'table')
|
|
|
|
assert(#probable_strings > 0)
|
2017-06-27 11:50:27 +00:00
|
|
|
assert(type(amount) == 'number')
|
2017-06-11 16:09:24 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2017-06-09 13:22:25 +00:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
local function internal_error (self, module_suffix, format_msg, ...)
|
|
|
|
-- internal_error(error_handler, module_suffix [, format_msg, ...])
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
-- Error check
|
|
|
|
assert(type(self) == 'table' and self.is_error_handler)
|
|
|
|
assert(type(module_suffix) == 'string')
|
|
|
|
format_msg = format_msg or DEFAULT_ERROR_MSG_NORMAL
|
|
|
|
assert(type(format_msg) == 'string')
|
|
|
|
-- Format
|
|
|
|
return error(('[%s%s]: '..format_msg):format(self.module_name, module_suffix, ...), 3)
|
2017-06-09 13:22:25 +00:00
|
|
|
end
|
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
local function external_error (self, module_suffix, format_msg, ...)
|
|
|
|
-- external_error(error_handler, module_suffix [, format_msg, ...])
|
|
|
|
|
|
|
|
-- Error check
|
|
|
|
assert(type(self) == 'table' and self.is_error_handler)
|
|
|
|
assert(type(module_suffix) == 'string')
|
|
|
|
format_msg = format_msg or DEFAULT_ERROR_MSG_INTERNAL
|
|
|
|
assert(type(format_msg) == 'string')
|
|
|
|
-- Find error level
|
|
|
|
local level = 3
|
|
|
|
while self.registered[debug.getinfo(level, 'f').func] do
|
|
|
|
level = level + 1
|
|
|
|
end
|
|
|
|
-- Format
|
|
|
|
return error(('[%s%s]: '..format_msg):format(self.module_name, module_suffix, ...), level -1)
|
2017-06-09 13:22:25 +00:00
|
|
|
end
|
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
local function correct_error (self, module_suffix, format_msg, gotten_string, possible_strings)
|
|
|
|
-- correct_error(error_handler, module_suffix [, format_msg], gotten_string, possible_strings)
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
-- Error check
|
|
|
|
assert(type(self) == 'table' and self.is_error_handler)
|
|
|
|
assert(type(module_suffix) == 'string')
|
|
|
|
format_msg = format_msg or DEFAULT_ERROR_MSG_CORRECT
|
|
|
|
assert(type(format_msg) == 'string')
|
|
|
|
assert(type(gotten_string) == 'string')
|
|
|
|
assert(type(possible_strings) == 'table')
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
-- Do stuff
|
|
|
|
local possible_strings = string_dist.strings_with_highest_similarity(gotten_string, possible_strings)
|
|
|
|
local list_string = format_probable_strings(possible_strings, 3)
|
|
|
|
-- Format
|
|
|
|
return error(('[%s%s]: '..format_msg):format(self.module_name, module_suffix, gotten_string, list_string), 3)
|
|
|
|
end
|
2017-06-09 13:22:25 +00:00
|
|
|
|
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
local ErrorHandler_mt = {__call = function (self, ...) internal_error(self, '', ...) end}
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-11 16:09:24 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
return function (module_name)
|
|
|
|
assert(type(module_name) == 'string')
|
2017-06-11 16:09:24 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
local err_hdl = setmetatable({}, ErrorHandler_mt)
|
|
|
|
err_hdl.is_error_handler = true
|
|
|
|
err_hdl.module_name = module_name
|
|
|
|
err_hdl.registered = {}
|
|
|
|
err_hdl.any_registered = false
|
2017-06-11 16:09:24 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
function err_hdl.internal (...)
|
|
|
|
local args = {...}
|
|
|
|
if args[1] == err_hdl then table.remove(args, 1) end
|
|
|
|
internal_error(err_hdl, '/internal', unpack(args))
|
|
|
|
end
|
|
|
|
|
|
|
|
function err_hdl.external (...)
|
|
|
|
local args = {...}
|
|
|
|
if args[1] == err_hdl then table.remove(args, 1) end
|
|
|
|
external_error(err_hdl, '', unpack(args))
|
|
|
|
end
|
2017-06-09 13:22:25 +00:00
|
|
|
|
2017-06-27 11:50:27 +00:00
|
|
|
function err_hdl.correct (...)
|
|
|
|
local args = {...}
|
|
|
|
if args[1] == err_hdl then table.remove(args, 1) end
|
|
|
|
if #args == 2 then table.insert(args, 1, DEFAULT_ERROR_MSG_CORRECT) end
|
|
|
|
correct_error(err_hdl, '', unpack(args))
|
|
|
|
end
|
|
|
|
|
|
|
|
function err_hdl.register (...)
|
|
|
|
local args = {...}
|
|
|
|
if args[1] == err_hdl then table.remove(args, 1) end
|
|
|
|
assert(#args > 0)
|
|
|
|
for i = 1, #args do
|
|
|
|
assert(type(args[i]) == 'function')
|
|
|
|
err_hdl.registered[args[i]] = true
|
|
|
|
err_hdl.any_registered = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return err_hdl
|
|
|
|
end
|