* fix(__internal) : fix slash problem in oldfiles - Problems Problem with slash and backslash being mixed up is chronic issue of neovim in Windows. it makes telescope prompt perceive same path differently when it execute to oldfiles picker. some function like `nvim_buf_get_name()` or `vim.v.oldfiles` give paths which are mixed up with slash and backslash. - What it did For windows, it always needs to change slash(/) to backslash(\) when function which deal with path because entry_maker works properly only the case that path string has \ not /. - Effect 1) oldfiles picker doesn't show duplicated list 2) `defaults.path_display` configuration feature will works well at oldfiles pikcer * fix(__internal) : Repeated comments are erased
1518 lines
45 KiB
Lua
1518 lines
45 KiB
Lua
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 state = require "telescope.state"
|
|
local utils = require "telescope.utils"
|
|
|
|
local conf = require("telescope.config").values
|
|
|
|
-- 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
|
|
|
|
---@return boolean
|
|
local function buf_in_cwd(bufname, cwd)
|
|
if cwd:sub(-1) ~= Path.path.sep then
|
|
cwd = cwd .. Path.path.sep
|
|
end
|
|
local bufname_prefix = bufname:sub(1, #cwd)
|
|
return bufname_prefix == cwd
|
|
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
|
|
|
|
table.sort(objs, function(a, b)
|
|
return a.text < b.text
|
|
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(prompt_bufnr)
|
|
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
|
|
|
|
actions.close(prompt_bufnr)
|
|
vim.schedule(function()
|
|
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)
|
|
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
|
|
opts.resumed_picker = true
|
|
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 curr_picker = action_state.get_current_picker(prompt_bufnr)
|
|
local curr_entry = action_state.get_selected_entry()
|
|
if not curr_entry then
|
|
return
|
|
end
|
|
|
|
actions.close(prompt_bufnr)
|
|
|
|
local selection_index, _ = utils.list_find(function(v)
|
|
if curr_entry.value == v.value then
|
|
return true
|
|
end
|
|
return false
|
|
end, curr_picker.finder.results)
|
|
|
|
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", "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 show_moon = opts.show_moon 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") and (show_moon or not v:find "moon") 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
|
|
local cr = vim.api.nvim_replace_termcodes("<cr>", true, false, true)
|
|
cmd = cmd .. cr
|
|
end
|
|
vim.cmd [[stopinsert]]
|
|
vim.api.nvim_feedkeys(cmd, "nt", false)
|
|
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
|
|
utils.notify("builtin.quickfix", { msg = "No quickfix items", level = "INFO" })
|
|
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(_, map)
|
|
action_set.select:replace(function(prompt_bufnr)
|
|
local nr = action_state.get_selected_entry().nr
|
|
actions.close(prompt_bufnr)
|
|
internal.quickfix { nr = nr }
|
|
end)
|
|
|
|
map({ "i", "n" }, "<C-q>", function(prompt_bufnr)
|
|
local nr = action_state.get_selected_entry().nr
|
|
actions.close(prompt_bufnr)
|
|
vim.cmd(nr .. "chistory")
|
|
vim.cmd "botright copen"
|
|
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
|
|
utils.notify("builtin.loclist", { msg = "No loclist items", level = "INFO" })
|
|
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 utils.iswin then -- for slash problem in windows
|
|
current_file = current_file:gsub("/", "\\")
|
|
end
|
|
|
|
if opts.include_current_session then
|
|
for _, buffer in ipairs(utils.split_lines(vim.fn.execute ":buffers! t")) 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 utils.iswin then
|
|
file = file:gsub("/", "\\")
|
|
end
|
|
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 utils.iswin then
|
|
file = file:gsub("/", "\\")
|
|
end
|
|
local file_stat = vim.loop.fs_stat(file)
|
|
if file_stat and file_stat.type == "file" and not vim.tbl_contains(results, file) and file ~= current_file then
|
|
table.insert(results, file)
|
|
end
|
|
end
|
|
|
|
if opts.cwd_only or opts.cwd then
|
|
local cwd = opts.cwd_only and vim.loop.cwd() or opts.cwd
|
|
results = vim.tbl_filter(function(file)
|
|
return buf_in_cwd(file, cwd)
|
|
end, results)
|
|
end
|
|
|
|
pickers
|
|
.new(opts, {
|
|
prompt_title = "Oldfiles",
|
|
__locations_input = true,
|
|
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.grep_previewer(opts),
|
|
})
|
|
:find()
|
|
end
|
|
|
|
internal.command_history = function(opts)
|
|
local history_string = vim.fn.execute "history cmd"
|
|
local history_list = utils.split_lines(history_string)
|
|
|
|
local results = {}
|
|
local filter_fn = opts.filter_fn
|
|
|
|
for i = #history_list, 3, -1 do
|
|
local item = history_list[i]
|
|
local _, finish = string.find(item, "%d+ +")
|
|
local cmd = string.sub(item, finish + 1)
|
|
|
|
if filter_fn then
|
|
if filter_fn(cmd) then
|
|
table.insert(results, cmd)
|
|
end
|
|
else
|
|
table.insert(results, cmd)
|
|
end
|
|
end
|
|
|
|
pickers
|
|
.new(opts, {
|
|
prompt_title = "Command History",
|
|
finder = finders.new_table(results),
|
|
sorter = conf.generic_sorter(opts),
|
|
|
|
attach_mappings = function(_, map)
|
|
actions.select_default:replace(actions.set_command_line)
|
|
map({ "i", "n" }, "<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 = utils.split_lines(search_string)
|
|
|
|
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)
|
|
actions.select_default:replace(actions.set_search_line)
|
|
map({ "i", "n" }, "<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, ",", { trimempty = 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 rtp = vim.o.runtimepath
|
|
-- extend the runtime path with all plugins not loaded by lazy.nvim
|
|
local lazy = package.loaded["lazy.core.util"]
|
|
if lazy and lazy.get_unloaded_rtp then
|
|
local paths = lazy.get_unloaded_rtp ""
|
|
if #paths > 0 then
|
|
rtp = rtp .. "," .. table.concat(paths, ",")
|
|
end
|
|
end
|
|
local all_files = vim.fn.globpath(rtp, "doc/*", 1, 1)
|
|
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 = utils.split_lines(Path:new(file):read(), { trimempty = 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, { trimempty = 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(utils.islist(opts.sections), "sections should be a list")
|
|
opts.man_cmd = utils.get_lazy_default(opts.man_cmd, function()
|
|
local uname = vim.loop.os_uname()
|
|
local sysname = string.lower(uname.sysname)
|
|
if sysname == "darwin" then
|
|
local major_version = tonumber(vim.fn.matchlist(uname.release, [[^\(\d\+\)\..*]])[2]) or 0
|
|
return major_version >= 22 and { "apropos", "." } or { "apropos", " " }
|
|
elseif sysname == "freebsd" then
|
|
return { "apropos", "." }
|
|
else
|
|
return { "apropos", "" }
|
|
end
|
|
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 = vim.tbl_filter(function(bufnr)
|
|
if 1 ~= vim.fn.buflisted(bufnr) 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(bufnr) then
|
|
return false
|
|
end
|
|
if opts.ignore_current_buffer and bufnr == vim.api.nvim_get_current_buf() then
|
|
return false
|
|
end
|
|
|
|
local bufname = vim.api.nvim_buf_get_name(bufnr)
|
|
|
|
if opts.cwd_only and not buf_in_cwd(bufname, vim.loop.cwd()) then
|
|
return false
|
|
end
|
|
if not opts.cwd_only and opts.cwd and not buf_in_cwd(bufname, opts.cwd) then
|
|
return false
|
|
end
|
|
return true
|
|
end, vim.api.nvim_list_bufs())
|
|
|
|
if not next(bufnrs) then
|
|
utils.notify("builtin.buffers", { msg = "No buffers found with the provided options", level = "INFO" })
|
|
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
|
|
|
|
if type(opts.sort_buffers) == "function" then
|
|
table.sort(bufnrs, opts.sort_buffers)
|
|
end
|
|
|
|
local buffers = {}
|
|
local default_selection_idx = 1
|
|
for i, 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
|
|
if opts.select_current and flag == "%" then
|
|
default_selection_idx = i
|
|
end
|
|
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,
|
|
attach_mappings = function(_, map)
|
|
map({ "i", "n" }, "<M-d>", actions.delete_buffer)
|
|
return true
|
|
end,
|
|
})
|
|
:find()
|
|
end
|
|
|
|
internal.colorscheme = function(opts)
|
|
local before_background = vim.o.background
|
|
local before_color = vim.api.nvim_exec2("colorscheme", { output = true }).output
|
|
local need_restore = not not opts.enable_preview
|
|
|
|
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 not vim.tbl_contains(colors, color)
|
|
end, vim.fn.getcompletion("", "color"))
|
|
)
|
|
|
|
-- if lazy is available, extend the colors list with unloaded colorschemes
|
|
local lazy = package.loaded["lazy.core.util"]
|
|
if lazy and lazy.get_unloaded_rtp then
|
|
local paths = lazy.get_unloaded_rtp ""
|
|
local all_files = vim.fn.globpath(table.concat(paths, ","), "colors/*", 1, 1)
|
|
for _, f in ipairs(all_files) do
|
|
local color = vim.fn.fnamemodify(f, ":t:r")
|
|
if not vim.tbl_contains(colors, color) then
|
|
table.insert(colors, color)
|
|
end
|
|
end
|
|
end
|
|
|
|
if opts.ignore_builtins then
|
|
-- stylua: ignore
|
|
local builtins = {
|
|
"blue", "darkblue", "default", "delek", "desert", "elflord", "evening",
|
|
"habamax", "industry", "koehler", "lunaperche", "morning", "murphy",
|
|
"pablo", "peachpuff", "quiet", "retrobox", "ron", "shine", "slate",
|
|
"sorbet", "torte", "vim", "wildcharm", "zaibatsu", "zellner",
|
|
}
|
|
colors = vim.tbl_filter(function(color)
|
|
return not vim.tbl_contains(builtins, color)
|
|
end, colors)
|
|
end
|
|
|
|
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)
|
|
|
|
-- show current buffer content in previewer
|
|
previewer = previewers.new_buffer_previewer {
|
|
get_buffer_by_name = function()
|
|
return p
|
|
end,
|
|
define_preview = function(self)
|
|
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
|
|
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
|
|
|
|
need_restore = false
|
|
actions.close(prompt_bufnr)
|
|
vim.cmd.colorscheme(selection.value)
|
|
end)
|
|
return true
|
|
end,
|
|
on_complete = {
|
|
function()
|
|
local selection = action_state.get_selected_entry()
|
|
if selection == nil then
|
|
utils.__warn_no_selection "builtin.colorscheme"
|
|
return
|
|
end
|
|
if opts.enable_preview then
|
|
vim.cmd.colorscheme(selection.value)
|
|
end
|
|
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
|
|
|
|
-- rewrite picker.set_selection so that color schemes can be previewed when the current
|
|
-- selection is shifted using the keyboard or if an item is clicked with the mouse
|
|
local set_selection = picker.set_selection
|
|
picker.set_selection = function(self, row)
|
|
set_selection(self, row)
|
|
local selection = action_state.get_selected_entry()
|
|
if selection == nil then
|
|
utils.__warn_no_selection "builtin.colorscheme"
|
|
return
|
|
end
|
|
if opts.enable_preview then
|
|
vim.cmd.colorscheme(selection.value)
|
|
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)
|
|
local all_marks = {}
|
|
opts.mark_type = vim.F.if_nil(opts.mark_type, "all")
|
|
if opts.mark_type == "all" then
|
|
all_marks = { local_marks, global_marks }
|
|
elseif opts.mark_type == "local" then
|
|
all_marks = { local_marks }
|
|
elseif opts.mark_type == "global" then
|
|
all_marks = { global_marks }
|
|
end
|
|
|
|
for _, cnf in ipairs(all_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 = utils.path_expand(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),
|
|
},
|
|
sorter = conf.generic_sorter(opts),
|
|
attach_mappings = function(_, map)
|
|
actions.select_default:replace(actions.paste_register)
|
|
map({ "i", "n" }, "<C-e>", actions.edit_register)
|
|
|
|
return true
|
|
end,
|
|
})
|
|
:find()
|
|
end
|
|
|
|
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)
|
|
opts.only_buf = vim.F.if_nil(opts.only_buf, false)
|
|
|
|
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>"))
|
|
and (not opts.lhs_filter or opts.lhs_filter(keymap.lhs))
|
|
and (not opts.filter or opts.filter(keymap))
|
|
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)
|
|
if not opts.only_buf then
|
|
extract_keymaps(global)
|
|
end
|
|
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 cb = val.callback
|
|
if vim.is_callable(cb) then
|
|
if type(cb) ~= "string" then
|
|
local f = type(cb) == "function" and cb or rawget(getmetatable(cb), "__call")
|
|
local info = debug.getinfo(f, "S")
|
|
local file = info.source:match "^@(.+)"
|
|
local lnum = info.linedefined
|
|
if file and (lnum or 0) > 0 then
|
|
selection.filename, selection.lnum, selection.col = file, lnum, 1
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
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 - 1, jumplist[i].lnum, 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)
|