feat(config): add clean_up_buffers option#6
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new clean_up_buffers configuration option that automatically deletes file buffers created by diffview when the view is closed, but only if those buffers weren't already open before diffview opened them. This helps keep the buffer list clean when users don't want diffview-created buffers persisting after closing the view.
Changes:
- Added
clean_up_buffersconfig option (default: false) to enable automatic cleanup of created buffers - Implemented buffer tracking in
File.created_bufsto identify which LOCAL file buffers were created by diffview - Added cleanup logic in both
DiffView:close()andFileHistoryView:close()methods to delete tracked buffers when the view closes
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| lua/diffview/config.lua | Adds the new clean_up_buffers configuration option with default value false |
| lua/diffview/vcs/file.lua | Introduces File.created_bufs tracking table and marks buffers as created when _create_local_buffer() creates a new buffer |
| lua/diffview/scene/views/file_history/file_history_view.lua | Implements buffer cleanup logic in close() method to delete tracked buffers that meet cleanup criteria |
| lua/diffview/scene/views/diff/diff_view.lua | Implements identical buffer cleanup logic in close() method to delete tracked buffers that meet cleanup criteria |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| -- Clean up LOCAL buffers created by diffview that the user didn't have open before. | ||
| if config.get_config().clean_up_buffers then | ||
| for bufnr, _ in pairs(File.created_bufs) do | ||
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | ||
| local dominated = true | ||
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | ||
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | ||
| dominated = false | ||
| break | ||
| end | ||
| end | ||
|
|
||
| if dominated then | ||
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | ||
| end | ||
| end | ||
|
|
||
| File.created_bufs[bufnr] = nil | ||
| end | ||
| end |
There was a problem hiding this comment.
The File.created_bufs tracking table is global and shared across all views. When multiple diffview instances are open simultaneously (in different tabpages), closing one view will clean up and remove tracking entries for buffers that might still be used by other open views. This could lead to incorrect behavior where buffers are either not cleaned up when they should be, or the tracking state becomes inconsistent. Consider making the tracking table per-view or adding logic to check if any buffer is still in use by other views before removing it from the tracking table.
| for bufnr, _ in pairs(File.created_bufs) do | ||
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | ||
| -- Only delete if not displayed in a window outside this tabpage. | ||
| local dominated = true | ||
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | ||
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | ||
| dominated = false | ||
| break | ||
| end | ||
| end | ||
|
|
||
| if dominated then | ||
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | ||
| end | ||
| end | ||
|
|
||
| File.created_bufs[bufnr] = nil | ||
| end |
There was a problem hiding this comment.
The buffer tracking cleanup logic is duplicated between FileHistoryView and DiffView. Consider extracting this into a shared helper method in the File class (e.g., File.cleanup_created_buffers(tabpage)) to improve maintainability and ensure consistent behavior across both view types.
| for bufnr, _ in pairs(File.created_bufs) do | |
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | |
| -- Only delete if not displayed in a window outside this tabpage. | |
| local dominated = true | |
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | |
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | |
| dominated = false | |
| break | |
| end | |
| end | |
| if dominated then | |
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | |
| end | |
| end | |
| File.created_bufs[bufnr] = nil | |
| end | |
| File.cleanup_created_buffers(self.tabpage) |
| File.created_bufs[bufnr] = nil | ||
| end | ||
| end |
There was a problem hiding this comment.
The File.created_bufs tracking table has a potential memory leak when clean_up_buffers is disabled. Buffer entries are added to File.created_bufs but are only removed in the close methods when clean_up_buffers is enabled. This means that if a user has clean_up_buffers disabled, the tracking table will accumulate buffer references indefinitely, even after buffers are deleted through other means. Consider always cleaning up the tracking table entries (setting them to nil) regardless of the clean_up_buffers config setting, or add cleanup in File:destroy() method.
| -- Clean up LOCAL buffers created by diffview that the user didn't have open before. | ||
| if config.get_config().clean_up_buffers then | ||
| for bufnr, _ in pairs(File.created_bufs) do | ||
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | ||
| -- Only delete if not displayed in a window outside this tabpage. | ||
| local dominated = true | ||
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | ||
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | ||
| dominated = false | ||
| break | ||
| end | ||
| end | ||
|
|
||
| if dominated then | ||
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | ||
| end | ||
| end | ||
|
|
||
| File.created_bufs[bufnr] = nil | ||
| end | ||
| end |
There was a problem hiding this comment.
The File.created_bufs tracking table is global and shared across all views. When multiple diffview instances are open simultaneously (in different tabpages), closing one view will clean up and remove tracking entries for buffers that might still be used by other open views. This could lead to incorrect behavior where buffers are either not cleaned up when they should be, or the tracking state becomes inconsistent. Consider making the tracking table per-view or adding logic to check if any buffer is still in use by other views before removing it from the tracking table.
| for bufnr, _ in pairs(File.created_bufs) do | ||
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | ||
| local dominated = true | ||
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | ||
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | ||
| dominated = false | ||
| break | ||
| end | ||
| end | ||
|
|
||
| if dominated then | ||
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | ||
| end | ||
| end | ||
|
|
||
| File.created_bufs[bufnr] = nil |
There was a problem hiding this comment.
The buffer tracking cleanup logic is duplicated between FileHistoryView and DiffView. Consider extracting this into a shared helper method in the File class (e.g., File.cleanup_created_buffers(tabpage)) to improve maintainability and ensure consistent behavior across both view types.
| for bufnr, _ in pairs(File.created_bufs) do | |
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | |
| local dominated = true | |
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | |
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | |
| dominated = false | |
| break | |
| end | |
| end | |
| if dominated then | |
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | |
| end | |
| end | |
| File.created_bufs[bufnr] = nil | |
| if type(File.cleanup_created_buffers) == "function" then | |
| File.cleanup_created_buffers(self.tabpage) | |
| else | |
| for bufnr, _ in pairs(File.created_bufs) do | |
| if api.nvim_buf_is_valid(bufnr) and not vim.bo[bufnr].modified then | |
| local dominated = true | |
| for _, winid in ipairs(utils.win_find_buf(bufnr, 0)) do | |
| if api.nvim_win_get_tabpage(winid) ~= self.tabpage then | |
| dominated = false | |
| break | |
| end | |
| end | |
| if dominated then | |
| pcall(api.nvim_buf_delete, bufnr, { force = false }) | |
| end | |
| end | |
| File.created_bufs[bufnr] = nil | |
| end |
| File.created_bufs[bufnr] = nil | ||
| end | ||
| end |
There was a problem hiding this comment.
The File.created_bufs tracking table has a potential memory leak when clean_up_buffers is disabled. Buffer entries are added to File.created_bufs but are only removed in the close methods when clean_up_buffers is enabled. This means that if a user has clean_up_buffers disabled, the tracking table will accumulate buffer references indefinitely, even after buffers are deleted through other means. Consider always cleaning up the tracking table entries (setting them to nil) regardless of the clean_up_buffers config setting, or add cleanup in File:destroy() method.
No description provided.