|
|
|
@@ -213,28 +213,17 @@ function Picker:clear_extra_rows(results_bufnr)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
if not ok then
|
|
|
|
if not ok then
|
|
|
|
log.debug(msg)
|
|
|
|
log.debug("Failed to set lines:", msg)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
log.trace("Clearing:", worst_line)
|
|
|
|
log.trace("Clearing:", worst_line)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:highlight_displayed_rows(results_bufnr, prompt)
|
|
|
|
function Picker:highlight_one_row(results_bufnr, prompt, display, row)
|
|
|
|
if not self.sorter or not self.sorter.highlighter then
|
|
|
|
if not self.sorter.highlighter then
|
|
|
|
return
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_clear_namespace(results_bufnr, ns_telescope_matching, 0, -1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local displayed_rows = vim.api.nvim_buf_get_lines(results_bufnr, 0, -1, false)
|
|
|
|
|
|
|
|
for row_index = 1, math.min(#displayed_rows, self.max_results) do
|
|
|
|
|
|
|
|
local display = displayed_rows[row_index]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self:highlight_one_row(results_bufnr, prompt, display, row_index - 1)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:highlight_one_row(results_bufnr, prompt, display, row)
|
|
|
|
|
|
|
|
local highlights = self.sorter:highlighter(prompt, display)
|
|
|
|
local highlights = self.sorter:highlighter(prompt, display)
|
|
|
|
|
|
|
|
|
|
|
|
if highlights then
|
|
|
|
if highlights then
|
|
|
|
@@ -352,22 +341,19 @@ function Picker:find()
|
|
|
|
self.prompt_prefix = prompt_prefix
|
|
|
|
self.prompt_prefix = prompt_prefix
|
|
|
|
self:_reset_prefix_color()
|
|
|
|
self:_reset_prefix_color()
|
|
|
|
|
|
|
|
|
|
|
|
-- First thing we want to do is set all the lines to blank.
|
|
|
|
-- TODO: This could be configurable in the future, but I don't know why you would
|
|
|
|
self.max_results = popup_opts.results.height
|
|
|
|
-- want to scroll through more than 10,000 items.
|
|
|
|
|
|
|
|
--
|
|
|
|
|
|
|
|
-- This just lets us stop doing stuff after tons of things.
|
|
|
|
|
|
|
|
self.max_results = 1000
|
|
|
|
|
|
|
|
|
|
|
|
-- TODO(scrolling): This may be a hack when we get a little further into implementing scrolling.
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_lines(results_bufnr, 0, self.max_results, false, utils.repeated_table(self.max_results, ""))
|
|
|
|
vim.api.nvim_buf_set_lines(results_bufnr, 0, self.max_results, false, utils.repeated_table(self.max_results, ""))
|
|
|
|
|
|
|
|
|
|
|
|
-- TODO(status): I would love to get the status text not moving back and forth. Perhaps it is just a problem with
|
|
|
|
|
|
|
|
-- virtual text & prompt buffers or something though. I can't figure out why it would redraw the way it does.
|
|
|
|
|
|
|
|
--
|
|
|
|
|
|
|
|
-- A "hacked" version of this would be to calculate where the area I want the status to go and put a new window there.
|
|
|
|
|
|
|
|
-- With this method, I do not need to worry about padding or antying, just make it take up X characters or something.
|
|
|
|
|
|
|
|
local status_updater = self:get_status_updater(prompt_win, prompt_bufnr)
|
|
|
|
local status_updater = self:get_status_updater(prompt_win, prompt_bufnr)
|
|
|
|
local debounced_status = debounce.throttle_leading(status_updater, 50)
|
|
|
|
local debounced_status = debounce.throttle_leading(status_updater, 50)
|
|
|
|
|
|
|
|
|
|
|
|
local tx, rx = channel.mpsc()
|
|
|
|
local tx, rx = channel.mpsc()
|
|
|
|
self.__on_lines = tx.send
|
|
|
|
self._on_lines = tx.send
|
|
|
|
|
|
|
|
|
|
|
|
local find_id = self:_next_find_id()
|
|
|
|
local find_id = self:_next_find_id()
|
|
|
|
|
|
|
|
|
|
|
|
@@ -412,25 +398,14 @@ function Picker:find()
|
|
|
|
|
|
|
|
|
|
|
|
local start_time = vim.loop.hrtime()
|
|
|
|
local start_time = vim.loop.hrtime()
|
|
|
|
|
|
|
|
|
|
|
|
local prompt = self:_get_prompt()
|
|
|
|
local prompt = self:_get_next_filtered_prompt()
|
|
|
|
local on_input_result = self._on_input_filter_cb(prompt) or {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local new_prompt = on_input_result.prompt
|
|
|
|
|
|
|
|
if new_prompt then
|
|
|
|
|
|
|
|
prompt = new_prompt
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local new_finder = on_input_result.updated_finder
|
|
|
|
|
|
|
|
if new_finder then
|
|
|
|
|
|
|
|
self.finder:close()
|
|
|
|
|
|
|
|
self.finder = new_finder
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
|
|
|
|
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
|
|
|
|
if self.cache_picker == false or not (self.cache_picker.is_cached == true) then
|
|
|
|
if self.cache_picker == false or not (self.cache_picker.is_cached == true) then
|
|
|
|
self.sorter:_start(prompt)
|
|
|
|
self.sorter:_start(prompt)
|
|
|
|
self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats)
|
|
|
|
self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_clear_namespace(results_bufnr, ns_telescope_matching, 0, -1)
|
|
|
|
local process_result = self:get_result_processor(find_id, prompt, debounced_status)
|
|
|
|
local process_result = self:get_result_processor(find_id, prompt, debounced_status)
|
|
|
|
local process_complete = self:get_result_completor(self.results_bufnr, find_id, prompt, status_updater)
|
|
|
|
local process_complete = self:get_result_completor(self.results_bufnr, find_id, prompt, status_updater)
|
|
|
|
|
|
|
|
|
|
|
|
@@ -447,26 +422,8 @@ function Picker:find()
|
|
|
|
async.util.sleep(self.debounce - diff_time)
|
|
|
|
async.util.sleep(self.debounce - diff_time)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
else
|
|
|
|
-- resume previous picker
|
|
|
|
-- TODO(scroll): This can only happen once, I don't like where it is.
|
|
|
|
local index = 1
|
|
|
|
self:_resume_picker()
|
|
|
|
for entry in self.manager:iter() do
|
|
|
|
|
|
|
|
self:entry_adder(index, entry, _, true)
|
|
|
|
|
|
|
|
index = index + 1
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
self.cache_picker.is_cached = false
|
|
|
|
|
|
|
|
-- if text changed, required to set anew to restart finder; otherwise hl and selection
|
|
|
|
|
|
|
|
if self.cache_picker.cached_prompt ~= self.default_text then
|
|
|
|
|
|
|
|
self:reset_prompt()
|
|
|
|
|
|
|
|
self:set_prompt(self.default_text)
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
-- scheduling required to apply highlighting and selection appropriately
|
|
|
|
|
|
|
|
await_schedule(function()
|
|
|
|
|
|
|
|
self:highlight_displayed_rows(self.results_bufnr, self.cache_picker.cached_prompt)
|
|
|
|
|
|
|
|
if self.cache_picker.selection_row ~= nil then
|
|
|
|
|
|
|
|
self:set_selection(self.cache_picker.selection_row)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
@@ -476,10 +433,10 @@ function Picker:find()
|
|
|
|
on_lines = function(...)
|
|
|
|
on_lines = function(...)
|
|
|
|
find_id = self:_next_find_id()
|
|
|
|
find_id = self:_next_find_id()
|
|
|
|
|
|
|
|
|
|
|
|
self._result_completed = false
|
|
|
|
|
|
|
|
status_updater { completed = false }
|
|
|
|
status_updater { completed = false }
|
|
|
|
tx.send(...)
|
|
|
|
self._on_lines(...)
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
|
|
on_detach = function()
|
|
|
|
on_detach = function()
|
|
|
|
self:_detach()
|
|
|
|
self:_detach()
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
@@ -753,7 +710,7 @@ function Picker:refresh(finder, opts)
|
|
|
|
self._multi = MultiSelect:new()
|
|
|
|
self._multi = MultiSelect:new()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
self.__on_lines(nil, nil, nil, 0, 1)
|
|
|
|
self._on_lines(nil, nil, nil, 0, 1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:set_selection(row)
|
|
|
|
function Picker:set_selection(row)
|
|
|
|
@@ -856,6 +813,8 @@ function Picker:set_selection(row)
|
|
|
|
self._selection_row = row
|
|
|
|
self._selection_row = row
|
|
|
|
|
|
|
|
|
|
|
|
self:refresh_previewer()
|
|
|
|
self:refresh_previewer()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_win_set_cursor(self.results_win, { row + 1, 0 })
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:refresh_previewer()
|
|
|
|
function Picker:refresh_previewer()
|
|
|
|
@@ -918,9 +877,7 @@ function Picker:entry_adder(index, entry, _, insert)
|
|
|
|
|
|
|
|
|
|
|
|
self:_increment "displayed"
|
|
|
|
self:_increment "displayed"
|
|
|
|
|
|
|
|
|
|
|
|
-- TODO: Don't need to schedule this if we schedule the adder.
|
|
|
|
|
|
|
|
local offset = insert and 0 or 1
|
|
|
|
local offset = insert and 0 or 1
|
|
|
|
vim.schedule(function()
|
|
|
|
|
|
|
|
if not vim.api.nvim_buf_is_valid(self.results_bufnr) then
|
|
|
|
if not vim.api.nvim_buf_is_valid(self.results_bufnr) then
|
|
|
|
log.debug "ON_ENTRY: Invalid buffer"
|
|
|
|
log.debug "ON_ENTRY: Invalid buffer"
|
|
|
|
return
|
|
|
|
return
|
|
|
|
@@ -942,6 +899,7 @@ function Picker:entry_adder(index, entry, _, insert)
|
|
|
|
local set_ok, msg = pcall(vim.api.nvim_buf_set_lines, self.results_bufnr, row, row + offset, false, { display })
|
|
|
|
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
|
|
|
|
if set_ok and display_highlights then
|
|
|
|
self.highlighter:hi_display(row, prefix, display_highlights)
|
|
|
|
self.highlighter:hi_display(row, prefix, display_highlights)
|
|
|
|
|
|
|
|
self:highlight_one_row(self.results_bufnr, self:_get_prompt(), display, row)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
if not set_ok then
|
|
|
|
if not set_ok then
|
|
|
|
@@ -954,7 +912,6 @@ function Picker:entry_adder(index, entry, _, insert)
|
|
|
|
display = display:gsub("\n", " | ")
|
|
|
|
display = display:gsub("\n", " | ")
|
|
|
|
vim.api.nvim_buf_set_lines(self.results_bufnr, row, row + 1, false, { display })
|
|
|
|
vim.api.nvim_buf_set_lines(self.results_bufnr, row, row + 1, false, { display })
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:_reset_track()
|
|
|
|
function Picker:_reset_track()
|
|
|
|
@@ -1025,6 +982,8 @@ function Picker:get_status_updater(prompt_win, prompt_bufnr)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:get_result_processor(find_id, prompt, status_updater)
|
|
|
|
function Picker:get_result_processor(find_id, prompt, status_updater)
|
|
|
|
|
|
|
|
local count = 0
|
|
|
|
|
|
|
|
|
|
|
|
local cb_add = function(score, entry)
|
|
|
|
local cb_add = function(score, entry)
|
|
|
|
self.manager:add_entry(self, score, entry)
|
|
|
|
self.manager:add_entry(self, score, entry)
|
|
|
|
status_updater { completed = false }
|
|
|
|
status_updater { completed = false }
|
|
|
|
@@ -1045,6 +1004,8 @@ function Picker:get_result_processor(find_id, prompt, status_updater)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
count = count + 1
|
|
|
|
|
|
|
|
|
|
|
|
-- TODO: Probably should asyncify this / cache this / do something because this probably takes
|
|
|
|
-- TODO: Probably should asyncify this / cache this / do something because this probably takes
|
|
|
|
-- a ton of time on large results.
|
|
|
|
-- a ton of time on large results.
|
|
|
|
log.trace("Processing result... ", entry)
|
|
|
|
log.trace("Processing result... ", entry)
|
|
|
|
@@ -1060,6 +1021,13 @@ function Picker:get_result_processor(find_id, prompt, status_updater)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
self.sorter:score(prompt, entry, cb_add, cb_filter)
|
|
|
|
self.sorter:score(prompt, entry, cb_add, cb_filter)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Only on the first addition do we want to set the selection.
|
|
|
|
|
|
|
|
-- This allows us to handle moving the cursor to the bottom or top of the window
|
|
|
|
|
|
|
|
-- depending on the strategy.
|
|
|
|
|
|
|
|
if count == 1 then
|
|
|
|
|
|
|
|
self:_do_selection(prompt)
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1075,12 +1043,9 @@ function Picker:get_result_completor(results_bufnr, find_id, prompt, status_upda
|
|
|
|
status_updater { completed = true }
|
|
|
|
status_updater { completed = true }
|
|
|
|
|
|
|
|
|
|
|
|
self:clear_extra_rows(results_bufnr)
|
|
|
|
self:clear_extra_rows(results_bufnr)
|
|
|
|
self:highlight_displayed_rows(results_bufnr, prompt)
|
|
|
|
|
|
|
|
self.sorter:_finish(prompt)
|
|
|
|
self.sorter:_finish(prompt)
|
|
|
|
|
|
|
|
|
|
|
|
self:_on_complete()
|
|
|
|
self:_on_complete()
|
|
|
|
|
|
|
|
|
|
|
|
self._result_completed = true
|
|
|
|
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1226,6 +1191,46 @@ function Picker:_detach()
|
|
|
|
self.closed = true
|
|
|
|
self.closed = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:_get_next_filtered_prompt()
|
|
|
|
|
|
|
|
local prompt = self:_get_prompt()
|
|
|
|
|
|
|
|
local on_input_result = self._on_input_filter_cb(prompt) or {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local new_prompt = on_input_result.prompt
|
|
|
|
|
|
|
|
if new_prompt then
|
|
|
|
|
|
|
|
prompt = new_prompt
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local new_finder = on_input_result.updated_finder
|
|
|
|
|
|
|
|
if new_finder then
|
|
|
|
|
|
|
|
self.finder:close()
|
|
|
|
|
|
|
|
self.finder = new_finder
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return prompt
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function Picker:_resume_picker()
|
|
|
|
|
|
|
|
-- resume previous picker
|
|
|
|
|
|
|
|
local index = 1
|
|
|
|
|
|
|
|
for entry in self.manager:iter() do
|
|
|
|
|
|
|
|
self:entry_adder(index, entry, _, true)
|
|
|
|
|
|
|
|
index = index + 1
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
self.cache_picker.is_cached = false
|
|
|
|
|
|
|
|
-- if text changed, required to set anew to restart finder; otherwise hl and selection
|
|
|
|
|
|
|
|
if self.cache_picker.cached_prompt ~= self.default_text then
|
|
|
|
|
|
|
|
self:reset_prompt()
|
|
|
|
|
|
|
|
self:set_prompt(self.default_text)
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
-- scheduling required to apply highlighting and selection appropriately
|
|
|
|
|
|
|
|
await_schedule(function()
|
|
|
|
|
|
|
|
if self.cache_picker.selection_row ~= nil then
|
|
|
|
|
|
|
|
self:set_selection(self.cache_picker.selection_row)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
pickers._Picker = Picker
|
|
|
|
pickers._Picker = Picker
|
|
|
|
|
|
|
|
|
|
|
|
return pickers
|
|
|
|
return pickers
|
|
|
|
|