feat(nav): add option to auto preview

Resolves #494
This commit is contained in:
Lewis Russell 2022-03-25 16:52:13 +00:00 committed by Lewis Russell
parent 3791dfa1ee
commit 7ff03e1eba
6 changed files with 98 additions and 14 deletions

View File

@ -146,8 +146,27 @@ require('gitsigns').setup{
end
-- Navigation
map('n', ']c', "&diff ? ']c' : '<cmd>Gitsigns next_hunk<CR>'", {expr=true})
map('n', '[c', "&diff ? '[c' : '<cmd>Gitsigns prev_hunk<CR>'", {expr=true})
map('n', ']c', function()
if vim.wo.diff then
return ']c'
else
vim.schedule(function()
gitsigns.next_hunk()
end)
return '<Ignore>'
end
end, {expr=true})
map('n', '[c', function()
if vim.wo.diff then
return '[c'
else
vim.schedule(function()
gitsigns.prev_hunk()
end)
return '<Ignore>'
end
end, {expr=true})
-- Actions
map({'n', 'v'}, '<leader>hs', ':Gitsigns stage_hunk<CR>')

View File

@ -312,6 +312,9 @@ next_hunk({opts}) *gitsigns.next_hunk()*
Expand folds when navigating to a hunk which is
inside a fold. Defaults to `true` if 'foldopen'
contains `search`.
• {preview}: (boolean)
Automatically open preview_hunk() upon navigating
to a hunk.
reset_buffer_index() *gitsigns.reset_buffer_index()*
Unstage all hunks for current buffer in the index. Note:

View File

@ -28,6 +28,7 @@ local NavHunkOpts = {}
local M = {QFListOpts = {}, }
@ -329,6 +330,15 @@ local function process_nav_opts(opts)
end
end
local function defer(fn)
if vim.in_fast_event() then
vim.schedule(fn)
else
vim.defer_fn(fn, 1)
end
end
local function nav_hunk(opts)
process_nav_opts(opts)
local bcache = cache[current_buf()]
@ -365,8 +375,10 @@ local function nav_hunk(opts)
if opts.foldopen then
vim.cmd('silent! foldopen!')
end
if pcall(api.nvim_buf_get_var, 0, '_gitsigns_preview_open') then
vim.schedule(M.preview_hunk)
if opts.preview or popup.is_open() then
defer(M.preview_hunk)
end
if index ~= nil and opts.navigation_message then
@ -390,6 +402,9 @@ end
M.next_hunk = function(opts)
opts = opts or {}
opts.forwards = true
@ -476,9 +491,6 @@ M.preview_hunk = noautocmd(function()
add_highlight(bufnr, -1, 'Title', 0, 0, -1)
api.nvim_buf_set_var(cbuf, '_gitsigns_preview_open', true)
vim.cmd([[autocmd CursorMoved,CursorMovedI <buffer> ++once silent! unlet b:_gitsigns_preview_open]])
local offset = #lines - hunk.removed.count - hunk.added.count
highlight_hunk_lines(bufnr, offset, hunk)
end)

21
lua/gitsigns/popup.lua generated
View File

@ -59,6 +59,8 @@ function popup.create(lines, opts)
local win_id = api.nvim_open_win(bufnr, false, opts1)
api.nvim_win_set_var(win_id, 'gitsigns_preview', true)
if not opts.height then
expand_height(win_id, #lines)
end
@ -73,14 +75,21 @@ function popup.create(lines, opts)
local group = 'gitsigns_popup' .. win_id
nvim.augroup(group)
local old_cursor = api.nvim_win_get_cursor(0)
nvim.autocmd({ 'CursorMoved', 'CursorMovedI' }, {
group = group,
callback = function()
if api.nvim_get_current_win() ~= win_id then
local cursor = api.nvim_win_get_cursor(0)
if (old_cursor[1] ~= cursor[1] or old_cursor[2] ~= cursor[2]) and
api.nvim_get_current_win() ~= win_id then
nvim.augroup(group)
pcall(api.nvim_win_close, win_id, true)
return
end
old_cursor = cursor
end,
})
@ -88,4 +97,14 @@ function popup.create(lines, opts)
end
function popup.is_open()
for _, winid in ipairs(api.nvim_list_wins()) do
local exists = pcall(api.nvim_win_get_var, winid, 'gitsigns_preview')
if exists then
return true
end
end
return false
end
return popup

View File

@ -26,6 +26,7 @@ local record NavHunkOpts
wrap: boolean
navigation_message: boolean
foldopen: boolean
preview: boolean
end
local record M
@ -329,6 +330,15 @@ local function process_nav_opts(opts: NavHunkOpts)
end
end
-- Defer function to the next main event
local function defer(fn: function)
if vim.in_fast_event() then
vim.schedule(fn)
else
vim.defer_fn(fn, 1)
end
end
local function nav_hunk(opts: NavHunkOpts)
process_nav_opts(opts)
local bcache = cache[current_buf()]
@ -365,8 +375,10 @@ local function nav_hunk(opts: NavHunkOpts)
if opts.foldopen then
vim.cmd('silent! foldopen!')
end
if pcall(api.nvim_buf_get_var, 0, '_gitsigns_preview_open') then
vim.schedule(M.preview_hunk)
if opts.preview or popup.is_open() then
-- Use defer so the cursor change can settle, otherwise the popup might
-- appear in the old position
defer(M.preview_hunk)
end
if index ~= nil and opts.navigation_message then
@ -390,6 +402,9 @@ end
--- Expand folds when navigating to a hunk which is
--- inside a fold. Defaults to `true` if 'foldopen'
--- contains `search`.
--- • {preview}: (boolean)
--- Automatically open preview_hunk() upon navigating
--- to a hunk.
M.next_hunk = function(opts: NavHunkOpts)
opts = opts or {}
opts.forwards = true
@ -476,9 +491,6 @@ M.preview_hunk = noautocmd(function()
add_highlight(bufnr, -1, 'Title', 0, 0, -1)
api.nvim_buf_set_var(cbuf, '_gitsigns_preview_open', true)
vim.cmd[[autocmd CursorMoved,CursorMovedI <buffer> ++once silent! unlet b:_gitsigns_preview_open]]
local offset = #lines - hunk.removed.count - hunk.added.count
highlight_hunk_lines(bufnr as integer, offset, hunk)
end)

View File

@ -59,6 +59,8 @@ function popup.create(lines: {string}, opts: {string:any}): integer, integer
local win_id = api.nvim_open_win(bufnr, false, opts1)
api.nvim_win_set_var(win_id, 'gitsigns_preview', true)
if not opts.height then
expand_height(win_id, #lines)
end
@ -73,14 +75,21 @@ function popup.create(lines: {string}, opts: {string:any}): integer, integer
-- itself.
local group = 'gitsigns_popup'..win_id
nvim.augroup(group)
local old_cursor = api.nvim_win_get_cursor(0)
nvim.autocmd({'CursorMoved', 'CursorMovedI'}, {
group = group,
callback = function()
if api.nvim_get_current_win() ~= win_id then
local cursor = api.nvim_win_get_cursor(0)
-- Did the cursor REALLY change (neovim/neovim#12923)
if (old_cursor[1] ~= cursor[1] or old_cursor[2] ~= cursor[2])
and api.nvim_get_current_win() ~= win_id then
-- Clear the augroup
nvim.augroup(group)
pcall(api.nvim_win_close, win_id, true)
return
end
old_cursor = cursor
end
})
@ -88,4 +97,14 @@ function popup.create(lines: {string}, opts: {string:any}): integer, integer
end
function popup.is_open(): boolean
for _, winid in ipairs(api.nvim_list_wins()) do
local exists = pcall(api.nvim_win_get_var, winid, 'gitsigns_preview')
if exists then
return true
end
end
return false
end
return popup