diff --git a/Aux-Addon.toc b/Aux-Addon.toc
index 6d439e2..9bf83c1 100644
--- a/Aux-Addon.toc
+++ b/Aux-Addon.toc
@@ -20,5 +20,5 @@ about.xml
list.xml
-completion.lua
+completion.xml
diff --git a/buy.lua b/buy.lua
index a877291..e139fc0 100644
--- a/buy.lua
+++ b/buy.lua
@@ -419,21 +419,12 @@ function AuxBuyTooltipButton_OnClick()
local pattern = AuxBuyTooltipInputBox:GetText()
if pattern ~= '' then
Aux.util.set_add(tooltip_patterns, pattern)
- end
- AuxBuyTooltipInputBox:SetText('')
- if DropDownList1:IsVisible() then
+ if DropDownList1:IsVisible() then
+ Aux.buy.toggle_tooltip_dropdown()
+ end
Aux.buy.toggle_tooltip_dropdown()
end
- Aux.buy.toggle_tooltip_dropdown()
-end
-
-function AuxBuyTooltipRemoveButton_OnClick()
- Aux.util.set_remove(tooltip_patterns, AuxBuyTooltipInputBox:GetText())
AuxBuyTooltipInputBox:SetText('')
- if DropDownList1:IsVisible() then
- Aux.buy.toggle_tooltip_dropdown()
- end
- Aux.buy.toggle_tooltip_dropdown()
end
function AuxBuyTooltipDropDown_Initialize()
@@ -442,6 +433,7 @@ function AuxBuyTooltipDropDown_Initialize()
text = pattern,
value = pattern,
func = AuxBuyTooltipDropDown_OnClick,
+ notCheckable = true,
}
end
end
diff --git a/buy.xml b/buy.xml
index 0c3f6a4..ad50f51 100644
--- a/buy.xml
+++ b/buy.xml
@@ -231,12 +231,19 @@
-
- Aux.util.item_name_autocomplete()
-
+
+ Aux.completion.make_suggestions(this)
+
+
+ Aux.completion.highlight_next(this)
+
- this:ClearFocus()
- Aux.buy.SearchButton_onclick()
+ if Aux.completion.highlighted() then
+ Aux.completion.select(this)
+ else
+ this:ClearFocus()
+ Aux.buy.SearchButton_onclick()
+ end
diff --git a/completion.lua b/completion.lua
index 53dbbed..f33d6d3 100644
--- a/completion.lua
+++ b/completion.lua
@@ -1,44 +1,127 @@
+Aux.completion = {}
+
local NUM_MATCHES = 5
+local leven, fuzzy, populate_dropdown, toggle_dropdown, suggestions, highlight
+
local item_names = {}
-for item_id=1,100 do
+
+local current_suggestions = {}
+local selected_index
+
+
+for item_id=1,30000 do
local name = GetItemInfo(item_id)
- tinsert(item_names, name)
+ if name then
+ tinsert(item_names, name)
+ end
end
-function leven(s,t)
- if s == '' then return strlen(t) end
- if t == '' then return strlen(s) end
-
- local s1 = string.sub(s, 2, -1)
- local t1 = string.sub(t, 2, -1)
-
- if string.sub(s, 0, 1) == string.sub(t, 0, 1) then
- return leven(s1, t1)
- end
-
- return 1 + math.min(
- leven(s1, t1),
- leven(s, t1),
- leven(s1, t)
- )
+function fuzzy(input)
+ local uppercase_input = strupper(input)
+ local pattern = '(.*)'
+ for i=1,strlen(uppercase_input) do
+ pattern = pattern .. string.sub(uppercase_input, i, i) .. '(.*)'
+ end
+ return function(input)
+ local match = { string.find(strupper(input), pattern) }
+ if match[1] then
+ local rating = 1
+ for i=3,getn(match) do
+ rating = rating * max(strlen(match[i]), 1)
+ end
+ return rating
+ end
+ end
end
-function get_matches(input)
- local closest = {}
- for _, name in pairs(item_names) do
- local edit_distance = leven(input, name)
- if getn(closest) < NUM_MATCHES then
- tinsert(closest, { name=name, edit_distance=edit_distance })
+function update_highlighting()
+ for i=1,32 do
+ local highlight = getglobal('DropDownList1Button' .. i .. 'Highlight')
+ if i == selected_index then
+ highlight:Show()
else
- sort(closest, function(a, b) return a.edit_distance > b.edit_distance end)
- if closest[1].edit_distance > edit_distance then
- closest[1] = { name=name, edit_distance=edit_distance }
+ highlight:Hide()
+ end
+ end
+end
+
+function suggestions(input)
+ local matcher = fuzzy(input)
+
+ local best = {}
+ for _, name in ipairs(item_names) do
+ local rating = matcher(name)
+ if rating then
+ if getn(best) < NUM_MATCHES then
+ tinsert(best, { name=name, rating=rating })
+ sort(best, function(a, b) return a.rating < b.rating end)
+ else
+ if best[1].rating > rating then
+ best[1] = { name=name, rating=rating }
+ sort(best, function(a, b) return a.rating < b.rating end)
+ end
end
end
end
- for _, winner in ipairs(closest) do
- Aux.log(winner.name)
+ return Aux.util.map(best, function(match) return match.name end)
+end
+
+function Aux.completion.make_suggestions(input_box)
+ selected_index = nil
+ update_highlighting()
+ local input = input_box:GetText()
+ if input == '' then
+ current_suggestions = {}
+ else
+ current_suggestions = suggestions(input)
+ UIDropDownMenu_Initialize(AuxCompletionDropDown, function() populate_dropdown(input_box, current_suggestions) end)
end
+
+ if DropDownList1:IsVisible() then
+ toggle_dropdown(input_box)
+ end
+ toggle_dropdown(input_box)
+end
+
+function Aux.completion.highlight_next(input_box)
+ if getn(current_suggestions) > 0 then
+ selected_index = selected_index and math.mod(selected_index, getn(current_suggestions)) + 1 or 1
+ end
+ update_highlighting()
+end
+
+function Aux.completion.highlighted()
+ return selected_index ~= nil
+end
+
+function Aux.completion.select(input_box)
+ Aux.completion.set_quietly(input_box, current_suggestions[selected_index])
+ selected_index = nil
+ update_highlighting()
+ CloseDropDownMenus(1)
+end
+
+function Aux.completion.set_quietly(edit_box, text)
+ local orig = edit_box:GetScript('OnTextChanged')
+ edit_box:SetScript('OnTextChanged', function() edit_box:SetScript('OnTextChanged', orig) end)
+ edit_box:SetText(text)
+end
+
+function populate_dropdown(input_box, suggestions)
+ for _, suggestion in ipairs(suggestions) do
+ UIDropDownMenu_AddButton{
+ text = suggestion,
+ value = suggestion,
+ notCheckable = true,
+ func = function()
+ Aux.completion.set_quietly(input_box, this.value)
+ end,
+ }
+ end
+end
+
+function toggle_dropdown(input_box)
+ ToggleDropDownMenu(1, nil, AuxCompletionDropDown, input_box, -12, 4)
end
\ No newline at end of file
diff --git a/completion.xml b/completion.xml
new file mode 100644
index 0000000..c1338bc
--- /dev/null
+++ b/completion.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core.lua b/core.lua
index 96e467e..d6d2779 100644
--- a/core.lua
+++ b/core.lua
@@ -114,7 +114,6 @@ end
function Aux_SetupHookFunctions()
- BrowseName:SetScript('OnChar', Aux.util.item_name_autocomplete)
Aux.orig.AuctionFrameAuctions_OnShow = AuctionFrameAuctions_OnShow
AuctionFrameAuctions_OnShow = Aux_Sell_AuctionFrameAuctions_OnShow
diff --git a/util.lua b/util.lua
index a5a560b..6f5bc69 100644
--- a/util.lua
+++ b/util.lua
@@ -6,6 +6,9 @@ Aux.util.GT = {}
local merge, copy_array
+function Aux.util.pass()
+end
+
function Aux.util.iter(array)
local with_index = ipairs(array)
return function()
@@ -14,20 +17,6 @@ function Aux.util.iter(array)
end
end
-function Aux.util.item_name_autocomplete()
- local text = this:GetText()
- local textlen = strlen(text)
- local name
- for item_id=1,30000 do
- name = GetItemInfo(item_id)
- if name and strfind(strupper(name), '^' .. strupper(text)) then
- this:SetText(name)
- this:HighlightText(textlen, -1)
- return
- end
- end
-end
-
function Aux.util.format_money(val)
local g = math.floor(val / 10000)
@@ -91,14 +80,42 @@ function Aux.util.all(xs, p)
return holds
end
-function Aux.util.set_filter(set, p)
- filtered = {}
- for x, _ in pairs(set) do
+function Aux.util.set_filter(xs, p)
+ ys = {}
+ for x, _ in pairs(xs) do
if p(x) then
- Aux.util.set_add(filtered, x)
+ Aux.util.set_add(ys, x)
end
end
- return filtered
+ return ys
+end
+
+function Aux.util.filter(xs, p)
+ ys = {}
+ for _, x in ipairs(xs) do
+ if p(x) then
+ tinsert(ys, x)
+ end
+ end
+ return ys
+end
+
+function Aux.util.map(xs, f)
+ ys = {}
+ for _, x in ipairs(xs) do
+ tinsert(ys, f(x))
+ end
+ return ys
+end
+
+function Aux.util.take(n, xs)
+ ys = {}
+ for i=1,n do
+ if xs[i] then
+ tinsert(ys, xs[i])
+ end
+ end
+ return ys
end
function Aux.util.merge_sort(A, comp)