summaryrefslogtreecommitdiff
path: root/lua/telescope/entry_manager.lua
diff options
context:
space:
mode:
authorTJ DeVries <devries.timothyj@gmail.com>2021-01-11 13:29:37 -0500
committerGitHub <noreply@github.com>2021-01-11 13:29:37 -0500
commit8783bea06e1e0dfa8dfd4834058923088471d832 (patch)
tree050096ba649a94bb01e7c0b3a029e9b4eb060029 /lua/telescope/entry_manager.lua
parentde80a9837cd1d207981c1f6dbf504436f8bfee13 (diff)
feat: quickfix (#293)
* feat: quickfix (not implemented) * [WIP]: Wed 09 Dec 2020 11:11:30 PM EST * somewhat working linked list impl * getting closer * might be working * might be working for real * works and implemented basic example * dont forget to close prompt * fix descending and add more tests * test fixes * fix test * more logging * Fix some more tests * Fix logging messing up tests * fix: lint * fix: multi select stuffs
Diffstat (limited to 'lua/telescope/entry_manager.lua')
-rw-r--r--lua/telescope/entry_manager.lua221
1 files changed, 141 insertions, 80 deletions
diff --git a/lua/telescope/entry_manager.lua b/lua/telescope/entry_manager.lua
index 237f0e5..c7350cb 100644
--- a/lua/telescope/entry_manager.lua
+++ b/lua/telescope/entry_manager.lua
@@ -1,131 +1,192 @@
local log = require("telescope.log")
+local LinkedList = require('telescope.algos.linked_list')
+
+--[[
+
+OK, new idea.
+We can do linked list here.
+To convert at the end to quickfix, just run the list.
+...
+
+start node
+end node
+
+if past loop of must have scores,
+ then we can just add to end node and shift end node to current node.
+ etc.
+
+
+ always inserts a row, because we clear everything before?
+
+ can also optimize by keeping worst acceptable score around.
+
+--]]
+
local EntryManager = {}
EntryManager.__index = EntryManager
-function EntryManager:new(max_results, set_entry, info)
+function EntryManager:new(max_results, set_entry, info, id)
log.trace("Creating entry_manager...")
info = info or {}
info.looped = 0
info.inserted = 0
+ info.find_loop = 0
-- state contains list of
- -- {
- -- score = ...
- -- line = ...
- -- metadata ? ...
- -- }
- local entry_state = {}
-
+ -- { entry, score }
+ -- Stored directly in a table, accessed as [1], [2]
set_entry = set_entry or function() end
return setmetatable({
- set_entry = set_entry,
+ id = id,
+ linked_states = LinkedList:new { track_at = max_results },
+ info = info,
max_results = max_results,
+ set_entry = set_entry,
worst_acceptable_score = math.huge,
+ }, self)
+end
- entry_state = entry_state,
- info = info,
+function EntryManager:num_results()
+ return self.linked_states.size
+end
- num_results = function()
- return #entry_state
- end,
+function EntryManager:get_container(index)
+ local count = 0
+ for val in self.linked_states:iter() do
+ count = count + 1
- get_ordinal = function(em, index)
- return em:get_entry(index).ordinal
- end,
+ if count == index then
+ return val
+ end
+ end
- get_entry = function(_, index)
- return (entry_state[index] or {}).entry
- end,
+ return {}
+end
+
+function EntryManager:get_entry(index)
+ return self:get_container(index)[1]
+end
- get_score = function(_, index)
- return (entry_state[index] or {}).score
- end,
+function EntryManager:get_score(index)
+ return self:get_container(index)[2]
+end
- find_entry = function(_, entry)
- if entry == nil then
- return nil
- end
+function EntryManager:get_ordinal(index)
+ return self:get_entry(index).ordinal
+end
- for k, v in ipairs(entry_state) do
- local existing_entry = v.entry
+function EntryManager:find_entry(entry)
+ local info = self.info
- -- FIXME: This has the problem of assuming that display will not be the same for two different entries.
- if existing_entry == entry then
- return k
- end
- end
+ local count = 0
+ for container in self.linked_states:iter() do
+ count = count + 1
- return nil
- end,
+ if container[1] == entry then
+ info.find_loop = info.find_loop + count
- _get_state = function()
- return entry_state
- end,
- }, self)
-end
+ return count
+ end
+ end
-function EntryManager:should_save_result(index)
- return index <= self.max_results
+ info.find_loop = info.find_loop + count
+ return nil
end
-function EntryManager:add_entry(picker, score, entry)
- score = score or 0
+function EntryManager:_update_score_from_tracked()
+ local linked = self.linked_states
- if score >= self.worst_acceptable_score then
- return
+ if linked.tracked then
+ self.worst_acceptable_score = math.min(self.worst_acceptable_score, linked.tracked[2])
end
+end
- for index, item in ipairs(self.entry_state) do
- self.info.looped = self.info.looped + 1
+function EntryManager:_insert_container_before(picker, index, linked_node, new_container)
+ self.linked_states:place_before(index, linked_node, new_container)
+ self.set_entry(picker, index, new_container[1], new_container[2], true)
- if item.score > score then
- return self:insert(picker, index, {
- score = score,
- entry = entry,
- })
- end
+ self:_update_score_from_tracked()
+end
- -- Don't add results that are too bad.
- if not self:should_save_result(index) then
+function EntryManager:_insert_container_after(picker, index, linked_node, new_container)
+ self.linked_states:place_after(index, linked_node, new_container)
+ self.set_entry(picker, index, new_container[1], new_container[2], true)
+
+ self:_update_score_from_tracked()
+end
+
+function EntryManager:_append_container(picker, new_container, should_update)
+ self.linked_states:append(new_container)
+ self.worst_acceptable_score = math.min(self.worst_acceptable_score, new_container[2])
+
+ if should_update then
+ self.set_entry(picker, self.linked_states.size, new_container[1], new_container[2])
+ end
+end
+
+function EntryManager:add_entry(picker, score, entry)
+ if picker and picker.id then
+ if picker.request_number ~= self.id then
+ error("ADDING ENTRY TOO LATE!")
return
end
end
- return self:insert(picker, {
- score = score,
- entry = entry,
- })
-end
+ score = score or 0
+
+ local max_res = self.max_results
+ local worst_score = self.worst_acceptable_score
+ local size = self.linked_states.size
+
+ local info = self.info
+ info.maxed = info.maxed or 0
-function EntryManager:insert(picker, index, entry)
- if entry == nil then
- entry = index
- index = #self.entry_state + 1
+ local new_container = { entry, score, }
+
+ -- Short circuit for bad scores -- they never need to be displayed.
+ -- Just save them and we'll deal with them later.
+ if score >= worst_score then
+ return self.linked_states:append(new_container)
end
- -- To insert something, we place at the next available index (or specified index)
- -- and then shift all the corresponding items one place.
- local next_entry, last_score
- repeat
- self.info.inserted = self.info.inserted + 1
- next_entry = self.entry_state[index]
+ -- Short circuit for first entry.
+ if size == 0 then
+ self.linked_states:prepend(new_container)
+ self.set_entry(picker, 1, entry, score)
+ return
+ end
- self.set_entry(picker, index, entry.entry, entry.score)
- self.entry_state[index] = entry
+ for index, container, node in self.linked_states:ipairs() do
+ info.looped = info.looped + 1
- last_score = entry.score
+ if container[2] > score then
+ -- print("Inserting: ", picker, index, node, new_container)
+ return self:_insert_container_before(picker, index, node, new_container)
+ end
- index = index + 1
- entry = next_entry
- until not next_entry or not self:should_save_result(index)
+ -- Don't add results that are too bad.
+ if index >= max_res then
+ info.maxed = info.maxed + 1
+ return self:_append_container(picker, new_container, false)
+ end
+ end
- if not self:should_save_result(index) then
- self.worst_acceptable_score = last_score
+ if self.linked_states.size >= max_res then
+ self.worst_acceptable_score = math.min(self.worst_acceptable_score, score)
end
+
+ return self:_insert_container_after(picker, size + 1, self.linked_states.tail, new_container)
end
+function EntryManager:iter()
+ return coroutine.wrap(function()
+ for val in self.linked_states:iter() do
+ coroutine.yield(val[1])
+ end
+ end)
+end
return EntryManager