feat(performance): Major performance improvements using async v2 from @oberblastmeister (#987)
* start: Working w/ async jobs * short circuit to using bad finder if you pass writer.
This commit is contained in:
@@ -15,9 +15,6 @@ ignore = {
|
|||||||
globals = {
|
globals = {
|
||||||
"_",
|
"_",
|
||||||
"TelescopeGlobalState",
|
"TelescopeGlobalState",
|
||||||
"TelescopeCachedUppers",
|
|
||||||
"TelescopeCachedTails",
|
|
||||||
"TelescopeCachedNgrams",
|
|
||||||
"_TelescopeConfigurationValues",
|
"_TelescopeConfigurationValues",
|
||||||
"_TelescopeConfigurationPickers",
|
"_TelescopeConfigurationPickers",
|
||||||
"__TelescopeKeymapStore",
|
"__TelescopeKeymapStore",
|
||||||
|
|||||||
296
lua/telescope/_.lua
Normal file
296
lua/telescope/_.lua
Normal file
@@ -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
|
||||||
@@ -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)()
|
|
||||||
@@ -582,12 +582,22 @@ actions.git_staging_toggle = function(prompt_bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local entry_to_qf = function(entry)
|
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 {
|
return {
|
||||||
bufnr = entry.bufnr,
|
bufnr = entry.bufnr,
|
||||||
filename = from_entry.path(entry, false),
|
filename = from_entry.path(entry, false),
|
||||||
lnum = entry.lnum,
|
lnum = entry.lnum,
|
||||||
col = entry.col,
|
col = entry.col,
|
||||||
text = entry.text or entry.value.text or entry.value,
|
text = text,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ end
|
|||||||
|
|
||||||
--- Gets the current line
|
--- Gets the current line
|
||||||
function action_state.get_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
|
end
|
||||||
|
|
||||||
--- Gets the current picker
|
--- Gets the current picker
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ local finders = require "telescope.finders"
|
|||||||
local make_entry = require "telescope.make_entry"
|
local make_entry = require "telescope.make_entry"
|
||||||
local pickers = require "telescope.pickers"
|
local pickers = require "telescope.pickers"
|
||||||
local previewers = require "telescope.previewers"
|
local previewers = require "telescope.previewers"
|
||||||
|
local sorters = require "telescope.sorters"
|
||||||
local utils = require "telescope.utils"
|
local utils = require "telescope.utils"
|
||||||
local conf = require("telescope.config").values
|
local conf = require("telescope.config").values
|
||||||
local log = require "telescope.log"
|
local log = require "telescope.log"
|
||||||
@@ -80,8 +81,6 @@ files.live_grep = function(opts)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
prompt = escape_chars(prompt)
|
|
||||||
|
|
||||||
local search_list = {}
|
local search_list = {}
|
||||||
|
|
||||||
if search_dirs then
|
if search_dirs then
|
||||||
@@ -103,7 +102,9 @@ files.live_grep = function(opts)
|
|||||||
prompt_title = "Live Grep",
|
prompt_title = "Live Grep",
|
||||||
finder = live_grepper,
|
finder = live_grepper,
|
||||||
previewer = conf.grep_previewer(opts),
|
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()
|
}):find()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
local actions = require "telescope.actions"
|
local channel = require("plenary.async.control").channel
|
||||||
|
|
||||||
local action_state = require "telescope.actions.state"
|
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 finders = require "telescope.finders"
|
||||||
local make_entry = require "telescope.make_entry"
|
local make_entry = require "telescope.make_entry"
|
||||||
local pickers = require "telescope.pickers"
|
local pickers = require "telescope.pickers"
|
||||||
local entry_display = require "telescope.pickers.entry_display"
|
|
||||||
local utils = require "telescope.utils"
|
|
||||||
local strings = require "plenary.strings"
|
local strings = require "plenary.strings"
|
||||||
local a = require "plenary.async_lib"
|
local utils = require "telescope.utils"
|
||||||
local async, await = a.async, a.await
|
|
||||||
local channel = a.util.channel
|
|
||||||
|
|
||||||
local conf = require("telescope.config").values
|
|
||||||
|
|
||||||
local lsp = {}
|
local lsp = {}
|
||||||
|
|
||||||
@@ -309,20 +307,21 @@ lsp.workspace_symbols = function(opts)
|
|||||||
}):find()
|
}):find()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO(MERGE)
|
||||||
local function get_workspace_symbols_requester(bufnr)
|
local function get_workspace_symbols_requester(bufnr)
|
||||||
local cancel = function() end
|
local cancel = function() end
|
||||||
|
|
||||||
return async(function(prompt)
|
return function(prompt)
|
||||||
local tx, rx = channel.oneshot()
|
local tx, rx = channel.oneshot()
|
||||||
cancel()
|
cancel()
|
||||||
_, cancel = vim.lsp.buf_request(bufnr, "workspace/symbol", { query = prompt }, tx)
|
_, 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)
|
assert(not err, err)
|
||||||
|
|
||||||
local locations = vim.lsp.util.symbols_to_items(results_lsp or {}, bufnr) or {}
|
local locations = vim.lsp.util.symbols_to_items(results_lsp or {}, bufnr) or {}
|
||||||
return locations
|
return locations
|
||||||
end)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
lsp.dynamic_workspace_symbols = function(opts)
|
lsp.dynamic_workspace_symbols = function(opts)
|
||||||
@@ -335,7 +334,7 @@ lsp.dynamic_workspace_symbols = function(opts)
|
|||||||
fn = get_workspace_symbols_requester(curr_bufnr),
|
fn = get_workspace_symbols_requester(curr_bufnr),
|
||||||
},
|
},
|
||||||
previewer = conf.qflist_previewer(opts),
|
previewer = conf.qflist_previewer(opts),
|
||||||
sorter = conf.generic_sorter(),
|
sorter = conf.generic_sorter(opts),
|
||||||
}):find()
|
}):find()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -219,13 +219,20 @@ local telescope_defaults = {
|
|||||||
borderchars = { { "─", "│", "─", "│", "╭", "╮", "╯", "╰" } },
|
borderchars = { { "─", "│", "─", "│", "╭", "╮", "╯", "╰" } },
|
||||||
|
|
||||||
get_status_text = {
|
get_status_text = {
|
||||||
function(self)
|
function(self, opts)
|
||||||
local xx = (self.stats.processed or 0) - (self.stats.filtered or 0)
|
local xx = (self.stats.processed or 0) - (self.stats.filtered or 0)
|
||||||
local yy = self.stats.processed or 0
|
local yy = self.stats.processed or 0
|
||||||
if xx == 0 and yy == 0 then
|
if xx == 0 and yy == 0 then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- local status_icon
|
||||||
|
-- if opts.completed then
|
||||||
|
-- status_icon = "✔️"
|
||||||
|
-- else
|
||||||
|
-- status_icon = "*"
|
||||||
|
-- end
|
||||||
|
|
||||||
return string.format("%s / %s", xx, yy)
|
return string.format("%s / %s", xx, yy)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -155,7 +155,10 @@ function EntryManager:add_entry(picker, score, entry)
|
|||||||
info.looped = info.looped + 1
|
info.looped = info.looped + 1
|
||||||
|
|
||||||
if container[2] > score then
|
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)
|
return self:_insert_container_before(picker, index, node, new_container)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -174,11 +177,13 @@ function EntryManager:add_entry(picker, score, entry)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function EntryManager:iter()
|
function EntryManager:iter()
|
||||||
return coroutine.wrap(function()
|
local iterator = self.linked_states:iter()
|
||||||
for val in self.linked_states:iter() do
|
return function()
|
||||||
coroutine.yield(val[1])
|
local val = iterator()
|
||||||
|
if val then
|
||||||
|
return val[1]
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return EntryManager
|
return EntryManager
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ local Job = require "plenary.job"
|
|||||||
|
|
||||||
local make_entry = require "telescope.make_entry"
|
local make_entry = require "telescope.make_entry"
|
||||||
local log = require "telescope.log"
|
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_static_finder = require "telescope.finders.async_static_finder"
|
||||||
local async_oneshot_finder = require "telescope.finders.async_oneshot_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 = {}
|
local finders = {}
|
||||||
|
|
||||||
@@ -103,7 +101,7 @@ function JobFinder:_find(prompt, process_result, process_complete)
|
|||||||
enable_recording = false,
|
enable_recording = false,
|
||||||
|
|
||||||
on_stdout = on_output,
|
on_stdout = on_output,
|
||||||
on_stderr = on_output,
|
-- on_stderr = on_output,
|
||||||
|
|
||||||
on_exit = function()
|
on_exit = function()
|
||||||
process_complete()
|
process_complete()
|
||||||
@@ -131,17 +129,15 @@ function DynamicFinder:new(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function DynamicFinder:_find(prompt, process_result, process_complete)
|
function DynamicFinder:_find(prompt, process_result, process_complete)
|
||||||
a.scope(function()
|
local results = self.fn(prompt)
|
||||||
local results = await(self.fn(prompt))
|
|
||||||
|
|
||||||
for _, result in ipairs(results) do
|
for _, result in ipairs(results) do
|
||||||
if process_result(self.entry_maker(result)) then
|
if process_result(self.entry_maker(result)) then
|
||||||
return
|
return
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
process_complete()
|
process_complete()
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return a new Finder
|
--- Return a new Finder
|
||||||
@@ -154,31 +150,18 @@ finders._new = function(opts)
|
|||||||
return JobFinder:new(opts)
|
return JobFinder:new(opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
finders.new_job = function(command_generator, entry_maker, maximum_results, cwd)
|
finders.new_async_job = function(opts)
|
||||||
-- return async_job_finder {
|
if opts.writer then
|
||||||
-- command_generator = command_generator,
|
return finders._new(opts)
|
||||||
-- entry_maker = entry_maker,
|
end
|
||||||
-- maximum_results = maximum_results,
|
|
||||||
-- cwd = cwd,
|
|
||||||
-- }
|
|
||||||
|
|
||||||
return JobFinder:new {
|
return async_job_finder(opts)
|
||||||
fn_command = function(_, prompt)
|
end
|
||||||
local command_list = command_generator(prompt)
|
|
||||||
if command_list == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local command = table.remove(command_list, 1)
|
|
||||||
|
|
||||||
return {
|
|
||||||
command = command,
|
|
||||||
args = command_list,
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
|
|
||||||
|
finders.new_job = function(command_generator, entry_maker, _, cwd)
|
||||||
|
return async_job_finder {
|
||||||
|
command_generator = command_generator,
|
||||||
entry_maker = entry_maker,
|
entry_maker = entry_maker,
|
||||||
maximum_results = maximum_results,
|
|
||||||
cwd = cwd,
|
cwd = cwd,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -186,8 +169,8 @@ end
|
|||||||
--- One shot job
|
--- One shot job
|
||||||
---@param command_list string[]: Command list to execute.
|
---@param command_list string[]: Command list to execute.
|
||||||
---@param opts table: stuff
|
---@param opts table: stuff
|
||||||
--- @key entry_maker function Optional: function(line: string) => table
|
-- @key entry_maker function Optional: function(line: string) => table
|
||||||
--- @key cwd string
|
-- @key cwd string
|
||||||
finders.new_oneshot_job = function(command_list, opts)
|
finders.new_oneshot_job = function(command_list, opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
local log = require "telescope.log"
|
local async_job = require "telescope._"
|
||||||
local Job = require "plenary.job"
|
local LinesPipe = require("telescope._").LinesPipe
|
||||||
|
|
||||||
local async_lib = require "plenary.async_lib"
|
|
||||||
local async = async_lib.async
|
|
||||||
-- local await = async_lib.await
|
|
||||||
local void = async_lib.void
|
|
||||||
|
|
||||||
local make_entry = require "telescope.make_entry"
|
local make_entry = require "telescope.make_entry"
|
||||||
|
local log = require "telescope.log"
|
||||||
|
|
||||||
return function(opts)
|
return function(opts)
|
||||||
|
log.trace("Creating async_job:", opts)
|
||||||
local entry_maker = opts.entry_maker or make_entry.gen_from_string()
|
local entry_maker = opts.entry_maker or make_entry.gen_from_string()
|
||||||
local fn_command = function(prompt)
|
local fn_command = function(prompt)
|
||||||
local command_list = opts.command_generator(prompt)
|
local command_list = opts.command_generator(prompt)
|
||||||
@@ -18,58 +15,61 @@ return function(opts)
|
|||||||
|
|
||||||
local command = table.remove(command_list, 1)
|
local command = table.remove(command_list, 1)
|
||||||
|
|
||||||
return {
|
local res = {
|
||||||
command = command,
|
command = command,
|
||||||
args = command_list,
|
args = command_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
local job
|
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)
|
local callable = function(_, prompt, process_result, process_complete)
|
||||||
if not job_opts then
|
if job then
|
||||||
|
job:close(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
local job_opts = fn_command(prompt)
|
||||||
|
if not job_opts then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
job = async_job.spawn {
|
||||||
|
command = job_opts.command,
|
||||||
|
args = job_opts.args,
|
||||||
|
cwd = job_opts.cwd or opts.cwd,
|
||||||
|
writer = writer,
|
||||||
|
|
||||||
|
stdout = stdout,
|
||||||
|
}
|
||||||
|
|
||||||
|
for line in stdout:iter(true) do
|
||||||
|
if process_result(entry_maker(line)) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local writer = nil
|
process_complete()
|
||||||
if job_opts.writer and Job.is_job(job_opts.writer) then
|
end
|
||||||
writer = job_opts.writer
|
|
||||||
elseif opts.writer then
|
return setmetatable({
|
||||||
writer = Job:new(job_opts.writer)
|
close = function()
|
||||||
|
if job then
|
||||||
|
job:close(true)
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
job = Job:new {
|
}, {
|
||||||
command = job_opts.command,
|
__call = callable,
|
||||||
args = job_opts.args,
|
|
||||||
cwd = job_opts.cwd or opts.cwd,
|
|
||||||
maximum_results = opts.maximum_results,
|
|
||||||
writer = writer,
|
|
||||||
enable_recording = false,
|
|
||||||
|
|
||||||
on_stdout = vim.schedule_wrap(function(_, line)
|
|
||||||
if not line or line == "" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO: shutdown job here.
|
|
||||||
process_result(entry_maker(line))
|
|
||||||
end),
|
|
||||||
|
|
||||||
on_exit = function()
|
|
||||||
process_complete()
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
job:start()
|
|
||||||
end)),
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
local async_lib = require "plenary.async_lib"
|
local async = require "plenary.async"
|
||||||
local async = async_lib.async
|
local async_job = require "telescope._"
|
||||||
local await = async_lib.await
|
local LinesPipe = require("telescope._").LinesPipe
|
||||||
local void = async_lib.void
|
|
||||||
|
|
||||||
local AWAITABLE = 1000
|
|
||||||
|
|
||||||
local make_entry = require "telescope.make_entry"
|
local make_entry = require "telescope.make_entry"
|
||||||
|
|
||||||
local Job = require "plenary.job"
|
|
||||||
|
|
||||||
return function(opts)
|
return function(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
|
|
||||||
@@ -21,64 +16,65 @@ return function(opts)
|
|||||||
|
|
||||||
local job_started = false
|
local job_started = false
|
||||||
local job_completed = false
|
local job_completed = false
|
||||||
|
local stdout = nil
|
||||||
|
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
close = function()
|
-- close = function() results = {}; job_started = false end,
|
||||||
results = {}
|
close = function() end,
|
||||||
job_started = false
|
|
||||||
end,
|
|
||||||
results = results,
|
results = results,
|
||||||
}, {
|
}, {
|
||||||
__call = void(async(function(_, prompt, process_result, process_complete)
|
__call = function(_, prompt, process_result, process_complete)
|
||||||
if not job_started then
|
if not job_started then
|
||||||
local job_opts = fn_command()
|
local job_opts = fn_command()
|
||||||
|
|
||||||
local writer
|
-- TODO: Handle writers.
|
||||||
if job_opts.writer and Job.is_job(job_opts.writer) then
|
-- local writer
|
||||||
writer = job_opts.writer
|
-- if job_opts.writer and Job.is_job(job_opts.writer) then
|
||||||
elseif job_opts.writer then
|
-- writer = job_opts.writer
|
||||||
writer = Job:new(job_opts.writer)
|
-- elseif job_opts.writer then
|
||||||
end
|
-- writer = Job:new(job_opts.writer)
|
||||||
|
-- end
|
||||||
|
|
||||||
local job = Job:new {
|
stdout = LinesPipe()
|
||||||
|
local _ = async_job.spawn {
|
||||||
command = job_opts.command,
|
command = job_opts.command,
|
||||||
args = job_opts.args,
|
args = job_opts.args,
|
||||||
cwd = job_opts.cwd or cwd,
|
cwd = cwd,
|
||||||
maximum_results = opts.maximum_results,
|
|
||||||
writer = writer,
|
|
||||||
enable_recording = false,
|
|
||||||
|
|
||||||
on_stdout = vim.schedule_wrap(function(_, line)
|
stdout = stdout,
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job:start()
|
|
||||||
job_started = true
|
job_started = true
|
||||||
end
|
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
|
local current_count = num_results
|
||||||
for index = 1, current_count do
|
for index = 1, current_count do
|
||||||
|
-- TODO: Figure out scheduling...
|
||||||
|
async.util.scheduler()
|
||||||
|
|
||||||
if process_result(results[index]) then
|
if process_result(results[index]) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
if index % AWAITABLE == 0 then
|
|
||||||
await(async_lib.scheduler())
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if job_completed then
|
if job_completed then
|
||||||
process_complete()
|
process_complete()
|
||||||
end
|
end
|
||||||
end)),
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
local async_lib = require "plenary.async_lib"
|
local scheduler = require("plenary.async").util.scheduler
|
||||||
local async = async_lib.async
|
|
||||||
local await = async_lib.await
|
|
||||||
local void = async_lib.void
|
|
||||||
|
|
||||||
local make_entry = require "telescope.make_entry"
|
local make_entry = require "telescope.make_entry"
|
||||||
|
|
||||||
@@ -29,18 +26,18 @@ return function(opts)
|
|||||||
results = results,
|
results = results,
|
||||||
close = function() end,
|
close = function() end,
|
||||||
}, {
|
}, {
|
||||||
__call = void(async(function(_, _, process_result, process_complete)
|
__call = function(_, _, process_result, process_complete)
|
||||||
for i, v in ipairs(results) do
|
for i, v in ipairs(results) do
|
||||||
if process_result(v) then
|
if process_result(v) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
if i % 1000 == 0 then
|
if i % 1000 == 0 then
|
||||||
await(async_lib.scheduler())
|
scheduler()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
process_complete()
|
process_complete()
|
||||||
end)),
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require "telescope._compat"
|
|
||||||
|
|
||||||
local _extensions = require "telescope._extensions"
|
local _extensions = require "telescope._extensions"
|
||||||
|
|
||||||
local telescope = {}
|
local telescope = {}
|
||||||
|
|||||||
@@ -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,
|
|
||||||
})
|
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
|
require "telescope"
|
||||||
|
|
||||||
local a = vim.api
|
local a = vim.api
|
||||||
|
|
||||||
local async_lib = require "plenary.async_lib"
|
local async = require "plenary.async"
|
||||||
local async_util = async_lib.util
|
local await_schedule = async.util.scheduler
|
||||||
|
local channel = require("plenary.async.control").channel
|
||||||
local popup = require "plenary.popup"
|
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 actions = require "telescope.actions"
|
||||||
local action_set = require "telescope.actions.set"
|
local action_set = require "telescope.actions.set"
|
||||||
local config = require "telescope.config"
|
local config = require "telescope.config"
|
||||||
@@ -70,12 +67,13 @@ function Picker:new(opts)
|
|||||||
selection_caret = get_default(opts.selection_caret, config.values.selection_caret),
|
selection_caret = get_default(opts.selection_caret, config.values.selection_caret),
|
||||||
entry_prefix = get_default(opts.entry_prefix, config.values.entry_prefix),
|
entry_prefix = get_default(opts.entry_prefix, config.values.entry_prefix),
|
||||||
initial_mode = get_default(opts.initial_mode, config.values.initial_mode),
|
initial_mode = get_default(opts.initial_mode, config.values.initial_mode),
|
||||||
|
debounce = get_default(tonumber(opts.debounce), nil),
|
||||||
|
|
||||||
default_text = opts.default_text,
|
default_text = opts.default_text,
|
||||||
get_status_text = get_default(opts.get_status_text, config.values.get_status_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,
|
_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(),
|
sorter = opts.sorter or require("telescope.sorters").empty(),
|
||||||
|
|
||||||
all_previewers = opts.previewer,
|
all_previewers = opts.previewer,
|
||||||
@@ -228,7 +226,7 @@ function Picker:highlight_displayed_rows(results_bufnr, prompt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Picker:highlight_one_row(results_bufnr, prompt, display, row)
|
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
|
if highlights then
|
||||||
for _, hl in ipairs(highlights) do
|
for _, hl in ipairs(highlights) do
|
||||||
@@ -274,8 +272,6 @@ function Picker:find()
|
|||||||
self:close_existing_pickers()
|
self:close_existing_pickers()
|
||||||
self:reset_selection()
|
self:reset_selection()
|
||||||
|
|
||||||
assert(self.finder, "Finder is required to do picking")
|
|
||||||
|
|
||||||
self.original_win_id = a.nvim_get_current_win()
|
self.original_win_id = a.nvim_get_current_win()
|
||||||
|
|
||||||
-- User autocmd run it before create Telescope window
|
-- User autocmd run it before create Telescope window
|
||||||
@@ -346,26 +342,50 @@ function Picker:find()
|
|||||||
self.prompt_prefix = prompt_prefix
|
self.prompt_prefix = prompt_prefix
|
||||||
self:_reset_prefix_color()
|
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.
|
-- First thing we want to do is set all the lines to blank.
|
||||||
self.max_results = popup_opts.results.height
|
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, ""))
|
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 debounced_status = status_updater
|
|
||||||
|
|
||||||
local tx, rx = channel.mpsc()
|
local tx, rx = channel.mpsc()
|
||||||
self.__on_lines = tx.send
|
self.__on_lines = tx.send
|
||||||
|
|
||||||
local main_loop = async(function()
|
local find_id = self:_next_find_id()
|
||||||
while true do
|
|
||||||
await(async_lib.scheduler())
|
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
|
||||||
|
-- Wait for the next input
|
||||||
|
rx.last()
|
||||||
|
|
||||||
local _, _, _, first_line, last_line = await(rx.last())
|
|
||||||
self:_reset_track()
|
self:_reset_track()
|
||||||
|
|
||||||
if not vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
if not vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
||||||
@@ -373,74 +393,58 @@ function Picker:find()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not first_line then
|
local start_time = vim.loop.hrtime()
|
||||||
first_line = 0
|
|
||||||
end
|
local prompt = self:_get_prompt()
|
||||||
if not last_line then
|
local on_input_result = self._on_input_filter_cb(prompt) or {}
|
||||||
last_line = 1
|
|
||||||
|
local new_prompt = on_input_result.prompt
|
||||||
|
if new_prompt then
|
||||||
|
prompt = new_prompt
|
||||||
end
|
end
|
||||||
|
|
||||||
if first_line > 0 or last_line > 1 then
|
local new_finder = on_input_result.updated_finder
|
||||||
log.debug("ON_LINES: Bad range", first_line, last_line, self:_get_prompt())
|
if new_finder then
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local original_prompt = self:_get_prompt()
|
|
||||||
local on_input_result = self._on_input_filter_cb(original_prompt) or {}
|
|
||||||
|
|
||||||
local prompt = on_input_result.prompt or original_prompt
|
|
||||||
local finder = on_input_result.updated_finder
|
|
||||||
|
|
||||||
if finder then
|
|
||||||
self.finder:close()
|
self.finder:close()
|
||||||
self.finder = finder
|
self.finder = new_finder
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.sorter then
|
self.sorter:_start(prompt)
|
||||||
self.sorter:_start(prompt)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO: Entry manager should have a "bulk" setter. This can prevent a lot of redraws from display
|
|
||||||
self.manager = EntryManager:new(self.max_results, self.entry_adder, self.stats)
|
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_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)
|
||||||
|
|
||||||
local ok, msg = pcall(function()
|
local ok, msg = pcall(function()
|
||||||
self.finder(prompt, process_result, vim.schedule_wrap(process_complete))
|
self.finder(prompt, process_result, process_complete)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if not ok then
|
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
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Register attach
|
-- Register attach
|
||||||
vim.api.nvim_buf_attach(prompt_bufnr, false, {
|
vim.api.nvim_buf_attach(prompt_bufnr, false, {
|
||||||
on_lines = tx.send,
|
on_lines = function(...)
|
||||||
|
find_id = self:_next_find_id()
|
||||||
|
|
||||||
|
self._result_completed = false
|
||||||
|
status_updater { completed = false }
|
||||||
|
|
||||||
|
tx.send(...)
|
||||||
|
end,
|
||||||
on_detach = function()
|
on_detach = function()
|
||||||
-- TODO: Can we add a "cleanup" / "teardown" function that completely removes these.
|
self:_detach()
|
||||||
self.finder = nil
|
|
||||||
self.previewer = nil
|
|
||||||
self.sorter = nil
|
|
||||||
self.manager = nil
|
|
||||||
|
|
||||||
self.closed = true
|
|
||||||
|
|
||||||
-- TODO: Should we actually do this?
|
|
||||||
collectgarbage()
|
|
||||||
collectgarbage()
|
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
if self.sorter then
|
|
||||||
self.sorter:_init()
|
|
||||||
end
|
|
||||||
async_lib.run(main_loop())
|
|
||||||
status_updater()
|
|
||||||
|
|
||||||
-- TODO: Use WinLeave as well?
|
-- TODO: Use WinLeave as well?
|
||||||
local on_buf_leave = string.format(
|
local on_buf_leave = string.format(
|
||||||
[[ autocmd BufLeave <buffer> ++nested ++once :silent lua require('telescope.pickers').on_close_prompt(%s)]],
|
[[ 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)
|
mappings.apply_keymap(prompt_bufnr, self.attach_mappings, config.values.mappings)
|
||||||
|
|
||||||
-- Do filetype last, so that users can register at the last second.
|
tx.send()
|
||||||
pcall(a.nvim_buf_set_option, prompt_bufnr, "filetype", "TelescopePrompt")
|
main_loop()
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Picker:hide_preview()
|
function Picker:hide_preview()
|
||||||
@@ -791,9 +784,7 @@ function Picker:set_selection(row)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local caret = self.selection_caret
|
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)
|
local display, display_highlights = entry_display.resolve(self, entry)
|
||||||
display = caret .. display
|
display = caret .. display
|
||||||
|
|
||||||
@@ -939,23 +930,6 @@ function Picker:_reset_track()
|
|||||||
self.stats.highlights = 0
|
self.stats.highlights = 0
|
||||||
end
|
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)
|
function Picker:_increment(key)
|
||||||
self.stats[key] = (self.stats[key] or 0) + 1
|
self.stats[key] = (self.stats[key] or 0) + 1
|
||||||
end
|
end
|
||||||
@@ -987,12 +961,12 @@ function Picker:close_existing_pickers()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Picker:get_status_updater(prompt_win, prompt_bufnr)
|
function Picker:get_status_updater(prompt_win, prompt_bufnr)
|
||||||
return function()
|
return function(opts)
|
||||||
local text = self:get_status_text()
|
|
||||||
if self.closed or not vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
if self.closed or not vim.api.nvim_buf_is_valid(prompt_bufnr) then
|
||||||
return
|
return
|
||||||
end
|
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
|
if not current_prompt then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -1001,10 +975,11 @@ function Picker:get_status_updater(prompt_win, prompt_bufnr)
|
|||||||
return
|
return
|
||||||
end
|
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)
|
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_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" } }, {})
|
vim.api.nvim_buf_set_virtual_text(prompt_bufnr, ns_telescope_prompt, 0, { { padding .. text, "NonText" } }, {})
|
||||||
|
|
||||||
-- TODO: Wait for bfredl
|
-- TODO: Wait for bfredl
|
||||||
@@ -1022,7 +997,7 @@ end
|
|||||||
function Picker:get_result_processor(find_id, prompt, status_updater)
|
function Picker:get_result_processor(find_id, prompt, status_updater)
|
||||||
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()
|
status_updater { completed = false }
|
||||||
end
|
end
|
||||||
|
|
||||||
local cb_filter = function(_)
|
local cb_filter = function(_)
|
||||||
@@ -1030,7 +1005,7 @@ function Picker:get_result_processor(find_id, prompt, status_updater)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return function(entry)
|
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
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1059,61 +1034,62 @@ function Picker:get_result_processor(find_id, prompt, status_updater)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Picker:get_result_completor(results_bufnr, find_id, prompt, status_updater)
|
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
|
if self.closed == true or self:is_done() then
|
||||||
return
|
return
|
||||||
end
|
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
|
state.set_global_key("current_line", self:_get_prompt())
|
||||||
if selection_strategy == "row" then
|
status_updater { completed = true }
|
||||||
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
|
|
||||||
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))
|
|
||||||
else
|
|
||||||
self:set_selection(self:get_reset_row())
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("Unknown selection strategy: " .. selection_strategy)
|
|
||||||
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:clear_extra_rows(results_bufnr)
|
||||||
self:highlight_displayed_rows(results_bufnr, prompt)
|
self:highlight_displayed_rows(results_bufnr, prompt)
|
||||||
if self.sorter then
|
self.sorter:_finish(prompt)
|
||||||
self.sorter:_finish(prompt)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:_on_complete()
|
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
|
||||||
|
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))
|
||||||
|
else
|
||||||
|
self:set_selection(self:get_reset_row())
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error("Unknown selection strategy: " .. selection_strategy)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1169,6 +1145,18 @@ function Picker:_reset_highlights()
|
|||||||
self.highlighter:clear_display()
|
self.highlighter:clear_display()
|
||||||
end
|
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
|
pickers._Picker = Picker
|
||||||
|
|
||||||
return pickers
|
return pickers
|
||||||
|
|||||||
@@ -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
|
-- 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?
|
-- when i shouldn't... perhaps it's a bout the gravity of the extmark?
|
||||||
if #existing_marks > 0 then
|
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)
|
vim.api.nvim_buf_clear_namespace(results_bufnr, ns_telescope_multiselection, row, row + 1)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -96,10 +96,10 @@ function Sorter:_start(prompt)
|
|||||||
local len_previous = #previous
|
local len_previous = #previous
|
||||||
|
|
||||||
if #prompt < len_previous then
|
if #prompt < len_previous then
|
||||||
log.debug "Reset discard because shorter prompt"
|
log.trace "Reset discard because shorter prompt"
|
||||||
self._discard_state.filtered = {}
|
self._discard_state.filtered = {}
|
||||||
elseif string.sub(prompt, 1, len_previous) ~= previous then
|
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 = {}
|
self._discard_state.filtered = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -167,11 +167,10 @@ end
|
|||||||
|
|
||||||
sorters.Sorter = Sorter
|
sorters.Sorter = Sorter
|
||||||
|
|
||||||
TelescopeCachedTails = TelescopeCachedTails or nil
|
local make_cached_tail = function()
|
||||||
if not TelescopeCachedTails then
|
|
||||||
local os_sep = util.get_separator()
|
local os_sep = util.get_separator()
|
||||||
local match_string = "[^" .. os_sep .. "]*$"
|
local match_string = "[^" .. os_sep .. "]*$"
|
||||||
TelescopeCachedTails = setmetatable({}, {
|
return setmetatable({}, {
|
||||||
__index = function(t, k)
|
__index = function(t, k)
|
||||||
local tail = string.match(k, match_string)
|
local tail = string.match(k, match_string)
|
||||||
|
|
||||||
@@ -181,8 +180,8 @@ if not TelescopeCachedTails then
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
TelescopeCachedUppers = TelescopeCachedUppers
|
local make_cached_uppers = function()
|
||||||
or setmetatable({}, {
|
return setmetatable({}, {
|
||||||
__index = function(t, k)
|
__index = function(t, k)
|
||||||
local obj = {}
|
local obj = {}
|
||||||
for i = 1, #k do
|
for i = 1, #k do
|
||||||
@@ -196,8 +195,7 @@ TelescopeCachedUppers = TelescopeCachedUppers
|
|||||||
return obj
|
return obj
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
end
|
||||||
TelescopeCachedNgrams = TelescopeCachedNgrams or {}
|
|
||||||
|
|
||||||
-- TODO: Match on upper case words
|
-- TODO: Match on upper case words
|
||||||
-- TODO: Match on last match
|
-- TODO: Match on last match
|
||||||
@@ -206,9 +204,11 @@ sorters.get_fuzzy_file = function(opts)
|
|||||||
|
|
||||||
local ngram_len = opts.ngram_len or 2
|
local ngram_len = opts.ngram_len or 2
|
||||||
|
|
||||||
|
local cached_ngrams = {}
|
||||||
|
|
||||||
local function overlapping_ngrams(s, n)
|
local function overlapping_ngrams(s, n)
|
||||||
if TelescopeCachedNgrams[s] and TelescopeCachedNgrams[s][n] then
|
if cached_ngrams[s] and cached_ngrams[s][n] then
|
||||||
return TelescopeCachedNgrams[s][n]
|
return cached_ngrams[s][n]
|
||||||
end
|
end
|
||||||
|
|
||||||
local R = {}
|
local R = {}
|
||||||
@@ -216,15 +216,18 @@ sorters.get_fuzzy_file = function(opts)
|
|||||||
R[#R + 1] = s:sub(i, i + n - 1)
|
R[#R + 1] = s:sub(i, i + n - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not TelescopeCachedNgrams[s] then
|
if not cached_ngrams[s] then
|
||||||
TelescopeCachedNgrams[s] = {}
|
cached_ngrams[s] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
TelescopeCachedNgrams[s][n] = R
|
cached_ngrams[s][n] = R
|
||||||
|
|
||||||
return R
|
return R
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local cached_tails = make_cached_tail()
|
||||||
|
local cached_uppers = make_cached_uppers()
|
||||||
|
|
||||||
return Sorter:new {
|
return Sorter:new {
|
||||||
scoring_function = function(_, prompt, line)
|
scoring_function = function(_, prompt, line)
|
||||||
local N = #prompt
|
local N = #prompt
|
||||||
@@ -243,8 +246,8 @@ sorters.get_fuzzy_file = function(opts)
|
|||||||
-- Contains the original string
|
-- Contains the original string
|
||||||
local contains_string = line_lower:find(prompt_lower, 1, true)
|
local contains_string = line_lower:find(prompt_lower, 1, true)
|
||||||
|
|
||||||
local prompt_uppers = TelescopeCachedUppers[prompt]
|
local prompt_uppers = cached_uppers[prompt]
|
||||||
local line_uppers = TelescopeCachedUppers[line]
|
local line_uppers = cached_uppers[line]
|
||||||
|
|
||||||
local uppers_matching = 0
|
local uppers_matching = 0
|
||||||
for k, _ in pairs(prompt_uppers) do
|
for k, _ in pairs(prompt_uppers) do
|
||||||
@@ -254,7 +257,7 @@ sorters.get_fuzzy_file = function(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Consider case senstivity
|
-- TODO: Consider case senstivity
|
||||||
local tail = TelescopeCachedTails[line_lower]
|
local tail = cached_tails[line_lower]
|
||||||
local contains_tail = tail:find(prompt, 1, true)
|
local contains_tail = tail:find(prompt, 1, true)
|
||||||
|
|
||||||
local consecutive_matches = 0
|
local consecutive_matches = 0
|
||||||
@@ -313,9 +316,10 @@ sorters.get_generic_fuzzy_sorter = function(opts)
|
|||||||
|
|
||||||
local ngram_len = opts.ngram_len or 2
|
local ngram_len = opts.ngram_len or 2
|
||||||
|
|
||||||
|
local cached_ngrams = {}
|
||||||
local function overlapping_ngrams(s, n)
|
local function overlapping_ngrams(s, n)
|
||||||
if TelescopeCachedNgrams[s] and TelescopeCachedNgrams[s][n] then
|
if cached_ngrams[s] and cached_ngrams[s][n] then
|
||||||
return TelescopeCachedNgrams[s][n]
|
return cached_ngrams[s][n]
|
||||||
end
|
end
|
||||||
|
|
||||||
local R = {}
|
local R = {}
|
||||||
@@ -323,11 +327,11 @@ sorters.get_generic_fuzzy_sorter = function(opts)
|
|||||||
R[#R + 1] = s:sub(i, i + n - 1)
|
R[#R + 1] = s:sub(i, i + n - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not TelescopeCachedNgrams[s] then
|
if not cached_ngrams[s] then
|
||||||
TelescopeCachedNgrams[s] = {}
|
cached_ngrams[s] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
TelescopeCachedNgrams[s][n] = R
|
cached_ngrams[s][n] = R
|
||||||
|
|
||||||
return R
|
return R
|
||||||
end
|
end
|
||||||
@@ -462,6 +466,9 @@ sorters.get_fzy_sorter = function(opts)
|
|||||||
}
|
}
|
||||||
end
|
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)
|
sorters.highlighter_only = function(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
local fzy = opts.fzy_mod or require "telescope.algos.fzy"
|
local fzy = opts.fzy_mod or require "telescope.algos.fzy"
|
||||||
|
|||||||
@@ -11,8 +11,13 @@ describe("telescope", function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe("attach_mappings", function()
|
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()
|
it("should allow for passing in a function", function()
|
||||||
local p = picker.new({}, {
|
local p = new_picker({}, {
|
||||||
attach_mappings = function()
|
attach_mappings = function()
|
||||||
return 1
|
return 1
|
||||||
end,
|
end,
|
||||||
@@ -22,7 +27,7 @@ describe("telescope", function()
|
|||||||
|
|
||||||
it("should override an attach mappings passed in by opts", function()
|
it("should override an attach mappings passed in by opts", function()
|
||||||
local called_order = {}
|
local called_order = {}
|
||||||
local p = picker.new({
|
local p = new_picker({
|
||||||
attach_mappings = function()
|
attach_mappings = function()
|
||||||
table.insert(called_order, "opts")
|
table.insert(called_order, "opts")
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -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()
|
|
||||||
@@ -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()
|
|
||||||
@@ -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
|
|
||||||
@@ -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]]
|
|
||||||
@@ -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()
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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!"
|
|
||||||
@@ -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()
|
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
|
|
||||||
" default.vim - Better vim than the default
|
|
||||||
" Maintainer: Liu-Cheng Xu <https://github.com/liuchengxu>
|
|
||||||
" Version: 1.0
|
|
||||||
" vim: et ts=2 sts=2 sw=2
|
|
||||||
|
|
||||||
scriptencoding utf-8
|
|
||||||
|
|
||||||
if &compatible || exists('g:loaded_vim_better_default')
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let g:loaded_vim_better_default = 1
|
|
||||||
|
|
||||||
let s:save_cpo = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
" Neovim has set these as default
|
|
||||||
if !has('nvim')
|
|
||||||
|
|
||||||
set nocompatible
|
|
||||||
|
|
||||||
syntax on " Syntax highlighting
|
|
||||||
filetype plugin indent on " Automatically detect file types
|
|
||||||
set autoindent " Indent at the same level of the previous line
|
|
||||||
set autoread " Automatically read a file changed outside of vim
|
|
||||||
set backspace=indent,eol,start " Backspace for dummies
|
|
||||||
set complete-=i " Exclude files completion
|
|
||||||
set display=lastline " Show as much as possible of the last line
|
|
||||||
set encoding=utf-8 " Set default encoding
|
|
||||||
set history=10000 " Maximum history record
|
|
||||||
set hlsearch " Highlight search terms
|
|
||||||
set incsearch " Find as you type search
|
|
||||||
set laststatus=2 " Always show status line
|
|
||||||
set mouse=a " Automatically enable mouse usage
|
|
||||||
set smarttab " Smart tab
|
|
||||||
set ttyfast " Faster redrawing
|
|
||||||
set viminfo+=! " Viminfo include !
|
|
||||||
set wildmenu " Show list instead of just completing
|
|
||||||
|
|
||||||
set ttymouse=xterm2
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
set shortmess=atOI " No help Uganda information, and overwrite read messages to avoid PRESS ENTER prompts
|
|
||||||
set ignorecase " Case insensitive search
|
|
||||||
set smartcase " ... but case sensitive when uc present
|
|
||||||
set scrolljump=5 " Line to scroll when cursor leaves screen
|
|
||||||
set scrolloff=3 " Minumum lines to keep above and below cursor
|
|
||||||
set nowrap " Do not wrap long lines
|
|
||||||
set shiftwidth=4 " Use indents of 4 spaces
|
|
||||||
set tabstop=4 " An indentation every four columns
|
|
||||||
set softtabstop=4 " Let backspace delete indent
|
|
||||||
set splitright " Puts new vsplit windows to the right of the current
|
|
||||||
set splitbelow " Puts new split windows to the bottom of the current
|
|
||||||
set autowrite " Automatically write a file when leaving a modified buffer
|
|
||||||
set mousehide " Hide the mouse cursor while typing
|
|
||||||
set hidden " Allow buffer switching without saving
|
|
||||||
set t_Co=256 " Use 256 colors
|
|
||||||
set ruler " Show the ruler
|
|
||||||
set showcmd " Show partial commands in status line and Selected characters/lines in visual mode
|
|
||||||
set showmode " Show current mode in command-line
|
|
||||||
set showmatch " Show matching brackets/parentthesis
|
|
||||||
set matchtime=5 " Show matching time
|
|
||||||
set report=0 " Always report changed lines
|
|
||||||
set linespace=0 " No extra spaces between rows
|
|
||||||
set pumheight=20 " Avoid the pop up menu occupying the whole screen
|
|
||||||
|
|
||||||
if !exists('g:vim_better_default_tabs_as_spaces') || g:vim_better_default_tabs_as_spaces
|
|
||||||
set expandtab " Tabs are spaces, not tabs
|
|
||||||
end
|
|
||||||
|
|
||||||
" http://stackoverflow.com/questions/6427650/vim-in-tmux-background-color-changes-when-paging/15095377#15095377
|
|
||||||
set t_ut=
|
|
||||||
|
|
||||||
set winminheight=0
|
|
||||||
set wildmode=list:longest,full
|
|
||||||
|
|
||||||
set listchars=tab:→\ ,eol:↵,trail:·,extends:↷,precedes:↶
|
|
||||||
|
|
||||||
set whichwrap+=<,>,h,l " Allow backspace and cursor keys to cross line boundaries
|
|
||||||
|
|
||||||
set termencoding=utf-8
|
|
||||||
set fileencoding=utf-8
|
|
||||||
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
|
|
||||||
|
|
||||||
set wildignore+=*swp,*.class,*.pyc,*.png,*.jpg,*.gif,*.zip
|
|
||||||
set wildignore+=*/tmp/*,*.o,*.obj,*.so " Unix
|
|
||||||
set wildignore+=*\\tmp\\*,*.exe " Windows
|
|
||||||
|
|
||||||
" Visual shifting (does not exit Visual mode)
|
|
||||||
vnoremap < <gv
|
|
||||||
vnoremap > >gv
|
|
||||||
" Treat long lines as break lines (useful when moving around in them)
|
|
||||||
nmap j gj
|
|
||||||
nmap k gk
|
|
||||||
vmap j gj
|
|
||||||
vmap k gk
|
|
||||||
|
|
||||||
" :W sudo saves the file
|
|
||||||
" (useful for handling the permission-denied error)
|
|
||||||
command! W w !sudo tee % > /dev/null
|
|
||||||
|
|
||||||
" Change cursor shape for iTerm2 on macOS {
|
|
||||||
" bar in Insert mode
|
|
||||||
" inside iTerm2
|
|
||||||
if $TERM_PROGRAM =~# 'iTerm'
|
|
||||||
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
|
|
||||||
let &t_SR = "\<Esc>]50;CursorShape=2\x7"
|
|
||||||
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
|
|
||||||
endif
|
|
||||||
|
|
||||||
" inside tmux
|
|
||||||
if exists('$TMUX') && $TERM != 'xterm-kitty'
|
|
||||||
let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
|
|
||||||
let &t_SR = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=2\x7\<Esc>\\"
|
|
||||||
let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
|
|
||||||
endif
|
|
||||||
|
|
||||||
" inside neovim
|
|
||||||
if has('nvim')
|
|
||||||
let $NVIM_TUI_ENABLE_CURSOR_SHAPE=2
|
|
||||||
endif
|
|
||||||
" }
|
|
||||||
|
|
||||||
if get(g:, 'vim_better_default_minimum', 0)
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get(g:, 'vim_better_default_backup_on', 0)
|
|
||||||
set backup
|
|
||||||
else
|
|
||||||
set nobackup
|
|
||||||
set noswapfile
|
|
||||||
set nowritebackup
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get(g:, 'vim_better_default_enable_folding', 1)
|
|
||||||
set foldenable
|
|
||||||
set foldmarker={,}
|
|
||||||
set foldlevel=0
|
|
||||||
set foldmethod=marker
|
|
||||||
" set foldcolumn=3
|
|
||||||
set foldlevelstart=99
|
|
||||||
endif
|
|
||||||
|
|
||||||
set background=dark " Assume dark background
|
|
||||||
set cursorline " Highlight current line
|
|
||||||
set fileformats=unix,dos,mac " Use Unix as the standard file type
|
|
||||||
set number " Line numbers on
|
|
||||||
set relativenumber " Relative numbers on
|
|
||||||
set fillchars=stl:\ ,stlnc:\ ,fold:\ ,vert:│
|
|
||||||
|
|
||||||
" Annoying temporary files
|
|
||||||
set directory=/tmp//,.
|
|
||||||
set backupdir=/tmp//,.
|
|
||||||
if v:version >= 703
|
|
||||||
set undodir=/tmp//,.
|
|
||||||
endif
|
|
||||||
|
|
||||||
highlight clear SignColumn " SignColumn should match background
|
|
||||||
" highlight clear LineNr " Current line number row will have same background color in relative mode
|
|
||||||
|
|
||||||
if has('unnamedplus')
|
|
||||||
set clipboard=unnamedplus,unnamed
|
|
||||||
else
|
|
||||||
set clipboard+=unnamed
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get(g:, 'vim_better_default_persistent_undo', 0)
|
|
||||||
if has('persistent_undo')
|
|
||||||
set undofile " Persistent undo
|
|
||||||
set undolevels=1000 " Maximum number of changes that can be undone
|
|
||||||
set undoreload=10000 " Maximum number lines to save for undo on a buffer reload
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
if has('gui_running')
|
|
||||||
set guioptions-=r " Hide the right scrollbar
|
|
||||||
set guioptions-=L " Hide the left scrollbar
|
|
||||||
set guioptions-=T
|
|
||||||
set guioptions-=e
|
|
||||||
set shortmess+=c
|
|
||||||
" No annoying sound on errors
|
|
||||||
set noerrorbells
|
|
||||||
set novisualbell
|
|
||||||
set visualbell t_vb=
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Key (re)Mappings {
|
|
||||||
|
|
||||||
if get(g:, 'vim_better_default_key_mapping', 1)
|
|
||||||
|
|
||||||
" Basic {
|
|
||||||
if get(g:, 'vim_better_default_basic_key_mapping', 1)
|
|
||||||
" Add <slient> for the rhs is Ex-cmd as some GUI app, e.g., gnvim,
|
|
||||||
" flashes when you use these mappings.
|
|
||||||
" Quit normal mode
|
|
||||||
nnoremap <silent> <Leader>q :q<CR>
|
|
||||||
nnoremap <silent> <Leader>Q :qa!<CR>
|
|
||||||
" Move half page faster
|
|
||||||
nnoremap <Leader>d <C-d>
|
|
||||||
nnoremap <Leader>u <C-u>
|
|
||||||
" Insert mode shortcut
|
|
||||||
inoremap <C-h> <BS>
|
|
||||||
inoremap <C-j> <Down>
|
|
||||||
inoremap <C-k> <Up>
|
|
||||||
inoremap <C-b> <Left>
|
|
||||||
inoremap <C-f> <Right>
|
|
||||||
" Bash like
|
|
||||||
inoremap <C-a> <Home>
|
|
||||||
inoremap <C-e> <End>
|
|
||||||
inoremap <C-d> <Delete>
|
|
||||||
" Command mode shortcut
|
|
||||||
cnoremap <C-h> <BS>
|
|
||||||
cnoremap <C-j> <Down>
|
|
||||||
cnoremap <C-k> <Up>
|
|
||||||
cnoremap <C-b> <Left>
|
|
||||||
cnoremap <C-f> <Right>
|
|
||||||
cnoremap <C-a> <Home>
|
|
||||||
cnoremap <C-e> <End>
|
|
||||||
cnoremap <C-d> <Delete>
|
|
||||||
" jj | escaping
|
|
||||||
inoremap jj <Esc>
|
|
||||||
cnoremap jj <C-c>
|
|
||||||
" Quit visual mode
|
|
||||||
vnoremap v <Esc>
|
|
||||||
" Move to the start of line
|
|
||||||
nnoremap H ^
|
|
||||||
" Move to the end of line
|
|
||||||
nnoremap L $
|
|
||||||
" Redo
|
|
||||||
nnoremap U <C-r>
|
|
||||||
" Quick command mode
|
|
||||||
nnoremap <CR> :
|
|
||||||
" In the quickfix window, <CR> is used to jump to the error under the
|
|
||||||
" cursor, so undefine the mapping there.
|
|
||||||
autocmd BufReadPost quickfix nnoremap <buffer> <CR> <CR>
|
|
||||||
" Yank to the end of line
|
|
||||||
nnoremap Y y$
|
|
||||||
" Auto indent pasted text
|
|
||||||
" nnoremap p p=`]<C-o>
|
|
||||||
" Open shell in vim
|
|
||||||
if has('nvim') || has('terminal')
|
|
||||||
map <silent> <Leader>' :terminal<CR>
|
|
||||||
else
|
|
||||||
map <silent> <Leader>' :shell<CR>
|
|
||||||
endif
|
|
||||||
" Search result highlight countermand
|
|
||||||
nnoremap <silent> <Leader>sc :nohlsearch<CR>
|
|
||||||
" Toggle pastemode
|
|
||||||
nnoremap <silent> <Leader>tp :setlocal paste!<CR>
|
|
||||||
endif
|
|
||||||
" }
|
|
||||||
|
|
||||||
" Buffer {
|
|
||||||
if get(g:, 'vim_better_default_buffer_key_mapping', 1)
|
|
||||||
nnoremap <silent> <Leader>bp :bprevious<CR>
|
|
||||||
nnoremap <silent> <Leader>bn :bnext<CR>
|
|
||||||
nnoremap <silent> <Leader>bf :bfirst<CR>
|
|
||||||
nnoremap <silent> <Leader>bl :blast<CR>
|
|
||||||
nnoremap <silent> <Leader>bd :bd<CR>
|
|
||||||
nnoremap <silent> <Leader>bk :bw<CR>
|
|
||||||
endif
|
|
||||||
" }
|
|
||||||
|
|
||||||
" File {
|
|
||||||
if get(g:, 'vim_better_default_file_key_mapping', 1)
|
|
||||||
" File save
|
|
||||||
nnoremap <silent> <Leader>fs :update<CR>
|
|
||||||
endif
|
|
||||||
" }
|
|
||||||
|
|
||||||
" Fold {
|
|
||||||
if get(g:, 'vim_better_default_fold_key_mapping', 1)
|
|
||||||
nnoremap <silent> <Leader>f0 :set foldlevel=0<CR>
|
|
||||||
nnoremap <silent> <Leader>f1 :set foldlevel=1<CR>
|
|
||||||
nnoremap <silent> <Leader>f2 :set foldlevel=2<CR>
|
|
||||||
nnoremap <silent> <Leader>f3 :set foldlevel=3<CR>
|
|
||||||
nnoremap <silent> <Leader>f4 :set foldlevel=4<CR>
|
|
||||||
nnoremap <silent> <Leader>f5 :set foldlevel=5<CR>
|
|
||||||
nnoremap <silent> <Leader>f6 :set foldlevel=6<CR>
|
|
||||||
nnoremap <silent> <Leader>f7 :set foldlevel=7<CR>
|
|
||||||
nnoremap <silent> <Leader>f8 :set foldlevel=8<CR>
|
|
||||||
nnoremap <silent> <Leader>f9 :set foldlevel=9<CR>
|
|
||||||
endif
|
|
||||||
" }
|
|
||||||
|
|
||||||
" Window {
|
|
||||||
if get(g:, 'vim_better_default_window_key_mapping', 1)
|
|
||||||
nnoremap <Leader>ww <C-W>w
|
|
||||||
nnoremap <Leader>wr <C-W>r
|
|
||||||
nnoremap <Leader>wd <C-W>c
|
|
||||||
nnoremap <Leader>wq <C-W>q
|
|
||||||
nnoremap <Leader>wj <C-W>j
|
|
||||||
nnoremap <Leader>wk <C-W>k
|
|
||||||
nnoremap <Leader>wh <C-W>h
|
|
||||||
nnoremap <Leader>wl <C-W>l
|
|
||||||
if has('nvim') || has('terminal')
|
|
||||||
tnoremap <Leader>wj <C-W>j
|
|
||||||
tnoremap <Leader>wk <C-W>k
|
|
||||||
tnoremap <Leader>wh <C-W>h
|
|
||||||
tnoremap <Leader>wl <C-W>l
|
|
||||||
endif
|
|
||||||
nnoremap <Leader>wH <C-W>5<
|
|
||||||
nnoremap <Leader>wL <C-W>5>
|
|
||||||
nnoremap <Leader>wJ :resize +5<CR>
|
|
||||||
nnoremap <Leader>wK :resize -5<CR>
|
|
||||||
nnoremap <Leader>w= <C-W>=
|
|
||||||
nnoremap <Leader>ws <C-W>s
|
|
||||||
nnoremap <Leader>w- <C-W>s
|
|
||||||
nnoremap <Leader>wv <C-W>v
|
|
||||||
nnoremap <Leader>w\| <C-W>v
|
|
||||||
nnoremap <Leader>w2 <C-W>v
|
|
||||||
endif
|
|
||||||
" }
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }
|
|
||||||
|
|
||||||
let &cpo = s:save_cpo
|
|
||||||
unlet s:save_cpo
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
|
|
||||||
---------------------------
|
|
||||||
-- bk-tree datastructure
|
|
||||||
--
|
|
||||||
-- http://en.wikipedia.org/wiki/BK-tree
|
|
||||||
-- @module bk-tree
|
|
||||||
-- @author Robin Hübner
|
|
||||||
-- robinhubner@gmail.com
|
|
||||||
-- @release version 1.0.2
|
|
||||||
-- @license MIT
|
|
||||||
|
|
||||||
local bk_tree = {}
|
|
||||||
|
|
||||||
|
|
||||||
local function lazy_copy(t1)
|
|
||||||
|
|
||||||
local cp = {}
|
|
||||||
|
|
||||||
for k, v in pairs(t1) do
|
|
||||||
cp[k] = v
|
|
||||||
end
|
|
||||||
|
|
||||||
return cp
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function min(a, b, c)
|
|
||||||
|
|
||||||
local min_val = a
|
|
||||||
|
|
||||||
if b < min_val then min_val = b end
|
|
||||||
if c < min_val then min_val = c end
|
|
||||||
|
|
||||||
return min_val
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
----------------------------------
|
|
||||||
--- Levenshtein distance function.
|
|
||||||
-- @tparam string s1
|
|
||||||
-- @tparam string s2
|
|
||||||
-- @treturn number the levenshtein distance
|
|
||||||
-- @within Metrics
|
|
||||||
function bk_tree.levenshtein_dist(s1, s2)
|
|
||||||
|
|
||||||
if s1 == s2 then return 0 end
|
|
||||||
if s1:len() == 0 then return s2:len() end
|
|
||||||
if s2:len() == 0 then return s1:len() end
|
|
||||||
if s1:len() < s2:len() then s1, s2 = s2, s1 end
|
|
||||||
|
|
||||||
t = {}
|
|
||||||
for i=1, #s1+1 do
|
|
||||||
t[i] = {i-1}
|
|
||||||
end
|
|
||||||
|
|
||||||
for i=1, #s2+1 do
|
|
||||||
t[1][i] = i-1
|
|
||||||
end
|
|
||||||
|
|
||||||
local cost
|
|
||||||
for i=2, #s1+1 do
|
|
||||||
|
|
||||||
for j=2, #s2+1 do
|
|
||||||
cost = (s1:sub(i-1,i-1) == s2:sub(j-1,j-1) and 0) or 1
|
|
||||||
t[i][j] = min(
|
|
||||||
t[i-1][j] + 1,
|
|
||||||
t[i][j-1] + 1,
|
|
||||||
t[i-1][j-1] + cost)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return t[#s1+1][#s2+1]
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function bk_tree.hook(param)
|
|
||||||
|
|
||||||
local name, callee = debug.getlocal(2, 1)
|
|
||||||
local f = debug.getinfo(2, "f").func
|
|
||||||
local p = debug.getinfo(3, "f").func
|
|
||||||
--[[ previous function in the callstack, if called from the same place,
|
|
||||||
don't add to the insert/remove counters. ]]--
|
|
||||||
|
|
||||||
if f == bk_tree.insert and p ~= bk_tree.insert then
|
|
||||||
callee.stats.nodes = callee.stats.nodes + 1
|
|
||||||
elseif f == bk_tree.remove and p ~= bk_tree.remove then
|
|
||||||
callee.stats.nodes = callee.stats.nodes - 1
|
|
||||||
elseif f == bk_tree.query and p == bk_tree.query then
|
|
||||||
callee.stats.queries = callee.stats.queries + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Hooks debugging into tree execution.
|
|
||||||
-- Keeps track of number of nodes created, queries made,
|
|
||||||
-- note that this must be run directly after tree is created
|
|
||||||
-- in order to get correct information.
|
|
||||||
-- @within Debug
|
|
||||||
--- @usage
|
|
||||||
-- local bktree = require "bk-tree"
|
|
||||||
-- local tree = bktree:new("word")
|
|
||||||
-- tree:debug()
|
|
||||||
-- tree:insert("perceive")
|
|
||||||
-- tree:insert("beautiful")
|
|
||||||
-- tree:insert("definitely")
|
|
||||||
-- local result = tree:query("definately", 3)
|
|
||||||
-- tree:print_stats()
|
|
||||||
--
|
|
||||||
-- -- output
|
|
||||||
-- Nodes: 4
|
|
||||||
-- Queries: 3
|
|
||||||
-- Nodes Queried: 75%
|
|
||||||
function bk_tree:debug()
|
|
||||||
|
|
||||||
local nc = 0
|
|
||||||
if self.root then nc = 1 end
|
|
||||||
self.stats = { nodes = nc, queries = 0 }
|
|
||||||
debug.sethook(self.hook, "c")
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Print execution stats.
|
|
||||||
-- Prints nodes queried and total nodes, as well as a fraction of
|
|
||||||
-- nodes visited to satisfy the query, resets the counter of nodes queried when called.
|
|
||||||
-- @within Debug
|
|
||||||
-- @see debug
|
|
||||||
function bk_tree:print_stats()
|
|
||||||
|
|
||||||
print("\nNodes: " .. self.stats.nodes)
|
|
||||||
print("Queries: " .. self.stats.queries)
|
|
||||||
print("Nodes Queried: " .. self.stats.queries/self.stats.nodes*100 .. "%\n")
|
|
||||||
self.stats.queries = 0
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Fetch execution stats.
|
|
||||||
-- Returns a copy of the execution stats that @{print_stats} would print, requires debug to have been enabled
|
|
||||||
-- to not just return defaults. Useful if you want to profile things.
|
|
||||||
-- @within Debug
|
|
||||||
-- @return {key = value,...}
|
|
||||||
function bk_tree:get_stats()
|
|
||||||
|
|
||||||
return lazy_copy(self.stats)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
--- Creates a new bk-tree.
|
|
||||||
-- @constructor
|
|
||||||
-- @string[opt] root_word the root of the new tree
|
|
||||||
-- @tparam[opt=levenshtein_dist] function dist_func the distance function used
|
|
||||||
-- @see levenshtein_dist
|
|
||||||
-- @return the new bk-tree instance
|
|
||||||
--- @usage
|
|
||||||
-- local bktree = require "bk-tree"
|
|
||||||
-- local tree = bktree:new("word")
|
|
||||||
function bk_tree:new(root_word, dist_func)
|
|
||||||
|
|
||||||
local n_obj = {}
|
|
||||||
if root_word then n_obj.root = { str = root_word, children = {} } end
|
|
||||||
n_obj.dist_func = dist_func or self.levenshtein_dist
|
|
||||||
|
|
||||||
setmetatable(n_obj, self)
|
|
||||||
self.__index = self
|
|
||||||
|
|
||||||
return n_obj
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------
|
|
||||||
--- Inserts word into the tree.
|
|
||||||
-- @string word
|
|
||||||
-- @treturn bool true if inserted, false if word already exists in tree
|
|
||||||
--- @usage
|
|
||||||
-- local bktree = require "bk-tree"
|
|
||||||
-- local tree = bktree:new("root")
|
|
||||||
-- local success = tree:insert("other_word")
|
|
||||||
function bk_tree:insert(word, node)
|
|
||||||
|
|
||||||
node = node or self.root
|
|
||||||
|
|
||||||
if not node then
|
|
||||||
self.root = { str = word, children = {} }
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local dist = self.dist_func(word, node.str)
|
|
||||||
if dist == 0 then return false end
|
|
||||||
|
|
||||||
local some_node = node.children[dist]
|
|
||||||
|
|
||||||
if not some_node then
|
|
||||||
node.children[dist] = { str = word, children = {} }
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
return self:insert(word, some_node)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------
|
|
||||||
--- Query the tree for matches.
|
|
||||||
-- @string word
|
|
||||||
-- @tparam number n max edit distance to use when querying
|
|
||||||
-- @treturn {{str=string,distance=number},....} table of tables with matching words, empty table if no matches
|
|
||||||
--- @usage
|
|
||||||
-- local bktree = require "bk-tree"
|
|
||||||
-- local tree = bktree:new("word")
|
|
||||||
-- tree:insert("hello")
|
|
||||||
-- tree:insert("goodbye")
|
|
||||||
-- tree:insert("woop")
|
|
||||||
-- local result = tree:query("woop", 1)
|
|
||||||
function bk_tree:query(word, n, node, matches)
|
|
||||||
|
|
||||||
node = node or self.root
|
|
||||||
matches = matches or {}
|
|
||||||
|
|
||||||
if not node then return matches end
|
|
||||||
|
|
||||||
local dist = self.dist_func(word, node.str)
|
|
||||||
if dist <= n then matches[#matches+1] = {str = node.str, distance = dist} end
|
|
||||||
|
|
||||||
for k, child in pairs(node.children) do
|
|
||||||
if child ~= nil then
|
|
||||||
if k >= dist-n and k <= dist+n then
|
|
||||||
self:query(word, n, child, matches)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return matches
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
--- Queries the the tree for a match, sorts the results.
|
|
||||||
-- Calls @{query} and returns the results sorted.
|
|
||||||
-- @string word
|
|
||||||
-- @tparam number n max edit distance to use when querying
|
|
||||||
-- @treturn {{str=string,distance=number},....} table of tables with matching words sorted by distance, empty table if no matches
|
|
||||||
--- @usage
|
|
||||||
-- local bktree = require "bk-tree"
|
|
||||||
-- local tree = bktree:new("word")
|
|
||||||
-- tree:insert("woop")
|
|
||||||
-- tree:insert("worp")
|
|
||||||
-- tree:insert("warp")
|
|
||||||
-- local result = tree:query_sorted("woop", 3)
|
|
||||||
function bk_tree:query_sorted(word, n)
|
|
||||||
|
|
||||||
local result = self:query(word, n)
|
|
||||||
|
|
||||||
table.sort(result, function(a,b) return a.distance < b.distance end)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local tree = bk_tree:new("word")
|
|
||||||
tree:insert("hello")
|
|
||||||
tree:insert("welp")
|
|
||||||
tree:insert("function")
|
|
||||||
tree:insert("this long line what")
|
|
||||||
tree:insert("what this long line what")
|
|
||||||
print(vim.inspect(tree))
|
|
||||||
print(vim.inspect(tree:query_sorted("what", 3)))
|
|
||||||
|
|
||||||
|
|
||||||
return bk_tree
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
local a = vim.api
|
|
||||||
|
|
||||||
local ns = a.nvim_create_namespace("treesitter/highlighter")
|
|
||||||
print(ns)
|
|
||||||
local bufnr = 0
|
|
||||||
|
|
||||||
-- P(a.nvim_buf_get_extmarks(bufnr, ns, 0, -1, { details = true }))
|
|
||||||
|
|
||||||
local parser = vim.treesitter.get_parser(bufnr, "lua")
|
|
||||||
local query = vim.treesitter.get_query("lua", "highlights")
|
|
||||||
P(query)
|
|
||||||
|
|
||||||
local root = parser:parse()[1]:root()
|
|
||||||
print("root", root)
|
|
||||||
|
|
||||||
local highlighter = vim.treesitter.highlighter.new(parser)
|
|
||||||
local highlighter_query = highlighter:get_query("lua")
|
|
||||||
|
|
||||||
for id, node, metadata in query:iter_captures(root, bufnr, 0, -1) do
|
|
||||||
local row1, col1, row2, col2 = node:range()
|
|
||||||
print(highlighter_query.hl_cache[id])
|
|
||||||
-- print(id, node, metadata, vim.treesitter.get_node_text(node, bufnr))
|
|
||||||
-- print(">>>>", row1, col1, row2, col2)
|
|
||||||
end
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
vim.cmd [[packadd! plenary.nvim]]
|
|
||||||
vim.cmd [[packadd! telescope.nvim]]
|
|
||||||
|
|
||||||
local finders = require "telescope.finders"
|
|
||||||
local previewers = require "telescope.previewers"
|
|
||||||
local pickers = require "telescope.pickers"
|
|
||||||
local sorters = require "telescope.sorters"
|
|
||||||
local utils = require "telescope.utils"
|
|
||||||
|
|
||||||
local rgargs = { "--color=never", "--no-heading", "--with-filename", "--line-number", "--column", "--smart-case" }
|
|
||||||
-- grep typed string in current directory (live, not fuzzy!)
|
|
||||||
finders.rg_live = function(opts)
|
|
||||||
local live_grepper = finders.new {
|
|
||||||
fn_command = function(_, prompt)
|
|
||||||
if not prompt or prompt == "" then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
command = "rg",
|
|
||||||
args = vim.tbl_flatten { rgargs, prompt },
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt = "Live Grep",
|
|
||||||
finder = live_grepper,
|
|
||||||
previewer = previewers.vimgrep,
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- fuzzy grep string in current directory (slow!)
|
|
||||||
finders.rg = function(opts)
|
|
||||||
opts = opts or {}
|
|
||||||
|
|
||||||
local search = opts.search or ""
|
|
||||||
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt = "Find Word",
|
|
||||||
finder = finders.new_oneshot_job(vim.tbl_flatten { "rg", rgargs, search }),
|
|
||||||
previewer = previewers.vimgrep,
|
|
||||||
sorter = sorters.get_norcalli_sorter(),
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- fuzzy find files in current directory (may be slow in root dir)
|
|
||||||
finders.fd = function(opts)
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt = "Find Files",
|
|
||||||
finder = finders.new_oneshot_job { "fd" },
|
|
||||||
previewer = previewers.bat,
|
|
||||||
sorter = sorters.get_fuzzy_file(),
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- fuzzy find in references to symbol under cursor
|
|
||||||
finders.lsp_references = function(opts)
|
|
||||||
local params = vim.lsp.util.make_position_params()
|
|
||||||
params.context = { includeDeclaration = false }
|
|
||||||
|
|
||||||
local results_lsp, err = vim.lsp.buf_request_sync(0, "textDocument/references", params)
|
|
||||||
if err then
|
|
||||||
vim.api.nvim_err_writeln("Error when finding references: " .. err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local locations = {}
|
|
||||||
for _, server_results in pairs(results_lsp) do
|
|
||||||
vim.list_extend(locations, vim.lsp.util.locations_to_items(server_results.result) or {})
|
|
||||||
end
|
|
||||||
|
|
||||||
local results = utils.quickfix_items_to_entries(locations)
|
|
||||||
|
|
||||||
if vim.tbl_isempty(results) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt = "LSP References",
|
|
||||||
finder = finders.new_table(results),
|
|
||||||
previewer = previewers.qflist,
|
|
||||||
sorter = sorters.get_norcalli_sorter(),
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- fuzzy find in document symbols
|
|
||||||
finders.lsp_document_symbols = function(opts)
|
|
||||||
local params = vim.lsp.util.make_position_params()
|
|
||||||
local results_lsp, err = vim.lsp.buf_request_sync(0, "textDocument/documentSymbol", params)
|
|
||||||
if err then
|
|
||||||
vim.api.nvim_err_writeln("Error when finding document symbols: " .. err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local locations = {}
|
|
||||||
for _, server_results in pairs(results_lsp) do
|
|
||||||
vim.list_extend(locations, vim.lsp.util.symbols_to_items(server_results.result, 0) or {})
|
|
||||||
end
|
|
||||||
|
|
||||||
local results = utils.quickfix_items_to_entries(locations)
|
|
||||||
|
|
||||||
if vim.tbl_isempty(results) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt = "LSP Document Symbols",
|
|
||||||
finder = finders.new_table(results),
|
|
||||||
previewer = previewers.qflist,
|
|
||||||
sorter = sorters.get_norcalli_sorter(),
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- fuzzy find in all workspace symbols (may need longer timeout!)
|
|
||||||
finders.lsp_workspace_symbols = function(opts)
|
|
||||||
local params = { query = "" }
|
|
||||||
local results_lsp, err = vim.lsp.buf_request_sync(0, "workspace/symbol", params, 1000)
|
|
||||||
if err then
|
|
||||||
vim.api.nvim_err_writeln("Error when finding symbols: " .. err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local locations = {}
|
|
||||||
for _, server_results in pairs(results_lsp) do
|
|
||||||
vim.list_extend(locations, vim.lsp.util.symbols_to_items(server_results.result, 0) or {})
|
|
||||||
end
|
|
||||||
|
|
||||||
local results = utils.quickfix_items_to_entries(locations)
|
|
||||||
|
|
||||||
if vim.tbl_isempty(results) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt = "LSP Workspace Symbols",
|
|
||||||
finder = finders.new_table(results),
|
|
||||||
previewer = previewers.qflist,
|
|
||||||
sorter = sorters.get_norcalli_sorter(),
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
return finders
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
set rtp+=.
|
|
||||||
set rtp+=../plenary.nvim/
|
|
||||||
|
|
||||||
source plugin/telescope.vim
|
|
||||||
|
|
||||||
inoremap <tab> <c-n>
|
|
||||||
|
|
||||||
let case = 1
|
|
||||||
|
|
||||||
if case == 1
|
|
||||||
set completeopt=menu
|
|
||||||
endif
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
local y = function() end
|
|
||||||
|
|
||||||
local x = function()
|
|
||||||
asdf
|
|
||||||
print(y)
|
|
||||||
end
|
|
||||||
|
|
||||||
x()
|
|
||||||
|
|
||||||
y()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
set rtp+=.
|
|
||||||
set rtp+=../plenary.nvim/
|
|
||||||
|
|
||||||
|
|
||||||
set statusline=""
|
|
||||||
set statusline+=%<%f:%l:%v " filename:col:line/total lines
|
|
||||||
set statusline+=\ "
|
|
||||||
set statusline+=%h%m%r " help/modified/readonly
|
|
||||||
set statusline+=\ "
|
|
||||||
set statusline+=[%{&ft}] " filetype
|
|
||||||
set statusline+=%= " alignment group
|
|
||||||
set statusline+=\ "
|
|
||||||
|
|
||||||
" nnoremap <silent> <c-p> :lua require('telescope.builtin').git_files()<CR>
|
|
||||||
nnoremap <silent> <c-p> :lua require("telescope.builtin").find_files{ find_command = { "rg", "--smart-case", "--files", "--hidden", "--follow", "-g", "!.git/*" } }<CR>
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
|
|
||||||
local finder = Finder:new {
|
|
||||||
'rg %s -l',
|
|
||||||
pipeable = true,
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
local filter = Filter:new {
|
|
||||||
"fzf --filter '%s'"
|
|
||||||
}
|
|
||||||
|
|
||||||
local lua_filter = Filter:new {
|
|
||||||
function(input, line)
|
|
||||||
if string.match(line, input) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
local picker_read = Picker:new {
|
|
||||||
filter = filter,
|
|
||||||
|
|
||||||
previewer = function(window, buffer, line)
|
|
||||||
local file = io.open(line, "r")
|
|
||||||
|
|
||||||
local filename = vim.split(line, ':')[1]
|
|
||||||
if vim.fn.bufexists(filename) then
|
|
||||||
vim.api.nvim_win_set_buf(window, vim.fn.bufnr(filename))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local lines = {}
|
|
||||||
for _ = 1, 100 do
|
|
||||||
table.insert(lines, file:read("l"))
|
|
||||||
|
|
||||||
-- TODO: Check if we're out of lines
|
|
||||||
end
|
|
||||||
|
|
||||||
-- optionally set the filetype or whatever...
|
|
||||||
vim.api.nvim_buf_set_lines(buffer, 0, -1, false, lines)
|
|
||||||
end,
|
|
||||||
|
|
||||||
mappings = {
|
|
||||||
["<CR>"] = function(line)
|
|
||||||
vim.cmd(string.format('e ', vim.split(line, ':')))
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local picker = Picker:new {
|
|
||||||
filter = filter,
|
|
||||||
|
|
||||||
-- idk
|
|
||||||
previewer = function(window, line)
|
|
||||||
vim.api.nvim_win_set_current_window(window)
|
|
||||||
|
|
||||||
-- if is_file_loaded(line) then
|
|
||||||
-- lien_number = vim.api.nvim_...
|
|
||||||
|
|
||||||
vim.fn.termopen(string.format(
|
|
||||||
'bat --color=always --style=grid %s',
|
|
||||||
vim.split(line, ':')[1]
|
|
||||||
))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
local test_line = "/home/tj/hello/world.lua"
|
|
||||||
|
|
||||||
local function fast_split(line, split)
|
|
||||||
-- local split_line = vim.split(line, split)
|
|
||||||
local areas = {}
|
|
||||||
|
|
||||||
local processed = 1
|
|
||||||
local line_length = #line + 1
|
|
||||||
|
|
||||||
local part, start
|
|
||||||
repeat
|
|
||||||
start = string.find(line, split, processed, true) or line_length
|
|
||||||
part = string.sub(line, processed, start - 1)
|
|
||||||
|
|
||||||
if start - processed > 0 then
|
|
||||||
table.insert(areas, {
|
|
||||||
word = part,
|
|
||||||
offset = processed
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
processed = start + 1
|
|
||||||
until start == line_length
|
|
||||||
|
|
||||||
return areas
|
|
||||||
end
|
|
||||||
|
|
||||||
print(vim.inspect(fast_split(test_line, '/')))
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
local telescope = require('telescope')
|
|
||||||
|
|
||||||
-- Goals:
|
|
||||||
-- 1. You pick a directory
|
|
||||||
-- 2. We `git ls-files` in that directory ONCE and ONLY ONCE to get the results.
|
|
||||||
-- 3. You can fuzzy find those results w/ fzf
|
|
||||||
-- 4. Select one and go to file.
|
|
||||||
|
|
||||||
|
|
||||||
--[[
|
|
||||||
ls_files_job.start()
|
|
||||||
fzf_job.stdin = ls_files_job.stdout
|
|
||||||
|
|
||||||
self.stdin = vim.loop.new_pipe(false)
|
|
||||||
-> self.stdin = finder.stdout
|
|
||||||
|
|
||||||
|
|
||||||
-- Finder:
|
|
||||||
intermediary_pipe = self.stdout
|
|
||||||
|
|
||||||
-- repeat send this pipe when we want to get new filtering
|
|
||||||
self.stdin = intermediary_pipe
|
|
||||||
|
|
||||||
|
|
||||||
-- Filter + Sort
|
|
||||||
ok, we could do scoring + cutoff and have that always be the case.
|
|
||||||
|
|
||||||
OR
|
|
||||||
|
|
||||||
filter takes a function, signature (prompt: str, line: str): number
|
|
||||||
|
|
||||||
=> echo $line | fzf --filter "prompt"
|
|
||||||
return stdout != ""
|
|
||||||
|
|
||||||
=> lua_fuzzy_finder(prompt, line) return true if good enough
|
|
||||||
|
|
||||||
TODO: Rename everything to be more clear like the name below.
|
|
||||||
IFilterSorterAbstractFactoryGeneratorv1ProtoBeta
|
|
||||||
|
|
||||||
--]]
|
|
||||||
|
|
||||||
|
|
||||||
local file_finder = telescope.finders.new {
|
|
||||||
static = true,
|
|
||||||
|
|
||||||
-- self, prompt
|
|
||||||
fn_command = function()
|
|
||||||
return 'git ls-files'
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local file_sorter = telescope.sorters.get_ngram_sorter()
|
|
||||||
|
|
||||||
-- local string_distance = require('telescope.algos.string_distance')
|
|
||||||
-- new {
|
|
||||||
-- scoring_function = function(self, prompt, line)
|
|
||||||
-- if prompt == '' then return 0 end
|
|
||||||
-- if not line then return -1 end
|
|
||||||
|
|
||||||
-- return tonumber(vim.fn.systemlist(string.format(
|
|
||||||
-- "echo '%s' | ~/tmp/fuzzy_test/target/debug/fuzzy_test '%s'",
|
|
||||||
-- line,
|
|
||||||
-- prompt
|
|
||||||
-- ))[1])
|
|
||||||
-- end
|
|
||||||
-- }
|
|
||||||
|
|
||||||
|
|
||||||
local file_previewer = telescope.previewers.vim_buffer_or_bat
|
|
||||||
|
|
||||||
local file_picker = telescope.pickers.new {
|
|
||||||
previewer = file_previewer
|
|
||||||
}
|
|
||||||
|
|
||||||
file_picker:find {
|
|
||||||
prompt = 'Find File',
|
|
||||||
finder = file_finder,
|
|
||||||
sorter = file_sorter,
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
line = "hello"
|
|
||||||
prompt = "h"
|
|
||||||
print(vim.inspect(vim.fn.systemlist(string.format(
|
|
||||||
"echo '%s' | ~/tmp/fuzzy_test/target/debug/fuzzy_test '%s'",
|
|
||||||
line,
|
|
||||||
prompt
|
|
||||||
))))
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
local start = vim.loop.hrtime()
|
|
||||||
|
|
||||||
local counts = 1e6
|
|
||||||
for _ = 1, counts do
|
|
||||||
local _ = vim.loop.hrtime()
|
|
||||||
end
|
|
||||||
|
|
||||||
print(counts, ":", (vim.loop.hrtime() - start) / 1e9)
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
RELOAD('telescope')
|
|
||||||
require('telescope.builtin').find_files(require('telescope.themes').get_ivy { previewer = false })
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
local t = setmetatable({}, {
|
|
||||||
__newindex = function(t, k, v)
|
|
||||||
print(t, k, v)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
-- table.insert(t, "hello")
|
|
||||||
t[1] = "hello"
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
|
|
||||||
local function ngrams(counts, doc)
|
|
||||||
local DEPTH = 5
|
|
||||||
local docLen = #doc
|
|
||||||
local min, concat = math.min, table.concat
|
|
||||||
for i = 1, docLen - 1 do
|
|
||||||
for j = i, min(i + DEPTH - 1, docLen) do
|
|
||||||
if not doc[j] then break end
|
|
||||||
local k = concat(doc, " ", i, j)
|
|
||||||
counts[k] = (counts[k] or 0) + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local bz = io.popen('bzcat /home/tj/Downloads/pages.xml.bz2')
|
|
||||||
local title, content = "", ""
|
|
||||||
local inText = false
|
|
||||||
|
|
||||||
local numDocs = 0
|
|
||||||
local globalCounts = {}
|
|
||||||
|
|
||||||
local function set(t)
|
|
||||||
local s = {}
|
|
||||||
for _, v in pairs(t) do s[v] = true end
|
|
||||||
return s
|
|
||||||
end
|
|
||||||
|
|
||||||
local bad = set({
|
|
||||||
'after', 'also', 'article', 'date', 'defaultsort', 'external', 'first', 'from',
|
|
||||||
'have', 'html', 'http', 'image', 'infobox', 'links', 'name', 'other', 'preserve',
|
|
||||||
'references', 'reflist', 'space', 'that', 'this', 'title', 'which', 'with',
|
|
||||||
'quot', 'ref', 'name', 'http', 'amp', 'ndash', 'www', 'cite', 'nbsp',
|
|
||||||
'style', 'text', 'align', 'center', 'background'
|
|
||||||
})
|
|
||||||
|
|
||||||
local function isnumber(w)
|
|
||||||
s, e = w:find("[0-9]+")
|
|
||||||
return s
|
|
||||||
end
|
|
||||||
|
|
||||||
for line in bz:lines() do
|
|
||||||
local _, _, mTitle = line:find("<title>(.*)</title>")
|
|
||||||
local _, _, bText = line:find("<text[^>]*>([^<]*)")
|
|
||||||
local eText, _ = line:find("</text>")
|
|
||||||
|
|
||||||
if mTitle then
|
|
||||||
title = mTitle
|
|
||||||
elseif bText then
|
|
||||||
content = bText
|
|
||||||
inText = true
|
|
||||||
elseif inText then
|
|
||||||
content = content .. line
|
|
||||||
end
|
|
||||||
|
|
||||||
if eText then
|
|
||||||
words = {}
|
|
||||||
for v in content:gmatch("%w+") do
|
|
||||||
v = v:lower()
|
|
||||||
if #v >= 3 and #v < 12 and not bad[v] and not isnumber(v) then
|
|
||||||
table.insert(words, v)
|
|
||||||
else
|
|
||||||
table.insert(words, nil)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ngrams(globalCounts, words)
|
|
||||||
inText = false
|
|
||||||
|
|
||||||
numDocs = numDocs + 1
|
|
||||||
if numDocs % 10 == 0 then
|
|
||||||
io.write(string.format("Working... %d documents processed.\r", numDocs))
|
|
||||||
io.flush()
|
|
||||||
end
|
|
||||||
|
|
||||||
if numDocs == 500 then
|
|
||||||
local f = io.open('/tmp/freqs.lua.txt', 'w')
|
|
||||||
for k, v in pairs(globalCounts) do
|
|
||||||
f:write(k, '\t', v, '\n')
|
|
||||||
end
|
|
||||||
f:close()
|
|
||||||
|
|
||||||
globalCounts = {}
|
|
||||||
os.exit(0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
local ffi = require("ffi")
|
|
||||||
-- ffi.load("/home/tj/build/neovim/build/include/eval/funcs.h.generated.h")
|
|
||||||
|
|
||||||
ffi.cdef [[
|
|
||||||
typedef unsigned char char_u;
|
|
||||||
char_u *shorten_dir(char_u *str);
|
|
||||||
]]
|
|
||||||
|
|
||||||
local text = "scratch/file.lua"
|
|
||||||
local c_str = ffi.new("char[?]", #text)
|
|
||||||
ffi.copy(c_str, text)
|
|
||||||
|
|
||||||
print(vim.inspect(ffi.string(ffi.C.shorten_dir(c_str))))
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
-- Hot reload stuff
|
|
||||||
package.loaded['telescope'] = nil
|
|
||||||
package.loaded['telescope.init'] = nil
|
|
||||||
package.loaded['telescope.picker'] = nil
|
|
||||||
package.loaded['telescope.finder'] = nil
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
local log = require('telescope.log')
|
|
||||||
|
|
||||||
local PromptCache = {}
|
|
||||||
|
|
||||||
function getFirstByteDiffIdx(a, b)
|
|
||||||
local idx = 1
|
|
||||||
local max_idx = #a
|
|
||||||
while a:byte(idx) == b:byte(idx) and idx <= max_idx do
|
|
||||||
idx = idx + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
return idx
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:new(opts)
|
|
||||||
self.__index = self
|
|
||||||
local obj = setmetatable({
|
|
||||||
current_line = nil,
|
|
||||||
cached_results = {},
|
|
||||||
cache_round = 0
|
|
||||||
}, self)
|
|
||||||
|
|
||||||
return obj
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:set_cache(prompt, item_to_cache)
|
|
||||||
self.results = item_to_cache
|
|
||||||
self:_complete(prompt)
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:_complete(prompt)
|
|
||||||
if #prompt == 0 then
|
|
||||||
self:_reset()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local cached_lines = self.results
|
|
||||||
|
|
||||||
local idx = 1
|
|
||||||
if self.current_line ~= nil then
|
|
||||||
idx = getFirstByteDiffIdx(self.current_line, prompt)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ABC
|
|
||||||
-- ABDC
|
|
||||||
-- IDX = 3
|
|
||||||
-- cr = 3
|
|
||||||
-- diff = 1
|
|
||||||
local diff = #self.cached_results - (idx - 1)
|
|
||||||
while diff > 0 do
|
|
||||||
table.remove(self.cached_results)
|
|
||||||
diff = diff - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ABC
|
|
||||||
-- ADBC
|
|
||||||
-- diff = 2
|
|
||||||
for i = idx, #prompt do
|
|
||||||
if #self.cached_results < (#prompt - 1) then
|
|
||||||
local last_cache = self:get_last_cache()
|
|
||||||
table.insert(self.cached_results, last_cache)
|
|
||||||
else
|
|
||||||
table.insert(self.cached_results, cached_lines)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.current_line = prompt
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:start_round(cache_round)
|
|
||||||
self.cache_round = cache_round
|
|
||||||
log.trace("start_round (had this", self.results and #self.results or nil, "for past results)", self.cache_round)
|
|
||||||
self.results = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:add_to_round(cache_round, line, score)
|
|
||||||
if cache_round < self.cache_round or score == -1 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(self.results, line)
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:get_last_cache()
|
|
||||||
local last_cache = nil
|
|
||||||
|
|
||||||
for idx = 1, #self.cached_results do
|
|
||||||
local cache = self.cached_results[idx]
|
|
||||||
if cache then
|
|
||||||
last_cache = cache
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return last_cache
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:complete_round(cache_round, prompt)
|
|
||||||
if cache_round ~= self.cache_round then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self:_complete(prompt)
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:get_cache(prompt)
|
|
||||||
if self.current_line == nil or #prompt == 0 then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local idx = getFirstByteDiffIdx(self.current_line, prompt)
|
|
||||||
|
|
||||||
if idx == 1 then
|
|
||||||
self:_reset()
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- if we are off, then we simply need to prune the cache or let complete do
|
|
||||||
-- that
|
|
||||||
local results = nil
|
|
||||||
repeat
|
|
||||||
results = self.cached_results[idx - 1]
|
|
||||||
idx = idx - 1
|
|
||||||
until idx <= 1 or results
|
|
||||||
|
|
||||||
return results
|
|
||||||
end
|
|
||||||
|
|
||||||
function PromptCache:_reset()
|
|
||||||
self.current_line = nil
|
|
||||||
self.cached_results = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
PromptCache = PromptCache
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
local function get_rg_results(bufnr, search_string)
|
|
||||||
local start_time = vim.fn.reltime()
|
|
||||||
|
|
||||||
vim.fn.jobstart(string.format('rg %s', search_string), {
|
|
||||||
cwd = '/home/tj/build/neovim',
|
|
||||||
|
|
||||||
on_stdout = function(job_id, data, event)
|
|
||||||
vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, data)
|
|
||||||
end,
|
|
||||||
|
|
||||||
on_exit = function()
|
|
||||||
print("Finished in: ", vim.fn.reltimestr(vim.fn.reltime(start_time)))
|
|
||||||
end,
|
|
||||||
|
|
||||||
stdout_buffer = true,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local bufnr = 14
|
|
||||||
get_rg_results(bufnr, 'vim.api')
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
builtin.git_files = function(opts)
|
|
||||||
opts = opts or {}
|
|
||||||
|
|
||||||
opts.show_preview = get_default(opts.show_preview, true)
|
|
||||||
|
|
||||||
opts.finder = opts.finder or finders.new {
|
|
||||||
static = true,
|
|
||||||
|
|
||||||
fn_command = function()
|
|
||||||
return {
|
|
||||||
command = 'git',
|
|
||||||
args = {'ls-files'}
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.prompt = opts.prompt or 'Simple File'
|
|
||||||
opts.previewer = opts.previewer or previewers.cat
|
|
||||||
opts.sorter = opts.sorter or sorters.get_norcalli_sorter()
|
|
||||||
|
|
||||||
pickers.new(opts):find()
|
|
||||||
end
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
local x = {}
|
|
||||||
print(x); print("wow");
|
|
||||||
|
|
||||||
local function other() end
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
local telescope = require('telescope')
|
|
||||||
|
|
||||||
-- Uhh, finder should probably just GET the results
|
|
||||||
-- and then update some table.
|
|
||||||
-- When updating the table, we should call filter on those items
|
|
||||||
-- and then only display ones that pass the filter
|
|
||||||
local rg_finder = telescope.finders.new {
|
|
||||||
fn_command = function(_, prompt)
|
|
||||||
return string.format('rg --vimgrep %s', prompt)
|
|
||||||
end,
|
|
||||||
|
|
||||||
responsive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
local p = telescope.pickers.new {
|
|
||||||
previewer = telescope.previewers.vim_buffer
|
|
||||||
}
|
|
||||||
p:find {
|
|
||||||
prompt = 'grep',
|
|
||||||
finder = rg_finder
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
require('plenary.reload').reload_module('telescope')
|
|
||||||
|
|
||||||
local telescope = require('telescope')
|
|
||||||
|
|
||||||
-- What is a finder?
|
|
||||||
-- Finders return a list of stuff that you want to fuzzy look through.
|
|
||||||
-- Finders can be static or not.
|
|
||||||
-- Static finders just return a list that never changes
|
|
||||||
-- Otherwise they return a new list on each input, you should handle them async.
|
|
||||||
local file_finder = telescope.finders.new {
|
|
||||||
static = true,
|
|
||||||
|
|
||||||
fn_command = function() return 'git ls-files' end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local file_previewer = telescope.previewers.vim_buffer_or_bat
|
|
||||||
|
|
||||||
local file_picker = telescope.pickers.new {
|
|
||||||
previewer = file_previewer
|
|
||||||
}
|
|
||||||
|
|
||||||
-- local file_sorter = telescope.sorters.get_ngram_sorter()
|
|
||||||
-- local file_sorter = require('telescope.sorters').get_levenshtein_sorter()
|
|
||||||
local file_sorter = require('telescope.sorters').get_norcalli_sorter()
|
|
||||||
|
|
||||||
file_picker:find {
|
|
||||||
prompt = 'Simple File',
|
|
||||||
finder = file_finder,
|
|
||||||
sorter = file_sorter,
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
local string_distance = require('telescope.algos.string_distance')
|
|
||||||
|
|
||||||
print(string_distance("hello", "help"))
|
|
||||||
print(string_distance("hello", "hello"))
|
|
||||||
print(string_distance("hello", "asdf"))
|
|
||||||
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
Goal: Implement scrolling
|
|
||||||
|
|
||||||
So we want to start keeping track of more/all of the results
|
|
||||||
|
|
||||||
We still want them sorted, so when you scroll past,
|
|
||||||
you still get the stuff you'd expect.
|
|
||||||
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
Probably want some X / Y count
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Options
|
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
RELOAD('telescope')
|
|
||||||
|
|
||||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
|
||||||
|
|
||||||
-- Test for tail.
|
|
||||||
assert(sorter:score("aaa", "aaa/bbb") > sorter:score("aaa", "bbb/aaa"))
|
|
||||||
assert(
|
|
||||||
sorter:score("path", "/path/to/directory/file.txt")
|
|
||||||
> sorter:score("path", "/file/to/directory/path.txt")
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Matches well for UpperCase (basically just bonus points for having uppercase letters)
|
|
||||||
assert(sorter:score("AAA", "/blah/this/aaa/that") > sorter:score("AAA", "/blah/this/AAA/that"))
|
|
||||||
|
|
||||||
-- TODO: Determine our strategy for these
|
|
||||||
-- TODO: Make it so that capital letters count extra for being after a path sep.
|
|
||||||
-- assert(sorter:score("ftp", "/folder/to/python") > sorter:score("FTP", "/folder/to/python"))
|
|
||||||
|
|
||||||
-- TODO: Make it so that
|
|
||||||
-- assert(sorter:score("build", "/home/tj/build/neovim") > sorter:score("htbn", "/home/tj/build/neovim"))
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
local uv = require('luv')
|
|
||||||
|
|
||||||
-- print(vim.inspect(uv))
|
|
||||||
|
|
||||||
|
|
||||||
local my_table = {}
|
|
||||||
local my_value = 1
|
|
||||||
|
|
||||||
local table_adder = uv.new_thread(function(tbl)
|
|
||||||
table.insert(tbl, "HELLO")
|
|
||||||
end, my_table)
|
|
||||||
|
|
||||||
uv.thread_join(table_adder)
|
|
||||||
-- print(vim.inspect(MY_TABLE))
|
|
||||||
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
local uv = vim.loop
|
|
||||||
|
|
||||||
local has_ts, _ = pcall(require, 'nvim-treesitter')
|
|
||||||
if not has_ts then
|
|
||||||
error("ASKDLFJAKLSJFLASKDFJ")
|
|
||||||
end
|
|
||||||
|
|
||||||
local ts_highlight = require('nvim-treesitter.highlight')
|
|
||||||
local ts_parsers = require('nvim-treesitter.parsers')
|
|
||||||
|
|
||||||
local function readFile(path, callback)
|
|
||||||
uv.fs_open(path, "r", 438, function(err, fd)
|
|
||||||
assert(not err, err)
|
|
||||||
uv.fs_fstat(fd, function(err, stat)
|
|
||||||
assert(not err, err)
|
|
||||||
uv.fs_read(fd, stat.size, 0, function(err, data)
|
|
||||||
assert(not err, err)
|
|
||||||
uv.fs_close(fd, function(err)
|
|
||||||
assert(not err, err)
|
|
||||||
return callback(data)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local determine_filetype = function(filepath)
|
|
||||||
-- Obviously TODO
|
|
||||||
return "lua"
|
|
||||||
end
|
|
||||||
|
|
||||||
local filepath = "lua/telescope/init.lua"
|
|
||||||
|
|
||||||
local load_ts_buffer = function(bufnr, filepath)
|
|
||||||
local filetype = determine_filetype(filepath)
|
|
||||||
if not ts_parsers.has_parser(filetype) then
|
|
||||||
error("TODO CONNI")
|
|
||||||
end
|
|
||||||
|
|
||||||
readFile(filepath, vim.schedule_wrap(function(data)
|
|
||||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- pcall(ts_highlight.detach, bufnr)
|
|
||||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, vim.split(data, "\n"))
|
|
||||||
ts_highlight.attach(bufnr, filetype)
|
|
||||||
end))
|
|
||||||
end
|
|
||||||
|
|
||||||
load_ts_buffer(3, filepath)
|
|
||||||
Reference in New Issue
Block a user