break: prefix internal files and add deprecation messages (#2032)
This commit is contained in:
150
lua/telescope/builtin/__diagnostics.lua
Normal file
150
lua/telescope/builtin/__diagnostics.lua
Normal file
@@ -0,0 +1,150 @@
|
||||
local conf = require("telescope.config").values
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local utils = require "telescope.utils"
|
||||
|
||||
local diagnostics = {}
|
||||
|
||||
local convert_diagnostic_type = function(severities, severity)
|
||||
-- convert from string to int
|
||||
if type(severity) == "string" then
|
||||
-- make sure that e.g. error is uppercased to ERROR
|
||||
return severities[severity:upper()]
|
||||
end
|
||||
-- otherwise keep original value, incl. nil
|
||||
return severity
|
||||
end
|
||||
|
||||
local diagnostics_to_tbl = function(opts)
|
||||
opts = vim.F.if_nil(opts, {})
|
||||
local items = {}
|
||||
local severities = vim.diagnostic.severity
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
|
||||
opts.severity = convert_diagnostic_type(severities, opts.severity)
|
||||
opts.severity_limit = convert_diagnostic_type(severities, opts.severity_limit)
|
||||
opts.severity_bound = convert_diagnostic_type(severities, opts.severity_bound)
|
||||
|
||||
local diagnosis_opts = { severity = {}, namespace = opts.namespace }
|
||||
if opts.severity ~= nil then
|
||||
if opts.severity_limit ~= nil or opts.severity_bound ~= nil then
|
||||
utils.notify("builtin.diagnostics", {
|
||||
msg = "Invalid severity parameters. Both a specific severity and a limit/bound is not allowed",
|
||||
level = "ERROR",
|
||||
})
|
||||
return {}
|
||||
end
|
||||
diagnosis_opts.severity = opts.severity
|
||||
else
|
||||
if opts.severity_limit ~= nil then
|
||||
diagnosis_opts.severity["min"] = opts.severity_limit
|
||||
end
|
||||
if opts.severity_bound ~= nil then
|
||||
diagnosis_opts.severity["max"] = opts.severity_bound
|
||||
end
|
||||
end
|
||||
|
||||
opts.root_dir = opts.root_dir == true and vim.loop.cwd() or opts.root_dir
|
||||
|
||||
local bufnr_name_map = {}
|
||||
local filter_diag = function(diagnostic)
|
||||
if bufnr_name_map[diagnostic.bufnr] == nil then
|
||||
bufnr_name_map[diagnostic.bufnr] = vim.api.nvim_buf_get_name(diagnostic.bufnr)
|
||||
end
|
||||
|
||||
local root_dir_test = not opts.root_dir
|
||||
or string.sub(bufnr_name_map[diagnostic.bufnr], 1, #opts.root_dir) == opts.root_dir
|
||||
local listed_test = not opts.no_unlisted or vim.api.nvim_buf_get_option(diagnostic.bufnr, "buflisted")
|
||||
|
||||
return root_dir_test and listed_test
|
||||
end
|
||||
|
||||
local preprocess_diag = function(diagnostic)
|
||||
return {
|
||||
bufnr = diagnostic.bufnr,
|
||||
filename = bufnr_name_map[diagnostic.bufnr],
|
||||
lnum = diagnostic.lnum + 1,
|
||||
col = diagnostic.col + 1,
|
||||
text = vim.trim(diagnostic.message:gsub("[\n]", "")),
|
||||
type = severities[diagnostic.severity] or severities[1],
|
||||
}
|
||||
end
|
||||
|
||||
for _, d in ipairs(vim.diagnostic.get(opts.bufnr, diagnosis_opts)) do
|
||||
if filter_diag(d) then
|
||||
table.insert(items, preprocess_diag(d))
|
||||
end
|
||||
end
|
||||
|
||||
-- sort results by bufnr (prioritize cur buf), severity, lnum
|
||||
table.sort(items, function(a, b)
|
||||
if a.bufnr == b.bufnr then
|
||||
if a.type == b.type then
|
||||
return a.lnum < b.lnum
|
||||
else
|
||||
return a.type < b.type
|
||||
end
|
||||
else
|
||||
-- prioritize for current bufnr
|
||||
if a.bufnr == current_buf then
|
||||
return true
|
||||
end
|
||||
if b.bufnr == current_buf then
|
||||
return false
|
||||
end
|
||||
return a.bufnr < b.bufnr
|
||||
end
|
||||
end)
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
diagnostics.get = function(opts)
|
||||
if opts.bufnr ~= 0 then
|
||||
opts.bufnr = nil
|
||||
end
|
||||
if opts.bufnr == nil then
|
||||
opts.path_display = vim.F.if_nil(opts.path_display, {})
|
||||
end
|
||||
if type(opts.bufnr) == "string" then
|
||||
opts.bufnr = tonumber(opts.bufnr)
|
||||
end
|
||||
|
||||
local locations = diagnostics_to_tbl(opts)
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
utils.notify("builtin.diagnostics", {
|
||||
msg = "No diagnostics found",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
opts.path_display = vim.F.if_nil(opts.path_display, "hidden")
|
||||
pickers.new(opts, {
|
||||
prompt_title = opts.bufnr == nil and "Workspace Diagnostics" or "Document Diagnostics",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_diagnostics(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "type",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
}):find()
|
||||
end
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = opts or {}
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(diagnostics)
|
||||
522
lua/telescope/builtin/__files.lua
Normal file
522
lua/telescope/builtin/__files.lua
Normal file
@@ -0,0 +1,522 @@
|
||||
local action_state = require "telescope.actions.state"
|
||||
local action_set = require "telescope.actions.set"
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local previewers = require "telescope.previewers"
|
||||
local sorters = require "telescope.sorters"
|
||||
local utils = require "telescope.utils"
|
||||
local conf = require("telescope.config").values
|
||||
local log = require "telescope.log"
|
||||
|
||||
local Path = require "plenary.path"
|
||||
|
||||
local flatten = vim.tbl_flatten
|
||||
local filter = vim.tbl_filter
|
||||
|
||||
local files = {}
|
||||
|
||||
local escape_chars = function(string)
|
||||
return string.gsub(string, "[%(|%)|\\|%[|%]|%-|%{%}|%?|%+|%*|%^|%$|%.]", {
|
||||
["\\"] = "\\\\",
|
||||
["-"] = "\\-",
|
||||
["("] = "\\(",
|
||||
[")"] = "\\)",
|
||||
["["] = "\\[",
|
||||
["]"] = "\\]",
|
||||
["{"] = "\\{",
|
||||
["}"] = "\\}",
|
||||
["?"] = "\\?",
|
||||
["+"] = "\\+",
|
||||
["*"] = "\\*",
|
||||
["^"] = "\\^",
|
||||
["$"] = "\\$",
|
||||
["."] = "\\.",
|
||||
})
|
||||
end
|
||||
|
||||
-- Special keys:
|
||||
-- opts.search_dirs -- list of directory to search in
|
||||
-- opts.grep_open_files -- boolean to restrict search to open files
|
||||
files.live_grep = function(opts)
|
||||
local vimgrep_arguments = opts.vimgrep_arguments or conf.vimgrep_arguments
|
||||
local search_dirs = opts.search_dirs
|
||||
local grep_open_files = opts.grep_open_files
|
||||
opts.cwd = opts.cwd and vim.fn.expand(opts.cwd) or vim.loop.cwd()
|
||||
|
||||
local filelist = {}
|
||||
|
||||
if grep_open_files then
|
||||
local bufnrs = filter(function(b)
|
||||
if 1 ~= vim.fn.buflisted(b) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end, vim.api.nvim_list_bufs())
|
||||
if not next(bufnrs) then
|
||||
return
|
||||
end
|
||||
|
||||
for _, bufnr in ipairs(bufnrs) do
|
||||
local file = vim.api.nvim_buf_get_name(bufnr)
|
||||
table.insert(filelist, Path:new(file):make_relative(opts.cwd))
|
||||
end
|
||||
elseif search_dirs then
|
||||
for i, path in ipairs(search_dirs) do
|
||||
search_dirs[i] = vim.fn.expand(path)
|
||||
end
|
||||
end
|
||||
|
||||
local additional_args = {}
|
||||
if opts.additional_args ~= nil and type(opts.additional_args) == "function" then
|
||||
additional_args = opts.additional_args(opts)
|
||||
end
|
||||
|
||||
if opts.type_filter then
|
||||
additional_args[#additional_args + 1] = "--type=" .. opts.type_filter
|
||||
end
|
||||
|
||||
if type(opts.glob_pattern) == "string" then
|
||||
additional_args[#additional_args + 1] = "--glob=" .. opts.glob_pattern
|
||||
elseif type(opts.glob_pattern) == "table" then
|
||||
for i = 1, #opts.glob_pattern do
|
||||
additional_args[#additional_args + 1] = "--glob=" .. opts.glob_pattern[i]
|
||||
end
|
||||
end
|
||||
|
||||
local live_grepper = finders.new_job(function(prompt)
|
||||
-- TODO: Probably could add some options for smart case and whatever else rg offers.
|
||||
|
||||
if not prompt or prompt == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local search_list = {}
|
||||
|
||||
if search_dirs then
|
||||
table.insert(search_list, search_dirs)
|
||||
end
|
||||
|
||||
if grep_open_files then
|
||||
search_list = filelist
|
||||
end
|
||||
|
||||
return flatten { vimgrep_arguments, additional_args, "--", prompt, search_list }
|
||||
end, opts.entry_maker or make_entry.gen_from_vimgrep(opts), opts.max_results, opts.cwd)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Live Grep",
|
||||
finder = live_grepper,
|
||||
previewer = conf.grep_previewer(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),
|
||||
attach_mappings = function(_, map)
|
||||
map("i", "<c-space>", function(prompt_bufnr)
|
||||
local line = action_state.get_current_line()
|
||||
require("telescope.actions.generate").refine(prompt_bufnr, {
|
||||
prompt_title = "Find Word (" .. line .. ")",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
})
|
||||
end)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
-- Special keys:
|
||||
-- opts.search -- the string to search.
|
||||
-- opts.search_dirs -- list of directory to search in
|
||||
-- opts.use_regex -- special characters won't be escaped
|
||||
files.grep_string = function(opts)
|
||||
-- TODO: This should probably check your visual selection as well, if you've got one
|
||||
|
||||
local vimgrep_arguments = opts.vimgrep_arguments or conf.vimgrep_arguments
|
||||
local search_dirs = opts.search_dirs
|
||||
local word = opts.search or vim.fn.expand "<cword>"
|
||||
local search = opts.use_regex and word or escape_chars(word)
|
||||
local word_match = opts.word_match
|
||||
opts.entry_maker = opts.entry_maker or make_entry.gen_from_vimgrep(opts)
|
||||
|
||||
local title_word = word:gsub("\n", "\\n")
|
||||
|
||||
local additional_args = {}
|
||||
if opts.additional_args ~= nil and type(opts.additional_args) == "function" then
|
||||
additional_args = opts.additional_args(opts)
|
||||
end
|
||||
|
||||
local args = flatten {
|
||||
vimgrep_arguments,
|
||||
additional_args,
|
||||
word_match,
|
||||
"--",
|
||||
search,
|
||||
}
|
||||
|
||||
if search_dirs then
|
||||
for _, path in ipairs(search_dirs) do
|
||||
table.insert(args, vim.fn.expand(path))
|
||||
end
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Find Word (" .. title_word .. ")",
|
||||
finder = finders.new_oneshot_job(args, opts),
|
||||
previewer = conf.grep_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.find_files = function(opts)
|
||||
local find_command = (function()
|
||||
if opts.find_command then
|
||||
if type(opts.find_command) == "function" then
|
||||
return opts.find_command(opts)
|
||||
end
|
||||
return opts.find_command
|
||||
elseif 1 == vim.fn.executable "fd" then
|
||||
return { "fd", "--type", "f" }
|
||||
elseif 1 == vim.fn.executable "fdfind" then
|
||||
return { "fdfind", "--type", "f" }
|
||||
elseif 1 == vim.fn.executable "rg" then
|
||||
return { "rg", "--files" }
|
||||
elseif 1 == vim.fn.executable "find" and vim.fn.has "win32" == 0 then
|
||||
return { "find", ".", "-type", "f" }
|
||||
elseif 1 == vim.fn.executable "where" then
|
||||
return { "where", "/r", ".", "*" }
|
||||
end
|
||||
end)()
|
||||
|
||||
if not find_command then
|
||||
utils.notify("builtin.find_files", {
|
||||
msg = "You need to install either find, fd, or rg",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local command = find_command[1]
|
||||
local hidden = opts.hidden
|
||||
local no_ignore = opts.no_ignore
|
||||
local no_ignore_parent = opts.no_ignore_parent
|
||||
local follow = opts.follow
|
||||
local search_dirs = opts.search_dirs
|
||||
local search_file = opts.search_file
|
||||
|
||||
if search_dirs then
|
||||
for k, v in pairs(search_dirs) do
|
||||
search_dirs[k] = vim.fn.expand(v)
|
||||
end
|
||||
end
|
||||
|
||||
if command == "fd" or command == "fdfind" or command == "rg" then
|
||||
if hidden then
|
||||
table.insert(find_command, "--hidden")
|
||||
end
|
||||
if no_ignore then
|
||||
table.insert(find_command, "--no-ignore")
|
||||
end
|
||||
if no_ignore_parent then
|
||||
table.insert(find_command, "--no-ignore-parent")
|
||||
end
|
||||
if follow then
|
||||
table.insert(find_command, "-L")
|
||||
end
|
||||
if search_file then
|
||||
if command == "rg" then
|
||||
table.insert(find_command, "-g")
|
||||
table.insert(find_command, "*" .. search_file .. "*")
|
||||
else
|
||||
table.insert(find_command, search_file)
|
||||
end
|
||||
end
|
||||
if search_dirs then
|
||||
if command ~= "rg" and not search_file then
|
||||
table.insert(find_command, ".")
|
||||
end
|
||||
for _, v in pairs(search_dirs) do
|
||||
table.insert(find_command, v)
|
||||
end
|
||||
end
|
||||
elseif command == "find" then
|
||||
if not hidden then
|
||||
table.insert(find_command, { "-not", "-path", "*/.*" })
|
||||
find_command = flatten(find_command)
|
||||
end
|
||||
if no_ignore ~= nil then
|
||||
log.warn "The `no_ignore` key is not available for the `find` command in `find_files`."
|
||||
end
|
||||
if no_ignore_parent ~= nil then
|
||||
log.warn "The `no_ignore_parent` key is not available for the `find` command in `find_files`."
|
||||
end
|
||||
if follow then
|
||||
table.insert(find_command, 2, "-L")
|
||||
end
|
||||
if search_file then
|
||||
table.insert(find_command, "-name")
|
||||
table.insert(find_command, "*" .. search_file .. "*")
|
||||
end
|
||||
if search_dirs then
|
||||
table.remove(find_command, 2)
|
||||
for _, v in pairs(search_dirs) do
|
||||
table.insert(find_command, 2, v)
|
||||
end
|
||||
end
|
||||
elseif command == "where" then
|
||||
if hidden ~= nil then
|
||||
log.warn "The `hidden` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if no_ignore ~= nil then
|
||||
log.warn "The `no_ignore` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if no_ignore_parent ~= nil then
|
||||
log.warn "The `no_ignore_parent` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if follow ~= nil then
|
||||
log.warn "The `follow` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if search_dirs ~= nil then
|
||||
log.warn "The `search_dirs` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if search_file ~= nil then
|
||||
log.warn "The `search_file` key is not available for the Windows `where` command in `find_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)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Find Files",
|
||||
finder = finders.new_oneshot_job(find_command, opts),
|
||||
previewer = conf.file_previewer(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
}):find()
|
||||
end
|
||||
|
||||
local function prepare_match(entry, kind)
|
||||
local entries = {}
|
||||
|
||||
if entry.node then
|
||||
table.insert(entries, entry)
|
||||
else
|
||||
for name, item in pairs(entry) do
|
||||
vim.list_extend(entries, prepare_match(item, name))
|
||||
end
|
||||
end
|
||||
|
||||
return entries
|
||||
end
|
||||
|
||||
-- TODO: finish docs for opts.show_line
|
||||
files.treesitter = function(opts)
|
||||
opts.show_line = vim.F.if_nil(opts.show_line, true)
|
||||
|
||||
local has_nvim_treesitter, _ = pcall(require, "nvim-treesitter")
|
||||
if not has_nvim_treesitter then
|
||||
utils.notify("builtin.treesitter", {
|
||||
msg = "User need to install nvim-treesitter needs to be installed",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
if not parsers.has_parser(parsers.get_buf_lang(opts.bufnr)) then
|
||||
utils.notify("builtin.treesitter", {
|
||||
msg = "No parser for the current buffer",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local ts_locals = require "nvim-treesitter.locals"
|
||||
local results = {}
|
||||
for _, definition in ipairs(ts_locals.get_definitions(opts.bufnr)) do
|
||||
local entries = prepare_match(ts_locals.get_local_nodes(definition))
|
||||
for _, entry in ipairs(entries) do
|
||||
entry.kind = vim.F.if_nil(entry.kind, "")
|
||||
table.insert(results, entry)
|
||||
end
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(results) then
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Treesitter Symbols",
|
||||
finder = finders.new_table {
|
||||
results = results,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_treesitter(opts),
|
||||
},
|
||||
previewer = conf.grep_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "kind",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.current_buffer_fuzzy_find = function(opts)
|
||||
-- All actions are on the current buffer
|
||||
local filename = vim.fn.expand(vim.api.nvim_buf_get_name(opts.bufnr))
|
||||
local filetype = vim.api.nvim_buf_get_option(opts.bufnr, "filetype")
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(opts.bufnr, 0, -1, false)
|
||||
local lines_with_numbers = {}
|
||||
|
||||
for lnum, line in ipairs(lines) do
|
||||
table.insert(lines_with_numbers, {
|
||||
lnum = lnum,
|
||||
bufnr = opts.bufnr,
|
||||
filename = filename,
|
||||
text = line,
|
||||
})
|
||||
end
|
||||
|
||||
local ts_ok, ts_parsers = pcall(require, "nvim-treesitter.parsers")
|
||||
if ts_ok then
|
||||
filetype = ts_parsers.ft_to_lang(filetype)
|
||||
end
|
||||
local _, ts_configs = pcall(require, "nvim-treesitter.configs")
|
||||
|
||||
local parser_ok, parser = pcall(vim.treesitter.get_parser, opts.bufnr, filetype)
|
||||
local query_ok, query = pcall(vim.treesitter.get_query, filetype, "highlights")
|
||||
if parser_ok and query_ok and ts_ok and ts_configs.is_enabled("highlight", filetype, opts.bufnr) then
|
||||
local root = parser:parse()[1]:root()
|
||||
|
||||
local highlighter = vim.treesitter.highlighter.new(parser)
|
||||
local highlighter_query = highlighter:get_query(filetype)
|
||||
|
||||
local line_highlights = setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
local obj = {}
|
||||
rawset(t, k, obj)
|
||||
return obj
|
||||
end,
|
||||
})
|
||||
for id, node in query:iter_captures(root, opts.bufnr, 0, -1) do
|
||||
local hl = highlighter_query:_get_hl_from_capture(id)
|
||||
if hl and type(hl) ~= "number" then
|
||||
local row1, col1, row2, col2 = node:range()
|
||||
|
||||
if row1 == row2 then
|
||||
local row = row1 + 1
|
||||
|
||||
for index = col1, col2 do
|
||||
line_highlights[row][index] = hl
|
||||
end
|
||||
else
|
||||
local row = row1 + 1
|
||||
for index = col1, #lines[row] do
|
||||
line_highlights[row][index] = hl
|
||||
end
|
||||
|
||||
while row < row2 + 1 do
|
||||
row = row + 1
|
||||
|
||||
for index = 0, #(lines[row] or {}) do
|
||||
line_highlights[row][index] = hl
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
opts.line_highlights = line_highlights
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Current Buffer Fuzzy",
|
||||
finder = finders.new_table {
|
||||
results = lines_with_numbers,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_buffer_lines(opts),
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
previewer = conf.grep_previewer(opts),
|
||||
attach_mappings = function()
|
||||
action_set.select:enhance {
|
||||
post = function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
|
||||
end,
|
||||
}
|
||||
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.tags = function(opts)
|
||||
local tagfiles = opts.ctags_file and { opts.ctags_file } or vim.fn.tagfiles()
|
||||
for i, ctags_file in ipairs(tagfiles) do
|
||||
tagfiles[i] = vim.fn.expand(ctags_file, true)
|
||||
end
|
||||
if vim.tbl_isempty(tagfiles) then
|
||||
utils.notify("builtin.tags", {
|
||||
msg = "No tags file found. Create one with ctags -R",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_ctags(opts))
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Tags",
|
||||
finder = finders.new_oneshot_job(flatten { "cat", tagfiles }, opts),
|
||||
previewer = previewers.ctags.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function()
|
||||
action_set.select:enhance {
|
||||
post = function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
if not selection then
|
||||
return
|
||||
end
|
||||
|
||||
if selection.scode then
|
||||
-- un-escape / then escape required
|
||||
-- special chars for vim.fn.search()
|
||||
-- ] ~ *
|
||||
local scode = selection.scode:gsub([[\/]], "/"):gsub("[%]~*]", function(x)
|
||||
return "\\" .. x
|
||||
end)
|
||||
|
||||
vim.cmd "norm! gg"
|
||||
vim.fn.search(scode)
|
||||
vim.cmd "norm! zz"
|
||||
else
|
||||
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
|
||||
end
|
||||
end,
|
||||
}
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.current_buffer_tags = function(opts)
|
||||
return files.tags(vim.tbl_extend("force", {
|
||||
prompt_title = "Current Buffer Tags",
|
||||
only_current_file = true,
|
||||
path_display = "hidden",
|
||||
}, opts))
|
||||
end
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(files)
|
||||
411
lua/telescope/builtin/__git.lua
Normal file
411
lua/telescope/builtin/__git.lua
Normal file
@@ -0,0 +1,411 @@
|
||||
local actions = require "telescope.actions"
|
||||
local action_state = require "telescope.actions.state"
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local previewers = require "telescope.previewers"
|
||||
local utils = require "telescope.utils"
|
||||
local entry_display = require "telescope.pickers.entry_display"
|
||||
local strings = require "plenary.strings"
|
||||
local Path = require "plenary.path"
|
||||
|
||||
local conf = require("telescope.config").values
|
||||
|
||||
local git = {}
|
||||
|
||||
git.files = function(opts)
|
||||
if opts.is_bare then
|
||||
utils.notify("builtin.git_files", {
|
||||
msg = "This operation must be run in a work tree",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local show_untracked = vim.F.if_nil(opts.show_untracked, false)
|
||||
local recurse_submodules = vim.F.if_nil(opts.recurse_submodules, false)
|
||||
if show_untracked and recurse_submodules then
|
||||
utils.notify("builtin.git_files", {
|
||||
msg = "Git does not support both --others and --recurse-submodules",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
-- By creating the entry maker after the cwd options,
|
||||
-- we ensure the maker uses the cwd options when being created.
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_file(opts))
|
||||
local git_command = vim.F.if_nil(opts.git_command, { "git", "ls-files", "--exclude-standard", "--cached" })
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Files",
|
||||
finder = finders.new_oneshot_job(
|
||||
vim.tbl_flatten {
|
||||
git_command,
|
||||
show_untracked and "--others" or nil,
|
||||
recurse_submodules and "--recurse-submodules" or nil,
|
||||
},
|
||||
opts
|
||||
),
|
||||
previewer = conf.file_previewer(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.commits = function(opts)
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
|
||||
local git_command = vim.F.if_nil(opts.git_command, { "git", "log", "--pretty=oneline", "--abbrev-commit", "--", "." })
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Commits",
|
||||
finder = finders.new_oneshot_job(git_command, opts),
|
||||
previewer = {
|
||||
previewers.git_commit_diff_to_parent.new(opts),
|
||||
previewers.git_commit_diff_to_head.new(opts),
|
||||
previewers.git_commit_diff_as_was.new(opts),
|
||||
previewers.git_commit_message.new(opts),
|
||||
},
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function(_, map)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
map("i", "<c-r>m", actions.git_reset_mixed)
|
||||
map("n", "<c-r>m", actions.git_reset_mixed)
|
||||
map("i", "<c-r>s", actions.git_reset_soft)
|
||||
map("n", "<c-r>s", actions.git_reset_soft)
|
||||
map("i", "<c-r>h", actions.git_reset_hard)
|
||||
map("n", "<c-r>h", actions.git_reset_hard)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.stash = function(opts)
|
||||
opts.show_branch = vim.F.if_nil(opts.show_branch, true)
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_stash(opts))
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Stash",
|
||||
finder = finders.new_oneshot_job(
|
||||
vim.tbl_flatten {
|
||||
"git",
|
||||
"--no-pager",
|
||||
"stash",
|
||||
"list",
|
||||
},
|
||||
opts
|
||||
),
|
||||
previewer = previewers.git_stash_diff.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.select_default:replace(actions.git_apply_stash)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
local get_current_buf_line = function(winnr)
|
||||
local lnum = vim.api.nvim_win_get_cursor(winnr)[1]
|
||||
return vim.trim(vim.api.nvim_buf_get_lines(vim.api.nvim_win_get_buf(winnr), lnum - 1, lnum, false)[1])
|
||||
end
|
||||
|
||||
git.bcommits = function(opts)
|
||||
opts.current_line = (opts.current_file == nil) and get_current_buf_line(opts.winnr) or nil
|
||||
opts.current_file = vim.F.if_nil(opts.current_file, vim.api.nvim_buf_get_name(opts.bufnr))
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
|
||||
local git_command = vim.F.if_nil(
|
||||
opts.git_command,
|
||||
{ "git", "log", "--pretty=oneline", "--abbrev-commit", "--follow" }
|
||||
)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git BCommits",
|
||||
finder = finders.new_oneshot_job(
|
||||
vim.tbl_flatten {
|
||||
git_command,
|
||||
opts.current_file,
|
||||
},
|
||||
opts
|
||||
),
|
||||
previewer = {
|
||||
previewers.git_commit_diff_to_parent.new(opts),
|
||||
previewers.git_commit_diff_to_head.new(opts),
|
||||
previewers.git_commit_diff_as_was.new(opts),
|
||||
previewers.git_commit_message.new(opts),
|
||||
},
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.select_default:replace(actions.git_checkout_current_buffer)
|
||||
local transfrom_file = function()
|
||||
return opts.current_file and Path:new(opts.current_file):make_relative(opts.cwd) or ""
|
||||
end
|
||||
|
||||
local get_buffer_of_orig = function(selection)
|
||||
local value = selection.value .. ":" .. transfrom_file()
|
||||
local content = utils.get_os_command_output({ "git", "--no-pager", "show", value }, opts.cwd)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, content)
|
||||
vim.api.nvim_buf_set_name(bufnr, "Original")
|
||||
return bufnr
|
||||
end
|
||||
|
||||
local vimdiff = function(selection, command)
|
||||
local ft = vim.bo.filetype
|
||||
vim.cmd "diffthis"
|
||||
|
||||
local bufnr = get_buffer_of_orig(selection)
|
||||
vim.cmd(string.format("%s %s", command, bufnr))
|
||||
vim.bo.filetype = ft
|
||||
vim.cmd "diffthis"
|
||||
|
||||
vim.api.nvim_create_autocmd("WinClosed", {
|
||||
buffer = bufnr,
|
||||
nested = true,
|
||||
once = true,
|
||||
callback = function()
|
||||
vim.api.nvim_buf_delete(bufnr, { force = true })
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
actions.select_vertical:replace(function(prompt_bufnr)
|
||||
actions.close(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry()
|
||||
vimdiff(selection, "leftabove vert sbuffer")
|
||||
end)
|
||||
|
||||
actions.select_horizontal:replace(function(prompt_bufnr)
|
||||
actions.close(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry()
|
||||
vimdiff(selection, "belowright sbuffer")
|
||||
end)
|
||||
|
||||
actions.select_tab:replace(function(prompt_bufnr)
|
||||
actions.close(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry()
|
||||
vim.cmd("tabedit " .. transfrom_file())
|
||||
vimdiff(selection, "leftabove vert sbuffer")
|
||||
end)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.branches = function(opts)
|
||||
local format = "%(HEAD)"
|
||||
.. "%(refname)"
|
||||
.. "%(authorname)"
|
||||
.. "%(upstream:lstrip=2)"
|
||||
.. "%(committerdate:format-local:%Y/%m/%d %H:%M:%S)"
|
||||
local output = utils.get_os_command_output(
|
||||
{ "git", "for-each-ref", "--perl", "--format", format, opts.pattern },
|
||||
opts.cwd
|
||||
)
|
||||
|
||||
local results = {}
|
||||
local widths = {
|
||||
name = 0,
|
||||
authorname = 0,
|
||||
upstream = 0,
|
||||
committerdate = 0,
|
||||
}
|
||||
local unescape_single_quote = function(v)
|
||||
return string.gsub(v, "\\([\\'])", "%1")
|
||||
end
|
||||
local parse_line = function(line)
|
||||
local fields = vim.split(string.sub(line, 2, -2), "''", true)
|
||||
local entry = {
|
||||
head = fields[1],
|
||||
refname = unescape_single_quote(fields[2]),
|
||||
authorname = unescape_single_quote(fields[3]),
|
||||
upstream = unescape_single_quote(fields[4]),
|
||||
committerdate = fields[5],
|
||||
}
|
||||
local prefix
|
||||
if vim.startswith(entry.refname, "refs/remotes/") then
|
||||
prefix = "refs/remotes/"
|
||||
elseif vim.startswith(entry.refname, "refs/heads/") then
|
||||
prefix = "refs/heads/"
|
||||
else
|
||||
return
|
||||
end
|
||||
local index = 1
|
||||
if entry.head ~= "*" then
|
||||
index = #results + 1
|
||||
end
|
||||
|
||||
entry.name = string.sub(entry.refname, string.len(prefix) + 1)
|
||||
for key, value in pairs(widths) do
|
||||
widths[key] = math.max(value, strings.strdisplaywidth(entry[key] or ""))
|
||||
end
|
||||
if string.len(entry.upstream) > 0 then
|
||||
widths.upstream_indicator = 2
|
||||
end
|
||||
table.insert(results, index, entry)
|
||||
end
|
||||
for _, line in ipairs(output) do
|
||||
parse_line(line)
|
||||
end
|
||||
if #results == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local displayer = entry_display.create {
|
||||
separator = " ",
|
||||
items = {
|
||||
{ width = 1 },
|
||||
{ width = widths.name },
|
||||
{ width = widths.authorname },
|
||||
{ width = widths.upstream_indicator },
|
||||
{ width = widths.upstream },
|
||||
{ width = widths.committerdate },
|
||||
},
|
||||
}
|
||||
|
||||
local make_display = function(entry)
|
||||
return displayer {
|
||||
{ entry.head },
|
||||
{ entry.name, "TelescopeResultsIdentifier" },
|
||||
{ entry.authorname },
|
||||
{ string.len(entry.upstream) > 0 and "=>" or "" },
|
||||
{ entry.upstream, "TelescopeResultsIdentifier" },
|
||||
{ entry.committerdate },
|
||||
}
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Branches",
|
||||
finder = finders.new_table {
|
||||
results = results,
|
||||
entry_maker = function(entry)
|
||||
entry.value = entry.name
|
||||
entry.ordinal = entry.name
|
||||
entry.display = make_display
|
||||
return make_entry.set_default_entry_mt(entry, opts)
|
||||
end,
|
||||
},
|
||||
previewer = previewers.git_branch_log.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function(_, map)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
map("i", "<c-t>", actions.git_track_branch)
|
||||
map("n", "<c-t>", actions.git_track_branch)
|
||||
|
||||
map("i", "<c-r>", actions.git_rebase_branch)
|
||||
map("n", "<c-r>", actions.git_rebase_branch)
|
||||
|
||||
map("i", "<c-a>", actions.git_create_branch)
|
||||
map("n", "<c-a>", actions.git_create_branch)
|
||||
|
||||
map("i", "<c-s>", actions.git_switch_branch)
|
||||
map("n", "<c-s>", actions.git_switch_branch)
|
||||
|
||||
map("i", "<c-d>", actions.git_delete_branch)
|
||||
map("n", "<c-d>", actions.git_delete_branch)
|
||||
|
||||
map("i", "<c-y>", actions.git_merge_branch)
|
||||
map("n", "<c-y>", actions.git_merge_branch)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.status = function(opts)
|
||||
if opts.is_bare then
|
||||
utils.notify("builtin.git_status", {
|
||||
msg = "This operation must be run in a work tree",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local gen_new_finder = function()
|
||||
local expand_dir = vim.F.if_nil(opts.expand_dir, true)
|
||||
local git_cmd = { "git", "status", "-s", "--", "." }
|
||||
|
||||
if expand_dir then
|
||||
table.insert(git_cmd, #git_cmd - 1, "-u")
|
||||
end
|
||||
|
||||
local output = utils.get_os_command_output(git_cmd, opts.cwd)
|
||||
|
||||
if #output == 0 then
|
||||
print "No changes found"
|
||||
utils.notify("builtin.git_status", {
|
||||
msg = "No changes found",
|
||||
level = "WARN",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
return finders.new_table {
|
||||
results = output,
|
||||
entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_status(opts)),
|
||||
}
|
||||
end
|
||||
|
||||
local initial_finder = gen_new_finder()
|
||||
if not initial_finder then
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Status",
|
||||
finder = initial_finder,
|
||||
previewer = previewers.git_file_diff.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr, map)
|
||||
actions.git_staging_toggle:enhance {
|
||||
post = function()
|
||||
action_state.get_current_picker(prompt_bufnr):refresh(gen_new_finder(), { reset_prompt = true })
|
||||
end,
|
||||
}
|
||||
|
||||
map("i", "<tab>", actions.git_staging_toggle)
|
||||
map("n", "<tab>", actions.git_staging_toggle)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
local set_opts_cwd = function(opts)
|
||||
if opts.cwd then
|
||||
opts.cwd = vim.fn.expand(opts.cwd)
|
||||
else
|
||||
opts.cwd = vim.loop.cwd()
|
||||
end
|
||||
|
||||
-- Find root of git directory and remove trailing newline characters
|
||||
local git_root, ret = utils.get_os_command_output({ "git", "rev-parse", "--show-toplevel" }, opts.cwd)
|
||||
local use_git_root = vim.F.if_nil(opts.use_git_root, true)
|
||||
|
||||
if ret ~= 0 then
|
||||
local in_worktree = utils.get_os_command_output({ "git", "rev-parse", "--is-inside-work-tree" }, opts.cwd)
|
||||
local in_bare = utils.get_os_command_output({ "git", "rev-parse", "--is-bare-repository" }, opts.cwd)
|
||||
|
||||
if in_worktree[1] ~= "true" and in_bare[1] ~= "true" then
|
||||
error(opts.cwd .. " is not a git directory")
|
||||
elseif in_worktree[1] ~= "true" and in_bare[1] == "true" then
|
||||
opts.is_bare = true
|
||||
end
|
||||
else
|
||||
if use_git_root then
|
||||
opts.cwd = git_root[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = vim.F.if_nil(opts, {})
|
||||
|
||||
set_opts_cwd(opts)
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(git)
|
||||
1318
lua/telescope/builtin/__internal.lua
Normal file
1318
lua/telescope/builtin/__internal.lua
Normal file
File diff suppressed because it is too large
Load Diff
389
lua/telescope/builtin/__lsp.lua
Normal file
389
lua/telescope/builtin/__lsp.lua
Normal file
@@ -0,0 +1,389 @@
|
||||
local channel = require("plenary.async.control").channel
|
||||
local action_state = require "telescope.actions.state"
|
||||
local sorters = require "telescope.sorters"
|
||||
local conf = require("telescope.config").values
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local utils = require "telescope.utils"
|
||||
|
||||
local lsp = {}
|
||||
|
||||
lsp.references = function(opts)
|
||||
local filepath = vim.api.nvim_buf_get_name(opts.bufnr)
|
||||
local lnum = vim.api.nvim_win_get_cursor(opts.winnr)[1]
|
||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||
local include_current_line = vim.F.if_nil(opts.include_current_line, false)
|
||||
params.context = { includeDeclaration = vim.F.if_nil(opts.include_declaration, true) }
|
||||
|
||||
vim.lsp.buf_request(opts.bufnr, "textDocument/references", params, function(err, result, ctx, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when finding references: " .. err.message)
|
||||
return
|
||||
end
|
||||
|
||||
local locations = {}
|
||||
if result then
|
||||
local results = vim.lsp.util.locations_to_items(result, vim.lsp.get_client_by_id(ctx.client_id).offset_encoding)
|
||||
if include_current_line then
|
||||
locations = vim.tbl_filter(function(v)
|
||||
-- Remove current line from result
|
||||
return not (v.filename == filepath and v.lnum == lnum)
|
||||
end, vim.F.if_nil(results, {}))
|
||||
else
|
||||
locations = vim.F.if_nil(results, {})
|
||||
end
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP References",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
local function call_hierarchy(opts, method, title, direction, item)
|
||||
vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error handling " .. title .. ": " .. err)
|
||||
return
|
||||
end
|
||||
|
||||
if not result or vim.tbl_isempty(result) then
|
||||
return
|
||||
end
|
||||
|
||||
local locations = {}
|
||||
for _, ch_call in pairs(result) do
|
||||
local ch_item = ch_call[direction]
|
||||
for _, range in pairs(ch_call.fromRanges) do
|
||||
table.insert(locations, {
|
||||
filename = vim.uri_to_fname(ch_item.uri),
|
||||
text = ch_item.name,
|
||||
lnum = range.start.line + 1,
|
||||
col = range.start.character + 1,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = title,
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
local function pick_call_hierarchy_item(call_hierarchy_items)
|
||||
if not call_hierarchy_items then
|
||||
return
|
||||
end
|
||||
if #call_hierarchy_items == 1 then
|
||||
return call_hierarchy_items[1]
|
||||
end
|
||||
local items = {}
|
||||
for i, item in pairs(call_hierarchy_items) do
|
||||
local entry = item.detail or item.name
|
||||
table.insert(items, string.format("%d. %s", i, entry))
|
||||
end
|
||||
local choice = vim.fn.inputlist(items)
|
||||
if choice < 1 or choice > #items then
|
||||
return
|
||||
end
|
||||
return choice
|
||||
end
|
||||
|
||||
local function calls(opts, direction)
|
||||
local params = vim.lsp.util.make_position_params()
|
||||
vim.lsp.buf_request(opts.bufnr, "textDocument/prepareCallHierarchy", params, function(err, result)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when preparing call hierarchy: " .. err)
|
||||
return
|
||||
end
|
||||
|
||||
local call_hierarchy_item = pick_call_hierarchy_item(result)
|
||||
if not call_hierarchy_item then
|
||||
return
|
||||
end
|
||||
|
||||
if direction == "from" then
|
||||
call_hierarchy(opts, "callHierarchy/incomingCalls", "LSP Incoming Calls", direction, call_hierarchy_item)
|
||||
else
|
||||
call_hierarchy(opts, "callHierarchy/outgoingCalls", "LSP Outgoing Calls", direction, call_hierarchy_item)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
lsp.incoming_calls = function(opts)
|
||||
calls(opts, "from")
|
||||
end
|
||||
|
||||
lsp.outgoing_calls = function(opts)
|
||||
calls(opts, "to")
|
||||
end
|
||||
|
||||
local function list_or_jump(action, title, opts)
|
||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||
vim.lsp.buf_request(opts.bufnr, action, params, function(err, result, ctx, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when executing " .. action .. " : " .. err.message)
|
||||
return
|
||||
end
|
||||
local flattened_results = {}
|
||||
if result then
|
||||
-- textDocument/definition can return Location or Location[]
|
||||
if not vim.tbl_islist(result) then
|
||||
flattened_results = { result }
|
||||
end
|
||||
|
||||
vim.list_extend(flattened_results, result)
|
||||
end
|
||||
|
||||
local offset_encoding = vim.lsp.get_client_by_id(ctx.client_id).offset_encoding
|
||||
|
||||
if #flattened_results == 0 then
|
||||
return
|
||||
elseif #flattened_results == 1 and opts.jump_type ~= "never" then
|
||||
if opts.jump_type == "tab" then
|
||||
vim.cmd "tabedit"
|
||||
elseif opts.jump_type == "split" then
|
||||
vim.cmd "new"
|
||||
elseif opts.jump_type == "vsplit" then
|
||||
vim.cmd "vnew"
|
||||
end
|
||||
vim.lsp.util.jump_to_location(flattened_results[1], offset_encoding)
|
||||
else
|
||||
local locations = vim.lsp.util.locations_to_items(flattened_results, offset_encoding)
|
||||
pickers.new(opts, {
|
||||
prompt_title = title,
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
lsp.definitions = function(opts)
|
||||
return list_or_jump("textDocument/definition", "LSP Definitions", opts)
|
||||
end
|
||||
|
||||
lsp.type_definitions = function(opts)
|
||||
return list_or_jump("textDocument/typeDefinition", "LSP Type Definitions", opts)
|
||||
end
|
||||
|
||||
lsp.implementations = function(opts)
|
||||
return list_or_jump("textDocument/implementation", "LSP Implementations", opts)
|
||||
end
|
||||
|
||||
lsp.document_symbols = function(opts)
|
||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||
vim.lsp.buf_request(opts.bufnr, "textDocument/documentSymbol", params, function(err, result, _, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when finding document symbols: " .. err.message)
|
||||
return
|
||||
end
|
||||
|
||||
if not result or vim.tbl_isempty(result) then
|
||||
utils.notify("builtin.lsp_document_symbols", {
|
||||
msg = "No results from textDocument/documentSymbol",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local locations = vim.lsp.util.symbols_to_items(result or {}, opts.bufnr) or {}
|
||||
locations = utils.filter_symbols(locations, opts)
|
||||
if locations == nil then
|
||||
-- error message already printed in `utils.filter_symbols`
|
||||
return
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
utils.notify("builtin.lsp_document_symbols", {
|
||||
msg = "No document_symbol locations found",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
opts.path_display = { "hidden" }
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP Document Symbols",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "symbol_type",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
lsp.workspace_symbols = function(opts)
|
||||
local params = { query = opts.query or "" }
|
||||
vim.lsp.buf_request(opts.bufnr, "workspace/symbol", params, function(err, server_result, _, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when finding workspace symbols: " .. err.message)
|
||||
return
|
||||
end
|
||||
|
||||
local locations = vim.lsp.util.symbols_to_items(server_result or {}, opts.bufnr) or {}
|
||||
locations = utils.filter_symbols(locations, opts)
|
||||
if locations == nil then
|
||||
-- error message already printed in `utils.filter_symbols`
|
||||
return
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
utils.notify("builtin.lsp_workspace_symbols", {
|
||||
msg = "No results from workspace/symbol. Maybe try a different query: "
|
||||
.. "'Telescope lsp_workspace_symbols query=example'",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
opts.ignore_filename = vim.F.if_nil(opts.ignore_filename, false)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP Workspace Symbols",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "symbol_type",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
local function get_workspace_symbols_requester(bufnr, opts)
|
||||
local cancel = function() end
|
||||
|
||||
return function(prompt)
|
||||
local tx, rx = channel.oneshot()
|
||||
cancel()
|
||||
_, cancel = vim.lsp.buf_request(bufnr, "workspace/symbol", { query = prompt }, tx)
|
||||
|
||||
-- Handle 0.5 / 0.5.1 handler situation
|
||||
local err, res = rx()
|
||||
assert(not err, err)
|
||||
|
||||
local locations = vim.lsp.util.symbols_to_items(res or {}, bufnr) or {}
|
||||
if not vim.tbl_isempty(locations) then
|
||||
locations = utils.filter_symbols(locations, opts) or {}
|
||||
end
|
||||
return locations
|
||||
end
|
||||
end
|
||||
|
||||
lsp.dynamic_workspace_symbols = function(opts)
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP Dynamic Workspace Symbols",
|
||||
finder = finders.new_dynamic {
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
|
||||
fn = get_workspace_symbols_requester(opts.bufnr, opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = sorters.highlighter_only(opts),
|
||||
attach_mappings = function(_, map)
|
||||
map("i", "<c-space>", function(prompt_bufnr)
|
||||
local line = action_state.get_current_line()
|
||||
require("telescope.actions.generate").refine(prompt_bufnr, {
|
||||
prompt_title = "LSP Workspace Symbols (" .. line .. ")",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
})
|
||||
end)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
local function check_capabilities(feature, bufnr)
|
||||
local clients = vim.lsp.buf_get_clients(bufnr)
|
||||
|
||||
local supported_client = false
|
||||
for _, client in pairs(clients) do
|
||||
supported_client = client.server_capabilities[feature]
|
||||
if supported_client then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if supported_client then
|
||||
return true
|
||||
else
|
||||
if #clients == 0 then
|
||||
utils.notify("builtin.lsp_*", {
|
||||
msg = "no client attached",
|
||||
level = "INFO",
|
||||
})
|
||||
else
|
||||
utils.notify("builtin.lsp_*", {
|
||||
msg = "server does not support " .. feature,
|
||||
level = "INFO",
|
||||
})
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local feature_map = {
|
||||
["document_symbols"] = "documentSymbolProvider",
|
||||
["references"] = "referencesProvider",
|
||||
["definitions"] = "definitionProvider",
|
||||
["type_definitions"] = "typeDefinitionProvider",
|
||||
["implementations"] = "implementationProvider",
|
||||
["workspace_symbols"] = "workspaceSymbolProvider",
|
||||
["incoming_calls"] = "callHierarchyProvider",
|
||||
["outgoing_calls"] = "callHierarchyProvider",
|
||||
}
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local feature_name = feature_map[k]
|
||||
if feature_name and not check_capabilities(feature_name, opts.bufnr) then
|
||||
return
|
||||
end
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(lsp)
|
||||
@@ -1,150 +1,17 @@
|
||||
local conf = require("telescope.config").values
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local m = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
local utils = require "telescope.utils"
|
||||
|
||||
local diagnostics = {}
|
||||
|
||||
local convert_diagnostic_type = function(severities, severity)
|
||||
-- convert from string to int
|
||||
if type(severity) == "string" then
|
||||
-- make sure that e.g. error is uppercased to ERROR
|
||||
return severities[severity:upper()]
|
||||
end
|
||||
-- otherwise keep original value, incl. nil
|
||||
return severity
|
||||
end
|
||||
|
||||
local diagnostics_to_tbl = function(opts)
|
||||
opts = vim.F.if_nil(opts, {})
|
||||
local items = {}
|
||||
local severities = vim.diagnostic.severity
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
|
||||
opts.severity = convert_diagnostic_type(severities, opts.severity)
|
||||
opts.severity_limit = convert_diagnostic_type(severities, opts.severity_limit)
|
||||
opts.severity_bound = convert_diagnostic_type(severities, opts.severity_bound)
|
||||
|
||||
local diagnosis_opts = { severity = {}, namespace = opts.namespace }
|
||||
if opts.severity ~= nil then
|
||||
if opts.severity_limit ~= nil or opts.severity_bound ~= nil then
|
||||
utils.notify("builtin.diagnostics", {
|
||||
msg = "Invalid severity parameters. Both a specific severity and a limit/bound is not allowed",
|
||||
utils.notify("builtin", {
|
||||
msg = string.format(
|
||||
'You are using an internal interface. Do not use `require("telescope.builtin.diagnostics").%s`,'
|
||||
.. ' please use `require("telescope.builtin").diagnostics`! We will remove this endpoint soon!',
|
||||
k,
|
||||
k
|
||||
),
|
||||
level = "ERROR",
|
||||
})
|
||||
return {}
|
||||
end
|
||||
diagnosis_opts.severity = opts.severity
|
||||
else
|
||||
if opts.severity_limit ~= nil then
|
||||
diagnosis_opts.severity["min"] = opts.severity_limit
|
||||
end
|
||||
if opts.severity_bound ~= nil then
|
||||
diagnosis_opts.severity["max"] = opts.severity_bound
|
||||
end
|
||||
end
|
||||
|
||||
opts.root_dir = opts.root_dir == true and vim.loop.cwd() or opts.root_dir
|
||||
|
||||
local bufnr_name_map = {}
|
||||
local filter_diag = function(diagnostic)
|
||||
if bufnr_name_map[diagnostic.bufnr] == nil then
|
||||
bufnr_name_map[diagnostic.bufnr] = vim.api.nvim_buf_get_name(diagnostic.bufnr)
|
||||
end
|
||||
|
||||
local root_dir_test = not opts.root_dir
|
||||
or string.sub(bufnr_name_map[diagnostic.bufnr], 1, #opts.root_dir) == opts.root_dir
|
||||
local listed_test = not opts.no_unlisted or vim.api.nvim_buf_get_option(diagnostic.bufnr, "buflisted")
|
||||
|
||||
return root_dir_test and listed_test
|
||||
end
|
||||
|
||||
local preprocess_diag = function(diagnostic)
|
||||
return {
|
||||
bufnr = diagnostic.bufnr,
|
||||
filename = bufnr_name_map[diagnostic.bufnr],
|
||||
lnum = diagnostic.lnum + 1,
|
||||
col = diagnostic.col + 1,
|
||||
text = vim.trim(diagnostic.message:gsub("[\n]", "")),
|
||||
type = severities[diagnostic.severity] or severities[1],
|
||||
}
|
||||
end
|
||||
|
||||
for _, d in ipairs(vim.diagnostic.get(opts.bufnr, diagnosis_opts)) do
|
||||
if filter_diag(d) then
|
||||
table.insert(items, preprocess_diag(d))
|
||||
end
|
||||
end
|
||||
|
||||
-- sort results by bufnr (prioritize cur buf), severity, lnum
|
||||
table.sort(items, function(a, b)
|
||||
if a.bufnr == b.bufnr then
|
||||
if a.type == b.type then
|
||||
return a.lnum < b.lnum
|
||||
else
|
||||
return a.type < b.type
|
||||
end
|
||||
else
|
||||
-- prioritize for current bufnr
|
||||
if a.bufnr == current_buf then
|
||||
return true
|
||||
end
|
||||
if b.bufnr == current_buf then
|
||||
return false
|
||||
end
|
||||
return a.bufnr < b.bufnr
|
||||
end
|
||||
end)
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
diagnostics.get = function(opts)
|
||||
if opts.bufnr ~= 0 then
|
||||
opts.bufnr = nil
|
||||
end
|
||||
if opts.bufnr == nil then
|
||||
opts.path_display = vim.F.if_nil(opts.path_display, {})
|
||||
end
|
||||
if type(opts.bufnr) == "string" then
|
||||
opts.bufnr = tonumber(opts.bufnr)
|
||||
end
|
||||
|
||||
local locations = diagnostics_to_tbl(opts)
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
utils.notify("builtin.diagnostics", {
|
||||
msg = "No diagnostics found",
|
||||
level = "INFO",
|
||||
return require("telescope.builtin").diagnostics
|
||||
end,
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
opts.path_display = vim.F.if_nil(opts.path_display, "hidden")
|
||||
pickers.new(opts, {
|
||||
prompt_title = opts.bufnr == nil and "Workspace Diagnostics" or "Document Diagnostics",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_diagnostics(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "type",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
}):find()
|
||||
end
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = opts or {}
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(diagnostics)
|
||||
return m
|
||||
|
||||
@@ -1,522 +1,17 @@
|
||||
local action_state = require "telescope.actions.state"
|
||||
local action_set = require "telescope.actions.set"
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local previewers = require "telescope.previewers"
|
||||
local sorters = require "telescope.sorters"
|
||||
local m = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
local utils = require "telescope.utils"
|
||||
local conf = require("telescope.config").values
|
||||
local log = require "telescope.log"
|
||||
|
||||
local Path = require "plenary.path"
|
||||
|
||||
local flatten = vim.tbl_flatten
|
||||
local filter = vim.tbl_filter
|
||||
|
||||
local files = {}
|
||||
|
||||
local escape_chars = function(string)
|
||||
return string.gsub(string, "[%(|%)|\\|%[|%]|%-|%{%}|%?|%+|%*|%^|%$|%.]", {
|
||||
["\\"] = "\\\\",
|
||||
["-"] = "\\-",
|
||||
["("] = "\\(",
|
||||
[")"] = "\\)",
|
||||
["["] = "\\[",
|
||||
["]"] = "\\]",
|
||||
["{"] = "\\{",
|
||||
["}"] = "\\}",
|
||||
["?"] = "\\?",
|
||||
["+"] = "\\+",
|
||||
["*"] = "\\*",
|
||||
["^"] = "\\^",
|
||||
["$"] = "\\$",
|
||||
["."] = "\\.",
|
||||
})
|
||||
end
|
||||
|
||||
-- Special keys:
|
||||
-- opts.search_dirs -- list of directory to search in
|
||||
-- opts.grep_open_files -- boolean to restrict search to open files
|
||||
files.live_grep = function(opts)
|
||||
local vimgrep_arguments = opts.vimgrep_arguments or conf.vimgrep_arguments
|
||||
local search_dirs = opts.search_dirs
|
||||
local grep_open_files = opts.grep_open_files
|
||||
opts.cwd = opts.cwd and vim.fn.expand(opts.cwd) or vim.loop.cwd()
|
||||
|
||||
local filelist = {}
|
||||
|
||||
if grep_open_files then
|
||||
local bufnrs = filter(function(b)
|
||||
if 1 ~= vim.fn.buflisted(b) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end, vim.api.nvim_list_bufs())
|
||||
if not next(bufnrs) then
|
||||
return
|
||||
end
|
||||
|
||||
for _, bufnr in ipairs(bufnrs) do
|
||||
local file = vim.api.nvim_buf_get_name(bufnr)
|
||||
table.insert(filelist, Path:new(file):make_relative(opts.cwd))
|
||||
end
|
||||
elseif search_dirs then
|
||||
for i, path in ipairs(search_dirs) do
|
||||
search_dirs[i] = vim.fn.expand(path)
|
||||
end
|
||||
end
|
||||
|
||||
local additional_args = {}
|
||||
if opts.additional_args ~= nil and type(opts.additional_args) == "function" then
|
||||
additional_args = opts.additional_args(opts)
|
||||
end
|
||||
|
||||
if opts.type_filter then
|
||||
additional_args[#additional_args + 1] = "--type=" .. opts.type_filter
|
||||
end
|
||||
|
||||
if type(opts.glob_pattern) == "string" then
|
||||
additional_args[#additional_args + 1] = "--glob=" .. opts.glob_pattern
|
||||
elseif type(opts.glob_pattern) == "table" then
|
||||
for i = 1, #opts.glob_pattern do
|
||||
additional_args[#additional_args + 1] = "--glob=" .. opts.glob_pattern[i]
|
||||
end
|
||||
end
|
||||
|
||||
local live_grepper = finders.new_job(function(prompt)
|
||||
-- TODO: Probably could add some options for smart case and whatever else rg offers.
|
||||
|
||||
if not prompt or prompt == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
local search_list = {}
|
||||
|
||||
if search_dirs then
|
||||
table.insert(search_list, search_dirs)
|
||||
end
|
||||
|
||||
if grep_open_files then
|
||||
search_list = filelist
|
||||
end
|
||||
|
||||
return flatten { vimgrep_arguments, additional_args, "--", prompt, search_list }
|
||||
end, opts.entry_maker or make_entry.gen_from_vimgrep(opts), opts.max_results, opts.cwd)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Live Grep",
|
||||
finder = live_grepper,
|
||||
previewer = conf.grep_previewer(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),
|
||||
attach_mappings = function(_, map)
|
||||
map("i", "<c-space>", function(prompt_bufnr)
|
||||
local line = action_state.get_current_line()
|
||||
require("telescope.actions.generate").refine(prompt_bufnr, {
|
||||
prompt_title = "Find Word (" .. line .. ")",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
})
|
||||
end)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
-- Special keys:
|
||||
-- opts.search -- the string to search.
|
||||
-- opts.search_dirs -- list of directory to search in
|
||||
-- opts.use_regex -- special characters won't be escaped
|
||||
files.grep_string = function(opts)
|
||||
-- TODO: This should probably check your visual selection as well, if you've got one
|
||||
|
||||
local vimgrep_arguments = opts.vimgrep_arguments or conf.vimgrep_arguments
|
||||
local search_dirs = opts.search_dirs
|
||||
local word = opts.search or vim.fn.expand "<cword>"
|
||||
local search = opts.use_regex and word or escape_chars(word)
|
||||
local word_match = opts.word_match
|
||||
opts.entry_maker = opts.entry_maker or make_entry.gen_from_vimgrep(opts)
|
||||
|
||||
local title_word = word:gsub("\n", "\\n")
|
||||
|
||||
local additional_args = {}
|
||||
if opts.additional_args ~= nil and type(opts.additional_args) == "function" then
|
||||
additional_args = opts.additional_args(opts)
|
||||
end
|
||||
|
||||
local args = flatten {
|
||||
vimgrep_arguments,
|
||||
additional_args,
|
||||
word_match,
|
||||
"--",
|
||||
search,
|
||||
}
|
||||
|
||||
if search_dirs then
|
||||
for _, path in ipairs(search_dirs) do
|
||||
table.insert(args, vim.fn.expand(path))
|
||||
end
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Find Word (" .. title_word .. ")",
|
||||
finder = finders.new_oneshot_job(args, opts),
|
||||
previewer = conf.grep_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.find_files = function(opts)
|
||||
local find_command = (function()
|
||||
if opts.find_command then
|
||||
if type(opts.find_command) == "function" then
|
||||
return opts.find_command(opts)
|
||||
end
|
||||
return opts.find_command
|
||||
elseif 1 == vim.fn.executable "fd" then
|
||||
return { "fd", "--type", "f" }
|
||||
elseif 1 == vim.fn.executable "fdfind" then
|
||||
return { "fdfind", "--type", "f" }
|
||||
elseif 1 == vim.fn.executable "rg" then
|
||||
return { "rg", "--files" }
|
||||
elseif 1 == vim.fn.executable "find" and vim.fn.has "win32" == 0 then
|
||||
return { "find", ".", "-type", "f" }
|
||||
elseif 1 == vim.fn.executable "where" then
|
||||
return { "where", "/r", ".", "*" }
|
||||
end
|
||||
end)()
|
||||
|
||||
if not find_command then
|
||||
utils.notify("builtin.find_files", {
|
||||
msg = "You need to install either find, fd, or rg",
|
||||
utils.notify("builtin", {
|
||||
msg = string.format(
|
||||
'You are using an internal interface. Do not use `require("telescope.builtin.files").%s`,'
|
||||
.. ' please use `require("telescope.builtin").%s`! We will remove this endpoint soon!',
|
||||
k,
|
||||
k
|
||||
),
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local command = find_command[1]
|
||||
local hidden = opts.hidden
|
||||
local no_ignore = opts.no_ignore
|
||||
local no_ignore_parent = opts.no_ignore_parent
|
||||
local follow = opts.follow
|
||||
local search_dirs = opts.search_dirs
|
||||
local search_file = opts.search_file
|
||||
|
||||
if search_dirs then
|
||||
for k, v in pairs(search_dirs) do
|
||||
search_dirs[k] = vim.fn.expand(v)
|
||||
end
|
||||
end
|
||||
|
||||
if command == "fd" or command == "fdfind" or command == "rg" then
|
||||
if hidden then
|
||||
table.insert(find_command, "--hidden")
|
||||
end
|
||||
if no_ignore then
|
||||
table.insert(find_command, "--no-ignore")
|
||||
end
|
||||
if no_ignore_parent then
|
||||
table.insert(find_command, "--no-ignore-parent")
|
||||
end
|
||||
if follow then
|
||||
table.insert(find_command, "-L")
|
||||
end
|
||||
if search_file then
|
||||
if command == "rg" then
|
||||
table.insert(find_command, "-g")
|
||||
table.insert(find_command, "*" .. search_file .. "*")
|
||||
else
|
||||
table.insert(find_command, search_file)
|
||||
end
|
||||
end
|
||||
if search_dirs then
|
||||
if command ~= "rg" and not search_file then
|
||||
table.insert(find_command, ".")
|
||||
end
|
||||
for _, v in pairs(search_dirs) do
|
||||
table.insert(find_command, v)
|
||||
end
|
||||
end
|
||||
elseif command == "find" then
|
||||
if not hidden then
|
||||
table.insert(find_command, { "-not", "-path", "*/.*" })
|
||||
find_command = flatten(find_command)
|
||||
end
|
||||
if no_ignore ~= nil then
|
||||
log.warn "The `no_ignore` key is not available for the `find` command in `find_files`."
|
||||
end
|
||||
if no_ignore_parent ~= nil then
|
||||
log.warn "The `no_ignore_parent` key is not available for the `find` command in `find_files`."
|
||||
end
|
||||
if follow then
|
||||
table.insert(find_command, 2, "-L")
|
||||
end
|
||||
if search_file then
|
||||
table.insert(find_command, "-name")
|
||||
table.insert(find_command, "*" .. search_file .. "*")
|
||||
end
|
||||
if search_dirs then
|
||||
table.remove(find_command, 2)
|
||||
for _, v in pairs(search_dirs) do
|
||||
table.insert(find_command, 2, v)
|
||||
end
|
||||
end
|
||||
elseif command == "where" then
|
||||
if hidden ~= nil then
|
||||
log.warn "The `hidden` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if no_ignore ~= nil then
|
||||
log.warn "The `no_ignore` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if no_ignore_parent ~= nil then
|
||||
log.warn "The `no_ignore_parent` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if follow ~= nil then
|
||||
log.warn "The `follow` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if search_dirs ~= nil then
|
||||
log.warn "The `search_dirs` key is not available for the Windows `where` command in `find_files`."
|
||||
end
|
||||
if search_file ~= nil then
|
||||
log.warn "The `search_file` key is not available for the Windows `where` command in `find_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)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Find Files",
|
||||
finder = finders.new_oneshot_job(find_command, opts),
|
||||
previewer = conf.file_previewer(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
}):find()
|
||||
end
|
||||
|
||||
local function prepare_match(entry, kind)
|
||||
local entries = {}
|
||||
|
||||
if entry.node then
|
||||
table.insert(entries, entry)
|
||||
else
|
||||
for name, item in pairs(entry) do
|
||||
vim.list_extend(entries, prepare_match(item, name))
|
||||
end
|
||||
end
|
||||
|
||||
return entries
|
||||
end
|
||||
|
||||
-- TODO: finish docs for opts.show_line
|
||||
files.treesitter = function(opts)
|
||||
opts.show_line = vim.F.if_nil(opts.show_line, true)
|
||||
|
||||
local has_nvim_treesitter, _ = pcall(require, "nvim-treesitter")
|
||||
if not has_nvim_treesitter then
|
||||
utils.notify("builtin.treesitter", {
|
||||
msg = "User need to install nvim-treesitter needs to be installed",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
if not parsers.has_parser(parsers.get_buf_lang(opts.bufnr)) then
|
||||
utils.notify("builtin.treesitter", {
|
||||
msg = "No parser for the current buffer",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local ts_locals = require "nvim-treesitter.locals"
|
||||
local results = {}
|
||||
for _, definition in ipairs(ts_locals.get_definitions(opts.bufnr)) do
|
||||
local entries = prepare_match(ts_locals.get_local_nodes(definition))
|
||||
for _, entry in ipairs(entries) do
|
||||
entry.kind = vim.F.if_nil(entry.kind, "")
|
||||
table.insert(results, entry)
|
||||
end
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(results) then
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Treesitter Symbols",
|
||||
finder = finders.new_table {
|
||||
results = results,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_treesitter(opts),
|
||||
},
|
||||
previewer = conf.grep_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "kind",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.current_buffer_fuzzy_find = function(opts)
|
||||
-- All actions are on the current buffer
|
||||
local filename = vim.fn.expand(vim.api.nvim_buf_get_name(opts.bufnr))
|
||||
local filetype = vim.api.nvim_buf_get_option(opts.bufnr, "filetype")
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(opts.bufnr, 0, -1, false)
|
||||
local lines_with_numbers = {}
|
||||
|
||||
for lnum, line in ipairs(lines) do
|
||||
table.insert(lines_with_numbers, {
|
||||
lnum = lnum,
|
||||
bufnr = opts.bufnr,
|
||||
filename = filename,
|
||||
text = line,
|
||||
})
|
||||
end
|
||||
|
||||
local ts_ok, ts_parsers = pcall(require, "nvim-treesitter.parsers")
|
||||
if ts_ok then
|
||||
filetype = ts_parsers.ft_to_lang(filetype)
|
||||
end
|
||||
local _, ts_configs = pcall(require, "nvim-treesitter.configs")
|
||||
|
||||
local parser_ok, parser = pcall(vim.treesitter.get_parser, opts.bufnr, filetype)
|
||||
local query_ok, query = pcall(vim.treesitter.get_query, filetype, "highlights")
|
||||
if parser_ok and query_ok and ts_ok and ts_configs.is_enabled("highlight", filetype, opts.bufnr) then
|
||||
local root = parser:parse()[1]:root()
|
||||
|
||||
local highlighter = vim.treesitter.highlighter.new(parser)
|
||||
local highlighter_query = highlighter:get_query(filetype)
|
||||
|
||||
local line_highlights = setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
local obj = {}
|
||||
rawset(t, k, obj)
|
||||
return obj
|
||||
return require("telescope.builtin")[k]
|
||||
end,
|
||||
})
|
||||
for id, node in query:iter_captures(root, opts.bufnr, 0, -1) do
|
||||
local hl = highlighter_query:_get_hl_from_capture(id)
|
||||
if hl and type(hl) ~= "number" then
|
||||
local row1, col1, row2, col2 = node:range()
|
||||
|
||||
if row1 == row2 then
|
||||
local row = row1 + 1
|
||||
|
||||
for index = col1, col2 do
|
||||
line_highlights[row][index] = hl
|
||||
end
|
||||
else
|
||||
local row = row1 + 1
|
||||
for index = col1, #lines[row] do
|
||||
line_highlights[row][index] = hl
|
||||
end
|
||||
|
||||
while row < row2 + 1 do
|
||||
row = row + 1
|
||||
|
||||
for index = 0, #(lines[row] or {}) do
|
||||
line_highlights[row][index] = hl
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
opts.line_highlights = line_highlights
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Current Buffer Fuzzy",
|
||||
finder = finders.new_table {
|
||||
results = lines_with_numbers,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_buffer_lines(opts),
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
previewer = conf.grep_previewer(opts),
|
||||
attach_mappings = function()
|
||||
action_set.select:enhance {
|
||||
post = function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
|
||||
end,
|
||||
}
|
||||
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.tags = function(opts)
|
||||
local tagfiles = opts.ctags_file and { opts.ctags_file } or vim.fn.tagfiles()
|
||||
for i, ctags_file in ipairs(tagfiles) do
|
||||
tagfiles[i] = vim.fn.expand(ctags_file, true)
|
||||
end
|
||||
if vim.tbl_isempty(tagfiles) then
|
||||
utils.notify("builtin.tags", {
|
||||
msg = "No tags file found. Create one with ctags -R",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_ctags(opts))
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Tags",
|
||||
finder = finders.new_oneshot_job(flatten { "cat", tagfiles }, opts),
|
||||
previewer = previewers.ctags.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function()
|
||||
action_set.select:enhance {
|
||||
post = function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
if not selection then
|
||||
return
|
||||
end
|
||||
|
||||
if selection.scode then
|
||||
-- un-escape / then escape required
|
||||
-- special chars for vim.fn.search()
|
||||
-- ] ~ *
|
||||
local scode = selection.scode:gsub([[\/]], "/"):gsub("[%]~*]", function(x)
|
||||
return "\\" .. x
|
||||
end)
|
||||
|
||||
vim.cmd "norm! gg"
|
||||
vim.fn.search(scode)
|
||||
vim.cmd "norm! zz"
|
||||
else
|
||||
vim.api.nvim_win_set_cursor(0, { selection.lnum, 0 })
|
||||
end
|
||||
end,
|
||||
}
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
files.current_buffer_tags = function(opts)
|
||||
return files.tags(vim.tbl_extend("force", {
|
||||
prompt_title = "Current Buffer Tags",
|
||||
only_current_file = true,
|
||||
path_display = "hidden",
|
||||
}, opts))
|
||||
end
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(files)
|
||||
return m
|
||||
|
||||
@@ -1,411 +1,17 @@
|
||||
local actions = require "telescope.actions"
|
||||
local action_state = require "telescope.actions.state"
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local previewers = require "telescope.previewers"
|
||||
local m = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
local utils = require "telescope.utils"
|
||||
local entry_display = require "telescope.pickers.entry_display"
|
||||
local strings = require "plenary.strings"
|
||||
local Path = require "plenary.path"
|
||||
|
||||
local conf = require("telescope.config").values
|
||||
|
||||
local git = {}
|
||||
|
||||
git.files = function(opts)
|
||||
if opts.is_bare then
|
||||
utils.notify("builtin.git_files", {
|
||||
msg = "This operation must be run in a work tree",
|
||||
utils.notify("builtin", {
|
||||
msg = string.format(
|
||||
'You are using an internal interface. Do not use `require("telescope.builtin.git").%s`,'
|
||||
.. ' please use `require("telescope.builtin").git_%s`! We will remove this endpoint soon!',
|
||||
k,
|
||||
k
|
||||
),
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local show_untracked = vim.F.if_nil(opts.show_untracked, false)
|
||||
local recurse_submodules = vim.F.if_nil(opts.recurse_submodules, false)
|
||||
if show_untracked and recurse_submodules then
|
||||
utils.notify("builtin.git_files", {
|
||||
msg = "Git does not support both --others and --recurse-submodules",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
-- By creating the entry maker after the cwd options,
|
||||
-- we ensure the maker uses the cwd options when being created.
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_file(opts))
|
||||
local git_command = vim.F.if_nil(opts.git_command, { "git", "ls-files", "--exclude-standard", "--cached" })
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Files",
|
||||
finder = finders.new_oneshot_job(
|
||||
vim.tbl_flatten {
|
||||
git_command,
|
||||
show_untracked and "--others" or nil,
|
||||
recurse_submodules and "--recurse-submodules" or nil,
|
||||
},
|
||||
opts
|
||||
),
|
||||
previewer = conf.file_previewer(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.commits = function(opts)
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
|
||||
local git_command = vim.F.if_nil(opts.git_command, { "git", "log", "--pretty=oneline", "--abbrev-commit", "--", "." })
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Commits",
|
||||
finder = finders.new_oneshot_job(git_command, opts),
|
||||
previewer = {
|
||||
previewers.git_commit_diff_to_parent.new(opts),
|
||||
previewers.git_commit_diff_to_head.new(opts),
|
||||
previewers.git_commit_diff_as_was.new(opts),
|
||||
previewers.git_commit_message.new(opts),
|
||||
},
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function(_, map)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
map("i", "<c-r>m", actions.git_reset_mixed)
|
||||
map("n", "<c-r>m", actions.git_reset_mixed)
|
||||
map("i", "<c-r>s", actions.git_reset_soft)
|
||||
map("n", "<c-r>s", actions.git_reset_soft)
|
||||
map("i", "<c-r>h", actions.git_reset_hard)
|
||||
map("n", "<c-r>h", actions.git_reset_hard)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.stash = function(opts)
|
||||
opts.show_branch = vim.F.if_nil(opts.show_branch, true)
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_stash(opts))
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Stash",
|
||||
finder = finders.new_oneshot_job(
|
||||
vim.tbl_flatten {
|
||||
"git",
|
||||
"--no-pager",
|
||||
"stash",
|
||||
"list",
|
||||
},
|
||||
opts
|
||||
),
|
||||
previewer = previewers.git_stash_diff.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.select_default:replace(actions.git_apply_stash)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
local get_current_buf_line = function(winnr)
|
||||
local lnum = vim.api.nvim_win_get_cursor(winnr)[1]
|
||||
return vim.trim(vim.api.nvim_buf_get_lines(vim.api.nvim_win_get_buf(winnr), lnum - 1, lnum, false)[1])
|
||||
end
|
||||
|
||||
git.bcommits = function(opts)
|
||||
opts.current_line = (opts.current_file == nil) and get_current_buf_line(opts.winnr) or nil
|
||||
opts.current_file = vim.F.if_nil(opts.current_file, vim.api.nvim_buf_get_name(opts.bufnr))
|
||||
opts.entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_commits(opts))
|
||||
local git_command = vim.F.if_nil(
|
||||
opts.git_command,
|
||||
{ "git", "log", "--pretty=oneline", "--abbrev-commit", "--follow" }
|
||||
)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git BCommits",
|
||||
finder = finders.new_oneshot_job(
|
||||
vim.tbl_flatten {
|
||||
git_command,
|
||||
opts.current_file,
|
||||
},
|
||||
opts
|
||||
),
|
||||
previewer = {
|
||||
previewers.git_commit_diff_to_parent.new(opts),
|
||||
previewers.git_commit_diff_to_head.new(opts),
|
||||
previewers.git_commit_diff_as_was.new(opts),
|
||||
previewers.git_commit_message.new(opts),
|
||||
},
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.select_default:replace(actions.git_checkout_current_buffer)
|
||||
local transfrom_file = function()
|
||||
return opts.current_file and Path:new(opts.current_file):make_relative(opts.cwd) or ""
|
||||
end
|
||||
|
||||
local get_buffer_of_orig = function(selection)
|
||||
local value = selection.value .. ":" .. transfrom_file()
|
||||
local content = utils.get_os_command_output({ "git", "--no-pager", "show", value }, opts.cwd)
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, content)
|
||||
vim.api.nvim_buf_set_name(bufnr, "Original")
|
||||
return bufnr
|
||||
end
|
||||
|
||||
local vimdiff = function(selection, command)
|
||||
local ft = vim.bo.filetype
|
||||
vim.cmd "diffthis"
|
||||
|
||||
local bufnr = get_buffer_of_orig(selection)
|
||||
vim.cmd(string.format("%s %s", command, bufnr))
|
||||
vim.bo.filetype = ft
|
||||
vim.cmd "diffthis"
|
||||
|
||||
vim.api.nvim_create_autocmd("WinClosed", {
|
||||
buffer = bufnr,
|
||||
nested = true,
|
||||
once = true,
|
||||
callback = function()
|
||||
vim.api.nvim_buf_delete(bufnr, { force = true })
|
||||
return require("telescope.builtin")["git_" .. k]
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
actions.select_vertical:replace(function(prompt_bufnr)
|
||||
actions.close(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry()
|
||||
vimdiff(selection, "leftabove vert sbuffer")
|
||||
end)
|
||||
|
||||
actions.select_horizontal:replace(function(prompt_bufnr)
|
||||
actions.close(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry()
|
||||
vimdiff(selection, "belowright sbuffer")
|
||||
end)
|
||||
|
||||
actions.select_tab:replace(function(prompt_bufnr)
|
||||
actions.close(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry()
|
||||
vim.cmd("tabedit " .. transfrom_file())
|
||||
vimdiff(selection, "leftabove vert sbuffer")
|
||||
end)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.branches = function(opts)
|
||||
local format = "%(HEAD)"
|
||||
.. "%(refname)"
|
||||
.. "%(authorname)"
|
||||
.. "%(upstream:lstrip=2)"
|
||||
.. "%(committerdate:format-local:%Y/%m/%d %H:%M:%S)"
|
||||
local output = utils.get_os_command_output(
|
||||
{ "git", "for-each-ref", "--perl", "--format", format, opts.pattern },
|
||||
opts.cwd
|
||||
)
|
||||
|
||||
local results = {}
|
||||
local widths = {
|
||||
name = 0,
|
||||
authorname = 0,
|
||||
upstream = 0,
|
||||
committerdate = 0,
|
||||
}
|
||||
local unescape_single_quote = function(v)
|
||||
return string.gsub(v, "\\([\\'])", "%1")
|
||||
end
|
||||
local parse_line = function(line)
|
||||
local fields = vim.split(string.sub(line, 2, -2), "''", true)
|
||||
local entry = {
|
||||
head = fields[1],
|
||||
refname = unescape_single_quote(fields[2]),
|
||||
authorname = unescape_single_quote(fields[3]),
|
||||
upstream = unescape_single_quote(fields[4]),
|
||||
committerdate = fields[5],
|
||||
}
|
||||
local prefix
|
||||
if vim.startswith(entry.refname, "refs/remotes/") then
|
||||
prefix = "refs/remotes/"
|
||||
elseif vim.startswith(entry.refname, "refs/heads/") then
|
||||
prefix = "refs/heads/"
|
||||
else
|
||||
return
|
||||
end
|
||||
local index = 1
|
||||
if entry.head ~= "*" then
|
||||
index = #results + 1
|
||||
end
|
||||
|
||||
entry.name = string.sub(entry.refname, string.len(prefix) + 1)
|
||||
for key, value in pairs(widths) do
|
||||
widths[key] = math.max(value, strings.strdisplaywidth(entry[key] or ""))
|
||||
end
|
||||
if string.len(entry.upstream) > 0 then
|
||||
widths.upstream_indicator = 2
|
||||
end
|
||||
table.insert(results, index, entry)
|
||||
end
|
||||
for _, line in ipairs(output) do
|
||||
parse_line(line)
|
||||
end
|
||||
if #results == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local displayer = entry_display.create {
|
||||
separator = " ",
|
||||
items = {
|
||||
{ width = 1 },
|
||||
{ width = widths.name },
|
||||
{ width = widths.authorname },
|
||||
{ width = widths.upstream_indicator },
|
||||
{ width = widths.upstream },
|
||||
{ width = widths.committerdate },
|
||||
},
|
||||
}
|
||||
|
||||
local make_display = function(entry)
|
||||
return displayer {
|
||||
{ entry.head },
|
||||
{ entry.name, "TelescopeResultsIdentifier" },
|
||||
{ entry.authorname },
|
||||
{ string.len(entry.upstream) > 0 and "=>" or "" },
|
||||
{ entry.upstream, "TelescopeResultsIdentifier" },
|
||||
{ entry.committerdate },
|
||||
}
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Branches",
|
||||
finder = finders.new_table {
|
||||
results = results,
|
||||
entry_maker = function(entry)
|
||||
entry.value = entry.name
|
||||
entry.ordinal = entry.name
|
||||
entry.display = make_display
|
||||
return make_entry.set_default_entry_mt(entry, opts)
|
||||
end,
|
||||
},
|
||||
previewer = previewers.git_branch_log.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function(_, map)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
map("i", "<c-t>", actions.git_track_branch)
|
||||
map("n", "<c-t>", actions.git_track_branch)
|
||||
|
||||
map("i", "<c-r>", actions.git_rebase_branch)
|
||||
map("n", "<c-r>", actions.git_rebase_branch)
|
||||
|
||||
map("i", "<c-a>", actions.git_create_branch)
|
||||
map("n", "<c-a>", actions.git_create_branch)
|
||||
|
||||
map("i", "<c-s>", actions.git_switch_branch)
|
||||
map("n", "<c-s>", actions.git_switch_branch)
|
||||
|
||||
map("i", "<c-d>", actions.git_delete_branch)
|
||||
map("n", "<c-d>", actions.git_delete_branch)
|
||||
|
||||
map("i", "<c-y>", actions.git_merge_branch)
|
||||
map("n", "<c-y>", actions.git_merge_branch)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
git.status = function(opts)
|
||||
if opts.is_bare then
|
||||
utils.notify("builtin.git_status", {
|
||||
msg = "This operation must be run in a work tree",
|
||||
level = "ERROR",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local gen_new_finder = function()
|
||||
local expand_dir = vim.F.if_nil(opts.expand_dir, true)
|
||||
local git_cmd = { "git", "status", "-s", "--", "." }
|
||||
|
||||
if expand_dir then
|
||||
table.insert(git_cmd, #git_cmd - 1, "-u")
|
||||
end
|
||||
|
||||
local output = utils.get_os_command_output(git_cmd, opts.cwd)
|
||||
|
||||
if #output == 0 then
|
||||
print "No changes found"
|
||||
utils.notify("builtin.git_status", {
|
||||
msg = "No changes found",
|
||||
level = "WARN",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
return finders.new_table {
|
||||
results = output,
|
||||
entry_maker = vim.F.if_nil(opts.entry_maker, make_entry.gen_from_git_status(opts)),
|
||||
}
|
||||
end
|
||||
|
||||
local initial_finder = gen_new_finder()
|
||||
if not initial_finder then
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "Git Status",
|
||||
finder = initial_finder,
|
||||
previewer = previewers.git_file_diff.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr, map)
|
||||
actions.git_staging_toggle:enhance {
|
||||
post = function()
|
||||
action_state.get_current_picker(prompt_bufnr):refresh(gen_new_finder(), { reset_prompt = true })
|
||||
end,
|
||||
}
|
||||
|
||||
map("i", "<tab>", actions.git_staging_toggle)
|
||||
map("n", "<tab>", actions.git_staging_toggle)
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
local set_opts_cwd = function(opts)
|
||||
if opts.cwd then
|
||||
opts.cwd = vim.fn.expand(opts.cwd)
|
||||
else
|
||||
opts.cwd = vim.loop.cwd()
|
||||
end
|
||||
|
||||
-- Find root of git directory and remove trailing newline characters
|
||||
local git_root, ret = utils.get_os_command_output({ "git", "rev-parse", "--show-toplevel" }, opts.cwd)
|
||||
local use_git_root = vim.F.if_nil(opts.use_git_root, true)
|
||||
|
||||
if ret ~= 0 then
|
||||
local in_worktree = utils.get_os_command_output({ "git", "rev-parse", "--is-inside-work-tree" }, opts.cwd)
|
||||
local in_bare = utils.get_os_command_output({ "git", "rev-parse", "--is-bare-repository" }, opts.cwd)
|
||||
|
||||
if in_worktree[1] ~= "true" and in_bare[1] ~= "true" then
|
||||
error(opts.cwd .. " is not a git directory")
|
||||
elseif in_worktree[1] ~= "true" and in_bare[1] == "true" then
|
||||
opts.is_bare = true
|
||||
end
|
||||
else
|
||||
if use_git_root then
|
||||
opts.cwd = git_root[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = vim.F.if_nil(opts, {})
|
||||
|
||||
set_opts_cwd(opts)
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(git)
|
||||
return m
|
||||
|
||||
@@ -60,7 +60,7 @@ end
|
||||
---@field additional_args function: function(opts) which returns a table of additional arguments to be passed on
|
||||
---@field max_results number: define a upper result value
|
||||
---@field disable_coordinates boolean: don't show the line & row numbers (default: false)
|
||||
builtin.live_grep = require_on_exported_call("telescope.builtin.files").live_grep
|
||||
builtin.live_grep = require_on_exported_call("telescope.builtin.__files").live_grep
|
||||
|
||||
--- Searches for the string under your cursor in your current working directory
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -72,7 +72,7 @@ builtin.live_grep = require_on_exported_call("telescope.builtin.files").live_gre
|
||||
---@field additional_args function: function(opts) which returns a table of additional arguments to be passed on
|
||||
---@field disable_coordinates boolean: don't show the line and row numbers (default: false)
|
||||
---@field only_sort_text boolean: only sort the text, not the file, line or row (default: false)
|
||||
builtin.grep_string = require_on_exported_call("telescope.builtin.files").grep_string
|
||||
builtin.grep_string = require_on_exported_call("telescope.builtin.__files").grep_string
|
||||
|
||||
--- Search for files (respecting .gitignore)
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -84,7 +84,7 @@ builtin.grep_string = require_on_exported_call("telescope.builtin.files").grep_s
|
||||
---@field no_ignore_parent boolean: show files ignored by .gitignore, .ignore, etc. in parent dirs. (default: false)
|
||||
---@field search_dirs table: directory/directories/files to search
|
||||
---@field search_file string: specify a filename to search for
|
||||
builtin.find_files = require_on_exported_call("telescope.builtin.files").find_files
|
||||
builtin.find_files = require_on_exported_call("telescope.builtin.__files").find_files
|
||||
|
||||
--- This is an alias for the `find_files` picker
|
||||
builtin.fd = builtin.find_files
|
||||
@@ -95,12 +95,12 @@ builtin.fd = builtin.find_files
|
||||
---@field show_line boolean: if true, shows the row:column that the result is found at (default: true)
|
||||
---@field bufnr number: specify the buffer number where treesitter should run. (default: current buffer)
|
||||
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
|
||||
builtin.treesitter = require_on_exported_call("telescope.builtin.files").treesitter
|
||||
builtin.treesitter = require_on_exported_call("telescope.builtin.__files").treesitter
|
||||
|
||||
--- Live fuzzy search inside of the currently open buffer
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field skip_empty_lines boolean: if true we dont display empty lines (default: false)
|
||||
builtin.current_buffer_fuzzy_find = require_on_exported_call("telescope.builtin.files").current_buffer_fuzzy_find
|
||||
builtin.current_buffer_fuzzy_find = require_on_exported_call("telescope.builtin.__files").current_buffer_fuzzy_find
|
||||
|
||||
--- Lists tags in current directory with tag location file preview (users are required to run ctags -R to generate tags
|
||||
--- or update when introducing new changes)
|
||||
@@ -110,7 +110,7 @@ builtin.current_buffer_fuzzy_find = require_on_exported_call("telescope.builtin.
|
||||
---@field show_line boolean: if true, shows the content of the line the tag is found on in the picker (default: true)
|
||||
---@field only_sort_tags boolean: if true we will only sort tags (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.tags = require_on_exported_call("telescope.builtin.files").tags
|
||||
builtin.tags = require_on_exported_call("telescope.builtin.__files").tags
|
||||
|
||||
--- Lists all of the tags for the currently open buffer, with a preview
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -119,7 +119,7 @@ builtin.tags = require_on_exported_call("telescope.builtin.files").tags
|
||||
---@field show_line boolean: if true, shows the content of the line the tag is found on in the picker (default: true)
|
||||
---@field only_sort_tags boolean: if true we will only sort tags (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.current_buffer_tags = require_on_exported_call("telescope.builtin.files").current_buffer_tags
|
||||
builtin.current_buffer_tags = require_on_exported_call("telescope.builtin.__files").current_buffer_tags
|
||||
|
||||
--
|
||||
--
|
||||
@@ -137,7 +137,7 @@ builtin.current_buffer_tags = require_on_exported_call("telescope.builtin.files"
|
||||
---@field show_untracked boolean: if true, adds `--others` flag to command and shows untracked files (default: false)
|
||||
---@field recurse_submodules boolean: if true, adds the `--recurse-submodules` flag to command (default: false)
|
||||
---@field git_command table: command that will be exectued. {"git","ls-files","--exclude-standard","--cached"}
|
||||
builtin.git_files = require_on_exported_call("telescope.builtin.git").files
|
||||
builtin.git_files = require_on_exported_call("telescope.builtin.__git").files
|
||||
|
||||
--- Lists commits for current directory with diff preview
|
||||
--- - Default keymaps:
|
||||
@@ -149,7 +149,7 @@ builtin.git_files = require_on_exported_call("telescope.builtin.git").files
|
||||
---@field cwd string: specify the path of the repo
|
||||
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
|
||||
---@field git_command table: command that will be exectued. {"git","log","--pretty=oneline","--abbrev-commit","--","."}
|
||||
builtin.git_commits = require_on_exported_call("telescope.builtin.git").commits
|
||||
builtin.git_commits = require_on_exported_call("telescope.builtin.__git").commits
|
||||
|
||||
--- Lists commits for current buffer with diff preview
|
||||
--- - Default keymaps or your overriden `select_` keys:
|
||||
@@ -162,7 +162,7 @@ builtin.git_commits = require_on_exported_call("telescope.builtin.git").commits
|
||||
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
|
||||
---@field current_file string: specify the current file that should be used for bcommits (default: current buffer)
|
||||
---@field git_command table: command that will be exectued. {"git","log","--pretty=oneline","--abbrev-commit"}
|
||||
builtin.git_bcommits = require_on_exported_call("telescope.builtin.git").bcommits
|
||||
builtin.git_bcommits = require_on_exported_call("telescope.builtin.__git").bcommits
|
||||
|
||||
--- List branches for current directory, with output from `git log --oneline` shown in the preview window
|
||||
--- - Default keymaps:
|
||||
@@ -176,7 +176,7 @@ builtin.git_bcommits = require_on_exported_call("telescope.builtin.git").bcommit
|
||||
---@field cwd string: specify the path of the repo
|
||||
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
|
||||
---@field pattern string: specify the pattern to match all refs
|
||||
builtin.git_branches = require_on_exported_call("telescope.builtin.git").branches
|
||||
builtin.git_branches = require_on_exported_call("telescope.builtin.__git").branches
|
||||
|
||||
--- Lists git status for current directory
|
||||
--- - Default keymaps:
|
||||
@@ -186,7 +186,7 @@ builtin.git_branches = require_on_exported_call("telescope.builtin.git").branche
|
||||
---@field cwd string: specify the path of the repo
|
||||
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
|
||||
---@field git_icons table: string -> string. Matches name with icon (see source code, make_entry.lua git_icon_defaults)
|
||||
builtin.git_status = require_on_exported_call("telescope.builtin.git").status
|
||||
builtin.git_status = require_on_exported_call("telescope.builtin.__git").status
|
||||
|
||||
--- Lists stash items in current repository
|
||||
--- - Default keymaps:
|
||||
@@ -195,7 +195,7 @@ builtin.git_status = require_on_exported_call("telescope.builtin.git").status
|
||||
---@field cwd string: specify the path of the repo
|
||||
---@field use_git_root boolean: if we should use git root as cwd or the cwd (important for submodule) (default: true)
|
||||
---@field show_branch boolean: if we should display the branch name for git stash entries (default: true)
|
||||
builtin.git_stash = require_on_exported_call("telescope.builtin.git").stash
|
||||
builtin.git_stash = require_on_exported_call("telescope.builtin.__git").stash
|
||||
|
||||
--
|
||||
--
|
||||
@@ -207,14 +207,14 @@ builtin.git_stash = require_on_exported_call("telescope.builtin.git").stash
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field include_extensions boolean: if true will show the pickers of the installed extensions (default: false)
|
||||
---@field use_default_opts boolean: if the selected picker should use its default options (default: false)
|
||||
builtin.builtin = require_on_exported_call("telescope.builtin.internal").builtin
|
||||
builtin.builtin = require_on_exported_call("telescope.builtin.__internal").builtin
|
||||
|
||||
--- Opens the previous picker in the identical state (incl. multi selections)
|
||||
--- - Notes:
|
||||
--- - Requires `cache_picker` in setup or when having invoked pickers, see |telescope.defaults.cache_picker|
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field cache_index number: what picker to resume, where 1 denotes most recent (default: 1)
|
||||
builtin.resume = require_on_exported_call("telescope.builtin.internal").resume
|
||||
builtin.resume = require_on_exported_call("telescope.builtin.__internal").resume
|
||||
|
||||
--- Opens a picker over previously cached pickers in their preserved states (incl. multi selections)
|
||||
--- - Default keymaps:
|
||||
@@ -222,12 +222,12 @@ builtin.resume = require_on_exported_call("telescope.builtin.internal").resume
|
||||
--- - Notes:
|
||||
--- - Requires `cache_picker` in setup or when having invoked pickers, see |telescope.defaults.cache_picker|
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.pickers = require_on_exported_call("telescope.builtin.internal").pickers
|
||||
builtin.pickers = require_on_exported_call("telescope.builtin.__internal").pickers
|
||||
|
||||
--- Use the telescope...
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_pluto boolean: we love pluto (default: false, because its a hidden feature)
|
||||
builtin.planets = require_on_exported_call("telescope.builtin.internal").planets
|
||||
builtin.planets = require_on_exported_call("telescope.builtin.__internal").planets
|
||||
|
||||
--- Lists symbols inside of `data/telescope-sources/*.json` found in your runtime path
|
||||
--- or found in `stdpath("data")/telescope/symbols/*.json`. The second path can be customized.
|
||||
@@ -237,12 +237,12 @@ builtin.planets = require_on_exported_call("telescope.builtin.internal").planets
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field symbol_path string: specify the second path. Default: `stdpath("data")/telescope/symbols/*.json`
|
||||
---@field sources table: specify a table of sources you want to load this time
|
||||
builtin.symbols = require_on_exported_call("telescope.builtin.internal").symbols
|
||||
builtin.symbols = require_on_exported_call("telescope.builtin.__internal").symbols
|
||||
|
||||
--- Lists available plugin/user commands and runs them on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_buf_command boolean: show buf local command (Default: true)
|
||||
builtin.commands = require_on_exported_call("telescope.builtin.internal").commands
|
||||
builtin.commands = require_on_exported_call("telescope.builtin.__internal").commands
|
||||
|
||||
--- Lists items in the quickfix list, jumps to location on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -250,58 +250,58 @@ builtin.commands = require_on_exported_call("telescope.builtin.internal").comman
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
---@field nr number: specify the quickfix list number
|
||||
builtin.quickfix = require_on_exported_call("telescope.builtin.internal").quickfix
|
||||
builtin.quickfix = require_on_exported_call("telescope.builtin.__internal").quickfix
|
||||
|
||||
--- Lists all quickfix lists in your history and open them with `builtin.quickfix`. It seems that neovim
|
||||
--- only keeps the full history for 10 lists
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.quickfixhistory = require_on_exported_call("telescope.builtin.internal").quickfixhistory
|
||||
builtin.quickfixhistory = require_on_exported_call("telescope.builtin.__internal").quickfixhistory
|
||||
|
||||
--- Lists items from the current window's location list, jumps to location on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.loclist = require_on_exported_call("telescope.builtin.internal").loclist
|
||||
builtin.loclist = require_on_exported_call("telescope.builtin.__internal").loclist
|
||||
|
||||
--- Lists previously open files, opens on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field only_cwd boolean: show only files in the cwd (default: false)
|
||||
---@field cwd_only boolean: alias for only_cwd
|
||||
builtin.oldfiles = require_on_exported_call("telescope.builtin.internal").oldfiles
|
||||
builtin.oldfiles = require_on_exported_call("telescope.builtin.__internal").oldfiles
|
||||
|
||||
--- Lists commands that were executed recently, and reruns them on `<cr>`
|
||||
--- - Default keymaps:
|
||||
--- - `<C-e>`: open the command line with the text of the currently selected result populated in it
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.command_history = require_on_exported_call("telescope.builtin.internal").command_history
|
||||
builtin.command_history = require_on_exported_call("telescope.builtin.__internal").command_history
|
||||
|
||||
--- Lists searches that were executed recently, and reruns them on `<cr>`
|
||||
--- - Default keymaps:
|
||||
--- - `<C-e>`: open a search window with the text of the currently selected search result populated in it
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.search_history = require_on_exported_call("telescope.builtin.internal").search_history
|
||||
builtin.search_history = require_on_exported_call("telescope.builtin.__internal").search_history
|
||||
|
||||
--- Lists vim options, allows you to edit the current value on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.vim_options = require_on_exported_call("telescope.builtin.internal").vim_options
|
||||
builtin.vim_options = require_on_exported_call("telescope.builtin.__internal").vim_options
|
||||
|
||||
--- Lists available help tags and opens a new window with the relevant help info on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field lang string: specify language (default: vim.o.helplang)
|
||||
---@field fallback boolean: fallback to en if language isn't installed (default: true)
|
||||
builtin.help_tags = require_on_exported_call("telescope.builtin.internal").help_tags
|
||||
builtin.help_tags = require_on_exported_call("telescope.builtin.__internal").help_tags
|
||||
|
||||
--- Lists manpage entries, opens them in a help window on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field sections table: a list of sections to search, use `{ "ALL" }` to search in all sections (default: { "1" })
|
||||
---@field man_cmd function: that returns the man command. (Default: `apropos ""` on linux, `apropos " "` on macos)
|
||||
builtin.man_pages = require_on_exported_call("telescope.builtin.internal").man_pages
|
||||
builtin.man_pages = require_on_exported_call("telescope.builtin.__internal").man_pages
|
||||
|
||||
--- Lists lua modules and reloads them on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field column_len number: define the max column len for the module name (default: dynamic, longest module name)
|
||||
builtin.reloader = require_on_exported_call("telescope.builtin.internal").reloader
|
||||
builtin.reloader = require_on_exported_call("telescope.builtin.__internal").reloader
|
||||
|
||||
--- Lists open buffers in current neovim instance, opens selected buffer on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -312,58 +312,58 @@ builtin.reloader = require_on_exported_call("telescope.builtin.internal").reload
|
||||
---@field sort_lastused boolean: Sorts current and last buffer to the top and selects the lastused (default: false)
|
||||
---@field sort_mru boolean: Sorts all buffers after most recent used. Not just the current and last one (default: false)
|
||||
---@field bufnr_width number: Defines the width of the buffer numbers in front of the filenames (default: dynamic)
|
||||
builtin.buffers = require_on_exported_call("telescope.builtin.internal").buffers
|
||||
builtin.buffers = require_on_exported_call("telescope.builtin.__internal").buffers
|
||||
|
||||
--- Lists available colorschemes and applies them on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field enable_preview boolean: if true, will preview the selected color
|
||||
builtin.colorscheme = require_on_exported_call("telescope.builtin.internal").colorscheme
|
||||
builtin.colorscheme = require_on_exported_call("telescope.builtin.__internal").colorscheme
|
||||
|
||||
--- Lists vim marks and their value, jumps to the mark on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.marks = require_on_exported_call("telescope.builtin.internal").marks
|
||||
builtin.marks = require_on_exported_call("telescope.builtin.__internal").marks
|
||||
|
||||
--- Lists vim registers, pastes the contents of the register on `<cr>`
|
||||
--- - Default keymaps:
|
||||
--- - `<C-e>`: edit the contents of the currently selected register
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.registers = require_on_exported_call("telescope.builtin.internal").registers
|
||||
builtin.registers = require_on_exported_call("telescope.builtin.__internal").registers
|
||||
|
||||
--- Lists normal mode keymappings, runs the selected keymap on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field modes table: a list of short-named keymap modes to search (default: { "n", "i", "c", "x" })
|
||||
---@field show_plug boolean: if true, the keymaps for which the lhs contains "<Plug>" are also shown (default: true)
|
||||
builtin.keymaps = require_on_exported_call("telescope.builtin.internal").keymaps
|
||||
builtin.keymaps = require_on_exported_call("telescope.builtin.__internal").keymaps
|
||||
|
||||
--- Lists all available filetypes, sets currently open buffer's filetype to selected filetype in Telescope on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.filetypes = require_on_exported_call("telescope.builtin.internal").filetypes
|
||||
builtin.filetypes = require_on_exported_call("telescope.builtin.__internal").filetypes
|
||||
|
||||
--- Lists all available highlights
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.highlights = require_on_exported_call("telescope.builtin.internal").highlights
|
||||
builtin.highlights = require_on_exported_call("telescope.builtin.__internal").highlights
|
||||
|
||||
--- Lists vim autocommands and goes to their declaration on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.autocommands = require_on_exported_call("telescope.builtin.internal").autocommands
|
||||
builtin.autocommands = require_on_exported_call("telescope.builtin.__internal").autocommands
|
||||
|
||||
--- Lists spelling suggestions for the current word under the cursor, replaces word with selected suggestion on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
builtin.spell_suggest = require_on_exported_call("telescope.builtin.internal").spell_suggest
|
||||
builtin.spell_suggest = require_on_exported_call("telescope.builtin.__internal").spell_suggest
|
||||
|
||||
--- Lists the tag stack for the current window, jumps to tag on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.tagstack = require_on_exported_call("telescope.builtin.internal").tagstack
|
||||
builtin.tagstack = require_on_exported_call("telescope.builtin.__internal").tagstack
|
||||
|
||||
--- Lists items from Vim's jumplist, jumps to location on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.jumplist = require_on_exported_call("telescope.builtin.internal").jumplist
|
||||
builtin.jumplist = require_on_exported_call("telescope.builtin.__internal").jumplist
|
||||
|
||||
--
|
||||
--
|
||||
@@ -377,19 +377,19 @@ builtin.jumplist = require_on_exported_call("telescope.builtin.internal").jumpli
|
||||
---@field include_current_line boolean: include current line (default: false)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.lsp_references = require_on_exported_call("telescope.builtin.lsp").references
|
||||
builtin.lsp_references = require_on_exported_call("telescope.builtin.__lsp").references
|
||||
|
||||
--- Lists LSP incoming calls for word under the cursor, jumps to reference on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
builtin.lsp_incoming_calls = require_on_exported_call("telescope.builtin.lsp").incoming_calls
|
||||
builtin.lsp_incoming_calls = require_on_exported_call("telescope.builtin.__lsp").incoming_calls
|
||||
|
||||
--- Lists LSP outgoing calls for word under the cursor, jumps to reference on `<cr>`
|
||||
---@param opts table: options to pass to the picker
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
builtin.lsp_outgoing_calls = require_on_exported_call("telescope.builtin.lsp").outgoing_calls
|
||||
builtin.lsp_outgoing_calls = require_on_exported_call("telescope.builtin.__lsp").outgoing_calls
|
||||
|
||||
--- Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -397,7 +397,7 @@ builtin.lsp_outgoing_calls = require_on_exported_call("telescope.builtin.lsp").o
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.lsp_definitions = require_on_exported_call("telescope.builtin.lsp").definitions
|
||||
builtin.lsp_definitions = require_on_exported_call("telescope.builtin.__lsp").definitions
|
||||
|
||||
--- Goto the definition of the type of the word under the cursor, if there's only one,
|
||||
--- otherwise show all options in Telescope
|
||||
@@ -406,7 +406,7 @@ builtin.lsp_definitions = require_on_exported_call("telescope.builtin.lsp").defi
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.lsp_type_definitions = require("telescope.builtin.lsp").type_definitions
|
||||
builtin.lsp_type_definitions = require("telescope.builtin.__lsp").type_definitions
|
||||
|
||||
--- Goto the implementation of the word under the cursor if there's only one, otherwise show all options in Telescope
|
||||
---@param opts table: options to pass to the picker
|
||||
@@ -414,7 +414,7 @@ builtin.lsp_type_definitions = require("telescope.builtin.lsp").type_definitions
|
||||
---@field show_line boolean: show results text (default: true)
|
||||
---@field trim_text boolean: trim results text (default: false)
|
||||
---@field fname_width number: defines the width of the filename section (default: 30)
|
||||
builtin.lsp_implementations = require_on_exported_call("telescope.builtin.lsp").implementations
|
||||
builtin.lsp_implementations = require_on_exported_call("telescope.builtin.__lsp").implementations
|
||||
|
||||
--- Lists LSP document symbols in the current buffer
|
||||
--- - Default keymaps:
|
||||
@@ -424,7 +424,7 @@ builtin.lsp_implementations = require_on_exported_call("telescope.builtin.lsp").
|
||||
---@field symbols string|table: filter results by symbol kind(s)
|
||||
---@field ignore_symbols string|table: list of symbols to ignore
|
||||
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
|
||||
builtin.lsp_document_symbols = require_on_exported_call("telescope.builtin.lsp").document_symbols
|
||||
builtin.lsp_document_symbols = require_on_exported_call("telescope.builtin.__lsp").document_symbols
|
||||
|
||||
--- Lists LSP document symbols in the current workspace
|
||||
--- - Default keymaps:
|
||||
@@ -435,7 +435,7 @@ builtin.lsp_document_symbols = require_on_exported_call("telescope.builtin.lsp")
|
||||
---@field symbols string|table: filter results by symbol kind(s)
|
||||
---@field ignore_symbols string|table: list of symbols to ignore
|
||||
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
|
||||
builtin.lsp_workspace_symbols = require_on_exported_call("telescope.builtin.lsp").workspace_symbols
|
||||
builtin.lsp_workspace_symbols = require_on_exported_call("telescope.builtin.__lsp").workspace_symbols
|
||||
|
||||
--- Dynamically lists LSP for all workspace symbols
|
||||
--- - Default keymaps:
|
||||
@@ -445,7 +445,7 @@ builtin.lsp_workspace_symbols = require_on_exported_call("telescope.builtin.lsp"
|
||||
---@field symbols string|table: filter results by symbol kind(s)
|
||||
---@field ignore_symbols string|table: list of symbols to ignore
|
||||
---@field symbol_highlights table: string -> string. Matches symbol with hl_group
|
||||
builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.builtin.lsp").dynamic_workspace_symbols
|
||||
builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.builtin.__lsp").dynamic_workspace_symbols
|
||||
|
||||
--
|
||||
--
|
||||
@@ -468,7 +468,7 @@ builtin.lsp_dynamic_workspace_symbols = require_on_exported_call("telescope.buil
|
||||
---@field no_sign boolean: hide DiagnosticSigns from Results (default: false)
|
||||
---@field line_width number: set length of diagnostic entry text in Results
|
||||
---@field namespace number: limit your diagnostics to a specific namespace
|
||||
builtin.diagnostics = require_on_exported_call("telescope.builtin.diagnostics").get
|
||||
builtin.diagnostics = require_on_exported_call("telescope.builtin.__diagnostics").get
|
||||
|
||||
local apply_config = function(mod)
|
||||
local pickers_conf = require("telescope.config").pickers
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,389 +1,17 @@
|
||||
local channel = require("plenary.async.control").channel
|
||||
local action_state = require "telescope.actions.state"
|
||||
local sorters = require "telescope.sorters"
|
||||
local conf = require("telescope.config").values
|
||||
local finders = require "telescope.finders"
|
||||
local make_entry = require "telescope.make_entry"
|
||||
local pickers = require "telescope.pickers"
|
||||
local m = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
local utils = require "telescope.utils"
|
||||
|
||||
local lsp = {}
|
||||
|
||||
lsp.references = function(opts)
|
||||
local filepath = vim.api.nvim_buf_get_name(opts.bufnr)
|
||||
local lnum = vim.api.nvim_win_get_cursor(opts.winnr)[1]
|
||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||
local include_current_line = vim.F.if_nil(opts.include_current_line, false)
|
||||
params.context = { includeDeclaration = vim.F.if_nil(opts.include_declaration, true) }
|
||||
|
||||
vim.lsp.buf_request(opts.bufnr, "textDocument/references", params, function(err, result, ctx, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when finding references: " .. err.message)
|
||||
return
|
||||
end
|
||||
|
||||
local locations = {}
|
||||
if result then
|
||||
local results = vim.lsp.util.locations_to_items(result, vim.lsp.get_client_by_id(ctx.client_id).offset_encoding)
|
||||
if include_current_line then
|
||||
locations = vim.tbl_filter(function(v)
|
||||
-- Remove current line from result
|
||||
return not (v.filename == filepath and v.lnum == lnum)
|
||||
end, vim.F.if_nil(results, {}))
|
||||
else
|
||||
locations = vim.F.if_nil(results, {})
|
||||
end
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
return
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP References",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
local function call_hierarchy(opts, method, title, direction, item)
|
||||
vim.lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error handling " .. title .. ": " .. err)
|
||||
return
|
||||
end
|
||||
|
||||
if not result or vim.tbl_isempty(result) then
|
||||
return
|
||||
end
|
||||
|
||||
local locations = {}
|
||||
for _, ch_call in pairs(result) do
|
||||
local ch_item = ch_call[direction]
|
||||
for _, range in pairs(ch_call.fromRanges) do
|
||||
table.insert(locations, {
|
||||
filename = vim.uri_to_fname(ch_item.uri),
|
||||
text = ch_item.name,
|
||||
lnum = range.start.line + 1,
|
||||
col = range.start.character + 1,
|
||||
utils.notify("builtin", {
|
||||
msg = string.format(
|
||||
'You are using an internal interface. Do not use `require("telescope.builtin.lsp").%s`,'
|
||||
.. ' please use `require("telescope.builtin").lsp_%s`! We will remove this endpoint soon!',
|
||||
k,
|
||||
k
|
||||
),
|
||||
level = "ERROR",
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = title,
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
local function pick_call_hierarchy_item(call_hierarchy_items)
|
||||
if not call_hierarchy_items then
|
||||
return
|
||||
end
|
||||
if #call_hierarchy_items == 1 then
|
||||
return call_hierarchy_items[1]
|
||||
end
|
||||
local items = {}
|
||||
for i, item in pairs(call_hierarchy_items) do
|
||||
local entry = item.detail or item.name
|
||||
table.insert(items, string.format("%d. %s", i, entry))
|
||||
end
|
||||
local choice = vim.fn.inputlist(items)
|
||||
if choice < 1 or choice > #items then
|
||||
return
|
||||
end
|
||||
return choice
|
||||
end
|
||||
|
||||
local function calls(opts, direction)
|
||||
local params = vim.lsp.util.make_position_params()
|
||||
vim.lsp.buf_request(opts.bufnr, "textDocument/prepareCallHierarchy", params, function(err, result)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when preparing call hierarchy: " .. err)
|
||||
return
|
||||
end
|
||||
|
||||
local call_hierarchy_item = pick_call_hierarchy_item(result)
|
||||
if not call_hierarchy_item then
|
||||
return
|
||||
end
|
||||
|
||||
if direction == "from" then
|
||||
call_hierarchy(opts, "callHierarchy/incomingCalls", "LSP Incoming Calls", direction, call_hierarchy_item)
|
||||
else
|
||||
call_hierarchy(opts, "callHierarchy/outgoingCalls", "LSP Outgoing Calls", direction, call_hierarchy_item)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
lsp.incoming_calls = function(opts)
|
||||
calls(opts, "from")
|
||||
end
|
||||
|
||||
lsp.outgoing_calls = function(opts)
|
||||
calls(opts, "to")
|
||||
end
|
||||
|
||||
local function list_or_jump(action, title, opts)
|
||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||
vim.lsp.buf_request(opts.bufnr, action, params, function(err, result, ctx, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when executing " .. action .. " : " .. err.message)
|
||||
return
|
||||
end
|
||||
local flattened_results = {}
|
||||
if result then
|
||||
-- textDocument/definition can return Location or Location[]
|
||||
if not vim.tbl_islist(result) then
|
||||
flattened_results = { result }
|
||||
end
|
||||
|
||||
vim.list_extend(flattened_results, result)
|
||||
end
|
||||
|
||||
local offset_encoding = vim.lsp.get_client_by_id(ctx.client_id).offset_encoding
|
||||
|
||||
if #flattened_results == 0 then
|
||||
return
|
||||
elseif #flattened_results == 1 and opts.jump_type ~= "never" then
|
||||
if opts.jump_type == "tab" then
|
||||
vim.cmd "tabedit"
|
||||
elseif opts.jump_type == "split" then
|
||||
vim.cmd "new"
|
||||
elseif opts.jump_type == "vsplit" then
|
||||
vim.cmd "vnew"
|
||||
end
|
||||
vim.lsp.util.jump_to_location(flattened_results[1], offset_encoding)
|
||||
else
|
||||
local locations = vim.lsp.util.locations_to_items(flattened_results, offset_encoding)
|
||||
pickers.new(opts, {
|
||||
prompt_title = title,
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
lsp.definitions = function(opts)
|
||||
return list_or_jump("textDocument/definition", "LSP Definitions", opts)
|
||||
end
|
||||
|
||||
lsp.type_definitions = function(opts)
|
||||
return list_or_jump("textDocument/typeDefinition", "LSP Type Definitions", opts)
|
||||
end
|
||||
|
||||
lsp.implementations = function(opts)
|
||||
return list_or_jump("textDocument/implementation", "LSP Implementations", opts)
|
||||
end
|
||||
|
||||
lsp.document_symbols = function(opts)
|
||||
local params = vim.lsp.util.make_position_params(opts.winnr)
|
||||
vim.lsp.buf_request(opts.bufnr, "textDocument/documentSymbol", params, function(err, result, _, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when finding document symbols: " .. err.message)
|
||||
return
|
||||
end
|
||||
|
||||
if not result or vim.tbl_isempty(result) then
|
||||
utils.notify("builtin.lsp_document_symbols", {
|
||||
msg = "No results from textDocument/documentSymbol",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local locations = vim.lsp.util.symbols_to_items(result or {}, opts.bufnr) or {}
|
||||
locations = utils.filter_symbols(locations, opts)
|
||||
if locations == nil then
|
||||
-- error message already printed in `utils.filter_symbols`
|
||||
return
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
utils.notify("builtin.lsp_document_symbols", {
|
||||
msg = "No document_symbol locations found",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
opts.path_display = { "hidden" }
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP Document Symbols",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "symbol_type",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
push_cursor_on_edit = true,
|
||||
push_tagstack_on_edit = true,
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
lsp.workspace_symbols = function(opts)
|
||||
local params = { query = opts.query or "" }
|
||||
vim.lsp.buf_request(opts.bufnr, "workspace/symbol", params, function(err, server_result, _, _)
|
||||
if err then
|
||||
vim.api.nvim_err_writeln("Error when finding workspace symbols: " .. err.message)
|
||||
return
|
||||
end
|
||||
|
||||
local locations = vim.lsp.util.symbols_to_items(server_result or {}, opts.bufnr) or {}
|
||||
locations = utils.filter_symbols(locations, opts)
|
||||
if locations == nil then
|
||||
-- error message already printed in `utils.filter_symbols`
|
||||
return
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(locations) then
|
||||
utils.notify("builtin.lsp_workspace_symbols", {
|
||||
msg = "No results from workspace/symbol. Maybe try a different query: "
|
||||
.. "'Telescope lsp_workspace_symbols query=example'",
|
||||
level = "INFO",
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
opts.ignore_filename = vim.F.if_nil(opts.ignore_filename, false)
|
||||
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP Workspace Symbols",
|
||||
finder = finders.new_table {
|
||||
results = locations,
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = conf.prefilter_sorter {
|
||||
tag = "symbol_type",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
},
|
||||
}):find()
|
||||
end)
|
||||
end
|
||||
|
||||
local function get_workspace_symbols_requester(bufnr, opts)
|
||||
local cancel = function() end
|
||||
|
||||
return function(prompt)
|
||||
local tx, rx = channel.oneshot()
|
||||
cancel()
|
||||
_, cancel = vim.lsp.buf_request(bufnr, "workspace/symbol", { query = prompt }, tx)
|
||||
|
||||
-- Handle 0.5 / 0.5.1 handler situation
|
||||
local err, res = rx()
|
||||
assert(not err, err)
|
||||
|
||||
local locations = vim.lsp.util.symbols_to_items(res or {}, bufnr) or {}
|
||||
if not vim.tbl_isempty(locations) then
|
||||
locations = utils.filter_symbols(locations, opts) or {}
|
||||
end
|
||||
return locations
|
||||
end
|
||||
end
|
||||
|
||||
lsp.dynamic_workspace_symbols = function(opts)
|
||||
pickers.new(opts, {
|
||||
prompt_title = "LSP Dynamic Workspace Symbols",
|
||||
finder = finders.new_dynamic {
|
||||
entry_maker = opts.entry_maker or make_entry.gen_from_lsp_symbols(opts),
|
||||
fn = get_workspace_symbols_requester(opts.bufnr, opts),
|
||||
},
|
||||
previewer = conf.qflist_previewer(opts),
|
||||
sorter = sorters.highlighter_only(opts),
|
||||
attach_mappings = function(_, map)
|
||||
map("i", "<c-space>", function(prompt_bufnr)
|
||||
local line = action_state.get_current_line()
|
||||
require("telescope.actions.generate").refine(prompt_bufnr, {
|
||||
prompt_title = "LSP Workspace Symbols (" .. line .. ")",
|
||||
sorter = conf.generic_sorter(opts),
|
||||
})
|
||||
end)
|
||||
return true
|
||||
return require("telescope.builtin")["lsp_" .. k]
|
||||
end,
|
||||
}):find()
|
||||
end
|
||||
|
||||
local function check_capabilities(feature, bufnr)
|
||||
local clients = vim.lsp.buf_get_clients(bufnr)
|
||||
|
||||
local supported_client = false
|
||||
for _, client in pairs(clients) do
|
||||
supported_client = client.server_capabilities[feature]
|
||||
if supported_client then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if supported_client then
|
||||
return true
|
||||
else
|
||||
if #clients == 0 then
|
||||
utils.notify("builtin.lsp_*", {
|
||||
msg = "no client attached",
|
||||
level = "INFO",
|
||||
})
|
||||
else
|
||||
utils.notify("builtin.lsp_*", {
|
||||
msg = "server does not support " .. feature,
|
||||
level = "INFO",
|
||||
})
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local feature_map = {
|
||||
["document_symbols"] = "documentSymbolProvider",
|
||||
["references"] = "referencesProvider",
|
||||
["definitions"] = "definitionProvider",
|
||||
["type_definitions"] = "typeDefinitionProvider",
|
||||
["implementations"] = "implementationProvider",
|
||||
["workspace_symbols"] = "workspaceSymbolProvider",
|
||||
["incoming_calls"] = "callHierarchyProvider",
|
||||
["outgoing_calls"] = "callHierarchyProvider",
|
||||
}
|
||||
|
||||
local function apply_checks(mod)
|
||||
for k, v in pairs(mod) do
|
||||
mod[k] = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local feature_name = feature_map[k]
|
||||
if feature_name and not check_capabilities(feature_name, opts.bufnr) then
|
||||
return
|
||||
end
|
||||
v(opts)
|
||||
end
|
||||
end
|
||||
|
||||
return mod
|
||||
end
|
||||
|
||||
return apply_checks(lsp)
|
||||
return m
|
||||
|
||||
Reference in New Issue
Block a user