Skip to content

Commit

Permalink
feat: actions for sending oil entries to quickfix (#249)
Browse files Browse the repository at this point in the history
* Implement actions for sending oil entries to quickfix/location-list

* Use vim.notify instead of vim.notify_once in util quickfix function

* Remove redundant files/directories options for sending to qf

always send just files

* set qflist/loclist with a single call

* Add type annotations and default values for send_to_quickfix

* In visual mode, send only selected items to qf
  • Loading branch information
lpoto authored Dec 8, 2023
1 parent b3c24f4 commit 3ffb830
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 11 deletions.
40 changes: 40 additions & 0 deletions lua/oil/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,46 @@ M.toggle_trash = {
end,
}

M.send_to_qflist = {
desc = "Sends files in the current oil directory to the quickfix list, replacing the previous entries.",
callback = function()
util.send_to_quickfix({
target = "qflist",
mode = "r",
})
end,
}

M.add_to_qflist = {
desc = "Adds files in the current oil directory to the quickfix list, keeping the previous entries.",
callback = function()
util.send_to_quickfix({
target = "qflist",
mode = "a",
})
end,
}

M.send_to_loclist = {
desc = "Sends files in the current oil directory to the location list, replacing the previous entries.",
callback = function()
util.send_to_quickfix({
target = "loclist",
mode = "r",
})
end,
}

M.add_to_loclist = {
desc = "Adds files in the current oil directory to the location list, keeping the previous entries.",
callback = function()
util.send_to_quickfix({
target = "loclist",
mode = "a",
})
end,
}

---List actions for documentation generation
---@private
M._get_actions = function()
Expand Down
14 changes: 3 additions & 11 deletions lua/oil/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -456,20 +456,12 @@ M.select = function(opts, callback)
return finish("Could not find adapter for current buffer")
end

local mode = vim.api.nvim_get_mode().mode
local is_visual = mode:match("^[vV]")
local visual_range = util.get_visual_range()

---@type oil.Entry[]
local entries = {}
if is_visual then
-- This is the best way to get the visual selection at the moment
-- https://github.com/neovim/neovim/pull/13896
local _, start_lnum, _, _ = unpack(vim.fn.getpos("v"))
local _, end_lnum, _, _, _ = unpack(vim.fn.getcurpos())
if start_lnum > end_lnum then
start_lnum, end_lnum = end_lnum, start_lnum
end
for i = start_lnum, end_lnum do
if visual_range then
for i = visual_range.start_lnum, visual_range.end_lnum do
local entry = M.get_entry_on_line(0, i)
if entry then
table.insert(entries, entry)
Expand Down
62 changes: 62 additions & 0 deletions lua/oil/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -697,4 +697,66 @@ M.adapter_list_all = function(adapter, url, opts, callback)
end)
end

---Send files from the current oil directory to quickfix
---based on the provided options.
---@param opts {target?: "qflist"|"loclist", mode?: "r"|"a"}
M.send_to_quickfix = function(opts)
if type(opts) ~= "table" then
opts = {}
end
local oil = require("oil")
local dir = oil.get_current_dir()
if type(dir) ~= "string" then
return
end
local range = M.get_visual_range()
if not range then
range = { start_lnum = 1, end_lnum = vim.fn.line("$") }
end
local qf_entries = {}
for i = range.start_lnum, range.end_lnum do
local entry = oil.get_entry_on_line(0, i)
if entry and entry.type == "file" then
local qf_entry = {
filename = dir .. entry.name,
lnum = 1,
col = 1,
text = entry.name,
}
table.insert(qf_entries, qf_entry)
end
end
if #qf_entries == 0 then
vim.notify("[oil] No entries found to send to quickfix", vim.log.levels.WARN)
return
end
vim.api.nvim_exec_autocmds("QuickFixCmdPre", {})
local qf_title = "oil files"
local mode = opts.mode == "a" and "a" or "r"
if opts.target == "loclist" then
vim.fn.setloclist(0, {}, mode, { title = qf_title, items = qf_entries })
else
vim.fn.setqflist({}, mode, { title = qf_title, items = qf_entries })
end
vim.api.nvim_exec_autocmds("QuickFixCmdPost", {})
end

---Get the current visual selection range. If not in visual mode, return nil.
---@return {start_lnum: integer, end_lnum: integer}?
M.get_visual_range = function()
local mode = vim.api.nvim_get_mode().mode
local is_visual = mode:match("^[vV]")
if not is_visual then
return
end
-- This is the best way to get the visual selection at the moment
-- https://github.com/neovim/neovim/pull/13896
local _, start_lnum, _, _ = unpack(vim.fn.getpos("v"))
local _, end_lnum, _, _, _ = unpack(vim.fn.getcurpos())
if start_lnum > end_lnum then
start_lnum, end_lnum = end_lnum, start_lnum
end
return { start_lnum = start_lnum, end_lnum = end_lnum }
end

return M

0 comments on commit 3ffb830

Please sign in to comment.