Skip to content

Commit dea927d

Browse files
authored
feat: Add scrolling through results (#1232)
* some scrollin * [WIP]: Fri 10 Sep 2021 02:24:20 PM EDT * ok, I think scrolling works * change to 1000 for now, dont need to scroll that far :)
1 parent ec6c13f commit dea927d

5 files changed

Lines changed: 101 additions & 116 deletions

File tree

ftplugin/TelescopeResults.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- Don't have scrolloff, it makes things weird.
2+
vim.opt.scrolloff = 0

lua/telescope/entry_manager.lua

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,6 @@ local log = require "telescope.log"
22

33
local LinkedList = require "telescope.algos.linked_list"
44

5-
--[[
6-
7-
OK, new idea.
8-
We can do linked list here.
9-
To convert at the end to quickfix, just run the list.
10-
...
11-
12-
start node
13-
end node
14-
15-
if past loop of must have scores,
16-
then we can just add to end node and shift end node to current node.
17-
etc.
18-
19-
20-
always inserts a row, because we clear everything before?
21-
22-
can also optimize by keeping worst acceptable score around.
23-
24-
--]]
25-
265
local EntryManager = {}
276
EntryManager.__index = EntryManager
287

lua/telescope/finders/async_job_finder.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ local log = require "telescope.log"
77
return function(opts)
88
log.trace("Creating async_job:", opts)
99
local entry_maker = opts.entry_maker or make_entry.gen_from_string()
10+
1011
local fn_command = function(prompt)
1112
local command_list = opts.command_generator(prompt)
1213
if command_list == nil then

lua/telescope/log.lua

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
local user = vim.loop.os_getenv "USER"
2-
31
return require("plenary.log").new {
42
plugin = "telescope",
5-
level = ((user == "tj" or user == "tjdevries") and "debug") or "warn",
3+
level = "info",
64
}

lua/telescope/pickers.lua

Lines changed: 97 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -213,28 +213,17 @@ function Picker:clear_extra_rows(results_bufnr)
213213
end
214214

215215
if not ok then
216-
log.debug(msg)
216+
log.debug("Failed to set lines:", msg)
217217
end
218218

219219
log.trace("Clearing:", worst_line)
220220
end
221221

222-
function Picker:highlight_displayed_rows(results_bufnr, prompt)
223-
if not self.sorter or not self.sorter.highlighter then
222+
function Picker:highlight_one_row(results_bufnr, prompt, display, row)
223+
if not self.sorter.highlighter then
224224
return
225225
end
226226

227-
vim.api.nvim_buf_clear_namespace(results_bufnr, ns_telescope_matching, 0, -1)
228-
229-
local displayed_rows = vim.api.nvim_buf_get_lines(results_bufnr, 0, -1, false)
230-
for row_index = 1, math.min(#displayed_rows, self.max_results) do
231-
local display = displayed_rows[row_index]
232-
233-
self:highlight_one_row(results_bufnr, prompt, display, row_index - 1)
234-
end
235-
end
236-
237-
function Picker:highlight_one_row(results_bufnr, prompt, display, row)
238227
local highlights = self.sorter:highlighter(prompt, display)
239228

240229
if highlights then
@@ -352,22 +341,19 @@ function Picker:find()
352341
self.prompt_prefix = prompt_prefix
353342
self:_reset_prefix_color()
354343

355-
-- First thing we want to do is set all the lines to blank.
356-
self.max_results = popup_opts.results.height
344+
-- TODO: This could be configurable in the future, but I don't know why you would
345+
-- want to scroll through more than 10,000 items.
346+
--
347+
-- This just lets us stop doing stuff after tons of things.
348+
self.max_results = 1000
357349

358-
-- TODO(scrolling): This may be a hack when we get a little further into implementing scrolling.
359350
vim.api.nvim_buf_set_lines(results_bufnr, 0, self.max_results, false, utils.repeated_table(self.max_results, ""))
360351

361-
-- TODO(status): I would love to get the status text not moving back and forth. Perhaps it is just a problem with
362-
-- virtual text & prompt buffers or something though. I can't figure out why it would redraw the way it does.
363-
--
364-
-- A "hacked" version of this would be to calculate where the area I want the status to go and put a new window there.
365-
-- With this method, I do not need to worry about padding or antying, just make it take up X characters or something.
366352
local status_updater = self:get_status_updater(prompt_win, prompt_bufnr)
367353
local debounced_status = debounce.throttle_leading(status_updater, 50)
368354

369355
local tx, rx = channel.mpsc()
370-
self.__on_lines = tx.send
356+
self._on_lines = tx.send
371357

372358
local find_id = self:_next_find_id()
373359

@@ -412,25 +398,14 @@ function Picker:find()
412398

413399
local start_time = vim.loop.hrtime()
414400

415-
local prompt = self:_get_prompt()
416-
local on_input_result = self._on_input_filter_cb(prompt) or {}
417-
418-
local new_prompt = on_input_result.prompt
419-
if new_prompt then
420-
prompt = new_prompt
421-
end
422-
423-
local new_finder = on_input_result.updated_finder
424-
if new_finder then
425-
self.finder:close()
426-
self.finder = new_finder
427-
end
401+
local prompt = self:_get_next_filtered_prompt()
428402

429403
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
430404
if self.cache_picker == false or not (self.cache_picker.is_cached == true) then
431405
self.sorter:_start(prompt)
432406
self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats)
433407

408+
vim.api.nvim_buf_clear_namespace(results_bufnr, ns_telescope_matching, 0, -1)
434409
local process_result = self:get_result_processor(find_id, prompt, debounced_status)
435410
local process_complete = self:get_result_completor(self.results_bufnr, find_id, prompt, status_updater)
436411

@@ -447,26 +422,8 @@ function Picker:find()
447422
async.util.sleep(self.debounce - diff_time)
448423
end
449424
else
450-
-- resume previous picker
451-
local index = 1
452-
for entry in self.manager:iter() do
453-
self:entry_adder(index, entry, _, true)
454-
index = index + 1
455-
end
456-
self.cache_picker.is_cached = false
457-
-- if text changed, required to set anew to restart finder; otherwise hl and selection
458-
if self.cache_picker.cached_prompt ~= self.default_text then
459-
self:reset_prompt()
460-
self:set_prompt(self.default_text)
461-
else
462-
-- scheduling required to apply highlighting and selection appropriately
463-
await_schedule(function()
464-
self:highlight_displayed_rows(self.results_bufnr, self.cache_picker.cached_prompt)
465-
if self.cache_picker.selection_row ~= nil then
466-
self:set_selection(self.cache_picker.selection_row)
467-
end
468-
end)
469-
end
425+
-- TODO(scroll): This can only happen once, I don't like where it is.
426+
self:_resume_picker()
470427
end
471428
end
472429
end)
@@ -476,10 +433,10 @@ function Picker:find()
476433
on_lines = function(...)
477434
find_id = self:_next_find_id()
478435

479-
self._result_completed = false
480436
status_updater { completed = false }
481-
tx.send(...)
437+
self._on_lines(...)
482438
end,
439+
483440
on_detach = function()
484441
self:_detach()
485442
end,
@@ -753,7 +710,7 @@ function Picker:refresh(finder, opts)
753710
self._multi = MultiSelect:new()
754711
end
755712

756-
self.__on_lines(nil, nil, nil, 0, 1)
713+
self._on_lines(nil, nil, nil, 0, 1)
757714
end
758715

759716
function Picker:set_selection(row)
@@ -856,6 +813,8 @@ function Picker:set_selection(row)
856813
self._selection_row = row
857814

858815
self:refresh_previewer()
816+
817+
vim.api.nvim_win_set_cursor(self.results_win, { row + 1, 0 })
859818
end
860819

861820
function Picker:refresh_previewer()
@@ -918,43 +877,41 @@ function Picker:entry_adder(index, entry, _, insert)
918877

919878
self:_increment "displayed"
920879

921-
-- TODO: Don't need to schedule this if we schedule the adder.
922880
local offset = insert and 0 or 1
923-
vim.schedule(function()
924-
if not vim.api.nvim_buf_is_valid(self.results_bufnr) then
925-
log.debug "ON_ENTRY: Invalid buffer"
926-
return
927-
end
881+
if not vim.api.nvim_buf_is_valid(self.results_bufnr) then
882+
log.debug "ON_ENTRY: Invalid buffer"
883+
return
884+
end
928885

929-
-- TODO: Does this every get called?
930-
-- local line_count = vim.api.nvim_win_get_height(self.results_win)
931-
local line_count = vim.api.nvim_buf_line_count(self.results_bufnr)
932-
if row > line_count then
933-
return
934-
end
886+
-- TODO: Does this every get called?
887+
-- local line_count = vim.api.nvim_win_get_height(self.results_win)
888+
local line_count = vim.api.nvim_buf_line_count(self.results_bufnr)
889+
if row > line_count then
890+
return
891+
end
935892

936-
if insert then
937-
if self.sorting_strategy == "descending" then
938-
vim.api.nvim_buf_set_lines(self.results_bufnr, 0, 1, false, {})
939-
end
893+
if insert then
894+
if self.sorting_strategy == "descending" then
895+
vim.api.nvim_buf_set_lines(self.results_bufnr, 0, 1, false, {})
940896
end
897+
end
941898

942-
local set_ok, msg = pcall(vim.api.nvim_buf_set_lines, self.results_bufnr, row, row + offset, false, { display })
943-
if set_ok and display_highlights then
944-
self.highlighter:hi_display(row, prefix, display_highlights)
945-
end
899+
local set_ok, msg = pcall(vim.api.nvim_buf_set_lines, self.results_bufnr, row, row + offset, false, { display })
900+
if set_ok and display_highlights then
901+
self.highlighter:hi_display(row, prefix, display_highlights)
902+
self:highlight_one_row(self.results_bufnr, self:_get_prompt(), display, row)
903+
end
946904

947-
if not set_ok then
948-
log.debug("Failed to set lines...", msg)
949-
end
905+
if not set_ok then
906+
log.debug("Failed to set lines...", msg)
907+
end
950908

951-
-- This pretty much only fails when people leave newlines in their results.
952-
-- So we'll clean it up for them if it fails.
953-
if not set_ok and display:find "\n" then
954-
display = display:gsub("\n", " | ")
955-
vim.api.nvim_buf_set_lines(self.results_bufnr, row, row + 1, false, { display })
956-
end
957-
end)
909+
-- This pretty much only fails when people leave newlines in their results.
910+
-- So we'll clean it up for them if it fails.
911+
if not set_ok and display:find "\n" then
912+
display = display:gsub("\n", " | ")
913+
vim.api.nvim_buf_set_lines(self.results_bufnr, row, row + 1, false, { display })
914+
end
958915
end
959916

960917
function Picker:_reset_track()
@@ -1025,6 +982,8 @@ function Picker:get_status_updater(prompt_win, prompt_bufnr)
1025982
end
1026983

1027984
function Picker:get_result_processor(find_id, prompt, status_updater)
985+
local count = 0
986+
1028987
local cb_add = function(score, entry)
1029988
self.manager:add_entry(self, score, entry)
1030989
status_updater { completed = false }
@@ -1045,6 +1004,8 @@ function Picker:get_result_processor(find_id, prompt, status_updater)
10451004
return
10461005
end
10471006

1007+
count = count + 1
1008+
10481009
-- TODO: Probably should asyncify this / cache this / do something because this probably takes
10491010
-- a ton of time on large results.
10501011
log.trace("Processing result... ", entry)
@@ -1060,6 +1021,13 @@ function Picker:get_result_processor(find_id, prompt, status_updater)
10601021
end
10611022

10621023
self.sorter:score(prompt, entry, cb_add, cb_filter)
1024+
1025+
-- Only on the first addition do we want to set the selection.
1026+
-- This allows us to handle moving the cursor to the bottom or top of the window
1027+
-- depending on the strategy.
1028+
if count == 1 then
1029+
self:_do_selection(prompt)
1030+
end
10631031
end
10641032
end
10651033

@@ -1075,12 +1043,9 @@ function Picker:get_result_completor(results_bufnr, find_id, prompt, status_upda
10751043
status_updater { completed = true }
10761044

10771045
self:clear_extra_rows(results_bufnr)
1078-
self:highlight_displayed_rows(results_bufnr, prompt)
10791046
self.sorter:_finish(prompt)
10801047

10811048
self:_on_complete()
1082-
1083-
self._result_completed = true
10841049
end)
10851050
end
10861051

@@ -1226,6 +1191,46 @@ function Picker:_detach()
12261191
self.closed = true
12271192
end
12281193

1194+
function Picker:_get_next_filtered_prompt()
1195+
local prompt = self:_get_prompt()
1196+
local on_input_result = self._on_input_filter_cb(prompt) or {}
1197+
1198+
local new_prompt = on_input_result.prompt
1199+
if new_prompt then
1200+
prompt = new_prompt
1201+
end
1202+
1203+
local new_finder = on_input_result.updated_finder
1204+
if new_finder then
1205+
self.finder:close()
1206+
self.finder = new_finder
1207+
end
1208+
1209+
return prompt
1210+
end
1211+
1212+
function Picker:_resume_picker()
1213+
-- resume previous picker
1214+
local index = 1
1215+
for entry in self.manager:iter() do
1216+
self:entry_adder(index, entry, _, true)
1217+
index = index + 1
1218+
end
1219+
self.cache_picker.is_cached = false
1220+
-- if text changed, required to set anew to restart finder; otherwise hl and selection
1221+
if self.cache_picker.cached_prompt ~= self.default_text then
1222+
self:reset_prompt()
1223+
self:set_prompt(self.default_text)
1224+
else
1225+
-- scheduling required to apply highlighting and selection appropriately
1226+
await_schedule(function()
1227+
if self.cache_picker.selection_row ~= nil then
1228+
self:set_selection(self.cache_picker.selection_row)
1229+
end
1230+
end)
1231+
end
1232+
end
1233+
12291234
pickers._Picker = Picker
12301235

12311236
return pickers

0 commit comments

Comments
 (0)