diff options
| author | TJ DeVries <devries.timothyj@gmail.com> | 2021-01-11 13:29:37 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-11 13:29:37 -0500 |
| commit | 8783bea06e1e0dfa8dfd4834058923088471d832 (patch) | |
| tree | 050096ba649a94bb01e7c0b3a029e9b4eb060029 /lua/telescope/entry_manager.lua | |
| parent | de80a9837cd1d207981c1f6dbf504436f8bfee13 (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.lua | 221 |
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 |
