X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/18d51459aa08c4eb80d90519c1f127965e413028..e0dcaa3feec553efba8a2e1306b08c6220fddeff:/lisp/whitespace.el diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 459383a17b..a119793c3a 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -1,8 +1,8 @@ -;;; 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, 2005 Free Software Foundation, Inc. -;; Author: Rajesh Vaidheeswarran +;; Author: Rajesh Vaidheeswarran ;; Keywords: convenience ;; This file is part of GNU Emacs. @@ -23,32 +23,70 @@ ;; 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:! 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 +;; !. +;; +;; (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.5" "Version of the whitespace library.") (defvar whitespace-all-buffer-files nil "An associated list of buffers and files checked for whitespace cleanliness. @@ -59,69 +97,157 @@ visited by the buffers.") (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." + "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 'string + :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) (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-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 '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 @@ -153,7 +279,7 @@ Errors*' buffer before opening (or closing) another file." "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': @@ -161,9 +287,10 @@ 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 @@ -174,19 +301,53 @@ 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 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) @@ -196,9 +357,64 @@ To disable timer scans, set this to zero." 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\). @@ -210,95 +426,96 @@ and: 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 (if whitespace-check-leading-whitespace - (whitespace-buffer-leading) - nil)) - (whitespace-trailing (if whitespace-check-trailing-whitespace - (whitespace-buffer-trailing) - nil)) - (whitespace-indent (if whitespace-check-indent-whitespace - (whitespace-buffer-search - whitespace-indent-regexp) - nil)) - (whitespace-spacetab (if whitespace-check-spacetab-whitespace + (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-spacetab-regexp) + whitespace-indent-regexp) nil)) - (whitespace-ateol (if whitespace-check-ateol-whitespace - (whitespace-buffer-search - whitespace-ateol-regexp) - nil)) - (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))) - - ;; Now test and set the whitespaces that are not checked. - (whitespace-display-unchecked-whitespaces - (if whitespace-error - (concat " W:" 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 + (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) + (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 (current-buffer) 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)))))))) + whitespace-error)) ;;;###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 @@ -323,31 +540,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 "") @@ -357,15 +574,14 @@ whitespace problems." (if whitespace-any (whitespace-cleanup) (progn - (message "%s clean" buffer-file-name) - (setq whitespace-mode-line nil) - (whitespace-force-mode-line-update) - (whitespace-display-unchecked-whitespaces))) + (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 @@ -384,7 +600,9 @@ 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 () @@ -420,7 +638,9 @@ whitespace problems." (end-of-line) (setq pmax (point)) (if (equal pmin pmax) - t + (progn + (whitespace-highlight-the-space (- pmin 1) pmax) + t) nil)) nil)))) @@ -454,8 +674,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)))) @@ -477,26 +699,53 @@ whitespace problems." (delete-region (match-beginning 0) (point)) (indent-to column))))) -(defun whitespace-display-unchecked-whitespaces (&optional whitespace-str) - "Update modeline with whitespaces whose testing has been turned off." - (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")))) - (setq whitespace-mode-line whitespace-str) - (if (not (equal whitespace-this-modeline "")) - (setq whitespace-mode-line - (concat whitespace-str " Woff:" whitespace-this-modeline))) - (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 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 + (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. @@ -515,12 +764,9 @@ If timer is not set, then set it to scan the files in `whitespace-rescan-timer-time') for whitespace creep." (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." @@ -528,9 +774,7 @@ If timer is not set, then set it to scan the files in 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)) @@ -560,73 +804,55 @@ If timer is not set, then set it to scan the files in (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. +(defalias 'global-whitespace-mode 'whitespace-global-mode) -Whitespace errors are reported in a buffer, and on the modeline. - -Modeline will show a W: 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. - -If any of the whitespace checks is turned off, the modeline will display a -Woff:, where `x' can be one (or more) of the above. - - (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. +;;;###autoload +(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.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)) + +(add-hook 'whitespace-unload-hook 'whitespace-unload-hook) (provide 'whitespace) +;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c ;;; whitespace.el ends here