@ -2,8 +2,9 @@
local _G = _G
local Grichelde = _G.Grichelde
local nilOrEmpty , ipairs , tContains , tFilter , tInsert , tConcat , find , sub , gsub , toLower , trim , length
= Grichelde.functions . nilOrEmpty , Grichelde.functions . ipairs , Grichelde.functions . tContains , Grichelde.functions . tFilter , Grichelde.functions . tInsert , Grichelde.functions . tConcat , Grichelde.functions . find , Grichelde.functions . sub , Grichelde.functions . gsub , Grichelde.functions . toLower , Grichelde.functions . trim , Grichelde.functions . length
local nilOrEmpty , ipairs , spairs , tContains , tFilter , tInsert , tConcat , find , sub , isUpper , isLower , toUpper , toLower , trim , length
= Grichelde.functions . nilOrEmpty , Grichelde.functions . ipairs , Grichelde.functions . spairs , Grichelde.functions . tContains , Grichelde.functions . tFilter , Grichelde.functions . tInsert , Grichelde.functions . tConcat ,
Grichelde.functions . find , Grichelde.functions . sub , Grichelde.functions . isUpper , Grichelde.functions . isLower , Grichelde.functions . toUpper , Grichelde.functions . toLower , Grichelde.functions . trim , Grichelde.functions . length
--- Before a chat message is sent, check if replacement is required and replace the text accordingly.
-- @param message string
@ -13,7 +14,6 @@ local nilOrEmpty, ipairs, tContains, tFilter, tInsert, tConcat, find, sub, gsub,
function Grichelde : SendChatMessage ( message , type , language , channel , ... )
local replacedText = self : CheckAndReplace ( message , type )
self : DebugPrint ( " SendChatMessage : replacedText: " , replacedText )
-- Send text in chunks if length exceeds 255 bytes after replacement
local chunks = self : SplitText ( replacedText )
@ -55,7 +55,7 @@ function Grichelde:CheckReplacement(text, channel)
)
self : DebugPrint ( " CheckReplacement : allowed channels: " , tConcat ( allowedChannels , " , " ) )
local type = self : ConvertBlizChannelToType ( channel )
if ( type ~= nil and not tContains ( allowedChannels , type ) ) then
if ( type == nil or not tContains ( allowedChannels , type ) ) then
self : DebugPrint ( " CheckReplacement : skip channel type: " , type )
return false
end
@ -103,7 +103,7 @@ function Grichelde:ReplaceText(text)
while current <= length ( newText ) do
local currentChar = sub ( newText , current , current )
self : Debug Print( " current/char : %s,%s " , current , currentChar )
self : Trace Print( " current/char : %s,%s " , current , currentChar )
if ( not tContains ( lookAheads , currentChar ) ) then
current = current + 1
@ -194,17 +194,181 @@ end
-- @param text string
-- @return string
function Grichelde : ReplaceCharacters ( text )
-- todo: read from options
-- todo: case (in)sensitivity
-- todo: consolidate consecutive
-- todo: prevent infinite loops - is that even possible?
local replacement = text
replacement = gsub ( replacement , " s " , " ch " )
replacement = gsub ( replacement , " S " , " Ch " )
replacement = gsub ( replacement , " t " , " k " )
replacement = gsub ( replacement , " T " , " K " )
self : DebugPrint ( " ReplaceCharacters : replaced \" %s \" with \" %s \" " , text , replacement )
return replacement
local replacements = self.db . profile.replacements or { }
self : DebugPrint ( " ReplaceCharacters : replacements " )
self : DebugPrint ( replacements )
local result = text
local consolidate = { }
-- replacements are done first
for replName , replTable in spairs ( replacements ) do
local before = result
local search = replTable.searchText
if not nilOrEmpty ( search ) then
local replace = replTable.replaceText
consolidate [ replName ] = { }
if replTable.ignoreCase then
self : DebugPrint ( " ReplaceCharacters : \" %s => %s \" (ignoreCase) " , search , replace )
local pos , offset = 1 , 0
local lowerResult = toLower ( result )
local lowerSearch = toLower ( search )
local pos1 , pos2 = find ( lowerResult , lowerSearch , pos )
while ( pos1 and pos2 ) do
self : TracePrint ( " pos1: %d, pos2: %d " , pos1 , pos2 )
local pre = sub ( result , 1 , pos1 - 1 + offset )
local match = sub ( result , pos1 + offset , pos2 + offset )
local post = sub ( result , pos2 + 1 + offset )
self : TracePrint ( " pre: %s, match: %s, post: %s " , pre , match , post )
-- keep cases
local repl = " "
local lastCase = nil
for p = pos1 , pos2 do
self : TracePrint ( " p: %d " , p )
local c = sub ( match , p - pos1 + 1 , p - pos1 + 1 )
local r = sub ( replace , p - pos1 + 1 , p - pos1 + 1 ) or " "
if ( isUpper ( c ) ) then -- all UPPER-CASE letter
lastCase = true
repl = repl .. toUpper ( r )
elseif ( isLower ( match ) ) then -- all lower_case letter
lastCase = false
repl = repl .. toLower ( r )
else -- no letter
lastCase = nil
repl = repl .. r
end
self : TracePrint ( " character: %s, %s " , c , r )
end
self : TracePrint ( " length %d > %d " , length ( replace ) , pos2 - pos1 + 1 )
if ( length ( replace ) > pos2 - pos1 + 1 ) then
local remainingReplace = sub ( replace , pos2 - pos1 + 2 )
local nextLetter = sub ( post , 1 , 1 )
self : TracePrint ( " rest: %s, n: %s, lastCase: %s " , remainingReplace , nextLetter , lastCase )
if ( isUpper ( nextLetter ) ) then
repl = repl .. toUpper ( remainingReplace )
elseif ( isLower ( nextLetter ) ) then
repl = repl .. toLower ( remainingReplace )
else
-- no letter
repl = repl .. remainingReplace
-- if lastCase == nil then
-- repl = repl .. remainingReplace
-- elseif lastCase == false then
-- repl = repl .. toLower(remainingReplace)
-- else
-- repl = repl .. toUpper(remainingReplace)
-- end
end
end
-- actual replacement
result = pre .. repl .. post
self : DebugPrint ( " result: %s " , result )
-- remember positions for consolidate
if replTable.consolidate then
tInsert ( consolidate [ replName ] , pos1 + offset )
end
-- replacement text can be longer or shorter the resulting text
-- after replacement result and lowerResult can have different sizes
offset = offset + length ( repl ) - length ( lowerSearch )
-- update values for next iteration
pos = pos2 + 1
pos1 , pos2 = find ( lowerResult , lowerSearch , pos )
end
else
-- exact case
self : DebugPrint ( " ReplaceCharacters : \" %s => %s \" (exact case) " , search , replace )
local pos , offset = 1 , 0
local oldResult = result
local pos1 , pos2 = find ( oldResult , search , pos )
while ( pos1 and pos2 ) do
self : TracePrint ( " pos1: %d, pos2: %d " , pos1 , pos2 )
local pre = sub ( result , 1 , pos1 - 1 + offset )
local post = sub ( result , pos2 + 1 + offset )
self : TracePrint ( " pre: %s, post: %s " , pre , post )
-- actual replacement
result = pre .. replace .. post
self : DebugPrint ( " result: %s " , result )
-- remember positions for consolidate
if replTable.consolidate then
tInsert ( consolidate [ replName ] , pos1 + offset )
end
-- replacement text can lengthen or shorten the resulting text
-- after replacement result and lowerResult can have different sizes
offset = offset + length ( replace ) - length ( search )
-- update values for next iteration
pos = pos2 + 1
pos1 , pos2 = find ( oldResult , search , pos )
end
end
if before ~= result then
self : DebugPrint ( " ReplaceCharacters : replaced \" %s \" with \" %s \" " , before , result )
end
else
self : DebugPrint ( " ReplaceCharacters : Skip replacement for empty mapping " )
end
end
-- consolidation is done last
for replName , replTable in spairs ( replacements ) do
local before = result
--local search = replTable.searchText
local search = replTable.searchText
if not nilOrEmpty ( search ) then
local replace = replTable.replaceText
local lowerResult = toLower ( result )
local offset = 0
if replTable.consolidate then
self : DebugPrint ( " ReplaceCharacters : consolidating \" %s => %s \" " , search , replace )
self : DebugPrint ( " consolidate[ " .. replName .. " ] is: " )
self : DebugPrint ( consolidate [ replName ] )
for _ , pos1 in spairs ( consolidate [ replName ] ) do
local pos2 = pos1 + length ( replace ) - 1
self : TracePrint ( " pos1: %d, pos2: %d " , pos1 , pos2 )
local match = sub ( lowerResult , pos1 , pos2 )
local next = sub ( lowerResult , pos2 + 1 , pos2 + 1 + pos2 - pos1 )
self : TracePrint ( " match: %s, next: %s " , match , next )
local _ , p2 = find ( next , " ^ " .. match )
self : TracePrint ( " p2: %d " , p2 )
if ( p2 ) then
result = sub ( result , 1 , pos2 + offset ) .. sub ( result , pos2 + 1 + p2 + offset )
-- consolidation will shorten the resulting text
offset = offset + length ( result ) - length ( lowerResult )
end
self : DebugPrint ( " result: %s " , result )
end
end
if before ~= result then
self : DebugPrint ( " ReplaceCharacters : consolidate \" %s \" with \" %s \" " , before , result )
end
else
self : DebugPrint ( " ReplaceCharacters : Skip consolidation for empty mapping " )
end
end
self : DebugPrint ( " ReplaceCharacters : final text: " , result )
return result
end
--- Splits a long text in longest possible chunks of <= 255 length, split at last available space