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 }