summaryrefslogtreecommitdiff
path: root/lua/telescope/entry_manager.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/telescope/entry_manager.lua')
-rw-r--r--lua/telescope/entry_manager.lua131
1 files changed, 131 insertions, 0 deletions
diff --git a/lua/telescope/entry_manager.lua b/lua/telescope/entry_manager.lua
new file mode 100644
index 0000000..bca4e55
--- /dev/null
+++ b/lua/telescope/entry_manager.lua
@@ -0,0 +1,131 @@
+local log = require("telescope.log")
+
+local EntryManager = {}
+EntryManager.__index = EntryManager
+
+function EntryManager:new(max_results, set_entry, info)
+ log.trace("Creating entry_manager...")
+
+ info = info or {}
+ info.looped = 0
+ info.inserted = 0
+
+ -- state contains list of
+ -- {
+ -- score = ...
+ -- line = ...
+ -- metadata ? ...
+ -- }
+ local entry_state = {}
+
+ set_entry = set_entry or function() end
+
+ return setmetatable({
+ set_entry = set_entry,
+ max_results = max_results,
+ worst_acceptable_score = math.huge,
+
+ entry_state = entry_state,
+ info = info,
+
+ num_results = function()
+ return #entry_state
+ end,
+
+ get_ordinal = function(self, index)
+ return self:get_entry(index).ordinal
+ end,
+
+ get_entry = function(_, index)
+ return (entry_state[index] or {}).entry
+ end,
+
+ get_score = function(_, index)
+ return (entry_state[index] or {}).score
+ end,
+
+ find_entry = function(_, entry)
+ if entry == nil then
+ return nil
+ end
+
+ for k, v in ipairs(entry_state) do
+ local existing_entry = v.entry
+
+ -- FIXME: This has the problem of assuming that display will not be the same for two different entries.
+ if existing_entry.display == entry.display then
+ return k
+ end
+ end
+
+ return nil
+ end,
+
+ _get_state = function()
+ return entry_state
+ end,
+ }, self)
+end
+
+function EntryManager:should_save_result(index)
+ return index <= self.max_results
+end
+
+function EntryManager:add_entry(score, entry)
+ score = score or 0
+
+ if score >= self.worst_acceptable_score then
+ return
+ end
+
+ for index, item in ipairs(self.entry_state) do
+ self.info.looped = self.info.looped + 1
+
+ if item.score > score then
+ return self:insert(index, {
+ score = score,
+ entry = entry,
+ })
+ end
+
+ -- Don't add results that are too bad.
+ if not self:should_save_result(index) then
+ return
+ end
+ end
+
+ return self:insert({
+ score = score,
+ entry = entry,
+ })
+end
+
+function EntryManager:insert(index, entry)
+ if entry == nil then
+ entry = index
+ index = #self.entry_state + 1
+ 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]
+
+ self.set_entry(index, entry.entry)
+ self.entry_state[index] = entry
+
+ last_score = entry.score
+
+ index = index + 1
+ entry = next_entry
+ until not next_entry or not self:should_save_result(index)
+
+ if not self:should_save_result(index) then
+ self.worst_acceptable_score = last_score
+ end
+end
+
+
+return EntryManager