Subject: bug#13837: 24.2; Make it possible to turn whitespace-mode only when there are no existing problems

From: Stefan Monnier <[email-masked]>
Date: Sun, 26 Jan 2014 20:52:50 -0500

> Thanks for that information, I can try to remember to tag bugs in future
> when I provide a patch.

I could be convinced to install it if it's "obviously safe".
The patch as sent is a large chunk of "new" code plus a large chunk of
"removed" code, so it's not very appealing.  Diffing while ignoring
whitespace indicates it's more of a "refactoring", and by introducing an
"artificial" new function while helps keep the text lines in the
original order (and hence helps reduce the size of the diff), I get the
patch below.

But it's not obviously safe to me.  Two non-obvious parts are:
- the removal of "(add-to-list 'whitespace-style (car option))".
- the change from has-bogus to bogus-list, where bogus-list will
  (initially) only be nil if whitespace-report-list is nil.
Another problem is that the docstring of whitespace-test-region does not
accurately describe its return value.
So it's probably best to keep it for after 24.4, but let's try to
deal with it as soon as the trunk reopens (real soon now).

        Stefan

=== modified file 'lisp/whitespace.el'
--- lisp/whitespace.el	2014-01-06 06:25:30 +0000
+++ lisp/whitespace.el	2014-01-27 01:35:49 +0000
@@ -1779,7 +1779,20 @@
 If REPORT-IF-BOGUS is non-nil, it reports only when there are any
 whitespace problems in buffer.
 
-Report if some of the following whitespace problems exist:
+For a description of whitespace problems, see
+`whitespace-test-region'."
+  (interactive "r")
+  (setq force (or current-prefix-arg force))
+  (whitespace--report-region start end force report-if-bogus))
+
+;;;###autoload
+(defun whitespace-test-region (start end)
+  "Find whether there are whitespace problems in a region.
+
+Return a list of whitespace problems (hence, nil if there is no
+whitespace problem).
+
+A whitespace problem is one of the following:
 
 * If `indent-tabs-mode' is non-nil:
    empty		1. empty lines at beginning of buffer.
@@ -1800,18 +1813,13 @@
 See `whitespace-style' for documentation.
 See also `whitespace-cleanup' and `whitespace-cleanup-region' for
 cleaning up these problems."
-  (interactive "r")
-  (setq force (or current-prefix-arg force))
   (save-excursion
     (save-match-data                ;FIXME: Why?
-      (let* ((has-bogus nil)
-	     (rstart    (min start end))
+      (let* ((rstart    (min start end))
 	     (rend      (max start end))
 	     (bogus-list
 	      (mapcar
 	       #'(lambda (option)
-		   (when force
-		     (add-to-list 'whitespace-style (car option)))
 		   (goto-char rstart)
 		   (let ((regexp
 			  (cond
@@ -1830,9 +1838,14 @@
 			   (t
 			    (cdr option)))))
 		     (and (re-search-forward regexp rend t)
-			  (setq has-bogus t))))
+                          t)))
 	       whitespace-report-list)))
-	(when (if report-if-bogus has-bogus t)
+        bogus-list))))
+
+(defun whitespace--report-region (start end &optional force report-if-bogus)
+  (save-excursion
+    (let ((bogus-list (whitespace-test-region start end)))
+      (when (if report-if-bogus bogus-list t)
 	  (whitespace-kill-buffer whitespace-report-buffer-name)
 	  ;; `whitespace-indent-tabs-mode' is local to current buffer
 	  ;; `whitespace-tab-width' is local to current buffer
@@ -1855,14 +1868,14 @@
 	      (forward-line 1)
 	      (whitespace-insert-value ws-indent-tabs-mode)
 	      (whitespace-insert-value ws-tab-width)
-	      (when has-bogus
+            (when bogus-list
 		(goto-char (point-max))
 		(insert " Type `M-x whitespace-cleanup'"
 			" to cleanup the buffer.\n\n"
 			" Type `M-x whitespace-cleanup-region'"
 			" to cleanup a region.\n\n"))
 	      (whitespace-display-window (current-buffer)))))
-	has-bogus))))
+      (null bogus-list))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;