-
-
Notifications
You must be signed in to change notification settings - Fork 344
Keep current file selected after staging #1760
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
base: master
Are you sure you want to change the base?
Changes from 4 commits
4a57913
094a432
4ccbb92
7ade26e
0e85360
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,6 @@ local dv_utils = require("diffview.utils") | |
|
|
||
| local Watcher = require("neogit.watcher") | ||
| local git = require("neogit.lib.git") | ||
| local a = require("plenary.async") | ||
|
|
||
| local function get_local_diff_view(section_name, item_name, opts) | ||
| local left = Rev(RevType.STAGE) | ||
|
|
@@ -18,23 +17,33 @@ local function get_local_diff_view(section_name, item_name, opts) | |
| section_name = "working" | ||
| end | ||
|
|
||
| local function update_files() | ||
| local function update_files(current_file_path) | ||
| local files = {} | ||
|
|
||
| git.repo:dispatch_refresh { | ||
| source = "diffview_update", | ||
| callback = function() end, | ||
| } | ||
|
|
||
| local repo_state = git.repo.state | ||
| if not repo_state then | ||
| return files | ||
| end | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about this - the git repo should always have state at this point. How would you get here with an uninitialized repository?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was just defensive programming and isn't actually needed in this context. I've removed it. |
||
|
|
||
| local sections = { | ||
| conflicting = { | ||
| items = vim.tbl_filter(function(item) | ||
| return item.mode and item.mode:sub(2, 2) == "U" | ||
| end, git.repo.state.untracked.items), | ||
| end, repo_state.untracked and repo_state.untracked.items or {}), | ||
| }, | ||
| working = git.repo.state.unstaged, | ||
| staged = git.repo.state.staged, | ||
| working = repo_state.unstaged or { items = {} }, | ||
| staged = repo_state.staged or { items = {} }, | ||
| } | ||
|
|
||
| for kind, section in pairs(sections) do | ||
| files[kind] = {} | ||
|
|
||
| for idx, item in ipairs(section.items) do | ||
| for idx, item in ipairs(section.items or {}) do | ||
| local file = { | ||
| path = item.name, | ||
| status = item.mode and item.mode:sub(1, 1), | ||
|
|
@@ -44,7 +53,9 @@ local function get_local_diff_view(section_name, item_name, opts) | |
| } or nil, | ||
| left_null = vim.tbl_contains({ "A", "?" }, item.mode), | ||
| right_null = false, | ||
| selected = (item_name and item.name == item_name) or (not item_name and idx == 1), | ||
| selected = (current_file_path and item.name == current_file_path) | ||
| or (item_name and item.name == item_name) | ||
| or (not item_name and not current_file_path and idx == 1), | ||
| } | ||
|
|
||
| -- restrict diff to only a particular section | ||
|
|
@@ -84,11 +95,11 @@ local function get_local_diff_view(section_name, item_name, opts) | |
| end, | ||
| } | ||
|
|
||
| view:on_files_staged(a.void(function(_) | ||
| Watcher.instance():dispatch_refresh() | ||
| view:update_files() | ||
| end)) | ||
|
|
||
| view:on_files_staged(function() | ||
| vim.schedule(function() | ||
| Watcher.instance():dispatch_refresh() | ||
| end) | ||
| end) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain why this needs to be scheduled, instead of non-blocking async? Not sure I follow.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I originally added vim.schedule because I was concerned about a potential race condition and thought I needed to manually defer the async refresh until after diffview's synchronous operations were complete. However, I realized that dispatch_refresh already uses plenary.a.void internally. |
||
| dv_lib.add_view(view) | ||
|
|
||
| return view | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks like this argument will always be nil? I don't see any callers passing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, that argument is never a file path as its name implied. My initial implementation incorrectly assumed I needed to manage the selected state during refreshes. I later realized diffview actually passes its view object to the update callback, and the old code was only working due to a subtle side-effect: the truthy view object prevented my fallback logic from running, which implicitly preserved the selection.
I've made a new commit which aligns correctly with the diffview API. The selected flag is now set only on the initial file list passed to the constructor. The update_files function acts as a pure data provider for refreshes, which properly leaves the selection management to diffview itself.