You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
6.3 KiB

---------------------------------------------------------------------------------
--
-- 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