summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorSimon Hauser <Simon-Hauser@outlook.de>2022-07-01 22:20:12 +0200
committerGitHub <noreply@github.com>2022-07-01 22:20:12 +0200
commit0621c1c6ba3e561dfb06f58a7b0aedfcd464b590 (patch)
treeab54eeabbb23e167c652d81553a0f3ddc365ae0b /lua
parentbf1a25dbfe9a4368b10354cb46e4b3a0ab0a41a4 (diff)
break: prefix internal files and add deprecation messages (#2032)
Diffstat (limited to 'lua')
-rw-r--r--lua/telescope/builtin/__diagnostics.lua150
-rw-r--r--lua/telescope/builtin/__files.lua522
-rw-r--r--lua/telescope/builtin/__git.lua411
-rw-r--r--lua/telescope/builtin/__internal.lua1318
-rw-r--r--lua/telescope/builtin/__lsp.lua389
-rw-r--r--lua/telescope/builtin/diagnostics.lua163
-rw-r--r--lua/telescope/builtin/files.lua533
-rw-r--r--lua/telescope/builtin/git.lua422
-rw-r--r--lua/telescope/builtin/init.lua100
-rw-r--r--lua/telescope/builtin/internal.lua1329
-rw-r--r--lua/telescope/builtin/lsp.lua406
11 files changed, 2914 insertions, 2829 deletions
diff --git a/lua/telescope/builtin/__diagnostics.lua b/lua/telescope/builtin/__diagnostics.lua
new file mode 100644
index 0000000..2614e36
--- /dev/null
+++ b/lua/telescope/builtin/__diagnostics.lua
@@ -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)
diff --git a/lua/telescope/builtin/__files.lua b/lua/telescope/builtin/__files.lua
new file mode 100644
index 0000000..dddd18a
--- /dev/null
+++ b/lua/telescope/builtin/__files.lua
@@ -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)
diff --git a/lua/telescope/builtin/__git.lua b/lua/telescope/builtin/__git.lua
new file mode 100644
index 0000000..7db45ef
--- /dev/null
+++ b/lua/telescope/builtin/__git.lua
@@ -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)
diff --git a/lua/telescope/builtin/__internal.lua b/lua/telescope/builtin/__internal.lua
new file mode 100644
index 0000000..4277e2e
--- /dev/null
+++ b/lua/telescope/builtin/__internal.lua
@@ -0,0 +1,1318 @@
+local actions = require "telescope.actions"
+local action_set = require "telescope.actions.set"
+local action_state = require "telescope.actions.state"
+local finders = require "telescope.finders"
+local make_entry = require "telescope.make_entry"
+local Path = require "plenary.path"
+local pickers = require "telescope.pickers"
+local previewers = require "telescope.previewers"
+local p_window = require "telescope.pickers.window"
+local sorters = require "telescope.sorters"
+local state = require "telescope.state"
+local utils = require "telescope.utils"
+
+local conf = require("telescope.config").values
+
+local filter = vim.tbl_filter
+
+-- Makes sure aliased options are set correctly
+local function apply_cwd_only_aliases(opts)
+ local has_cwd_only = opts.cwd_only ~= nil
+ local has_only_cwd = opts.only_cwd ~= nil
+
+ if has_only_cwd and not has_cwd_only then
+ -- Internally, use cwd_only
+ opts.cwd_only = opts.only_cwd
+ opts.only_cwd = nil
+ end
+
+ return opts
+end
+
+local internal = {}
+
+internal.builtin = function(opts)
+ opts.include_extensions = vim.F.if_nil(opts.include_extensions, false)
+ opts.use_default_opts = vim.F.if_nil(opts.use_default_opts, false)
+
+ local objs = {}
+
+ for k, v in pairs(require "telescope.builtin") do
+ local debug_info = debug.getinfo(v)
+ table.insert(objs, {
+ filename = string.sub(debug_info.source, 2),
+ text = k,
+ })
+ end
+
+ local title = "Telescope Builtin"
+
+ if opts.include_extensions then
+ title = "Telescope Pickers"
+ for ext, funcs in pairs(require("telescope").extensions) do
+ for func_name, func_obj in pairs(funcs) do
+ -- Only include exported functions whose name doesn't begin with an underscore
+ if type(func_obj) == "function" and string.sub(func_name, 0, 1) ~= "_" then
+ local debug_info = debug.getinfo(func_obj)
+ table.insert(objs, {
+ filename = string.sub(debug_info.source, 2),
+ text = string.format("%s : %s", ext, func_name),
+ })
+ end
+ end
+ end
+ end
+
+ opts.bufnr = vim.api.nvim_get_current_buf()
+ opts.winnr = vim.api.nvim_get_current_win()
+ pickers.new(opts, {
+ prompt_title = title,
+ finder = finders.new_table {
+ results = objs,
+ entry_maker = function(entry)
+ return make_entry.set_default_entry_mt({
+ value = entry,
+ text = entry.text,
+ display = entry.text,
+ ordinal = entry.text,
+ filename = entry.filename,
+ }, opts)
+ end,
+ },
+ previewer = previewers.builtin.new(opts),
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(_)
+ actions.select_default:replace(function(_)
+ local selection = action_state.get_selected_entry()
+ if not selection then
+ utils.__warn_no_selection "builtin.builtin"
+ return
+ end
+
+ -- we do this to avoid any surprises
+ opts.include_extensions = nil
+
+ local picker_opts
+ if not opts.use_default_opts then
+ picker_opts = opts
+ end
+
+ if string.match(selection.text, " : ") then
+ -- Call appropriate function from extensions
+ local split_string = vim.split(selection.text, " : ")
+ local ext = split_string[1]
+ local func = split_string[2]
+ require("telescope").extensions[ext][func](picker_opts)
+ else
+ -- Call appropriate telescope builtin
+ require("telescope.builtin")[selection.text](picker_opts)
+ end
+ end)
+ return true
+ end,
+ }):find()
+end
+
+internal.resume = function(opts)
+ opts = opts or {}
+ opts.cache_index = vim.F.if_nil(opts.cache_index, 1)
+
+ local cached_pickers = state.get_global_key "cached_pickers"
+ if cached_pickers == nil or vim.tbl_isempty(cached_pickers) then
+ utils.notify("builtin.resume", {
+ msg = "No cached picker(s).",
+ level = "INFO",
+ })
+ return
+ end
+ local picker = cached_pickers[opts.cache_index]
+ if picker == nil then
+ utils.notify("builtin.resume", {
+ msg = string.format("Index too large as there are only '%s' pickers cached", #cached_pickers),
+ level = "ERROR",
+ })
+ return
+ end
+ -- reset layout strategy and get_window_options if default as only one is valid
+ -- and otherwise unclear which was actually set
+ if picker.layout_strategy == conf.layout_strategy then
+ picker.layout_strategy = nil
+ end
+ if picker.get_window_options == p_window.get_window_options then
+ picker.get_window_options = nil
+ end
+ picker.cache_picker.index = opts.cache_index
+
+ -- avoid partial `opts.cache_picker` at picker creation
+ if opts.cache_picker ~= false then
+ picker.cache_picker = vim.tbl_extend("keep", opts.cache_picker or {}, picker.cache_picker)
+ else
+ picker.cache_picker.disabled = true
+ end
+ opts.cache_picker = nil
+ picker.previewer = picker.all_previewers
+ if picker.hidden_previewer then
+ picker.hidden_previewer = nil
+ opts.previewer = vim.F.if_nil(opts.previewer, false)
+ end
+ pickers.new(opts, picker):find()
+end
+
+internal.pickers = function(opts)
+ local cached_pickers = state.get_global_key "cached_pickers"
+ if cached_pickers == nil or vim.tbl_isempty(cached_pickers) then
+ utils.notify("builtin.pickers", {
+ msg = "No cached picker(s).",
+ level = "INFO",
+ })
+ return
+ end
+
+ opts = opts or {}
+
+ -- clear cache picker for immediate pickers.new and pass option to resumed picker
+ if opts.cache_picker ~= nil then
+ opts._cache_picker = opts.cache_picker
+ opts.cache_picker = nil
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Pickers",
+ finder = finders.new_table {
+ results = cached_pickers,
+ entry_maker = make_entry.gen_from_picker(opts),
+ },
+ previewer = previewers.pickers.new(opts),
+ sorter = conf.generic_sorter(opts),
+ cache_picker = false,
+ attach_mappings = function(_, map)
+ actions.select_default:replace(function(prompt_bufnr)
+ local current_picker = action_state.get_current_picker(prompt_bufnr)
+ local selection_index = current_picker:get_index(current_picker:get_selection_row())
+ actions.close(prompt_bufnr)
+ opts.cache_picker = opts._cache_picker
+ opts["cache_index"] = selection_index
+ opts["initial_mode"] = cached_pickers[selection_index].initial_mode
+ internal.resume(opts)
+ end)
+ map("i", "<C-x>", actions.remove_selected_picker)
+ map("n", "<C-x>", actions.remove_selected_picker)
+ return true
+ end,
+ }):find()
+end
+
+internal.planets = function(opts)
+ local show_pluto = opts.show_pluto or false
+
+ local sourced_file = require("plenary.debug_utils").sourced_filepath()
+ local base_directory = vim.fn.fnamemodify(sourced_file, ":h:h:h:h")
+
+ local globbed_files = vim.fn.globpath(base_directory .. "/data/memes/planets/", "*", true, true)
+ local acceptable_files = {}
+ for _, v in ipairs(globbed_files) do
+ if show_pluto or not v:find "pluto" then
+ table.insert(acceptable_files, vim.fn.fnamemodify(v, ":t"))
+ end
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Planets",
+ finder = finders.new_table {
+ results = acceptable_files,
+ entry_maker = function(line)
+ return make_entry.set_default_entry_mt({
+ ordinal = line,
+ display = line,
+ filename = base_directory .. "/data/memes/planets/" .. line,
+ }, opts)
+ end,
+ },
+ previewer = previewers.cat.new(opts),
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.planets"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ print("Enjoy astronomy! You viewed:", selection.display)
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.symbols = function(opts)
+ local initial_mode = vim.fn.mode()
+ local files = vim.api.nvim_get_runtime_file("data/telescope-sources/*.json", true)
+ local data_path = (function()
+ if not opts.symbol_path then
+ return Path:new { vim.fn.stdpath "data", "telescope", "symbols" }
+ else
+ return Path:new { opts.symbol_path }
+ end
+ end)()
+ if data_path:exists() then
+ for _, v in ipairs(require("plenary.scandir").scan_dir(data_path:absolute(), { search_pattern = "%.json$" })) do
+ table.insert(files, v)
+ end
+ end
+
+ if #files == 0 then
+ utils.notify("builtin.symbols", {
+ msg = "No sources found! Check out https://github.com/nvim-telescope/telescope-symbols.nvim "
+ .. "for some prebuild symbols or how to create you own symbol source.",
+ level = "ERROR",
+ })
+ return
+ end
+
+ local sources = {}
+ if opts.sources then
+ for _, v in ipairs(files) do
+ for _, s in ipairs(opts.sources) do
+ if v:find(s) then
+ table.insert(sources, v)
+ end
+ end
+ end
+ else
+ sources = files
+ end
+
+ local results = {}
+ for _, source in ipairs(sources) do
+ local data = vim.json.decode(Path:new(source):read())
+ for _, entry in ipairs(data) do
+ table.insert(results, entry)
+ end
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Symbols",
+ finder = finders.new_table {
+ results = results,
+ entry_maker = function(entry)
+ return make_entry.set_default_entry_mt({
+ value = entry,
+ ordinal = entry[1] .. " " .. entry[2],
+ display = entry[1] .. " " .. entry[2],
+ }, opts)
+ end,
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(_)
+ if initial_mode == "i" then
+ actions.select_default:replace(actions.insert_symbol_i)
+ else
+ actions.select_default:replace(actions.insert_symbol)
+ end
+ return true
+ end,
+ }):find()
+end
+
+internal.commands = function(opts)
+ pickers.new(opts, {
+ prompt_title = "Commands",
+ finder = finders.new_table {
+ results = (function()
+ local command_iter = vim.api.nvim_get_commands {}
+ local commands = {}
+
+ for _, cmd in pairs(command_iter) do
+ table.insert(commands, cmd)
+ end
+
+ local need_buf_command = vim.F.if_nil(opts.show_buf_command, true)
+
+ if need_buf_command then
+ local buf_command_iter = vim.api.nvim_buf_get_commands(0, {})
+ buf_command_iter[true] = nil -- remove the redundant entry
+ for _, cmd in pairs(buf_command_iter) do
+ table.insert(commands, cmd)
+ end
+ end
+ return commands
+ end)(),
+
+ entry_maker = opts.entry_maker or make_entry.gen_from_commands(opts),
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.commands"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ local val = selection.value
+ local cmd = string.format([[:%s ]], val.name)
+
+ if val.nargs == "0" then
+ vim.cmd(cmd)
+ else
+ vim.cmd [[stopinsert]]
+ vim.fn.feedkeys(cmd, "n")
+ end
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.quickfix = function(opts)
+ local qf_identifier = opts.id or vim.F.if_nil(opts.nr, "$")
+ local locations = vim.fn.getqflist({ [opts.id and "id" or "nr"] = qf_identifier, items = true }).items
+
+ if vim.tbl_isempty(locations) then
+ return
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Quickfix",
+ 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),
+ }):find()
+end
+
+internal.quickfixhistory = function(opts)
+ local qflists = {}
+ for i = 1, 10 do -- (n)vim keeps at most 10 quickfix lists in full
+ -- qf weirdness: id = 0 gets id of quickfix list nr
+ local qflist = vim.fn.getqflist { nr = i, id = 0, title = true, items = true }
+ if not vim.tbl_isempty(qflist.items) then
+ table.insert(qflists, qflist)
+ end
+ end
+ local entry_maker = opts.make_entry
+ or function(entry)
+ return make_entry.set_default_entry_mt({
+ value = entry.title or "Untitled",
+ ordinal = entry.title or "Untitled",
+ display = entry.title or "Untitled",
+ nr = entry.nr,
+ id = entry.id,
+ items = entry.items,
+ }, opts)
+ end
+ local qf_entry_maker = make_entry.gen_from_quickfix(opts)
+ pickers.new(opts, {
+ prompt_title = "Quickfix History",
+ finder = finders.new_table {
+ results = qflists,
+ entry_maker = entry_maker,
+ },
+ previewer = previewers.new_buffer_previewer {
+ title = "Quickfix List Preview",
+ dyn_title = function(_, entry)
+ return entry.title
+ end,
+
+ get_buffer_by_name = function(_, entry)
+ return "quickfixlist_" .. tostring(entry.nr)
+ end,
+
+ define_preview = function(self, entry)
+ if self.state.bufname then
+ return
+ end
+ local entries = vim.tbl_map(function(i)
+ return qf_entry_maker(i):display()
+ end, entry.items)
+ vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, entries)
+ end,
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(_, _)
+ action_set.select:replace(function(prompt_bufnr)
+ local nr = action_state.get_selected_entry().nr
+ actions.close(prompt_bufnr)
+ internal.quickfix { nr = nr }
+ end)
+ return true
+ end,
+ }):find()
+end
+
+internal.loclist = function(opts)
+ local locations = vim.fn.getloclist(0)
+ local filenames = {}
+ for _, value in pairs(locations) do
+ local bufnr = value.bufnr
+ if filenames[bufnr] == nil then
+ filenames[bufnr] = vim.api.nvim_buf_get_name(bufnr)
+ end
+ value.filename = filenames[bufnr]
+ end
+
+ if vim.tbl_isempty(locations) then
+ return
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Loclist",
+ 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),
+ }):find()
+end
+
+internal.oldfiles = function(opts)
+ opts = apply_cwd_only_aliases(opts)
+ opts.include_current_session = vim.F.if_nil(opts.include_current_session, true)
+
+ local current_buffer = vim.api.nvim_get_current_buf()
+ local current_file = vim.api.nvim_buf_get_name(current_buffer)
+ local results = {}
+
+ if opts.include_current_session then
+ for _, buffer in ipairs(vim.split(vim.fn.execute ":buffers! t", "\n")) do
+ local match = tonumber(string.match(buffer, "%s*(%d+)"))
+ local open_by_lsp = string.match(buffer, "line 0$")
+ if match and not open_by_lsp then
+ local file = vim.api.nvim_buf_get_name(match)
+ if vim.loop.fs_stat(file) and match ~= current_buffer then
+ table.insert(results, file)
+ end
+ end
+ end
+ end
+
+ for _, file in ipairs(vim.v.oldfiles) do
+ if vim.loop.fs_stat(file) and not vim.tbl_contains(results, file) and file ~= current_file then
+ table.insert(results, file)
+ end
+ end
+
+ if opts.cwd_only then
+ local cwd = vim.loop.cwd()
+ cwd = cwd:gsub([[\]], [[\\]])
+ results = vim.tbl_filter(function(file)
+ return vim.fn.matchstrpos(file, cwd)[2] ~= -1
+ end, results)
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Oldfiles",
+ finder = finders.new_table {
+ results = results,
+ entry_maker = opts.entry_maker or make_entry.gen_from_file(opts),
+ },
+ sorter = conf.file_sorter(opts),
+ previewer = conf.file_previewer(opts),
+ }):find()
+end
+
+internal.command_history = function(opts)
+ local history_string = vim.fn.execute "history cmd"
+ local history_list = vim.split(history_string, "\n")
+
+ local results = {}
+ for i = #history_list, 3, -1 do
+ local item = history_list[i]
+ local _, finish = string.find(item, "%d+ +")
+ table.insert(results, string.sub(item, finish + 1))
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Command History",
+ finder = finders.new_table(results),
+ sorter = conf.generic_sorter(opts),
+
+ attach_mappings = function(_, map)
+ map("i", "<CR>", actions.set_command_line)
+ map("n", "<CR>", actions.set_command_line)
+ map("n", "<C-e>", actions.edit_command_line)
+ map("i", "<C-e>", actions.edit_command_line)
+
+ -- TODO: Find a way to insert the text... it seems hard.
+ -- map('i', '<C-i>', actions.insert_value, { expr = true })
+
+ return true
+ end,
+ }):find()
+end
+
+internal.search_history = function(opts)
+ local search_string = vim.fn.execute "history search"
+ local search_list = vim.split(search_string, "\n")
+
+ local results = {}
+ for i = #search_list, 3, -1 do
+ local item = search_list[i]
+ local _, finish = string.find(item, "%d+ +")
+ table.insert(results, string.sub(item, finish + 1))
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Search History",
+ finder = finders.new_table(results),
+ sorter = conf.generic_sorter(opts),
+
+ attach_mappings = function(_, map)
+ map("i", "<CR>", actions.set_search_line)
+ map("n", "<CR>", actions.set_search_line)
+ map("n", "<C-e>", actions.edit_search_line)
+ map("i", "<C-e>", actions.edit_search_line)
+
+ -- TODO: Find a way to insert the text... it seems hard.
+ -- map('i', '<C-i>', actions.insert_value, { expr = true })
+
+ return true
+ end,
+ }):find()
+end
+
+internal.vim_options = function(opts)
+ local res = {}
+ for _, v in pairs(vim.api.nvim_get_all_options_info()) do
+ table.insert(res, v)
+ end
+ table.sort(res, function(left, right)
+ return left.name < right.name
+ end)
+
+ pickers.new(opts, {
+ prompt_title = "options",
+ finder = finders.new_table {
+ results = res,
+ entry_maker = opts.entry_maker or make_entry.gen_from_vimoptions(opts),
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function()
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.vim_options"
+ return
+ end
+
+ local esc = ""
+ if vim.fn.mode() == "i" then
+ esc = vim.api.nvim_replace_termcodes("<esc>", true, false, true)
+ end
+
+ vim.api.nvim_feedkeys(
+ string.format("%s:set %s=%s", esc, selection.value.name, selection.value.value),
+ "m",
+ true
+ )
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.help_tags = function(opts)
+ opts.lang = vim.F.if_nil(opts.lang, vim.o.helplang)
+ opts.fallback = vim.F.if_nil(opts.fallback, true)
+ opts.file_ignore_patterns = {}
+
+ local langs = vim.split(opts.lang, ",", true)
+ if opts.fallback and not vim.tbl_contains(langs, "en") then
+ table.insert(langs, "en")
+ end
+ local langs_map = {}
+ for _, lang in ipairs(langs) do
+ langs_map[lang] = true
+ end
+
+ local tag_files = {}
+ local function add_tag_file(lang, file)
+ if langs_map[lang] then
+ if tag_files[lang] then
+ table.insert(tag_files[lang], file)
+ else
+ tag_files[lang] = { file }
+ end
+ end
+ end
+
+ local help_files = {}
+ local all_files = vim.api.nvim_get_runtime_file("doc/*", true)
+ for _, fullpath in ipairs(all_files) do
+ local file = utils.path_tail(fullpath)
+ if file == "tags" then
+ add_tag_file("en", fullpath)
+ elseif file:match "^tags%-..$" then
+ local lang = file:sub(-2)
+ add_tag_file(lang, fullpath)
+ else
+ help_files[file] = fullpath
+ end
+ end
+
+ local tags = {}
+ local tags_map = {}
+ local delimiter = string.char(9)
+ for _, lang in ipairs(langs) do
+ for _, file in ipairs(tag_files[lang] or {}) do
+ local lines = vim.split(Path:new(file):read(), "\n", true)
+ for _, line in ipairs(lines) do
+ -- TODO: also ignore tagComment starting with ';'
+ if not line:match "^!_TAG_" then
+ local fields = vim.split(line, delimiter, true)
+ if #fields == 3 and not tags_map[fields[1]] then
+ if fields[1] ~= "help-tags" or fields[2] ~= "tags" then
+ table.insert(tags, {
+ name = fields[1],
+ filename = help_files[fields[2]],
+ cmd = fields[3],
+ lang = lang,
+ })
+ tags_map[fields[1]] = true
+ end
+ end
+ end
+ end
+ end
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Help",
+ finder = finders.new_table {
+ results = tags,
+ entry_maker = function(entry)
+ return make_entry.set_default_entry_mt({
+ value = entry.name .. "@" .. entry.lang,
+ display = entry.name,
+ ordinal = entry.name,
+ filename = entry.filename,
+ cmd = entry.cmd,
+ }, opts)
+ end,
+ },
+ previewer = previewers.help.new(opts),
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ action_set.select:replace(function(_, cmd)
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.help_tags"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ if cmd == "default" or cmd == "horizontal" then
+ vim.cmd("help " .. selection.value)
+ elseif cmd == "vertical" then
+ vim.cmd("vert help " .. selection.value)
+ elseif cmd == "tab" then
+ vim.cmd("tab help " .. selection.value)
+ end
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.man_pages = function(opts)
+ opts.sections = vim.F.if_nil(opts.sections, { "1" })
+ assert(vim.tbl_islist(opts.sections), "sections should be a list")
+ opts.man_cmd = utils.get_lazy_default(opts.man_cmd, function()
+ local is_darwin = vim.loop.os_uname().sysname == "Darwin"
+ return is_darwin and { "apropos", " " } or { "apropos", "" }
+ end)
+ opts.entry_maker = opts.entry_maker or make_entry.gen_from_apropos(opts)
+ opts.env = { PATH = vim.env.PATH, MANPATH = vim.env.MANPATH }
+
+ pickers.new(opts, {
+ prompt_title = "Man",
+ finder = finders.new_oneshot_job(opts.man_cmd, opts),
+ previewer = previewers.man.new(opts),
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ action_set.select:replace(function(_, cmd)
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.man_pages"
+ return
+ end
+
+ local args = selection.section .. " " .. selection.value
+ actions.close(prompt_bufnr)
+ if cmd == "default" or cmd == "horizontal" then
+ vim.cmd("Man " .. args)
+ elseif cmd == "vertical" then
+ vim.cmd("vert Man " .. args)
+ elseif cmd == "tab" then
+ vim.cmd("tab Man " .. args)
+ end
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.reloader = function(opts)
+ local package_list = vim.tbl_keys(package.loaded)
+
+ -- filter out packages we don't want and track the longest package name
+ local column_len = 0
+ for index, module_name in pairs(package_list) do
+ if
+ type(require(module_name)) ~= "table"
+ or module_name:sub(1, 1) == "_"
+ or package.searchpath(module_name, package.path) == nil
+ then
+ table.remove(package_list, index)
+ elseif #module_name > column_len then
+ column_len = #module_name
+ end
+ end
+ opts.column_len = vim.F.if_nil(opts.column_len, column_len)
+
+ pickers.new(opts, {
+ prompt_title = "Packages",
+ finder = finders.new_table {
+ results = package_list,
+ entry_maker = opts.entry_maker or make_entry.gen_from_packages(opts),
+ },
+ -- previewer = previewers.vim_buffer.new(opts),
+ sorter = conf.generic_sorter(opts),
+
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.reloader"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ require("plenary.reload").reload_module(selection.value)
+ utils.notify("builtin.reloader", {
+ msg = string.format("[%s] - module reloaded", selection.value),
+ level = "INFO",
+ })
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.buffers = function(opts)
+ opts = apply_cwd_only_aliases(opts)
+ local bufnrs = filter(function(b)
+ if 1 ~= vim.fn.buflisted(b) then
+ return false
+ end
+ -- only hide unloaded buffers if opts.show_all_buffers is false, keep them listed if true or nil
+ if opts.show_all_buffers == false and not vim.api.nvim_buf_is_loaded(b) then
+ return false
+ end
+ if opts.ignore_current_buffer and b == vim.api.nvim_get_current_buf() then
+ return false
+ end
+ if opts.cwd_only and not string.find(vim.api.nvim_buf_get_name(b), vim.loop.cwd(), 1, true) then
+ return false
+ end
+ return true
+ end, vim.api.nvim_list_bufs())
+ if not next(bufnrs) then
+ return
+ end
+ if opts.sort_mru then
+ table.sort(bufnrs, function(a, b)
+ return vim.fn.getbufinfo(a)[1].lastused > vim.fn.getbufinfo(b)[1].lastused
+ end)
+ end
+
+ local buffers = {}
+ local default_selection_idx = 1
+ for _, bufnr in ipairs(bufnrs) do
+ local flag = bufnr == vim.fn.bufnr "" and "%" or (bufnr == vim.fn.bufnr "#" and "#" or " ")
+
+ if opts.sort_lastused and not opts.ignore_current_buffer and flag == "#" then
+ default_selection_idx = 2
+ end
+
+ local element = {
+ bufnr = bufnr,
+ flag = flag,
+ info = vim.fn.getbufinfo(bufnr)[1],
+ }
+
+ if opts.sort_lastused and (flag == "#" or flag == "%") then
+ local idx = ((buffers[1] ~= nil and buffers[1].flag == "%") and 2 or 1)
+ table.insert(buffers, idx, element)
+ else
+ table.insert(buffers, element)
+ end
+ end
+
+ if not opts.bufnr_width then
+ local max_bufnr = math.max(unpack(bufnrs))
+ opts.bufnr_width = #tostring(max_bufnr)
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Buffers",
+ finder = finders.new_table {
+ results = buffers,
+ entry_maker = opts.entry_maker or make_entry.gen_from_buffer(opts),
+ },
+ previewer = conf.grep_previewer(opts),
+ sorter = conf.generic_sorter(opts),
+ default_selection_index = default_selection_idx,
+ }):find()
+end
+
+internal.colorscheme = function(opts)
+ local before_background = vim.o.background
+ local before_color = vim.api.nvim_exec("colorscheme", true)
+ local need_restore = true
+
+ local colors = opts.colors or { before_color }
+ if not vim.tbl_contains(colors, before_color) then
+ table.insert(colors, 1, before_color)
+ end
+
+ colors = vim.list_extend(
+ colors,
+ vim.tbl_filter(function(color)
+ return color ~= before_color
+ end, vim.fn.getcompletion("", "color"))
+ )
+
+ local previewer
+ if opts.enable_preview then
+ -- define previewer
+ local bufnr = vim.api.nvim_get_current_buf()
+ local p = vim.api.nvim_buf_get_name(bufnr)
+
+ -- don't need previewer
+ if vim.fn.buflisted(bufnr) ~= 1 then
+ local deleted = false
+ local function del_win(win_id)
+ if win_id and vim.api.nvim_win_is_valid(win_id) then
+ utils.buf_delete(vim.api.nvim_win_get_buf(win_id))
+ pcall(vim.api.nvim_win_close, win_id, true)
+ end
+ end
+
+ previewer = previewers.new {
+ preview_fn = function(_, entry, status)
+ if not deleted then
+ deleted = true
+ del_win(status.preview_win)
+ del_win(status.preview_border_win)
+ end
+ vim.cmd("colorscheme " .. entry.value)
+ end,
+ }
+ else
+ -- show current buffer content in previewer
+ previewer = previewers.new_buffer_previewer {
+ get_buffer_by_name = function()
+ return p
+ end,
+ define_preview = function(self, entry)
+ if vim.loop.fs_stat(p) then
+ conf.buffer_previewer_maker(p, self.state.bufnr, { bufname = self.state.bufname })
+ else
+ local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+ vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, lines)
+ end
+ vim.cmd("colorscheme " .. entry.value)
+ end,
+ }
+ end
+ end
+
+ local picker = pickers.new(opts, {
+ prompt_title = "Change Colorscheme",
+ finder = finders.new_table {
+ results = colors,
+ },
+ sorter = conf.generic_sorter(opts),
+ previewer = previewer,
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.colorscheme"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ need_restore = false
+ vim.cmd("colorscheme " .. selection.value)
+ end)
+
+ return true
+ end,
+ })
+
+ if opts.enable_preview then
+ -- rewrite picker.close_windows. restore color if needed
+ local close_windows = picker.close_windows
+ picker.close_windows = function(status)
+ close_windows(status)
+ if need_restore then
+ vim.o.background = before_background
+ vim.cmd("colorscheme " .. before_color)
+ end
+ end
+ end
+
+ picker:find()
+end
+
+internal.marks = function(opts)
+ local local_marks = {
+ items = vim.fn.getmarklist(opts.bufnr),
+ name_func = function(_, line)
+ return vim.api.nvim_buf_get_lines(opts.bufnr, line - 1, line, false)[1]
+ end,
+ }
+ local global_marks = {
+ items = vim.fn.getmarklist(),
+ name_func = function(mark, _)
+ -- get buffer name if it is opened, otherwise get file name
+ return vim.api.nvim_get_mark(mark, {})[4]
+ end,
+ }
+ local marks_table = {}
+ local marks_others = {}
+ local bufname = vim.api.nvim_buf_get_name(opts.bufnr)
+ for _, cnf in ipairs { local_marks, global_marks } do
+ for _, v in ipairs(cnf.items) do
+ -- strip the first single quote character
+ local mark = string.sub(v.mark, 2, 3)
+ local _, lnum, col, _ = unpack(v.pos)
+ local name = cnf.name_func(mark, lnum)
+ -- same format to :marks command
+ local line = string.format("%s %6d %4d %s", mark, lnum, col - 1, name)
+ local row = {
+ line = line,
+ lnum = lnum,
+ col = col,
+ filename = v.file or bufname,
+ }
+ -- non alphanumeric marks goes to last
+ if mark:match "%w" then
+ table.insert(marks_table, row)
+ else
+ table.insert(marks_others, row)
+ end
+ end
+ end
+ marks_table = vim.fn.extend(marks_table, marks_others)
+
+ pickers.new(opts, {
+ prompt_title = "Marks",
+ finder = finders.new_table {
+ results = marks_table,
+ entry_maker = opts.entry_maker or make_entry.gen_from_marks(opts),
+ },
+ previewer = conf.grep_previewer(opts),
+ sorter = conf.generic_sorter(opts),
+ push_cursor_on_edit = true,
+ push_tagstack_on_edit = true,
+ }):find()
+end
+
+internal.registers = function(opts)
+ local registers_table = { '"', "_", "#", "=", "_", "/", "*", "+", ":", ".", "%" }
+
+ -- named
+ for i = 0, 9 do
+ table.insert(registers_table, tostring(i))
+ end
+
+ -- alphabetical
+ for i = 65, 90 do
+ table.insert(registers_table, string.char(i))
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Registers",
+ finder = finders.new_table {
+ results = registers_table,
+ entry_maker = opts.entry_maker or make_entry.gen_from_registers(opts),
+ },
+ -- use levenshtein as n-gram doesn't support <2 char matches
+ sorter = sorters.get_levenshtein_sorter(),
+ attach_mappings = function(_, map)
+ actions.select_default:replace(actions.paste_register)
+ map("i", "<C-e>", actions.edit_register)
+
+ return true
+ end,
+ }):find()
+end
+
+-- TODO: make filtering include the mapping and the action
+internal.keymaps = function(opts)
+ opts.modes = vim.F.if_nil(opts.modes, { "n", "i", "c", "x" })
+ opts.show_plug = vim.F.if_nil(opts.show_plug, true)
+
+ local keymap_encountered = {} -- used to make sure no duplicates are inserted into keymaps_table
+ local keymaps_table = {}
+ local max_len_lhs = 0
+
+ -- helper function to populate keymaps_table and determine max_len_lhs
+ local function extract_keymaps(keymaps)
+ for _, keymap in pairs(keymaps) do
+ local keymap_key = keymap.buffer .. keymap.mode .. keymap.lhs -- should be distinct for every keymap
+ if not keymap_encountered[keymap_key] then
+ keymap_encountered[keymap_key] = true
+ if opts.show_plug or not string.find(keymap.lhs, "<Plug>") then
+ table.insert(keymaps_table, keymap)
+ max_len_lhs = math.max(max_len_lhs, #utils.display_termcodes(keymap.lhs))
+ end
+ end
+ end
+ end
+
+ for _, mode in pairs(opts.modes) do
+ local global = vim.api.nvim_get_keymap(mode)
+ local buf_local = vim.api.nvim_buf_get_keymap(0, mode)
+ extract_keymaps(global)
+ extract_keymaps(buf_local)
+ end
+ opts.width_lhs = max_len_lhs + 1
+
+ pickers.new(opts, {
+ prompt_title = "Key Maps",
+ finder = finders.new_table {
+ results = keymaps_table,
+ entry_maker = opts.entry_maker or make_entry.gen_from_keymaps(opts),
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.keymaps"
+ return
+ end
+
+ vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(selection.value.lhs, true, false, true), "t", true)
+ return actions.close(prompt_bufnr)
+ end)
+ return true
+ end,
+ }):find()
+end
+
+internal.filetypes = function(opts)
+ local filetypes = vim.fn.getcompletion("", "filetype")
+
+ pickers.new(opts, {
+ prompt_title = "Filetypes",
+ finder = finders.new_table {
+ results = filetypes,
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ print "[telescope] Nothing currently selected"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ vim.cmd("setfiletype " .. selection[1])
+ end)
+ return true
+ end,
+ }):find()
+end
+
+internal.highlights = function(opts)
+ local highlights = vim.fn.getcompletion("", "highlight")
+
+ pickers.new(opts, {
+ prompt_title = "Highlights",
+ finder = finders.new_table {
+ results = highlights,
+ entry_maker = opts.entry_maker or make_entry.gen_from_highlights(opts),
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.highlights"
+ return
+ end
+
+ actions.close(prompt_bufnr)
+ vim.cmd("hi " .. selection.value)
+ end)
+ return true
+ end,
+ previewer = previewers.highlights.new(opts),
+ }):find()
+end
+
+internal.autocommands = function(opts)
+ local autocmds = vim.api.nvim_get_autocmds {}
+ table.sort(autocmds, function(lhs, rhs)
+ return lhs.event < rhs.event
+ end)
+ pickers.new(opts, {
+ prompt_title = "autocommands",
+ finder = finders.new_table {
+ results = autocmds,
+ entry_maker = opts.entry_maker or make_entry.gen_from_autocommands(opts),
+ },
+ previewer = previewers.autocommands.new(opts),
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ action_set.select:replace_if(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ return false
+ end
+ local val = selection.value
+ local group_name = val.group_name ~= "<anonymous>" and val.group_name or ""
+ local output = vim.fn.execute("verb autocmd " .. group_name .. " " .. val.event .. " " .. val.pattern, "silent")
+ for line in output:gmatch "[^\r\n]+" do
+ local source_file = line:match "Last set from (.*) line %d*$" or line:match "Last set from (.*)$"
+ if source_file and source_file ~= "Lua" then
+ selection.filename = source_file
+ local source_lnum = line:match "line (%d*)$" or "1"
+ selection.lnum = tonumber(source_lnum)
+ selection.col = 1
+ return false
+ end
+ end
+ return true
+ end, function()
+ local selection = action_state.get_selected_entry()
+ actions.close(prompt_bufnr)
+ print("You selected autocmd: " .. vim.inspect(selection.value))
+ end)
+
+ return true
+ end,
+ }):find()
+end
+
+internal.spell_suggest = function(opts)
+ local cursor_word = vim.fn.expand "<cword>"
+ local suggestions = vim.fn.spellsuggest(cursor_word)
+
+ pickers.new(opts, {
+ prompt_title = "Spelling Suggestions",
+ finder = finders.new_table {
+ results = suggestions,
+ },
+ sorter = conf.generic_sorter(opts),
+ attach_mappings = function(prompt_bufnr)
+ actions.select_default:replace(function()
+ local selection = action_state.get_selected_entry()
+ if selection == nil then
+ utils.__warn_no_selection "builtin.spell_suggest"
+ return
+ end
+
+ action_state.get_current_picker(prompt_bufnr)._original_mode = "i"
+ actions.close(prompt_bufnr)
+ vim.cmd("normal! ciw" .. selection[1])
+ vim.cmd "stopinsert"
+ end)
+ return true
+ end,
+ }):find()
+end
+
+internal.tagstack = function(opts)
+ opts = opts or {}
+ local tagstack = vim.fn.gettagstack().items
+
+ local tags = {}
+ for i = #tagstack, 1, -1 do
+ local tag = tagstack[i]
+ tag.bufnr = tag.from[1]
+ if vim.api.nvim_buf_is_valid(tag.bufnr) then
+ tags[#tags + 1] = tag
+ tag.filename = vim.fn.bufname(tag.bufnr)
+ tag.lnum = tag.from[2]
+ tag.col = tag.from[3]
+
+ tag.text = vim.api.nvim_buf_get_lines(tag.bufnr, tag.lnum - 1, tag.lnum, false)[1] or ""
+ end
+ end
+
+ if vim.tbl_isempty(tags) then
+ utils.notify("builtin.tagstack", {
+ msg = "No tagstack available",
+ level = "WARN",
+ })
+ return
+ end
+
+ pickers.new(opts, {
+ prompt_title = "TagStack",
+ finder = finders.new_table {
+ results = tags,
+ entry_maker = make_entry.gen_from_quickfix(opts),
+ },
+ previewer = conf.qflist_previewer(opts),
+ sorter = conf.generic_sorter(opts),
+ }):find()
+end
+
+internal.jumplist = function(opts)
+ opts = opts or {}
+ local jumplist = vim.fn.getjumplist()[1]
+
+ -- reverse the list
+ local sorted_jumplist = {}
+ for i = #jumplist, 1, -1 do
+ if vim.api.nvim_buf_is_valid(jumplist[i].bufnr) then
+ jumplist[i].text = vim.api.nvim_buf_get_lines(jumplist[i].bufnr, jumplist[i].lnum, jumplist[i].lnum + 1, false)[1]
+ or ""
+ table.insert(sorted_jumplist, jumplist[i])
+ end
+ end
+
+ pickers.new(opts, {
+ prompt_title = "Jumplist",
+ finder = finders.new_table {
+ results = sorted_jumplist,
+ entry_maker = make_entry.gen_from_quickfix(opts),
+ },
+ previewer = conf.qflist_previewer(opts),
+ 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(internal)
diff --git a/lua/telescope/builtin/__lsp.lua b/lua/telescope/builtin/__lsp.lua
new file mode 100644
index 0000000..480d456
--- /dev/null
+++ b/lua/telescope/builtin/__lsp.lua
@@ -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)
diff --git a/lua/telescope/builtin/diagnostics.lua b/lua/telescope/builtin/diagnostics.lua
index 2614e36..5d8f926 100644
--- a/lua/telescope/builtin/diagnostics.lua
+++ b/lua/telescope/builtin/diagnostics.lua
@@ -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 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",
+local m = setmetatable({}, {
+ __index = function(_, k)
+ local utils = require "telescope.utils"
+ 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
-
- 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 require("telescope.builtin").diagnostics
+ end,
+})
-return apply_checks(diagnostics)
+return m
diff --git a/lua/telescope/builtin/files.lua b/lua/telescope/builtin/files.lua
index dddd18a..645fc10 100644
--- a/lua/telescope/builtin/files.lua
+++ b/lua/telescope/builtin/files.lua
@@ -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 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",
+local m = setmetatable({}, {
+ __index = function(_, k)
+ local utils = require "telescope.utils"
+ 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
- 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 require("telescope.builtin")[k]
+ end,
+})
-return apply_checks(files)
+return m
diff --git a/lua/telescope/builtin/git.lua b/lua/telescope/builtin/git.lua
index 7db45ef..e6da478 100644
--- a/lua/telescope/builtin/git.lua
+++ b/lua/telescope/builtin/git.lua
@@ -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 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",
+local m = setmetatable({}, {
+ __index = function(_, k)
+ local utils = require "telescope.utils"
+ 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 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 require("telescope.builtin")["git_" .. k]
+ end,
+})
-return apply_checks(git)
+return m
diff --git a/lua/telescope/builtin/init.lua b/lua/telescope/builtin/init.lua
index 71cb583..f25d059 100644
--- a/lua/telescope/builtin/init.lua
+++ b/lua/telescope/builtin/init.lua
@@ -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
diff --git a/lua/telescope/builtin/internal.lua b/lua/telescope/builtin/internal.lua
index 4277e2e..b4d4197 100644
--- a/lua/telescope/builtin/internal.lua
+++ b/lua/telescope/builtin/internal.lua
@@ -1,1318 +1,17 @@
-local actions = require "telescope.actions"
-local action_set = require "telescope.actions.set"
-local action_state = require "telescope.actions.state"
-local finders = require "telescope.finders"
-local make_entry = require "telescope.make_entry"
-local Path = require "plenary.path"
-local pickers = require "telescope.pickers"
-local previewers = require "telescope.previewers"
-local p_window = require "telescope.pickers.window"
-local sorters = require "telescope.sorters"
-local state = require "telescope.state"
-local utils = require "telescope.utils"
-
-local conf = require("telescope.config").values
-
-local filter = vim.tbl_filter
-
--- Makes sure aliased options are set correctly
-local function apply_cwd_only_aliases(opts)
- local has_cwd_only = opts.cwd_only ~= nil
- local has_only_cwd = opts.only_cwd ~= nil
-
- if has_only_cwd and not has_cwd_only then
- -- Internally, use cwd_only
- opts.cwd_only = opts.only_cwd
- opts.only_cwd = nil
- end
-
- return opts
-end
-
-local internal = {}
-
-internal.builtin = function(opts)
- opts.include_extensions = vim.F.if_nil(opts.include_extensions, false)
- opts.use_default_opts = vim.F.if_nil(opts.use_default_opts, false)
-
- local objs = {}
-
- for k, v in pairs(require "telescope.builtin") do
- local debug_info = debug.getinfo(v)
- table.insert(objs, {
- filename = string.sub(debug_info.source, 2),
- text = k,
- })
- end
-
- local title = "Telescope Builtin"
-
- if opts.include_extensions then
- title = "Telescope Pickers"
- for ext, funcs in pairs(require("telescope").extensions) do
- for func_name, func_obj in pairs(funcs) do
- -- Only include exported functions whose name doesn't begin with an underscore
- if type(func_obj) == "function" and string.sub(func_name, 0, 1) ~= "_" then
- local debug_info = debug.getinfo(func_obj)
- table.insert(objs, {
- filename = string.sub(debug_info.source, 2),
- text = string.format("%s : %s", ext, func_name),
- })
- end
- end
- end
- end
-
- opts.bufnr = vim.api.nvim_get_current_buf()
- opts.winnr = vim.api.nvim_get_current_win()
- pickers.new(opts, {
- prompt_title = title,
- finder = finders.new_table {
- results = objs,
- entry_maker = function(entry)
- return make_entry.set_default_entry_mt({
- value = entry,
- text = entry.text,
- display = entry.text,
- ordinal = entry.text,
- filename = entry.filename,
- }, opts)
- end,
- },
- previewer = previewers.builtin.new(opts),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(_)
- actions.select_default:replace(function(_)
- local selection = action_state.get_selected_entry()
- if not selection then
- utils.__warn_no_selection "builtin.builtin"
- return
- end
-
- -- we do this to avoid any surprises
- opts.include_extensions = nil
-
- local picker_opts
- if not opts.use_default_opts then
- picker_opts = opts
- end
-
- if string.match(selection.text, " : ") then
- -- Call appropriate function from extensions
- local split_string = vim.split(selection.text, " : ")
- local ext = split_string[1]
- local func = split_string[2]
- require("telescope").extensions[ext][func](picker_opts)
- else
- -- Call appropriate telescope builtin
- require("telescope.builtin")[selection.text](picker_opts)
- end
- end)
- return true
- end,
- }):find()
-end
-
-internal.resume = function(opts)
- opts = opts or {}
- opts.cache_index = vim.F.if_nil(opts.cache_index, 1)
-
- local cached_pickers = state.get_global_key "cached_pickers"
- if cached_pickers == nil or vim.tbl_isempty(cached_pickers) then
- utils.notify("builtin.resume", {
- msg = "No cached picker(s).",
- level = "INFO",
- })
- return
- end
- local picker = cached_pickers[opts.cache_index]
- if picker == nil then
- utils.notify("builtin.resume", {
- msg = string.format("Index too large as there are only '%s' pickers cached", #cached_pickers),
+local m = setmetatable({}, {
+ __index = function(_, k)
+ local utils = require "telescope.utils"
+ utils.notify("builtin", {
+ msg = string.format(
+ 'You are using an internal interface. Do not use `require("telescope.builtin.internal").%s`,'
+ .. ' please use `require("telescope.builtin").%s`! We will remove this endpoint soon!',
+ k,
+ k
+ ),
level = "ERROR",
})
- return
- end
- -- reset layout strategy and get_window_options if default as only one is valid
- -- and otherwise unclear which was actually set
- if picker.layout_strategy == conf.layout_strategy then
- picker.layout_strategy = nil
- end
- if picker.get_window_options == p_window.get_window_options then
- picker.get_window_options = nil
- end
- picker.cache_picker.index = opts.cache_index
-
- -- avoid partial `opts.cache_picker` at picker creation
- if opts.cache_picker ~= false then
- picker.cache_picker = vim.tbl_extend("keep", opts.cache_picker or {}, picker.cache_picker)
- else
- picker.cache_picker.disabled = true
- end
- opts.cache_picker = nil
- picker.previewer = picker.all_previewers
- if picker.hidden_previewer then
- picker.hidden_previewer = nil
- opts.previewer = vim.F.if_nil(opts.previewer, false)
- end
- pickers.new(opts, picker):find()
-end
-
-internal.pickers = function(opts)
- local cached_pickers = state.get_global_key "cached_pickers"
- if cached_pickers == nil or vim.tbl_isempty(cached_pickers) then
- utils.notify("builtin.pickers", {
- msg = "No cached picker(s).",
- level = "INFO",
- })
- return
- end
-
- opts = opts or {}
-
- -- clear cache picker for immediate pickers.new and pass option to resumed picker
- if opts.cache_picker ~= nil then
- opts._cache_picker = opts.cache_picker
- opts.cache_picker = nil
- end
-
- pickers.new(opts, {
- prompt_title = "Pickers",
- finder = finders.new_table {
- results = cached_pickers,
- entry_maker = make_entry.gen_from_picker(opts),
- },
- previewer = previewers.pickers.new(opts),
- sorter = conf.generic_sorter(opts),
- cache_picker = false,
- attach_mappings = function(_, map)
- actions.select_default:replace(function(prompt_bufnr)
- local current_picker = action_state.get_current_picker(prompt_bufnr)
- local selection_index = current_picker:get_index(current_picker:get_selection_row())
- actions.close(prompt_bufnr)
- opts.cache_picker = opts._cache_picker
- opts["cache_index"] = selection_index
- opts["initial_mode"] = cached_pickers[selection_index].initial_mode
- internal.resume(opts)
- end)
- map("i", "<C-x>", actions.remove_selected_picker)
- map("n", "<C-x>", actions.remove_selected_picker)
- return true
- end,
- }):find()
-end
-
-internal.planets = function(opts)
- local show_pluto = opts.show_pluto or false
-
- local sourced_file = require("plenary.debug_utils").sourced_filepath()
- local base_directory = vim.fn.fnamemodify(sourced_file, ":h:h:h:h")
-
- local globbed_files = vim.fn.globpath(base_directory .. "/data/memes/planets/", "*", true, true)
- local acceptable_files = {}
- for _, v in ipairs(globbed_files) do
- if show_pluto or not v:find "pluto" then
- table.insert(acceptable_files, vim.fn.fnamemodify(v, ":t"))
- end
- end
-
- pickers.new(opts, {
- prompt_title = "Planets",
- finder = finders.new_table {
- results = acceptable_files,
- entry_maker = function(line)
- return make_entry.set_default_entry_mt({
- ordinal = line,
- display = line,
- filename = base_directory .. "/data/memes/planets/" .. line,
- }, opts)
- end,
- },
- previewer = previewers.cat.new(opts),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.planets"
- return
- end
-
- actions.close(prompt_bufnr)
- print("Enjoy astronomy! You viewed:", selection.display)
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.symbols = function(opts)
- local initial_mode = vim.fn.mode()
- local files = vim.api.nvim_get_runtime_file("data/telescope-sources/*.json", true)
- local data_path = (function()
- if not opts.symbol_path then
- return Path:new { vim.fn.stdpath "data", "telescope", "symbols" }
- else
- return Path:new { opts.symbol_path }
- end
- end)()
- if data_path:exists() then
- for _, v in ipairs(require("plenary.scandir").scan_dir(data_path:absolute(), { search_pattern = "%.json$" })) do
- table.insert(files, v)
- end
- end
-
- if #files == 0 then
- utils.notify("builtin.symbols", {
- msg = "No sources found! Check out https://github.com/nvim-telescope/telescope-symbols.nvim "
- .. "for some prebuild symbols or how to create you own symbol source.",
- level = "ERROR",
- })
- return
- end
-
- local sources = {}
- if opts.sources then
- for _, v in ipairs(files) do
- for _, s in ipairs(opts.sources) do
- if v:find(s) then
- table.insert(sources, v)
- end
- end
- end
- else
- sources = files
- end
-
- local results = {}
- for _, source in ipairs(sources) do
- local data = vim.json.decode(Path:new(source):read())
- for _, entry in ipairs(data) do
- table.insert(results, entry)
- end
- end
-
- pickers.new(opts, {
- prompt_title = "Symbols",
- finder = finders.new_table {
- results = results,
- entry_maker = function(entry)
- return make_entry.set_default_entry_mt({
- value = entry,
- ordinal = entry[1] .. " " .. entry[2],
- display = entry[1] .. " " .. entry[2],
- }, opts)
- end,
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(_)
- if initial_mode == "i" then
- actions.select_default:replace(actions.insert_symbol_i)
- else
- actions.select_default:replace(actions.insert_symbol)
- end
- return true
- end,
- }):find()
-end
-
-internal.commands = function(opts)
- pickers.new(opts, {
- prompt_title = "Commands",
- finder = finders.new_table {
- results = (function()
- local command_iter = vim.api.nvim_get_commands {}
- local commands = {}
-
- for _, cmd in pairs(command_iter) do
- table.insert(commands, cmd)
- end
-
- local need_buf_command = vim.F.if_nil(opts.show_buf_command, true)
-
- if need_buf_command then
- local buf_command_iter = vim.api.nvim_buf_get_commands(0, {})
- buf_command_iter[true] = nil -- remove the redundant entry
- for _, cmd in pairs(buf_command_iter) do
- table.insert(commands, cmd)
- end
- end
- return commands
- end)(),
-
- entry_maker = opts.entry_maker or make_entry.gen_from_commands(opts),
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.commands"
- return
- end
-
- actions.close(prompt_bufnr)
- local val = selection.value
- local cmd = string.format([[:%s ]], val.name)
-
- if val.nargs == "0" then
- vim.cmd(cmd)
- else
- vim.cmd [[stopinsert]]
- vim.fn.feedkeys(cmd, "n")
- end
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.quickfix = function(opts)
- local qf_identifier = opts.id or vim.F.if_nil(opts.nr, "$")
- local locations = vim.fn.getqflist({ [opts.id and "id" or "nr"] = qf_identifier, items = true }).items
-
- if vim.tbl_isempty(locations) then
- return
- end
-
- pickers.new(opts, {
- prompt_title = "Quickfix",
- 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),
- }):find()
-end
-
-internal.quickfixhistory = function(opts)
- local qflists = {}
- for i = 1, 10 do -- (n)vim keeps at most 10 quickfix lists in full
- -- qf weirdness: id = 0 gets id of quickfix list nr
- local qflist = vim.fn.getqflist { nr = i, id = 0, title = true, items = true }
- if not vim.tbl_isempty(qflist.items) then
- table.insert(qflists, qflist)
- end
- end
- local entry_maker = opts.make_entry
- or function(entry)
- return make_entry.set_default_entry_mt({
- value = entry.title or "Untitled",
- ordinal = entry.title or "Untitled",
- display = entry.title or "Untitled",
- nr = entry.nr,
- id = entry.id,
- items = entry.items,
- }, opts)
- end
- local qf_entry_maker = make_entry.gen_from_quickfix(opts)
- pickers.new(opts, {
- prompt_title = "Quickfix History",
- finder = finders.new_table {
- results = qflists,
- entry_maker = entry_maker,
- },
- previewer = previewers.new_buffer_previewer {
- title = "Quickfix List Preview",
- dyn_title = function(_, entry)
- return entry.title
- end,
-
- get_buffer_by_name = function(_, entry)
- return "quickfixlist_" .. tostring(entry.nr)
- end,
-
- define_preview = function(self, entry)
- if self.state.bufname then
- return
- end
- local entries = vim.tbl_map(function(i)
- return qf_entry_maker(i):display()
- end, entry.items)
- vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, entries)
- end,
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(_, _)
- action_set.select:replace(function(prompt_bufnr)
- local nr = action_state.get_selected_entry().nr
- actions.close(prompt_bufnr)
- internal.quickfix { nr = nr }
- end)
- return true
- end,
- }):find()
-end
-
-internal.loclist = function(opts)
- local locations = vim.fn.getloclist(0)
- local filenames = {}
- for _, value in pairs(locations) do
- local bufnr = value.bufnr
- if filenames[bufnr] == nil then
- filenames[bufnr] = vim.api.nvim_buf_get_name(bufnr)
- end
- value.filename = filenames[bufnr]
- end
-
- if vim.tbl_isempty(locations) then
- return
- end
-
- pickers.new(opts, {
- prompt_title = "Loclist",
- 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),
- }):find()
-end
-
-internal.oldfiles = function(opts)
- opts = apply_cwd_only_aliases(opts)
- opts.include_current_session = vim.F.if_nil(opts.include_current_session, true)
-
- local current_buffer = vim.api.nvim_get_current_buf()
- local current_file = vim.api.nvim_buf_get_name(current_buffer)
- local results = {}
-
- if opts.include_current_session then
- for _, buffer in ipairs(vim.split(vim.fn.execute ":buffers! t", "\n")) do
- local match = tonumber(string.match(buffer, "%s*(%d+)"))
- local open_by_lsp = string.match(buffer, "line 0$")
- if match and not open_by_lsp then
- local file = vim.api.nvim_buf_get_name(match)
- if vim.loop.fs_stat(file) and match ~= current_buffer then
- table.insert(results, file)
- end
- end
- end
- end
-
- for _, file in ipairs(vim.v.oldfiles) do
- if vim.loop.fs_stat(file) and not vim.tbl_contains(results, file) and file ~= current_file then
- table.insert(results, file)
- end
- end
-
- if opts.cwd_only then
- local cwd = vim.loop.cwd()
- cwd = cwd:gsub([[\]], [[\\]])
- results = vim.tbl_filter(function(file)
- return vim.fn.matchstrpos(file, cwd)[2] ~= -1
- end, results)
- end
-
- pickers.new(opts, {
- prompt_title = "Oldfiles",
- finder = finders.new_table {
- results = results,
- entry_maker = opts.entry_maker or make_entry.gen_from_file(opts),
- },
- sorter = conf.file_sorter(opts),
- previewer = conf.file_previewer(opts),
- }):find()
-end
-
-internal.command_history = function(opts)
- local history_string = vim.fn.execute "history cmd"
- local history_list = vim.split(history_string, "\n")
-
- local results = {}
- for i = #history_list, 3, -1 do
- local item = history_list[i]
- local _, finish = string.find(item, "%d+ +")
- table.insert(results, string.sub(item, finish + 1))
- end
-
- pickers.new(opts, {
- prompt_title = "Command History",
- finder = finders.new_table(results),
- sorter = conf.generic_sorter(opts),
-
- attach_mappings = function(_, map)
- map("i", "<CR>", actions.set_command_line)
- map("n", "<CR>", actions.set_command_line)
- map("n", "<C-e>", actions.edit_command_line)
- map("i", "<C-e>", actions.edit_command_line)
-
- -- TODO: Find a way to insert the text... it seems hard.
- -- map('i', '<C-i>', actions.insert_value, { expr = true })
-
- return true
- end,
- }):find()
-end
-
-internal.search_history = function(opts)
- local search_string = vim.fn.execute "history search"
- local search_list = vim.split(search_string, "\n")
-
- local results = {}
- for i = #search_list, 3, -1 do
- local item = search_list[i]
- local _, finish = string.find(item, "%d+ +")
- table.insert(results, string.sub(item, finish + 1))
- end
-
- pickers.new(opts, {
- prompt_title = "Search History",
- finder = finders.new_table(results),
- sorter = conf.generic_sorter(opts),
-
- attach_mappings = function(_, map)
- map("i", "<CR>", actions.set_search_line)
- map("n", "<CR>", actions.set_search_line)
- map("n", "<C-e>", actions.edit_search_line)
- map("i", "<C-e>", actions.edit_search_line)
-
- -- TODO: Find a way to insert the text... it seems hard.
- -- map('i', '<C-i>', actions.insert_value, { expr = true })
-
- return true
- end,
- }):find()
-end
-
-internal.vim_options = function(opts)
- local res = {}
- for _, v in pairs(vim.api.nvim_get_all_options_info()) do
- table.insert(res, v)
- end
- table.sort(res, function(left, right)
- return left.name < right.name
- end)
-
- pickers.new(opts, {
- prompt_title = "options",
- finder = finders.new_table {
- results = res,
- entry_maker = opts.entry_maker or make_entry.gen_from_vimoptions(opts),
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function()
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.vim_options"
- return
- end
-
- local esc = ""
- if vim.fn.mode() == "i" then
- esc = vim.api.nvim_replace_termcodes("<esc>", true, false, true)
- end
-
- vim.api.nvim_feedkeys(
- string.format("%s:set %s=%s", esc, selection.value.name, selection.value.value),
- "m",
- true
- )
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.help_tags = function(opts)
- opts.lang = vim.F.if_nil(opts.lang, vim.o.helplang)
- opts.fallback = vim.F.if_nil(opts.fallback, true)
- opts.file_ignore_patterns = {}
-
- local langs = vim.split(opts.lang, ",", true)
- if opts.fallback and not vim.tbl_contains(langs, "en") then
- table.insert(langs, "en")
- end
- local langs_map = {}
- for _, lang in ipairs(langs) do
- langs_map[lang] = true
- end
-
- local tag_files = {}
- local function add_tag_file(lang, file)
- if langs_map[lang] then
- if tag_files[lang] then
- table.insert(tag_files[lang], file)
- else
- tag_files[lang] = { file }
- end
- end
- end
-
- local help_files = {}
- local all_files = vim.api.nvim_get_runtime_file("doc/*", true)
- for _, fullpath in ipairs(all_files) do
- local file = utils.path_tail(fullpath)
- if file == "tags" then
- add_tag_file("en", fullpath)
- elseif file:match "^tags%-..$" then
- local lang = file:sub(-2)
- add_tag_file(lang, fullpath)
- else
- help_files[file] = fullpath
- end
- end
-
- local tags = {}
- local tags_map = {}
- local delimiter = string.char(9)
- for _, lang in ipairs(langs) do
- for _, file in ipairs(tag_files[lang] or {}) do
- local lines = vim.split(Path:new(file):read(), "\n", true)
- for _, line in ipairs(lines) do
- -- TODO: also ignore tagComment starting with ';'
- if not line:match "^!_TAG_" then
- local fields = vim.split(line, delimiter, true)
- if #fields == 3 and not tags_map[fields[1]] then
- if fields[1] ~= "help-tags" or fields[2] ~= "tags" then
- table.insert(tags, {
- name = fields[1],
- filename = help_files[fields[2]],
- cmd = fields[3],
- lang = lang,
- })
- tags_map[fields[1]] = true
- end
- end
- end
- end
- end
- end
-
- pickers.new(opts, {
- prompt_title = "Help",
- finder = finders.new_table {
- results = tags,
- entry_maker = function(entry)
- return make_entry.set_default_entry_mt({
- value = entry.name .. "@" .. entry.lang,
- display = entry.name,
- ordinal = entry.name,
- filename = entry.filename,
- cmd = entry.cmd,
- }, opts)
- end,
- },
- previewer = previewers.help.new(opts),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- action_set.select:replace(function(_, cmd)
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.help_tags"
- return
- end
-
- actions.close(prompt_bufnr)
- if cmd == "default" or cmd == "horizontal" then
- vim.cmd("help " .. selection.value)
- elseif cmd == "vertical" then
- vim.cmd("vert help " .. selection.value)
- elseif cmd == "tab" then
- vim.cmd("tab help " .. selection.value)
- end
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.man_pages = function(opts)
- opts.sections = vim.F.if_nil(opts.sections, { "1" })
- assert(vim.tbl_islist(opts.sections), "sections should be a list")
- opts.man_cmd = utils.get_lazy_default(opts.man_cmd, function()
- local is_darwin = vim.loop.os_uname().sysname == "Darwin"
- return is_darwin and { "apropos", " " } or { "apropos", "" }
- end)
- opts.entry_maker = opts.entry_maker or make_entry.gen_from_apropos(opts)
- opts.env = { PATH = vim.env.PATH, MANPATH = vim.env.MANPATH }
-
- pickers.new(opts, {
- prompt_title = "Man",
- finder = finders.new_oneshot_job(opts.man_cmd, opts),
- previewer = previewers.man.new(opts),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- action_set.select:replace(function(_, cmd)
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.man_pages"
- return
- end
-
- local args = selection.section .. " " .. selection.value
- actions.close(prompt_bufnr)
- if cmd == "default" or cmd == "horizontal" then
- vim.cmd("Man " .. args)
- elseif cmd == "vertical" then
- vim.cmd("vert Man " .. args)
- elseif cmd == "tab" then
- vim.cmd("tab Man " .. args)
- end
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.reloader = function(opts)
- local package_list = vim.tbl_keys(package.loaded)
-
- -- filter out packages we don't want and track the longest package name
- local column_len = 0
- for index, module_name in pairs(package_list) do
- if
- type(require(module_name)) ~= "table"
- or module_name:sub(1, 1) == "_"
- or package.searchpath(module_name, package.path) == nil
- then
- table.remove(package_list, index)
- elseif #module_name > column_len then
- column_len = #module_name
- end
- end
- opts.column_len = vim.F.if_nil(opts.column_len, column_len)
-
- pickers.new(opts, {
- prompt_title = "Packages",
- finder = finders.new_table {
- results = package_list,
- entry_maker = opts.entry_maker or make_entry.gen_from_packages(opts),
- },
- -- previewer = previewers.vim_buffer.new(opts),
- sorter = conf.generic_sorter(opts),
-
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.reloader"
- return
- end
-
- actions.close(prompt_bufnr)
- require("plenary.reload").reload_module(selection.value)
- utils.notify("builtin.reloader", {
- msg = string.format("[%s] - module reloaded", selection.value),
- level = "INFO",
- })
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.buffers = function(opts)
- opts = apply_cwd_only_aliases(opts)
- local bufnrs = filter(function(b)
- if 1 ~= vim.fn.buflisted(b) then
- return false
- end
- -- only hide unloaded buffers if opts.show_all_buffers is false, keep them listed if true or nil
- if opts.show_all_buffers == false and not vim.api.nvim_buf_is_loaded(b) then
- return false
- end
- if opts.ignore_current_buffer and b == vim.api.nvim_get_current_buf() then
- return false
- end
- if opts.cwd_only and not string.find(vim.api.nvim_buf_get_name(b), vim.loop.cwd(), 1, true) then
- return false
- end
- return true
- end, vim.api.nvim_list_bufs())
- if not next(bufnrs) then
- return
- end
- if opts.sort_mru then
- table.sort(bufnrs, function(a, b)
- return vim.fn.getbufinfo(a)[1].lastused > vim.fn.getbufinfo(b)[1].lastused
- end)
- end
-
- local buffers = {}
- local default_selection_idx = 1
- for _, bufnr in ipairs(bufnrs) do
- local flag = bufnr == vim.fn.bufnr "" and "%" or (bufnr == vim.fn.bufnr "#" and "#" or " ")
-
- if opts.sort_lastused and not opts.ignore_current_buffer and flag == "#" then
- default_selection_idx = 2
- end
-
- local element = {
- bufnr = bufnr,
- flag = flag,
- info = vim.fn.getbufinfo(bufnr)[1],
- }
-
- if opts.sort_lastused and (flag == "#" or flag == "%") then
- local idx = ((buffers[1] ~= nil and buffers[1].flag == "%") and 2 or 1)
- table.insert(buffers, idx, element)
- else
- table.insert(buffers, element)
- end
- end
-
- if not opts.bufnr_width then
- local max_bufnr = math.max(unpack(bufnrs))
- opts.bufnr_width = #tostring(max_bufnr)
- end
-
- pickers.new(opts, {
- prompt_title = "Buffers",
- finder = finders.new_table {
- results = buffers,
- entry_maker = opts.entry_maker or make_entry.gen_from_buffer(opts),
- },
- previewer = conf.grep_previewer(opts),
- sorter = conf.generic_sorter(opts),
- default_selection_index = default_selection_idx,
- }):find()
-end
-
-internal.colorscheme = function(opts)
- local before_background = vim.o.background
- local before_color = vim.api.nvim_exec("colorscheme", true)
- local need_restore = true
-
- local colors = opts.colors or { before_color }
- if not vim.tbl_contains(colors, before_color) then
- table.insert(colors, 1, before_color)
- end
-
- colors = vim.list_extend(
- colors,
- vim.tbl_filter(function(color)
- return color ~= before_color
- end, vim.fn.getcompletion("", "color"))
- )
-
- local previewer
- if opts.enable_preview then
- -- define previewer
- local bufnr = vim.api.nvim_get_current_buf()
- local p = vim.api.nvim_buf_get_name(bufnr)
-
- -- don't need previewer
- if vim.fn.buflisted(bufnr) ~= 1 then
- local deleted = false
- local function del_win(win_id)
- if win_id and vim.api.nvim_win_is_valid(win_id) then
- utils.buf_delete(vim.api.nvim_win_get_buf(win_id))
- pcall(vim.api.nvim_win_close, win_id, true)
- end
- end
-
- previewer = previewers.new {
- preview_fn = function(_, entry, status)
- if not deleted then
- deleted = true
- del_win(status.preview_win)
- del_win(status.preview_border_win)
- end
- vim.cmd("colorscheme " .. entry.value)
- end,
- }
- else
- -- show current buffer content in previewer
- previewer = previewers.new_buffer_previewer {
- get_buffer_by_name = function()
- return p
- end,
- define_preview = function(self, entry)
- if vim.loop.fs_stat(p) then
- conf.buffer_previewer_maker(p, self.state.bufnr, { bufname = self.state.bufname })
- else
- local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
- vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, lines)
- end
- vim.cmd("colorscheme " .. entry.value)
- end,
- }
- end
- end
-
- local picker = pickers.new(opts, {
- prompt_title = "Change Colorscheme",
- finder = finders.new_table {
- results = colors,
- },
- sorter = conf.generic_sorter(opts),
- previewer = previewer,
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.colorscheme"
- return
- end
-
- actions.close(prompt_bufnr)
- need_restore = false
- vim.cmd("colorscheme " .. selection.value)
- end)
-
- return true
- end,
- })
-
- if opts.enable_preview then
- -- rewrite picker.close_windows. restore color if needed
- local close_windows = picker.close_windows
- picker.close_windows = function(status)
- close_windows(status)
- if need_restore then
- vim.o.background = before_background
- vim.cmd("colorscheme " .. before_color)
- end
- end
- end
-
- picker:find()
-end
-
-internal.marks = function(opts)
- local local_marks = {
- items = vim.fn.getmarklist(opts.bufnr),
- name_func = function(_, line)
- return vim.api.nvim_buf_get_lines(opts.bufnr, line - 1, line, false)[1]
- end,
- }
- local global_marks = {
- items = vim.fn.getmarklist(),
- name_func = function(mark, _)
- -- get buffer name if it is opened, otherwise get file name
- return vim.api.nvim_get_mark(mark, {})[4]
- end,
- }
- local marks_table = {}
- local marks_others = {}
- local bufname = vim.api.nvim_buf_get_name(opts.bufnr)
- for _, cnf in ipairs { local_marks, global_marks } do
- for _, v in ipairs(cnf.items) do
- -- strip the first single quote character
- local mark = string.sub(v.mark, 2, 3)
- local _, lnum, col, _ = unpack(v.pos)
- local name = cnf.name_func(mark, lnum)
- -- same format to :marks command
- local line = string.format("%s %6d %4d %s", mark, lnum, col - 1, name)
- local row = {
- line = line,
- lnum = lnum,
- col = col,
- filename = v.file or bufname,
- }
- -- non alphanumeric marks goes to last
- if mark:match "%w" then
- table.insert(marks_table, row)
- else
- table.insert(marks_others, row)
- end
- end
- end
- marks_table = vim.fn.extend(marks_table, marks_others)
-
- pickers.new(opts, {
- prompt_title = "Marks",
- finder = finders.new_table {
- results = marks_table,
- entry_maker = opts.entry_maker or make_entry.gen_from_marks(opts),
- },
- previewer = conf.grep_previewer(opts),
- sorter = conf.generic_sorter(opts),
- push_cursor_on_edit = true,
- push_tagstack_on_edit = true,
- }):find()
-end
-
-internal.registers = function(opts)
- local registers_table = { '"', "_", "#", "=", "_", "/", "*", "+", ":", ".", "%" }
-
- -- named
- for i = 0, 9 do
- table.insert(registers_table, tostring(i))
- end
-
- -- alphabetical
- for i = 65, 90 do
- table.insert(registers_table, string.char(i))
- end
-
- pickers.new(opts, {
- prompt_title = "Registers",
- finder = finders.new_table {
- results = registers_table,
- entry_maker = opts.entry_maker or make_entry.gen_from_registers(opts),
- },
- -- use levenshtein as n-gram doesn't support <2 char matches
- sorter = sorters.get_levenshtein_sorter(),
- attach_mappings = function(_, map)
- actions.select_default:replace(actions.paste_register)
- map("i", "<C-e>", actions.edit_register)
-
- return true
- end,
- }):find()
-end
-
--- TODO: make filtering include the mapping and the action
-internal.keymaps = function(opts)
- opts.modes = vim.F.if_nil(opts.modes, { "n", "i", "c", "x" })
- opts.show_plug = vim.F.if_nil(opts.show_plug, true)
-
- local keymap_encountered = {} -- used to make sure no duplicates are inserted into keymaps_table
- local keymaps_table = {}
- local max_len_lhs = 0
-
- -- helper function to populate keymaps_table and determine max_len_lhs
- local function extract_keymaps(keymaps)
- for _, keymap in pairs(keymaps) do
- local keymap_key = keymap.buffer .. keymap.mode .. keymap.lhs -- should be distinct for every keymap
- if not keymap_encountered[keymap_key] then
- keymap_encountered[keymap_key] = true
- if opts.show_plug or not string.find(keymap.lhs, "<Plug>") then
- table.insert(keymaps_table, keymap)
- max_len_lhs = math.max(max_len_lhs, #utils.display_termcodes(keymap.lhs))
- end
- end
- end
- end
-
- for _, mode in pairs(opts.modes) do
- local global = vim.api.nvim_get_keymap(mode)
- local buf_local = vim.api.nvim_buf_get_keymap(0, mode)
- extract_keymaps(global)
- extract_keymaps(buf_local)
- end
- opts.width_lhs = max_len_lhs + 1
-
- pickers.new(opts, {
- prompt_title = "Key Maps",
- finder = finders.new_table {
- results = keymaps_table,
- entry_maker = opts.entry_maker or make_entry.gen_from_keymaps(opts),
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.keymaps"
- return
- end
-
- vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(selection.value.lhs, true, false, true), "t", true)
- return actions.close(prompt_bufnr)
- end)
- return true
- end,
- }):find()
-end
-
-internal.filetypes = function(opts)
- local filetypes = vim.fn.getcompletion("", "filetype")
-
- pickers.new(opts, {
- prompt_title = "Filetypes",
- finder = finders.new_table {
- results = filetypes,
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- print "[telescope] Nothing currently selected"
- return
- end
-
- actions.close(prompt_bufnr)
- vim.cmd("setfiletype " .. selection[1])
- end)
- return true
- end,
- }):find()
-end
-
-internal.highlights = function(opts)
- local highlights = vim.fn.getcompletion("", "highlight")
-
- pickers.new(opts, {
- prompt_title = "Highlights",
- finder = finders.new_table {
- results = highlights,
- entry_maker = opts.entry_maker or make_entry.gen_from_highlights(opts),
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.highlights"
- return
- end
-
- actions.close(prompt_bufnr)
- vim.cmd("hi " .. selection.value)
- end)
- return true
- end,
- previewer = previewers.highlights.new(opts),
- }):find()
-end
-
-internal.autocommands = function(opts)
- local autocmds = vim.api.nvim_get_autocmds {}
- table.sort(autocmds, function(lhs, rhs)
- return lhs.event < rhs.event
- end)
- pickers.new(opts, {
- prompt_title = "autocommands",
- finder = finders.new_table {
- results = autocmds,
- entry_maker = opts.entry_maker or make_entry.gen_from_autocommands(opts),
- },
- previewer = previewers.autocommands.new(opts),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- action_set.select:replace_if(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- return false
- end
- local val = selection.value
- local group_name = val.group_name ~= "<anonymous>" and val.group_name or ""
- local output = vim.fn.execute("verb autocmd " .. group_name .. " " .. val.event .. " " .. val.pattern, "silent")
- for line in output:gmatch "[^\r\n]+" do
- local source_file = line:match "Last set from (.*) line %d*$" or line:match "Last set from (.*)$"
- if source_file and source_file ~= "Lua" then
- selection.filename = source_file
- local source_lnum = line:match "line (%d*)$" or "1"
- selection.lnum = tonumber(source_lnum)
- selection.col = 1
- return false
- end
- end
- return true
- end, function()
- local selection = action_state.get_selected_entry()
- actions.close(prompt_bufnr)
- print("You selected autocmd: " .. vim.inspect(selection.value))
- end)
-
- return true
- end,
- }):find()
-end
-
-internal.spell_suggest = function(opts)
- local cursor_word = vim.fn.expand "<cword>"
- local suggestions = vim.fn.spellsuggest(cursor_word)
-
- pickers.new(opts, {
- prompt_title = "Spelling Suggestions",
- finder = finders.new_table {
- results = suggestions,
- },
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(prompt_bufnr)
- actions.select_default:replace(function()
- local selection = action_state.get_selected_entry()
- if selection == nil then
- utils.__warn_no_selection "builtin.spell_suggest"
- return
- end
-
- action_state.get_current_picker(prompt_bufnr)._original_mode = "i"
- actions.close(prompt_bufnr)
- vim.cmd("normal! ciw" .. selection[1])
- vim.cmd "stopinsert"
- end)
- return true
- end,
- }):find()
-end
-
-internal.tagstack = function(opts)
- opts = opts or {}
- local tagstack = vim.fn.gettagstack().items
-
- local tags = {}
- for i = #tagstack, 1, -1 do
- local tag = tagstack[i]
- tag.bufnr = tag.from[1]
- if vim.api.nvim_buf_is_valid(tag.bufnr) then
- tags[#tags + 1] = tag
- tag.filename = vim.fn.bufname(tag.bufnr)
- tag.lnum = tag.from[2]
- tag.col = tag.from[3]
-
- tag.text = vim.api.nvim_buf_get_lines(tag.bufnr, tag.lnum - 1, tag.lnum, false)[1] or ""
- end
- end
-
- if vim.tbl_isempty(tags) then
- utils.notify("builtin.tagstack", {
- msg = "No tagstack available",
- level = "WARN",
- })
- return
- end
-
- pickers.new(opts, {
- prompt_title = "TagStack",
- finder = finders.new_table {
- results = tags,
- entry_maker = make_entry.gen_from_quickfix(opts),
- },
- previewer = conf.qflist_previewer(opts),
- sorter = conf.generic_sorter(opts),
- }):find()
-end
-
-internal.jumplist = function(opts)
- opts = opts or {}
- local jumplist = vim.fn.getjumplist()[1]
-
- -- reverse the list
- local sorted_jumplist = {}
- for i = #jumplist, 1, -1 do
- if vim.api.nvim_buf_is_valid(jumplist[i].bufnr) then
- jumplist[i].text = vim.api.nvim_buf_get_lines(jumplist[i].bufnr, jumplist[i].lnum, jumplist[i].lnum + 1, false)[1]
- or ""
- table.insert(sorted_jumplist, jumplist[i])
- end
- end
-
- pickers.new(opts, {
- prompt_title = "Jumplist",
- finder = finders.new_table {
- results = sorted_jumplist,
- entry_maker = make_entry.gen_from_quickfix(opts),
- },
- previewer = conf.qflist_previewer(opts),
- 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 require("telescope.builtin")[k]
+ end,
+})
-return apply_checks(internal)
+return m
diff --git a/lua/telescope/builtin/lsp.lua b/lua/telescope/builtin/lsp.lua
index 480d456..8c297dc 100644
--- a/lua/telescope/builtin/lsp.lua
+++ b/lua/telescope/builtin/lsp.lua
@@ -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 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)
+local m = setmetatable({}, {
+ __index = function(_, k)
+ local utils = require "telescope.utils"
+ 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",
+ })
+ return require("telescope.builtin")["lsp_" .. k]
+ end,
+})
+
+return m