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
263 lines
6.3 KiB
|
3 years ago
|
---------------------------------------------------------------------------------
|
||
|
|
--
|
||
|
|
-- 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
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|