hey jlam, thanks for the advice
I was able to rewrite the code to look like
Lua Code:
local letterTable, coloredMessage, holder, placeHolderWord = {}, {} --letterTable will be used to hold our individual words free from any punctuation or numbers, coloredMessage is ultimately what we will return, holder is used to find strings of letters and insert them into our letterTable, placeHolderWord is so we can perform a final gsub at the end
local function hexColorNames(chatMessage, modChatColor)
wipe(coloredMessage) --blizzard function that will clear our table
for word in gmatch(chatMessage, '%S+') do --look at each word individually, separating them by spaces (we look for non-whitespace)
placeHolderWord = word
local _
local class, name, coloredName = nil, nil, nil
wipe(letterTable) --wipe our letterTable from any previous entries
while strfind(placeHolderWord, '%a') do --we're going to be removing all blocks of letters from our word
holder = placeHolderWord:match('[^%p%s%d]+') --extract our blocks of letters, we don't want numbers, spaces, or punctuation, (we use this instead of [%a]+ because it allows for non-ascii characters
if holder then --safety so we don't throw an error inserting nil into a table
table.insert(letterTable, holder) --put our letter block into our letterTable holder
placeHolderWord = placeHolderWord:gsub(holder, '') --names can ultimately be a simple name from your realm, a name with
end
end
if (#letterTable == 1 and letterTable[1]:lower() ~= 'player' and letterTable[1]:lower() ~= 'target' and letterTable[1]:lower() ~= 'focus') then --our table is only 1 entry long, and therefore it can't be someone on another realm
name = letterTable[1]
_, class = UnitClass(letterTable[1])
elseif #letterTable == 2 then
if strfind(word, 'Area52') then
name = letterTable[1]..'%-'..letterTable[2]..'52' --we use the % so we can gsub; the '52' won't be transferred to letterTable as it specifically excludes numbers, this is a shitty hack for people on Area 52
_, class = UnitClass(letterTable[1]..'-'..letterTable[2]..'52')
else
name = letterTable[1]..'%-'..letterTable[2] --we use the % so we can gsub
_, class = UnitClass(letterTable[1]..'-'..letterTable[2])
end
elseif #letterTable >= 3 then --we use >= rather than == incase someone adds letters afterwards to try and catch more names this way
name = letterTable[1]..'%-'..letterTable[2].."%'"..letterTable[3] --we use the % in front of the magic characters so we can gsub
_, class = UnitClass(letterTable[1]..'-'..letterTable[2].."'"..letterTable[3])
end
if (class and class ~= '') then --if we actually got a class and it's not '' then we can modify the text to have class color and return back to the text color before it
coloredName = '|c'..RAID_CLASS_COLORS[class or class:gsub(' ', '')].colorStr..name..modChatColor
word = word:gsub(name, coloredName)
end
table.insert(coloredMessage, word)
end
return(table.concat(coloredMessage, ' '))
end
and
Lua Code:
local function modHexColorNames(chatMessage, modChatColor) --differs from hexColorNames because it class colors 'You' and 'you' and 'Your' and 'your' and removes realmNames from players
wipe(coloredMessage) --blizzard function that will clear our table
for word in gmatch(chatMessage, '%S+') do --look at each word individually, separating them by spaces (we look for non-whitespace)
placeHolderWord = word
local _
local class, name, coloredName = nil, nil, nil
wipe(letterTable) --wipe our letterTable from any previous entries
while strfind(placeHolderWord, '%a') do --we're going to be removing all blocks of letters from our word
holder = placeHolderWord:match('[^%p%s%d]+') --extract our blocks of letters, we don't want numbers, spaces, or punctuation, (we use this instead of [%a]+ because it allows for non-ascii characters
if holder then --safety so we don't throw an error inserting nil into a table
table.insert(letterTable, holder) --put our letter block into our letterTable holder
placeHolderWord = placeHolderWord:gsub(holder, '') --names can ultimately be a simple name from your realm, a name with
end
end
for i = 1, 3 do
if (i == 1 and letterTable[i]) then --the potential name doesn't have a realm
_, class = UnitClass(letterTable[1])
if class and class ~= '' then break end
elseif (i == 2 and letterTable[i]) then --the potential name has at least a realm name
if strfind(word, 'Area52') then --hack because our match specifically avoids numbers, Area 52 is the only realm with numbers
_, class = UnitClass(letterTable[1]..'-'..letterTable[2]..'52')
if class and class ~= '' then break end
else
_, class = UnitClass(letterTable[1]..'-'..letterTable[2])
if class and class ~= '' then break end
end
elseif (i == 3 and letterTable[i]) then --the potential name might have a realm and an ' in the realmName
_, class = UnitClass(letterTable[1]..'-'..letterTable[2].."'"..letterTable[3])
end
end
if (class and class ~= '') then --if we actually got a class and it's not '' then we can modify the text to have class color and return back to the text color before it
if #letterTable == 2 then
word = word:gsub('%-%P+', '') --remove the realm name but preserve any punctuation attached at the end
elseif #letterTable == 3 then
word = word:gsub('%-%P+', '') --remove the realm name, but we're going to get stuck on the '
word = word:gsub("%'%P+", '') --remove the rest of the realm name
end
coloredName = '|c'..RAID_CLASS_COLORS[class or class:gsub(' ', '')].colorStr..letterTable[1]..modChatColor --color the name
word = word:gsub(letterTable[1], coloredName) --replace the name with the colored name
end
if (letterTable[1] and (letterTable[1]:lower() == 'you' or letterTable[1]:lower() == 'your')) then --color this
coloredName = '|c'..playerClassColorTable.colorStr..letterTable[1]..modChatColor --this is an addon-wide static formed at the beginning of the addon as it's frequently used
word = word:gsub(letterTable[1], coloredName)
end
table.insert(coloredMessage, word)
end
return(table.concat(coloredMessage, ' '))
end
It works with non-ascii characters, works with off-realm players, works with people on realms with apostrophes, works under every scenario I can throw at it. It is fairly "hard-coded." I say that because player names can only be a name, a name-realm, or a name-re'alm with no numbers or punctuations in the name. This allowed me to perform the #letterTable == integer test.
Let me know what you think, or if you see a better way of doing this.