summaryrefslogtreecommitdiff
path: root/lua/quicker/follow.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/quicker/follow.lua')
-rw-r--r--lua/quicker/follow.lua84
1 files changed, 84 insertions, 0 deletions
diff --git a/lua/quicker/follow.lua b/lua/quicker/follow.lua
new file mode 100644
index 0000000..d5500a2
--- /dev/null
+++ b/lua/quicker/follow.lua
@@ -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