Skip to content

Commit

Permalink
feat: option to scroll to closest quickfix item (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Dec 24, 2024
1 parent da7e910 commit cc8bb67
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 5 deletions.
12 changes: 12 additions & 0 deletions lua/quicker/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ local default_config = {
-- Load the referenced buffers to apply more accurate highlights (may be slow)
load_buffers = true,
},
follow = {
-- When quickfix window is open, scroll to closest item to the cursor
enabled = false,
},
-- Map of quickfix item type to icon
type_icons = {
E = "󰅚 ",
Expand Down Expand Up @@ -74,6 +78,7 @@ local default_config = {
---@field use_default_opts boolean
---@field constrain_cursor boolean
---@field highlight quicker.HighlightConfig
---@field follow quicker.FollowConfig
---@field edit quicker.EditConfig
---@field type_icons table<string, string>
---@field borders quicker.Borders
Expand All @@ -89,6 +94,7 @@ local M = {}
---@field use_default_opts? boolean Set to false to disable the default options in `opts`
---@field constrain_cursor? boolean Keep the cursor to the right of the filename and lnum columns
---@field highlight? quicker.SetupHighlightConfig Configure syntax highlighting
---@field follow? quicker.SetupFollowConfig Configure cursor following
---@field edit? quicker.SetupEditConfig
---@field type_icons? table<string, string> Map of quickfix item type to icon
---@field borders? quicker.SetupBorders Characters used for drawing the borders
Expand Down Expand Up @@ -157,6 +163,12 @@ end
---@field lsp? boolean Use LSP semantic token highlighting
---@field load_buffers? boolean Load the referenced buffers to apply more accurate highlights (may be slow)

---@class (exact) quicker.FollowConfig
---@field enabled boolean

---@class (exact) quicker.SetupFollowConfig
---@field enabled? boolean

---@class (exact) quicker.EditConfig
---@field enabled boolean
---@field autosave boolean|"unmodified"
Expand Down
84 changes: 84 additions & 0 deletions lua/quicker/follow.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
local util = require("quicker.util")
local M = {}

M.seek_to_position = function()
if util.is_open(0) then
local qf_list = vim.fn.getloclist(0, { winid = 0, items = 0 })
local new_pos = M.calculate_pos(qf_list.items)
if new_pos then
M.set_pos(qf_list.winid, new_pos)
end
end

if util.is_open() then
local qf_list = vim.fn.getqflist({ winid = 0, items = 0 })
local new_pos = M.calculate_pos(qf_list.items)
if new_pos then
M.set_pos(qf_list.winid, new_pos)
end
end
end

---Calculate the current buffer/cursor location in the quickfix list
---@param list QuickFixItem[]
---@return nil|integer
M.calculate_pos = function(list)
if vim.bo.buftype ~= "" then
return
end
local bufnr = vim.api.nvim_get_current_buf()
local cursor = vim.api.nvim_win_get_cursor(0)
local lnum, col = cursor[1], cursor[2] + 1
local prev_lnum = -1
local prev_col = -1
local found_buf = false
local ret
for i, entry in ipairs(list) do
if entry.bufnr ~= bufnr then
if found_buf then
return ret
end
else
found_buf = true

-- If we detect that the list isn't sorted, bail.
if
prev_lnum > -1
and (entry.lnum < prev_lnum or (entry.lnum == prev_lnum and entry.col <= prev_col))
then
return
end

if prev_lnum == -1 or lnum > entry.lnum or (lnum == entry.lnum and col >= entry.col) then
ret = i
end
prev_lnum = entry.lnum
prev_col = entry.col
end
end

return ret
end

local timers = {}
---@param winid integer
---@param pos integer
M.set_pos = function(winid, pos)
local timer = timers[winid]
if timer then
timer:close()
end
timer = assert(vim.uv.new_timer())
timers[winid] = timer
timer:start(10, 0, function()
timer:close()
timers[winid] = nil
vim.schedule(function()
if vim.api.nvim_win_is_valid(winid) then
pcall(vim.api.nvim_win_set_cursor, winid, { pos, 0 })
end
end)
end)
end

return M
16 changes: 11 additions & 5 deletions lua/quicker/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ local function setup(opts)
end,
})
end
if config.follow.enabled then
vim.api.nvim_create_autocmd({ "CursorMoved", "BufEnter" }, {
desc = "quicker.nvim scroll to nearest location in quickfix",
pattern = "*",
group = aug,
callback = function()
require("quicker.follow").seek_to_position()
end,
})
end

vim.o.quickfixtextfunc = "v:lua.require'quicker.display'.quickfixtextfunc"

Expand Down Expand Up @@ -95,11 +105,7 @@ end

---@param loclist_win? integer Check if loclist is open for the given window. If nil, check quickfix.
M.is_open = function(loclist_win)
if loclist_win then
return vim.fn.getloclist(loclist_win or 0, { winid = 0 }).winid ~= 0
else
return vim.fn.getqflist({ winid = 0 }).winid ~= 0
end
return require("quicker.util").is_open(loclist_win)
end

---@class quicker.OpenCmdMods: vim.api.keyset.parse_cmd.mods
Expand Down
9 changes: 9 additions & 0 deletions lua/quicker/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ function M.buf_find_win(bufnr)
end
end

---@param loclist_win? integer Check if loclist is open for the given window. If nil, check quickfix.
M.is_open = function(loclist_win)
if loclist_win then
return vim.fn.getloclist(loclist_win or 0, { winid = 0 }).winid ~= 0
else
return vim.fn.getqflist({ winid = 0 }).winid ~= 0
end
end

---@param winid nil|integer
---@return nil|"c"|"l"
M.get_win_type = function(winid)
Expand Down

0 comments on commit cc8bb67

Please sign in to comment.