From 279f1dd3e1945ca982e93b37443274300f1bb788 Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Thu, 11 Feb 2021 11:18:20 -0500 Subject: [PATCH] wip: having some highlighting / flickering issues --- lua/telescope/algos/linked_list.lua | 40 +++++++++++++ lua/telescope/finders/executor.lua | 76 +++++++++++++++++++----- lua/telescope/finders/static.lua | 61 +++++++++++++++++++ lua/telescope/mappings.lua | 4 +- lua/telescope/pickers.lua | 5 +- lua/tests/automated/linked_list_spec.lua | 62 +++++++++++++++++++ scratch/executor_test.lua | 33 ++++++++++ 7 files changed, 265 insertions(+), 16 deletions(-) create mode 100644 scratch/executor_test.lua diff --git a/lua/telescope/algos/linked_list.lua b/lua/telescope/algos/linked_list.lua index cf1c47d..d48f8ed 100644 --- a/lua/telescope/algos/linked_list.lua +++ b/lua/telescope/algos/linked_list.lua @@ -83,6 +83,46 @@ function LinkedList:prepend(item) end end +function LinkedList:shift() + if self.size == 0 then + return nil + end + + local head = self.head + + if head == self.tail then + self.tail = nil + end + + self.head = head.next + if self.head then + self.head.prev = nil + end + + self.size = self.size - 1 + return head.item +end + +function LinkedList:pop() + if self.size == 0 then + return nil + end + + local tail = self.tail + + if tail == self.head then + self.head = nil + end + + self.tail = tail.prev + if self.tail then + self.tail.next = nil + end + + self.size = self.size - 1 + return tail.item +end + -- [a, b, c] -- b.prev = a -- b.next = c diff --git a/lua/telescope/finders/executor.lua b/lua/telescope/finders/executor.lua index b0f29e4..877aff5 100644 --- a/lua/telescope/finders/executor.lua +++ b/lua/telescope/finders/executor.lua @@ -1,5 +1,8 @@ +local co = coroutine local uv = vim.loop +local LinkedList = require('telescope.algos.linked_list') + local modes = setmetatable({ init = "init", next = "next", @@ -8,14 +11,23 @@ local modes = setmetatable({ error(string.format("'%s' is not a valid mode", k)) end }) +local is_dead = function(c) + return co.status(c) == "dead" +end + local Executor = {} Executor.__index = Executor -function Executor:new() +-- TODO: I would like to make it so we just have one function for each task, +-- but I think it's fine for now to store both things. +function Executor:new(func) return setmetatable({ - tasks = {}, - mode = modes.next, - index = 1, + func = func, + + -- mode = modes.init, + -- tasks = LinkedList:new(), + + -- Will be initialized at each run. _idle = nil, }, self) end @@ -23,35 +35,71 @@ end function Executor:run() if not self._idle then self._idle = uv.new_idle() + -- self._idle = uv.new_check() end - self._idle:start(function() - if #self.tasks == 0 then - return self:stop() + self._idle:start((function() + -- if self.tasks.size == 0 then + -- return self:stop() + -- end + self:step() + + if true then return end + + if self.mode == modes.init then + self:start() end - if self.mode == modes.init - or self.mode == modes.next then + if self.mode == modes.next then self:step() elseif self.mode == modes.done then self:complete() else error(debug.traceback("Unknown mode: " .. tostring(self.mode))) end - end) + end)) +end + +function Executor:start() + self.mode = modes.next +end + +function Executor:step() + co.resume(self.func) + if is_dead(self.func) then + print("DEAD") + -- self.tasks:shift() + return self:stop() + else + return self + end + + if self.tasks.size == 0 then return end + + local task = self.tasks.head.item + if task == nil then + error("Should not get step with no tasks left") + end + + local task_co = task[1] + co.resume(task_co, unpack(task[2])) + if is_dead(task_co) then + print("DEAD") + self.tasks:shift() + end end function Executor:complete() end -function Executor:step() - if #self.tasks == 0 then return end -end - function Executor:stop() + if not self._idle then return end + self._idle:stop() self._idle:close() self._idle = nil return self end + +return Executor diff --git a/lua/telescope/finders/static.lua b/lua/telescope/finders/static.lua index e69de29..df5c9fe 100644 --- a/lua/telescope/finders/static.lua +++ b/lua/telescope/finders/static.lua @@ -0,0 +1,61 @@ +local co = coroutine + +local Executor = require("telescope.finders.executor") +local make_entry = require('telescope.make_entry') + +local StaticFinder = {} +StaticFinder.__index = StaticFinder + +function StaticFinder:new(opts) + assert(opts, "Options are required. See documentation for usage") + + local input_results = assert(opts.results) + local entry_maker = opts.entry_maker or make_entry.gen_from_string() + local operations = opts.operations or 1 + + assert(type(input_results) == 'table', "results must be a table") + + local results = {} + for k, v in ipairs(input_results) do + local entry = entry_maker(v) + + if entry then + entry.index = k + table.insert(results, entry) + end + end + + return setmetatable({ + results = results, + _operations = operations, + }, self) +end + +local try_idle = true +function StaticFinder:__call(_, process_result, process_complete) + if not try_idle then + return self:_find(_, process_result, process_complete) + end + + print("CALLING STATIC FIND", _, process_result, process_complete) + local executor = Executor:new(co.create(function() + for index, v in ipairs(self.results) do + process_result(v) + co.yield() + end + + process_complete() + end)) + + executor:run() +end + +function StaticFinder:_find(_, process_result, process_complete) + for _, v in ipairs(self.results) do + process_result(v) + end + + process_complete() +end + +return StaticFinder diff --git a/lua/telescope/mappings.lua b/lua/telescope/mappings.lua index 499be3e..be0d54e 100644 --- a/lua/telescope/mappings.lua +++ b/lua/telescope/mappings.lua @@ -47,7 +47,7 @@ mappings.default_mappings = config.values.default_mappings or { }, } -local keymap_store = setmetatable({}, { +TelescopeKeyMapper = TelescopeKeyMapper or setmetatable({}, { __index = function(t, k) rawset(t, k, {}) @@ -55,6 +55,8 @@ local keymap_store = setmetatable({}, { end }) +local keymap_store = TelescopeKeyMapper + local _mapping_key_id = 0 local get_next_id = function() _mapping_key_id = _mapping_key_id + 1 diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 1a74bc3..05e37ff 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -780,7 +780,7 @@ function Picker:entry_adder(index, entry, _, insert) end if self.request_number ~= scheduled_request then - log.debug("Cancelling request number:", self.request_number, " // ", scheduled_request) + -- log.debug("Cancelling request number:", self.request_number, " // ", scheduled_request) return end @@ -795,6 +795,9 @@ function Picker:entry_adder(index, entry, _, insert) end end + if insert then + log.info("Inserting...", display) + end local set_ok, msg = pcall(vim.api.nvim_buf_set_lines, self.results_bufnr, row, row + offset, false, {display}) if set_ok and display_highlights then self.highlighter:hi_display(row, prefix, display_highlights) diff --git a/lua/tests/automated/linked_list_spec.lua b/lua/tests/automated/linked_list_spec.lua index 49c035a..eca18ae 100644 --- a/lua/tests/automated/linked_list_spec.lua +++ b/lua/tests/automated/linked_list_spec.lua @@ -1,5 +1,7 @@ local LinkedList = require('telescope.algos.linked_list') +local eq = assert.are.same + describe('LinkedList', function() it('can create a list', function() local l = LinkedList:new() @@ -129,5 +131,65 @@ describe('LinkedList', function() assert.are.same("first", l.tracked) end) + + describe(':shift()', function() + it('should return nil for empty list', function() + local l = LinkedList:new() + + eq(nil, l:shift()) + end) + + it('should return the first element, and then nothing if length 1', function() + local l = LinkedList:new { track_at = 2 } + l:append('hello') + + eq('hello', l:shift()) + eq(0, l.size) + + eq(nil, l:shift()) + end) + + it('should return each element', function() + local l = LinkedList:new { track_at = 2 } + l:append('hello') + l:append('world') + l:append('last') + + eq('hello', l:shift()) + eq('world', l:shift()) + + eq(1, l.size) + end) + end) + + describe(':pop()', function() + it('should return nil for empty list', function() + local l = LinkedList:new() + + eq(nil, l:pop()) + end) + + it('should return the first element, and then nothing if length 1', function() + local l = LinkedList:new { track_at = 2 } + l:append('hello') + + eq('hello', l:pop()) + eq(0, l.size) + + eq(nil, l:pop()) + end) + + it('should return each element', function() + local l = LinkedList:new { track_at = 2 } + l:append('hello') + l:append('world') + l:append('last') + + eq('last', l:pop()) + eq('world', l:pop()) + + eq(1, l.size) + end) + end) end) end) diff --git a/scratch/executor_test.lua b/scratch/executor_test.lua new file mode 100644 index 0000000..20bfb0d --- /dev/null +++ b/scratch/executor_test.lua @@ -0,0 +1,33 @@ +RELOAD("telescope") + +local make_entry = require('telescope.make_entry') +local pickers = require('telescope.pickers') +local conf = require('telescope.config').values +local themes = require('telescope.themes') + + +local find_files = function(opts) + opts = themes.get_dropdown { + winblend = 10, + border = true, + previewer = false, + shorten_path = false, + } + + local files = vim.fn.systemlist('rg --files') + opts.entry_maker = opts.entry_maker or make_entry.gen_from_file(opts) + + + pickers.new(opts, { + prompt_title = 'Find Files', + finder = require('telescope.finders.static'):new { + operations = 1000, + results = files, + entry_maker = make_entry.gen_from_file(opts), + }, + previewer = conf.file_previewer(opts), + sorter = conf.file_sorter(opts), + }):find() +end + +find_files()