(python-font-lock-keywords): Add `self' and other quasi-keywords.
[bpt/emacs.git] / lisp / whitespace.el
CommitLineData
e8af40ee 1;;; whitespace.el --- warn about and clean bogus whitespaces in the file
acc975b1 2
0d30b337 3;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
aaef169d 4;; 2005, 2006 Free Software Foundation, Inc.
acc975b1 5
7f565d87 6;; Author: Rajesh Vaidheeswarran <rv@gnu.org>
acc975b1
DL
7;; Keywords: convenience
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
acc975b1
DL
25
26;;; Commentary:
37a23b5d
RV
27;;
28;; URL: http://www.dsmit.com/lisp/
29;;
07089c84
SM
30;; The whitespace library is intended to find and help fix five different types
31;; of whitespace problems that commonly exist in source code.
37a23b5d 32;;
07089c84
SM
33;; 1. Leading space (empty lines at the top of a file).
34;; 2. Trailing space (empty lines at the end of a file).
35;; 3. Indentation space (8 or more spaces at beginning of line, that should be
c98ddbe5 36;; replaced with TABS).
07089c84
SM
37;; 4. Spaces followed by a TAB. (Almost always, we never want that).
38;; 5. Spaces or TABS at the end of a line.
37a23b5d 39;;
07089c84 40;; Whitespace errors are reported in a buffer, and on the modeline.
37a23b5d 41;;
07089c84
SM
42;; Modeline will show a W:<x>!<y> to denote a particular type of whitespace,
43;; where `x' and `y' can be one (or more) of:
37a23b5d 44;;
07089c84
SM
45;; e - End-of-Line whitespace.
46;; i - Indentation whitespace.
47;; l - Leading whitespace.
48;; s - Space followed by Tab.
49;; t - Trailing whitespace.
37a23b5d 50;;
07089c84
SM
51;; If any of the whitespace checks is turned off, the modeline will display a
52;; !<y>.
37a23b5d 53;;
07089c84
SM
54;; (since (3) is the most controversial one, here is the rationale: Most
55;; terminal drivers and printer drivers have TAB configured or even
56;; hardcoded to be 8 spaces. (Some of them allow configuration, but almost
57;; always they default to 8.)
37a23b5d 58;;
07089c84
SM
59;; Changing `tab-width' to other than 8 and editing will cause your code to
60;; look different from within Emacs, and say, if you cat it or more it, or
61;; even print it.
37a23b5d 62;;
07089c84
SM
63;; Almost all the popular programming modes let you define an offset (like
64;; c-basic-offset or perl-indent-level) to configure the offset, so you
65;; should never have to set your `tab-width' to be other than 8 in all
66;; these modes. In fact, with an indent level of say, 4, 2 TABS will cause
67;; Emacs to replace your 8 spaces with one \t (try it). If vi users in
68;; your office complain, tell them to use vim, which distinguishes between
69;; tabstop and shiftwidth (vi equivalent of our offsets), and also ask them
70;; to set smarttab.)
37a23b5d 71;;
07089c84
SM
72;; All the above have caused (and will cause) unwanted codeline integration and
73;; merge problems.
37a23b5d 74;;
07089c84
SM
75;; whitespace.el will complain if it detects whitespaces on opening a file, and
76;; warn you on closing a file also (in case you had inserted any
77;; whitespaces during the process of your editing).
37a23b5d 78;;
acc975b1 79;; Exported functions:
37a23b5d 80;;
acc975b1
DL
81;; `whitespace-buffer' - To check the current buffer for whitespace problems.
82;; `whitespace-cleanup' - To cleanup all whitespaces in the current buffer.
24b72a45
RS
83;; `whitespace-region' - To check between point and mark for whitespace
84;; problems.
85;; `whitespace-cleanup-region' - To cleanup all whitespaces between point
86;; and mark in the current buffer.
acc975b1
DL
87
88;;; Code:
89
7a15a271 90(defvar whitespace-version "3.5" "Version of the whitespace library.")
acc975b1 91
24b72a45
RS
92(defvar whitespace-all-buffer-files nil
93 "An associated list of buffers and files checked for whitespace cleanliness.
acc975b1 94
24b72a45
RS
95This is to enable periodic checking of whitespace cleanliness in the files
96visited by the buffers.")
acc975b1 97
24b72a45
RS
98(defvar whitespace-rescan-timer nil
99 "Timer object used to rescan the files in buffers that have been modified.")
acc975b1 100
dd24f431
GM
101;; Tell Emacs about this new kind of minor mode
102(defvar whitespace-mode nil
103 "Non-nil when Whitespace mode (a minor mode) is enabled.")
104(make-variable-buffer-local 'whitespace-mode)
105(put 'whitespace-mode 'permanent-local nil)
106
107(defvar whitespace-mode-line nil
108 "String to display in the mode line for Whitespace mode.")
109(make-variable-buffer-local 'whitespace-mode-line)
110(put 'whitespace-mode-line 'permanent-local nil)
111
a3db02ad 112(defvar whitespace-check-buffer-leading nil
7f34d6d4 113 "Test leading whitespace for file in current buffer if t.")
a3db02ad
RV
114(make-variable-buffer-local 'whitespace-check-buffer-leading)
115(put 'whitespace-check-buffer-leading 'permanent-local nil)
116
117(defvar whitespace-check-buffer-trailing nil
7f34d6d4 118 "Test trailing whitespace for file in current buffer if t.")
a3db02ad
RV
119(make-variable-buffer-local 'whitespace-check-buffer-trailing)
120(put 'whitespace-check-buffer-trailing 'permanent-local nil)
121
122(defvar whitespace-check-buffer-indent nil
7f34d6d4 123 "Test indentation whitespace for file in current buffer if t.")
a3db02ad
RV
124(make-variable-buffer-local 'whitespace-check-buffer-indent)
125(put 'whitespace-check-buffer-indent 'permanent-local nil)
126
127(defvar whitespace-check-buffer-spacetab nil
7f34d6d4 128 "Test Space-followed-by-TABS whitespace for file in current buffer if t.")
a3db02ad
RV
129(make-variable-buffer-local 'whitespace-check-buffer-spacetab)
130(put 'whitespace-check-buffer-spacetab 'permanent-local nil)
131
132(defvar whitespace-check-buffer-ateol nil
7f34d6d4 133 "Test end-of-line whitespace for file in current buffer if t.")
a3db02ad
RV
134(make-variable-buffer-local 'whitespace-check-buffer-ateol)
135(put 'whitespace-check-buffer-ateol 'permanent-local nil)
136
5dc2e846 137(defvar whitespace-highlighted-space nil
7f34d6d4 138 "The variable to store the extent to highlight.")
5dc2e846
RV
139(make-variable-buffer-local 'whitespace-highlighted-space)
140(put 'whitespace-highlighted-space 'permanent-local nil)
141
07dc4175 142;; For flavors of Emacs which don't define `defgroup' and `defcustom'.
24b72a45 143(eval-when-compile
07dc4175
GM
144 (if (not (fboundp 'defgroup))
145 (defmacro defgroup (sym memb doc &rest args)
7f34d6d4 146 "Null macro for `defgroup' in all versions of Emacs that don't define it."
07dc4175
GM
147 t))
148 (if (not (fboundp 'defcustom))
149 (defmacro defcustom (sym val doc &rest args)
7f34d6d4
JB
150 "Macro to alias `defcustom' to `defvar' in all versions of Emacs that
151don't define it."
07dc4175 152 `(defvar ,sym ,val ,doc))))
acc975b1 153
9d8f0a3c
RS
154(defalias 'whitespace-make-overlay
155 (if (featurep 'xemacs) 'make-extent 'make-overlay))
156(defalias 'whitespace-overlay-put
157 (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
158(defalias 'whitespace-delete-overlay
159 (if (featurep 'xemacs) 'delete-extent 'delete-overlay))
160(defalias 'whitespace-overlay-start
161 (if (featurep 'xemacs) 'extent-start 'overlay-start))
162(defalias 'whitespace-overlay-end
163 (if (featurep 'xemacs) 'extent-end 'overlay-end))
164(defalias 'whitespace-mode-line-update
165 (if (featurep 'xemacs) 'redraw-modeline 'force-mode-line-update))
166
fc333790
DL
167(defgroup whitespace nil
168 "Check for and fix five different types of whitespaces in source code."
169 :version "21.1"
37a23b5d 170 :link '(emacs-commentary-link "whitespace.el")
9d8f0a3c
RS
171 ;; Since XEmacs doesn't have a 'convenience group, use the next best group
172 ;; which is 'editing?
173 :group (if (featurep 'xemacs) 'editing 'convenience))
acc975b1 174
18d51459 175(defcustom whitespace-check-leading-whitespace t
7f34d6d4 176 "Flag to check leading whitespace. This is the global for the system.
a3db02ad 177It can be overriden by setting a buffer local variable
7f34d6d4 178`whitespace-check-buffer-leading'."
18d51459
RS
179 :type 'boolean
180 :group 'whitespace)
181
182(defcustom whitespace-check-trailing-whitespace t
7f34d6d4 183 "Flag to check trailing whitespace. This is the global for the system.
a3db02ad 184It can be overriden by setting a buffer local variable
7f34d6d4 185`whitespace-check-buffer-trailing'."
18d51459
RS
186 :type 'boolean
187 :group 'whitespace)
188
189(defcustom whitespace-check-spacetab-whitespace t
7f34d6d4 190 "Flag to check space followed by a TAB. This is the global for the system.
a3db02ad 191It can be overriden by setting a buffer local variable
7f34d6d4 192`whitespace-check-buffer-spacetab'."
18d51459
RS
193 :type 'boolean
194 :group 'whitespace)
195
5dc2e846 196(defcustom whitespace-spacetab-regexp "[ ]+\t"
18d51459 197 "Regexp to match a space followed by a TAB."
fc333790 198 :type 'regexp
24b72a45 199 :group 'whitespace)
acc975b1 200
1f8437c4 201(defcustom whitespace-check-indent-whitespace indent-tabs-mode
7f34d6d4 202 "Flag to check indentation whitespace. This is the global for the system.
a3db02ad 203It can be overriden by setting a buffer local variable
7f34d6d4 204`whitespace-check-buffer-indent'."
18d51459
RS
205 :type 'boolean
206 :group 'whitespace)
207
24b72a45
RS
208(defcustom whitespace-indent-regexp (concat "^\\(\t*\\) " " ")
209 "Regexp to match (any TABS followed by) 8/more whitespaces at start of line."
fc333790 210 :type 'regexp
24b72a45
RS
211 :group 'whitespace)
212
18d51459 213(defcustom whitespace-check-ateol-whitespace t
7f34d6d4 214 "Flag to check end-of-line whitespace. This is the global for the system.
a3db02ad 215It can be overriden by setting a buffer local variable
7f34d6d4 216`whitespace-check-buffer-ateol'."
18d51459
RS
217 :type 'boolean
218 :group 'whitespace)
219
5dc2e846
RV
220;; (defcustom whitespace-ateol-regexp "[ \t]$"
221(defcustom whitespace-ateol-regexp "[ \t]+$"
24b72a45 222 "Regexp to match a TAB or a space at the EOL."
fc333790 223 :type 'regexp
24b72a45
RS
224 :group 'whitespace)
225
226(defcustom whitespace-errbuf "*Whitespace Errors*"
fc333790 227 "The name of the buffer where whitespace related messages will be logged."
24b72a45
RS
228 :type 'string
229 :group 'whitespace)
230
c98ddbe5
RV
231(defcustom whitespace-clean-msg "clean."
232 "If non-nil, this message will be displayed after a whitespace check
233determines a file to be clean."
234 :type 'string
235 :group 'whitespace)
236
1f8437c4 237(defcustom whitespace-abort-on-error nil
7f34d6d4
JB
238 "While writing a file, abort if the file is unclean.
239If `whitespace-auto-cleanup' is set, that takes precedence over
240this variable."
1f8437c4
RV
241 :type 'boolean
242 :group 'whitespace)
243
24b72a45
RS
244(defcustom whitespace-auto-cleanup nil
245 "Cleanup a buffer automatically on finding it whitespace unclean."
acc975b1
DL
246 :type 'boolean
247 :group 'whitespace)
248
249(defcustom whitespace-silent nil
24b72a45 250 "All whitespace errors will be shown only in the modeline when t.
acc975b1
DL
251
252Note that setting this may cause all whitespaces introduced in a file to go
253unnoticed when the buffer is killed, unless the user visits the `*Whitespace
24b72a45 254Errors*' buffer before opening (or closing) another file."
acc975b1
DL
255 :type 'boolean
256 :group 'whitespace)
257
258(defcustom whitespace-modes '(ada-mode asm-mode autoconf-mode awk-mode
18d51459
RS
259 c-mode c++-mode cc-mode
260 change-log-mode cperl-mode
acc975b1
DL
261 electric-nroff-mode emacs-lisp-mode
262 f90-mode fortran-mode html-mode
263 html3-mode java-mode jde-mode
264 ksh-mode latex-mode LaTeX-mode
265 lisp-mode m4-mode makefile-mode
266 modula-2-mode nroff-mode objc-mode
267 pascal-mode perl-mode prolog-mode
268 python-mode scheme-mode sgml-mode
18d51459
RS
269 sh-mode shell-script-mode simula-mode
270 tcl-mode tex-mode texinfo-mode
271 vrml-mode xml-mode)
acc975b1 272
7f34d6d4 273 "Major modes in which we turn on whitespace checking.
acc975b1 274
fc333790 275These are mostly programming and documentation modes. But you may add other
24b72a45
RS
276modes that you want whitespaces checked in by adding something like the
277following to your `.emacs':
acc975b1 278
24b72a45
RS
279\(setq whitespace-modes (cons 'my-mode (cons 'my-other-mode
280 whitespace-modes))\)
acc975b1 281
24b72a45 282Or, alternately, you can use the Emacs `customize' command to set this."
fc333790 283 :type '(repeat symbol)
24b72a45 284 :group 'whitespace)
acc975b1 285
7f565d87 286(defcustom whitespace-rescan-timer-time 600
24b72a45
RS
287 "Period in seconds to rescan modified buffers for whitespace creep.
288
289This is the period after which the timer will fire causing
290`whitespace-rescan-files-in-buffers' to check for whitespace creep in
18d51459
RS
291modified buffers.
292
293To disable timer scans, set this to zero."
acc975b1
DL
294 :type 'integer
295 :group 'whitespace)
296
dd24f431
GM
297(defcustom whitespace-display-in-modeline t
298 "Display whitespace errors on the modeline."
299 :type 'boolean
300 :group 'whitespace)
acc975b1 301
5dc2e846 302(defcustom whitespace-display-spaces-in-color t
ee01ad0e
MB
303 "Display the bogus whitespaces by coloring them with the face
304`whitespace-highlight'."
5dc2e846
RV
305 :type 'boolean
306 :group 'whitespace)
307
308(defgroup whitespace-faces nil
309 "Faces used in whitespace."
310 :prefix "whitespace-"
311 :group 'whitespace
312 :group 'faces)
313
ee01ad0e
MB
314(defface whitespace-highlight '((((class color) (background light))
315 (:background "green1"))
316 (((class color) (background dark))
317 (:background "sea green"))
318 (((class grayscale mono)
319 (background light))
320 (:background "black"))
321 (((class grayscale mono)
322 (background dark))
323 (:background "white")))
5dc2e846
RV
324 "Face used for highlighting the bogus whitespaces that exist in the buffer."
325 :group 'whitespace-faces)
ee01ad0e
MB
326;; backward-compatibility alias
327(put 'whitespace-highlight-face 'face-alias 'whitespace-highlight)
5dc2e846 328
acc975b1
DL
329(if (not (assoc 'whitespace-mode minor-mode-alist))
330 (setq minor-mode-alist (cons '(whitespace-mode whitespace-mode-line)
331 minor-mode-alist)))
332
a3db02ad
RV
333(set-default 'whitespace-check-buffer-leading
334 whitespace-check-leading-whitespace)
335(set-default 'whitespace-check-buffer-trailing
336 whitespace-check-trailing-whitespace)
337(set-default 'whitespace-check-buffer-indent
338 whitespace-check-indent-whitespace)
339(set-default 'whitespace-check-buffer-spacetab
340 whitespace-check-spacetab-whitespace)
341(set-default 'whitespace-check-buffer-ateol
342 whitespace-check-ateol-whitespace)
343
acc975b1 344(defun whitespace-check-whitespace-mode (&optional arg)
24b72a45 345 "Test and set the whitespace-mode in qualifying buffers."
acc975b1
DL
346 (if (null whitespace-mode)
347 (setq whitespace-mode
348 (if (or arg (member major-mode whitespace-modes))
349 t
350 nil))))
351
a3db02ad
RV
352;;;###autoload
353(defun whitespace-toggle-leading-check ()
354 "Toggle the check for leading space in the local buffer."
355 (interactive)
356 (let ((current-val whitespace-check-buffer-leading))
357 (setq whitespace-check-buffer-leading (not current-val))
358 (message "Will%s check for leading space in buffer."
359 (if whitespace-check-buffer-leading "" " not"))
360 (if whitespace-check-buffer-leading (whitespace-buffer-leading))))
361
362;;;###autoload
363(defun whitespace-toggle-trailing-check ()
364 "Toggle the check for trailing space in the local buffer."
365 (interactive)
366 (let ((current-val whitespace-check-buffer-trailing))
367 (setq whitespace-check-buffer-trailing (not current-val))
368 (message "Will%s check for trailing space in buffer."
369 (if whitespace-check-buffer-trailing "" " not"))
370 (if whitespace-check-buffer-trailing (whitespace-buffer-trailing))))
371
372;;;###autoload
373(defun whitespace-toggle-indent-check ()
374 "Toggle the check for indentation space in the local buffer."
375 (interactive)
376 (let ((current-val whitespace-check-buffer-indent))
377 (setq whitespace-check-buffer-indent (not current-val))
378 (message "Will%s check for indentation space in buffer."
379 (if whitespace-check-buffer-indent "" " not"))
380 (if whitespace-check-buffer-indent
381 (whitespace-buffer-search whitespace-indent-regexp))))
382
383;;;###autoload
384(defun whitespace-toggle-spacetab-check ()
385 "Toggle the check for space-followed-by-TABs in the local buffer."
386 (interactive)
387 (let ((current-val whitespace-check-buffer-spacetab))
388 (setq whitespace-check-buffer-spacetab (not current-val))
389 (message "Will%s check for space-followed-by-TABs in buffer."
390 (if whitespace-check-buffer-spacetab "" " not"))
391 (if whitespace-check-buffer-spacetab
392 (whitespace-buffer-search whitespace-spacetab-regexp))))
393
394
395;;;###autoload
396(defun whitespace-toggle-ateol-check ()
397 "Toggle the check for end-of-line space in the local buffer."
398 (interactive)
399 (let ((current-val whitespace-check-buffer-ateol))
400 (setq whitespace-check-buffer-ateol (not current-val))
401 (message "Will%s check for end-of-line space in buffer."
402 (if whitespace-check-buffer-ateol "" " not"))
403 (if whitespace-check-buffer-ateol
404 (whitespace-buffer-search whitespace-ateol-regexp))))
405
406
24b72a45 407;;;###autoload
acc975b1 408(defun whitespace-buffer (&optional quiet)
fc333790
DL
409 "Find five different types of white spaces in buffer.
410These are:
acc975b1
DL
4111. Leading space \(empty lines at the top of a file\).
4122. Trailing space \(empty lines at the end of a file\).
4133. Indentation space \(8 or more spaces, that should be replaced with TABS\).
4144. Spaces followed by a TAB. \(Almost always, we never want that\).
4155. Spaces or TABS at the end of a line.
416
417Check for whitespace only if this buffer really contains a non-empty file
418and:
4191. the major mode is one of the whitespace-modes, or
24b72a45 4202. `whitespace-buffer' was explicitly called with a prefix argument."
acc975b1 421 (interactive)
dd24f431
GM
422 (let ((whitespace-error nil))
423 (whitespace-check-whitespace-mode current-prefix-arg)
424 (if (and buffer-file-name (> (buffer-size) 0) whitespace-mode)
425 (progn
426 (whitespace-check-buffer-list (buffer-name) buffer-file-name)
427 (whitespace-tickle-timer)
5dc2e846 428 (whitespace-unhighlight-the-space)
dd24f431
GM
429 (if whitespace-auto-cleanup
430 (if buffer-read-only
431 (if (not quiet)
432 (message "Can't cleanup: %s is read-only" (buffer-name)))
f473c8d5 433 (whitespace-cleanup-internal))
a3db02ad 434 (let ((whitespace-leading (if whitespace-check-buffer-leading
dd24f431
GM
435 (whitespace-buffer-leading)
436 nil))
a3db02ad 437 (whitespace-trailing (if whitespace-check-buffer-trailing
dd24f431
GM
438 (whitespace-buffer-trailing)
439 nil))
a3db02ad 440 (whitespace-indent (if whitespace-check-buffer-indent
18d51459 441 (whitespace-buffer-search
dd24f431 442 whitespace-indent-regexp)
18d51459 443 nil))
a3db02ad 444 (whitespace-spacetab (if whitespace-check-buffer-spacetab
dd24f431
GM
445 (whitespace-buffer-search
446 whitespace-spacetab-regexp)
447 nil))
a3db02ad 448 (whitespace-ateol (if whitespace-check-buffer-ateol
dd24f431
GM
449 (whitespace-buffer-search
450 whitespace-ateol-regexp)
451 nil))
452 (whitespace-errmsg nil)
453 (whitespace-filename buffer-file-name)
454 (whitespace-this-modeline ""))
455
456 ;; Now let's complain if we found any of the above.
457 (setq whitespace-error (or whitespace-leading whitespace-indent
458 whitespace-spacetab whitespace-ateol
459 whitespace-trailing))
460
461 (if whitespace-error
acc975b1 462 (progn
dd24f431
GM
463 (setq whitespace-errmsg
464 (concat whitespace-filename " contains:\n"
465 (if whitespace-leading
466 "Leading whitespace\n")
467 (if whitespace-indent
468 (concat "Indentation whitespace"
469 whitespace-indent "\n"))
470 (if whitespace-spacetab
471 (concat "Space followed by Tab"
472 whitespace-spacetab "\n"))
473 (if whitespace-ateol
474 (concat "End-of-line whitespace"
475 whitespace-ateol "\n"))
476 (if whitespace-trailing
477 "Trailing whitespace\n")
478 "\ntype `M-x whitespace-cleanup' to "
479 "cleanup the file."))
480 (setq whitespace-this-modeline
481 (concat (if whitespace-ateol "e")
482 (if whitespace-indent "i")
483 (if whitespace-leading "l")
484 (if whitespace-spacetab "s")
485 (if whitespace-trailing "t")))))
486 (whitespace-update-modeline whitespace-this-modeline)
c22c3db0
SM
487 (if (get-buffer whitespace-errbuf)
488 (kill-buffer whitespace-errbuf))
489 (with-current-buffer (get-buffer-create whitespace-errbuf)
dd24f431
GM
490 (if whitespace-errmsg
491 (progn
492 (insert whitespace-errmsg)
493 (if (not (or quiet whitespace-silent))
c22c3db0 494 (display-buffer (current-buffer) t))
dd24f431
GM
495 (if (not quiet)
496 (message "Whitespaces: [%s%s] in %s"
497 whitespace-this-modeline
498 (let ((whitespace-unchecked
499 (whitespace-unchecked-whitespaces)))
500 (if whitespace-unchecked
501 (concat "!" whitespace-unchecked)
502 ""))
503 whitespace-filename)))
c98ddbe5
RV
504 (if (and (not quiet) (not (equal whitespace-clean-msg "")))
505 (message "%s %s" whitespace-filename
506 whitespace-clean-msg))))))))
c22c3db0 507 whitespace-error))
acc975b1 508
24b72a45 509;;;###autoload
acc975b1 510(defun whitespace-region (s e)
fc333790 511 "Check the region for whitespace errors."
acc975b1
DL
512 (interactive "r")
513 (save-excursion
514 (save-restriction
515 (narrow-to-region s e)
516 (whitespace-buffer))))
517
24b72a45 518;;;###autoload
acc975b1 519(defun whitespace-cleanup ()
24b72a45 520 "Cleanup the five different kinds of whitespace problems.
0d92660c
RS
521It normally applies to the whole buffer, but in Transient Mark mode
522when the mark is active it applies to the region.
04f0adee 523See `whitespace-buffer' docstring for a summary of the problems."
acc975b1 524 (interactive)
f473c8d5
RV
525 (if (and transient-mark-mode mark-active)
526 (whitespace-cleanup-region (region-beginning) (region-end))
527 (whitespace-cleanup-internal)))
528
6e6f0cb6 529(defun whitespace-cleanup-internal (&optional region-only)
acc975b1
DL
530 ;; If this buffer really contains a file, then run, else quit.
531 (whitespace-check-whitespace-mode current-prefix-arg)
532 (if (and buffer-file-name whitespace-mode)
533 (let ((whitespace-any nil)
534 (whitespace-tabwith 8)
535 (whitespace-tabwith-saved tab-width))
536
537 ;; since all printable TABS should be 8, irrespective of how
538 ;; they are displayed.
539 (setq tab-width whitespace-tabwith)
540
a3db02ad 541 (if (and whitespace-check-buffer-leading
18d51459 542 (whitespace-buffer-leading))
acc975b1
DL
543 (progn
544 (whitespace-buffer-leading-cleanup)
545 (setq whitespace-any t)))
546
a3db02ad 547 (if (and whitespace-check-buffer-trailing
18d51459 548 (whitespace-buffer-trailing))
acc975b1
DL
549 (progn
550 (whitespace-buffer-trailing-cleanup)
551 (setq whitespace-any t)))
552
a3db02ad 553 (if (and whitespace-check-buffer-indent
18d51459 554 (whitespace-buffer-search whitespace-indent-regexp))
acc975b1
DL
555 (progn
556 (whitespace-indent-cleanup)
557 (setq whitespace-any t)))
558
a3db02ad 559 (if (and whitespace-check-buffer-spacetab
18d51459 560 (whitespace-buffer-search whitespace-spacetab-regexp))
acc975b1
DL
561 (progn
562 (whitespace-buffer-cleanup whitespace-spacetab-regexp "\t")
563 (setq whitespace-any t)))
564
a3db02ad 565 (if (and whitespace-check-buffer-ateol
18d51459 566 (whitespace-buffer-search whitespace-ateol-regexp))
acc975b1
DL
567 (progn
568 (whitespace-buffer-cleanup whitespace-ateol-regexp "")
569 (setq whitespace-any t)))
570
571 ;; Call this recursively till everything is taken care of
18d51459 572 (if whitespace-any
f473c8d5 573 (whitespace-cleanup-internal)
6e6f0cb6 574 ;; if we are done, talk to the user
acc975b1 575 (progn
6e6f0cb6
EZ
576 (unless whitespace-silent
577 (if region-only
578 (message "The region is now clean")
579 (message "%s is now clean" buffer-file-name)))
dd24f431 580 (whitespace-update-modeline)))
acc975b1
DL
581 (setq tab-width whitespace-tabwith-saved))))
582
24b72a45 583;;;###autoload
acc975b1 584(defun whitespace-cleanup-region (s e)
fc333790 585 "Whitespace cleanup on the region."
acc975b1
DL
586 (interactive "r")
587 (save-excursion
588 (save-restriction
589 (narrow-to-region s e)
6e6f0cb6 590 (whitespace-cleanup-internal t))
acc975b1
DL
591 (whitespace-buffer t)))
592
593(defun whitespace-buffer-leading ()
594 "Check to see if there are any empty lines at the top of the file."
595 (save-excursion
596 (let ((pmin nil)
597 (pmax nil))
598 (goto-char (point-min))
599 (beginning-of-line)
600 (setq pmin (point))
601 (end-of-line)
602 (setq pmax (point))
df5e8d2c 603 (if (equal pmin pmax)
5dc2e846 604 (progn
df5e8d2c 605 (whitespace-highlight-the-space pmin (1+ pmax))
5dc2e846 606 t)
acc975b1
DL
607 nil))))
608
609(defun whitespace-buffer-leading-cleanup ()
24b72a45 610 "Remove any empty lines at the top of the file."
acc975b1 611 (save-excursion
185d43ee
RS
612 (goto-char (point-min))
613 (skip-chars-forward "\n")
614 (delete-region (point-min) (point))))
acc975b1
DL
615
616(defun whitespace-buffer-trailing ()
617 "Check to see if are is more than one empty line at the bottom."
618 (save-excursion
619 (let ((pmin nil)
620 (pmax nil))
621 (goto-char (point-max))
622 (beginning-of-line)
623 (setq pmin (point))
624 (end-of-line)
625 (setq pmax (point))
626 (if (equal pmin pmax)
627 (progn
628 (goto-char (- (point) 1))
629 (beginning-of-line)
630 (setq pmin (point))
631 (end-of-line)
632 (setq pmax (point))
df5e8d2c 633 (if (equal pmin pmax)
5dc2e846 634 (progn
df5e8d2c 635 (whitespace-highlight-the-space (- pmin 1) pmax)
5dc2e846 636 t)
acc975b1
DL
637 nil))
638 nil))))
639
640(defun whitespace-buffer-trailing-cleanup ()
641 "Delete all the empty lines at the bottom."
642 (save-excursion
185d43ee
RS
643 (goto-char (point-max))
644 (skip-chars-backward "\n")
645 (if (not (bolp))
646 (forward-char 1))
647 (delete-region (point) (point-max))))
acc975b1
DL
648
649(defun whitespace-buffer-search (regexp)
650 "Search for any given whitespace REGEXP."
651 (let ((whitespace-retval ""))
652 (save-excursion
653 (goto-char (point-min))
654 (while (re-search-forward regexp nil t)
5dc2e846
RV
655 (progn
656 (setq whitespace-retval (format "%s %s" whitespace-retval
657 (match-beginning 0)))
658 (whitespace-highlight-the-space (match-beginning 0) (match-end 0))))
acc975b1
DL
659 (if (equal "" whitespace-retval)
660 nil
661 whitespace-retval))))
662
663(defun whitespace-buffer-cleanup (regexp newregexp)
664 "Search for any given whitespace REGEXP and replace it with the NEWREGEXP."
665 (save-excursion
666 (goto-char (point-min))
667 (while (re-search-forward regexp nil t)
668 (replace-match newregexp))))
669
670(defun whitespace-indent-cleanup ()
24b72a45 671 "Search for 8/more spaces at the start of a line and replace it with tabs."
acc975b1
DL
672 (save-excursion
673 (goto-char (point-min))
674 (while (re-search-forward whitespace-indent-regexp nil t)
675 (let ((column (current-column))
676 (indent-tabs-mode t))
677 (delete-region (match-beginning 0) (point))
678 (indent-to column)))))
679
dd24f431
GM
680(defun whitespace-unchecked-whitespaces ()
681 "Return the list of whitespaces whose testing has been suppressed."
a3db02ad
RV
682 (let ((unchecked-spaces
683 (concat (if (not whitespace-check-buffer-ateol) "e")
684 (if (not whitespace-check-buffer-indent) "i")
685 (if (not whitespace-check-buffer-leading) "l")
686 (if (not whitespace-check-buffer-spacetab) "s")
687 (if (not whitespace-check-buffer-trailing) "t"))))
688 (if (not (equal unchecked-spaces ""))
689 unchecked-spaces
dd24f431
GM
690 nil)))
691
692(defun whitespace-update-modeline (&optional whitespace-err)
fc333790
DL
693 "Update modeline with whitespace errors.
694Also with whitespaces whose testing has been turned off."
dd24f431 695 (if whitespace-display-in-modeline
0e38b2a2
GM
696 (progn
697 (setq whitespace-mode-line nil)
698 ;; Whitespace errors
699 (if (and whitespace-err (not (equal whitespace-err "")))
700 (setq whitespace-mode-line whitespace-err))
701 ;; Whitespace suppressed errors
702 (let ((whitespace-unchecked (whitespace-unchecked-whitespaces)))
703 (if whitespace-unchecked
704 (setq whitespace-mode-line
705 (concat whitespace-mode-line "!" whitespace-unchecked))))
706 ;; Add the whitespace modeline prefix
707 (setq whitespace-mode-line (if whitespace-mode-line
708 (concat " W:" whitespace-mode-line)
709 nil))
5dc2e846 710 (whitespace-mode-line-update))))
18d51459 711
5dc2e846
RV
712(defun whitespace-highlight-the-space (b e)
713 "Highlight the current line, unhighlighting a previously jumped to line."
714 (if whitespace-display-spaces-in-color
c22c3db0 715 (let ((ol (whitespace-make-overlay b e)))
c22c3db0 716 (push ol whitespace-highlighted-space)
ee01ad0e 717 (whitespace-overlay-put ol 'face 'whitespace-highlight))))
5dc2e846
RV
718;; (add-hook 'pre-command-hook 'whitespace-unhighlight-the-space))
719
7dbe67a4 720(defun whitespace-unhighlight-the-space()
5dc2e846
RV
721 "Unhighlight the currently highlight line."
722 (if (and whitespace-display-spaces-in-color whitespace-highlighted-space)
c22c3db0
SM
723 (progn
724 (mapc 'whitespace-delete-overlay whitespace-highlighted-space)
5dc2e846
RV
725 (setq whitespace-highlighted-space nil))
726 (remove-hook 'pre-command-hook 'whitespace-unhighlight-the-space)))
acc975b1
DL
727
728(defun whitespace-check-buffer-list (buf-name buf-file)
24b72a45
RS
729 "Add a buffer and its file to the whitespace monitor list.
730
731The buffer named BUF-NAME and its associated file BUF-FILE are now monitored
732periodically for whitespace."
acc975b1
DL
733 (if (and whitespace-mode (not (member (list buf-file buf-name)
734 whitespace-all-buffer-files)))
735 (add-to-list 'whitespace-all-buffer-files (list buf-file buf-name))))
736
737(defun whitespace-tickle-timer ()
24b72a45
RS
738 "Tickle timer to periodically to scan qualifying files for whitespace creep.
739
740If timer is not set, then set it to scan the files in
741`whitespace-all-buffer-files' periodically (defined by
742`whitespace-rescan-timer-time') for whitespace creep."
18d51459 743 (if (and whitespace-rescan-timer-time (not whitespace-rescan-timer))
acc975b1 744 (setq whitespace-rescan-timer
fc333790
DL
745 (add-timeout whitespace-rescan-timer-time
746 'whitespace-rescan-files-in-buffers nil
747 whitespace-rescan-timer-time))))
acc975b1
DL
748
749(defun whitespace-rescan-files-in-buffers (&optional arg)
24b72a45 750 "Check monitored files for whitespace creep since last scan."
acc975b1 751 (let ((whitespace-all-my-files whitespace-all-buffer-files)
24b72a45 752 buffile bufname thiselt buf)
acc975b1
DL
753 (if (not whitespace-all-my-files)
754 (progn
fc333790 755 (disable-timeout whitespace-rescan-timer)
acc975b1
DL
756 (setq whitespace-rescan-timer nil))
757 (while whitespace-all-my-files
758 (setq thiselt (car whitespace-all-my-files))
759 (setq whitespace-all-my-files (cdr whitespace-all-my-files))
760 (setq buffile (car thiselt))
761 (setq bufname (cadr thiselt))
762 (setq buf (get-buffer bufname))
763 (if (buffer-live-p buf)
764 (save-excursion
765 ;;(message "buffer %s live" bufname)
766 (set-buffer bufname)
767 (if whitespace-mode
768 (progn
769 ;;(message "checking for whitespace in %s" bufname)
770 (if whitespace-auto-cleanup
771 (progn
772 ;;(message "cleaning up whitespace in %s" bufname)
f473c8d5 773 (whitespace-cleanup-internal))
acc975b1
DL
774 (progn
775 ;;(message "whitespace-buffer %s." (buffer-name))
776 (whitespace-buffer t))))
777 ;;(message "Removing %s from refresh list" bufname)
778 (whitespace-refresh-rescan-list buffile bufname)))
779 ;;(message "Removing %s from refresh list" bufname)
780 (whitespace-refresh-rescan-list buffile bufname))))))
781
782(defun whitespace-refresh-rescan-list (buffile bufname)
24b72a45 783 "Refresh the list of files to be rescaned for whitespace creep."
acc975b1 784 (if whitespace-all-buffer-files
fc333790
DL
785 (setq whitespace-all-buffer-files
786 (delete (list buffile bufname) whitespace-all-buffer-files))
787 (when whitespace-rescan-timer
788 (disable-timeout whitespace-rescan-timer)
789 (setq whitespace-rescan-timer nil))))
790
35bf5a4e
RS
791;;;###autoload
792(defalias 'global-whitespace-mode 'whitespace-global-mode)
793
fc333790 794;;;###autoload
07089c84 795(define-minor-mode whitespace-global-mode
fc333790 796 "Toggle using Whitespace mode in new buffers.
c98ddbe5 797With ARG, turn the mode on iff ARG is positive.
fc333790
DL
798
799When this mode is active, `whitespace-buffer' is added to
07089c84 800`find-file-hook' and `kill-buffer-hook'."
9800cbdd 801 :global t
9800cbdd 802 :group 'whitespace
07089c84 803 (if whitespace-global-mode
acc975b1 804 (progn
07089c84
SM
805 (add-hook 'find-file-hook 'whitespace-buffer)
806 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
fc333790 807 (add-hook 'kill-buffer-hook 'whitespace-buffer))
07089c84
SM
808 (remove-hook 'find-file-hook 'whitespace-buffer)
809 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
fc333790 810 (remove-hook 'kill-buffer-hook 'whitespace-buffer)))
acc975b1 811
1f8437c4
RV
812;;;###autoload
813(defun whitespace-write-file-hook ()
07089c84
SM
814 "Hook function to be called on the buffer when whitespace check is enabled.
815This is meant to be added buffer-locally to `write-file-functions'."
1f8437c4
RV
816 (interactive)
817 (let ((werr nil))
818 (if whitespace-auto-cleanup
f473c8d5 819 (whitespace-cleanup-internal)
1f8437c4
RV
820 (setq werr (whitespace-buffer)))
821 (if (and whitespace-abort-on-error werr)
822 (error (concat "Abort write due to whitespaces in "
823 buffer-file-name))))
824 nil)
825
fc333790 826(defun whitespace-unload-hook ()
07089c84 827 (remove-hook 'find-file-hook 'whitespace-buffer)
e23d264d 828 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
fc333790
DL
829 (remove-hook 'kill-buffer-hook 'whitespace-buffer))
830
fd07aeb3
RS
831(add-hook 'whitespace-unload-hook 'whitespace-unload-hook)
832
acc975b1 833(provide 'whitespace)
ab5796a9 834
c22c3db0 835;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c
acc975b1 836;;; whitespace.el ends here