--------------------------------------------------------------------------------- -- -- Prat - A framework for World of Warcraft chat mods -- -- Copyright (C) 2006-2018 Prat Development Team -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License -- as published by the Free Software Foundation; either version 2 -- of the License, or (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to: -- -- Free Software Foundation, Inc., -- 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -- -- ------------------------------------------------------------------------------- --[[ BEGIN STANDARD HEADER ]] -- -- Imports local _G = _G local table = table local unpack = unpack local pairs, ipairs = pairs, ipairs local tinsert, tremove, tconcat = table.insert, table.remove, table.concat local wipe = wipe local type = type local setmetatable = setmetatable local rawset, rawget = rawset, rawget local tostring, tonumber = tostring, tonumber local random = math.random -- Isolate the environment setfenv(1, select(2, ...)) --[[ END STANDARD HEADER ]] -- local debug = function(...) -- _G.ChatFrame1:print(...) end function CaseInsensitveWordPattern(word) local upper = word:upper() local lower = word:lower() local pattern = "" for i=1,word:len() do pattern = pattern .. "[" .. upper:sub(i, i) .. lower:sub(i, i) .. "]" end return pattern end local function uuid() local template ='xyxxxxyx' return template:gsub('[xy]', function (c) local v = (c == 'x') and random(0, 0xf) or random(8, 0xb) return ('%x'):format(v) end) end -- Register a pattern with the pattern matching engine -- You can supply a priority 1 - 100. Default is 50 -- 1 = highest, 100 = lowest. -- pattern = { pattern, matchfunc, priority, type} -- -- Priorities arent used currently, they are to help with -- collisions later on if there are alot of patterns -- local PatternRegistry = { patterns = {}, sortedList = {}, sorted = true} --[==[@debug@ _G.Prat.PatternRegistry = PatternRegistry --@end-debug@]==] do function RegisterPattern(pattern, who) local idx repeat idx = uuid() until PatternRegistry.patterns[idx] == nil PatternRegistry.patterns[idx] = pattern PatternRegistry.sortedList[#PatternRegistry.sortedList+1] = pattern PatternRegistry.sorted = false pattern.owner = who pattern.idx = idx debug("RegisterPattern", who, pattern) return idx end function UnregisterAllPatterns(who) debug("UnregisterAllPatterns", who) for i, pattern in ipairs(PatternRegistry.sortedList) do if pattern.owner == who then tremove(PatternRegistry.sortedList, i) PatternRegistry.patterns[pattern.idx] = nil end end end end function GetPattern(idx) return PatternRegistry.patterns[idx] end function UnregisterPattern(idx) for i, pattern in ipairs(PatternRegistry.sortedList) do if pattern.idx == idx then tremove(PatternRegistry.sortedList, i) PatternRegistry.patterns[pattern.idx] = nil return end end end do local tokennum = 1 local MatchTable = setmetatable({}, { __index = function(self, key) if type(rawget(self, key)) ~= "table" then rawset(self, key, {}) end return rawget(self, key) end }) function RegisterMatch(self, text, ptype) tokennum = tokennum + 1 local token = "@##" .. tokennum .. "##@" debug("RegisterMatch", text, token) local mt = MatchTable[ptype or "FRAME"] mt[token] = text -- return text return token end function MatchPatterns(m, ptype) local startTime = _G.debugprofilestop() local text = m.MESSAGE if type(m) == "string" then text = m m = nil end ptype = ptype or "FRAME" tokennum = 0 if not PatternRegistry.sorted then table.sort(PatternRegistry.sortedList, function(a, b) local ap = a.priority or 50 local bp = b.priority or 50 return ap < bp end) PatternRegistry.sorted = true end debug("MatchPatterns -->", text, tokennum) -- Match and remove strings for _, v in ipairs(PatternRegistry.sortedList) do if text and ptype == (v.type or "FRAME") then if type(v.pattern) == "string" and (v.pattern):len() > 0 then debug("MatchPatterns :", v.pattern) if v.deformat then text = v.matchfunc(text) else if v.matchfunc ~= nil then text = text:gsub(v.pattern, function(...) local parms = {...} parms[#parms+1] = m return v.matchfunc(unpack(parms)) end) else debug("ERROR", v.pattern) end end end end end local runTime = _G.debugprofilestop() - startTime debug("MatchPatterns <--", text, tokennum, runTime) if m then m.PATTERN_TIMES = { match = runTime } end return text end function ReplaceMatches(m, ptype) local startTime = _G.debugprofilestop() local text = m.MESSAGE if type(m) == "string" then text = m m = nil end -- Substitute them (or something else) back in local mt = MatchTable[ptype or "FRAME"] debug("ReplaceMatches -->", text) local k for t = tokennum, 1, -1 do k = "@##" .. tostring(t) .. "##@" if (mt[k]) then text = text:gsub(k, mt[k]) else debug("ERROR", k) end mt[k] = nil end -- for k,v in pairs(mt) do -- text = text:gsub(k, v) -- mt[k] = nil -- end local runTime = _G.debugprofilestop() - startTime debug("ReplaceMatches <--", text, runTime) if m then m.PATTERN_TIMES.replace = runTime end return text end end