模块:TryError
外观
local p={}
local lib_arg={}
local yesno = {}
function p._message(err_obj)
local err_array = err_obj
local body = ''
if type(err_obj.message) == type("string") then err_array={err_obj} end
for i=1,#err_array do body = body .. err_array[i].message or ''end
return body
end
function p._throw(err_obj)
local err_array = err_obj
local body = ''
if type(err_obj.message) == type("string") then err_array={err_obj} end
for i=1,#err_array do
local message = err_array[i].message or ''
if mw.text.trim(message) == '' then message = error('没有指定的錯誤-{zh-cn:信息; zh-tw:資訊}-', 2) end
message = tostring(message)
local tag = 'strong'
-- Generate the html.
local root = mw.html.create(tag)
for j=1,#err_array[i].types do
root:addClass(err_array[i].types[j])
end
root
:addClass('error')
:wikitext(message)
body = body .. tostring(root)
end
return body
end
function p._constructErrorFromArg(str)
local error_array = {}
mw.ustring.gsub(str,"([^%(]+)%(([^%)]*)%)",function(name,para)
error_array[#error_array + 1] = {['message']=para,['types']=mw.text.split(name,',')or {name} }
return name..para
end)
return error_array
end
function p._constructError(str)
local result={['message']='',['types']={}}
if mw.text.trim(str or '') == "" then return {['message']='',['types']={'unknown'}} end
local error_tags = {'strong', 'span', 'p', 'div'}
for i=1,#error_tags do
local check_tag = error_tags[i]:gsub('^(.-)$','<%1[^>]*>(.-)</%1>')
local find_msg = '<'
mw.ustring.gsub(str,check_tag,function(check_msg)find_msg=check_msg end)
find_msg = mw.text.trim(find_msg)
if mw.ustring.sub(find_msg,1,1) ~= '<' then
result.message = find_msg
break
end
end
local error_attritube = {'class', 'id'}
local typemap={['error']=1}
for i=1,#error_attritube do
local check_tag_dstr = error_attritube[i]:gsub('^(.-)$','%1="([^"]+)"')
local check_tag_sstr = error_attritube[i]:gsub('^(.-)$',"%1='([^']+)'")
local check_tag_pstr = error_attritube[i]:gsub('^(.-)$',"%1=([^%%s]+)")
local dstr,sstr,pstr = '','',''
mw.ustring.gsub(str,check_tag_dstr,function(check_msg)dstr=mw.text.trim(check_msg)end)
mw.ustring.gsub(str,check_tag_sstr,function(check_msg)sstr=mw.text.trim(check_msg)end)
mw.ustring.gsub(str,check_tag_pstr,function(check_msg)pstr=mw.text.trim(check_msg)end)
local pstr_ch = mw.ustring.sub(pstr,1,1)
if pstr_ch ~= '"' and pstr_ch ~= "'" then
if mw.text.trim(pstr) ~= "" then
typemap[pstr] = 1
end
end
local sdstr = mw.ustring.gsub(dstr .. ' ' .. sstr, '%s+', ' ')
local sdarr = mw.text.split(sdstr,' ')
for _,class_name in ipairs(sdarr) do
if mw.text.trim(class_name) ~= "" then
typemap[class_name] = 1
end
end
end
for class_name,_ in pairs(typemap) do
if type(result.types) ~= type{"table"} then result.types={} end
result.types[#result.types + 1]=class_name
end
local getFrommsg = mw.text.split(result.message,"[::︓﹕。%s]")
result.types[#result.types + 1]=mw.ustring.gsub(getFrommsg[1],"<[^>]+>","")
result.types[#result.types]=mw.ustring.gsub(result.types[#result.types],'[“"「][^”"」]-[”"」]','')
return result
end
function p.try(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_try = args[1] or args['1']
local multi_catch = false
if (args.multi or '') ~= '' then
if type(yesno) ~= type(tonumber) then yesno = require('Module:Yesno') end
multi_catch = yesno(args.multi or 'no')
end
local preprocess = false
if (args.preprocess or '') ~= '' then
if type(yesno) ~= type(tonumber) then yesno = require('Module:Yesno') end
preprocess = yesno(args.preprocess or 'no')
end
local if_errorcall = tonumber(mw.getCurrentFrame().args.if_errorcall or '0') or 0
local catch_list = {}
local default_catch = {["value"]="{{{throw|error(未處理的例外狀況:)}}}{{{throw}}}", ["exception"]={} }
for key,value in pairs(args) do
local argname = mw.ustring.lower(tostring(key))
local exception_data ,checker = mw.ustring.gsub(argname,'^%s*catch%s*%((.-)%)%s*$','%1')
if checker > 0 then
catch_list[#catch_list+1] = {["value"]=value, ["exception"]=(mw.text.split(exception_data,',') or {exception_data})}
elseif mw.text.trim(argname) == 'catch' then
default_catch.value=value
end
end
catch_list[#catch_list+1]=default_catch
local find_error = ' ' .. (input_try or '') .. ' '--/^...$/
local error_tags = {'strong', 'span', 'p', 'div'}
local exceptions = {}
for i=1,#error_tags do
local check_tag = error_tags[i]:gsub('^(.-)$','<%1[^>]+error.-</%1>')
find_error = mw.ustring.gsub(find_error,check_tag,function(exception)
exceptions[#exceptions + 1] = p._constructError(exception)
return''end)
end
find_error = mw.text.trim(find_error)
if #exceptions<=0 and if_errorcall > 0 then
exceptions[#exceptions + 1] = {['message']='其他錯誤',['types']={'error'}}
end
if #exceptions<=0 and if_errorcall <= 0 then
if preprocess == true then return working_frame:preprocess(input_try) end
return input_try
end
local body = ''
local catched = false
for i=1,#catch_list do
local current_catch = catch_list[i]
local found = false
local exception_obj = nil
for j=1,#current_catch.exception do
for k=1,#exceptions do
for ke=1,#exceptions[k].types do
local to_check_ex = mw.ustring.lower(exceptions[k].types[ke])
local to_check_pattern = mw.text.trim(mw.ustring.lower(current_catch.exception[j]))
local check_eq = to_check_ex == to_check_pattern
local check_isregexp = false
if mw.ustring.sub(to_check_pattern,1,1) == '/' and mw.ustring.sub(to_check_pattern,-1,-1) == '/' then
to_check_pattern = mw.ustring.sub(to_check_pattern,2,-2)
if check_eq ~= true then
xpcall( function()
local check_req = mw.ustring.find(to_check_ex, to_check_pattern)
if check_req then check_eq = true end
end , function() end )
end
end
if check_eq == true then
found = true
exception_obj = exceptions[k]
break
end
end
if found == true then break end
end
if found == true then break end
end
if #exceptions > 0 and i==#catch_list then
exception_obj=exceptions[1]
found = true
end
if i==#catch_list then
if catched==true then
catch_list[#catch_list].value = "{{{throw}}}"
end
end
if found == true and exception_obj then
local catch_data = catch_list[i].value
catch_data = mw.ustring.gsub(catch_data, '%{%{%{%s*throw%s*(|?[^%}]*)%}%}%}',function(str)
local use_old_error = false
local input_throw = mw.text.trim(str)
if input_throw == '' then use_old_error = true end
if mw.ustring.sub(input_throw,1,1) == '|' then
input_throw=mw.text.trim(mw.ustring.sub(input_throw,2,-1))
if input_throw == '' then return '' end
return p._throw(p._constructErrorFromArg(input_throw))
elseif use_old_error == true then
if i==#catch_list then return p._throw(exceptions) end
return p._throw(exception_obj)
end
return '{{{throw' .. str .. '}}}'
end)
catch_data = mw.ustring.gsub(catch_data, '%{%{%{%s*message%s*(|?[^%}]*)%}%}%}',function(str)
local use_old_error = false
local input_throw = mw.text.trim(str)
if input_throw == '' then use_old_error = true end
if mw.ustring.sub(input_throw,1,1) == '|' then
input_throw=mw.text.trim(mw.ustring.sub(input_throw,2,-1))
if input_throw == '' then return '' end
return p._message(p._constructErrorFromArg(input_throw))
elseif use_old_error == true then
if i==#catch_list then return p._message(exceptions) end
return p._message(exception_obj)
end
return '{{{message' .. str .. '}}}'
end)
body = body .. catch_data
if multi_catch==true then
catched = true
else
break
end
end
end
body = mw.ustring.gsub(body, '%{%{%{%s*[Nn][Oo]%s*[Ee][Rr][Rr][Oo][Rr]%s*(|?[^%}]*)%}%}%}',function(str)
local use_old_error = false
local input_throw = mw.text.trim(str)
if input_throw == '' then use_old_error = true end
if mw.ustring.sub(input_throw,1,1) == '|' then
input_throw=mw.text.trim(mw.ustring.sub(input_throw,2,-1))
if mw.ustring.trim(input_throw) == '' then return '' end
if mw.ustring.trim(find_error) == '' then return input_throw end
return find_error
elseif use_old_error == true then return find_error end
return '{{{no error' .. str .. '}}}'
end)
if preprocess == true then return working_frame:preprocess(body) end
return body
end
return p