byplayer/egg — pull request #32 by 7max (2012-04-02 17:49:07+00:00)
Title: Persistenk hunk state fixes

Hi, I had finally packaged and debugged my Egg fixes, and would like you to consider merging it.

Use cases that were fixed/changed.

1. Always correctly calculate hunk line number. For example, if you have a file with 100 line file with 3 changes, A B and C, with change 1 changing line 20, change 2 adding 500 lines at line 50, and change C adding 1 line in the end of the file.

Then currently if you stage change A and C, but do not stage change B, when you go to the change C and press Enter, Egg goes to the wrong line number (off by around 500 lines)..

With my fix, Egg will always go to the exactly correct line number, no matter how staged / unstaged hunks of the same file are arranged.

2. Preserving the visibility state of sections, diffs and hunks. Currently when you stage or unstage hunks, or files, even if at the original place children were folded, its always expanded in the new place.

This leads to confusion when staging and unstaging a large number of changes.

Point also moves quite un-predictably and after staging a diff, your point may suddenly be in the middle of a diff from a different staged section, rather then some know place.

With my fixes, the visibility status of sections, files, and hunks is preserved when status and commit buffers are refreshed.

This is accomplished by calculating a "single-hunk-range" for each hunk, which is the hunk range (L1 S1 L2 S2) numbers from hunk header, with only that single hunk staged.. Unlike hunk headers calculated by GIT, this header is stable, and numbers will remain the same, no matter which other hunks are staged/unstaged, or any new hunks appearing due to more changes done to the working file.

This allows the above "single-hunk-range" to be used as a key, to remember hunk visibility and and children folding status.

3. Reserving point in a common sense manner.

When hunks or files are staged or unstaged, the point is preserved using same semantics as killing current line in the text editor, but without crossing section boundaries.

For example when given the following changes, with point represented by *

Unstaged

*Change A
Change B
Change C

Staged.

When user stages change A, point will move to Change B, and if that is staged it will move to Change C. When the last change in the section is gone, point will move to previous change, or section header.