Skip to content

Commit

Permalink
feat: you can now use dd and d to delete items in the trouble list.
Browse files Browse the repository at this point in the history
Fixes #149. Fixes #347
  • Loading branch information
folke committed Jun 7, 2024
1 parent 791278e commit e879302
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 30 deletions.
4 changes: 1 addition & 3 deletions lua/trouble/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,8 @@ function M.refresh(opts)
end

-- Proxy to last view's action.
---@param action trouble.Action|string
---@param action trouble.Action.spec
function M._action(action)
action = type(action) == "string" and Actions[action] or action
---@cast action trouble.Action
return function(opts)
local view = M.open(opts)
if view then
Expand Down
25 changes: 21 additions & 4 deletions lua/trouble/config/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ local Util = require("trouble.util")

---@alias trouble.Action.ctx {item?: trouble.Item, node?: trouble.Node, opts?: table}
---@alias trouble.ActionFn fun(view:trouble.View, ctx:trouble.Action.ctx)
---@alias trouble.Action trouble.ActionFn|{action:trouble.ActionFn, desc?:string}
---@alias trouble.Action {action: trouble.ActionFn, desc?: string, mode?: string}
---@alias trouble.Action.spec string|trouble.ActionFn|trouble.Action|{action: string}

---@class trouble.actions: {[string]: trouble.Action}
---@class trouble.actions: {[string]: trouble.ActionFn}
local M = {
-- Refresh the trouble source
refresh = function(self)
Expand Down Expand Up @@ -32,19 +33,35 @@ local M = {
self:preview(ctx.item)
end
end,
-- Open the preview
delete = function(self)
local enabled = self.opts.auto_refresh
self:delete()
if enabled and not self.opts.auto_refresh then
Util.warn("Auto refresh **disabled**", { id = "toggle_refresh" })
end
end,
-- Toggle the preview
toggle_preview = function(self)
toggle_preview = function(self, ctx)
self.opts.auto_preview = not self.opts.auto_preview
local enabled = self.opts.auto_preview and "enabled" or "disabled"
local notify = (enabled == "enabled") and Util.info or Util.warn
notify("Auto preview **" .. enabled .. "**", { id = "toggle_preview" })
local Preview = require("trouble.view.preview")
if self.opts.auto_preview then
self:preview()
if ctx.item then
self:preview()
end
else
Preview.close()
end
end,
-- Toggle the auto refresh
toggle_refresh = function(self)
self.opts.auto_refresh = not self.opts.auto_refresh
local enabled = self.opts.auto_refresh and "enabled" or "disabled"
local notify = (enabled == "enabled") and Util.info or Util.warn
notify("Auto refresh **" .. enabled .. "**", { id = "toggle_refresh" })
end,

filter = function(self, ctx)
Expand Down
4 changes: 3 additions & 1 deletion lua/trouble/config/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ local defaults = {
},
-- Key mappings can be set to the name of a builtin action,
-- or you can define your own custom action.
---@type table<string, string|trouble.Action>
---@type table<string, trouble.Action.spec>
keys = {
["?"] = "help",
r = "refresh",
Expand All @@ -70,6 +70,8 @@ local defaults = {
-- k = "prev",
["{"] = "prev",
["[["] = "prev",
dd = "delete",
d = { action = "delete", mode = "v" },
i = "inspect",
p = "preview",
P = "toggle_preview",
Expand Down
16 changes: 16 additions & 0 deletions lua/trouble/spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,22 @@ function M.section(spec)
return ret
end

---@param action trouble.Action.spec
function M.action(action)
if type(action) == "string" then
action = { action = action, desc = action:gsub("_", " ") }
end
if type(action) == "function" then
action = { action = action }
end
if type(action.action) == "string" then
action.desc = action.desc or action.action:gsub("_", " ")
action.action = require("trouble.config.actions")[action.action]
end
---@cast action trouble.Action
return action
end

---@param mode trouble.Mode
---@return trouble.Section.opts[]
function M.sections(mode)
Expand Down
21 changes: 21 additions & 0 deletions lua/trouble/tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@ function M.new(opts)
return self
end

function M:delete()
local parent = self.parent
if not parent then
return
end
if parent.children then
parent.children = vim.tbl_filter(function(c)
return c ~= self
end, parent.children)
end
if parent.index and self.id then
parent.index[self.id] = nil
end
parent._count = nil
parent._degree = nil
if parent:count() == 0 then
parent:delete()
end
end

-- Max depth of the tree
function M:degree()
if not self._degree then
Expand Down Expand Up @@ -60,6 +80,7 @@ function M:count()
return self._count
end

--- Gets all the items in the tree, recursively.
---@param ret trouble.Item[]?
function M:flatten(ret)
ret = ret or {}
Expand Down
18 changes: 16 additions & 2 deletions lua/trouble/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ end

M.islist = vim.islist or vim.tbl_islist

---@alias NotifyOpts {level?: number, title?: string, once?: boolean}
---@alias NotifyOpts {level?: number, title?: string, once?: boolean, id?:string}

---@type table<string, any>
local notif_ids = {}

---@param msg string|string[]
---@param opts? NotifyOpts
Expand All @@ -32,7 +35,8 @@ function M.notify(msg, opts)
msg = type(msg) == "table" and table.concat(msg, "\n") or msg
---@cast msg string
msg = vim.trim(msg)
return vim[opts.once and "notify_once" or "notify"](msg, opts.level, {
local ret = vim[opts.once and "notify_once" or "notify"](msg, opts.level, {
replace = opts.id and notif_ids[opts.id] or nil,
title = opts.title or "Trouble",
on_open = function(win)
vim.wo.conceallevel = 3
Expand All @@ -41,6 +45,10 @@ function M.notify(msg, opts)
vim.treesitter.start(vim.api.nvim_win_get_buf(win), "markdown")
end,
})
if opts.id then
notif_ids[opts.id] = ret
end
return ret
end

---@param msg string|string[]
Expand All @@ -49,6 +57,12 @@ function M.warn(msg, opts)
M.notify(msg, vim.tbl_extend("keep", { level = vim.log.levels.WARN }, opts or {}))
end

---@param msg string|string[]
---@param opts? NotifyOpts
function M.info(msg, opts)
M.notify(msg, vim.tbl_extend("keep", { level = vim.log.levels.INFO }, opts or {}))
end

---@param msg string|string[]
---@param opts? NotifyOpts
function M.error(msg, opts)
Expand Down
58 changes: 40 additions & 18 deletions lua/trouble/view/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,19 @@ function M:on_mount()
end, { remap = false, expr = true })
end

---@param node? trouble.Node
function M:delete(node)
local selection = node and { node } or self:selection()
if #selection == 0 then
return
end
for _, n in ipairs(selection) do
n:delete()
end
self.opts.auto_refresh = false
self:render()
end

---@param node? trouble.Node
---@param opts? trouble.Render.fold_opts
function M:fold(node, opts)
Expand Down Expand Up @@ -311,29 +324,37 @@ function M:at(cursor)
return self.renderer:at(cursor[1])
end

function M:selection()
if not vim.fn.mode():lower():find("v") then
local ret = self:at()
return ret.node and { ret.node } or {}
end
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<esc>", true, false, true), "x", false)

local from = vim.api.nvim_buf_get_mark(self.win.buf, "<")[1]
local to = vim.api.nvim_buf_get_mark(self.win.buf, ">")[1]
---@type trouble.Node[]
local ret = {}
for row = from, to do
local node = self.renderer:at(row).node
if not vim.tbl_contains(ret, node) then
ret[#ret + 1] = node
end
end
return ret
end

---@param key string
---@param action trouble.Action|string
---@param action trouble.Action.spec
function M:map(key, action)
local desc ---@type string?
if type(action) == "string" then
desc = action:gsub("_", " ")
action = require("trouble.config.actions")[action]
end
---@type trouble.ActionFn
local fn
if type(action) == "function" then
fn = action
else
fn = action.action
desc = action.desc or desc
end
action = Spec.action(action)
local _self = Util.weak(self)
self.win:map(key, function()
local this = _self()
if this then
this:action(fn)
this:action(action)
end
end, desc)
end, { desc = action.desc, mode = action.mode })
end

---@param opts? {idx?: number, up?:number, down?:number, jump?:boolean}
Expand Down Expand Up @@ -374,12 +395,13 @@ function M:move(opts)
end
end

---@param action trouble.Action
---@param action trouble.Action.spec
---@param opts? table
function M:action(action, opts)
action = Spec.action(action)
self:wait(function()
local at = self:at() or {}
action(self, {
action.action(self, {
item = at.item,
node = at.node,
opts = type(opts) == "table" and opts or {},
Expand Down
8 changes: 6 additions & 2 deletions lua/trouble/view/window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -363,19 +363,23 @@ end

---@param key string
---@param fn fun(self: trouble.Window):any
---@param opts? string|vim.keymap.set.Opts
---@param opts? string|vim.keymap.set.Opts|{mode?:string}
function M:map(key, fn, opts)
opts = vim.tbl_deep_extend("force", {
buffer = self.buf,
nowait = true,
mode = "n",
}, type(opts) == "string" and { desc = opts } or opts or {})
local mode = opts.mode
opts.mode = nil
---@cast opts vim.keymap.set.Opts
if not self:valid() then
error("Cannot create a keymap for an invalid window")
end

self.keys[key] = opts.desc or key
local weak_self = Util.weak(self)
vim.keymap.set("n", key, function()
vim.keymap.set(mode, key, function()
if weak_self() then
return fn(weak_self())
end
Expand Down

0 comments on commit e879302

Please sign in to comment.