diff options
Diffstat (limited to 'lua')
27 files changed, 620 insertions, 999 deletions
diff --git a/lua/telescope/_.lua b/lua/telescope/_.lua new file mode 100644 index 0000000..a325c7d --- /dev/null +++ b/lua/telescope/_.lua @@ -0,0 +1,296 @@ +local uv = vim.loop + +local Object = require "plenary.class" +local log = require "plenary.log" + +local async = require "plenary.async" +local channel = require("plenary.async").control.channel + +local M = {} + +local AsyncJob = {} +AsyncJob.__index = AsyncJob + +function AsyncJob.new(opts) + local self = setmetatable({}, AsyncJob) + + self.command, self.uv_opts = M.convert_opts(opts) + + self.stdin = opts.stdin or M.NullPipe() + self.stdout = opts.stdout or M.NullPipe() + self.stderr = opts.stderr or M.NullPipe() + + if opts.cwd then + -- TODO: not vim.fn + self.uv_opts.cwd = vim.fn.expand(opts.cwd) + end + + self.uv_opts.stdio = { + self.stdin.handle, + self.stdout.handle, + self.stderr.handle, + } + + return self +end + +function AsyncJob:_for_each_pipe(f, ...) + for _, pipe in ipairs { self.stdin, self.stdout, self.stderr } do + f(pipe, ...) + end +end + +function AsyncJob:close(force) + if force == nil then + force = true + end + + self:_for_each_pipe(function(p) + p:close(force) + end) + if not self.handle:is_closing() then + self.handle:close() + end + + log.debug "[async_job] closed" +end + +M.spawn = function(opts) + local self = AsyncJob.new(opts) + + self.handle = uv.spawn( + self.command, + self.uv_opts, + async.void(function() + self:close(false) + end) + ) + + return self +end + +---@class uv_pipe_t +--- A pipe handle from libuv +---@field read_start function: Start reading +---@field read_stop function: Stop reading +---@field close function: Close the handle +---@field is_closing function: Whether handle is currently closing +---@field is_active function: Whether the handle is currently reading + +---@class BasePipe +---@field super Object: Always available +---@field handle uv_pipe_t: A pipe handle +---@field extend function: Extend +local BasePipe = Object:extend() + +function BasePipe:new() + self.eof_tx, self.eof_rx = channel.oneshot() +end + +function BasePipe:close(force) + if force == nil then + force = true + end + + assert(self.handle, "Must have a pipe to close. Otherwise it's weird!") + + if self.handle:is_closing() then + return + end + + -- If we're not forcing the stop, allow waiting for eof + -- This ensures that we don't end up with weird race conditions + if not force then + self.eof_rx() + end + + self.handle:read_stop() + if not self.handle:is_closing() then + self.handle:close() + end + + self._closed = true +end + +---@class LinesPipe : BasePipe +local LinesPipe = BasePipe:extend() + +function LinesPipe:new() + LinesPipe.super.new(self) + self.handle = uv.new_pipe(false) +end + +function LinesPipe:read() + local read_tx, read_rx = channel.oneshot() + + self.handle:read_start(function(err, data) + assert(not err, err) + self.handle:read_stop() + + read_tx(data) + if data == nil then + self.eof_tx() + end + end) + + return read_rx() +end + +function LinesPipe:iter(schedule) + if schedule == nil then + schedule = true + end + + local text = nil + local index = nil + + local get_next_text = function(previous) + index = nil + + local read = self:read() + if previous == nil and read == nil then + return + end + + return (previous or "") .. (read or "") + end + + local next_value = nil + next_value = function() + if schedule then + async.util.scheduler() + end + + if text == nil or (text == "" and index == nil) then + return nil + end + + local start = index + index = string.find(text, "\n", index, true) + + if index == nil then + text = get_next_text(string.sub(text, start or 1)) + return next_value() + end + + index = index + 1 + + return string.sub(text, start or 1, index - 2) + end + + text = get_next_text() + + return function() + return next_value() + end +end + +---@class NullPipe : BasePipe +local NullPipe = BasePipe:extend() + +function NullPipe:new() + NullPipe.super.new(self) + self.start = function() end + self.read_start = function() end + self.close = function() end + + -- This always has eof tx done, so can just call it now + self.eof_tx() +end + +---@class ChunkPipe : BasePipe +local ChunkPipe = BasePipe:extend() + +function ChunkPipe:new() + ChunkPipe.super.new(self) + self.handle = uv.new_pipe(false) +end + +function ChunkPipe:read() + local read_tx, read_rx = channel.oneshot() + + self.handle:read_start(function(err, data) + assert(not err, err) + self.handle:read_stop() + + read_tx(data) + if data == nil then + self.eof_tx() + end + end) + + return read_rx() +end + +function ChunkPipe:iter() + return function() + if self._closed then + return nil + end + + return self:read() + end +end + +---@class ErrorPipe : BasePipe +local ErrorPipe = BasePipe:extend() + +function ErrorPipe:new() + ErrorPipe.super.new(self) + self.handle = uv.new_pipe(false) +end + +function ErrorPipe:start() + self.handle:read_start(function(err, data) + if not err and not data then + return + end + + self.handle:read_stop() + self.handle:close() + + error(string.format("Err: %s, Data: '%s'", err, data)) + end) +end + +M.NullPipe = NullPipe +M.LinesPipe = LinesPipe +M.ChunkPipe = ChunkPipe +M.ErrorPipe = ErrorPipe + +M.convert_opts = function(o) + if not o then + error(debug.traceback "Options are required for Job:new") + end + + local command = o.command + if not command then + if o[1] then + command = o[1] + else + error(debug.traceback "'command' is required for Job:new") + end + elseif o[1] then + error(debug.traceback "Cannot pass both 'command' and array args") + end + + local args = o.args + if not args then + if #o > 1 then + args = { select(2, unpack(o)) } + end + end + + local ok, is_exe = pcall(vim.fn.executable, command) + if not o.skip_validation and ok and 1 ~= is_exe then + error(debug.traceback(command .. ": Executable not found")) + end + + local obj = {} + + obj.args = args + + return command, obj +end + +return M diff --git a/lua/telescope/_compat.lua b/lua/telescope/_compat.lua deleted file mode 100644 index 42a3dfd..0000000 --- a/lua/telescope/_compat.lua +++ /dev/null @@ -1,56 +0,0 @@ -vim.deepcopy = (function() - local function _id(v) - return v - end - - local deepcopy_funcs = { - table = function(orig) - local copy = {} - - if vim._empty_dict_mt ~= nil and getmetatable(orig) == vim._empty_dict_mt then - copy = vim.empty_dict() - end - - for k, v in pairs(orig) do - copy[vim.deepcopy(k)] = vim.deepcopy(v) - end - - if getmetatable(orig) then - setmetatable(copy, getmetatable(orig)) - end - - return copy - end, - ["function"] = _id or function(orig) - local ok, dumped = pcall(string.dump, orig) - if not ok then - error(debug.traceback(dumped)) - end - - local cloned = loadstring(dumped) - local i = 1 - while true do - local name = debug.getupvalue(orig, i) - if not name then - break - end - debug.upvaluejoin(cloned, i, orig, i) - i = i + 1 - end - return cloned - end, - number = _id, - string = _id, - ["nil"] = _id, - boolean = _id, - } - - return function(orig) - local f = deepcopy_funcs[type(orig)] - if f then - return f(orig) - else - error("Cannot deepcopy object of type " .. type(orig)) - end - end -end)() diff --git a/lua/telescope/actions/init.lua b/lua/telescope/actions/init.lua index 6dc022e..43315cc 100644 --- a/lua/telescope/actions/init.lua +++ b/lua/telescope/actions/init.lua @@ -582,12 +582,22 @@ actions.git_staging_toggle = function(prompt_bufnr) end local entry_to_qf = function(entry) + local text = entry.text + + if not text then + if type(entry.value) == "table" then + text = entry.value.text + else + text = entry.value + end + end + return { bufnr = entry.bufnr, filename = from_entry.path(entry, false), lnum = entry.lnum, col = entry.col, - text = entry.text or entry.value.text or entry.value, + text = text, } end diff --git a/lua/telescope/actions/state.lua b/lua/telescope/actions/state.lua index 0be2c3f..80fef56 100644 --- a/lua/telescope/actions/state.lua +++ b/lua/telescope/actions/state.lua @@ -18,7 +18,7 @@ end --- Gets the current line function action_state.get_current_line() - return global_state.get_global_key "current_line" + return global_state.get_global_key "current_line" or "" end --- Gets the current picker diff --git a/lua/telescope/builtin/files.lua b/lua/telescope/builtin/files.lua index 605a874..b0cf342 100644 --- a/lua/telescope/builtin/files.lua +++ b/lua/telescope/builtin/files.lua @@ -5,6 +5,7 @@ local finders = require "telescope.finders" local make_entry = require "telescope.make_entry" local pickers = require "telescope.pickers" local previewers = require "telescope.previewers" +local sorters = require "telescope.sorters" local utils = require "telescope.utils" local conf = require("telescope.config").values local log = require "telescope.log" @@ -80,8 +81,6 @@ files.live_grep = function(opts) return nil end - prompt = escape_chars(prompt) - local search_list = {} if search_dirs then @@ -103,7 +102,9 @@ files.live_grep = function(opts) prompt_title = "Live Grep", finder = live_grepper, previewer = conf.grep_previewer(opts), - sorter = conf.generic_sorter(opts), + -- TODO: It would be cool to use `--json` output for this + -- and then we could get the highlight positions directly. + sorter = sorters.highlighter_only(opts), }):find() end diff --git a/lua/telescope/builtin/lsp.lua b/lua/telescope/builtin/lsp.lua index bcbb833..e0550fc 100644 --- a/lua/telescope/builtin/lsp.lua +++ b/lua/telescope/builtin/lsp.lua @@ -1,16 +1,14 @@ -local actions = require "telescope.actions" +local channel = require("plenary.async.control").channel + local action_state = require "telescope.actions.state" +local actions = require "telescope.actions" +local conf = require("telescope.config").values +local entry_display = require "telescope.pickers.entry_display" local finders = require "telescope.finders" local make_entry = require "telescope.make_entry" local pickers = require "telescope.pickers" -local entry_display = require "telescope.pickers.entry_display" -local utils = require "telescope.utils" local strings = require "plenary.strings" -local a = require "plenary.async_lib" -local async, await = a.async, a.await -local channel = a.util.channel - -local conf = require("telescope.config").values +local utils = require "telescope.utils" local lsp = {} @@ -309,20 +307,21 @@ lsp.workspace_symbols = function(opts) }):find() end +-- TODO(MERGE) local function get_workspace_symbols_requester(bufnr) local cancel = function() end - return async(function(prompt) + return function(prompt) local tx, rx = channel.oneshot() cancel() _, cancel = vim.lsp.buf_request(bufnr, "workspace/symbol", { query = prompt }, tx) - local err, _, results_lsp = await(rx()) + local err, _, results_lsp = rx() assert(not err, err) local locations = vim.lsp.util.symbols_to_items(results_lsp or {}, bufnr) or {} return locations - end) + end end lsp.dynamic_workspace_symbols = function(opts) @@ -335,7 +334,7 @@ lsp.dynamic_workspace_symbols = function(opts) fn = get_workspace_symbols_requester(curr_bufnr), }, previewer = conf.qflist_previewer(opts), - sorter = conf.generic_sorter(), + sorter = conf.generic_sorter(opts), }):find() end diff --git a/lua/telescope/config.lua b/lua/telescope/config.lua index 8db9cbb..1b0ce86 100644 --- a/lua/telescope/config.lua +++ b/lua/telescope/config.lua @@ -219,13 +219,20 @@ local telescope_defaults = { borderchars = { { "─", "│", "─", "│", "╭", "╮", "╯", "╰" } }, get_status_text = { - function(self) + function(self, opts) local xx = (self.stats.processed or 0) - (self.stats.filtered or 0) local yy = self.stats.processed or 0 if xx == 0 and yy == 0 then return "" end + -- local status_icon + -- if opts.completed then + -- status_icon = "✔️" + -- else + -- status_icon = "*" + -- end + return string.format("%s / %s", xx, yy) end, }, diff --git a/lua/telescope/entry_manager.lua b/lua/telescope/entry_manager.lua index ff8b9ba..5055171 100644 --- a/lua/telescope/entry_manager.lua +++ b/lua/telescope/entry_manager.lua @@ -155,7 +155,10 @@ function EntryManager:add_entry(picker, score, entry) info.looped = info.looped + 1 if container[2] > score then - -- print("Inserting: ", picker, index, node, new_container) + return self:_insert_container_before(picker, index, node, new_container) + end + + if score < 1 and container[2] == score and #entry.ordinal < #container[1].ordinal then return self:_insert_container_before(picker, index, node, new_container) end @@ -174,11 +177,13 @@ function EntryManager:add_entry(picker, score, entry) end function EntryManager:iter() - return coroutine.wrap(function() - for val in self.linked_states:iter() do - coroutine.yield(val[1]) + local iterator = self.linked_states:iter() + return function() + local val = iterator() + if val then + return val[1] end - end) + end end return EntryManager diff --git a/lua/telescope/finders.lua b/lua/telescope/finders.lua index 7fecd67..ea4b88b 100644 --- a/lua/telescope/finders.lua +++ b/lua/telescope/finders.lua @@ -2,12 +2,10 @@ local Job = require "plenary.job" local make_entry = require "telescope.make_entry" local log = require "telescope.log" -local a = require "plenary.async_lib" -local await = a.await local async_static_finder = require "telescope.finders.async_static_finder" local async_oneshot_finder = require "telescope.finders.async_oneshot_finder" --- local async_job_finder = require('telescope.finders.async_job_finder') +local async_job_finder = require "telescope.finders.async_job_finder" local finders = {} @@ -103,7 +101,7 @@ function JobFinder:_find(prompt, process_result, process_complete) enable_recording = false, on_stdout = on_output, - on_stderr = on_output, + -- on_stderr = on_output, on_exit = function() process_complete() @@ -131,17 +129,15 @@ function DynamicFinder:new(opts) end function DynamicFinder:_find(prompt, process_result, process_complete) - a.scope(function() - local results = await(self.fn(prompt)) + local results = self.fn(prompt) - for _, result in ipairs(results) do - if process_result(self.entry_maker(result)) then - return - end + for _, result in ipairs(results) do + if process_result(self.entry_maker(result)) then + return end + end - process_complete() - end) + process_complete() end --- Return a new Finder @@ -154,31 +150,18 @@ finders._new = function(opts) return JobFinder:new(opts) end -finders.new_job = function(command_generator, entry_maker, maximum_results, cwd) - -- return async_job_finder { - -- command_generator = command_generator, - -- entry_maker = entry_maker, - -- maximum_results = maximum_results, - -- cwd = cwd, - -- } - - return JobFinder:new { - fn_command = function(_, prompt) - local command_list = command_generator(prompt) - if command_list == nil then - return nil - end - - local command = table.remove(command_list, 1) +finders.new_async_job = function(opts) + if opts.writer then + return finders._new(opts) + end - return { - command = command, - args = command_list, - } - end, + return async_job_finder(opts) +end +finders.new_job = function(command_generator, entry_maker, _, cwd) + return async_job_finder { + command_generator = command_generator, entry_maker = entry_maker, - maximum_results = maximum_results, cwd = cwd, } end @@ -186,8 +169,8 @@ end --- One shot job ---@param command_list string[]: Command list to execute. ---@param opts table: stuff ---- @key entry_maker function Optional: function(line: string) => table ---- @key cwd string +-- @key entry_maker function Optional: function(line: string) => table +-- @key cwd string finders.new_oneshot_job = function(command_list, opts) opts = opts or {} diff --git a/lua/telescope/finders/async_job_finder.lua b/lua/telescope/finders/async_job_finder.lua index dfabf98..17799e8 100644 --- a/lua/telescope/finders/async_job_finder.lua +++ b/lua/telescope/finders/async_job_finder.lua @@ -1,14 +1,11 @@ -local log = require "telescope.log" -local Job = require "plenary.job" - -local async_lib = require "plenary.async_lib" -local async = async_lib.async --- local await = async_lib.await -local void = async_lib.void +local async_job = require "telescope._" +local LinesPipe = require("telescope._").LinesPipe local make_entry = require "telescope.make_entry" +local log = require "telescope.log" return function(opts) + log.trace("Creating async_job:", opts) local entry_maker = opts.entry_maker or make_entry.gen_from_string() local fn_command = function(prompt) local command_list = opts.command_generator(prompt) @@ -18,58 +15,61 @@ return function(opts) local command = table.remove(command_list, 1) - return { + local res = { command = command, args = command_list, } + + return res end local job - return setmetatable({ - close = function() end, - }, { - __call = void(async(function(prompt, process_result, process_complete) - print("are we callin anything?", job) - if job and not job.is_shutdown then - log.debug "Shutting down old job" - job:shutdown() - end - local job_opts = fn_command(prompt) - if not job_opts then - return - end + local callable = function(_, prompt, process_result, process_complete) + if job then + job:close(true) + end - local writer = nil - if job_opts.writer and Job.is_job(job_opts.writer) then - writer = job_opts.writer - elseif opts.writer then - writer = Job:new(job_opts.writer) - end + local job_opts = fn_command(prompt) + if not job_opts then + return + end - job = Job:new { - command = job_opts.command, - args = job_opts.args, - cwd = job_opts.cwd or opts.cwd, - maximum_results = opts.maximum_results, - writer = writer, - enable_recording = false, + local writer = nil + -- if job_opts.writer and Job.is_job(job_opts.writer) then + -- writer = job_opts.writer + if opts.writer then + error "async_job_finder.writer is not yet implemented" + writer = async_job.writer(opts.writer) + end + + local stdout = LinesPipe() - on_stdout = vim.schedule_wrap(function(_, line) - if not line or line == "" then - return - end + job = async_job.spawn { + command = job_opts.command, + args = job_opts.args, + cwd = job_opts.cwd or opts.cwd, + writer = writer, - -- TODO: shutdown job here. - process_result(entry_maker(line)) - end), + stdout = stdout, + } - on_exit = function() - process_complete() - end, - } + for line in stdout:iter(true) do + if process_result(entry_maker(line)) then + return + end + end - job:start() - end)), + process_complete() + end + + return setmetatable({ + close = function() + if job then + job:close(true) + end + end, + }, { + __call = callable, }) end diff --git a/lua/telescope/finders/async_oneshot_finder.lua b/lua/telescope/finders/async_oneshot_finder.lua index 20e5403..19c2195 100644 --- a/lua/telescope/finders/async_oneshot_finder.lua +++ b/lua/telescope/finders/async_oneshot_finder.lua @@ -1,14 +1,9 @@ -local async_lib = require "plenary.async_lib" -local async = async_lib.async -local await = async_lib.await -local void = async_lib.void - -local AWAITABLE = 1000 +local async = require "plenary.async" +local async_job = require "telescope._" +local LinesPipe = require("telescope._").LinesPipe local make_entry = require "telescope.make_entry" -local Job = require "plenary.job" - return function(opts) opts = opts or {} @@ -21,64 +16,65 @@ return function(opts) local job_started = false local job_completed = false + local stdout = nil + return setmetatable({ - close = function() - results = {} - job_started = false - end, + -- close = function() results = {}; job_started = false end, + close = function() end, results = results, }, { - __call = void(async(function(_, prompt, process_result, process_complete) + __call = function(_, prompt, process_result, process_complete) if not job_started then local job_opts = fn_command() - local writer - if job_opts.writer and Job.is_job(job_opts.writer) then - writer = job_opts.writer - elseif job_opts.writer then - writer = Job:new(job_opts.writer) - end + -- TODO: Handle writers. + -- local writer + -- if job_opts.writer and Job.is_job(job_opts.writer) then + -- writer = job_opts.writer + -- elseif job_opts.writer then + -- writer = Job:new(job_opts.writer) + -- end - local job = Job:new { + stdout = LinesPipe() + local _ = async_job.spawn { command = job_opts.command, args = job_opts.args, - cwd = job_opts.cwd or cwd, - maximum_results = opts.maximum_results, - writer = writer, - enable_recording = false, - - on_stdout = vim.schedule_wrap(function(_, line) - num_results = num_results + 1 - - local v = entry_maker(line) - results[num_results] = v - process_result(v) - end), - - on_exit = function() - process_complete() - job_completed = true - end, + cwd = cwd, + + stdout = stdout, } - job:start() job_started = true end + if not job_completed then + for line in stdout:iter(true) do + num_results = num_results + 1 + + local v = entry_maker(line) + results[num_results] = v + process_result(v) + end + + process_complete() + job_completed = true + + return + end + local current_count = num_results for index = 1, current_count do + -- TODO: Figure out scheduling... + async.util.scheduler() + if process_result(results[index]) then break end - - if index % AWAITABLE == 0 then - await(async_lib.scheduler()) - end end if job_completed then process_complete() end - end)), + end, }) end diff --git a/lua/telescope/finders/async_static_finder.lua b/lua/telescope/finders/async_static_finder.lua index 065b687..941d858 100644 --- a/lua/telescope/finders/async_static_finder.lua +++ b/lua/telescope/finders/async_static_finder.lua @@ -1,7 +1,4 @@ -local async_lib = require "plenary.async_lib" -local async = async_lib.async -local await = async_lib.await -local void = async_lib.void +local scheduler = require("plenary.async").util.scheduler local make_entry = require "telescope.make_entry" @@ -29,18 +26,18 @@ return function(opts) results = results, close = function() end, }, { - __call = void(async(function(_, _, process_result, process_complete) + __call = function(_, _, process_result, process_complete) for i, v in ipairs(results) do if process_result(v) then break end if i % 1000 == 0 then - await(async_lib.scheduler()) + scheduler() end end process_complete() - end)), + end, }) end diff --git a/lua/telescope/init.lua b/lua/telescope/init.lua index 17cd910..7a740a3 100644 --- a/lua/telescope/init.lua +++ b/lua/telescope/init.lua @@ -1,5 +1,3 @@ -require "telescope._compat" - local _extensions = require "telescope._extensions" local telescope = {} diff --git a/lua/telescope/path.lua b/lua/telescope/path.lua deleted file mode 100644 index 744c2fa..0000000 --- a/lua/telescope/path.lua +++ /dev/null @@ -1,103 +0,0 @@ -local log = require "telescope.log" - -local path = {} - -path.separator = package.config:sub(1, 1) -path.home = vim.fn.expand "~" - -path.make_relative = function(filepath, cwd) - if not cwd or not filepath then - return filepath - end - - if filepath:sub(1, #cwd) == cwd then - local offset = 0 - -- if cwd does ends in the os separator, we need to take it off - if cwd:sub(#cwd, #cwd) ~= path.separator then - offset = 1 - end - - filepath = filepath:sub(#cwd + 1 + offset, #filepath) - end - - return filepath -end - -path.shorten = (function() - if jit then - local ffi = require "ffi" - ffi.cdef [[ - typedef unsigned char char_u; - char_u *shorten_dir(char_u *str); - ]] - - return function(filepath) - if not filepath then - return filepath - end - - local c_str = ffi.new("char[?]", #filepath + 1) - ffi.copy(c_str, filepath) - return ffi.string(ffi.C.shorten_dir(c_str)) - end - else - return function(filepath) - return filepath - end - end -end)() - -path.normalize = function(filepath, cwd) - filepath = path.make_relative(filepath, cwd) - - -- Substitute home directory w/ "~" - filepath = filepath:gsub("^" .. path.home, "~", 1) - - -- Remove double path separators, it's annoying - filepath = filepath:gsub(path.separator .. path.separator, path.separator) - - return filepath -end - -path.read_file = function(filepath) - local fd = vim.loop.fs_open(filepath, "r", 438) - if fd == nil then - return "" - end - local stat = assert(vim.loop.fs_fstat(fd)) - if stat.type ~= "file" then - return "" - end - local data = assert(vim.loop.fs_read(fd, stat.size, 0)) - assert(vim.loop.fs_close(fd)) - return data -end - -path.read_file_async = function(filepath, callback) - vim.loop.fs_open(filepath, "r", 438, function(err_open, fd) - if err_open then - print("We tried to open this file but couldn't. We failed with following error message: " .. err_open) - return - end - vim.loop.fs_fstat(fd, function(err_fstat, stat) - assert(not err_fstat, err_fstat) - if stat.type ~= "file" then - return callback "" - end - vim.loop.fs_read(fd, stat.size, 0, function(err_read, data) - assert(not err_read, err_read) - vim.loop.fs_close(fd, function(err_close) - assert(not err_close, err_close) - return callback(data) - end) - end) - end) - end) -end - -return setmetatable({}, { - __index = function(_, k) - log.error "telescope.path is deprecated. please use plenary.path instead" - return path[k] - end, -}) diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 646af03..f8e48f1 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -1,15 +1,12 @@ +require "telescope" + local a = vim.api -local async_lib = require "plenary.async_lib" -local async_util = async_lib.util +local async = require "plenary.async" +local await_schedule = async.util.scheduler +local channel = require("plenary.async.control").channel local popup = require "plenary.popup" -local async = async_lib.async -local await = async_lib.await -local channel = async_util.channel - -require "telescope" - local actions = require "telescope.actions" local action_set = require "telescope.actions.set" local config = require "telescope.config" @@ -70,12 +67,13 @@ function Picker:new(opts) selection_caret = get_default(opts.selection_caret, config.values.selection_caret), entry_prefix = get_default(opts.entry_prefix, config.values.entry_prefix), initial_mode = get_default(opts.initial_mode, config.values.initial_mode), + debounce = get_default(tonumber(opts.debounce), nil), default_text = opts.default_text, get_status_text = get_default(opts.get_status_text, config.values.get_status_text), _on_input_filter_cb = opts.on_input_filter_cb or function() end, - finder = opts.finder, + finder = assert(opts.finder, "Finder is required."), sorter = opts.sorter or require("telescope.sorters").empty(), all_previewers = opts.previewer, @@ -228,7 +226,7 @@ function Picker:highlight_displayed_rows(results_bufnr, prompt) end function Picker:highlight_one_row(results_bufnr, prompt, display, row) - local highlights = self:_track("_highlight_time", self.sorter.highlighter, self.sorter, prompt, display) + local highlights = self.sorter:highlighter(prompt, display) if highlights then for _, hl in ipairs(highlights) do @@ -274,8 +272,6 @@ function Picker:find() self:close_existing_pickers() self:reset_selection() - assert(self.finder, "Finder is required to do picking") - self.original_win_id = a.nvim_get_current_win() -- User autocmd run it before create Telescope window @@ -346,26 +342,50 @@ function Picker:find() self.prompt_prefix = prompt_prefix self:_reset_prefix_color() - -- Temporarily disabled: Draw the screen ASAP. This makes things feel speedier. - -- vim.cmd [[redraw]] - -- First thing we want to do is set all the lines to blank. self.max_results = popup_opts.results.height + -- 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, "")) + -- 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 debounced_status = debounce.throttle_leading(status_updater, 50) - -- local debounced_status = status_updater local tx, rx = channel.mpsc() self.__on_lines = tx.send - local main_loop = async(function() + local find_id = self:_next_find_id() + + local main_loop = async.void(function() + self.sorter:_init() + + -- Do filetype last, so that users can register at the last second. + pcall(a.nvim_buf_set_option, prompt_bufnr, "filetype", "TelescopePrompt") + pcall(a.nvim_buf_set_option, results_bufnr, "filetype", "TelescopeResults") + + -- TODO(async): I wonder if this should actually happen _before_ we nvim_buf_attach. + -- This way the buffer would always start with what we think it should when we start the loop. + if self.default_text then + self:set_prompt(self.default_text) + end + + if self.initial_mode == "insert" then + vim.cmd [[startinsert!]] + elseif self.initial_mode ~= "normal" then + error("Invalid setting for initial_mode: " .. self.initial_mode) + end + + await_schedule() + while true do - await(async_lib.scheduler()) + -- Wait for the next input + rx.last() - local _, _, _, first_line, last_line = await(rx.last()) self:_reset_track() if not vim.api.nvim_buf_is_valid(prompt_bufnr) then @@ -373,74 +393,58 @@ function Picker:find() return end - if not first_line then - first_line = 0 - end - if not last_line then - last_line = 1 - end - - if first_line > 0 or last_line > 1 then - log.debug("ON_LINES: Bad range", first_line, last_line, self:_get_prompt()) - return - end - - local original_prompt = self:_get_prompt() - local on_input_result = self._on_input_filter_cb(original_prompt) or {} + local start_time = vim.loop.hrtime() - local prompt = on_input_result.prompt or original_prompt - local finder = on_input_result.updated_finder + local prompt = self:_get_prompt() + local on_input_result = self._on_input_filter_cb(prompt) or {} - if finder then - self.finder:close() - self.finder = finder + local new_prompt = on_input_result.prompt + if new_prompt then + prompt = new_prompt end - if self.sorter then - self.sorter:_start(prompt) + 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 + self.sorter:_start(prompt) self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats) - local find_id = self:_next_find_id() 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 ok, msg = pcall(function() - self.finder(prompt, process_result, vim.schedule_wrap(process_complete)) + self.finder(prompt, process_result, process_complete) end) if not ok then - log.warn("Failed with msg: ", msg) + log.warn("Finder failed with msg: ", msg) + end + + local diff_time = (vim.loop.hrtime() - start_time) / 1e6 + if self.debounce and diff_time < self.debounce then + async.util.sleep(self.debounce - diff_time) end end end) -- Register attach vim.api.nvim_buf_attach(prompt_bufnr, false, { - on_lines = tx.send, - on_detach = function() - -- TODO: Can we add a "cleanup" / "teardown" function that completely removes these. - self.finder = nil - self.previewer = nil - self.sorter = nil - self.manager = nil + on_lines = function(...) + find_id = self:_next_find_id() - self.closed = true + self._result_completed = false + status_updater { completed = false } - -- TODO: Should we actually do this? - collectgarbage() - collectgarbage() + tx.send(...) + end, + on_detach = function() + self:_detach() end, }) - if self.sorter then - self.sorter:_init() - end - async_lib.run(main_loop()) - status_updater() - -- TODO: Use WinLeave as well? local on_buf_leave = string.format( [[ autocmd BufLeave <buffer> ++nested ++once :silent lua require('telescope.pickers').on_close_prompt(%s)]], @@ -480,19 +484,8 @@ function Picker:find() mappings.apply_keymap(prompt_bufnr, self.attach_mappings, config.values.mappings) - -- Do filetype last, so that users can register at the last second. - pcall(a.nvim_buf_set_option, prompt_bufnr, "filetype", "TelescopePrompt") - pcall(a.nvim_buf_set_option, results_bufnr, "filetype", "TelescopeResults") - - if self.default_text then - self:set_prompt(self.default_text) - end - - if self.initial_mode == "insert" then - vim.cmd [[startinsert!]] - elseif self.initial_mode ~= "normal" then - error("Invalid setting for initial_mode: " .. self.initial_mode) - end + tx.send() + main_loop() end function Picker:hide_preview() @@ -791,9 +784,7 @@ function Picker:set_selection(row) end local caret = self.selection_caret - -- local display = string.format('%s %s', caret, - -- (a.nvim_buf_get_lines(results_bufnr, row, row + 1, false)[1] or ''):sub(3) - -- ) + local display, display_highlights = entry_display.resolve(self, entry) display = caret .. display @@ -939,23 +930,6 @@ function Picker:_reset_track() self.stats.highlights = 0 end -function Picker:_track(key, func, ...) - local start, final - if self.track then - start = vim.loop.hrtime() - end - - -- Hack... we just do this so that we can track stuff that returns two values. - local res1, res2 = func(...) - - if self.track then - final = vim.loop.hrtime() - self.stats[key] = final - start + self.stats[key] - end - - return res1, res2 -end - function Picker:_increment(key) self.stats[key] = (self.stats[key] or 0) + 1 end @@ -987,12 +961,12 @@ function Picker:close_existing_pickers() end function Picker:get_status_updater(prompt_win, prompt_bufnr) - return function() - local text = self:get_status_text() + return function(opts) if self.closed or not vim.api.nvim_buf_is_valid(prompt_bufnr) then return end - local current_prompt = vim.api.nvim_buf_get_lines(prompt_bufnr, 0, 1, false)[1] + + local current_prompt = self:_get_prompt() if not current_prompt then return end @@ -1001,10 +975,11 @@ function Picker:get_status_updater(prompt_win, prompt_bufnr) return end - local prompt_len = #current_prompt + local text = self:get_status_text(opts) + local prompt_len = #self.prompt_prefix + #current_prompt - local padding = string.rep(" ", vim.api.nvim_win_get_width(prompt_win) - prompt_len - #text - 3) - vim.api.nvim_buf_clear_namespace(prompt_bufnr, ns_telescope_prompt, 0, 1) + local padding = string.rep(" ", vim.api.nvim_win_get_width(prompt_win) - prompt_len - #text) + vim.api.nvim_buf_clear_namespace(prompt_bufnr, ns_telescope_prompt, 0, -1) vim.api.nvim_buf_set_virtual_text(prompt_bufnr, ns_telescope_prompt, 0, { { padding .. text, "NonText" } }, {}) -- TODO: Wait for bfredl @@ -1022,7 +997,7 @@ end function Picker:get_result_processor(find_id, prompt, status_updater) local cb_add = function(score, entry) self.manager:add_entry(self, score, entry) - status_updater() + status_updater { completed = false } end local cb_filter = function(_) @@ -1030,7 +1005,7 @@ function Picker:get_result_processor(find_id, prompt, status_updater) end return function(entry) - if find_id ~= self._find_id or self.closed or self:is_done() then + if find_id ~= self._find_id then return true end @@ -1059,61 +1034,62 @@ function Picker:get_result_processor(find_id, prompt, status_updater) end function Picker:get_result_completor(results_bufnr, find_id, prompt, status_updater) - return function() + return vim.schedule_wrap(function() if self.closed == true or self:is_done() then return end - local selection_strategy = self.selection_strategy or "reset" + self:_do_selection(prompt) - -- TODO: Either: always leave one result or make sure we actually clean up the results when nothing matches - if selection_strategy == "row" then - if self._selection_row == nil and self.default_selection_index ~= nil then - self:set_selection(self:get_row(self.default_selection_index)) - else - self:set_selection(self:get_selection_row()) - end - elseif selection_strategy == "follow" then - if self._selection_row == nil and self.default_selection_index ~= nil then - self:set_selection(self:get_row(self.default_selection_index)) - else - local index = self.manager:find_entry(self:get_selection()) + state.set_global_key("current_line", self:_get_prompt()) + status_updater { completed = true } - if index then - local follow_row = self:get_row(index) - self:set_selection(follow_row) - else - self:set_selection(self:get_reset_row()) - end - end - elseif selection_strategy == "reset" then - if self.default_selection_index ~= nil then - self:set_selection(self:get_row(self.default_selection_index)) - else - self:set_selection(self:get_reset_row()) - end - elseif selection_strategy == "closest" then - if prompt == "" and self.default_selection_index ~= nil then - self:set_selection(self:get_row(self.default_selection_index)) + self:clear_extra_rows(results_bufnr) + self:highlight_displayed_rows(results_bufnr, prompt) + self.sorter:_finish(prompt) + + self:_on_complete() + + self._result_completed = true + end) +end + +function Picker:_do_selection(prompt) + local selection_strategy = self.selection_strategy or "reset" + -- TODO: Either: always leave one result or make sure we actually clean up the results when nothing matches + if selection_strategy == "row" then + if self._selection_row == nil and self.default_selection_index ~= nil then + self:set_selection(self:get_row(self.default_selection_index)) + else + self:set_selection(self:get_selection_row()) + end + elseif selection_strategy == "follow" then + if self._selection_row == nil and self.default_selection_index ~= nil then + self:set_selection(self:get_row(self.default_selection_index)) + else + local index = self.manager:find_entry(self:get_selection()) + + if index then + local follow_row = self:get_row(index) + self:set_selection(follow_row) else self:set_selection(self:get_reset_row()) end + end + elseif selection_strategy == "reset" then + if self.default_selection_index ~= nil then + self:set_selection(self:get_row(self.default_selection_index)) else - error("Unknown selection strategy: " .. selection_strategy) + self:set_selection(self:get_reset_row()) end - - local current_line = vim.api.nvim_get_current_line():sub(self.prompt_prefix:len() + 1) - state.set_global_key("current_line", current_line) - - status_updater() - - self:clear_extra_rows(results_bufnr) - self:highlight_displayed_rows(results_bufnr, prompt) - if self.sorter then - self.sorter:_finish(prompt) + elseif selection_strategy == "closest" then + if prompt == "" and self.default_selection_index ~= nil then + self:set_selection(self:get_row(self.default_selection_index)) + else + self:set_selection(self:get_reset_row()) end - - self:_on_complete() + else + error("Unknown selection strategy: " .. selection_strategy) end end @@ -1169,6 +1145,18 @@ function Picker:_reset_highlights() self.highlighter:clear_display() end +function Picker:_detach() + self.finder:close() + + -- TODO: Can we add a "cleanup" / "teardown" function that completely removes these. + -- self.finder = nil + -- self.previewer = nil + -- self.sorter = nil + -- self.manager = nil + + self.closed = true +end + pickers._Picker = Picker return pickers diff --git a/lua/telescope/pickers/highlights.lua b/lua/telescope/pickers/highlights.lua index 1be289e..e7b99e1 100644 --- a/lua/telescope/pickers/highlights.lua +++ b/lua/telescope/pickers/highlights.lua @@ -89,7 +89,7 @@ function Highlighter:hi_multiselect(row, is_selected) -- This is still kind of weird to me, since it seems like I'm erasing stuff -- when i shouldn't... perhaps it's a bout the gravity of the extmark? if #existing_marks > 0 then - log.trace("Clearning row: ", row) + log.trace("Clearning highlight multi select row: ", row) vim.api.nvim_buf_clear_namespace(results_bufnr, ns_telescope_multiselection, row, row + 1) end diff --git a/lua/telescope/sorters.lua b/lua/telescope/sorters.lua index 8874287..ba38e2d 100644 --- a/lua/telescope/sorters.lua +++ b/lua/telescope/sorters.lua @@ -96,10 +96,10 @@ function Sorter:_start(prompt) local len_previous = #previous if #prompt < len_previous then - log.debug "Reset discard because shorter prompt" + log.trace "Reset discard because shorter prompt" self._discard_state.filtered = {} elseif string.sub(prompt, 1, len_previous) ~= previous then - log.debug "Reset discard no match" + log.trace "Reset discard no match" self._discard_state.filtered = {} end @@ -167,11 +167,10 @@ end sorters.Sorter = Sorter -TelescopeCachedTails = TelescopeCachedTails or nil -if not TelescopeCachedTails then +local make_cached_tail = function() local os_sep = util.get_separator() local match_string = "[^" .. os_sep .. "]*$" - TelescopeCachedTails = setmetatable({}, { + return setmetatable({}, { __index = function(t, k) local tail = string.match(k, match_string) @@ -181,8 +180,8 @@ if not TelescopeCachedTails then }) end -TelescopeCachedUppers = TelescopeCachedUppers - or setmetatable({}, { +local make_cached_uppers = function() + return setmetatable({}, { __index = function(t, k) local obj = {} for i = 1, #k do @@ -196,8 +195,7 @@ TelescopeCachedUppers = TelescopeCachedUppers return obj end, }) - -TelescopeCachedNgrams = TelescopeCachedNgrams or {} +end -- TODO: Match on upper case words -- TODO: Match on last match @@ -206,9 +204,11 @@ sorters.get_fuzzy_file = function(opts) local ngram_len = opts.ngram_len or 2 + local cached_ngrams = {} + local function overlapping_ngrams(s, n) - if TelescopeCachedNgrams[s] and TelescopeCachedNgrams[s][n] then - return TelescopeCachedNgrams[s][n] + if cached_ngrams[s] and cached_ngrams[s][n] then + return cached_ngrams[s][n] end local R = {} @@ -216,15 +216,18 @@ sorters.get_fuzzy_file = function(opts) R[#R + 1] = s:sub(i, i + n - 1) end - if not TelescopeCachedNgrams[s] then - TelescopeCachedNgrams[s] = {} + if not cached_ngrams[s] then + cached_ngrams[s] = {} end - TelescopeCachedNgrams[s][n] = R + cached_ngrams[s][n] = R return R end + local cached_tails = make_cached_tail() + local cached_uppers = make_cached_uppers() + return Sorter:new { scoring_function = function(_, prompt, line) local N = #prompt @@ -243,8 +246,8 @@ sorters.get_fuzzy_file = function(opts) -- Contains the original string local contains_string = line_lower:find(prompt_lower, 1, true) - local prompt_uppers = TelescopeCachedUppers[prompt] - local line_uppers = TelescopeCachedUppers[line] + local prompt_uppers = cached_uppers[prompt] + local line_uppers = cached_uppers[line] local uppers_matching = 0 for k, _ in pairs(prompt_uppers) do @@ -254,7 +257,7 @@ sorters.get_fuzzy_file = function(opts) end -- TODO: Consider case senstivity - local tail = TelescopeCachedTails[line_lower] + local tail = cached_tails[line_lower] local contains_tail = tail:find(prompt, 1, true) local consecutive_matches = 0 @@ -313,9 +316,10 @@ sorters.get_generic_fuzzy_sorter = function(opts) local ngram_len = opts.ngram_len or 2 + local cached_ngrams = {} local function overlapping_ngrams(s, n) - if TelescopeCachedNgrams[s] and TelescopeCachedNgrams[s][n] then - return TelescopeCachedNgrams[s][n] + if cached_ngrams[s] and cached_ngrams[s][n] then + return cached_ngrams[s][n] end local R = {} @@ -323,11 +327,11 @@ sorters.get_generic_fuzzy_sorter = function(opts) R[#R + 1] = s:sub(i, i + n - 1) end - if not TelescopeCachedNgrams[s] then - TelescopeCachedNgrams[s] = {} + if not cached_ngrams[s] then + cached_ngrams[s] = {} end - TelescopeCachedNgrams[s][n] = R + cached_ngrams[s][n] = R return R end @@ -462,6 +466,9 @@ sorters.get_fzy_sorter = function(opts) } end +-- TODO: Could probably do something nice where we check their conf +-- and choose their default for this. +-- But I think `fzy` is good default for now. sorters.highlighter_only = function(opts) opts = opts or {} local fzy = opts.fzy_mod or require "telescope.algos.fzy" diff --git a/lua/tests/automated/telescope_spec.lua b/lua/tests/automated/telescope_spec.lua index 9b4cd5e..3bb76c3 100644 --- a/lua/tests/automated/telescope_spec.lua +++ b/lua/tests/automated/telescope_spec.lua @@ -11,8 +11,13 @@ describe("telescope", function() end) describe("attach_mappings", function() + local new_picker = function(a, b) + a.finder = true + return picker.new(a, b) + end + it("should allow for passing in a function", function() - local p = picker.new({}, { + local p = new_picker({}, { attach_mappings = function() return 1 end, @@ -22,7 +27,7 @@ describe("telescope", function() it("should override an attach mappings passed in by opts", function() local called_order = {} - local p = picker.new({ + local p = new_picker({ attach_mappings = function() table.insert(called_order, "opts") end, diff --git a/lua/tests/manual/all_defaults.lua b/lua/tests/manual/all_defaults.lua deleted file mode 100644 index 4d39a05..0000000 --- a/lua/tests/manual/all_defaults.lua +++ /dev/null @@ -1,22 +0,0 @@ ---[[ -vim.api.nvim_buf_set_lines(0, 4, -1, false, vim.tbl_keys(require('telescope.builtin'))) ---]] - -require("telescope.builtin").git_files() -RELOAD "telescope" -require("telescope.builtin").oldfiles() -require("telescope.builtin").grep_string() -require("telescope.builtin").lsp_document_symbols() -RELOAD "telescope" -require("telescope.builtin").lsp_workspace_symbols() -require("telescope.builtin").lsp_references() -require("telescope.builtin").builtin() -require("telescope.builtin").fd() -require("telescope.builtin").command_history() -require("telescope.builtin").search_history() -require("telescope.builtin").live_grep() -require("telescope.builtin").loclist() - --- TODO: make a function that puts stuff into quickfix. --- that way we can test this better. -require("telescope.builtin").quickfix() diff --git a/lua/tests/manual/auto_picker.lua b/lua/tests/manual/auto_picker.lua deleted file mode 100644 index 5189ba7..0000000 --- a/lua/tests/manual/auto_picker.lua +++ /dev/null @@ -1,80 +0,0 @@ -RELOAD "telescope" - -local finders = require "telescope.finders" -local make_entry = require "telescope.make_entry" -local previewers = require "telescope.previewers" -local pickers = require "telescope.pickers" -local sorters = require "telescope.sorters" - -local find_files = function(opts) - opts = opts or {} - opts.prompt_prefix = "" - - local find_command = opts.find_command - - if not find_command then - if 1 == vim.fn.executable "fd" then - find_command = { "fd", "--type", "f" } - elseif 1 == vim.fn.executable "fdfind" then - find_command = { "fdfind", "--type", "f" } - elseif 1 == vim.fn.executable "rg" then - find_command = { "rg", "--files" } - end - end - - if opts.cwd then - opts.cwd = vim.fn.expand(opts.cwd) - end - - opts.entry_maker = opts.entry_maker or make_entry.gen_from_file(opts) - - local p = pickers.new(opts, { - prompt = "Find Files", - finder = finders.new_oneshot_job(find_command, opts), - previewer = previewers.cat.new(opts), - sorter = sorters.get_fuzzy_file(), - - track = true, - }) - - local count = 0 - p:register_completion_callback(function(s) - print( - count, - vim.inspect(s.stats, { - process = function(item) - if type(item) == "string" and item:sub(1, 1) == "_" then - return nil - end - - return item - end, - }) - ) - - count = count + 1 - end) - - local feed = function(text, feed_opts) - feed_opts = feed_opts or "n" - vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(text, true, false, true), feed_opts, true) - end - - p:register_completion_callback(coroutine.wrap(function() - local input = "pickers.lua" - for i = 1, #input do - feed(input:sub(i, i)) - coroutine.yield() - end - - vim.wait(300, function() end) - feed("<CR>", "") - - coroutine.yield() - print "STILL CALLED?" - end)) - - p:find() -end - -find_files() diff --git a/lua/tests/manual/find_and_sort_spec.lua b/lua/tests/manual/find_and_sort_spec.lua deleted file mode 100644 index eec44b6..0000000 --- a/lua/tests/manual/find_and_sort_spec.lua +++ /dev/null @@ -1,105 +0,0 @@ -require("plenary.reload").reload_module "plenary" -require("plenary.reload").reload_module "telescope" - ---[[ - -Goals: -1. Easily test a sorter and finder to make sure we get all the results we need. - ---]] - -local finders = require "telescope.finders" -local make_entry = require "telescope.make_entry" -local pickers = require "telescope.pickers" -local sorters = require "telescope.sorters" -local EntryManager = require "telescope.entry_manager" - -local find_and_sort_test = function(prompt, f, s) - local info = {} - - local start = vim.loop.hrtime() - - info.filtered = 0 - info.added = 0 - info.scoring_time = 0 - info.set_entry = 0 - - local entry_manager = EntryManager:new(25, function() - info.set_entry = info.set_entry + 1 - end, info) - - local completed = false - - local process_result = function(entry) - local score_start = vim.loop.hrtime() - local score = s:score(prompt, entry) - info.scoring_time = info.scoring_time + (vim.loop.hrtime() - score_start) / 1e9 - - -- Filter these out here. - if score == -1 then - info.filtered = info.filtered + 1 - return - end - - info.added = info.added + 1 - entry_manager:add_entry(s:score(prompt, entry), entry) - end - - local process_complete = function() - info.time = (vim.loop.hrtime() - start) / 1e9 - - info.total = info.filtered + info.added - completed = true - end - - f(prompt, process_result, process_complete) - - -- Wait until we're done to return - vim.wait(5000, function() - return completed - end, 10) - - return entry_manager, info -end - -local info_to_csv = function(info, filename) - local writer = io.open(filename, "a") - - writer:write(string.format("%.8f", info.scoring_time) .. "\t") - writer:write(string.format("%.8f", info.time) .. "\t") - writer:write(info.looped .. "\t") - writer:write(info.filtered .. "\t") - writer:write(info.added .. "\t") - writer:write(info.inserted .. "\t") - writer:write(info.total .. "\t") - writer:write(info.set_entry .. "\t") - writer:write(string.format("%.0f", collectgarbage "count") .. "\t") - writer:write "\n" - - writer:close() -end - -local cwd = vim.fn.expand "~/build/neovim" - -collectgarbage "collect" -for _ = 1, 1 do - -- local s = sorters.get_fuzzy_file() - local s = sorters.get_generic_fuzzy_sorter() - local finder = finders.new_oneshot_job({ "fdfind" }, { - cwd = cwd, - entry_maker = make_entry.gen_from_file { cwd = cwd }, - -- disable_devicons = true, - -- maximum_results = 1000, - }) - - local res, info = find_and_sort_test("pickers.lua", finder, s) - - -- print(vim.inspect(res:get_entry(1))) - -- print(vim.inspect(info)) - - info_to_csv(info, "/home/tj/tmp/profile.csv") - - collectgarbage "collect" -end --- No skip: 2,206,186 --- Ya skip: 2,133 diff --git a/lua/tests/manual/large_search.lua b/lua/tests/manual/large_search.lua deleted file mode 100644 index 2685214..0000000 --- a/lua/tests/manual/large_search.lua +++ /dev/null @@ -1,29 +0,0 @@ -RELOAD "plenary" -RELOAD "telescope" - -local finders = require "telescope.finders" -local make_entry = require "telescope.make_entry" -local previewers = require "telescope.previewers" -local pickers = require "telescope.pickers" -local sorters = require "telescope.sorters" - -local cwd = vim.fn.expand "~/build/neovim" - -pickers.new({ - prompt = "Large search", - finder = finders.new_oneshot_job({ "fdfind" }, { - cwd = cwd, - entry_maker = make_entry.gen_from_file { cwd = cwd }, - -- disable_devicons = true, - -- maximum_results = 1000, - }), - sorter = sorters.get_fuzzy_file(), - previewer = previewers.cat.new { cwd = cwd }, -}):find() - --- vim.wait(3000, function() --- vim.cmd [[redraw!]] --- return COMPLETED --- end, 100) --- vim.cmd [[bd!]] --- vim.cmd [[stopinsert]] diff --git a/lua/tests/manual/newline_tables.lua b/lua/tests/manual/newline_tables.lua deleted file mode 100644 index 3be57a9..0000000 --- a/lua/tests/manual/newline_tables.lua +++ /dev/null @@ -1,24 +0,0 @@ -require("plenary.reload").reload_module "telescope" - -local finders = require "telescope.finders" -local pickers = require "telescope.pickers" -local sorters = require "telescope.sorters" -local previewers = require "telescope.previewers" -local make_entry = require "telescope.make_entry" - -local my_list = { - "lua/telescope/WIP.lua", - "lua/telescope/actions.lua", - "lua/telescope/builtin.lua", -} - -local opts = {} - -pickers.new(opts, { - prompt = "Telescope Builtin", - finder = finders.new_table { - results = my_list, - }, - sorter = sorters.get_generic_fuzzy_sorter(), - previewer = previewers.cat.new(opts), -}):find() diff --git a/lua/tests/manual/profile_for_sorters.lua b/lua/tests/manual/profile_for_sorters.lua deleted file mode 100644 index 05a657a..0000000 --- a/lua/tests/manual/profile_for_sorters.lua +++ /dev/null @@ -1,70 +0,0 @@ --- TODO: Add a ladder test. --- 1, 2, 4, 8, 16, 32 attempts - -RELOAD "plenary" --- RELOAD('telescope') - -local profiler = require "plenary.profile.lua_profiler" -local Job = require "plenary.job" - -BIG_LIST = nil -BIG_LIST = BIG_LIST or Job:new({ command = "fdfind", cwd = "~/build/" }):sync() -print(#BIG_LIST) - -local do_profile = true -local sorter_to_test = require("telescope.sorters").get_fuzzy_file() - -local strings_to_test = { "", "ev", "eval.c", "neovim/eval.c" } - -if do_profile then - profiler.start() -end - -local first_results = setmetatable({}, { - __index = function(t, k) - local obj = {} - rawset(t, k, obj) - return obj - end, -}) - -local second_results = {} - -local do_iterations = function(num) - local start - for _, prompt in ipairs(strings_to_test) do - start = vim.fn.reltime() - - for _ = 1, num do - for _, v in ipairs(BIG_LIST) do - sorter_to_test:score(prompt, v) - end - end - -- print("First Time: ", vim.fn.reltimestr(vim.fn.reltime(start)), num, prompt) - table.insert(first_results[prompt], vim.fn.reltimestr(vim.fn.reltime(start))) - - start = vim.fn.reltime() - for _ = 1, num do - for _, v in ipairs(BIG_LIST) do - sorter_to_test:score(prompt, v) - end - end - - -- print("Second Time: ", vim.fn.reltimestr(vim.fn.reltime(start)), num, prompt) - table.insert(second_results, vim.fn.reltimestr(vim.fn.reltime(start))) - end -end - -do_iterations(1) --- do_iterations(2) --- do_iterations(4) --- do_iterations(8) --- do_iterations(16) --- do_iterations(32) - -print(vim.inspect(first_results)) - -if do_profile then - profiler.stop() - profiler.report "/home/tj/tmp/profiler_score.txt" -end diff --git a/lua/tests/manual/reference_tracker.lua b/lua/tests/manual/reference_tracker.lua deleted file mode 100644 index f9e04c9..0000000 --- a/lua/tests/manual/reference_tracker.lua +++ /dev/null @@ -1,50 +0,0 @@ --- local actions = require('telescope.actions') --- local utils = require('telescope.utils') -require "telescope" -local finders = require "telescope.finders" -local make_entry = require "telescope.make_entry" -local previewers = require "telescope.previewers" -local pickers = require "telescope.pickers" -local sorters = require "telescope.sorters" - -local log = require "telescope.log" - -local real_opts = setmetatable({}, { __mode = "v" }) -local opts = setmetatable({}, { - __index = function(t, k) - log.debug("accessing:", k) - return real_opts[k] - end, - __newindex = function(t, k, v) - log.debug("setting:", k, v) - real_opts[k] = v - end, -}) - -opts.entry_maker = opts.entry_maker or make_entry.gen_from_file() -if opts.cwd then - opts.cwd = vim.fn.expand(opts.cwd) -end - --- local get_finder_opts = function(opts) --- local t = {} --- t.entry_maker = table.pop(opts, 'entry_maker') --- return t --- end - --- local finder_opts = get_finder_opts(opts) --- assert(not opts.entry_maker) - -local picker_config = { - prompt = "Git File", - finder = finders.new_oneshot_job({ "git", "ls-files", "-o", "--exclude-standard", "-c" }, opts), - -- previewer = previewers.cat.new(opts), - -- sorter = sorters.get_fuzzy_file(opts), - -- sorter = sorters.get_fuzzy_file(), -} - -log.debug "Done with config" - -local x = pickers.new(picker_config) -x:find() -x = nil diff --git a/lua/tests/manual/resolver_spec.lua b/lua/tests/manual/resolver_spec.lua deleted file mode 100644 index a03bfea..0000000 --- a/lua/tests/manual/resolver_spec.lua +++ /dev/null @@ -1,62 +0,0 @@ -RELOAD "telescope" - -local resolve = require "telescope.config.resolve" - -local eq = function(a, b) - if a ~= b then - error(string.format("Expected a == b, got: %s and %s", vim.inspect(a), vim.inspect(b))) - end -end - -local opt = nil - -local height_config = 0.8 -opt = resolve.win_option(height_config) - -eq(height_config, opt.preview) -eq(height_config, opt.prompt) -eq(height_config, opt.results) - -opt = resolve.win_option(nil, height_config) - -eq(height_config, opt.preview) -eq(height_config, opt.prompt) -eq(height_config, opt.results) - -local table_val = { "a" } -opt = resolve.win_option(nil, table_val) -eq(table_val, opt.preview) -eq(table_val, opt.prompt) -eq(table_val, opt.results) - -local prompt_override = { "a", prompt = "b" } -opt = resolve.win_option(prompt_override) -eq("a", opt.preview) -eq("a", opt.results) -eq("b", opt.prompt) - -local all_specified = { preview = "a", prompt = "b", results = "c" } -opt = resolve.win_option(all_specified) -eq("a", opt.preview) -eq("b", opt.prompt) -eq("c", opt.results) - -local some_specified = { prompt = "b", results = "c" } -opt = resolve.win_option(some_specified, "a") -eq("a", opt.preview) -eq("b", opt.prompt) -eq("c", opt.results) - -eq(10, resolve.resolve_height(0.1)(nil, 24, 100)) -eq(2, resolve.resolve_width(0.1)(nil, 24, 100)) - -eq(10, resolve.resolve_width(10)(nil, 24, 100)) -eq(24, resolve.resolve_width(50)(nil, 24, 100)) - --- local true_table = {true} --- opt = resolve.win_option(some_specified, 'a') --- eq('a', opt.preview) --- eq('b', opt.prompt) --- eq('c', opt.results) - -print "DONE!" diff --git a/lua/tests/manual/slow_oneshot.lua b/lua/tests/manual/slow_oneshot.lua deleted file mode 100644 index e16b3e1..0000000 --- a/lua/tests/manual/slow_oneshot.lua +++ /dev/null @@ -1,70 +0,0 @@ -RELOAD "telescope" - -local actions = require "telescope.actions" -local finders = require "telescope.finders" -local make_entry = require "telescope.make_entry" -local previewers = require "telescope.previewers" -local pickers = require "telescope.pickers" -local sorters = require "telescope.sorters" -local utils = require "telescope.utils" - -local slow_proc = function(opts) - opts = opts or {} - - if opts.cwd then - opts.cwd = vim.fn.expand(opts.cwd) - end - - opts.entry_maker = opts.entry_maker or make_entry.gen_from_file(opts) - - local p = pickers.new(opts, { - prompt = "Slow Proc", - finder = finders.new_oneshot_job({ "./scratch/slow_proc.sh" }, opts), - previewer = previewers.cat.new(opts), - sorter = sorters.get_fuzzy_file(), - - track = true, - }) - - local count = 0 - p:register_completion_callback(function(s) - print( - count, - vim.inspect(s.stats, { - process = function(item) - if type(item) == "string" and item:sub(1, 1) == "_" then - return nil - end - - return item - end, - }) - ) - - count = count + 1 - end) - - local feed = function(text) - vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(text, true, false, true), "n", true) - end - - if false then - p:register_completion_callback(coroutine.wrap(function() - local input = "pickers.lua" - for i = 1, #input do - feed(input:sub(i, i)) - coroutine.yield() - end - - vim.wait(300, function() end) - - vim.cmd [[:q]] - vim.cmd [[:Messages]] - vim.cmd [[stopinsert]] - end)) - end - - p:find() -end - -slow_proc() |
