diff options
| author | TJ DeVries <devries.timothyj@gmail.com> | 2020-08-20 23:41:53 -0400 |
|---|---|---|
| committer | TJ DeVries <devries.timothyj@gmail.com> | 2020-08-20 23:41:53 -0400 |
| commit | cfddae42f59eacbd792a8853be089f4711bbf4ba (patch) | |
| tree | 9033de9a43822a63544244559380729b8f3d84bf /lua/telescope/pickers.lua | |
| parent | 96cac0a8c861d5cdb1bb7765cc2d20e47ebb7885 (diff) | |
WIP: Actually get the UI to work and add some tests
Diffstat (limited to 'lua/telescope/pickers.lua')
| -rw-r--r-- | lua/telescope/pickers.lua | 179 |
1 files changed, 117 insertions, 62 deletions
diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index db5ec7d..f2acfac 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -1,11 +1,7 @@ local a = vim.api -local fun = require('fun') local popup = require('popup') -local zip = fun.zip -local tomap = fun.tomap - local log = require('telescope.log') local mappings = require('telescope.mappings') local state = require('telescope.state') @@ -13,6 +9,8 @@ local utils = require('telescope.utils') local pickers = {} +--- Picker is the main UI that shows up to interact w/ your results. +-- Takes a filter & a previewr local Picker = {} Picker.__index = Picker @@ -133,98 +131,77 @@ function Picker:find(opts) local on_lines = function(_, _, _, first_line, last_line) local prompt = vim.api.nvim_buf_get_lines(prompt_bufnr, first_line, last_line, false)[1] - -- Create a closure that has all the data we need -- We pass a function called "newResult" to get_results -- get_results calles "newResult" every time it gets a new result -- picker then (if available) calls sorter -- and then appropriately places new result in the buffer. - - -- Sorted table by scores. - -- Lowest score gets lowest index. - self.line_scores = {} - -- TODO: We need to fix the sorting -- TODO: We should provide a simple fuzzy matcher in Lua for people -- TODO: We should get all the stuff on the bottom line directly, not floating around -- TODO: We need to handle huge lists in a good way, cause currently we'll just put too much stuff in the buffer -- TODO: Stop having things crash if we have an error. - local replace_line = function(score, row, line) - log.trace("Replacing @ %s w/ text '%s' (%s)", row, line, score) - vim.api.nvim_buf_set_lines(results_bufnr, row, row + 1, false, {line}) - end - - local insert_line = function(score, row, line) - log.trace("Inserting @ %s w/ text '%s' (%s)", row, line, score) - vim.api.nvim_buf_set_lines(results_bufnr, row, row, false, {line}) - end + local line_manager = pickers.line_manager( + self.max_results, + function(index, line) + local row = self.max_results - index + 1 + log.trace("Setting row", row, "with value", line) + vim.api.nvim_buf_set_lines(results_bufnr, row, row + 1, false, {line}) + end + ) local process_result = function(line) if vim.trim(line) == "" then return end + log.trace("Processing result... ", line) + + local sort_score = 0 if sorter then - local sort_score = sorter:score(prompt, line) + sort_score = sorter:score(prompt, line) if sort_score == -1 then + log.trace("Filtering out result: ", line) return end + end - -- { 7, 3, 1, 1 } - -- 2 - for row, row_score in utils.reversed_ipairs(self.line_scores) do - if row_score > sort_score then - -- Insert line at row - insert_line(sort_score, self.max_results - row, line) - - -- Insert current score in the table - table.insert(self.line_scores, row + 1, sort_score) - - -- All done :) - return - end + line_manager:add_result(sort_score, line) + end - -- Don't keep inserting stuff - if row > self.max_results then - return - end - end + local process_complete = function() + local worst_line = self.max_results - line_manager.num_results() + local empty_lines = utils.repeated_table(worst_line, "") + -- vim.api.nvim_buf_set_lines(results_bufnr, 0, worst_line + 1, false, empty_lines) - -- Worst score so far, so add to end + log.debug("Worst Line after process_complete: %s", worst_line, results_bufnr) - -- example: 5 max results, 8 - local worst_line = self.max_results - #self.line_scores - replace_line(sort_score, worst_line, line) - table.insert(self.line_scores, sort_score) - else - -- Just always append to the end of the buffer if this is all you got. - vim.api.nvim_buf_set_lines(results_bufnr, -1, -1, false, {line}) - end - end + -- local fun = require('fun') + -- local zip = fun.zip + -- local tomap = fun.tomap - local process_complete = function() - local worst_line = self.max_results - #self.line_scores - local empty_lines = {} - for _ = 1, worst_line do table.insert(empty_lines, "") end - vim.api.nvim_buf_set_lines(results_bufnr, 0, worst_line, false, empty_lines) - - log.info("Worst Line after process_complete: %s", worst_line) - log.trace("%s", tomap(zip( - a.nvim_buf_get_lines(results_bufnr, worst_line, self.max_results, false), - self.line_scores - ))) + -- log.trace("%s", tomap(zip( + -- a.nvim_buf_get_lines(results_bufnr, worst_line, self.max_results, false), + -- self.line_scores + -- ))) end - pcall(function() + local ok, msg = pcall(function() return finder(prompt, process_result, process_complete) end) + + if not ok then + log.warn("Failed with msg: ", msg) + end end - -- Call this once to pre-populate if it makes sense - -- vim.schedule_wrap(on_lines(nil, nil, nil, 0, 1)) + -- TODO: Uncomment + vim.schedule(function() + on_lines(nil, nil, nil, 0, 1) + end) -- Register attach vim.api.nvim_buf_attach(prompt_bufnr, true, { @@ -359,4 +336,82 @@ pickers.new = function(...) return Picker:new(...) end +-- TODO: We should consider adding `process_bulk` or `bulk_line_manager` for things +-- that we always know the items and can score quickly, so as to avoid drawing so much. +pickers.line_manager = function(max_results, set_line) + log.debug("Creating line_manager...") + + -- state contains list of + -- { + -- score = ... + -- line = ... + -- metadata ? ... + -- } + local state = {} + + set_line = set_line or function() end + + return setmetatable({ + add_result = function(self, score, line) + score = score or 0 + + for index, item in ipairs(state) do + if item.score > score then + return self:insert(index, { + score = score, + line = line, + }) + end + + -- Don't add results that are too bad. + if index >= max_results then + return self + end + end + + return self:insert({ + score = score, + line = line, + }) + end, + + insert = function(self, index, item) + if item == nil then + item = index + index = #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_item + repeat + next_item = state[index] + + set_line(index, item.line) + state[index] = item + + index = index + 1 + item = next_item + until not next_item + end, + + num_results = function() + return #state + end, + + _get_state = function() + return state + end, + }, { + -- insert = + + -- __index = function(_, line) + -- end, + + -- __newindex = function(_, index, line) + -- end, + }) +end + + return pickers |
