mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 02:50:03 +08:00
303 lines
6.9 KiB
Lua
303 lines
6.9 KiB
Lua
local View = require("trouble.view")
|
|
local config = require("trouble.config")
|
|
local colors = require("trouble.colors")
|
|
local util = require("trouble.util")
|
|
|
|
colors.setup()
|
|
|
|
local Trouble = {}
|
|
|
|
local view
|
|
|
|
function Trouble.is_open()
|
|
return view and view:is_valid() or false
|
|
end
|
|
|
|
function Trouble.setup(options)
|
|
if vim.fn.has("nvim-0.7.2") == 0 then
|
|
util.error("Trouble needs Neovim >= 0.7.2")
|
|
return
|
|
end
|
|
config.setup(options)
|
|
util.fix_mode(config.options)
|
|
colors.setup()
|
|
end
|
|
|
|
function Trouble.close()
|
|
if Trouble.is_open() then
|
|
view:close()
|
|
end
|
|
end
|
|
|
|
local function get_opts(...)
|
|
local args = { ... }
|
|
if vim.tbl_islist(args) and #args == 1 and type(args[1]) == "table" then
|
|
args = args[1]
|
|
end
|
|
local opts = {}
|
|
for key, value in pairs(args) do
|
|
if type(key) == "number" then
|
|
local k, v = value:match("^(.*)=(.*)$")
|
|
if k then
|
|
opts[k] = v
|
|
elseif opts.mode then
|
|
util.error("unknown option " .. value)
|
|
else
|
|
opts.mode = value
|
|
end
|
|
else
|
|
opts[key] = value
|
|
end
|
|
end
|
|
opts = opts or {}
|
|
util.fix_mode(opts)
|
|
config.options.cmd_options = opts
|
|
return opts
|
|
end
|
|
|
|
function Trouble.open(...)
|
|
local opts = get_opts(...)
|
|
if opts.mode and (opts.mode ~= config.options.mode) then
|
|
config.options.mode = opts.mode
|
|
end
|
|
|
|
if opts.severity and (opts.severity ~=config.options.severity) then
|
|
config.options.severity = opts.severity
|
|
end
|
|
|
|
opts.focus = true
|
|
opts.on_open = true
|
|
|
|
if Trouble.is_open() then
|
|
Trouble.refresh(opts)
|
|
elseif not opts.auto and vim.tbl_contains(config.options.auto_jump, opts.mode) then
|
|
require("trouble.providers").get(vim.api.nvim_get_current_win(), vim.api.nvim_get_current_buf(), function(results)
|
|
if #results == 1 then
|
|
util.jump_to_item(opts.win, opts.precmd, results[1])
|
|
elseif #results > 0 then
|
|
view = View.create(opts)
|
|
end
|
|
end, config.options)
|
|
else
|
|
view = View.create(opts)
|
|
end
|
|
end
|
|
|
|
function Trouble.toggle(...)
|
|
local opts = get_opts(...)
|
|
|
|
if opts.mode and (opts.mode ~= config.options.mode) then
|
|
config.options.mode = opts.mode
|
|
Trouble.open(...)
|
|
return
|
|
end
|
|
|
|
if Trouble.is_open() then
|
|
Trouble.close()
|
|
else
|
|
Trouble.open(...)
|
|
end
|
|
end
|
|
|
|
function Trouble.help()
|
|
local lines = { "# Key Bindings" }
|
|
local height = 1
|
|
for command, key in pairs(config.options.action_keys) do
|
|
if type(key) == "table" then
|
|
key = table.concat(key, " | ")
|
|
end
|
|
table.insert(lines, " * **" .. key .. "** " .. command:gsub("_", " "))
|
|
height = height + 1
|
|
end
|
|
-- help
|
|
vim.lsp.util.open_floating_preview(lines, "markdown", {
|
|
border = "single",
|
|
height = 20,
|
|
offset_y = -2,
|
|
offset_x = 2,
|
|
})
|
|
end
|
|
|
|
local updater = util.debounce(100, function()
|
|
-- buff might have been closed during the debounce
|
|
if not Trouble.is_open() then
|
|
util.debug("refresh: not open anymore")
|
|
return
|
|
end
|
|
|
|
util.debug("refresh: auto")
|
|
view:update({ auto = true })
|
|
end)
|
|
|
|
function Trouble.refresh(opts)
|
|
opts = opts or {}
|
|
|
|
-- dont do an update if this is an automated refresh from a different provider
|
|
if opts.auto then
|
|
if opts.provider == "diagnostics" and config.options.mode == "document_diagnostics" then
|
|
opts.provider = "document_diagnostics"
|
|
elseif opts.provider == "diagnostics" and config.options.mode == "workspace_diagnostics" then
|
|
opts.provider = "workspace_diagnostics"
|
|
elseif opts.provider == "qf" and config.options.mode == "quickfix" then
|
|
opts.provider = "quickfix"
|
|
elseif opts.provider == "qf" and config.options.mode == "loclist" then
|
|
opts.provider = "loclist"
|
|
end
|
|
if opts.provider ~= config.options.mode then
|
|
return
|
|
end
|
|
end
|
|
|
|
if Trouble.is_open() then
|
|
if opts.auto then
|
|
updater()
|
|
else
|
|
util.debug("refresh")
|
|
view:update(opts)
|
|
end
|
|
elseif opts.auto and config.options.auto_open and opts.provider == config.options.mode then
|
|
require("trouble.providers").get(vim.api.nvim_get_current_win(), vim.api.nvim_get_current_buf(), function(results)
|
|
if #results > 0 then
|
|
Trouble.open(opts)
|
|
end
|
|
end, config.options)
|
|
end
|
|
end
|
|
|
|
function Trouble.action(action)
|
|
if action == "toggle_mode" then
|
|
if config.options.mode == "document_diagnostics" then
|
|
config.options.mode = "workspace_diagnostics"
|
|
elseif config.options.mode == "workspace_diagnostics" then
|
|
config.options.mode = "document_diagnostics"
|
|
end
|
|
action = "refresh"
|
|
end
|
|
|
|
if action == 'switch_severity' then
|
|
if config.options.severity == nil then
|
|
config.options.severity = vim.diagnostic.severity.ERROR
|
|
elseif config.options.severity < 4 then
|
|
config.options.severity = config.options.severity + 1
|
|
else
|
|
config.options.severity = nil
|
|
end
|
|
action = "refresh"
|
|
end
|
|
|
|
if view and action == "on_win_enter" then
|
|
view:on_win_enter()
|
|
end
|
|
if not Trouble.is_open() then
|
|
return Trouble
|
|
end
|
|
if action == "hover" then
|
|
view:hover()
|
|
end
|
|
if action == "jump" then
|
|
view:jump()
|
|
elseif action == "open_split" then
|
|
view:jump({ precmd = "split" })
|
|
elseif action == "open_vsplit" then
|
|
view:jump({ precmd = "vsplit" })
|
|
elseif action == "open_tab" then
|
|
view:jump({ precmd = "tabe" })
|
|
end
|
|
if action == "jump_close" then
|
|
view:jump()
|
|
Trouble.close()
|
|
end
|
|
if action == "open_folds" then
|
|
Trouble.refresh({ open_folds = true })
|
|
end
|
|
if action == "close_folds" then
|
|
Trouble.refresh({ close_folds = true })
|
|
end
|
|
if action == "toggle_fold" then
|
|
view:toggle_fold()
|
|
end
|
|
if action == "on_enter" then
|
|
view:on_enter()
|
|
end
|
|
if action == "on_leave" then
|
|
view:on_leave()
|
|
end
|
|
if action == "cancel" then
|
|
view:switch_to_parent()
|
|
end
|
|
if action == "next" then
|
|
view:next_item()
|
|
return Trouble
|
|
end
|
|
if action == "previous" then
|
|
view:previous_item()
|
|
return Trouble
|
|
end
|
|
if action == "first" then
|
|
view:first_item()
|
|
return Trouble
|
|
end
|
|
if action == "last" then
|
|
view:last_item()
|
|
return Trouble
|
|
end
|
|
|
|
if action == "toggle_preview" then
|
|
config.options.auto_preview = not config.options.auto_preview
|
|
if not config.options.auto_preview then
|
|
view:close_preview()
|
|
else
|
|
action = "preview"
|
|
end
|
|
end
|
|
if action == "auto_preview" and config.options.auto_preview then
|
|
action = "preview"
|
|
end
|
|
if action == "preview" then
|
|
view:preview()
|
|
end
|
|
|
|
if Trouble[action] then
|
|
Trouble[action]()
|
|
end
|
|
return Trouble
|
|
end
|
|
|
|
function Trouble.next(opts)
|
|
util.fix_mode(opts)
|
|
if view then
|
|
view:next_item(opts)
|
|
end
|
|
end
|
|
|
|
function Trouble.previous(opts)
|
|
util.fix_mode(opts)
|
|
if view then
|
|
view:previous_item(opts)
|
|
end
|
|
end
|
|
|
|
function Trouble.first(opts)
|
|
util.fix_mode(opts)
|
|
if view then
|
|
view:first_item(opts)
|
|
end
|
|
end
|
|
|
|
function Trouble.last(opts)
|
|
util.fix_mode(opts)
|
|
if view then
|
|
view:last_item(opts)
|
|
end
|
|
end
|
|
|
|
function Trouble.get_items()
|
|
if view ~= nil then
|
|
return view.items
|
|
else
|
|
return {}
|
|
end
|
|
end
|
|
|
|
return Trouble
|