-
Notifications
You must be signed in to change notification settings - Fork 28
feat: add hunk and file-level staging, explorer actions, and enhanced untracked file support #216
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: main
Are you sure you want to change the base?
feat: add hunk and file-level staging, explorer actions, and enhanced untracked file support #216
Conversation
Display untracked files (status ??) in a single pane without diff highlighting, since there's nothing to compare against. When switching to tracked files, the two-pane layout is automatically restored. - Add update_windows() and is_single_pane_mode() to lifecycle module - Handle untracked file selection in explorer to close original window - Add single-pane recovery logic in view.update() for layout restoration
Instead of closing the original window (which corrupts session state), show an empty scratch buffer with a message in the left pane while displaying the untracked file in the right pane. This keeps the session state consistent and allows switching back to tracked files.
When viewing untracked files: - Shrink left pane to 1 column (effectively hidden) - Auto-skip the hidden pane when navigating with Ctrl+H/L - Restore equal window widths when switching to tracked files
Move the placeholder window restoration code to run synchronously after buffer loading, rather than inside the async render_everything callback. This ensures window widths are restored reliably.
- Use bufadd/bufload/nvim_win_set_buf instead of :edit to reuse buffers - Get old buffers from session before clearing highlights - Update all session state (buffers, paths, revisions, diff_result) after opening untracked file to keep state consistent - This fixes issues when switching between untracked and tracked files
- Create separate scratch buffers for each window in explorer mode so the initial tabnew buffer can be properly deleted - Capture scratch buffer before loading new buffers in view.update - Clean up old scratch buffers (buftype='nofile') in view.update - This fixes empty buffer accumulation and improves restoration when switching between untracked and tracked files
Keep the explorer scratch buffer fix (prevents empty buffer accumulation) but revert the changes to view.update that broke untracked→tracked file switching.
The :edit! command to load virtual files can fail in a 1-column window. Move the placeholder restoration code (window resizing) to run BEFORE buffer loading, so the window is a proper size when loading content.
2d63f70 to
9e0fee7
Compare
|
I'm sorry I was working on this without having pulled the latest changes from the main branch, hope I didn't break anything during rebase |
It did broke during rebase, I'll push a fix soon |
esmuellert
left a comment
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.
Basically, some keymaps seems lke to be existing, and the new implementation is duplicate? If so we might want to remove them first. The hunk level stage support is good and requested by many issues. I will take a look at it
| old_path = parts[2] | ||
| path = parts[3] | ||
| end | ||
| -- For revision comparison, we treat everything as "unstaged" for explorer compatibility |
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.
Can you run make format to format the code before submission?
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.
Will do
| }, | ||
| explorer = { | ||
| select = "<CR>", | ||
| open = "o", -- Alias for select (open file or toggle group) |
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.
I feel if user wants an alias, they can setup their own keymap locally, so it might not be necessary for us to have one?
| explorer = { | ||
| select = "<CR>", | ||
| open = "o", -- Alias for select (open file or toggle group) | ||
| focus_file = "l", -- Jump to modified pane if file is open, otherwise open file |
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.
To confirm the behavior, if a file was not selected, it will select that file first, then focus the modified pane, right?
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.
Using 'l' would open the file if not selected already, and move the cursor straight to the right pane so you can start scrolling and reviewing immediately. In case that you use 'l' and the file was already open, it just takes the cursor to the right pane the same way. When using 'o' it opens the file without moving the cursor from the file explorer, I thought it to be a good default, maybe I should've not call it "alias" in the comment next to it
| refresh = "R", | ||
| toggle_view_mode = "i", -- Toggle between 'list' and 'tree' views | ||
| toggle_view_mode = "i", -- Toggle between 'list' and 'tree' views | ||
| stage_file = "a", -- Stage file under cursor (git add) |
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.
These keymaps for stage/unstage/discard the file under cursor in explorer seem to be already implemented by - and X keymaps, so are they duplicated? If so, we might want to remove them
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.
Yeah maybe, I just found these more intuitive. I still don't know if this previously had a key binding for staging the file, since '-' works for unstaging, I tried using '+' to stage but didn't work
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.
Yes, - not only works for unstaging but also can stage unstaged if you click. It is basically a toggle. So the stage/unstage features seem to be duplicated
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.
Ohh gotcha!
Changes
Untracked file support
Hunk-level staging and unstaging
Sstages the hunk under the cursor to the git index (git apply --cached)Uunstages the hunk under the cursor from the git index (git apply --cached --reverse)Explorer file actions
a/sstages the file under the cursor (git add)uunstages the file under the cursor (git restore --staged)ddiscards file changes or deletes untracked files (with confirmation prompt)oopens the file under the cursor (alias for<CR>)ljumps to the modified (right) pane if the file is already open, otherwise opens itBug fixes
.tsfiles now get proper syntax highlighting)qkeymap not working in single-pane mode for untracked files