Subject: Re: bug#25105: M-p in diff-mode jumps too far

From: Tino Calancha <[email-masked]>
Date: Mon, 16 Jan 2017 15:26:00 +0900 (JST)

On Sat, 14 Jan 2017, Tino Calancha wrote:

> Essentially, my patch fix 1. and 2. in the commit message of 2c8a7e5.
> I am going to prepare one draft for the commit message based on Dima's 
> message by Monday or Tuesday: i will drop mentions to the navigation 
> commands.  Then i will show it here so that people in this thread can
> give me comments/corrections to make the message clear for everyone.
OK, below is my draft for the second commit.
Please don't hesitate to send me comments to make it more clear or/and
fix some broken grammar.
;; For the first commit, the revert of 2c8a7e5, i propose to keep the same 
;; as before.  Let me know in case you want to change it as well.  Maybe 
;; you want this commit list all the commits that it reverts?
;; Currently it just mentions 2c8a7e5, but it doesn't say a word about 
;; the 'children commits':
;; e5ef59b8, 6b6abe0d, 73349822, a283d655 and 61c6a10e.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Improve diff-mode manipulation commands

Fix Bug#17544.
The use of `diff-apply-hunk' and `diff-hunk-kill' had several annoying
corner cases that this patch fixes.  These corner cases were largely due
to inconsistent treatment of diff headers.
Consider following diff:

  diff --git a/foo b/bar
  index 44556ddd4a..3fc4713f0f 100644
  --- a/foo
  +++ b/bar
  @@ -52,7 +52,7 @@
  hunk1
  @@ -74,7 +74,7 @@
  hunk2
  diff --git a/baz b/qux
  index a8c3fcca2f..6b316c4073 100644
  --- a/baz
  +++ b/qux
  @@ -608,6 +608,6 @@
  hunk3
  @@ -654,7 +654,7 @@
  hunk4

The lines starting and ending with '@@' are the hunk headers.
The lines starting with '---' and '+++' are the file headers.
In addition, Git diffs add extra lines as those starting with
'diff' and 'index' above.  Let's call these lines Git header.
>From now on, these three headers are referred together as the diff header,
that is,
diff header = 'Git + file + hunk' headers.

Commands `diff-apply-hunk' and `diff-hunk-kill' behaves differently
depending on the point position within a diff header.

1. If point is at hunk1 header, '@@ -52,7 +52,7 @@' above, then
`diff-apply-hunk' moves point to hunk2 header,
i.e., '@@ -74,7 +74,7 @@' line.
If point is at '--- a/foo' line, then `diff-apply-hunk' moves point
to hunk1 header.

2. If point is at hunk3 header or its file header, then
`diff-hunk-kill' deletes hunk3.
If point is at the beginning of its Git header,
i.e., 'diff --git a/baz b/qux' line, then `diff-hunk-kill' deletes hunk2.

After this patch the behaviour of these commands is independent of the
point position in the diff header.  Then, it's possible to apply hunks
in order.  It's also possible to press M-k repeatedly to kill hunks in
the order they appear in the buffer.

* lisp/vc/diff-mode.el (diff-file-junk-re):
Move definition before it's used.
(diff--at-diff-header-p): New predicate.
(diff-beginning-of-hunk): Use it.
(diff-apply-hunk): Jump to beginning of hunk before apply the hunk.
(diff-hunk-kill, diff-file-kill): Jump to beginning of hunk after kill.
(diff-post-command-hook): Call diff-beginning-of-hunk with non-nil argument.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;