build: selene + stylua
This commit is contained in:
parent
0f584688c3
commit
135d4e95dd
|
@ -1,36 +1,36 @@
|
|||
local M = {}
|
||||
|
||||
local links = {
|
||||
Error = "LspDiagnosticsDefaultError",
|
||||
Warning = "LspDiagnosticsDefaultWarning",
|
||||
Information = "LspDiagnosticsDefaultInformation",
|
||||
Hint = "LspDiagnosticsDefaultHint",
|
||||
SignError = "LspDiagnosticsSignError",
|
||||
SignWarning = "LspDiagnosticsSignWarning",
|
||||
SignInformation = "LspDiagnosticsSignInformation",
|
||||
SignHint = "LspDiagnosticsSignHint",
|
||||
TextError = "LspTroubleText",
|
||||
TextWarning = "LspTroubleText",
|
||||
TextInformation = "LspTroubleText",
|
||||
TextHint = "LspTroubleText",
|
||||
Text = "Normal",
|
||||
File = "Directory",
|
||||
Source = "Comment",
|
||||
Code = "Comment",
|
||||
Location = "LineNr",
|
||||
FoldIcon = "CursorLineNr",
|
||||
Normal = "Normal",
|
||||
Count = "TabLineSel",
|
||||
Preview = "Search",
|
||||
Indent = "LineNr",
|
||||
SignOther = "LspTroubleSignInformation"
|
||||
Error = "LspDiagnosticsDefaultError",
|
||||
Warning = "LspDiagnosticsDefaultWarning",
|
||||
Information = "LspDiagnosticsDefaultInformation",
|
||||
Hint = "LspDiagnosticsDefaultHint",
|
||||
SignError = "LspDiagnosticsSignError",
|
||||
SignWarning = "LspDiagnosticsSignWarning",
|
||||
SignInformation = "LspDiagnosticsSignInformation",
|
||||
SignHint = "LspDiagnosticsSignHint",
|
||||
TextError = "LspTroubleText",
|
||||
TextWarning = "LspTroubleText",
|
||||
TextInformation = "LspTroubleText",
|
||||
TextHint = "LspTroubleText",
|
||||
Text = "Normal",
|
||||
File = "Directory",
|
||||
Source = "Comment",
|
||||
Code = "Comment",
|
||||
Location = "LineNr",
|
||||
FoldIcon = "CursorLineNr",
|
||||
Normal = "Normal",
|
||||
Count = "TabLineSel",
|
||||
Preview = "Search",
|
||||
Indent = "LineNr",
|
||||
SignOther = "LspTroubleSignInformation",
|
||||
}
|
||||
|
||||
function M.setup()
|
||||
for k, v in pairs(links) do
|
||||
vim.api.nvim_command('hi def link LspTrouble' .. k .. ' ' .. v)
|
||||
vim.api.nvim_command('hi def link Trouble' .. k .. ' LspTrouble' .. k)
|
||||
end
|
||||
for k, v in pairs(links) do
|
||||
vim.api.nvim_command("hi def link LspTrouble" .. k .. " " .. v)
|
||||
vim.api.nvim_command("hi def link Trouble" .. k .. " LspTrouble" .. k)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -5,45 +5,47 @@ M.namespace = vim.api.nvim_create_namespace("Trouble")
|
|||
---@class Options
|
||||
---@field buf number|nil
|
||||
---@field win number|nil
|
||||
-- TODO: make some options configurable per mode
|
||||
-- TODO: make it possible to have multiple trouble lists open at the same time
|
||||
local defaults = {
|
||||
debug = false,
|
||||
position = "bottom", -- position of the list can be: bottom, top, left, right
|
||||
height = 10, -- height of the trouble list when position is top or bottom
|
||||
width = 50, -- width of the list when position is left or right
|
||||
icons = true, -- use devicons for filenames
|
||||
mode = "lsp_workspace_diagnostics", -- "lsp_workspace_diagnostics", "lsp_document_diagnostics", "quickfix", "lsp_references", "loclist"
|
||||
fold_open = "", -- icon used for open folds
|
||||
fold_closed = "", -- icon used for closed folds
|
||||
action_keys = { -- key mappings for actions in the trouble list
|
||||
close = "q", -- close the list
|
||||
cancel = "<esc>", -- cancel the preview and get back to your last window / buffer / cursor
|
||||
refresh = "r", -- manually refresh
|
||||
jump = {"<cr>", "<tab>"}, -- jump to the diagnostic or open / close folds
|
||||
jump_close = {"o"}, -- jump to the diagnostic and close the list
|
||||
toggle_mode = "m", -- toggle between "workspace" and "document" mode
|
||||
toggle_preview = "P", -- toggle auto_preview
|
||||
hover = "K", -- opens a small poup with the full multiline message
|
||||
preview = "p", -- preview the diagnostic location
|
||||
close_folds = {"zM", "zm"}, -- close all folds
|
||||
open_folds = {"zR", "zr"}, -- open all folds
|
||||
toggle_fold = {"zA", "za"}, -- toggle fold of current file
|
||||
previous = "k", -- preview item
|
||||
next = "j" -- next item
|
||||
},
|
||||
indent_lines = true, -- add an indent guide below the fold icons
|
||||
auto_open = false, -- automatically open the list when you have diagnostics
|
||||
auto_close = false, -- automatically close the list when you have no diagnostics
|
||||
auto_preview = true, -- automatyically preview the location of the diagnostic. <esc> to close preview and go back to last window
|
||||
auto_fold = false, -- automatically fold a file trouble list at creation
|
||||
signs = {
|
||||
-- icons / text used for a diagnostic
|
||||
error = "",
|
||||
warning = "",
|
||||
hint = "",
|
||||
information = "",
|
||||
other = ""
|
||||
},
|
||||
use_lsp_diagnostic_signs = false -- enabling this will use the signs defined in your lsp client
|
||||
debug = false,
|
||||
position = "bottom", -- position of the list can be: bottom, top, left, right
|
||||
height = 10, -- height of the trouble list when position is top or bottom
|
||||
width = 50, -- width of the list when position is left or right
|
||||
icons = true, -- use devicons for filenames
|
||||
mode = "lsp_workspace_diagnostics", -- "lsp_workspace_diagnostics", "lsp_document_diagnostics", "quickfix", "lsp_references", "loclist"
|
||||
fold_open = "", -- icon used for open folds
|
||||
fold_closed = "", -- icon used for closed folds
|
||||
action_keys = { -- key mappings for actions in the trouble list
|
||||
close = "q", -- close the list
|
||||
cancel = "<esc>", -- cancel the preview and get back to your last window / buffer / cursor
|
||||
refresh = "r", -- manually refresh
|
||||
jump = { "<cr>", "<tab>" }, -- jump to the diagnostic or open / close folds
|
||||
jump_close = { "o" }, -- jump to the diagnostic and close the list
|
||||
toggle_mode = "m", -- toggle between "workspace" and "document" mode
|
||||
toggle_preview = "P", -- toggle auto_preview
|
||||
hover = "K", -- opens a small poup with the full multiline message
|
||||
preview = "p", -- preview the diagnostic location
|
||||
close_folds = { "zM", "zm" }, -- close all folds
|
||||
open_folds = { "zR", "zr" }, -- open all folds
|
||||
toggle_fold = { "zA", "za" }, -- toggle fold of current file
|
||||
previous = "k", -- preview item
|
||||
next = "j", -- next item
|
||||
},
|
||||
indent_lines = true, -- add an indent guide below the fold icons
|
||||
auto_open = false, -- automatically open the list when you have diagnostics
|
||||
auto_close = false, -- automatically close the list when you have no diagnostics
|
||||
auto_preview = true, -- automatyically preview the location of the diagnostic. <esc> to close preview and go back to last window
|
||||
auto_fold = false, -- automatically fold a file trouble list at creation
|
||||
signs = {
|
||||
-- icons / text used for a diagnostic
|
||||
error = "",
|
||||
warning = "",
|
||||
hint = "",
|
||||
information = "",
|
||||
other = "",
|
||||
},
|
||||
use_lsp_diagnostic_signs = false, -- enabling this will use the signs defined in your lsp client
|
||||
}
|
||||
|
||||
---@type Options
|
||||
|
@ -51,16 +53,16 @@ M.options = {}
|
|||
|
||||
---@return Options
|
||||
function M.setup(options)
|
||||
M.options = vim.tbl_deep_extend("force", {}, defaults, options or {})
|
||||
M.fix_mode(M.options)
|
||||
M.options = vim.tbl_deep_extend("force", {}, defaults, options or {})
|
||||
M.fix_mode(M.options)
|
||||
end
|
||||
|
||||
function M.fix_mode(opts)
|
||||
if opts.mode == "workspace" then
|
||||
opts.mode = "lsp_workspace_diagnostics"
|
||||
elseif opts.mode == "document" then
|
||||
opts.mode = "lsp_document_diagnostics"
|
||||
end
|
||||
if opts.mode == "workspace" then
|
||||
opts.mode = "lsp_workspace_diagnostics"
|
||||
elseif opts.mode == "document" then
|
||||
opts.mode = "lsp_document_diagnostics"
|
||||
end
|
||||
end
|
||||
|
||||
M.setup()
|
||||
|
|
|
@ -5,14 +5,20 @@ local M = {}
|
|||
M.folded = {}
|
||||
|
||||
function M.is_folded(filename)
|
||||
local fold = M.folded[filename]
|
||||
return (fold == nil and config.options.auto_fold == true) or (fold == true)
|
||||
local fold = M.folded[filename]
|
||||
return (fold == nil and config.options.auto_fold == true) or (fold == true)
|
||||
end
|
||||
|
||||
function M.toggle(filename) M.folded[filename] = not M.is_folded(filename) end
|
||||
function M.toggle(filename)
|
||||
M.folded[filename] = not M.is_folded(filename)
|
||||
end
|
||||
|
||||
function M.close(filename) M.folded[filename] = true end
|
||||
function M.close(filename)
|
||||
M.folded[filename] = true
|
||||
end
|
||||
|
||||
function M.open(filename) M.folded[filename] = false end
|
||||
function M.open(filename)
|
||||
M.folded[filename] = false
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -9,150 +9,191 @@ local Trouble = {}
|
|||
|
||||
local view
|
||||
|
||||
local function is_open() return view and view:is_valid() end
|
||||
|
||||
function Trouble.setup(options)
|
||||
config.setup(options)
|
||||
colors.setup()
|
||||
local function is_open()
|
||||
return view and view:is_valid()
|
||||
end
|
||||
|
||||
function Trouble.close() if is_open() then view:close() end end
|
||||
function Trouble.setup(options)
|
||||
config.setup(options)
|
||||
colors.setup()
|
||||
end
|
||||
|
||||
function Trouble.close()
|
||||
if is_open() then
|
||||
view:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function get_opts(opts)
|
||||
opts = opts or {}
|
||||
if type(opts) == "string" then opts = {mode = opts} end
|
||||
config.fix_mode(opts)
|
||||
return opts
|
||||
opts = opts or {}
|
||||
if type(opts) == "string" then
|
||||
opts = { mode = opts }
|
||||
end
|
||||
config.fix_mode(opts)
|
||||
return opts
|
||||
end
|
||||
|
||||
function Trouble.open(opts)
|
||||
opts = get_opts(opts)
|
||||
if opts.mode and (opts.mode ~= config.options.mode) then
|
||||
config.options.mode = opts.mode
|
||||
end
|
||||
opts.focus = true
|
||||
opts = get_opts(opts)
|
||||
if opts.mode and (opts.mode ~= config.options.mode) then
|
||||
config.options.mode = opts.mode
|
||||
end
|
||||
opts.focus = true
|
||||
|
||||
if is_open() then
|
||||
Trouble.refresh(opts)
|
||||
else
|
||||
view = View.create(opts)
|
||||
end
|
||||
if is_open() then
|
||||
Trouble.refresh(opts)
|
||||
else
|
||||
view = View.create(opts)
|
||||
end
|
||||
end
|
||||
|
||||
function Trouble.toggle(opts)
|
||||
opts = get_opts(opts)
|
||||
opts = get_opts(opts)
|
||||
|
||||
if opts.mode and (opts.mode ~= config.options.mode) then
|
||||
config.options.mode = opts.mode
|
||||
Trouble.open()
|
||||
return
|
||||
end
|
||||
if opts.mode and (opts.mode ~= config.options.mode) then
|
||||
config.options.mode = opts.mode
|
||||
Trouble.open()
|
||||
return
|
||||
end
|
||||
|
||||
if is_open() then
|
||||
Trouble.close()
|
||||
else
|
||||
Trouble.open()
|
||||
end
|
||||
if 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
|
||||
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
|
||||
-- help
|
||||
vim.lsp.util.open_floating_preview(lines, "markdown", {
|
||||
border = "single",
|
||||
height = 20,
|
||||
offset_y = -2,
|
||||
offset_x = 2
|
||||
})
|
||||
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()
|
||||
util.debug("refresh: auto")
|
||||
view:update({auto = true})
|
||||
util.debug("refresh: auto")
|
||||
view:update({ auto = true })
|
||||
end)
|
||||
|
||||
function Trouble.refresh(opts)
|
||||
opts = opts or {}
|
||||
opts = opts or {}
|
||||
|
||||
-- dont do an update if this is an automated refresh from a different provider
|
||||
-- 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 == "lsp_document_diagnostics" then
|
||||
opts.provider = "lsp_document_diagnostics"
|
||||
elseif opts.provider == "diagnostics" and config.options.mode == "lsp_workspace_diagnostics" then
|
||||
opts.provider = "lsp_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 is_open() then
|
||||
if opts.auto then
|
||||
if opts.provider == "diagnostics" and config.options.mode ==
|
||||
"lsp_document_diagnostics" then
|
||||
opts.provider = "lsp_document_diagnostics"
|
||||
elseif opts.provider == "diagnostics" and config.options.mode ==
|
||||
"lsp_workspace_diagnostics" then
|
||||
opts.provider = "lsp_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
|
||||
updater()
|
||||
else
|
||||
util.debug("refresh")
|
||||
view:update(opts)
|
||||
end
|
||||
|
||||
if 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.mode ==
|
||||
config.options.mode then
|
||||
local items = require("trouble.providers").get(
|
||||
vim.api.nvim_get_current_win(),
|
||||
vim.api.nvim_get_current_buf(), config.options)
|
||||
if #items > 0 then Trouble.open(opts) end
|
||||
elseif opts.auto and config.options.auto_open and opts.mode == config.options.mode then
|
||||
local items = require("trouble.providers").get(
|
||||
vim.api.nvim_get_current_win(),
|
||||
vim.api.nvim_get_current_buf(),
|
||||
config.options
|
||||
)
|
||||
if #items > 0 then
|
||||
Trouble.open(opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Trouble.action(action)
|
||||
if action == "toggle_mode" then
|
||||
if config.options.mode == "lsp_document_diagnostics" then
|
||||
config.options.mode = "lsp_workspace_diagnostics"
|
||||
elseif config.options.mode == "lsp_workspace_diagnostics" then
|
||||
config.options.mode = "lsp_document_diagnostics"
|
||||
end
|
||||
action = "refresh"
|
||||
if action == "toggle_mode" then
|
||||
if config.options.mode == "lsp_document_diagnostics" then
|
||||
config.options.mode = "lsp_workspace_diagnostics"
|
||||
elseif config.options.mode == "lsp_workspace_diagnostics" then
|
||||
config.options.mode = "lsp_document_diagnostics"
|
||||
end
|
||||
action = "refresh"
|
||||
end
|
||||
|
||||
if view and action == "on_win_enter" then view:on_win_enter() end
|
||||
if not is_open() then return end
|
||||
if action == "hover" then view:hover() end
|
||||
if action == "jump" then view:jump() 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() end
|
||||
if action == "previous" then view:previous_item() end
|
||||
if view and action == "on_win_enter" then
|
||||
view:on_win_enter()
|
||||
end
|
||||
if not is_open() then
|
||||
return
|
||||
end
|
||||
if action == "hover" then
|
||||
view:hover()
|
||||
end
|
||||
if action == "jump" then
|
||||
view:jump()
|
||||
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()
|
||||
end
|
||||
if action == "previous" then
|
||||
view:previous_item()
|
||||
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
|
||||
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
|
||||
if action == "auto_preview" and config.options.auto_preview then
|
||||
action = "preview"
|
||||
end
|
||||
if action == "preview" then view: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
|
||||
if Trouble[action] then
|
||||
Trouble[action]()
|
||||
end
|
||||
end
|
||||
|
||||
return Trouble
|
||||
|
|
|
@ -6,54 +6,56 @@ local lsp = require("trouble.providers.lsp")
|
|||
local M = {}
|
||||
|
||||
M.providers = {
|
||||
lsp_workspace_diagnostics = lsp.diagnostics,
|
||||
lsp_document_diagnostics = lsp.diagnostics,
|
||||
lsp_references = lsp.references,
|
||||
lsp_definitions = lsp.definitions,
|
||||
quickfix = qf.qflist,
|
||||
loclist = qf.loclist,
|
||||
telescope = telescope.telescope
|
||||
lsp_workspace_diagnostics = lsp.diagnostics,
|
||||
lsp_document_diagnostics = lsp.diagnostics,
|
||||
lsp_references = lsp.references,
|
||||
lsp_definitions = lsp.definitions,
|
||||
quickfix = qf.qflist,
|
||||
loclist = qf.loclist,
|
||||
telescope = telescope.telescope,
|
||||
}
|
||||
|
||||
---@param options Options
|
||||
function M.get(win, buf, cb, options)
|
||||
local name = options.mode
|
||||
local provider = M.providers[name]
|
||||
local name = options.mode
|
||||
local provider = M.providers[name]
|
||||
|
||||
if not provider then
|
||||
local ok, mod = pcall(require, "trouble.providers." .. name)
|
||||
if ok then
|
||||
M.providers[name] = mod
|
||||
provider = mod
|
||||
end
|
||||
if not provider then
|
||||
local ok, mod = pcall(require, "trouble.providers." .. name)
|
||||
if ok then
|
||||
M.providers[name] = mod
|
||||
provider = mod
|
||||
end
|
||||
end
|
||||
|
||||
if not provider then
|
||||
util.error(("invalid provider %q"):format(name))
|
||||
return {}
|
||||
end
|
||||
if not provider then
|
||||
util.error(("invalid provider %q"):format(name))
|
||||
return {}
|
||||
end
|
||||
|
||||
provider(win, buf, function(items)
|
||||
table.sort(items, function(a, b)
|
||||
if a.severity == b.severity then
|
||||
return a.lnum < b.lnum
|
||||
else
|
||||
return a.severity < b.severity
|
||||
end
|
||||
end)
|
||||
cb(items)
|
||||
end, options)
|
||||
provider(win, buf, function(items)
|
||||
table.sort(items, function(a, b)
|
||||
if a.severity == b.severity then
|
||||
return a.lnum < b.lnum
|
||||
else
|
||||
return a.severity < b.severity
|
||||
end
|
||||
end)
|
||||
cb(items)
|
||||
end, options)
|
||||
end
|
||||
|
||||
---@param items Item[]
|
||||
---@return table<string, Item[]>
|
||||
function M.group(items)
|
||||
local ret = {}
|
||||
for _, item in ipairs(items) do
|
||||
if ret[item.filename] == nil then ret[item.filename] = {} end
|
||||
table.insert(ret[item.filename], item)
|
||||
local ret = {}
|
||||
for _, item in ipairs(items) do
|
||||
if ret[item.filename] == nil then
|
||||
ret[item.filename] = {}
|
||||
end
|
||||
return ret
|
||||
table.insert(ret[item.filename], item)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -6,72 +6,74 @@ local M = {}
|
|||
|
||||
---@param options Options
|
||||
---@return Item[]
|
||||
function M.diagnostics(win, buf, cb, options)
|
||||
if options.mode == "lsp_workspace_diagnostics" then buf = nil end
|
||||
local buffer_diags = buf and {[buf] = vim.lsp.diagnostic.get(buf, nil)} or
|
||||
vim.lsp.diagnostic.get_all()
|
||||
function M.diagnostics(_win, buf, cb, options)
|
||||
if options.mode == "lsp_workspace_diagnostics" then
|
||||
buf = nil
|
||||
end
|
||||
local buffer_diags = buf and { [buf] = vim.lsp.diagnostic.get(buf, nil) } or vim.lsp.diagnostic.get_all()
|
||||
|
||||
local items = util.locations_to_items(buffer_diags, 1)
|
||||
if #items == 0 then util.warn("no diagnostics found") end
|
||||
cb(items)
|
||||
local items = util.locations_to_items(buffer_diags, 1)
|
||||
if #items == 0 then
|
||||
util.warn("no diagnostics found")
|
||||
end
|
||||
cb(items)
|
||||
end
|
||||
|
||||
---@return Item[]
|
||||
function M.references(win, buf, cb, options)
|
||||
local method = "textDocument/references"
|
||||
local params = util.make_position_params(win, buf)
|
||||
params.context = {includeDeclaration = true}
|
||||
lsp.buf_request(buf, method, params,
|
||||
function(err, method, result, client_id, bufnr, config)
|
||||
if err then
|
||||
util.error("an error happened getting references: " .. err)
|
||||
return cb({})
|
||||
end
|
||||
if result == nil or #result == 0 then
|
||||
util.warn("No referenes found")
|
||||
return cb({})
|
||||
end
|
||||
local ret = util.locations_to_items({result}, 0)
|
||||
cb(ret)
|
||||
end)
|
||||
function M.references(win, buf, cb, _options)
|
||||
local method = "textDocument/references"
|
||||
local params = util.make_position_params(win, buf)
|
||||
params.context = { includeDeclaration = true }
|
||||
lsp.buf_request(buf, method, params, function(err, _method, result, _client_id, _bufnr, _config)
|
||||
if err then
|
||||
util.error("an error happened getting references: " .. err)
|
||||
return cb({})
|
||||
end
|
||||
if result == nil or #result == 0 then
|
||||
util.warn("No referenes found")
|
||||
return cb({})
|
||||
end
|
||||
local ret = util.locations_to_items({ result }, 0)
|
||||
cb(ret)
|
||||
end)
|
||||
end
|
||||
|
||||
---@return Item[]
|
||||
function M.definitions(win, buf, cb, options)
|
||||
local method = "textDocument/definition"
|
||||
local params = util.make_position_params(win, buf)
|
||||
params.context = {includeDeclaration = true}
|
||||
lsp.buf_request(buf, method, params,
|
||||
function(err, method, result, client_id, bufnr, config)
|
||||
if err then
|
||||
util.error("an error happened getting definitions: " .. err)
|
||||
return cb({})
|
||||
end
|
||||
if result == nil or #result == 0 then
|
||||
util.warn("No definitions found")
|
||||
return cb({})
|
||||
end
|
||||
for _, value in ipairs(result) do
|
||||
value.uri = value.targetUri
|
||||
value.range = value.targetSelectionRange
|
||||
end
|
||||
local ret = util.locations_to_items({result}, 0)
|
||||
cb(ret)
|
||||
end)
|
||||
function M.definitions(win, buf, cb, _options)
|
||||
local method = "textDocument/definition"
|
||||
local params = util.make_position_params(win, buf)
|
||||
params.context = { includeDeclaration = true }
|
||||
lsp.buf_request(buf, method, params, function(err, _method, result, _client_id, _bufnr, _config)
|
||||
if err then
|
||||
util.error("an error happened getting definitions: " .. err)
|
||||
return cb({})
|
||||
end
|
||||
if result == nil or #result == 0 then
|
||||
util.warn("No definitions found")
|
||||
return cb({})
|
||||
end
|
||||
for _, value in ipairs(result) do
|
||||
value.uri = value.targetUri
|
||||
value.range = value.targetSelectionRange
|
||||
end
|
||||
local ret = util.locations_to_items({ result }, 0)
|
||||
cb(ret)
|
||||
end)
|
||||
end
|
||||
|
||||
function M.get_signs()
|
||||
local signs = {}
|
||||
for _, v in pairs(util.severity) do
|
||||
-- pcall to catch entirely unbound or cleared out sign hl group
|
||||
local status, sign = pcall(function()
|
||||
return vim.trim(vim.fn.sign_getdefined("LspDiagnosticsSign" .. v)[1]
|
||||
.text)
|
||||
end)
|
||||
if not status then sign = v:sub(1, 1) end
|
||||
signs[string.lower(v)] = sign
|
||||
local signs = {}
|
||||
for _, v in pairs(util.severity) do
|
||||
-- pcall to catch entirely unbound or cleared out sign hl group
|
||||
local status, sign = pcall(function()
|
||||
return vim.trim(vim.fn.sign_getdefined("LspDiagnosticsSign" .. v)[1].text)
|
||||
end)
|
||||
if not status then
|
||||
sign = v:sub(1, 1)
|
||||
end
|
||||
return signs
|
||||
signs[string.lower(v)] = sign
|
||||
end
|
||||
return signs
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -2,38 +2,41 @@ local util = require("trouble.util")
|
|||
|
||||
local M = {}
|
||||
|
||||
local severities = {E = 1, W = 2, I = 3, H = 4}
|
||||
local severities = { E = 1, W = 2, I = 3, H = 4 }
|
||||
|
||||
function M.get_list(winid)
|
||||
local list = winid == nil and vim.fn.getqflist({all = true}) or
|
||||
vim.fn.getloclist(winid, {all = true})
|
||||
local list = winid == nil and vim.fn.getqflist({ all = true }) or vim.fn.getloclist(winid, { all = true })
|
||||
|
||||
local ret = {}
|
||||
for _, item in pairs(list.items) do
|
||||
local row = (item.lnum == 0 and 1 or item.lnum) - 1
|
||||
local col = (item.col == 0 and 1 or item.col) - 1
|
||||
local ret = {}
|
||||
for _, item in pairs(list.items) do
|
||||
local row = (item.lnum == 0 and 1 or item.lnum) - 1
|
||||
local col = (item.col == 0 and 1 or item.col) - 1
|
||||
|
||||
local pitem = {
|
||||
row = row,
|
||||
col = col,
|
||||
message = item.text,
|
||||
severity = severities[item.type] or 0,
|
||||
range = {
|
||||
start = {line = row, character = col},
|
||||
["end"] = {line = row, character = -1}
|
||||
}
|
||||
}
|
||||
local pitem = {
|
||||
row = row,
|
||||
col = col,
|
||||
message = item.text,
|
||||
severity = severities[item.type] or 0,
|
||||
range = {
|
||||
start = { line = row, character = col },
|
||||
["end"] = { line = row, character = -1 },
|
||||
},
|
||||
}
|
||||
|
||||
table.insert(ret, util.process_item(pitem, item.bufnr))
|
||||
end
|
||||
if #ret == 0 then
|
||||
util.warn("the " .. (winid and "loclist" or "qflist") .. " is empty")
|
||||
end
|
||||
return ret
|
||||
table.insert(ret, util.process_item(pitem, item.bufnr))
|
||||
end
|
||||
if #ret == 0 then
|
||||
util.warn("the " .. (winid and "loclist" or "qflist") .. " is empty")
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function M.loclist(win, buf, cb, options) return cb(M.get_list(win)) end
|
||||
function M.loclist(win, _buf, cb, _options)
|
||||
return cb(M.get_list(win))
|
||||
end
|
||||
|
||||
function M.qflist(win, buf, cb, options) return cb(M.get_list()) end
|
||||
function M.qflist(_win, _buf, cb, _options)
|
||||
return cb(M.get_list())
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -3,45 +3,44 @@ local M = {}
|
|||
|
||||
M.results = {}
|
||||
|
||||
function M.open_with_trouble(prompt_bufnr, mode)
|
||||
local action_state = require('telescope.actions.state')
|
||||
local actions = require('telescope.actions')
|
||||
local picker = action_state.get_current_picker(prompt_bufnr)
|
||||
local manager = picker.manager
|
||||
function M.open_with_trouble(prompt_bufnr, _mode)
|
||||
local action_state = require("telescope.actions.state")
|
||||
local actions = require("telescope.actions")
|
||||
local picker = action_state.get_current_picker(prompt_bufnr)
|
||||
local manager = picker.manager
|
||||
|
||||
M.results = {}
|
||||
for item in manager:iter() do
|
||||
local row = (item.lnum or 1) - 1
|
||||
local col = (item.col or 1) - 1
|
||||
M.results = {}
|
||||
for item in manager:iter() do
|
||||
local row = (item.lnum or 1) - 1
|
||||
local col = (item.col or 1) - 1
|
||||
|
||||
if not item.bufnr then
|
||||
item.bufnr = vim.fn.bufnr(item.filename, true)
|
||||
end
|
||||
|
||||
local pitem = {
|
||||
row = row,
|
||||
col = col,
|
||||
message = item.text,
|
||||
severity = 0,
|
||||
range = {
|
||||
start = {line = row, character = col},
|
||||
["end"] = {line = row, character = -1}
|
||||
}
|
||||
}
|
||||
|
||||
table.insert(M.results, util.process_item(pitem, item.bufnr))
|
||||
if not item.bufnr then
|
||||
item.bufnr = vim.fn.bufnr(item.filename, true)
|
||||
end
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
require("trouble").open({mode = "telescope"})
|
||||
local pitem = {
|
||||
row = row,
|
||||
col = col,
|
||||
message = item.text,
|
||||
severity = 0,
|
||||
range = {
|
||||
start = { line = row, character = col },
|
||||
["end"] = { line = row, character = -1 },
|
||||
},
|
||||
}
|
||||
|
||||
table.insert(M.results, util.process_item(pitem, item.bufnr))
|
||||
end
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
require("trouble").open({ mode = "telescope" })
|
||||
end
|
||||
|
||||
function M.telescope(win, buf, cb, options)
|
||||
if #M.results == 0 then
|
||||
util.warn(
|
||||
"No Telescope results found. Open Telescopen and send results to Trouble first. Refer to the documentation for more info.")
|
||||
end
|
||||
cb(M.results)
|
||||
function M.telescope(_win, _buf, cb, _options)
|
||||
if #M.results == 0 then
|
||||
util.warn("No Telescope results found. Open Telescopen and send results to Trouble first. Refer to the documentation for more info.")
|
||||
end
|
||||
cb(M.results)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -10,59 +10,64 @@ local renderer = {}
|
|||
local signs = {}
|
||||
|
||||
local function get_icon(file)
|
||||
local ok, icons = pcall(require, "nvim-web-devicons")
|
||||
if not ok then
|
||||
util.warn(
|
||||
"'nvim-web-devicons' is not installed. Install it, or set icons=false in your configuration to disable this message")
|
||||
return ""
|
||||
end
|
||||
local fname = vim.fn.fnamemodify(file, ":t")
|
||||
local ext = vim.fn.fnamemodify(file, ":e")
|
||||
return icons.get_icon(fname, ext, {default = true})
|
||||
local ok, icons = pcall(require, "nvim-web-devicons")
|
||||
if not ok then
|
||||
util.warn("'nvim-web-devicons' is not installed. Install it, or set icons=false in your configuration to disable this message")
|
||||
return ""
|
||||
end
|
||||
local fname = vim.fn.fnamemodify(file, ":t")
|
||||
local ext = vim.fn.fnamemodify(file, ":e")
|
||||
return icons.get_icon(fname, ext, { default = true })
|
||||
end
|
||||
|
||||
local function update_signs()
|
||||
signs = config.options.signs
|
||||
if config.options.use_lsp_diagnostic_signs then
|
||||
local lsp_signs = require("trouble.providers.lsp").get_signs()
|
||||
signs = vim.tbl_deep_extend("force", {}, signs, lsp_signs)
|
||||
end
|
||||
signs = config.options.signs
|
||||
if config.options.use_lsp_diagnostic_signs then
|
||||
local lsp_signs = require("trouble.providers.lsp").get_signs()
|
||||
signs = vim.tbl_deep_extend("force", {}, signs, lsp_signs)
|
||||
end
|
||||
end
|
||||
|
||||
---@param view View
|
||||
function renderer.render(view, opts)
|
||||
opts = opts or {}
|
||||
local buf = vim.api.nvim_win_get_buf(view.parent)
|
||||
providers.get(view.parent, buf, function(items)
|
||||
local grouped = providers.group(items)
|
||||
local count = util.count(grouped)
|
||||
opts = opts or {}
|
||||
local buf = vim.api.nvim_win_get_buf(view.parent)
|
||||
providers.get(view.parent, buf, function(items)
|
||||
local grouped = providers.group(items)
|
||||
local count = util.count(grouped)
|
||||
|
||||
-- check for auto close
|
||||
if opts.auto and config.options.auto_close then
|
||||
if count == 0 then
|
||||
view:close()
|
||||
return
|
||||
end
|
||||
end
|
||||
-- check for auto close
|
||||
if opts.auto and config.options.auto_close then
|
||||
if count == 0 then
|
||||
view:close()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Update lsp signs
|
||||
update_signs()
|
||||
-- Update lsp signs
|
||||
update_signs()
|
||||
|
||||
local text = Text:new()
|
||||
view.items = {}
|
||||
local text = Text:new()
|
||||
view.items = {}
|
||||
|
||||
text:nl()
|
||||
text:nl()
|
||||
|
||||
-- render file groups
|
||||
for filename, group_items in pairs(grouped) do
|
||||
if opts.open_folds then folds.open(filename) end
|
||||
if opts.close_folds then folds.close(filename) end
|
||||
renderer.render_file(view, text, filename, group_items)
|
||||
end
|
||||
-- render file groups
|
||||
for filename, group_items in pairs(grouped) do
|
||||
if opts.open_folds then
|
||||
folds.open(filename)
|
||||
end
|
||||
if opts.close_folds then
|
||||
folds.close(filename)
|
||||
end
|
||||
renderer.render_file(view, text, filename, group_items)
|
||||
end
|
||||
|
||||
view:render(text)
|
||||
if opts.focus then view:focus() end
|
||||
end, config.options)
|
||||
view:render(text)
|
||||
if opts.focus then
|
||||
view:focus()
|
||||
end
|
||||
end, config.options)
|
||||
end
|
||||
|
||||
---@param view View
|
||||
|
@ -70,62 +75,68 @@ end
|
|||
---@param items Item[]
|
||||
---@param filename string
|
||||
function renderer.render_file(view, text, filename, items)
|
||||
view.items[text.lineNr + 1] = {filename = filename, is_file = true}
|
||||
view.items[text.lineNr + 1] = { filename = filename, is_file = true }
|
||||
|
||||
local count = util.count(items)
|
||||
local count = util.count(items)
|
||||
|
||||
text:render(" ")
|
||||
text:render(" ")
|
||||
|
||||
if folds.is_folded(filename) then
|
||||
text:render(config.options.fold_closed, "FoldIcon", " ")
|
||||
else
|
||||
text:render(config.options.fold_open, "FoldIcon", " ")
|
||||
end
|
||||
if folds.is_folded(filename) then
|
||||
text:render(config.options.fold_closed, "FoldIcon", " ")
|
||||
else
|
||||
text:render(config.options.fold_open, "FoldIcon", " ")
|
||||
end
|
||||
|
||||
if config.options.icons then
|
||||
local icon, icon_hl = get_icon(filename)
|
||||
text:render(icon, icon_hl, {exact = true, append = " "})
|
||||
end
|
||||
if config.options.icons then
|
||||
local icon, icon_hl = get_icon(filename)
|
||||
text:render(icon, icon_hl, { exact = true, append = " " })
|
||||
end
|
||||
|
||||
text:render(vim.fn.fnamemodify(filename, ":p:."), "File", " ")
|
||||
text:render(" " .. count .. " ", "Count")
|
||||
text:nl()
|
||||
text:render(vim.fn.fnamemodify(filename, ":p:."), "File", " ")
|
||||
text:render(" " .. count .. " ", "Count")
|
||||
text:nl()
|
||||
|
||||
if not folds.is_folded(filename) then
|
||||
renderer.render_diagnostics(view, text, items)
|
||||
end
|
||||
if not folds.is_folded(filename) then
|
||||
renderer.render_diagnostics(view, text, items)
|
||||
end
|
||||
end
|
||||
|
||||
---@param view View
|
||||
---@param text Text
|
||||
---@param items Item[]
|
||||
function renderer.render_diagnostics(view, text, items)
|
||||
for _, diag in ipairs(items) do
|
||||
view.items[text.lineNr + 1] = diag
|
||||
for _, diag in ipairs(items) do
|
||||
view.items[text.lineNr + 1] = diag
|
||||
|
||||
local sign = diag.sign or signs[string.lower(diag.type)]
|
||||
if not sign then sign = diag.type end
|
||||
|
||||
local indent = " "
|
||||
if config.options.indent_lines then indent = " │ " end
|
||||
|
||||
local sign_hl = diag.sign_hl or ("TroubleSign" .. diag.type)
|
||||
|
||||
text:render(indent, "Indent")
|
||||
text:render(sign .. " ", sign_hl, {exact = true})
|
||||
text:render(diag.text, "Text" .. diag.type, " ")
|
||||
-- text:render(diag.type, diag.type, " ")
|
||||
|
||||
if diag.source then text:render(diag.source, "Source") end
|
||||
if diag.code and diag.code ~= vim.NIL then
|
||||
text:render("(" .. diag.code .. ")", "Code")
|
||||
end
|
||||
|
||||
text:render(" ")
|
||||
|
||||
text:render("[" .. diag.lnum .. ", " .. diag.col .. "]", "Location")
|
||||
text:nl()
|
||||
local sign = diag.sign or signs[string.lower(diag.type)]
|
||||
if not sign then
|
||||
sign = diag.type
|
||||
end
|
||||
|
||||
local indent = " "
|
||||
if config.options.indent_lines then
|
||||
indent = " │ "
|
||||
end
|
||||
|
||||
local sign_hl = diag.sign_hl or ("TroubleSign" .. diag.type)
|
||||
|
||||
text:render(indent, "Indent")
|
||||
text:render(sign .. " ", sign_hl, { exact = true })
|
||||
text:render(diag.text, "Text" .. diag.type, " ")
|
||||
-- text:render(diag.type, diag.type, " ")
|
||||
|
||||
if diag.source then
|
||||
text:render(diag.source, "Source")
|
||||
end
|
||||
if diag.code and diag.code ~= vim.NIL then
|
||||
text:render("(" .. diag.code .. ")", "Code")
|
||||
end
|
||||
|
||||
text:render(" ")
|
||||
|
||||
text:render("[" .. diag.lnum .. ", " .. diag.col .. "]", "Location")
|
||||
text:nl()
|
||||
end
|
||||
end
|
||||
|
||||
return renderer
|
||||
|
|
|
@ -7,38 +7,46 @@ local Text = {}
|
|||
Text.__index = Text
|
||||
|
||||
function Text:new()
|
||||
local this = {lines = {}, hl = {}, lineNr = 0, current = ""}
|
||||
setmetatable(this, self)
|
||||
return this
|
||||
local this = { lines = {}, hl = {}, lineNr = 0, current = "" }
|
||||
setmetatable(this, self)
|
||||
return this
|
||||
end
|
||||
|
||||
function Text:nl()
|
||||
table.insert(self.lines, self.current)
|
||||
self.current = ""
|
||||
self.lineNr = self.lineNr + 1
|
||||
table.insert(self.lines, self.current)
|
||||
self.current = ""
|
||||
self.lineNr = self.lineNr + 1
|
||||
end
|
||||
|
||||
function Text:render(str, group, opts)
|
||||
str = str:gsub("[\n]", " ")
|
||||
if type(opts) == "string" then opts = {append = opts} end
|
||||
opts = opts or {}
|
||||
str = str:gsub("[\n]", " ")
|
||||
if type(opts) == "string" then
|
||||
opts = { append = opts }
|
||||
end
|
||||
opts = opts or {}
|
||||
|
||||
if group then
|
||||
if opts.exact ~= true then group = "Trouble" .. group end
|
||||
local from = string.len(self.current)
|
||||
---@class Highlight
|
||||
local hl
|
||||
hl = {
|
||||
line = self.lineNr,
|
||||
from = from,
|
||||
to = from + string.len(str),
|
||||
group = group
|
||||
}
|
||||
table.insert(self.hl, hl)
|
||||
if group then
|
||||
if opts.exact ~= true then
|
||||
group = "Trouble" .. group
|
||||
end
|
||||
self.current = self.current .. str
|
||||
if opts.append then self.current = self.current .. opts.append end
|
||||
if opts.nl then self:nl() end
|
||||
local from = string.len(self.current)
|
||||
---@class Highlight
|
||||
local hl
|
||||
hl = {
|
||||
line = self.lineNr,
|
||||
from = from,
|
||||
to = from + string.len(str),
|
||||
group = group,
|
||||
}
|
||||
table.insert(self.hl, hl)
|
||||
end
|
||||
self.current = self.current .. str
|
||||
if opts.append then
|
||||
self.current = self.current .. opts.append
|
||||
end
|
||||
if opts.nl then
|
||||
self:nl()
|
||||
end
|
||||
end
|
||||
|
||||
return Text
|
||||
|
|
|
@ -3,136 +3,149 @@ local config = require("trouble.config")
|
|||
local M = {}
|
||||
|
||||
function M.count(tab)
|
||||
local count = 0
|
||||
for _ in pairs(tab) do count = count + 1 end
|
||||
return count
|
||||
local count = 0
|
||||
for _ in pairs(tab) do
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
function M.log(msg, hl)
|
||||
hl = hl or "MsgArea"
|
||||
vim.api.nvim_echo({{'[Trouble] ', hl}, {msg}}, true, {})
|
||||
hl = hl or "MsgArea"
|
||||
vim.api.nvim_echo({ { "[Trouble] ", hl }, { msg } }, true, {})
|
||||
end
|
||||
|
||||
function M.warn(msg) M.log(msg, "WarningMsg") end
|
||||
function M.warn(msg)
|
||||
M.log(msg, "WarningMsg")
|
||||
end
|
||||
|
||||
function M.error(msg) M.log(msg, "Error") end
|
||||
function M.error(msg)
|
||||
M.log(msg, "Error")
|
||||
end
|
||||
|
||||
function M.debug(msg) if config.options.debug then M.log(msg) end end
|
||||
function M.debug(msg)
|
||||
if config.options.debug then
|
||||
M.log(msg)
|
||||
end
|
||||
end
|
||||
|
||||
function M.debounce(ms, fn)
|
||||
local timer = vim.loop.new_timer()
|
||||
return function(...)
|
||||
local argv = {...}
|
||||
timer:start(ms, 0, function()
|
||||
timer:stop()
|
||||
vim.schedule_wrap(fn)(unpack(argv))
|
||||
end)
|
||||
end
|
||||
local timer = vim.loop.new_timer()
|
||||
return function(...)
|
||||
local argv = { ... }
|
||||
timer:start(ms, 0, function()
|
||||
timer:stop()
|
||||
vim.schedule_wrap(fn)(unpack(argv))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function M.throttle(ms, fn)
|
||||
local timer = vim.loop.new_timer()
|
||||
local running = false
|
||||
return function(...)
|
||||
if not running then
|
||||
local argv = {...}
|
||||
local argc = select('#', ...)
|
||||
local timer = vim.loop.new_timer()
|
||||
local running = false
|
||||
return function(...)
|
||||
if not running then
|
||||
local argv = { ... }
|
||||
local argc = select("#", ...)
|
||||
|
||||
timer:start(ms, 0, function()
|
||||
running = false
|
||||
pcall(vim.schedule_wrap(fn), unpack(argv, 1, argc))
|
||||
end)
|
||||
running = true
|
||||
end
|
||||
timer:start(ms, 0, function()
|
||||
running = false
|
||||
pcall(vim.schedule_wrap(fn), unpack(argv, 1, argc))
|
||||
end)
|
||||
running = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.severity = {
|
||||
[0] = "Other",
|
||||
[1] = "Error",
|
||||
[2] = "Warning",
|
||||
[3] = "Information",
|
||||
[4] = "Hint"
|
||||
[0] = "Other",
|
||||
[1] = "Error",
|
||||
[2] = "Warning",
|
||||
[3] = "Information",
|
||||
[4] = "Hint",
|
||||
}
|
||||
|
||||
-- based on the Telescope diagnostics code
|
||||
-- see https://github.com/nvim-telescope/telescope.nvim/blob/0d6cd47990781ea760dd3db578015c140c7b9fa7/lua/telescope/utils.lua#L85
|
||||
|
||||
function M.process_item(item, bufnr)
|
||||
local filename = vim.api.nvim_buf_get_name(bufnr)
|
||||
local start = item.range["start"]
|
||||
local finish = item.range["end"]
|
||||
local row = start.line
|
||||
local col = start.character
|
||||
local line =
|
||||
(vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or {""})[1]
|
||||
item.message = item.message or line or ""
|
||||
local filename = vim.api.nvim_buf_get_name(bufnr)
|
||||
local start = item.range["start"]
|
||||
local finish = item.range["end"]
|
||||
local row = start.line
|
||||
local col = start.character
|
||||
local line = (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { "" })[1]
|
||||
item.message = item.message or line or ""
|
||||
|
||||
---@class Item
|
||||
---@field is_file boolean
|
||||
---@field fixed boolean
|
||||
local ret
|
||||
ret = {
|
||||
bufnr = bufnr,
|
||||
filename = filename,
|
||||
lnum = row + 1,
|
||||
col = col + 1,
|
||||
start = start,
|
||||
finish = finish,
|
||||
sign = item.sign,
|
||||
sign_hl = item.sign_hl,
|
||||
-- remove line break to avoid display issues
|
||||
text = vim.trim(item.message:gsub("[\n]", "")):sub(0, vim.o.columns),
|
||||
line = line,
|
||||
full_text = vim.trim(item.message),
|
||||
type = M.severity[item.severity] or M.severity[0],
|
||||
code = item.code,
|
||||
source = item.source,
|
||||
severity = item.severity or 0
|
||||
}
|
||||
return ret
|
||||
---@class Item
|
||||
---@field is_file boolean
|
||||
---@field fixed boolean
|
||||
local ret
|
||||
ret = {
|
||||
bufnr = bufnr,
|
||||
filename = filename,
|
||||
lnum = row + 1,
|
||||
col = col + 1,
|
||||
start = start,
|
||||
finish = finish,
|
||||
sign = item.sign,
|
||||
sign_hl = item.sign_hl,
|
||||
-- remove line break to avoid display issues
|
||||
text = vim.trim(item.message:gsub("[\n]", "")):sub(0, vim.o.columns),
|
||||
line = line,
|
||||
full_text = vim.trim(item.message),
|
||||
type = M.severity[item.severity] or M.severity[0],
|
||||
code = item.code,
|
||||
source = item.source,
|
||||
severity = item.severity or 0,
|
||||
}
|
||||
return ret
|
||||
end
|
||||
|
||||
-- takes either a table indexed by bufnr, or an lsp result with uri
|
||||
---@return Item[]
|
||||
function M.locations_to_items(results, default_severity)
|
||||
default_severity = default_severity or 0
|
||||
local ret = {}
|
||||
for bufnr, locs in pairs(results or {}) do
|
||||
for _, loc in pairs(locs.result or locs) do
|
||||
if not vim.tbl_isempty(loc) then
|
||||
local buf = loc.uri and vim.uri_to_bufnr(loc.uri) or bufnr
|
||||
loc.severity = loc.severity or default_severity
|
||||
-- load the buffer when needed
|
||||
vim.fn.bufload(buf)
|
||||
table.insert(ret, M.process_item(loc, buf))
|
||||
end
|
||||
end
|
||||
default_severity = default_severity or 0
|
||||
local ret = {}
|
||||
for bufnr, locs in pairs(results or {}) do
|
||||
for _, loc in pairs(locs.result or locs) do
|
||||
if not vim.tbl_isempty(loc) then
|
||||
local buf = loc.uri and vim.uri_to_bufnr(loc.uri) or bufnr
|
||||
loc.severity = loc.severity or default_severity
|
||||
-- load the buffer when needed
|
||||
vim.fn.bufload(buf)
|
||||
table.insert(ret, M.process_item(loc, buf))
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
-- @private
|
||||
local function make_position_param(win, buf)
|
||||
local row, col = unpack(vim.api.nvim_win_get_cursor(win))
|
||||
row = row - 1
|
||||
local line = vim.api.nvim_buf_get_lines(buf, row, row + 1, true)[1]
|
||||
if not line then return {line = 0, character = 0} end
|
||||
col = vim.str_utfindex(line, col)
|
||||
return {line = row, character = col}
|
||||
local row, col = unpack(vim.api.nvim_win_get_cursor(win))
|
||||
row = row - 1
|
||||
local line = vim.api.nvim_buf_get_lines(buf, row, row + 1, true)[1]
|
||||
if not line then
|
||||
return { line = 0, character = 0 }
|
||||
end
|
||||
col = vim.str_utfindex(line, col)
|
||||
return { line = row, character = col }
|
||||
end
|
||||
|
||||
function M.make_text_document_params(buf) return {uri = vim.uri_from_bufnr(buf)} end
|
||||
function M.make_text_document_params(buf)
|
||||
return { uri = vim.uri_from_bufnr(buf) }
|
||||
end
|
||||
|
||||
--- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position.
|
||||
---
|
||||
-- @returns `TextDocumentPositionParams` object
|
||||
-- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
|
||||
function M.make_position_params(win, buf)
|
||||
return {
|
||||
textDocument = M.make_text_document_params(buf),
|
||||
position = make_position_param(win, buf)
|
||||
}
|
||||
return {
|
||||
textDocument = M.make_text_document_params(buf),
|
||||
position = make_position_param(win, buf),
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -20,413 +20,445 @@ View.__index = View
|
|||
local hl_bufs = {}
|
||||
|
||||
local function clear_hl(bufnr)
|
||||
if vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, config.namespace, 0, -1)
|
||||
end
|
||||
if vim.api.nvim_buf_is_valid(bufnr) then
|
||||
vim.api.nvim_buf_clear_namespace(bufnr, config.namespace, 0, -1)
|
||||
end
|
||||
end
|
||||
|
||||
---Find a rogue Trouble buffer that might have been spawned by i.e. a session.
|
||||
local function find_rogue_buffer()
|
||||
for _, v in ipairs(vim.api.nvim_list_bufs()) do
|
||||
if vim.fn.bufname(v) == "Trouble" then return v end
|
||||
for _, v in ipairs(vim.api.nvim_list_bufs()) do
|
||||
if vim.fn.bufname(v) == "Trouble" then
|
||||
return v
|
||||
end
|
||||
return nil
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
---Find pre-existing Trouble buffer, delete its windows then wipe it.
|
||||
---@private
|
||||
local function wipe_rogue_buffer()
|
||||
local bn = find_rogue_buffer()
|
||||
if bn then
|
||||
local win_ids = vim.fn.win_findbuf(bn)
|
||||
for _, id in ipairs(win_ids) do
|
||||
if vim.fn.win_gettype(id) ~= "autocmd" then
|
||||
vim.api.nvim_win_close(id, true)
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_set_name(bn, "")
|
||||
vim.schedule(function() pcall(vim.api.nvim_buf_delete, bn, {}) end)
|
||||
local bn = find_rogue_buffer()
|
||||
if bn then
|
||||
local win_ids = vim.fn.win_findbuf(bn)
|
||||
for _, id in ipairs(win_ids) do
|
||||
if vim.fn.win_gettype(id) ~= "autocmd" then
|
||||
vim.api.nvim_win_close(id, true)
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_set_name(bn, "")
|
||||
vim.schedule(function()
|
||||
pcall(vim.api.nvim_buf_delete, bn, {})
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function View:new(opts)
|
||||
opts = opts or {}
|
||||
local this = {
|
||||
buf = vim.api.nvim_get_current_buf(),
|
||||
win = opts.win or vim.api.nvim_get_current_win(),
|
||||
parent = opts.parent,
|
||||
items = {}
|
||||
}
|
||||
setmetatable(this, self)
|
||||
return this
|
||||
opts = opts or {}
|
||||
local this = {
|
||||
buf = vim.api.nvim_get_current_buf(),
|
||||
win = opts.win or vim.api.nvim_get_current_win(),
|
||||
parent = opts.parent,
|
||||
items = {},
|
||||
}
|
||||
setmetatable(this, self)
|
||||
return this
|
||||
end
|
||||
|
||||
function View:set_option(name, value, win)
|
||||
if win then
|
||||
return vim.api.nvim_win_set_option(self.win, name, value)
|
||||
else
|
||||
return vim.api.nvim_buf_set_option(self.buf, name, value)
|
||||
end
|
||||
if win then
|
||||
return vim.api.nvim_win_set_option(self.win, name, value)
|
||||
else
|
||||
return vim.api.nvim_buf_set_option(self.buf, name, value)
|
||||
end
|
||||
end
|
||||
|
||||
---@param text Text
|
||||
function View:render(text)
|
||||
self:unlock()
|
||||
self:set_lines(text.lines)
|
||||
self:lock()
|
||||
clear_hl(self.buf)
|
||||
for _, data in ipairs(text.hl) do
|
||||
highlight(self.buf, config.namespace, data.group, data.line, data.from,
|
||||
data.to)
|
||||
end
|
||||
self:unlock()
|
||||
self:set_lines(text.lines)
|
||||
self:lock()
|
||||
clear_hl(self.buf)
|
||||
for _, data in ipairs(text.hl) do
|
||||
highlight(self.buf, config.namespace, data.group, data.line, data.from, data.to)
|
||||
end
|
||||
end
|
||||
|
||||
function View:clear()
|
||||
return vim.api.nvim_buf_set_lines(self.buf, 0, -1, false, {})
|
||||
return vim.api.nvim_buf_set_lines(self.buf, 0, -1, false, {})
|
||||
end
|
||||
|
||||
function View:unlock()
|
||||
self:set_option("modifiable", true)
|
||||
self:set_option("readonly", false)
|
||||
self:set_option("modifiable", true)
|
||||
self:set_option("readonly", false)
|
||||
end
|
||||
|
||||
function View:lock()
|
||||
self:set_option("readonly", true)
|
||||
self:set_option("modifiable", false)
|
||||
self:set_option("readonly", true)
|
||||
self:set_option("modifiable", false)
|
||||
end
|
||||
|
||||
function View:set_lines(lines, first, last, strict)
|
||||
first = first or 0
|
||||
last = last or -1
|
||||
strict = strict or false
|
||||
return vim.api.nvim_buf_set_lines(self.buf, first, last, strict, lines)
|
||||
first = first or 0
|
||||
last = last or -1
|
||||
strict = strict or false
|
||||
return vim.api.nvim_buf_set_lines(self.buf, first, last, strict, lines)
|
||||
end
|
||||
|
||||
function View:is_valid()
|
||||
return vim.api.nvim_buf_is_valid(self.buf) and
|
||||
vim.api.nvim_buf_is_loaded(self.buf)
|
||||
return vim.api.nvim_buf_is_valid(self.buf) and vim.api.nvim_buf_is_loaded(self.buf)
|
||||
end
|
||||
|
||||
function View:update(opts)
|
||||
util.debug("update")
|
||||
renderer.render(self, opts)
|
||||
util.debug("update")
|
||||
renderer.render(self, opts)
|
||||
end
|
||||
|
||||
function View:setup(opts)
|
||||
util.debug("setup")
|
||||
opts = opts or {}
|
||||
vim.cmd("setlocal nonu")
|
||||
vim.cmd("setlocal nornu")
|
||||
if not pcall(vim.api.nvim_buf_set_name, self.buf, 'Trouble') then
|
||||
wipe_rogue_buffer()
|
||||
vim.api.nvim_buf_set_name(self.buf, 'Trouble')
|
||||
end
|
||||
self:set_option("bufhidden", "wipe")
|
||||
self:set_option("filetype", "Trouble")
|
||||
self:set_option("buftype", "nofile")
|
||||
self:set_option("swapfile", false)
|
||||
self:set_option("buflisted", false)
|
||||
self:set_option("winfixwidth", true, true)
|
||||
self:set_option("spell", false, true)
|
||||
self:set_option("list", false, true)
|
||||
self:set_option("winfixheight", true, true)
|
||||
self:set_option("signcolumn", "no", true)
|
||||
self:set_option("foldmethod", "manual", true)
|
||||
self:set_option("foldcolumn", "0", true)
|
||||
self:set_option("foldlevel", 3, true)
|
||||
self:set_option("foldenable", false, true)
|
||||
self:set_option("winhighlight",
|
||||
"Normal:TroubleNormal,EndOfBuffer:TroubleNormal,SignColumn:TroubleNormal",
|
||||
true)
|
||||
self:set_option("fcs", "eob: ", true)
|
||||
util.debug("setup")
|
||||
opts = opts or {}
|
||||
vim.cmd("setlocal nonu")
|
||||
vim.cmd("setlocal nornu")
|
||||
if not pcall(vim.api.nvim_buf_set_name, self.buf, "Trouble") then
|
||||
wipe_rogue_buffer()
|
||||
vim.api.nvim_buf_set_name(self.buf, "Trouble")
|
||||
end
|
||||
self:set_option("bufhidden", "wipe")
|
||||
self:set_option("filetype", "Trouble")
|
||||
self:set_option("buftype", "nofile")
|
||||
self:set_option("swapfile", false)
|
||||
self:set_option("buflisted", false)
|
||||
self:set_option("winfixwidth", true, true)
|
||||
self:set_option("spell", false, true)
|
||||
self:set_option("list", false, true)
|
||||
self:set_option("winfixheight", true, true)
|
||||
self:set_option("signcolumn", "no", true)
|
||||
self:set_option("foldmethod", "manual", true)
|
||||
self:set_option("foldcolumn", "0", true)
|
||||
self:set_option("foldlevel", 3, true)
|
||||
self:set_option("foldenable", false, true)
|
||||
self:set_option("winhighlight", "Normal:TroubleNormal,EndOfBuffer:TroubleNormal,SignColumn:TroubleNormal", true)
|
||||
self:set_option("fcs", "eob: ", true)
|
||||
|
||||
for action, keys in pairs(config.options.action_keys) do
|
||||
if type(keys) == "string" then keys = {keys} end
|
||||
for _, key in pairs(keys) do
|
||||
vim.api.nvim_buf_set_keymap(self.buf, "n", key,
|
||||
[[<cmd>lua require("trouble").action("]] ..
|
||||
action .. [[")<cr>]],
|
||||
{silent = true, noremap = true})
|
||||
end
|
||||
for action, keys in pairs(config.options.action_keys) do
|
||||
if type(keys) == "string" then
|
||||
keys = { keys }
|
||||
end
|
||||
|
||||
if config.options.position == "top" or config.options.position == "bottom" then
|
||||
vim.api.nvim_win_set_height(self.win, config.options.height)
|
||||
else
|
||||
vim.api.nvim_win_set_width(self.win, config.options.width)
|
||||
for _, key in pairs(keys) do
|
||||
vim.api.nvim_buf_set_keymap(self.buf, "n", key, [[<cmd>lua require("trouble").action("]] .. action .. [[")<cr>]], {
|
||||
silent = true,
|
||||
noremap = true,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_exec([[
|
||||
if config.options.position == "top" or config.options.position == "bottom" then
|
||||
vim.api.nvim_win_set_height(self.win, config.options.height)
|
||||
else
|
||||
vim.api.nvim_win_set_width(self.win, config.options.width)
|
||||
end
|
||||
|
||||
vim.api.nvim_exec(
|
||||
[[
|
||||
augroup TroubleHighlights
|
||||
autocmd! * <buffer>
|
||||
autocmd BufEnter <buffer> lua require("trouble").action("on_enter")
|
||||
autocmd CursorMoved <buffer> lua require("trouble").action("auto_preview")
|
||||
autocmd BufLeave <buffer> lua require("trouble").action("on_leave")
|
||||
augroup END
|
||||
]], false)
|
||||
]],
|
||||
false
|
||||
)
|
||||
|
||||
if not opts.parent then self:on_enter() end
|
||||
self:lock()
|
||||
self:update(opts)
|
||||
if not opts.parent then
|
||||
self:on_enter()
|
||||
end
|
||||
self:lock()
|
||||
self:update(opts)
|
||||
end
|
||||
|
||||
function View:on_enter()
|
||||
util.debug("on_enter")
|
||||
util.debug("on_enter")
|
||||
|
||||
self.parent = self.parent or vim.fn.win_getid(vim.fn.winnr('#'))
|
||||
self.parent = self.parent or vim.fn.win_getid(vim.fn.winnr("#"))
|
||||
|
||||
if (not self:is_valid_parent(self.parent)) or self.parent == self.win then
|
||||
for _, win in pairs(vim.api.nvim_list_wins()) do
|
||||
if self:is_valid_parent(win) and win ~= self.win then
|
||||
self.parent = win
|
||||
break
|
||||
end
|
||||
end
|
||||
if (not self:is_valid_parent(self.parent)) or self.parent == self.win then
|
||||
for _, win in pairs(vim.api.nvim_list_wins()) do
|
||||
if self:is_valid_parent(win) and win ~= self.win then
|
||||
self.parent = win
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not vim.api.nvim_win_is_valid(self.parent) then return self:close() end
|
||||
if not vim.api.nvim_win_is_valid(self.parent) then
|
||||
return self:close()
|
||||
end
|
||||
|
||||
self.parent_state = {
|
||||
buf = vim.api.nvim_win_get_buf(self.parent),
|
||||
cursor = vim.api.nvim_win_get_cursor(self.parent)
|
||||
}
|
||||
self.parent_state = {
|
||||
buf = vim.api.nvim_win_get_buf(self.parent),
|
||||
cursor = vim.api.nvim_win_get_cursor(self.parent),
|
||||
}
|
||||
end
|
||||
|
||||
function View:on_leave()
|
||||
util.debug("on_leave")
|
||||
self:close_preview()
|
||||
util.debug("on_leave")
|
||||
self:close_preview()
|
||||
end
|
||||
|
||||
function View:close_preview()
|
||||
-- Clear preview highlights
|
||||
for buf, _ in pairs(hl_bufs) do
|
||||
clear_hl(buf)
|
||||
end
|
||||
hl_bufs = {}
|
||||
|
||||
-- Clear preview highlights
|
||||
for buf, _ in pairs(hl_bufs) do clear_hl(buf) end
|
||||
hl_bufs = {}
|
||||
-- Reset parent state
|
||||
local valid_win = vim.api.nvim_win_is_valid(self.parent)
|
||||
local valid_buf = vim.api.nvim_buf_is_valid(self.parent_state.buf)
|
||||
|
||||
-- Reset parent state
|
||||
local valid_win = vim.api.nvim_win_is_valid(self.parent)
|
||||
local valid_buf = vim.api.nvim_buf_is_valid(self.parent_state.buf)
|
||||
if self.parent_state and valid_buf and valid_win then
|
||||
vim.api.nvim_win_set_buf(self.parent, self.parent_state.buf)
|
||||
vim.api.nvim_win_set_cursor(self.parent, self.parent_state.cursor)
|
||||
end
|
||||
|
||||
if self.parent_state and valid_buf and valid_win then
|
||||
vim.api.nvim_win_set_buf(self.parent, self.parent_state.buf)
|
||||
vim.api.nvim_win_set_cursor(self.parent, self.parent_state.cursor)
|
||||
end
|
||||
|
||||
self.parent_state = nil
|
||||
self.parent_state = nil
|
||||
end
|
||||
|
||||
function View:is_float(win)
|
||||
local opts = vim.api.nvim_win_get_config(win)
|
||||
return opts and opts.relative and opts.relative ~= ""
|
||||
local opts = vim.api.nvim_win_get_config(win)
|
||||
return opts and opts.relative and opts.relative ~= ""
|
||||
end
|
||||
|
||||
function View:is_valid_parent(win)
|
||||
if not vim.api.nvim_win_is_valid(win) then return false end
|
||||
-- dont do anything for floating windows
|
||||
if View:is_float(win) then return false end
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
-- Skip special buffers
|
||||
if vim.api.nvim_buf_get_option(buf, "buftype") ~= "" then return false end
|
||||
if not vim.api.nvim_win_is_valid(win) then
|
||||
return false
|
||||
end
|
||||
-- dont do anything for floating windows
|
||||
if View:is_float(win) then
|
||||
return false
|
||||
end
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
-- Skip special buffers
|
||||
if vim.api.nvim_buf_get_option(buf, "buftype") ~= "" then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
return true
|
||||
end
|
||||
|
||||
function View:on_win_enter()
|
||||
util.debug("on_win_enter")
|
||||
util.debug("on_win_enter")
|
||||
|
||||
local current_win = vim.api.nvim_get_current_win()
|
||||
local current_win = vim.api.nvim_get_current_win()
|
||||
|
||||
if vim.fn.winnr('$') == 1 and current_win == self.win then
|
||||
vim.cmd [[q]]
|
||||
return
|
||||
if vim.fn.winnr("$") == 1 and current_win == self.win then
|
||||
vim.cmd([[q]])
|
||||
return
|
||||
end
|
||||
|
||||
if not self:is_valid_parent(current_win) then
|
||||
return
|
||||
end
|
||||
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
|
||||
-- update parent when needed
|
||||
if current_win ~= self.parent and current_win ~= self.win then
|
||||
self.parent = current_win
|
||||
-- update diagnostics to match the window we are viewing
|
||||
if self:is_valid() then
|
||||
vim.defer_fn(function()
|
||||
util.debug("update_on_win_enter")
|
||||
self:update()
|
||||
end, 100)
|
||||
end
|
||||
end
|
||||
|
||||
if not self:is_valid_parent(current_win) then return end
|
||||
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
|
||||
-- update parent when needed
|
||||
if current_win ~= self.parent and current_win ~= self.win then
|
||||
self.parent = current_win
|
||||
-- update diagnostics to match the window we are viewing
|
||||
if self:is_valid() then
|
||||
vim.defer_fn(function()
|
||||
util.debug("update_on_win_enter")
|
||||
self:update()
|
||||
end, 100)
|
||||
end
|
||||
end
|
||||
|
||||
-- check if another buffer took over our window
|
||||
local parent = self.parent
|
||||
if current_win == self.win and current_buf ~= self.buf then
|
||||
-- open the buffer in the parent
|
||||
vim.api.nvim_win_set_buf(parent, current_buf)
|
||||
-- HACK: somw window local settings need to be reset
|
||||
vim.api.nvim_win_set_option(parent, "winhl", "")
|
||||
-- close the current trouble window
|
||||
vim.api.nvim_win_close(self.win, false)
|
||||
-- open a new trouble window
|
||||
require("trouble").open()
|
||||
-- switch back to the opened window / buffer
|
||||
View.switch_to(parent, current_buf)
|
||||
-- util.warn("win_enter pro")
|
||||
end
|
||||
-- check if another buffer took over our window
|
||||
local parent = self.parent
|
||||
if current_win == self.win and current_buf ~= self.buf then
|
||||
-- open the buffer in the parent
|
||||
vim.api.nvim_win_set_buf(parent, current_buf)
|
||||
-- HACK: some window local settings need to be reset
|
||||
vim.api.nvim_win_set_option(parent, "winhl", "")
|
||||
-- close the current trouble window
|
||||
vim.api.nvim_win_close(self.win, false)
|
||||
-- open a new trouble window
|
||||
require("trouble").open()
|
||||
-- switch back to the opened window / buffer
|
||||
View.switch_to(parent, current_buf)
|
||||
-- util.warn("win_enter pro")
|
||||
end
|
||||
end
|
||||
|
||||
function View:focus()
|
||||
View.switch_to(self.win, self.buf)
|
||||
local line = self:get_line()
|
||||
if line == 1 then
|
||||
self:next_item()
|
||||
self:next_item()
|
||||
end
|
||||
View.switch_to(self.win, self.buf)
|
||||
local line = self:get_line()
|
||||
if line == 1 then
|
||||
self:next_item()
|
||||
self:next_item()
|
||||
end
|
||||
end
|
||||
|
||||
function View.switch_to(win, buf)
|
||||
if win then
|
||||
vim.api.nvim_set_current_win(win)
|
||||
if buf then vim.api.nvim_win_set_buf(win, buf) end
|
||||
if win then
|
||||
vim.api.nvim_set_current_win(win)
|
||||
if buf then
|
||||
vim.api.nvim_win_set_buf(win, buf)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function View:switch_to_parent()
|
||||
-- vim.cmd("wincmd p")
|
||||
View.switch_to(self.parent)
|
||||
-- vim.cmd("wincmd p")
|
||||
View.switch_to(self.parent)
|
||||
end
|
||||
|
||||
function View:close()
|
||||
util.debug("close")
|
||||
if vim.api.nvim_win_is_valid(self.win) then
|
||||
vim.api.nvim_win_close(self.win, {})
|
||||
end
|
||||
if vim.api.nvim_buf_is_valid(self.buf) then
|
||||
vim.api.nvim_buf_delete(self.buf, {})
|
||||
end
|
||||
util.debug("close")
|
||||
if vim.api.nvim_win_is_valid(self.win) then
|
||||
vim.api.nvim_win_close(self.win, {})
|
||||
end
|
||||
if vim.api.nvim_buf_is_valid(self.buf) then
|
||||
vim.api.nvim_buf_delete(self.buf, {})
|
||||
end
|
||||
end
|
||||
|
||||
function View.create(opts)
|
||||
opts = opts or {}
|
||||
if opts.win then
|
||||
View.switch_to(opts.win)
|
||||
vim.cmd("enew")
|
||||
else
|
||||
vim.cmd("below new")
|
||||
local pos = {bottom = "J", top = "K", left = "H", right = "L"}
|
||||
vim.cmd("wincmd " .. (pos[config.options.position] or "K"))
|
||||
end
|
||||
local buffer = View:new(opts)
|
||||
buffer:setup(opts)
|
||||
opts = opts or {}
|
||||
if opts.win then
|
||||
View.switch_to(opts.win)
|
||||
vim.cmd("enew")
|
||||
else
|
||||
vim.cmd("below new")
|
||||
local pos = { bottom = "J", top = "K", left = "H", right = "L" }
|
||||
vim.cmd("wincmd " .. (pos[config.options.position] or "K"))
|
||||
end
|
||||
local buffer = View:new(opts)
|
||||
buffer:setup(opts)
|
||||
|
||||
if opts and opts.auto then buffer:switch_to_parent() end
|
||||
return buffer
|
||||
if opts and opts.auto then
|
||||
buffer:switch_to_parent()
|
||||
end
|
||||
return buffer
|
||||
end
|
||||
|
||||
function View:get_cursor() return vim.api.nvim_win_get_cursor(self.win) end
|
||||
function View:get_line() return self:get_cursor()[1] end
|
||||
function View:get_col() return self:get_cursor()[2] end
|
||||
function View:get_cursor()
|
||||
return vim.api.nvim_win_get_cursor(self.win)
|
||||
end
|
||||
function View:get_line()
|
||||
return self:get_cursor()[1]
|
||||
end
|
||||
function View:get_col()
|
||||
return self:get_cursor()[2]
|
||||
end
|
||||
|
||||
function View:current_item()
|
||||
local line = self:get_line()
|
||||
local item = self.items[line]
|
||||
return item
|
||||
local line = self:get_line()
|
||||
local item = self.items[line]
|
||||
return item
|
||||
end
|
||||
|
||||
function View:next_item()
|
||||
local line = self:get_line()
|
||||
for i = line + 1, vim.api.nvim_buf_line_count(self.buf), 1 do
|
||||
if self.items[i] then
|
||||
vim.api.nvim_win_set_cursor(self.win, {i, self:get_col()})
|
||||
return
|
||||
end
|
||||
local line = self:get_line()
|
||||
for i = line + 1, vim.api.nvim_buf_line_count(self.buf), 1 do
|
||||
if self.items[i] then
|
||||
vim.api.nvim_win_set_cursor(self.win, { i, self:get_col() })
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function View:previous_item()
|
||||
local line = self:get_line()
|
||||
for i = line - 1, 0, -1 do
|
||||
if self.items[i] then
|
||||
vim.api.nvim_win_set_cursor(self.win, {i, self:get_col()})
|
||||
return
|
||||
end
|
||||
local line = self:get_line()
|
||||
for i = line - 1, 0, -1 do
|
||||
if self.items[i] then
|
||||
vim.api.nvim_win_set_cursor(self.win, { i, self:get_col() })
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function View:hover(opts)
|
||||
opts = opts or {}
|
||||
local item = opts.item or self:current_item()
|
||||
if not (item and item.full_text) then return end
|
||||
opts = opts or {}
|
||||
local item = opts.item or self:current_item()
|
||||
if not (item and item.full_text) then
|
||||
return
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
for line in item.full_text:gmatch("([^\n]*)\n?") do
|
||||
table.insert(lines, line)
|
||||
end
|
||||
local lines = {}
|
||||
for line in item.full_text:gmatch("([^\n]*)\n?") do
|
||||
table.insert(lines, line)
|
||||
end
|
||||
|
||||
vim.lsp.util.open_floating_preview(lines, "plaintext", {border = "single"})
|
||||
vim.lsp.util.open_floating_preview(lines, "plaintext", { border = "single" })
|
||||
end
|
||||
|
||||
function View:jump(opts)
|
||||
opts = opts or {}
|
||||
local item = opts.item or self:current_item()
|
||||
if not item then return end
|
||||
opts = opts or {}
|
||||
local item = opts.item or self:current_item()
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
|
||||
if item.is_file == true then
|
||||
folds.toggle(item.filename)
|
||||
self:update()
|
||||
if item.is_file == true then
|
||||
folds.toggle(item.filename)
|
||||
self:update()
|
||||
else
|
||||
View.switch_to(opts.win or self.parent)
|
||||
if vim.api.nvim_buf_get_option(item.bufnr, "buflisted") == false then
|
||||
vim.cmd("edit #" .. item.bufnr)
|
||||
else
|
||||
View.switch_to(opts.win or self.parent)
|
||||
if vim.api.nvim_buf_get_option(item.bufnr, "buflisted") == false then
|
||||
vim.cmd("edit #" .. item.bufnr)
|
||||
else
|
||||
vim.cmd("buffer " .. item.bufnr)
|
||||
end
|
||||
vim.api.nvim_win_set_cursor(self.parent,
|
||||
{item.start.line + 1, item.start.character})
|
||||
vim.cmd("buffer " .. item.bufnr)
|
||||
end
|
||||
vim.api.nvim_win_set_cursor(self.parent, { item.start.line + 1, item.start.character })
|
||||
end
|
||||
end
|
||||
|
||||
function View:toggle_fold()
|
||||
folds.toggle(self:current_item().filename)
|
||||
self:update()
|
||||
folds.toggle(self:current_item().filename)
|
||||
self:update()
|
||||
end
|
||||
|
||||
function View:_preview()
|
||||
if not vim.api.nvim_win_is_valid(self.parent) then return end
|
||||
util.debug("preview")
|
||||
if not vim.api.nvim_win_is_valid(self.parent) then
|
||||
return
|
||||
end
|
||||
util.debug("preview")
|
||||
|
||||
local item = self:current_item()
|
||||
if not item then return end
|
||||
local item = self:current_item()
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
|
||||
if item.is_file ~= true then
|
||||
if item.is_file ~= true then
|
||||
vim.api.nvim_win_set_buf(self.parent, item.bufnr)
|
||||
vim.api.nvim_win_set_cursor(self.parent, { item.start.line + 1, item.start.character })
|
||||
|
||||
vim.api.nvim_win_set_buf(self.parent, item.bufnr)
|
||||
vim.api.nvim_win_set_cursor(self.parent,
|
||||
{item.start.line + 1, item.start.character})
|
||||
vim.api.nvim_buf_call(item.bufnr, function()
|
||||
-- Center preview line on screen and open enough folds to show it
|
||||
vim.cmd("norm! zz zv")
|
||||
if vim.api.nvim_buf_get_option(item.bufnr, "filetype") == "" then
|
||||
vim.cmd("do BufRead")
|
||||
end
|
||||
end)
|
||||
|
||||
vim.api.nvim_buf_call(item.bufnr, function()
|
||||
-- Center preview line on screen and open enough folds to show it
|
||||
vim.cmd("norm! zz zv")
|
||||
if vim.api.nvim_buf_get_option(item.bufnr, "filetype") == "" then
|
||||
vim.cmd("do BufRead")
|
||||
end
|
||||
end)
|
||||
|
||||
clear_hl(item.bufnr)
|
||||
hl_bufs[item.bufnr] = true
|
||||
for row = item.start.line, item.finish.line, 1 do
|
||||
local col_start = 0
|
||||
local col_end = -1
|
||||
if row == item.start.line then
|
||||
col_start = item.start.character
|
||||
end
|
||||
if row == item.finish.line then
|
||||
col_end = item.finish.character
|
||||
end
|
||||
highlight(item.bufnr, config.namespace, "TroublePreview", row,
|
||||
col_start, col_end)
|
||||
end
|
||||
clear_hl(item.bufnr)
|
||||
hl_bufs[item.bufnr] = true
|
||||
for row = item.start.line, item.finish.line, 1 do
|
||||
local col_start = 0
|
||||
local col_end = -1
|
||||
if row == item.start.line then
|
||||
col_start = item.start.character
|
||||
end
|
||||
if row == item.finish.line then
|
||||
col_end = item.finish.character
|
||||
end
|
||||
highlight(item.bufnr, config.namespace, "TroublePreview", row, col_start, col_end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- View.preview = View._preview
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
std="lua51+vim"
|
|
@ -0,0 +1,3 @@
|
|||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
column_width = 120
|
Loading…
Reference in New Issue