-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 980fb07
Showing
10 changed files
with
617 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
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" | ||
} | ||
|
||
function M.setup() | ||
for k, v in pairs(links) do | ||
vim.api.nvim_command('hi def link LspTrouble' .. k .. ' ' .. v) | ||
end | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
local M = {} | ||
|
||
M.namespace = vim.api.nvim_create_namespace('LspTrouble') | ||
|
||
---@class Options | ||
local defaults = { | ||
height = 10, | ||
icons = true, | ||
fold_open = "", | ||
fold_closed = "", | ||
actions = { | ||
["<cr>"] = "jump", | ||
q = "close", | ||
r = "refresh", | ||
zR = "open_folds", | ||
zM = "close_folds", | ||
p = "preview", | ||
P = "toggle_preview" | ||
}, | ||
auto_open = false, | ||
auto_close = true, | ||
auto_preview = false | ||
} | ||
|
||
---@type Options | ||
M.options = {} | ||
|
||
---@return Options | ||
function M.setup(options) | ||
M.options = vim.tbl_deep_extend("force", {}, defaults, options or {}) | ||
end | ||
|
||
M.setup() | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
local M = {} | ||
|
||
M.folded = {} | ||
|
||
function M.is_folded(filename) return M.folded[filename] == true 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.open(filename) M.folded[filename] = false end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
local View = require("trouble.view") | ||
local config = require("trouble.config") | ||
local colors = require("trouble.colors") | ||
local util = require("trouble.util") | ||
local lsp = require("trouble.lsp") | ||
|
||
colors.setup() | ||
|
||
local Trouble = {} | ||
|
||
local view | ||
|
||
local function is_open() return view and view:is_valid() end | ||
|
||
function Trouble.setup(options) | ||
config.setup(options) | ||
colors.setup() | ||
end | ||
|
||
function Trouble.close() if is_open() then view:close() end end | ||
|
||
function Trouble.open(opts) | ||
if is_open() then | ||
view:focus() | ||
else | ||
view = View.create(opts) | ||
end | ||
end | ||
|
||
function Trouble.toggle() | ||
if is_open() then | ||
Trouble.close() | ||
else | ||
Trouble.open() | ||
end | ||
end | ||
|
||
function Trouble.refresh(opts) | ||
if is_open() then | ||
view:update(opts) | ||
elseif opts.auto and config.options.auto_open then | ||
local count = util.count(lsp.diagnostics()) | ||
if count > 0 then Trouble.open(opts) end | ||
end | ||
end | ||
|
||
function Trouble.action(action) | ||
if not is_open() then return end | ||
if action == "jump" then view:jump() 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_preview" then | ||
config.options.auto_preview = not config.options.auto_preview | ||
if config.options.auto_preview then action = "auto_preview" end | ||
end | ||
|
||
if action == "preview" or | ||
(action == "auto_preview" and config.options.auto_preview) then | ||
view:preview() | ||
end | ||
if Trouble[action] then Trouble[action]() end | ||
end | ||
|
||
return Trouble |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
---@class Lsp | ||
local M = {} | ||
|
||
local lsp_type_diagnostic = { | ||
[1] = "Error", | ||
[2] = "Warning", | ||
[3] = "Information", | ||
[4] = "Hint" | ||
} | ||
|
||
local function preprocess_diag(diag, bufnr) | ||
local filename = vim.api.nvim_buf_get_name(bufnr) | ||
local start = diag.range['start'] | ||
local finish = diag.range['end'] | ||
local row = start.line | ||
local col = start.character | ||
|
||
---@class Diagnostics | ||
---@field is_file boolean | ||
local ret | ||
ret = { | ||
bufnr = bufnr, | ||
filename = filename, | ||
lnum = row + 1, | ||
col = col + 1, | ||
start = start, | ||
finish = finish, | ||
-- remove line break to avoid display issues | ||
text = vim.trim(diag.message:gsub("[\n]", "")), | ||
type = lsp_type_diagnostic[diag.severity] or lsp_type_diagnostic[1], | ||
code = diag.code, | ||
source = diag.source, | ||
severity = diag.severity or 1 | ||
} | ||
return ret | ||
end | ||
|
||
---@return Diagnostics[] | ||
function M.diagnostics(opts) | ||
opts = opts or {} | ||
local items = {} | ||
|
||
local buffer_diags = opts.bufnr and | ||
{ | ||
[opts.bufnr] = vim.lsp.diagnostic.get(opts.bufnr, nil) | ||
} or vim.lsp.diagnostic.get_all() | ||
|
||
for bufnr, diags in pairs(buffer_diags) do | ||
for _, diag in pairs(diags) do | ||
-- workspace diagnostics may include empty tables for unused bufnr | ||
if not vim.tbl_isempty(diag) then | ||
table.insert(items, preprocess_diag(diag, bufnr)) | ||
end | ||
end | ||
end | ||
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) | ||
return items | ||
end | ||
|
||
---@param items Diagnostics[] | ||
---@return table<string, Diagnostics[]> | ||
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) | ||
end | ||
return ret | ||
end | ||
|
||
function M.get_signs() | ||
local signs = {} | ||
for _, v in pairs(lsp_type_diagnostic) 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[v] = sign | ||
end | ||
return signs | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
local lsp = require("trouble.lsp") | ||
local util = require("trouble.util") | ||
local config = require("trouble.config") | ||
local Text = require("trouble.text") | ||
local folds = require("trouble.folds") | ||
|
||
---@class Renderer | ||
local renderer = {} | ||
|
||
local signs = {} | ||
|
||
local function get_icon(file) | ||
local icons, _ = require('nvim-web-devicons') | ||
local fname = vim.fn.fnamemodify(file, ":t") | ||
local ext = vim.fn.fnamemodify(file, ":e") | ||
return icons.get_icon(fname, ext, {default = true}) | ||
end | ||
|
||
---@param view View | ||
function renderer.render(view, opts) | ||
opts = opts or {} | ||
local diagnostics = lsp.diagnostics(config.options) | ||
local grouped = lsp.group(diagnostics) | ||
|
||
-- check for auto close | ||
if opts.auto and config.options.auto_close then | ||
local count = util.count(grouped) | ||
if count == 0 then | ||
view:close() | ||
return | ||
end | ||
end | ||
|
||
-- Update lsp signs | ||
signs = lsp.get_signs() | ||
|
||
local text = Text:new() | ||
view.items = {} | ||
|
||
-- render file groups | ||
for filename, 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, items) | ||
end | ||
|
||
view:render(text) | ||
end | ||
|
||
---@param view View | ||
---@param text Text | ||
---@param items Diagnostics[] | ||
---@param filename string | ||
function renderer.render_file(view, text, filename, items) | ||
view.items[text.lineNr] = {filename = filename, is_file = true} | ||
|
||
local count = util.count(items) | ||
|
||
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 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() | ||
|
||
if not folds.is_folded(filename) then | ||
renderer.render_diagnostics(view, text, items) | ||
end | ||
end | ||
|
||
---@param view View | ||
---@param text Text | ||
---@param items Diagnostics[] | ||
function renderer.render_diagnostics(view, text, items) | ||
for _, diag in ipairs(items) do | ||
view.items[text.lineNr] = diag | ||
|
||
local sign = signs[diag.type] | ||
if not sign then sign = diag.type end | ||
|
||
text:render(" " .. sign .. " ", "Sign" .. diag.type) | ||
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 then | ||
text:render("(" .. diag.code .. ")", "Code", " ") | ||
end | ||
|
||
text:render("[" .. diag.lnum .. ", " .. diag.col .. "]", "Location") | ||
text:nl() | ||
end | ||
end | ||
|
||
return renderer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
---@class Text | ||
---@field lines string[] | ||
---@field hl Highlight[] | ||
---@field lineNr number | ||
---@field current string | ||
local Text = {} | ||
Text.__index = Text | ||
|
||
function Text:new() | ||
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 | ||
end | ||
|
||
function Text:render(str, group, opts) | ||
if type(opts) == "string" then opts = {append = opts} end | ||
opts = opts or {} | ||
|
||
if group then | ||
if opts.exact ~= true then group = "LspTrouble" .. 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) | ||
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 |
Oops, something went wrong.