-;;; 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 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
-;; Author: Rajesh Vaidheeswarran <rv@dsmit.com>
+;; Author: Rajesh Vaidheeswarran <rv@gnu.org>
;; Keywords: convenience
;; This file is part of GNU Emacs.
;; Boston, MA 02111-1307, 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:
-;; add a hook to find-file-hooks and kill-buffer-hook
-(add-hook 'find-file-hooks 'whitespace-buffer)
-(add-hook 'kill-buffer-hook 'whitespace-buffer)
-
-(defvar whitespace-version "2.3" "Version of the whitespace library.")
-;; Find out what type of Emacs we are running in.
-(defvar whitespace-running-emacs (if (string-match "XEmacs\\|Lucid"
- emacs-version) nil t)
- "If this is Emacs, not XEmacs, this is t.")
-
-(if whitespace-running-emacs (require 'timer))
+(defvar whitespace-version "3.4" "Version of the whitespace library.")
(defvar whitespace-all-buffer-files nil
"An associated list of buffers and files checked for whitespace cleanliness.
(defvar whitespace-rescan-timer nil
"Timer object used to rescan the files in buffers that have been modified.")
-;; For users of Emacs 19.x, defgroup and defcustom are not defined.
+;; Tell Emacs about this new kind of minor mode
+(defvar whitespace-mode nil
+ "Non-nil when Whitespace mode (a minor mode) is enabled.")
+(make-variable-buffer-local 'whitespace-mode)
+(put 'whitespace-mode 'permanent-local nil)
-(eval-when-compile
- (if (< (string-to-int emacs-version) 20)
- (progn
- (defmacro defgroup (sym memb doc &rest args)
- "Null macro for defgroup in all versions of Emacs < 20.x"
- t)
- (defmacro defcustom (sym val doc &rest args)
- "Macro to alias defcustom to defvar in all versions of Emacs < 20.x"
- `(defvar ,sym ,val ,doc)))))
+(defvar whitespace-mode-line nil
+ "String to display in the mode line for Whitespace mode.")
+(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"
+ 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"
+ `(defvar ,sym ,val ,doc))))
+
+(if (fboundp 'make-overlay)
+ (progn
+ (defalias 'whitespace-make-overlay 'make-overlay)
+ (defalias 'whitespace-overlay-put 'overlay-put)
+ (defalias 'whitespace-delete-overlay 'delete-overlay)
+ (defalias 'whitespace-overlay-start 'overlay-start)
+ (defalias 'whitespace-overlay-end 'overlay-end)
+ (defalias 'whitespace-mode-line-update 'force-mode-line-update))
+ (defalias 'whitespace-make-overlay 'make-extent)
+ (defalias 'whitespace-overlay-put 'set-extent-property)
+ (defalias 'whitespace-delete-overlay 'delete-extent)
+ (defalias 'whitespace-overlay-start 'extent-start)
+ (defalias 'whitespace-overlay-end 'extent-end)
+ (defalias 'whitespace-mode-line-update 'redraw-modeline))
+
+(if (featurep 'xemacs)
(defgroup whitespace nil
"Check for and fix five different types of whitespaces in source code."
;; Since XEmacs doesn't have a 'convenience group, use the next best group
;; which is 'editing?
- :group (if whitespace-running-emacs 'convenience 'editing))
+ :link '(emacs-commentary-link "whitespace.el")
+ :group 'editing)
+(defgroup whitespace nil
+ "Check for and fix five different types of whitespaces in source code."
+ :version "21.1"
+ :link '(emacs-commentary-link "whitespace.el")
+ :group 'convenience))
+
+(defcustom whitespace-check-leading-whitespace t
+ "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-spacetab-regexp " \t"
- "Regexp to match a TAB followed by a space."
- :type 'string
+(defcustom whitespace-check-trailing-whitespace t
+ "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. 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"
+ "Regexp to match a space followed by a TAB."
+ :type 'regexp
+ :group '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)
(defcustom whitespace-indent-regexp (concat "^\\(\t*\\) " " ")
"Regexp to match (any TABS followed by) 8/more whitespaces at start of line."
- :type 'string
+ :type 'regexp
:group 'whitespace)
-(defcustom whitespace-ateol-regexp "[ \t]$"
+(defcustom whitespace-check-ateol-whitespace t
+ "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]+$"
"Regexp to match a TAB or a space at the EOL."
- :type 'string
+ :type 'regexp
:group 'whitespace)
(defcustom whitespace-errbuf "*Whitespace Errors*"
- "The buffer where whitespace related messages will be logged."
+ "The name of the buffer where whitespace related messages will be logged."
: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
:group 'whitespace)
(defcustom whitespace-modes '(ada-mode asm-mode autoconf-mode awk-mode
- c-mode c++-mode cc-mode cperl-mode
+ c-mode c++-mode cc-mode
+ change-log-mode cperl-mode
electric-nroff-mode emacs-lisp-mode
f90-mode fortran-mode html-mode
html3-mode java-mode jde-mode
modula-2-mode nroff-mode objc-mode
pascal-mode perl-mode prolog-mode
python-mode scheme-mode sgml-mode
- sh-mode shell-script-mode
- simula-mode tcl-mode tex-mode
- texinfo-mode vrml-mode xml-mode)
+ sh-mode shell-script-mode simula-mode
+ tcl-mode tex-mode texinfo-mode
+ vrml-mode xml-mode)
"Major Modes in which we turn on whitespace checking.
-These are mostly programming and documentation modes. But you may add other
+These are mostly programming and documentation modes. But you may add other
modes that you want whitespaces checked in by adding something like the
following to your `.emacs':
whitespace-modes))\)
Or, alternately, you can use the Emacs `customize' command to set this."
+ :type '(repeat symbol)
:group 'whitespace)
-(defcustom whitespace-rescan-timer-time 60
+(defcustom whitespace-rescan-timer-time 600
"Period in seconds to rescan modified buffers for whitespace creep.
This is the period after which the timer will fire causing
`whitespace-rescan-files-in-buffers' to check for whitespace creep in
-modified buffers."
+modified buffers.
+
+To disable timer scans, set this to zero."
:type 'integer
:group 'whitespace)
-;; Tell Emacs about this new kind of minor mode
-(make-variable-buffer-local 'whitespace-mode)
-(put 'whitespace-mode 'permanent-local nil)
-(set-default 'whitespace-mode nil)
+(defcustom whitespace-display-in-modeline t
+ "Display whitespace errors on the modeline."
+ :type 'boolean
+ :group 'whitespace)
-(make-variable-buffer-local 'whitespace-mode-line)
-(put 'whitespace-mode-line 'permanent-local nil)
-(set-default 'whitespace-mode-line nil)
+(defcustom whitespace-display-spaces-in-color t
+ "Display the bogus whitespaces by coloring them with
+`whitespace-highlight-face'."
+ :type 'boolean
+ :group 'whitespace)
+
+(defgroup whitespace-faces nil
+ "Faces used in whitespace."
+ :prefix "whitespace-"
+ :group 'whitespace
+ :group 'faces)
+
+(defface whitespace-highlight-face '((((class color) (background light))
+ (:background "green"))
+ (((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)
(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)
nil))))
;;;###autoload
-(defun whitespace-buffer (&optional quiet)
- "Find five different types of white spaces in buffer:
+(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.
+These are:
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, that should be replaced with TABS\).
1. the major mode is one of the whitespace-modes, or
2. `whitespace-buffer' was explicitly called with a prefix argument."
(interactive)
- (whitespace-check-whitespace-mode current-prefix-arg)
- (if (and buffer-file-name (> (buffer-size) 0) whitespace-mode)
- (progn
- (whitespace-check-buffer-list (buffer-name) buffer-file-name)
- (whitespace-tickle-timer)
- (if whitespace-auto-cleanup
- (if (and (not quiet) buffer-read-only)
- (message "Can't Cleanup: %s is read-only." (buffer-name))
- (whitespace-cleanup))
- (let ((whitespace-leading (whitespace-buffer-leading))
- (whitespace-trailing (whitespace-buffer-trailing))
- (whitespace-indent (whitespace-buffer-search
- whitespace-indent-regexp))
- (whitespace-spacetab (whitespace-buffer-search
- whitespace-spacetab-regexp))
- (whitespace-ateol (whitespace-buffer-search
- whitespace-ateol-regexp))
- (whitespace-errmsg nil)
- (whitespace-error nil)
- (whitespace-filename buffer-file-name)
- (whitespace-this-modeline ""))
-
- ;; Now let's complain if we found any of the above.
- (setq whitespace-error (or whitespace-leading whitespace-indent
- whitespace-spacetab whitespace-ateol
- whitespace-trailing))
-
- (if whitespace-error
- (progn
- (setq whitespace-errmsg
- (concat whitespace-filename " contains:\n"
- (if whitespace-leading "Leading whitespace\n")
- (if whitespace-indent
- (concat "Indentation whitespace"
- whitespace-indent "\n"))
- (if whitespace-spacetab
- (concat "Space followed by Tab"
- whitespace-spacetab "\n"))
- (if whitespace-ateol
- (concat "End-of-line whitespace"
- whitespace-ateol "\n"))
- (if whitespace-trailing
- "Trailing whitespace.\n")
- "\ntype "
- "`whitespace-cleanup' to cleanup the file."))
- (setq whitespace-this-modeline
- (concat (if whitespace-ateol "e")
- (if whitespace-indent "i")
- (if whitespace-leading "l")
- (if whitespace-spacetab "s")
- (if whitespace-trailing "t")))
- (setq whitespace-mode-line
- (concat " W:" whitespace-this-modeline))
- (whitespace-force-mode-line-update)))
- (save-excursion
- (get-buffer-create whitespace-errbuf)
- (kill-buffer whitespace-errbuf)
- (get-buffer-create whitespace-errbuf)
- (set-buffer whitespace-errbuf)
- (if whitespace-errmsg
+ (let ((whitespace-error nil))
+ (whitespace-check-whitespace-mode current-prefix-arg)
+ (if (and buffer-file-name (> (buffer-size) 0) whitespace-mode)
+ (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-buffer-leading
+ (whitespace-buffer-leading)
+ nil))
+ (whitespace-trailing (if whitespace-check-buffer-trailing
+ (whitespace-buffer-trailing)
+ nil))
+ (whitespace-indent (if whitespace-check-buffer-indent
+ (whitespace-buffer-search
+ whitespace-indent-regexp)
+ nil))
+ (whitespace-spacetab (if whitespace-check-buffer-spacetab
+ (whitespace-buffer-search
+ whitespace-spacetab-regexp)
+ nil))
+ (whitespace-ateol (if whitespace-check-buffer-ateol
+ (whitespace-buffer-search
+ whitespace-ateol-regexp)
+ nil))
+ (whitespace-errmsg nil)
+ (whitespace-filename buffer-file-name)
+ (whitespace-this-modeline ""))
+
+ ;; Now let's complain if we found any of the above.
+ (setq whitespace-error (or whitespace-leading whitespace-indent
+ whitespace-spacetab whitespace-ateol
+ whitespace-trailing))
+
+ (if whitespace-error
(progn
- (insert whitespace-errmsg)
- (if (not (or quiet whitespace-silent))
- (display-buffer whitespace-errbuf t))
- (if (not quiet)
- (message "Whitespaces: [%s] in %s"
- whitespace-this-modeline
- whitespace-filename)))
- (if (not quiet)
- (message "%s clean" whitespace-filename)))))))))
+ (setq whitespace-errmsg
+ (concat whitespace-filename " contains:\n"
+ (if whitespace-leading
+ "Leading whitespace\n")
+ (if whitespace-indent
+ (concat "Indentation whitespace"
+ whitespace-indent "\n"))
+ (if whitespace-spacetab
+ (concat "Space followed by Tab"
+ whitespace-spacetab "\n"))
+ (if whitespace-ateol
+ (concat "End-of-line whitespace"
+ whitespace-ateol "\n"))
+ (if whitespace-trailing
+ "Trailing whitespace\n")
+ "\ntype `M-x whitespace-cleanup' to "
+ "cleanup the file."))
+ (setq whitespace-this-modeline
+ (concat (if whitespace-ateol "e")
+ (if whitespace-indent "i")
+ (if whitespace-leading "l")
+ (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 whitespace-errmsg
+ (progn
+ (insert whitespace-errmsg)
+ (if (not (or quiet whitespace-silent))
+ (display-buffer whitespace-errbuf t))
+ (if (not quiet)
+ (message "Whitespaces: [%s%s] in %s"
+ whitespace-this-modeline
+ (let ((whitespace-unchecked
+ (whitespace-unchecked-whitespaces)))
+ (if whitespace-unchecked
+ (concat "!" whitespace-unchecked)
+ ""))
+ whitespace-filename)))
+ (if (and (not quiet) (not (equal whitespace-clean-msg "")))
+ (message "%s %s" whitespace-filename
+ whitespace-clean-msg))))))))
+ (if whitespace-error
+ t
+ nil)))
;;;###autoload
(defun whitespace-region (s e)
- "Check a region specified by point and mark for whitespace errors."
+ "Check the region for whitespace errors."
(interactive "r")
(save-excursion
(save-restriction
;; they are displayed.
(setq tab-width whitespace-tabwith)
- (if (whitespace-buffer-leading)
+ (if (and whitespace-check-buffer-leading
+ (whitespace-buffer-leading))
(progn
(whitespace-buffer-leading-cleanup)
(setq whitespace-any t)))
- (if (whitespace-buffer-trailing)
+ (if (and whitespace-check-buffer-trailing
+ (whitespace-buffer-trailing))
(progn
(whitespace-buffer-trailing-cleanup)
(setq whitespace-any t)))
- (if (whitespace-buffer-search whitespace-indent-regexp)
+ (if (and whitespace-check-buffer-indent
+ (whitespace-buffer-search whitespace-indent-regexp))
(progn
(whitespace-indent-cleanup)
(setq whitespace-any t)))
- (if (whitespace-buffer-search whitespace-spacetab-regexp)
+ (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 (whitespace-buffer-search whitespace-ateol-regexp)
+ (if (and whitespace-check-buffer-ateol
+ (whitespace-buffer-search whitespace-ateol-regexp))
(progn
(whitespace-buffer-cleanup whitespace-ateol-regexp "")
(setq whitespace-any t)))
;; Call this recursively till everything is taken care of
- (if whitespace-any (whitespace-cleanup)
+ (if whitespace-any
+ (whitespace-cleanup)
(progn
- (message "%s clean" buffer-file-name)
- (setq whitespace-mode-line nil)
- (whitespace-force-mode-line-update)))
+ (if (not whitespace-silent)
+ (message "%s clean" buffer-file-name))
+ (whitespace-update-modeline)))
(setq tab-width whitespace-tabwith-saved))))
;;;###autoload
(defun whitespace-cleanup-region (s e)
- "Whitespace cleanup on a region specified by point and mark."
+ "Whitespace cleanup on the region."
(interactive "r")
(save-excursion
(save-restriction
(end-of-line)
(setq pmax (point))
(if (equal pmin pmax)
- t
+ (progn
+ (whitespace-highlight-the-space pmin pmax)
+ t)
nil))))
(defun whitespace-buffer-leading-cleanup ()
(end-of-line)
(setq pmax (point))
(if (equal pmin pmax)
- t
+ (progn
+ (whitespace-highlight-the-space pmin pmax)
+ t)
nil))
nil))))
(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))))
(delete-region (match-beginning 0) (point))
(indent-to column)))))
-;; 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 whitespace-running-emacs
- (force-mode-line-update) ; Emacs
- (redraw-modeline))) ; XEmacs
+(defun whitespace-unchecked-whitespaces ()
+ "Return the list of whitespaces whose testing has been suppressed."
+ (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)
+ "Update modeline with whitespace errors.
+Also with whitespaces whose testing has been turned off."
+ (if whitespace-display-in-modeline
+ (progn
+ (setq whitespace-mode-line nil)
+ ;; Whitespace errors
+ (if (and whitespace-err (not (equal whitespace-err "")))
+ (setq whitespace-mode-line whitespace-err))
+ ;; Whitespace suppressed errors
+ (let ((whitespace-unchecked (whitespace-unchecked-whitespaces)))
+ (if whitespace-unchecked
+ (setq whitespace-mode-line
+ (concat whitespace-mode-line "!" whitespace-unchecked))))
+ ;; Add the whitespace modeline prefix
+ (setq whitespace-mode-line (if whitespace-mode-line
+ (concat " W:" whitespace-mode-line)
+ nil))
+ (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
+ (progn
+ (whitespace-unhighlight-the-space)
+ (add-to-list 'whitespace-highlighted-space
+ (whitespace-make-overlay b e))
+ (whitespace-overlay-put (whitespace-make-overlay b e) 'face
+ 'whitespace-highlight-face))))
+;; (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)
+ (let ((whitespace-this-space nil))
+ (while whitespace-highlighted-space
+ (setq whitespace-this-space (car whitespace-highlighted-space))
+ (setq whitespace-highlighted-space
+ (cdr whitespace-highlighted-space))
+ (whitespace-delete-overlay whitespace-this-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.
If timer is not set, then set it to scan the files in
`whitespace-all-buffer-files' periodically (defined by
`whitespace-rescan-timer-time') for whitespace creep."
- (if (not whitespace-rescan-timer)
+ (if (and whitespace-rescan-timer-time (not whitespace-rescan-timer))
(setq whitespace-rescan-timer
- (if whitespace-running-emacs
- (run-at-time nil whitespace-rescan-timer-time
- 'whitespace-rescan-files-in-buffers)
- (add-timeout whitespace-rescan-timer-time
- 'whitespace-rescan-files-in-buffers nil
- whitespace-rescan-timer-time)))))
+ (add-timeout whitespace-rescan-timer-time
+ 'whitespace-rescan-files-in-buffers nil
+ whitespace-rescan-timer-time))))
(defun whitespace-rescan-files-in-buffers (&optional arg)
"Check monitored files for whitespace creep since last scan."
buffile bufname thiselt buf)
(if (not whitespace-all-my-files)
(progn
- (if whitespace-running-emacs
- (cancel-timer whitespace-rescan-timer)
- (disable-timeout whitespace-rescan-timer))
+ (disable-timeout whitespace-rescan-timer)
(setq whitespace-rescan-timer nil))
(while whitespace-all-my-files
(setq thiselt (car whitespace-all-my-files))
(defun whitespace-refresh-rescan-list (buffile bufname)
"Refresh the list of files to be rescaned for whitespace creep."
(if whitespace-all-buffer-files
- (progn
- (setq whitespace-all-buffer-files
- (delete (list buffile bufname) whitespace-all-buffer-files)))
- (progn
- (if (and whitespace-running-emacs (timerp whitespace-rescan-timer))
- (cancel-timer whitespace-rescan-timer))
- (if (and (not whitespace-running-emacs) whitespace-rescan-timer)
- (disable-timeout whitespace-rescan-timer))
- (if whitespace-rescan-timer
- (setq whitespace-rescan-timer nil)))))
+ (setq whitespace-all-buffer-files
+ (delete (list buffile bufname) whitespace-all-buffer-files))
+ (when whitespace-rescan-timer
+ (disable-timeout whitespace-rescan-timer)
+ (setq whitespace-rescan-timer nil))))
;;;###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.
+(define-minor-mode whitespace-global-mode
+ "Toggle using Whitespace mode in new buffers.
+With ARG, turn the mode on iff ARG is positive.
+
+When this mode is active, `whitespace-buffer' is added to
+`find-file-hook' and `kill-buffer-hook'."
+ :global t
+ :group 'whitespace
+ (if whitespace-global-mode
+ (progn
+ (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-hook 'whitespace-buffer)
+ (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
+ (remove-hook 'kill-buffer-hook 'whitespace-buffer)))
-Whitespace errors are reported in a buffer, and on the modeline.
-
-Modeline will show a W:<x> to denote a particular type of whitespace, where
-`x' 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.
-
- (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. (if in case you had inserted any
-whitespaces during the process of your editing.)"
+;;;###autoload
+(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-hook 'whitespace-buffer)
+ (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
+ (remove-hook 'kill-buffer-hook 'whitespace-buffer))
(provide 'whitespace)
+;;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c
;;; whitespace.el ends here