Skip to content

Commit

Permalink
refactor: new spec
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Oct 24, 2023
1 parent 44c8543 commit 13d5db9
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 191 deletions.
36 changes: 21 additions & 15 deletions lua/trouble/config/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
local M = {}

---@class trouble.Mode: trouble.Config
---@field filter? trouble.spec.filter
---@field sections? trouble.spec.section[]|trouble.spec.section
---@field filter? trouble.Filter.spec Optional filter to apply to items in all sections
---@field sections? string[]

---@class trouble.Config
---@field mode? string
---@field config? fun(opts:trouble.Config)
---@field sections table<string,trouble.Section.spec>
local defaults = {
debug = false,
indent_lines = true, -- add an indent guide below the fold icons
max_items = 200, -- limit number of items that can be displayed
events = { "BufEnter" }, -- events that trigger refresh. Also used by auto_open and auto_close
---@type trouble.Window.opts
win = {},
throttle = 100,
Expand All @@ -39,8 +39,10 @@ local defaults = {
},
---@type table<string, trouble.FilterFn>
filters = {}, -- custom filters
---@type table<string, trouble.Sorter>
---@type table<string, trouble.SorterFn>
sorters = {}, -- custom sorters
---@type table<string, trouble.Section.spec>
views = {}, -- custom sections
---@type table<string, string|trouble.Action>
keys = {
["?"] = "help",
Expand Down Expand Up @@ -102,14 +104,11 @@ function M.setup(opts)
return options
end

---@param modes table<string, trouble.Mode>
function M.register(modes)
for name, mode in pairs(modes) do
if defaults.modes[name] then
error("mode already registered: " .. name)
end
defaults.modes[name] = mode
end
--- Update the default config.
--- Should only be used by source to extend the default config.
---@param config trouble.Config
function M.defaults(config)
options = vim.tbl_deep_extend("force", config, options)
end

function M.modes()
Expand All @@ -125,6 +124,16 @@ end
function M.get(...)
options = options or M.setup()

-- check if we need to load sources
for i = 1, select("#", ...) do
---@type trouble.Config?
local opts = select(i, ...)
if type(opts) == "string" or (type(opts) == "table" and opts.mode) then
M.modes() -- trigger loading of sources
break
end
end

---@type trouble.Config[]
local all = { {}, defaults, options or {} }

Expand All @@ -138,9 +147,6 @@ function M.get(...)
opts = { mode = opts }
end
if opts then
if opts.mode then
M.modes() -- trigger loading of sources
end
table.insert(all, opts)
local idx = #all
while opts.mode and not modes[opts.mode] do
Expand Down
12 changes: 6 additions & 6 deletions lua/trouble/filter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ function M.filter(items, filter, view)
if not filter or (type(filter) == "table" and vim.tbl_isempty(filter)) then
return items, {}
end
local pass = {} ---@type trouble.Item[]
local fail = {} ---@type trouble.Item[]
if type(filter) == "function" then
return filter(items)
end
local ret = {} ---@type trouble.Item[]
for _, item in ipairs(items) do
if M.is(item, filter, view) then
pass[#pass + 1] = item
else
fail[#fail + 1] = item
ret[#ret + 1] = item
end
end
return pass, fail
return ret
end

return M
19 changes: 7 additions & 12 deletions lua/trouble/sort.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local Filter = require("trouble.filter")

local M = {}

---@type table<string, trouble.Sorter>
---@type table<string, trouble.SorterFn>
M.sorters = {
pos = function(obj)
-- Use large multipliers for higher priority fields to ensure their precedence in sorting
Expand All @@ -15,7 +15,7 @@ M.sorters = {

---@param items trouble.Item[]
---@param view trouble.View
---@param opts? trouble.Sort
---@param opts? trouble.Sort[]
function M.sort(items, opts, view)
if not opts or #opts == 0 then
return items
Expand All @@ -25,25 +25,20 @@ function M.sort(items, opts, view)
local desc = {} ---@type boolean[]

-- pre-compute fields
local fields = {} ---@type {sorter?:trouble.Sorter, field?:string, filter?:trouble.Filter}[]
local fields = {} ---@type trouble.Sort[]
for f, field in ipairs(opts) do
if type(field) == "function" then
---@cast field trouble.Sorter
fields[f] = { sorter = field }
elseif type(field) == "table" and field.field then
---@cast field {field:string, desc?:boolean}
if field.field then
---@diagnostic disable-next-line: no-unknown
local sorter = view.opts.sorters[field.field] or M.sorters[field.field]
if sorter then
fields[f] = { sorter = sorter }
else
fields[f] = { field = field.field }
end
desc[f] = field.desc
elseif type(field) == "table" then
fields[f] = { filter = field }
else
error("invalid sort field: " .. vim.inspect(field))
fields[f] = field
end
desc[f] = field.desc or false
end

-- pre-compute keys
Expand Down
14 changes: 10 additions & 4 deletions lua/trouble/source.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
local Preview = require("trouble.view.preview")
local Config = require("trouble.config")
local Util = require("trouble.util")

---@class trouble.Source
---@field highlights? table<string, string>
---@field modes? table<string,trouble.Mode>
---@field config? trouble.Config
---@field setup? fun()
---@field get trouble.Source.get|table<string, trouble.Source.get>

Expand All @@ -29,8 +29,14 @@ function M.register(name, source)
source.setup()
end
require("trouble.config.highlights").source(name, source.highlights)
if source.modes then
require("trouble.config").register(source.modes)
if source.config then
source.config.modes = source.config.modes or {}
for view in pairs(source.config.views or {}) do
source.config.modes[view] = source.config.modes[view] or {
sections = { view },
}
end
Config.defaults(source.config)
end
end
M.sources[name] = source
Expand Down
82 changes: 40 additions & 42 deletions lua/trouble/sources/diagnostics.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,53 +10,51 @@ M.highlights = {
Code = "Comment",
}

M.modes = {
diagnostics = {
events = { "DiagnosticChanged", "BufEnter" },
sections = {
{
-- Trouble classic for other buffers,
-- but only if they are in the current directory
source = "diagnostics",
groups = {
-- { format = "{hl:Special}蟀殺 {hl} {hl:Title}Diagnostics{hl} {count}" },
-- { "severity", format = "{severity_icon} {severity} {count}" },
{ "filename", format = "{file_icon} {filename} {count}" },
},
sort = { { buf = 0 }, "severity", "filename", "pos", "message" },
format = "{severity_icon} {message:md} {item.source} ({code}) {pos}",
-- filter = {
-- ["not"] = {
-- any = {
-- { severity = vim.diagnostic.severity.ERROR },
-- { buf = 0 },
-- },
-- },
-- function(item)
-- return item.filename:find(vim.loop.cwd(), 1, true)
-- end,
-- },
M.config = {
views = {
diagnostics = {
events = { "DiagnosticChanged", "BufEnter" },
-- Trouble classic for other buffers,
-- but only if they are in the current directory
source = "diagnostics",
groups = {
-- { format = "{hl:Special}蟀殺 {hl} {hl:Title}Diagnostics{hl} {count}" },
-- { "severity", format = "{severity_icon} {severity} {count}" },
{ "filename", format = "{file_icon} {filename} {count}" },
},
-- {
-- -- error from all files
-- source = "diagnostics",
-- groups = { "severity", "code", "filename" },
-- filter = {
-- -- severity = 1,
sort = { { buf = 0 }, "severity", "filename", "pos", "message" },
format = "{severity_icon} {message:md} {item.source} ({code}) {pos}",
-- filter = {
-- ["not"] = {
-- any = {
-- { severity = vim.diagnostic.severity.ERROR },
-- { buf = 0 },
-- },
-- sort = { "filename", "pos" },
-- format = "sig {severity_sign} {severity} file: {filename} pos: {pos}",
-- },
-- {
-- -- diagnostics from current buffer
-- source = "diagnostics",
-- groups = { "severity", "filename" },
-- filter = {
-- buf = 0,
-- },
-- sort = { "pos" },
-- function(item)
-- return item.filename:find(vim.loop.cwd(), 1, true)
-- end,
-- },
},
-- {
-- -- error from all files
-- source = "diagnostics",
-- groups = { "severity", "code", "filename" },
-- filter = {
-- -- severity = 1,
-- },
-- sort = { "filename", "pos" },
-- format = "sig {severity_sign} {severity} file: {filename} pos: {pos}",
-- },
-- {
-- -- diagnostics from current buffer
-- source = "diagnostics",
-- groups = { "severity", "filename" },
-- filter = {
-- buf = 0,
-- },
-- sort = { "pos" },
-- },
},
}

Expand Down
54 changes: 34 additions & 20 deletions lua/trouble/sources/lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@ local get_col = vim.lsp.util._get_line_byte_from_position
---@type trouble.Source
local M = {}

M.modes = {}
M.config = {
views = {},
modes = {
lsp = {
sections = { "lsp_definitions", "lsp_references", "lsp_implementations", "lsp_type_definitions" },
},
},
}

for _, mode in ipairs({ "definitions", "references", "implementations", "type_definitions" }) do
M.modes["lsp_" .. mode] = {
M.config.views["lsp_" .. mode] = {
title = "{hl:Title}" .. mode:gsub("^%l", string.upper) .. "{hl} {count}",
events = { "CursorHold" },
sections = {
{
source = "lsp." .. mode,
groups = {
{ "filename", format = "{file_icon} {filename} {count}" },
},
sort = { { buf = 0 }, "filename", "pos", "text" },
format = "{text:ts} ({item.client}) {pos}",
},
-- events = { "CursorHold", "CursorMoved" },
source = "lsp." .. mode,
groups = {
{ "filename", format = "{file_icon} {filename} {count}" },
},
sort = { { buf = 0 }, "filename", "pos", "text" },
format = "{text:ts} ({item.client}) {pos}",
}
end

Expand All @@ -34,16 +40,24 @@ function M.get_locations(method, cb, context)
---@diagnostic disable-next-line: inject-field
params.context = context

vim.lsp.buf_request_all(buf, method, params, function(results)
local items = {} ---@type trouble.Item[]
for client_id, result in pairs(results) do
if result and result.result then
local client = assert(vim.lsp.get_client_by_id(client_id))
vim.list_extend(items, M.get_items(client, result.result))
local clients = vim.lsp.get_clients({ method = method, bufnr = buf })

local items = {} ---@type trouble.Item[]
local done = 0
if #clients == 0 then
return cb(items)
end
for _, client in ipairs(clients) do
vim.lsp.buf_request(buf, method, params, function(_, result)
done = done + 1
if result then
vim.list_extend(items, M.get_items(client, result))
end
end
cb(items)
end)
if done == #clients then
cb(items)
end
end)
end
end

---@param client lsp.Client
Expand Down
38 changes: 19 additions & 19 deletions lua/trouble/sources/qf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,26 @@ local Item = require("trouble.item")
---@type trouble.Source
local M = {}

---@type trouble.spec.section[]
local sections = {
{
source = "qf.qflist",
groups = {
{ "filename", format = "{file_icon} {filename} {count}" },
M.config = {
views = {
qflist = {
events = { "BufEnter", "QuickFixCmdPost" },
source = "qf.qflist",
groups = {
{ "filename", format = "{file_icon} {filename} {count}" },
},
sort = { { buf = 0 }, "severity", "filename", "pos", "message" },
format = "{severity_icon|item.type:DiagnosticSignWarn} {text} {pos}",
},
loclist = {
events = { "BufEnter" },
source = "qf.loclist",
groups = {
{ "filename", format = "{file_icon} {filename} {count}" },
},
sort = { { buf = 0 }, "severity", "filename", "pos", "message" },
format = "{severity_icon|item.type:DiagnosticSignWarn} {text} {pos}",
},
sort = { { buf = 0 }, "severity", "filename", "pos", "message" },
format = "{severity_icon|item.type:DiagnosticSignWarn} {text} {pos}",
},
}

M.modes = {
qflist = {
events = { "BufEnter", "QuickFixCmdPost" },
sections = sections,
},
loclist = {
events = { "BufEnter" },
sections = sections,
},
}

Expand Down

0 comments on commit 13d5db9

Please sign in to comment.