Skip to content

Commit 656ec6f

Browse files
Add support for regex OR to tree and item search (#5766)
* Add support for regex or to tree * Fix mixed white space * Add support for item search * Avoid evaluating invalid patterns * Call and catch error like with tree to avoid other pattern matching crashes. * Escape all characters expect brackets and | * cleanup variable naming and a couple of pieces of the code * Allow brackets in tree search * Add support to anoint sorting
1 parent aeee2f2 commit 656ec6f

File tree

5 files changed

+62
-12
lines changed

5 files changed

+62
-12
lines changed

src/Classes/ItemDBControl.lua

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,38 +137,43 @@ function ItemDBClass:DoesItemMatchFilters(item)
137137
return false
138138
end
139139
end
140-
local searchStr = self.controls.search.buf:lower()
140+
local searchStr = self.controls.search.buf:lower():gsub("[%-%.%+%[%]%$%^%%%?%*]", "%%%0")
141141
if searchStr:match("%S") then
142142
local found = false
143143
local mode = self.controls.searchMode.selIndex
144144
if mode == 1 or mode == 2 then
145-
if item.name:lower():find(searchStr, 1, true) then
145+
local err, match = PCall(string.matchOrPattern, item.name:lower(), searchStr)
146+
if not err and match then
146147
found = true
147148
end
148149
end
149150
if mode == 1 or mode == 3 then
150151
for _, line in pairs(item.enchantModLines) do
151-
if line.line:lower():find(searchStr, 1, true) then
152+
local err, match = PCall(string.matchOrPattern, line.line:lower(), searchStr)
153+
if not err and match then
152154
found = true
153155
break
154156
end
155157
end
156158
for _, line in pairs(item.implicitModLines) do
157-
if line.line:lower():find(searchStr, 1, true) then
159+
local err, match = PCall(string.matchOrPattern, line.line:lower(), searchStr)
160+
if not err and match then
158161
found = true
159162
break
160163
end
161164
end
162165
for _, line in pairs(item.explicitModLines) do
163-
if line.line:lower():find(searchStr, 1, true) then
166+
local err, match = PCall(string.matchOrPattern, line.line:lower(), searchStr)
167+
if not err and match then
164168
found = true
165169
break
166170
end
167171
end
168172
if not found then
169173
searchStr = searchStr:gsub(" ","")
170174
for i, mod in ipairs(item.baseModList) do
171-
if mod.name:lower():find(searchStr, 1, true) then
175+
local err, match = PCall(string.matchOrPattern, mod.name:lower(), searchStr)
176+
if not err and match then
172177
found = true
173178
break
174179
end

src/Classes/NotableDBControl.lua

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,20 @@ function NotableDBClass:DoesNotableMatchFilters(node)
5252
return false
5353
end
5454

55-
local searchStr = self.controls.search.buf:lower()
55+
local searchStr = self.controls.search.buf:lower():gsub("[%-%.%+%[%]%$%^%%%?%*]", "%%%0")
5656
if searchStr:match("%S") then
5757
local found = false
5858
local mode = self.controls.searchMode.selIndex
5959
if mode == 1 or mode == 2 then
60-
if node.dn:lower():find(searchStr, 1, true) then
60+
local err, match = PCall(string.matchOrPattern, node.dn:lower(), searchStr)
61+
if not err and match then
6162
found = true
6263
end
6364
end
6465
if mode == 1 or mode == 3 then
6566
for _, line in ipairs(node.sd) do
66-
if line:lower():find(searchStr, 1, true) then
67+
local err, match = PCall(string.matchOrPattern, line:lower(), searchStr)
68+
if not err and match then
6769
found = true
6870
break
6971
end

src/Classes/PassiveTreeView.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents)
439439
local searchWords = {}
440440
for matchstring, v in search:gmatch('"([^"]*)"') do
441441
searchWords[#searchWords+1] = matchstring
442-
search = search:gsub('"'..matchstring..'"', "")
442+
search = search:gsub('"'..matchstring:gsub("([%(%)])", "%%%1")..'"', "")
443443
end
444444
for matchstring, v in search:gmatch("(%S*)") do
445445
if matchstring:match("%S") ~= nil then
@@ -804,7 +804,7 @@ function PassiveTreeViewClass:DoesNodeMatchSearchParams(node)
804804

805805
local function search(haystack, need)
806806
for i=#need, 1, -1 do
807-
if haystack:match(need[i]) then
807+
if haystack:matchOrPattern(need[i]) then
808808
table.remove(need, i)
809809
end
810810
end

src/Classes/TreeTab.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build)
118118
self.controls.export = new("ButtonControl", { "LEFT", self.controls.import, "RIGHT" }, 8, 0, 90, 20, "Export Tree", function()
119119
self:OpenExportPopup()
120120
end)
121-
self.controls.treeSearch = new("EditControl", { "LEFT", self.controls.export, "RIGHT" }, 8, 0, main.portraitMode and 200 or 300, 20, "", "Search", "%c%(%)", 100, function(buf)
121+
self.controls.treeSearch = new("EditControl", { "LEFT", self.controls.export, "RIGHT" }, 8, 0, main.portraitMode and 200 or 300, 20, "", "Search", "%c", 100, function(buf)
122122
self.viewer.searchStr = buf
123123
self.searchFlag = buf ~= self.viewer.searchStrSaved
124124
end)

src/Modules/Common.lua

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,4 +859,47 @@ function urlDecode(str)
859859
return s_char(tonumber(x, 16))
860860
end
861861
return str:gsub("%%(%x%x)", hexToChar)
862+
end
863+
864+
function string:matchOrPattern(pattern)
865+
local function generateOrPatterns(pattern)
866+
local subGroups = {}
867+
local index = 1
868+
-- find and call generate patterns on all subGroups
869+
for subGroup in pattern:gmatch("%b()") do
870+
local open, close = pattern:find(subGroup, (subGroups[index] and subGroups[index].close or 1), true)
871+
t_insert(subGroups, { open = open, close = close, patterns = generateOrPatterns(subGroup:sub(2,-2)) })
872+
index = index + 1
873+
end
874+
875+
-- generate complete patterns from the subGroup patterns
876+
local generatedPatterns = { pattern:sub(1, (subGroups[1] and subGroups[1].open or 0) - 1) }
877+
for i, subGroup in ipairs(subGroups) do
878+
local regularNextString = pattern:sub(subGroup.close + 1, (subGroups[i+1] and subGroups[i+1].open or 0) - 1)
879+
local tempPatterns = {}
880+
for _, subPattern in ipairs(generatedPatterns) do
881+
for subGroupPattern in pairs(subGroup.patterns) do
882+
t_insert(tempPatterns, subPattern..subGroupPattern..regularNextString)
883+
end
884+
end
885+
generatedPatterns = tempPatterns
886+
end
887+
888+
-- apply | operators
889+
local orPatterns = { }
890+
for _, generatedPattern in ipairs(generatedPatterns) do
891+
for orPattern in generatedPattern:gmatch("[^|]+") do
892+
orPatterns[orPattern] = true -- store string as key to avoid duplicates.
893+
end
894+
end
895+
return orPatterns
896+
end
897+
898+
local orPatterns = generateOrPatterns(pattern)
899+
for orPattern in pairs(orPatterns) do
900+
if self:match(orPattern) then
901+
return true
902+
end
903+
end
904+
return false
862905
end

0 commit comments

Comments
 (0)