|
|
|
-- read namespace from global env
|
|
|
|
local _G = _G
|
|
|
|
local Grichelde = _G.Grichelde or {}
|
|
|
|
|
|
|
|
-- constants and upvalues
|
|
|
|
Grichelde.LOG_LEVEL = { DEBUG = 1, TRACE = 2 }
|
|
|
|
|
|
|
|
-- chat input in client is limited to 255 bytes (unicode length is less)
|
|
|
|
Grichelde.INPUT_LIMIT = 255
|
|
|
|
-- safety measure in case malformed user input causes infinite loops on string parsing
|
|
|
|
Grichelde.ENDLESS_LOOP_LIMIT = 10000
|
|
|
|
Grichelde.MAPPING_OFFSET = 10
|
|
|
|
Grichelde.MINIMAP_ENABLED = 1.0
|
|
|
|
Grichelde.MINIMAP_DARKENDED = 0.5
|
|
|
|
|
|
|
|
Grichelde.ICONS = {
|
|
|
|
MOVE_UP = "Interface\\MainMenuBar\\UI-MainMenu-ScrollUpButton-Up",
|
|
|
|
MOVE_UP_DISABLED = "Interface\\MainMenuBar\\UI-MainMenu-ScrollUpButton-Disabled",
|
|
|
|
MOVE_DOWN = "Interface\\MainMenuBar\\UI-MainMenu-ScrollDownButton-Up",
|
|
|
|
MOVE_DOWN_DISABLED = "Interface\\MainMenuBar\\UI-MainMenu-ScrollDownButton-Disabled",
|
|
|
|
DELETE = "Interface\\Buttons\\UI-Panel-MinimizeButton-Up",
|
|
|
|
DELETE_DISABLED = "Interface\\Buttons\\UI-Panel-MinimizeButton-Disabled",
|
|
|
|
}
|
|
|
|
|
|
|
|
-- colors:
|
|
|
|
Grichelde.COLORS = {
|
|
|
|
NORMAL = _G.NORMAL_FONT_COLOR,
|
|
|
|
HIGHLIGHT = _G.HIGHLIGHT_FONT_COLOR,
|
|
|
|
RED = _G.RED_FONT_COLOR,
|
|
|
|
GREEN = _G.GREEN_FONT_COLOR,
|
|
|
|
}
|
|
|
|
|
|
|
|
Grichelde.COLOR_CODES = {
|
|
|
|
PREFIX = "|c00FFAA00",
|
|
|
|
-- https://github.com/stoneharry/Misc-WoW-Stuff/blob/master/EoC%20Interface/FrameXML/Constants.lua
|
|
|
|
NORMAL = _G.NORMAL_FONT_COLOR_CODE or "|cffffd200",
|
|
|
|
HIGHLIGHT = _G.HIGHLIGHT_FONT_COLOR_CODE or "|cffffffff",
|
|
|
|
RED = _G.RED_FONT_COLOR_CODE or "|cffff2020",
|
|
|
|
GREEN = _G.GREEN_FONT_COLOR_CODE or "|cff20ff20",
|
|
|
|
LIGHTGRAY = "|cffC0C0C0",
|
|
|
|
GRAY = _G.GRAY_FONT_COLOR_CODE or "|cff808080",
|
|
|
|
DARKGRAY = "|cff404040",
|
|
|
|
YELLOW = _G.YELLOW_FONT_COLOR_CODE or "|cffffff00",
|
|
|
|
LIGHTYELLOW = _G.LIGHTYELLOW_FONT_COLOR_CODE or "|cffffff9a",
|
|
|
|
ORANGE = _G.ORANGE_FONT_COLOR_CODE or "|cffff7f3f",
|
|
|
|
BLUE = "|cff0000ff",
|
|
|
|
HYPERLINK = "|cff4040ff",
|
|
|
|
CLOSE = _G.FONT_COLOR_CODE_CLOSE or "|r",
|
|
|
|
}
|
|
|
|
|
|
|
|
Grichelde.SLASH_COMMANDS = { "gri", "grichelde" }
|
|
|
|
|
|
|
|
Grichelde.SUPPORTED_CHAT_COMMANDS = {
|
|
|
|
["/s"] = "SAY",
|
|
|
|
["/say"] = "SAY",
|
|
|
|
["/sprechen"] = "SAY",
|
|
|
|
["/c"] = "CHANNEL",
|
|
|
|
["/csay"] = "CHANNEL",
|
|
|
|
["/e"] = "EMOTE",
|
|
|
|
["/em"] = "EMOTE",
|
|
|
|
["/me"] = "EMOTE",
|
|
|
|
["/emote"] = "EMOTE",
|
|
|
|
["/y"] = "YELL",
|
|
|
|
["/yell"] = "YELL",
|
|
|
|
["/sh"] = "YELL",
|
|
|
|
["/shout"] = "YELL",
|
|
|
|
["/schreien"] = "YELL",
|
|
|
|
["/sch"] = "YELL",
|
|
|
|
["/p"] = "PARTY",
|
|
|
|
["/party"] = "PARTY",
|
|
|
|
["/gruppe"] = "PARTY",
|
|
|
|
["/pl"] = "PARTY",
|
|
|
|
["/partyleader"] = "PARTY",
|
|
|
|
["/g"] = "GUILD",
|
|
|
|
["/gc"] = "GUILD",
|
|
|
|
["/guild"] = "GUILD",
|
|
|
|
["/gilde"] = "GUILD",
|
|
|
|
["/o"] = "OFFICER",
|
|
|
|
["/osay"] = "OFFICER",
|
|
|
|
["/officer"] = "OFFICER",
|
|
|
|
["/offizier"] = "OFFICER",
|
|
|
|
["/raid"] = "RAID",
|
|
|
|
["/rsay"] = "RAID",
|
|
|
|
["/rl"] = "RAID",
|
|
|
|
["/rsay"] = "RAID",
|
|
|
|
["/raidleader"] = "RAID",
|
|
|
|
["/schlachtzug"] = "RAID",
|
|
|
|
["/rw"] = "RAID_WARNING",
|
|
|
|
["/raidwarning"] = "RAID_WARNING",
|
|
|
|
["/i"] = "INSTANCE_CHAT",
|
|
|
|
["/instance"] = "INSTANCE_CHAT",
|
|
|
|
["/instanz"] = "INSTANCE_CHAT",
|
|
|
|
["/bg"] = "BATTLEGROUND",
|
|
|
|
["/battleground"] = "BATTLEGROUND",
|
|
|
|
["/schlachfeld"] = "BATTLEGROUND",
|
|
|
|
["/w"] = "WHISPER",
|
|
|
|
["/whisper"] = "WHISPER",
|
|
|
|
["/t"] = "WHISPER",
|
|
|
|
["/tell"] = "WHISPER",
|
|
|
|
["/send"] = "WHISPER",
|
|
|
|
["/tt"] = "WHISPER",
|
|
|
|
["/r"] = "WHISPER",
|
|
|
|
["/reply"] = "WHISPER",
|
|
|
|
["/fl\195\188stern"] = "WHISPER",
|
|
|
|
["/antworten"] = "WHISPER",
|
|
|
|
}
|
|
|
|
|
|
|
|
Grichelde.BLIZZ_TYPE_TO_OPTIONS = {
|
|
|
|
["SAY"] = "say",
|
|
|
|
["EMOTE"] = "emote",
|
|
|
|
["YELL"] = "yell",
|
|
|
|
["PARTY"] = "party",
|
|
|
|
["GUILD"] = "guild",
|
|
|
|
["OFFICER"] = "officer",
|
|
|
|
["RAID"] = "raid",
|
|
|
|
["RAID_WARNING"] = "raidWarning",
|
|
|
|
["INSTANCE"] = "instance",
|
|
|
|
["BATTLEGROUND"] = "battleground",
|
|
|
|
["WHISPER"] = "whisper",
|
|
|
|
}
|
|
|
|
|
|
|
|
-- do not replace these patterns
|
|
|
|
-- combined item links in the chat will look like this: |cff9d9d9d|Hitem:3299::::::::20:257::::::|h[Fractured Canine]|h|r
|
|
|
|
Grichelde.IGNORE_PATTERNS = {
|
|
|
|
LINKS = {
|
|
|
|
"|[Cc]%x%x%x%x%x%x%x%x.-|r", -- colored items (or links)
|
|
|
|
"|H.-|h", -- item links (http://www.wowwiki.com/ItemLink)
|
|
|
|
"|T.-|t", -- textures
|
|
|
|
"|K.-|k", -- Battle.net
|
|
|
|
"|n", -- newline
|
|
|
|
},
|
|
|
|
EMOTES = {
|
|
|
|
"%*.-%*", -- emotes *
|
|
|
|
"%*%*.-%*%*", -- emotes **
|
|
|
|
"%<.-%>", -- emotes < >
|
|
|
|
},
|
|
|
|
SUBSTITUTES = {
|
|
|
|
"%%n", -- player's name
|
|
|
|
"%%z", -- player's currnt zone
|
|
|
|
"%%sz", -- player's current sub-zone
|
|
|
|
"%%loc", -- player's map coordinates
|
|
|
|
"%%t", -- name of target
|
|
|
|
"%%f", -- name of focus target
|
|
|
|
"%%m", -- name of mouseover unit
|
|
|
|
"%%p", -- name of player pet
|
|
|
|
"%%tt", -- name of player's target's target
|
|
|
|
},
|
|
|
|
RAID_TARGETS = {
|
|
|
|
"{rt[1-8]}", -- rumbered raid target icons, localized raid targets are handled differently
|
|
|
|
},
|
|
|
|
LOCALIZED_RAID_TARGETS = {
|
|
|
|
"Star",
|
|
|
|
"Circle",
|
|
|
|
"Diamond",
|
|
|
|
"Triangle",
|
|
|
|
"Moon",
|
|
|
|
"Square",
|
|
|
|
"Cross",
|
|
|
|
"Skull",
|
|
|
|
},
|
|
|
|
OOC_BRACKETS = {
|
|
|
|
"%(%(.-%)%)", -- (( ... ))
|
|
|
|
"%(%s*ooc[%:%s].-%)", -- ( ooc )
|
|
|
|
},
|
|
|
|
OOC_NO_BRACKETS = {
|
|
|
|
"ooc[%:%s]",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
local function nilOrEmpty(s)
|
|
|
|
return s == nil or s:trim() == ""
|
|
|
|
end
|
|
|
|
|
|
|
|
local function spairs(tbl, orderFunc)
|
|
|
|
-- collect the keys
|
|
|
|
local sortedKeys = {}
|
|
|
|
-- for every non-nil value
|
|
|
|
for key, _ in Grichelde.F.pairs(tbl) do
|
|
|
|
Grichelde.F.tInsert(sortedKeys, key)
|
|
|
|
end
|
|
|
|
|
|
|
|
if (orderFunc ~= nil) then
|
|
|
|
Grichelde.F.tSort(sortedKeys, function(a, b) return orderFunc(sortedKeys, a, b) end)
|
|
|
|
else
|
|
|
|
-- lexicographical order
|
|
|
|
Grichelde.F.tSort(sortedKeys)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- return the iterator function
|
|
|
|
local it = 0
|
|
|
|
return function()
|
|
|
|
it = it + 1
|
|
|
|
if (sortedKeys[it] ~= nil) then
|
|
|
|
return sortedKeys[it], tbl[sortedKeys[it]]
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function tFilter(type, condition, extract)
|
|
|
|
local filtered = {}
|
|
|
|
for key, value in Grichelde.F.pairs(type) do
|
|
|
|
local cond = false
|
|
|
|
if (condition) then
|
|
|
|
local typ = Grichelde.F.type(condition)
|
|
|
|
if (typ == "function") then
|
|
|
|
cond = condition(typ, key, value)
|
|
|
|
elseif (typ == "string") or (typ == "number") then
|
|
|
|
cond = (value == condition)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if (cond) then
|
|
|
|
local val = value
|
|
|
|
if (extract and (Grichelde.F.type(extract) == "function")) then
|
|
|
|
val = extract(type, key, value)
|
|
|
|
end
|
|
|
|
Grichelde.F.tInsert(filtered, val)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return filtered
|
|
|
|
end
|
|
|
|
|
|
|
|
local function tSize(tbl)
|
|
|
|
local size = 0
|
|
|
|
if (tbl ~= nil) then
|
|
|
|
-- for every non-nil value
|
|
|
|
for _, _ in Grichelde.F.pairs(tbl) do
|
|
|
|
size = size + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return size
|
|
|
|
end
|
|
|
|
|
|
|
|
local function tIsEmpty(tbl)
|
|
|
|
if (not tbl) then return true end
|
|
|
|
return Grichelde.F.tNext(tbl) == nil
|
|
|
|
end
|
|
|
|
|
|
|
|
local function tClone(orig)
|
|
|
|
local orig_type = Grichelde.F.type(orig)
|
|
|
|
local copy
|
|
|
|
if (orig_type == 'table') then
|
|
|
|
copy = {}
|
|
|
|
-- for every non-nil value
|
|
|
|
for orig_key, orig_value in Grichelde.F.tNext, orig, nil do
|
|
|
|
copy[tClone(orig_key)] = tClone(orig_value)
|
|
|
|
end
|
|
|
|
Grichelde.F.setmetatable(copy, tClone(Grichelde.F.getmetatable(orig)))
|
|
|
|
else -- number, string, boolean, etc
|
|
|
|
copy = orig
|
|
|
|
end
|
|
|
|
return copy
|
|
|
|
end
|
|
|
|
|
|
|
|
local function getNextCharUtf8(word)
|
|
|
|
if ((word == nil) or (Grichelde.F.type(word) ~= "string") or (Grichelde.F.length(word) < 1)) then
|
|
|
|
return nil, nil
|
|
|
|
end
|
|
|
|
|
|
|
|
local wordLength = Grichelde.F.length(word)
|
|
|
|
local c1 = Grichelde.F.toByte(word, 1)
|
|
|
|
if (c1 > 0) and (c1 <= 127) then
|
|
|
|
-- UTF8-1
|
|
|
|
return Grichelde.F.bytes2Char(c1), Grichelde.F.sub(word, 2)
|
|
|
|
elseif (c1 >= 194) and (c1 <= 223) then
|
|
|
|
-- UTF8-2
|
|
|
|
Grichelde.F.assert(wordLength >= 2, "broken UTF-8 character")
|
|
|
|
local c2 = Grichelde.F.toByte(word, 2)
|
|
|
|
return Grichelde.F.bytes2Char(c1, c2), Grichelde.F.sub(word, 3)
|
|
|
|
elseif (c1 >= 224) and (c1 <= 239) then
|
|
|
|
-- UTF8-3
|
|
|
|
Grichelde.F.assert(wordLength >= 3, "broken UTF-8 character")
|
|
|
|
local c2 = Grichelde.F.toByte(word, 2)
|
|
|
|
local c3 = Grichelde.F.toByte(word, 3)
|
|
|
|
return Grichelde.F.bytes2Char(c1, c2, c3), Grichelde.F.sub(word, 4)
|
|
|
|
elseif (c1 >= 240) and (c1 <= 244) then
|
|
|
|
-- UTF8-4
|
|
|
|
Grichelde.F.assert(wordLength >= 4, "broken UTF-8 character")
|
|
|
|
local c2 = Grichelde.F.toByte(word, 2)
|
|
|
|
local c3 = Grichelde.F.toByte(word, 3)
|
|
|
|
local c4 = Grichelde.F.toByte(word, 4)
|
|
|
|
return Grichelde.F.bytes2Char(c1, c2, c3, c4), Grichelde.F.sub(word, 5)
|
|
|
|
else
|
|
|
|
return nil, nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function isLetter(word)
|
|
|
|
local char = Grichelde.F.getNextCharUtf8(word)
|
|
|
|
return (char ~= nil) and (Grichelde.F.toUpper(char) ~= Grichelde.F.toLower(char))
|
|
|
|
end
|
|
|
|
|
|
|
|
local function isNumber(digit)
|
|
|
|
if ((digit == nil) or (Grichelde.F.type(digit) ~= "string") or (Grichelde.F.length(digit) < 1)) then
|
|
|
|
return false
|
|
|
|
else
|
|
|
|
return Grichelde.F.find(digit, "%d+") ~= nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function isUpper(word)
|
|
|
|
if ((word == nil) or (Grichelde.F.type(word) ~= "string") or (Grichelde.F.length(word) < 1)) then
|
|
|
|
return false
|
|
|
|
elseif (Grichelde.F.toUpper(word) == Grichelde.F.toLower(word)) then
|
|
|
|
return false
|
|
|
|
else
|
|
|
|
return word == Grichelde.F.toUpper(word)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function isLower(word)
|
|
|
|
if ((word == nil) or (Grichelde.F.type(word) ~= "string") or (Grichelde.F.length(word) < 1)) then
|
|
|
|
return false
|
|
|
|
elseif (Grichelde.F.toUpper(word) == Grichelde.F.toLower(word)) then
|
|
|
|
return false
|
|
|
|
else
|
|
|
|
return word == Grichelde.F.toLower(word)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function isCapital(word)
|
|
|
|
if ((word == nil) or (Grichelde.F.type(word) ~= "string") or (Grichelde.F.length(word) < 1)) then
|
|
|
|
return false
|
|
|
|
else
|
|
|
|
local first, rest = Grichelde.F.getNextCharUtf8(word)
|
|
|
|
local isCap = Grichelde.F.isUpper(first)
|
|
|
|
if (rest ~= nil) then
|
|
|
|
return isCap and Grichelde.F.isLower(rest)
|
|
|
|
else
|
|
|
|
return isCap
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function capitalize(word)
|
|
|
|
if ((word == nil) or (Grichelde.F.type(word) ~= "string") or (Grichelde.F.length(word) < 1)) then
|
|
|
|
return ""
|
|
|
|
else
|
|
|
|
local first, rest = Grichelde.F.getNextCharUtf8(word)
|
|
|
|
local capital = Grichelde.F.toUpper(first)
|
|
|
|
if (rest ~= nil) then
|
|
|
|
return capital .. Grichelde.F.toLower(rest)
|
|
|
|
else
|
|
|
|
return capital
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function color(colour, text)
|
|
|
|
return colour .. text .. Grichelde.COLOR_CODES.CLOSE
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cPrefix(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.PREFIX, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cYellow(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.NORMAL, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cGray(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.GRAY, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cDarkgray(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.DARKGRAY, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cGreen(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.GREEN, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cOrange(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.ORANGE, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cRed(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.RED, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function cHyperlink(text)
|
|
|
|
return Grichelde.F.color(Grichelde.COLOR_CODES.HYPERLINK, text)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- faster function lookups by mapping to local refs
|
|
|
|
Grichelde.F = {
|
|
|
|
IsAddOnLoaded = _G.IsAddOnLoaded,
|
|
|
|
assert = _G.assert,
|
|
|
|
type = _G.type,
|
|
|
|
print = _G.print,
|
|
|
|
nilOrEmpty = nilOrEmpty,
|
|
|
|
pairs = _G.pairs,
|
|
|
|
ipairs = _G.ipairs,
|
|
|
|
spairs = spairs,
|
|
|
|
tContains = _G.tContains,
|
|
|
|
tFilter = tFilter,
|
|
|
|
tInsert = _G.table.insert,
|
|
|
|
tConcat = _G.table.concat,
|
|
|
|
tSize = tSize,
|
|
|
|
tIsEmpty = tIsEmpty,
|
|
|
|
tSort = _G.table.sort,
|
|
|
|
tClone = tClone,
|
|
|
|
tNext = _G.next,
|
|
|
|
tWipe = _G.wipe,
|
|
|
|
setmetatable = _G.setmetatable,
|
|
|
|
getmetatable = _G.getmetatable,
|
|
|
|
select = _G.select,
|
|
|
|
unpack = _G.unpack,
|
|
|
|
find = _G.string.find,
|
|
|
|
sub = _G.string.sub,
|
|
|
|
gsub = _G.string.gsub,
|
|
|
|
match = _G.strmatch,
|
|
|
|
gmatch = _G.string.gmatch,
|
|
|
|
join = _G.strjoin,
|
|
|
|
split = _G.strsplit,
|
|
|
|
toUpper = _G.strupper,
|
|
|
|
toLower = _G.strlower,
|
|
|
|
getNextCharUtf8 = getNextCharUtf8,
|
|
|
|
isLetter = isLetter,
|
|
|
|
isNumber = isNumber,
|
|
|
|
isUpper = isUpper,
|
|
|
|
isLower = isLower,
|
|
|
|
isCapital = isCapital,
|
|
|
|
capitalize = capitalize,
|
|
|
|
color = color,
|
|
|
|
cPrefix = cPrefix,
|
|
|
|
cYellow = cYellow,
|
|
|
|
cGray = cGray,
|
|
|
|
cDarkgray = cDarkgray,
|
|
|
|
cGreen = cGreen,
|
|
|
|
cOrange = cOrange,
|
|
|
|
cRed = cRed,
|
|
|
|
cHyperlink = cHyperlink,
|
|
|
|
toByte = _G.string.byte,
|
|
|
|
bytes2Char = _G.string.char,
|
|
|
|
format = _G.string.format,
|
|
|
|
rep = _G.string.rep,
|
|
|
|
trim = _G.strtrim,
|
|
|
|
length = _G.string.len,
|
|
|
|
lengthUtf8 = _G.strlenutf8,
|
|
|
|
toString = _G.tostring,
|
|
|
|
toNumber = _G.tonumber,
|
|
|
|
max = _G.math.max,
|
|
|
|
min = _G.math.min,
|
|
|
|
}
|