Skip to content

Commit 7195f66

Browse files
committed
refactor(gitcommit): improve auto-generation reliability for commit messages
- enhance auto-generation mechanism with multiple event triggers - add stable timing detection for different Git tools - implement debounce and tracking to prevent duplicate generations - support graceful handling of buffer states and Git operations
1 parent 0525804 commit 7195f66

File tree

1 file changed

+102
-30
lines changed

1 file changed

+102
-30
lines changed

lua/codecompanion/_extensions/gitcommit/buffer.lua

Lines changed: 102 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,112 @@ function Buffer.setup(opts)
3232
Buffer._setup_gitcommit_keymap(event.buf)
3333

3434
if config.auto_generate then
35-
-- Auto-generation triggers once when entering gitcommit window
36-
-- Avoids race conditions with plugins like neogit
37-
-- Skip auto-generation during git amend to preserve user intent
38-
vim.api.nvim_create_autocmd("WinEnter", {
35+
-- Auto-generation with stable timing detection for different Git tools
36+
local auto_generate_attempted = false
37+
local pending_timer = nil
38+
39+
local function should_attempt_auto_generate(bufnr)
40+
-- Don't attempt if we already successfully generated for this buffer
41+
if auto_generate_attempted then
42+
return false
43+
end
44+
45+
-- Ensure buffer is valid
46+
if not vim.api.nvim_buf_is_valid(bufnr) then
47+
return false
48+
end
49+
50+
-- Check if buffer already has commit message
51+
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
52+
local has_message = false
53+
for _, line in ipairs(lines) do
54+
if not line:match("^%s*#") and vim.trim(line) ~= "" then
55+
has_message = true
56+
break
57+
end
58+
end
59+
60+
-- Skip if buffer already has content
61+
if has_message then
62+
return false
63+
end
64+
65+
-- Skip auto-generation during git amend operation
66+
local should_skip_amend = config.skip_auto_generate_on_amend and Git.is_amending()
67+
if should_skip_amend then
68+
return false
69+
end
70+
71+
return true
72+
end
73+
74+
local function schedule_auto_generate(bufnr)
75+
-- Cancel any pending timer to avoid multiple generations
76+
if pending_timer then
77+
pending_timer:stop()
78+
pending_timer = nil
79+
end
80+
81+
-- Schedule generation with extended delay for stability
82+
pending_timer = vim.defer_fn(function()
83+
pending_timer = nil
84+
if should_attempt_auto_generate(bufnr) then
85+
auto_generate_attempted = true
86+
Buffer._generate_and_insert_commit_message(bufnr)
87+
end
88+
end, config.auto_generate_delay + 300) -- Extra delay for window stability
89+
end
90+
91+
-- Multiple event triggers to ensure compatibility with different Git tools
92+
local autocmd_opts = {
3993
buffer = event.buf,
40-
once = true,
41-
callback = function(args)
42-
-- Defer execution to ensure other plugins finish UI setup
43-
vim.defer_fn(function()
44-
if not vim.api.nvim_buf_is_valid(args.buf) then
45-
return
46-
end
94+
desc = "Auto-generate GitCommit message",
95+
}
4796

48-
-- Check if buffer already has commit message
49-
local lines = vim.api.nvim_buf_get_lines(args.buf, 0, -1, false)
50-
local has_message = false
51-
for _, line in ipairs(lines) do
52-
if not line:match("^%s*#") and vim.trim(line) ~= "" then
53-
has_message = true
54-
break
55-
end
56-
end
97+
-- Primary trigger: WinEnter (works with most tools)
98+
vim.api.nvim_create_autocmd(
99+
"WinEnter",
100+
vim.tbl_extend("force", autocmd_opts, {
101+
callback = function(args)
102+
schedule_auto_generate(args.buf)
103+
end,
104+
})
105+
)
57106

58-
-- Skip auto-generation if:
59-
-- 1. Buffer already has commit message
60-
-- 2. In git amend operation (user may want to keep existing message)
61-
local should_skip_amend = config.skip_auto_generate_on_amend and Git.is_amending()
62-
if not has_message and not should_skip_amend then
63-
Buffer._generate_and_insert_commit_message(args.buf)
107+
-- Secondary trigger: BufWinEnter (works with Fugitive)
108+
vim.api.nvim_create_autocmd(
109+
"BufWinEnter",
110+
vim.tbl_extend("force", autocmd_opts, {
111+
once = true,
112+
callback = function(args)
113+
schedule_auto_generate(args.buf)
114+
end,
115+
})
116+
)
117+
118+
-- Tertiary trigger: CursorMoved (fallback, with debouncing)
119+
vim.api.nvim_create_autocmd(
120+
"CursorMoved",
121+
vim.tbl_extend("force", autocmd_opts, {
122+
once = true,
123+
callback = function(args)
124+
schedule_auto_generate(args.buf)
125+
end,
126+
})
127+
)
128+
129+
-- Cleanup timer when buffer is deleted or unloaded
130+
vim.api.nvim_create_autocmd(
131+
{ "BufDelete", "BufUnload" },
132+
vim.tbl_extend("force", autocmd_opts, {
133+
callback = function()
134+
if pending_timer then
135+
pending_timer:stop()
136+
pending_timer = nil
64137
end
65-
end, config.auto_generate_delay)
66-
end,
67-
desc = "Auto-generate GitCommit message",
68-
})
138+
end,
139+
})
140+
)
69141
end
70142
end,
71143
desc = "Setup GitCommit AI assistant",

0 commit comments

Comments
 (0)