tpope / vim-fugitive

fugitive.vim: A Git wrapper so awesome, it should be illegal
https://www.vim.org/scripts/script.php?script_id=2975
20.12k stars 1.01k forks source link

When staging by hunk and a file is fully staged, put cursor on first hunk of next file vs next file name #1926

Closed gibfahn closed 2 years ago

gibfahn commented 2 years ago

Versions

Background

When staging, I'm either staging by file or by hunk. When staging by file, I'm giving each file a quick look then staging the whole thing. When staging by hunk, I'm carefully reading each diff.

When you stage a hunk, fugitive automatically puts the cursor on the hunk marker (@@ -1,9 +1,9 @@) for the next hunk, which is great as it lets you tap s repeatedly to go through the open hunks.

However, when you stage the last hunk in a file, fugitive puts the cursor on the next file marker (e.g. M README.markdown) instead of the first hunk marker in that file. This means you have to constantly be checking

Worked Example

  1. Modify a couple of files by running this shell snipped in this repo:
printf '%s\n%s\n%s\n' firstR "$(cat README.markdown)" lastR >README.markdown 
printf '%s\n%s\n%s\n' firstC "$(cat CONTRIBUTING.markdown)" lastC >CONTRIBUTING.markdown
  1. Open fugitive
Screenshot: image
  1. Go down to Unstaged (2) and hit = to expand the hunks
Screenshot: image
  1. Move down two lines to @@ -1,3 +1,4 @@, and hit s to stage the first hunk
Screenshot: image
  1. The cursor has automatically moved to the next hunk (which is excellent). Hit s again to stage that one too.
Screenshot: image
  1. Note that the cursor is now on M README.markdown, so hitting s a third time would stage all changes in that file, but we just want to stage hunk-wise. Therefore we have to move one line down to stage only the next (firstR) hunk rather than everything in this file.
Screenshot: image
tpope commented 2 years ago

I'm not convinced this should be changed. A possible alternative workflow would be to start with everything closed, press i to cycle through changes (which expands diffs automatically), and press s on the hunks you want to stage.

gibfahn commented 2 years ago

A possible alternative workflow would be to start with everything closed, press i to cycle through changes (which expands diffs automatically), and press s on the hunks you want to stage.

The expanding diffs automatically is nice, but this doesn't really make things any easier. Previously to stage the 4 hunks in the above example (cursor starting in the first hunk) it would be ssjs, and with i it's ssis.

Using i and s isn't so bad when you're just picking out a few diffs to stage out of a bunch of unconnected changes (when you're mostly not staging things). It's much more painful though when you're staging ~everything, and just using this as a point to do some code review on your changes before submitting.

As I mentioned above though, it's not so much the extra keystrokes as having to constantly remember to check whether the cursor is on a file or a hunk, which distracts from the focus on the code itself.

It looks like this mapping works as a workaround:

" Stage, go up a line, then skip to the next hunk.
:nmap S sk]c