]> code.delx.au - gnu-emacs/blobdiff - lisp/whitespace.el
(command-line-1): Refer to "Pure Storage" on
[gnu-emacs] / lisp / whitespace.el
index ca2813985e183b2e4abcc9d8337f4b915153a6da..7f3cbd913ca39c2144fa62186d35683182a383d8 100644 (file)
@@ -1,6 +1,7 @@
-;;; whitespace.el --- Warn about and clean bogus whitespaces in the file.
+;;; whitespace.el --- warn about and clean bogus whitespaces in the file
 
-;; Copyright (C) 1999-2000 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Rajesh Vaidheeswarran <rv@gnu.org>
 ;; Keywords: convenience
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
-
-;; Whitespace.el URL: http://www.dsmit.com/lisp/
-
+;;
+;; URL: http://www.dsmit.com/lisp/
+;;
+;; The whitespace library is intended to find and help fix five different types
+;; of whitespace problems that commonly exist in source code.
+;;
+;; 1. Leading space (empty lines at the top of a file).
+;; 2. Trailing space (empty lines at the end of a file).
+;; 3. Indentation space (8 or more spaces at beginning of line, that should be
+;;                   replaced with TABS).
+;; 4. Spaces followed by a TAB.  (Almost always, we never want that).
+;; 5. Spaces or TABS at the end of a line.
+;;
+;; Whitespace errors are reported in a buffer, and on the modeline.
+;;
+;; Modeline will show a W:<x>!<y> to denote a particular type of whitespace,
+;; where `x' and `y' can be one (or more) of:
+;;
+;; e - End-of-Line whitespace.
+;; i - Indentation whitespace.
+;; l - Leading whitespace.
+;; s - Space followed by Tab.
+;; t - Trailing whitespace.
+;;
+;; If any of the whitespace checks is turned off, the modeline will display a
+;; !<y>.
+;;
+;;     (since (3) is the most controversial one, here is the rationale: Most
+;;     terminal drivers and printer drivers have TAB configured or even
+;;     hardcoded to be 8 spaces.  (Some of them allow configuration, but almost
+;;     always they default to 8.)
+;;
+;;     Changing `tab-width' to other than 8 and editing will cause your code to
+;;     look different from within Emacs, and say, if you cat it or more it, or
+;;     even print it.
+;;
+;;     Almost all the popular programming modes let you define an offset (like
+;;     c-basic-offset or perl-indent-level) to configure the offset, so you
+;;     should never have to set your `tab-width' to be other than 8 in all
+;;     these modes.  In fact, with an indent level of say, 4, 2 TABS will cause
+;;     Emacs to replace your 8 spaces with one \t (try it).  If vi users in
+;;     your office complain, tell them to use vim, which distinguishes between
+;;     tabstop and shiftwidth (vi equivalent of our offsets), and also ask them
+;;     to set smarttab.)
+;;
+;; All the above have caused (and will cause) unwanted codeline integration and
+;; merge problems.
+;;
+;; whitespace.el will complain if it detects whitespaces on opening a file, and
+;; warn you on closing a file also (in case you had inserted any
+;; whitespaces during the process of your editing).
+;;
 ;; Exported functions:
-
+;;
 ;; `whitespace-buffer' - To check the current buffer for whitespace problems.
 ;; `whitespace-cleanup' - To cleanup all whitespaces in the current buffer.
 ;; `whitespace-region' - To check between point and mark for whitespace
 ;;                       problems.
 ;; `whitespace-cleanup-region' - To cleanup all whitespaces between point
 ;;                               and mark in the current buffer.
-;; `whitespace-describe' - A simple introduction to the library.
 
 ;;; Code:
 
-(defvar whitespace-version "2.8" "Version of the whitespace library.")
+(defvar whitespace-version "3.5" "Version of the whitespace library.")
 
 (defvar whitespace-all-buffer-files nil
   "An associated list of buffers and files checked for whitespace cleanliness.
@@ -60,52 +109,99 @@ visited by the buffers.")
 (make-variable-buffer-local 'whitespace-mode-line)
 (put 'whitespace-mode-line 'permanent-local nil)
 
+(defvar whitespace-check-buffer-leading nil
+  "Test leading whitespace for file in current buffer if t.")
+(make-variable-buffer-local 'whitespace-check-buffer-leading)
+(put 'whitespace-check-buffer-leading 'permanent-local nil)
+
+(defvar whitespace-check-buffer-trailing nil
+  "Test trailing whitespace for file in current buffer if t.")
+(make-variable-buffer-local 'whitespace-check-buffer-trailing)
+(put 'whitespace-check-buffer-trailing 'permanent-local nil)
+
+(defvar whitespace-check-buffer-indent nil
+  "Test indentation whitespace for file in current buffer if t.")
+(make-variable-buffer-local 'whitespace-check-buffer-indent)
+(put 'whitespace-check-buffer-indent 'permanent-local nil)
+
+(defvar whitespace-check-buffer-spacetab nil
+  "Test Space-followed-by-TABS whitespace for file in current buffer if t.")
+(make-variable-buffer-local 'whitespace-check-buffer-spacetab)
+(put 'whitespace-check-buffer-spacetab 'permanent-local nil)
+
+(defvar whitespace-check-buffer-ateol nil
+  "Test end-of-line whitespace for file in current buffer if t.")
+(make-variable-buffer-local 'whitespace-check-buffer-ateol)
+(put 'whitespace-check-buffer-ateol 'permanent-local nil)
+
+(defvar whitespace-highlighted-space nil
+  "The variable to store the extent to highlight.")
+(make-variable-buffer-local 'whitespace-highlighted-space)
+(put 'whitespace-highlighted-space 'permanent-local nil)
+
 ;; For flavors of Emacs which don't define `defgroup' and `defcustom'.
 (eval-when-compile
   (if (not (fboundp 'defgroup))
       (defmacro defgroup (sym memb doc &rest args)
-       "Null macro for defgroup in all versions of Emacs that don't define
-defgroup"
+       "Null macro for `defgroup' in all versions of Emacs that don't define it."
        t))
   (if (not (fboundp 'defcustom))
       (defmacro defcustom (sym val doc &rest args)
-       "Macro to alias defcustom to defvar in all versions of Emacs that
-don't define defcustom"
+       "Macro to alias `defcustom' to `defvar' in all versions of Emacs that
+don't define it."
        `(defvar ,sym ,val ,doc))))
 
-(if (featurep 'xemacs)
+(defalias 'whitespace-make-overlay
+  (if (featurep 'xemacs) 'make-extent 'make-overlay))
+(defalias 'whitespace-overlay-put
+  (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
+(defalias 'whitespace-delete-overlay
+  (if (featurep 'xemacs) 'delete-extent 'delete-overlay))
+(defalias 'whitespace-overlay-start
+  (if (featurep 'xemacs) 'extent-start 'overlay-start))
+(defalias 'whitespace-overlay-end
+  (if (featurep 'xemacs) 'extent-end 'overlay-end))
+(defalias 'whitespace-mode-line-update
+  (if (featurep 'xemacs) 'redraw-modeline 'force-mode-line-update))
+
 (defgroup whitespace nil
   "Check for and fix five different types of whitespaces in source code."
+  :version "21.1"
+  :link '(emacs-commentary-link "whitespace.el")
   ;; Since XEmacs doesn't have a 'convenience group, use the next best group
   ;; which is 'editing?
-  :group 'editing)
-(defgroup whitespace nil
-  "Check for and fix five different types of whitespaces in source code."
-  :version "21.1"
-  :group 'convenience))
+  :group (if (featurep 'xemacs) 'editing 'convenience))
 
 (defcustom whitespace-check-leading-whitespace t
-  "Flag to check leading whitespace."
+  "Flag to check leading whitespace.  This is the global for the system.
+It can be overriden by setting a buffer local variable
+`whitespace-check-buffer-leading'."
   :type 'boolean
   :group 'whitespace)
 
 (defcustom whitespace-check-trailing-whitespace t
-  "Flag to check trailing whitespace."
+  "Flag to check trailing whitespace.  This is the global for the system.
+It can be overriden by setting a buffer local variable
+`whitespace-check-buffer-trailing'."
   :type 'boolean
   :group 'whitespace)
 
 (defcustom whitespace-check-spacetab-whitespace t
-  "Flag to check space followed by a TAB."
+  "Flag to check space followed by a TAB.  This is the global for the system.
+It can be overriden by setting a buffer local variable
+`whitespace-check-buffer-spacetab'."
   :type 'boolean
   :group 'whitespace)
 
-(defcustom whitespace-spacetab-regexp " \t"
+(defcustom whitespace-spacetab-regexp "[ ]+\t"
   "Regexp to match a space followed by a TAB."
   :type 'regexp
   :group 'whitespace)
 
-(defcustom whitespace-check-indent-whitespace t
-  "Flag to check indentation whitespace."
+(defcustom whitespace-check-indent-whitespace indent-tabs-mode
+  "Flag to check indentation whitespace.  This is the global for the system.
+It can be overriden by setting a buffer local variable
+`whitespace-check-buffer-indent'."
   :type 'boolean
   :group 'whitespace)
 
@@ -115,11 +211,14 @@ don't define defcustom"
   :group 'whitespace)
 
 (defcustom whitespace-check-ateol-whitespace t
-  "Flag to check end-of-line whitespace."
+  "Flag to check end-of-line whitespace.  This is the global for the system.
+It can be overriden by setting a buffer local variable
+`whitespace-check-buffer-ateol'."
   :type 'boolean
   :group 'whitespace)
 
-(defcustom whitespace-ateol-regexp "[ \t]$"
+;; (defcustom whitespace-ateol-regexp "[ \t]$"
+(defcustom whitespace-ateol-regexp "[ \t]+$"
   "Regexp to match a TAB or a space at the EOL."
   :type 'regexp
   :group 'whitespace)
@@ -129,6 +228,19 @@ don't define defcustom"
   :type 'string
   :group 'whitespace)
 
+(defcustom whitespace-clean-msg "clean."
+  "If non-nil, this message will be displayed after a whitespace check
+determines a file to be clean."
+  :type 'string
+  :group 'whitespace)
+
+(defcustom whitespace-abort-on-error nil
+  "While writing a file, abort if the file is unclean.
+If `whitespace-auto-cleanup' is set, that takes precedence over
+this variable."
+  :type  'boolean
+  :group 'whitespace)
+
 (defcustom whitespace-auto-cleanup nil
   "Cleanup a buffer automatically on finding it whitespace unclean."
   :type  'boolean
@@ -158,7 +270,7 @@ Errors*' buffer before opening (or closing) another file."
                                       tcl-mode tex-mode texinfo-mode
                                       vrml-mode xml-mode)
 
-  "Major Modes in which we turn on whitespace checking.
+  "Major modes in which we turn on whitespace checking.
 
 These are mostly programming and documentation modes.  But you may add other
 modes that you want whitespaces checked in by adding something like the
@@ -187,10 +299,48 @@ To disable timer scans, set this to zero."
   :type 'boolean
   :group 'whitespace)
 
+(defcustom whitespace-display-spaces-in-color t
+  "Display the bogus whitespaces by coloring them with the face
+`whitespace-highlight'."
+  :type 'boolean
+  :group 'whitespace)
+
+(defgroup whitespace-faces nil
+  "Faces used in whitespace."
+  :prefix "whitespace-"
+  :group 'whitespace
+  :group 'faces)
+
+(defface whitespace-highlight '((((class color) (background light))
+                                (:background "green1"))
+                               (((class color) (background dark))
+                                (:background "sea green"))
+                               (((class grayscale mono)
+                                 (background light))
+                                (:background "black"))
+                               (((class grayscale mono)
+                                 (background dark))
+                                (:background "white")))
+  "Face used for highlighting the bogus whitespaces that exist in the buffer."
+  :group 'whitespace-faces)
+;; backward-compatibility alias
+(put 'whitespace-highlight-face 'face-alias 'whitespace-highlight)
+
 (if (not (assoc 'whitespace-mode minor-mode-alist))
     (setq minor-mode-alist (cons '(whitespace-mode whitespace-mode-line)
                                 minor-mode-alist)))
 
+(set-default 'whitespace-check-buffer-leading
+            whitespace-check-leading-whitespace)
+(set-default 'whitespace-check-buffer-trailing
+            whitespace-check-trailing-whitespace)
+(set-default 'whitespace-check-buffer-indent
+            whitespace-check-indent-whitespace)
+(set-default 'whitespace-check-buffer-spacetab
+            whitespace-check-spacetab-whitespace)
+(set-default 'whitespace-check-buffer-ateol
+            whitespace-check-ateol-whitespace)
+
 (defun whitespace-check-whitespace-mode (&optional arg)
   "Test and set the whitespace-mode in qualifying buffers."
   (if (null whitespace-mode)
@@ -199,6 +349,61 @@ To disable timer scans, set this to zero."
                t
              nil))))
 
+;;;###autoload
+(defun whitespace-toggle-leading-check ()
+  "Toggle the check for leading space in the local buffer."
+  (interactive)
+  (let ((current-val whitespace-check-buffer-leading))
+    (setq whitespace-check-buffer-leading (not current-val))
+    (message "Will%s check for leading space in buffer."
+            (if whitespace-check-buffer-leading "" " not"))
+    (if whitespace-check-buffer-leading (whitespace-buffer-leading))))
+
+;;;###autoload
+(defun whitespace-toggle-trailing-check ()
+  "Toggle the check for trailing space in the local buffer."
+  (interactive)
+  (let ((current-val whitespace-check-buffer-trailing))
+    (setq whitespace-check-buffer-trailing (not current-val))
+    (message "Will%s check for trailing space in buffer."
+            (if whitespace-check-buffer-trailing "" " not"))
+    (if whitespace-check-buffer-trailing (whitespace-buffer-trailing))))
+
+;;;###autoload
+(defun whitespace-toggle-indent-check ()
+  "Toggle the check for indentation space in the local buffer."
+  (interactive)
+  (let ((current-val whitespace-check-buffer-indent))
+    (setq whitespace-check-buffer-indent (not current-val))
+    (message "Will%s check for indentation space in buffer."
+            (if whitespace-check-buffer-indent "" " not"))
+    (if whitespace-check-buffer-indent
+       (whitespace-buffer-search whitespace-indent-regexp))))
+
+;;;###autoload
+(defun whitespace-toggle-spacetab-check ()
+  "Toggle the check for space-followed-by-TABs in the local buffer."
+  (interactive)
+  (let ((current-val whitespace-check-buffer-spacetab))
+    (setq whitespace-check-buffer-spacetab (not current-val))
+    (message "Will%s check for space-followed-by-TABs in buffer."
+            (if whitespace-check-buffer-spacetab "" " not"))
+    (if whitespace-check-buffer-spacetab
+       (whitespace-buffer-search whitespace-spacetab-regexp))))
+
+
+;;;###autoload
+(defun whitespace-toggle-ateol-check ()
+  "Toggle the check for end-of-line space in the local buffer."
+  (interactive)
+  (let ((current-val whitespace-check-buffer-ateol))
+    (setq whitespace-check-buffer-ateol (not current-val))
+    (message "Will%s check for end-of-line space in buffer."
+            (if whitespace-check-buffer-ateol "" " not"))
+    (if whitespace-check-buffer-ateol
+       (whitespace-buffer-search whitespace-ateol-regexp))))
+
+
 ;;;###autoload
 (defun whitespace-buffer (&optional quiet)
   "Find five different types of white spaces in buffer.
@@ -220,26 +425,27 @@ and:
        (progn
          (whitespace-check-buffer-list (buffer-name) buffer-file-name)
          (whitespace-tickle-timer)
+         (whitespace-unhighlight-the-space)
          (if whitespace-auto-cleanup
              (if buffer-read-only
                  (if (not quiet)
                      (message "Can't cleanup: %s is read-only" (buffer-name)))
                (whitespace-cleanup))
-           (let ((whitespace-leading (if whitespace-check-leading-whitespace
+           (let ((whitespace-leading (if whitespace-check-buffer-leading
                                          (whitespace-buffer-leading)
                                        nil))
-                 (whitespace-trailing (if whitespace-check-trailing-whitespace
+                 (whitespace-trailing (if whitespace-check-buffer-trailing
                                           (whitespace-buffer-trailing)
                                         nil))
-                 (whitespace-indent (if whitespace-check-indent-whitespace
+                 (whitespace-indent (if whitespace-check-buffer-indent
                                         (whitespace-buffer-search
                                          whitespace-indent-regexp)
                                       nil))
-                 (whitespace-spacetab (if whitespace-check-spacetab-whitespace
+                 (whitespace-spacetab (if whitespace-check-buffer-spacetab
                                           (whitespace-buffer-search
                                            whitespace-spacetab-regexp)
                                         nil))
-                 (whitespace-ateol (if whitespace-check-ateol-whitespace
+                 (whitespace-ateol (if whitespace-check-buffer-ateol
                                        (whitespace-buffer-search
                                         whitespace-ateol-regexp)
                                      nil))
@@ -278,16 +484,14 @@ and:
                                  (if whitespace-spacetab "s")
                                  (if whitespace-trailing "t")))))
              (whitespace-update-modeline whitespace-this-modeline)
-             (save-excursion
-               (get-buffer-create whitespace-errbuf)
-               (kill-buffer whitespace-errbuf)
-               (get-buffer-create whitespace-errbuf)
-               (set-buffer whitespace-errbuf)
+             (if (get-buffer whitespace-errbuf)
+                 (kill-buffer whitespace-errbuf))
+             (with-current-buffer (get-buffer-create whitespace-errbuf)
                (if whitespace-errmsg
                    (progn
                      (insert whitespace-errmsg)
                      (if (not (or quiet whitespace-silent))
-                         (display-buffer whitespace-errbuf t))
+                         (display-buffer (current-buffer) t))
                      (if (not quiet)
                          (message "Whitespaces: [%s%s] in %s"
                                   whitespace-this-modeline
@@ -297,11 +501,10 @@ and:
                                         (concat "!" whitespace-unchecked)
                                       ""))
                                   whitespace-filename)))
-                 (if (not quiet)
-                     (message "%s clean" whitespace-filename))))))))
-    (if whitespace-error
-       t
-      nil)))
+                 (if (and (not quiet) (not (equal whitespace-clean-msg "")))
+                     (message "%s %s" whitespace-filename
+                              whitespace-clean-msg))))))))
+    whitespace-error))
 
 ;;;###autoload
 (defun whitespace-region (s e)
@@ -315,9 +518,7 @@ and:
 ;;;###autoload
 (defun whitespace-cleanup ()
   "Cleanup the five different kinds of whitespace problems.
-
-Use \\[describe-function] whitespace-describe to read a summary of the
-whitespace problems."
+See `whitespace-buffer' docstring for a summary of the problems."
   (interactive)
   ;; If this buffer really contains a file, then run, else quit.
   (whitespace-check-whitespace-mode current-prefix-arg)
@@ -330,31 +531,31 @@ whitespace problems."
        ;; they are displayed.
        (setq tab-width whitespace-tabwith)
 
-       (if (and whitespace-check-leading-whitespace
+       (if (and whitespace-check-buffer-leading
                 (whitespace-buffer-leading))
            (progn
              (whitespace-buffer-leading-cleanup)
              (setq whitespace-any t)))
 
-       (if (and whitespace-check-trailing-whitespace
+       (if (and whitespace-check-buffer-trailing
                 (whitespace-buffer-trailing))
            (progn
              (whitespace-buffer-trailing-cleanup)
              (setq whitespace-any t)))
 
-       (if (and whitespace-check-indent-whitespace
+       (if (and whitespace-check-buffer-indent
                 (whitespace-buffer-search whitespace-indent-regexp))
            (progn
              (whitespace-indent-cleanup)
              (setq whitespace-any t)))
 
-       (if (and whitespace-check-spacetab-whitespace
+       (if (and whitespace-check-buffer-spacetab
                 (whitespace-buffer-search whitespace-spacetab-regexp))
            (progn
              (whitespace-buffer-cleanup whitespace-spacetab-regexp "\t")
              (setq whitespace-any t)))
 
-       (if (and whitespace-check-ateol-whitespace
+       (if (and whitespace-check-buffer-ateol
                 (whitespace-buffer-search whitespace-ateol-regexp))
            (progn
              (whitespace-buffer-cleanup whitespace-ateol-regexp "")
@@ -364,7 +565,8 @@ whitespace problems."
        (if whitespace-any
            (whitespace-cleanup)
          (progn
-           (message "%s clean" buffer-file-name)
+           (if (not whitespace-silent)
+               (message "%s clean" buffer-file-name))
            (whitespace-update-modeline)))
        (setq tab-width whitespace-tabwith-saved))))
 
@@ -389,23 +591,17 @@ whitespace problems."
       (end-of-line)
       (setq pmax (point))
       (if (equal pmin pmax)
-         t
+         (progn
+           (whitespace-highlight-the-space pmin (1+ pmax))
+           t)
        nil))))
 
 (defun whitespace-buffer-leading-cleanup ()
   "Remove any empty lines at the top of the file."
   (save-excursion
-    (let ((pmin nil)
-         (pmax nil))
-      (goto-char (point-min))
-      (beginning-of-line)
-      (setq pmin (point))
-      (end-of-line)
-      (setq pmax (point))
-      (if (equal pmin pmax)
-         (progn
-           (kill-line)
-           (whitespace-buffer-leading-cleanup))))))
+    (goto-char (point-min))
+    (skip-chars-forward "\n")
+    (delete-region (point-min) (point))))
 
 (defun whitespace-buffer-trailing ()
   "Check to see if are is more than one empty line at the bottom."
@@ -425,33 +621,20 @@ whitespace problems."
            (end-of-line)
            (setq pmax (point))
            (if (equal pmin pmax)
-               t
+               (progn
+                 (whitespace-highlight-the-space (- pmin 1) pmax)
+                 t)
              nil))
        nil))))
 
 (defun whitespace-buffer-trailing-cleanup ()
   "Delete all the empty lines at the bottom."
   (save-excursion
-    (let ((pmin nil)
-         (pmax nil))
-      (goto-char (point-max))
-      (beginning-of-line)
-      (setq pmin (point))
-      (end-of-line)
-      (setq pmax (point))
-      (if (equal pmin pmax)
-         (progn
-           (goto-char (1- pmin))
-           (beginning-of-line)
-           (setq pmin (point))
-           (end-of-line)
-           (setq pmax (point))
-           (if (equal pmin pmax)
-               (progn
-                 (goto-char (1- (point-max)))
-                 (beginning-of-line)
-                 (kill-line)
-                 (whitespace-buffer-trailing-cleanup))))))))
+    (goto-char (point-max))
+    (skip-chars-backward "\n")
+    (if (not (bolp))
+       (forward-char 1))
+    (delete-region (point) (point-max))))
 
 (defun whitespace-buffer-search (regexp)
   "Search for any given whitespace REGEXP."
@@ -459,8 +642,10 @@ whitespace problems."
     (save-excursion
       (goto-char (point-min))
       (while (re-search-forward regexp nil t)
-       (setq whitespace-retval (format "%s %s " whitespace-retval
-                                       (match-beginning 0))))
+       (progn
+         (setq whitespace-retval (format "%s %s" whitespace-retval
+                                       (match-beginning 0)))
+       (whitespace-highlight-the-space (match-beginning 0) (match-end 0))))
       (if (equal "" whitespace-retval)
          nil
        whitespace-retval))))
@@ -484,14 +669,14 @@ whitespace problems."
 
 (defun whitespace-unchecked-whitespaces ()
   "Return the list of whitespaces whose testing has been suppressed."
-  (let ((whitespace-this-modeline
-        (concat (if (not whitespace-check-ateol-whitespace) "e")
-                (if (not whitespace-check-indent-whitespace) "i")
-                (if (not whitespace-check-leading-whitespace) "l")
-                (if (not whitespace-check-spacetab-whitespace) "s")
-                (if (not whitespace-check-trailing-whitespace) "t"))))
-    (if (not (equal whitespace-this-modeline ""))
-       whitespace-this-modeline
+  (let ((unchecked-spaces
+        (concat (if (not whitespace-check-buffer-ateol) "e")
+                (if (not whitespace-check-buffer-indent) "i")
+                (if (not whitespace-check-buffer-leading) "l")
+                (if (not whitespace-check-buffer-spacetab) "s")
+                (if (not whitespace-check-buffer-trailing) "t"))))
+    (if (not (equal unchecked-spaces ""))
+       unchecked-spaces
       nil)))
 
 (defun whitespace-update-modeline (&optional whitespace-err)
@@ -512,14 +697,23 @@ Also with whitespaces whose testing has been turned off."
        (setq whitespace-mode-line (if whitespace-mode-line
                                       (concat " W:" whitespace-mode-line)
                                     nil))
-       (whitespace-force-mode-line-update))))
-
-;; Force mode line updation for different Emacs versions
-(defun whitespace-force-mode-line-update ()
-  "Force the mode line update for different flavors of Emacs."
-  (if (fboundp 'redraw-modeline)
-      (redraw-modeline)                        ; XEmacs
-    (force-mode-line-update)))         ; Emacs
+       (whitespace-mode-line-update))))
+
+(defun whitespace-highlight-the-space (b e)
+  "Highlight the current line, unhighlighting a previously jumped to line."
+  (if whitespace-display-spaces-in-color
+      (let ((ol (whitespace-make-overlay b e)))
+       (push ol whitespace-highlighted-space)
+       (whitespace-overlay-put ol 'face 'whitespace-highlight))))
+;;  (add-hook 'pre-command-hook 'whitespace-unhighlight-the-space))
+
+(defun whitespace-unhighlight-the-space()
+  "Unhighlight the currently highlight line."
+  (if (and whitespace-display-spaces-in-color whitespace-highlighted-space)
+      (progn
+       (mapc 'whitespace-delete-overlay whitespace-highlighted-space)
+       (setq whitespace-highlighted-space nil))
+    (remove-hook 'pre-command-hook 'whitespace-unhighlight-the-space)))
 
 (defun whitespace-check-buffer-list (buf-name buf-file)
   "Add a buffer and its file to the whitespace monitor list.
@@ -585,96 +779,48 @@ If timer is not set, then set it to scan the files in
       (setq whitespace-rescan-timer nil))))
 
 ;;;###autoload
-(defcustom whitespace-global-mode nil
-  "Toggle global Whitespace mode.
-
-Setting this variable directly does not take effect;
-use either \\[customize] or the function `whitespace-global-mode'
-\(which see)."
-  :set (lambda (sym val)
-        (whitespace-global-mode (or value 0)))
-  :initialize 'custom-initialize-default
-  :type 'boolean
-  :group 'whitespace
-  :require 'whitespace)
+(defalias 'global-whitespace-mode 'whitespace-global-mode)
 
-(defun whitespace-global-mode (&optional arg)
+;;;###autoload
+(define-minor-mode whitespace-global-mode
   "Toggle using Whitespace mode in new buffers.
-With ARG, turn the mode on if and only iff ARG is positive.
+With ARG, turn the mode on iff ARG is positive.
 
 When this mode is active, `whitespace-buffer' is added to
-`find-file-hooks' and `kill-buffer-hook'."
-  (interactive "P")
-  (setq arg (if arg
-               (> (prefix-numeric-value arg) 0)
-             (not whitespace-global-mode)))
-  (if arg
+`find-file-hook' and `kill-buffer-hook'."
+  :global t
+  :group 'whitespace
+  (if whitespace-global-mode
       (progn
-       (add-hook 'find-file-hooks 'whitespace-buffer)
+       (add-hook 'find-file-hook 'whitespace-buffer)
+       (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
        (add-hook 'kill-buffer-hook 'whitespace-buffer))
-    (remove-hook 'find-file-hooks 'whitespace-buffer)
+    (remove-hook 'find-file-hook 'whitespace-buffer)
+    (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
     (remove-hook 'kill-buffer-hook 'whitespace-buffer)))
 
 ;;;###autoload
-(defun whitespace-describe ()
-  "A summary of whitespaces and what this library can do about them.
-
-The whitespace library is intended to find and help fix five different types
-of whitespace problems that commonly exist in source code.
-
-1. Leading space (empty lines at the top of a file).
-2. Trailing space (empty lines at the end of a file).
-3. Indentation space (8 or more spaces at beginning of line, that should be
-                     replaced with TABS).
-4. Spaces followed by a TAB.  (Almost always, we never want that).
-5. Spaces or TABS at the end of a line.
-
-Whitespace errors are reported in a buffer, and on the modeline.
-
-Modeline will show a W:<x>!<y> to denote a particular type of whitespace,
-where `x' and `y' can be one (or more) of:
-
-e - End-of-Line whitespace.
-i - Indentation whitespace.
-l - Leading whitespace.
-s - Space followed by Tab.
-t - Trailing whitespace.
-
-If any of the whitespace checks is turned off, the modeline will display a
-!<y>.
-
-    (since (3) is the most controversial one, here is the rationale: Most
-    terminal drivers and printer drivers have TAB configured or even
-    hardcoded to be 8 spaces.  (Some of them allow configuration, but almost
-    always they default to 8.)
-
-    Changing `tab-width' to other than 8 and editing will cause your code to
-    look different from within Emacs, and say, if you cat it or more it, or
-    even print it.
-
-    Almost all the popular programming modes let you define an offset (like
-    c-basic-offset or perl-indent-level) to configure the offset, so you
-    should never have to set your `tab-width' to be other than 8 in all these
-    modes.  In fact, with an indent level of say, 4, 2 TABS will cause Emacs
-    to replace your 8 spaces with one \t (try it).  If vi users in your
-    office complain, tell them to use vim, which distinguishes between
-    tabstop and shiftwidth (vi equivalent of our offsets), and also ask them
-    to set smarttab.)
-
-All the above have caused (and will cause) unwanted codeline integration and
-merge problems.
-
-whitespace.el will complain if it detects whitespaces on opening a file, and
-warn you on closing a file also (in case you had inserted any
-whitespaces during the process of your editing)."
+(defun whitespace-write-file-hook ()
+  "Hook function to be called on the buffer when whitespace check is enabled.
+This is meant to be added buffer-locally to `write-file-functions'."
   (interactive)
-  (message "Use C-h f whitespace-describe to read about whitespace.el v%s."
-          whitespace-version))
+  (let ((werr nil))
+    (if whitespace-auto-cleanup
+       (whitespace-cleanup)
+      (setq werr (whitespace-buffer)))
+    (if (and whitespace-abort-on-error werr)
+       (error (concat "Abort write due to whitespaces in "
+                      buffer-file-name))))
+  nil)
 
 (defun whitespace-unload-hook ()
-  (remove-hook 'find-file-hooks 'whitespace-buffer)
+  (remove-hook 'find-file-hook 'whitespace-buffer)
+  (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
   (remove-hook 'kill-buffer-hook 'whitespace-buffer))
 
+(add-hook 'whitespace-unload-hook 'whitespace-unload-hook)
+
 (provide 'whitespace)
 
+;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c
 ;;; whitespace.el ends here