Subject: bug#25157: 26.0.50; whitespace-cleanup does not remove single trailing empty line anymore

From: Reuben Thomas <[email-masked]>
Date: Wed, 21 Dec 2016 00:51:04 +0000

I attach a patch for consideration, along the lines I previously proposed.
It seems to work: at least, it deletes a single trailing extra newline,
while still leaving a newline at the end of the buffer, and doesn't delete
a single newline at the end of the buffer.
From fb396e7a732f377747b013f7e589133acb12258f Mon Sep 17 00:00:00 2001
From: Reuben Thomas <[email-masked]>
Date: Wed, 21 Dec 2016 00:40:11 +0000
Subject: [PATCH 7/7] Fix whitespace-cleanup to remove single trailing newline
 (Bug#25157)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lisp/whitespace.el (whitespace-empty-at-eob-regexp): Simplify and
correct the regexp, which I broke when trying to fix Bug#24745.
(whitespace-cleanup): Remove a FIXME: the reason for save-match-data
is the call of re-search-forward.  Detect if we delete at least one
newline at the end of the buffer, and if so, add one back. This is
necessary because there’s no way to construct the the eob-regexp so
that it always leaves a single newline at the end of the buffer if at
least one newline was present after the last non-whitespace character.
---
 lisp/whitespace.el | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 29d60c9..009511f 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -729,7 +729,7 @@ whitespace-empty-at-bob-regexp
   :group 'whitespace)

-(defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]*\\(\n\\{2,\\}\\|[ \t]+\\)\\)\\'"
+(defcustom whitespace-empty-at-eob-regexp "\\([ \t]+\\|\\([ \t\n]*\n[ \t\n]+\\)\\)\\'"
   "Specify regexp for empty lines at end of buffer.
 
 Used when `whitespace-style' includes `empty'."
@@ -1398,7 +1398,7 @@ whitespace-cleanup
    ;; whole buffer
    (t
     (save-excursion
-      (save-match-data                ;FIXME: Why?
+      (save-match-data
 	;; PROBLEM 1: empty lines at bob
 	;; PROBLEM 2: empty lines at eob
 	;; ACTION: remove all empty lines at bob and/or eob
@@ -1408,7 +1408,10 @@ whitespace-cleanup
 	    (when (looking-at whitespace-empty-at-bob-regexp)
 	      (delete-region (match-beginning 1) (match-end 1)))
 	    (when (re-search-forward
-                   whitespace-empty-at-eob-regexp nil t)
+		   whitespace-empty-at-eob-regexp nil t)
+	      ;; If we deleted a trailing newline, reinsert it
+	      (if (string-match-p "\n" (match-string 0))
+		  (insert ?\n))
 	      (delete-region (match-beginning 1) (match-end 1)))))))
     ;; PROBLEM 3: `tab-width' or more SPACEs at bol
     ;; PROBLEM 4: SPACEs before TAB
-- 
2.7.4