Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(actions): Automatic inline diff preview on hover #817

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ require('gitsigns').setup {
ignore_whitespace = false,
},
current_line_blame_formatter = '<author>, <author_time:%Y-%m-%d> - <summary>',
automatic_hunk_inline = false, -- `:h gitsigns-config-automatic_hunk_inline`
sign_priority = 6,
update_debounce = 100,
status_formatter = nil, -- Use default
Expand Down Expand Up @@ -177,6 +178,7 @@ require('gitsigns').setup {
map('n', '<leader>hu', '<cmd>Gitsigns undo_stage_hunk<CR>')
map('n', '<leader>hR', '<cmd>Gitsigns reset_buffer<CR>')
map('n', '<leader>hp', '<cmd>Gitsigns preview_hunk<CR>')
map('n', '<leader>hP', '<cmd>Gitsigns automatic_hunk_inline<CR>')
map('n', '<leader>hb', '<cmd>lua require"gitsigns".blame_line{full=true}<CR>')
map('n', '<leader>tb', '<cmd>Gitsigns toggle_current_line_blame<CR>')
map('n', '<leader>hd', '<cmd>Gitsigns diffthis<CR>')
Expand Down Expand Up @@ -231,7 +233,7 @@ Ensures signs are always up to date | :white_check_mark: *
Never saves the buffer | :white_check_mark: | :white_check_mark: :heavy_exclamation_mark: * | * Writes [buffer](https://github.com/airblade/vim-gitgutter/blob/0f98634b92da9a35580b618c11a6d2adc42d9f90/autoload/gitgutter/diff.vim#L106) (and index) to short lived temp files
Quick jumping between hunks | :white_check_mark: | :white_check_mark: |
Stage/reset/preview individual hunks | :white_check_mark: | :white_check_mark: |
Preview hunks directly in the buffer (inline) | :white_check_mark: * | | * Via `preview_hunk_inline`
Preview hunks directly in the buffer (inline) | :white_check_mark: * | | * Via `preview_hunk_inline` on demand or on hover via `automatic_hunk_inline`
Stage/reset hunks in range/selection | :white_check_mark: | :white_check_mark: :heavy_exclamation_mark: * | * Only stage
Stage/reset all hunks in buffer | :white_check_mark: | |
Undo staged hunks | :white_check_mark: | |
Expand Down
18 changes: 17 additions & 1 deletion doc/gitsigns.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ For basic setup with all batteries included:

Configuration can be passed to the setup function. Here is an example with most
of the default settings:
>
>lua
require('gitsigns').setup {
signs = {
add = { text = '│' },
Expand All @@ -59,6 +59,7 @@ of the default settings:
ignore_whitespace = false,
},
current_line_blame_formatter = '<author>, <author_time:%Y-%m-%d> - <summary>',
automatic_hunk_inline = false, -- `:h gitsigns-config-automatic_hunk_inline`
sign_priority = 6,
update_debounce = 100,
status_formatter = nil, -- Use default
Expand Down Expand Up @@ -334,6 +335,13 @@ select_hunk() *gitsigns.select_hunk()*
preview_hunk_inline() *gitsigns.preview_hunk_inline()*
Preview the hunk at the cursor position inline in the buffer.

automatic_hunk_inline() *gitsigns.automatic_hunk_inline()*
Preview the hunk at the current cursor position inline in the
buffer automatically every time the CursorMoved event is
triggered. This function enables or disables the inline diff
functionality based on whether the cursor is inside or outside
of a hunk.

preview_hunk() *gitsigns.preview_hunk()*
Preview the hunk at the cursor position in a floating
window. If the preview is already open, calling this
Expand Down Expand Up @@ -919,6 +927,14 @@ debug_mode *gitsigns-config-debug_mode*
Enables debug logging and makes the following functions
available: `dump_cache`, `debug_messages`, `clear_debug`.

automatic_hunk_inline *gitsigns-config-automatic_hunk_inline*
Type: `boolean`, Default: `false`

The `automatic_hunk_inline` function enables automatic inline preview of
a hunk's diff when the cursor is inside the hunk. The preview is removed
when the cursor moves outside the hunk. This option ensures that any
newly attached buffer will have this functionality enabled by default,
without the need to manually call `Gitsigns automatic_hunk_inline`.

==============================================================================
HIGHLIGHT GROUPS *gitsigns-highlight-groups*
Expand Down
61 changes: 48 additions & 13 deletions lua/gitsigns/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,13 @@ M.preview_hunk = noautocmd(function()
popup.create(lines_spec, config.preview_config, 'hunk')
end)

local preview_hunk_state = { prev_hunk = nil, floating = nil, keep = false }

local function clear_preview_inline(bufnr)
preview_hunk_state.prev_hunk = nil
if preview_hunk_state.floating then
pcall(api.nvim_win_close, preview_hunk_state.floating, true)
end
api.nvim_buf_clear_namespace(bufnr, ns_inline, 0, -1)
end

Expand All @@ -686,32 +692,34 @@ M.preview_hunk_inline = function()
local hunk = get_cursor_hunk(bufnr)

if not hunk then
clear_preview_inline(bufnr)
return
end

if hunk == preview_hunk_state.prev_hunk then return end

clear_preview_inline(bufnr)
preview_hunk_state.prev_hunk = hunk

local winid ---@type integer
manager.show_added(bufnr, ns_inline, hunk)
if config._inline2 then
if hunk.removed.count > 0 then
winid = manager.show_deleted_in_float(bufnr, ns_inline, hunk)
preview_hunk_state.floating = manager.show_deleted_in_float(bufnr, ns_inline, hunk)
end
else
manager.show_deleted(bufnr, ns_inline, hunk)
end

api.nvim_create_autocmd({ 'CursorMoved', 'InsertEnter' }, {
buffer = bufnr,
desc = 'Clear gitsigns inline preview',
callback = function()
if winid then
pcall(api.nvim_win_close, winid, true)
end
clear_preview_inline(bufnr)
end,
once = true,
})
if not preview_hunk_state.keep then
api.nvim_create_autocmd({ 'CursorMoved', 'InsertEnter' }, {
buffer = bufnr,
desc = 'Clear gitsigns inline preview',
callback = function()
clear_preview_inline(bufnr)
end,
once = true,
})
end

-- Virtual lines will be hidden if cursor is on the top row, so automatically
-- scroll the viewport.
Expand All @@ -722,6 +730,33 @@ M.preview_hunk_inline = function()
end
end


--- Preview the hunk at the current cursor position inline in the buffer automatically
--- every time the CursorMoved event is triggered. This function enables or disables the inline
--- diff functionality based on whether the cursor is inside or outside of a hunk.
M.automatic_hunk_inline = noautocmd(function()
local bufnr = current_buf()
if not cache[bufnr] then return end

local group = api.nvim_create_augroup("gitsigns_automatic_hunk_inline", { clear = false })

-- If the autocmd group already has registered autocmds, clear them and disable the preview
if #api.nvim_get_autocmds({ group = group, buffer = bufnr }) > 0 then
api.nvim_clear_autocmds({ group = group, buffer = bufnr })
clear_preview_inline(bufnr)
preview_hunk_state = {}
else
-- Enable the preview
preview_hunk_state.keep = true
api.nvim_create_autocmd("CursorMoved", {
group = group,
buffer = bufnr,
callback = M.preview_hunk_inline,
desc = "Automatically show inline diff on hover"
})
end
end)

--- Select the hunk under the cursor.
M.select_hunk = function()
local hunk = get_cursor_hunk()
Expand Down
4 changes: 4 additions & 0 deletions lua/gitsigns/attach.lua
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,10 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
if config.keymaps and not vim.tbl_isempty(config.keymaps) then
require('gitsigns.mappings')(config.keymaps, cbuf)
end

if config.automatic_hunk_inline then
require('gitsigns.actions').automatic_hunk_inline()
end
end)

--- Detach Gitsigns from all buffers it is attached to.
Expand Down
13 changes: 13 additions & 0 deletions lua/gitsigns/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ end
--- @field worktrees {toplevel: string, gitdir: string}[]
--- @field word_diff boolean
--- @field keymaps table<string,string>
--- @field automatic_hunk_inline boolean
--- -- Undocumented
--- @field _refresh_staged_on_update boolean
--- @field _blame_cache boolean
Expand Down Expand Up @@ -762,6 +763,18 @@ M.schema = {
]],
},

automatic_hunk_inline = {
type = 'boolean',
default = false,
description = [[
The `automatic_hunk_inline` function enables automatic inline preview of
a hunk's diff when the cursor is inside the hunk. The preview is removed
when the cursor moves outside the hunk. This option ensures that any
newly attached buffer will have this functionality enabled by default,
without the need to manually call `Gitsigns automatic_hunk_inline`.
]],
},

_refresh_staged_on_update = {
type = 'boolean',
default = false,
Expand Down