Replace `iff' in doc-strings and comments.
[bpt/emacs.git] / lisp / whitespace.el
CommitLineData
e8af40ee 1;;; whitespace.el --- warn about and clean bogus whitespaces in the file
acc975b1 2
c90f2757 3;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
d7a0267c 4;; 2005, 2006, 2007 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
b4aa6026 13;; the Free Software Foundation; either version 3, or (at your option)
acc975b1
DL
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)
dd24f431
GM
105
106(defvar whitespace-mode-line nil
107 "String to display in the mode line for Whitespace mode.")
108(make-variable-buffer-local 'whitespace-mode-line)
dd24f431 109
a3db02ad 110(defvar whitespace-check-buffer-leading nil
7f34d6d4 111 "Test leading whitespace for file in current buffer if t.")
a3db02ad 112(make-variable-buffer-local 'whitespace-check-buffer-leading)
a3db02ad
RV
113
114(defvar whitespace-check-buffer-trailing nil
7f34d6d4 115 "Test trailing whitespace for file in current buffer if t.")
a3db02ad 116(make-variable-buffer-local 'whitespace-check-buffer-trailing)
a3db02ad
RV
117
118(defvar whitespace-check-buffer-indent nil
7f34d6d4 119 "Test indentation whitespace for file in current buffer if t.")
a3db02ad 120(make-variable-buffer-local 'whitespace-check-buffer-indent)
a3db02ad
RV
121
122(defvar whitespace-check-buffer-spacetab nil
7f34d6d4 123 "Test Space-followed-by-TABS whitespace for file in current buffer if t.")
a3db02ad 124(make-variable-buffer-local 'whitespace-check-buffer-spacetab)
a3db02ad
RV
125
126(defvar whitespace-check-buffer-ateol nil
7f34d6d4 127 "Test end-of-line whitespace for file in current buffer if t.")
a3db02ad 128(make-variable-buffer-local 'whitespace-check-buffer-ateol)
a3db02ad 129
5dc2e846 130(defvar whitespace-highlighted-space nil
7f34d6d4 131 "The variable to store the extent to highlight.")
5dc2e846 132(make-variable-buffer-local 'whitespace-highlighted-space)
5dc2e846 133
07dc4175 134;; For flavors of Emacs which don't define `defgroup' and `defcustom'.
24b72a45 135(eval-when-compile
07dc4175
GM
136 (if (not (fboundp 'defgroup))
137 (defmacro defgroup (sym memb doc &rest args)
7f34d6d4 138 "Null macro for `defgroup' in all versions of Emacs that don't define it."
07dc4175
GM
139 t))
140 (if (not (fboundp 'defcustom))
141 (defmacro defcustom (sym val doc &rest args)
7f34d6d4
JB
142 "Macro to alias `defcustom' to `defvar' in all versions of Emacs that
143don't define it."
07dc4175 144 `(defvar ,sym ,val ,doc))))
acc975b1 145
9d8f0a3c
RS
146(defalias 'whitespace-make-overlay
147 (if (featurep 'xemacs) 'make-extent 'make-overlay))
148(defalias 'whitespace-overlay-put
149 (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
150(defalias 'whitespace-delete-overlay
151 (if (featurep 'xemacs) 'delete-extent 'delete-overlay))
152(defalias 'whitespace-overlay-start
153 (if (featurep 'xemacs) 'extent-start 'overlay-start))
154(defalias 'whitespace-overlay-end
155 (if (featurep 'xemacs) 'extent-end 'overlay-end))
156(defalias 'whitespace-mode-line-update
157 (if (featurep 'xemacs) 'redraw-modeline 'force-mode-line-update))
158
fc333790
DL
159(defgroup whitespace nil
160 "Check for and fix five different types of whitespaces in source code."
161 :version "21.1"
37a23b5d 162 :link '(emacs-commentary-link "whitespace.el")
9d8f0a3c
RS
163 ;; Since XEmacs doesn't have a 'convenience group, use the next best group
164 ;; which is 'editing?
165 :group (if (featurep 'xemacs) 'editing 'convenience))
acc975b1 166
18d51459 167(defcustom whitespace-check-leading-whitespace t
7f34d6d4 168 "Flag to check leading whitespace. This is the global for the system.
a3db02ad 169It can be overriden by setting a buffer local variable
7f34d6d4 170`whitespace-check-buffer-leading'."
18d51459
RS
171 :type 'boolean
172 :group 'whitespace)
173
174(defcustom whitespace-check-trailing-whitespace t
7f34d6d4 175 "Flag to check trailing whitespace. This is the global for the system.
a3db02ad 176It can be overriden by setting a buffer local variable
7f34d6d4 177`whitespace-check-buffer-trailing'."
18d51459
RS
178 :type 'boolean
179 :group 'whitespace)
180
181(defcustom whitespace-check-spacetab-whitespace t
7f34d6d4 182 "Flag to check space followed by a TAB. This is the global for the system.
a3db02ad 183It can be overriden by setting a buffer local variable
7f34d6d4 184`whitespace-check-buffer-spacetab'."
18d51459
RS
185 :type 'boolean
186 :group 'whitespace)
187
5dc2e846 188(defcustom whitespace-spacetab-regexp "[ ]+\t"
113fa448 189 "Regexp to match one or more spaces followed by a TAB."
fc333790 190 :type 'regexp
24b72a45 191 :group 'whitespace)
acc975b1 192
1f8437c4 193(defcustom whitespace-check-indent-whitespace indent-tabs-mode
7f34d6d4 194 "Flag to check indentation whitespace. This is the global for the system.
a3db02ad 195It can be overriden by setting a buffer local variable
7f34d6d4 196`whitespace-check-buffer-indent'."
18d51459
RS
197 :type 'boolean
198 :group 'whitespace)
199
113fa448
EZ
200(defcustom whitespace-indent-regexp "^\t*\\( \\)+"
201 "Regexp to match multiples of eight spaces near line beginnings.
202The default value ignores leading TABs."
fc333790 203 :type 'regexp
24b72a45
RS
204 :group 'whitespace)
205
18d51459 206(defcustom whitespace-check-ateol-whitespace t
7f34d6d4 207 "Flag to check end-of-line whitespace. This is the global for the system.
a3db02ad 208It can be overriden by setting a buffer local variable
7f34d6d4 209`whitespace-check-buffer-ateol'."
18d51459
RS
210 :type 'boolean
211 :group 'whitespace)
212
5dc2e846 213(defcustom whitespace-ateol-regexp "[ \t]+$"
113fa448 214 "Regexp to match one or more TABs or spaces at line ends."
fc333790 215 :type 'regexp
24b72a45
RS
216 :group 'whitespace)
217
218(defcustom whitespace-errbuf "*Whitespace Errors*"
fc333790 219 "The name of the buffer where whitespace related messages will be logged."
24b72a45
RS
220 :type 'string
221 :group 'whitespace)
222
c98ddbe5
RV
223(defcustom whitespace-clean-msg "clean."
224 "If non-nil, this message will be displayed after a whitespace check
225determines a file to be clean."
226 :type 'string
227 :group 'whitespace)
228
1f8437c4 229(defcustom whitespace-abort-on-error nil
7f34d6d4
JB
230 "While writing a file, abort if the file is unclean.
231If `whitespace-auto-cleanup' is set, that takes precedence over
232this variable."
1f8437c4
RV
233 :type 'boolean
234 :group 'whitespace)
235
24b72a45
RS
236(defcustom whitespace-auto-cleanup nil
237 "Cleanup a buffer automatically on finding it whitespace unclean."
acc975b1
DL
238 :type 'boolean
239 :group 'whitespace)
240
241(defcustom whitespace-silent nil
24b72a45 242 "All whitespace errors will be shown only in the modeline when t.
acc975b1
DL
243
244Note that setting this may cause all whitespaces introduced in a file to go
245unnoticed when the buffer is killed, unless the user visits the `*Whitespace
24b72a45 246Errors*' buffer before opening (or closing) another file."
acc975b1
DL
247 :type 'boolean
248 :group 'whitespace)
249
250(defcustom whitespace-modes '(ada-mode asm-mode autoconf-mode awk-mode
18d51459
RS
251 c-mode c++-mode cc-mode
252 change-log-mode cperl-mode
acc975b1
DL
253 electric-nroff-mode emacs-lisp-mode
254 f90-mode fortran-mode html-mode
255 html3-mode java-mode jde-mode
256 ksh-mode latex-mode LaTeX-mode
257 lisp-mode m4-mode makefile-mode
258 modula-2-mode nroff-mode objc-mode
259 pascal-mode perl-mode prolog-mode
260 python-mode scheme-mode sgml-mode
18d51459
RS
261 sh-mode shell-script-mode simula-mode
262 tcl-mode tex-mode texinfo-mode
263 vrml-mode xml-mode)
acc975b1 264
7f34d6d4 265 "Major modes in which we turn on whitespace checking.
acc975b1 266
fc333790 267These are mostly programming and documentation modes. But you may add other
24b72a45
RS
268modes that you want whitespaces checked in by adding something like the
269following to your `.emacs':
acc975b1 270
24b72a45
RS
271\(setq whitespace-modes (cons 'my-mode (cons 'my-other-mode
272 whitespace-modes))\)
acc975b1 273
24b72a45 274Or, alternately, you can use the Emacs `customize' command to set this."
fc333790 275 :type '(repeat symbol)
24b72a45 276 :group 'whitespace)
acc975b1 277
7f565d87 278(defcustom whitespace-rescan-timer-time 600
24b72a45
RS
279 "Period in seconds to rescan modified buffers for whitespace creep.
280
281This is the period after which the timer will fire causing
282`whitespace-rescan-files-in-buffers' to check for whitespace creep in
18d51459
RS
283modified buffers.
284
285To disable timer scans, set this to zero."
acc975b1
DL
286 :type 'integer
287 :group 'whitespace)
288
dd24f431
GM
289(defcustom whitespace-display-in-modeline t
290 "Display whitespace errors on the modeline."
291 :type 'boolean
292 :group 'whitespace)
acc975b1 293
5dc2e846 294(defcustom whitespace-display-spaces-in-color t
ee01ad0e
MB
295 "Display the bogus whitespaces by coloring them with the face
296`whitespace-highlight'."
5dc2e846
RV
297 :type 'boolean
298 :group 'whitespace)
299
300(defgroup whitespace-faces nil
301 "Faces used in whitespace."
302 :prefix "whitespace-"
303 :group 'whitespace
304 :group 'faces)
305
ee01ad0e
MB
306(defface whitespace-highlight '((((class color) (background light))
307 (:background "green1"))
308 (((class color) (background dark))
309 (:background "sea green"))
310 (((class grayscale mono)
311 (background light))
312 (:background "black"))
313 (((class grayscale mono)
314 (background dark))
315 (:background "white")))
5dc2e846
RV
316 "Face used for highlighting the bogus whitespaces that exist in the buffer."
317 :group 'whitespace-faces)
ee01ad0e
MB
318;; backward-compatibility alias
319(put 'whitespace-highlight-face 'face-alias 'whitespace-highlight)
5dc2e846 320
acc975b1
DL
321(if (not (assoc 'whitespace-mode minor-mode-alist))
322 (setq minor-mode-alist (cons '(whitespace-mode whitespace-mode-line)
323 minor-mode-alist)))
324
a3db02ad
RV
325(set-default 'whitespace-check-buffer-leading
326 whitespace-check-leading-whitespace)
327(set-default 'whitespace-check-buffer-trailing
328 whitespace-check-trailing-whitespace)
329(set-default 'whitespace-check-buffer-indent
330 whitespace-check-indent-whitespace)
331(set-default 'whitespace-check-buffer-spacetab
332 whitespace-check-spacetab-whitespace)
333(set-default 'whitespace-check-buffer-ateol
334 whitespace-check-ateol-whitespace)
335
acc975b1 336(defun whitespace-check-whitespace-mode (&optional arg)
24b72a45 337 "Test and set the whitespace-mode in qualifying buffers."
acc975b1
DL
338 (if (null whitespace-mode)
339 (setq whitespace-mode
340 (if (or arg (member major-mode whitespace-modes))
341 t
342 nil))))
343
a3db02ad
RV
344;;;###autoload
345(defun whitespace-toggle-leading-check ()
346 "Toggle the check for leading space in the local buffer."
347 (interactive)
348 (let ((current-val whitespace-check-buffer-leading))
349 (setq whitespace-check-buffer-leading (not current-val))
350 (message "Will%s check for leading space in buffer."
351 (if whitespace-check-buffer-leading "" " not"))
352 (if whitespace-check-buffer-leading (whitespace-buffer-leading))))
353
354;;;###autoload
355(defun whitespace-toggle-trailing-check ()
356 "Toggle the check for trailing space in the local buffer."
357 (interactive)
358 (let ((current-val whitespace-check-buffer-trailing))
359 (setq whitespace-check-buffer-trailing (not current-val))
360 (message "Will%s check for trailing space in buffer."
361 (if whitespace-check-buffer-trailing "" " not"))
362 (if whitespace-check-buffer-trailing (whitespace-buffer-trailing))))
363
364;;;###autoload
365(defun whitespace-toggle-indent-check ()
366 "Toggle the check for indentation space in the local buffer."
367 (interactive)
368 (let ((current-val whitespace-check-buffer-indent))
369 (setq whitespace-check-buffer-indent (not current-val))
370 (message "Will%s check for indentation space in buffer."
371 (if whitespace-check-buffer-indent "" " not"))
372 (if whitespace-check-buffer-indent
373 (whitespace-buffer-search whitespace-indent-regexp))))
374
375;;;###autoload
376(defun whitespace-toggle-spacetab-check ()
377 "Toggle the check for space-followed-by-TABs in the local buffer."
378 (interactive)
379 (let ((current-val whitespace-check-buffer-spacetab))
380 (setq whitespace-check-buffer-spacetab (not current-val))
381 (message "Will%s check for space-followed-by-TABs in buffer."
382 (if whitespace-check-buffer-spacetab "" " not"))
383 (if whitespace-check-buffer-spacetab
384 (whitespace-buffer-search whitespace-spacetab-regexp))))
385
386
387;;;###autoload
388(defun whitespace-toggle-ateol-check ()
389 "Toggle the check for end-of-line space in the local buffer."
390 (interactive)
391 (let ((current-val whitespace-check-buffer-ateol))
392 (setq whitespace-check-buffer-ateol (not current-val))
393 (message "Will%s check for end-of-line space in buffer."
394 (if whitespace-check-buffer-ateol "" " not"))
395 (if whitespace-check-buffer-ateol
396 (whitespace-buffer-search whitespace-ateol-regexp))))
397
398
24b72a45 399;;;###autoload
acc975b1 400(defun whitespace-buffer (&optional quiet)
fc333790
DL
401 "Find five different types of white spaces in buffer.
402These are:
acc975b1
DL
4031. Leading space \(empty lines at the top of a file\).
4042. Trailing space \(empty lines at the end of a file\).
4053. Indentation space \(8 or more spaces, that should be replaced with TABS\).
4064. Spaces followed by a TAB. \(Almost always, we never want that\).
4075. Spaces or TABS at the end of a line.
408
409Check for whitespace only if this buffer really contains a non-empty file
410and:
4111. the major mode is one of the whitespace-modes, or
24b72a45 4122. `whitespace-buffer' was explicitly called with a prefix argument."
acc975b1 413 (interactive)
dd24f431
GM
414 (let ((whitespace-error nil))
415 (whitespace-check-whitespace-mode current-prefix-arg)
416 (if (and buffer-file-name (> (buffer-size) 0) whitespace-mode)
417 (progn
418 (whitespace-check-buffer-list (buffer-name) buffer-file-name)
419 (whitespace-tickle-timer)
113fa448 420 (overlay-recenter (point-max))
8eda2ca3 421 (remove-overlays nil nil 'face 'whitespace-highlight)
dd24f431
GM
422 (if whitespace-auto-cleanup
423 (if buffer-read-only
424 (if (not quiet)
425 (message "Can't cleanup: %s is read-only" (buffer-name)))
f473c8d5 426 (whitespace-cleanup-internal))
a3db02ad 427 (let ((whitespace-leading (if whitespace-check-buffer-leading
dd24f431
GM
428 (whitespace-buffer-leading)
429 nil))
a3db02ad 430 (whitespace-trailing (if whitespace-check-buffer-trailing
dd24f431
GM
431 (whitespace-buffer-trailing)
432 nil))
a3db02ad 433 (whitespace-indent (if whitespace-check-buffer-indent
18d51459 434 (whitespace-buffer-search
dd24f431 435 whitespace-indent-regexp)
18d51459 436 nil))
a3db02ad 437 (whitespace-spacetab (if whitespace-check-buffer-spacetab
dd24f431
GM
438 (whitespace-buffer-search
439 whitespace-spacetab-regexp)
440 nil))
a3db02ad 441 (whitespace-ateol (if whitespace-check-buffer-ateol
dd24f431
GM
442 (whitespace-buffer-search
443 whitespace-ateol-regexp)
444 nil))
445 (whitespace-errmsg nil)
446 (whitespace-filename buffer-file-name)
447 (whitespace-this-modeline ""))
448
449 ;; Now let's complain if we found any of the above.
450 (setq whitespace-error (or whitespace-leading whitespace-indent
451 whitespace-spacetab whitespace-ateol
452 whitespace-trailing))
453
454 (if whitespace-error
acc975b1 455 (progn
dd24f431
GM
456 (setq whitespace-errmsg
457 (concat whitespace-filename " contains:\n"
458 (if whitespace-leading
459 "Leading whitespace\n")
460 (if whitespace-indent
461 (concat "Indentation whitespace"
462 whitespace-indent "\n"))
463 (if whitespace-spacetab
464 (concat "Space followed by Tab"
465 whitespace-spacetab "\n"))
466 (if whitespace-ateol
467 (concat "End-of-line whitespace"
468 whitespace-ateol "\n"))
469 (if whitespace-trailing
470 "Trailing whitespace\n")
471 "\ntype `M-x whitespace-cleanup' to "
472 "cleanup the file."))
473 (setq whitespace-this-modeline
474 (concat (if whitespace-ateol "e")
475 (if whitespace-indent "i")
476 (if whitespace-leading "l")
477 (if whitespace-spacetab "s")
478 (if whitespace-trailing "t")))))
479 (whitespace-update-modeline whitespace-this-modeline)
c22c3db0
SM
480 (if (get-buffer whitespace-errbuf)
481 (kill-buffer whitespace-errbuf))
482 (with-current-buffer (get-buffer-create whitespace-errbuf)
dd24f431
GM
483 (if whitespace-errmsg
484 (progn
485 (insert whitespace-errmsg)
486 (if (not (or quiet whitespace-silent))
c22c3db0 487 (display-buffer (current-buffer) t))
dd24f431
GM
488 (if (not quiet)
489 (message "Whitespaces: [%s%s] in %s"
490 whitespace-this-modeline
491 (let ((whitespace-unchecked
492 (whitespace-unchecked-whitespaces)))
493 (if whitespace-unchecked
494 (concat "!" whitespace-unchecked)
495 ""))
496 whitespace-filename)))
c98ddbe5
RV
497 (if (and (not quiet) (not (equal whitespace-clean-msg "")))
498 (message "%s %s" whitespace-filename
499 whitespace-clean-msg))))))))
c22c3db0 500 whitespace-error))
acc975b1 501
24b72a45 502;;;###autoload
acc975b1 503(defun whitespace-region (s e)
fc333790 504 "Check the region for whitespace errors."
acc975b1
DL
505 (interactive "r")
506 (save-excursion
507 (save-restriction
508 (narrow-to-region s e)
509 (whitespace-buffer))))
510
24b72a45 511;;;###autoload
acc975b1 512(defun whitespace-cleanup ()
24b72a45 513 "Cleanup the five different kinds of whitespace problems.
0d92660c
RS
514It normally applies to the whole buffer, but in Transient Mark mode
515when the mark is active it applies to the region.
04f0adee 516See `whitespace-buffer' docstring for a summary of the problems."
acc975b1 517 (interactive)
f473c8d5
RV
518 (if (and transient-mark-mode mark-active)
519 (whitespace-cleanup-region (region-beginning) (region-end))
520 (whitespace-cleanup-internal)))
521
6e6f0cb6 522(defun whitespace-cleanup-internal (&optional region-only)
acc975b1
DL
523 ;; If this buffer really contains a file, then run, else quit.
524 (whitespace-check-whitespace-mode current-prefix-arg)
525 (if (and buffer-file-name whitespace-mode)
526 (let ((whitespace-any nil)
527 (whitespace-tabwith 8)
528 (whitespace-tabwith-saved tab-width))
529
530 ;; since all printable TABS should be 8, irrespective of how
531 ;; they are displayed.
532 (setq tab-width whitespace-tabwith)
533
a3db02ad 534 (if (and whitespace-check-buffer-leading
18d51459 535 (whitespace-buffer-leading))
acc975b1
DL
536 (progn
537 (whitespace-buffer-leading-cleanup)
538 (setq whitespace-any t)))
539
a3db02ad 540 (if (and whitespace-check-buffer-trailing
18d51459 541 (whitespace-buffer-trailing))
acc975b1
DL
542 (progn
543 (whitespace-buffer-trailing-cleanup)
544 (setq whitespace-any t)))
545
a3db02ad 546 (if (and whitespace-check-buffer-indent
18d51459 547 (whitespace-buffer-search whitespace-indent-regexp))
acc975b1
DL
548 (progn
549 (whitespace-indent-cleanup)
550 (setq whitespace-any t)))
551
a3db02ad 552 (if (and whitespace-check-buffer-spacetab
18d51459 553 (whitespace-buffer-search whitespace-spacetab-regexp))
acc975b1
DL
554 (progn
555 (whitespace-buffer-cleanup whitespace-spacetab-regexp "\t")
556 (setq whitespace-any t)))
557
a3db02ad 558 (if (and whitespace-check-buffer-ateol
18d51459 559 (whitespace-buffer-search whitespace-ateol-regexp))
acc975b1
DL
560 (progn
561 (whitespace-buffer-cleanup whitespace-ateol-regexp "")
562 (setq whitespace-any t)))
563
564 ;; Call this recursively till everything is taken care of
18d51459 565 (if whitespace-any
2b058c72 566 (whitespace-cleanup-internal region-only)
6e6f0cb6 567 ;; if we are done, talk to the user
acc975b1 568 (progn
6e6f0cb6
EZ
569 (unless whitespace-silent
570 (if region-only
571 (message "The region is now clean")
572 (message "%s is now clean" buffer-file-name)))
dd24f431 573 (whitespace-update-modeline)))
acc975b1
DL
574 (setq tab-width whitespace-tabwith-saved))))
575
24b72a45 576;;;###autoload
acc975b1 577(defun whitespace-cleanup-region (s e)
fc333790 578 "Whitespace cleanup on the region."
acc975b1
DL
579 (interactive "r")
580 (save-excursion
581 (save-restriction
582 (narrow-to-region s e)
6e6f0cb6 583 (whitespace-cleanup-internal t))
acc975b1
DL
584 (whitespace-buffer t)))
585
586(defun whitespace-buffer-leading ()
113fa448
EZ
587 "Return t if the current buffer has leading newline characters.
588If highlighting is enabled, highlight these characters."
acc975b1 589 (save-excursion
113fa448
EZ
590 (goto-char (point-min))
591 (skip-chars-forward "\n")
592 (unless (bobp)
593 (whitespace-highlight-the-space (point-min) (point))
594 t)))
acc975b1
DL
595
596(defun whitespace-buffer-leading-cleanup ()
113fa448 597 "Remove any leading newline characters from current buffer."
acc975b1 598 (save-excursion
185d43ee
RS
599 (goto-char (point-min))
600 (skip-chars-forward "\n")
601 (delete-region (point-min) (point))))
acc975b1
DL
602
603(defun whitespace-buffer-trailing ()
113fa448
EZ
604 "Return t if the current buffer has extra trailing newline characters.
605If highlighting is enabled, highlight these characters."
acc975b1 606 (save-excursion
113fa448
EZ
607 (goto-char (point-max))
608 (skip-chars-backward "\n")
609 (forward-line)
610 (unless (eobp)
611 (whitespace-highlight-the-space (point) (point-max))
612 t)))
acc975b1
DL
613
614(defun whitespace-buffer-trailing-cleanup ()
113fa448 615 "Remove extra trailing newline characters from current buffer."
acc975b1 616 (save-excursion
185d43ee
RS
617 (goto-char (point-max))
618 (skip-chars-backward "\n")
113fa448
EZ
619 (unless (eobp)
620 (forward-line)
621 (delete-region (point) (point-max)))))
acc975b1
DL
622
623(defun whitespace-buffer-search (regexp)
624 "Search for any given whitespace REGEXP."
113fa448
EZ
625 (with-local-quit
626 (let (whitespace-retval)
627 (save-excursion
628 (goto-char (point-min))
629 (while (re-search-forward regexp nil t)
630 (whitespace-highlight-the-space (match-beginning 0) (match-end 0))
631 (push (match-beginning 0) whitespace-retval)))
632 (when whitespace-retval
633 (format " %s" (nreverse whitespace-retval))))))
acc975b1
DL
634
635(defun whitespace-buffer-cleanup (regexp newregexp)
636 "Search for any given whitespace REGEXP and replace it with the NEWREGEXP."
637 (save-excursion
638 (goto-char (point-min))
639 (while (re-search-forward regexp nil t)
640 (replace-match newregexp))))
641
642(defun whitespace-indent-cleanup ()
24b72a45 643 "Search for 8/more spaces at the start of a line and replace it with tabs."
acc975b1
DL
644 (save-excursion
645 (goto-char (point-min))
646 (while (re-search-forward whitespace-indent-regexp nil t)
647 (let ((column (current-column))
648 (indent-tabs-mode t))
649 (delete-region (match-beginning 0) (point))
650 (indent-to column)))))
651
dd24f431
GM
652(defun whitespace-unchecked-whitespaces ()
653 "Return the list of whitespaces whose testing has been suppressed."
a3db02ad
RV
654 (let ((unchecked-spaces
655 (concat (if (not whitespace-check-buffer-ateol) "e")
656 (if (not whitespace-check-buffer-indent) "i")
657 (if (not whitespace-check-buffer-leading) "l")
658 (if (not whitespace-check-buffer-spacetab) "s")
659 (if (not whitespace-check-buffer-trailing) "t"))))
660 (if (not (equal unchecked-spaces ""))
661 unchecked-spaces
dd24f431
GM
662 nil)))
663
664(defun whitespace-update-modeline (&optional whitespace-err)
fc333790
DL
665 "Update modeline with whitespace errors.
666Also with whitespaces whose testing has been turned off."
dd24f431 667 (if whitespace-display-in-modeline
0e38b2a2
GM
668 (progn
669 (setq whitespace-mode-line nil)
670 ;; Whitespace errors
671 (if (and whitespace-err (not (equal whitespace-err "")))
672 (setq whitespace-mode-line whitespace-err))
673 ;; Whitespace suppressed errors
674 (let ((whitespace-unchecked (whitespace-unchecked-whitespaces)))
675 (if whitespace-unchecked
676 (setq whitespace-mode-line
677 (concat whitespace-mode-line "!" whitespace-unchecked))))
678 ;; Add the whitespace modeline prefix
679 (setq whitespace-mode-line (if whitespace-mode-line
680 (concat " W:" whitespace-mode-line)
681 nil))
5dc2e846 682 (whitespace-mode-line-update))))
18d51459 683
5dc2e846
RV
684(defun whitespace-highlight-the-space (b e)
685 "Highlight the current line, unhighlighting a previously jumped to line."
686 (if whitespace-display-spaces-in-color
c22c3db0 687 (let ((ol (whitespace-make-overlay b e)))
ee01ad0e 688 (whitespace-overlay-put ol 'face 'whitespace-highlight))))
5dc2e846 689
7dbe67a4 690(defun whitespace-unhighlight-the-space()
5dc2e846
RV
691 "Unhighlight the currently highlight line."
692 (if (and whitespace-display-spaces-in-color whitespace-highlighted-space)
c22c3db0
SM
693 (progn
694 (mapc 'whitespace-delete-overlay whitespace-highlighted-space)
113fa448 695 (setq whitespace-highlighted-space nil))))
acc975b1
DL
696
697(defun whitespace-check-buffer-list (buf-name buf-file)
24b72a45
RS
698 "Add a buffer and its file to the whitespace monitor list.
699
700The buffer named BUF-NAME and its associated file BUF-FILE are now monitored
701periodically for whitespace."
acc975b1
DL
702 (if (and whitespace-mode (not (member (list buf-file buf-name)
703 whitespace-all-buffer-files)))
704 (add-to-list 'whitespace-all-buffer-files (list buf-file buf-name))))
705
706(defun whitespace-tickle-timer ()
24b72a45
RS
707 "Tickle timer to periodically to scan qualifying files for whitespace creep.
708
709If timer is not set, then set it to scan the files in
710`whitespace-all-buffer-files' periodically (defined by
711`whitespace-rescan-timer-time') for whitespace creep."
18d51459 712 (if (and whitespace-rescan-timer-time (not whitespace-rescan-timer))
acc975b1 713 (setq whitespace-rescan-timer
fc333790
DL
714 (add-timeout whitespace-rescan-timer-time
715 'whitespace-rescan-files-in-buffers nil
716 whitespace-rescan-timer-time))))
acc975b1
DL
717
718(defun whitespace-rescan-files-in-buffers (&optional arg)
24b72a45 719 "Check monitored files for whitespace creep since last scan."
acc975b1 720 (let ((whitespace-all-my-files whitespace-all-buffer-files)
24b72a45 721 buffile bufname thiselt buf)
acc975b1
DL
722 (if (not whitespace-all-my-files)
723 (progn
fc333790 724 (disable-timeout whitespace-rescan-timer)
acc975b1
DL
725 (setq whitespace-rescan-timer nil))
726 (while whitespace-all-my-files
727 (setq thiselt (car whitespace-all-my-files))
728 (setq whitespace-all-my-files (cdr whitespace-all-my-files))
729 (setq buffile (car thiselt))
730 (setq bufname (cadr thiselt))
731 (setq buf (get-buffer bufname))
732 (if (buffer-live-p buf)
733 (save-excursion
734 ;;(message "buffer %s live" bufname)
735 (set-buffer bufname)
736 (if whitespace-mode
737 (progn
738 ;;(message "checking for whitespace in %s" bufname)
739 (if whitespace-auto-cleanup
740 (progn
741 ;;(message "cleaning up whitespace in %s" bufname)
f473c8d5 742 (whitespace-cleanup-internal))
acc975b1
DL
743 (progn
744 ;;(message "whitespace-buffer %s." (buffer-name))
745 (whitespace-buffer t))))
746 ;;(message "Removing %s from refresh list" bufname)
747 (whitespace-refresh-rescan-list buffile bufname)))
748 ;;(message "Removing %s from refresh list" bufname)
749 (whitespace-refresh-rescan-list buffile bufname))))))
750
751(defun whitespace-refresh-rescan-list (buffile bufname)
113fa448 752 "Refresh the list of files to be rescanned for whitespace creep."
acc975b1 753 (if whitespace-all-buffer-files
fc333790
DL
754 (setq whitespace-all-buffer-files
755 (delete (list buffile bufname) whitespace-all-buffer-files))
756 (when whitespace-rescan-timer
757 (disable-timeout whitespace-rescan-timer)
758 (setq whitespace-rescan-timer nil))))
759
35bf5a4e
RS
760;;;###autoload
761(defalias 'global-whitespace-mode 'whitespace-global-mode)
762
fc333790 763;;;###autoload
07089c84 764(define-minor-mode whitespace-global-mode
fc333790 765 "Toggle using Whitespace mode in new buffers.
4837b516 766With ARG, turn the mode on if ARG is positive, otherwise turn it off.
fc333790
DL
767
768When this mode is active, `whitespace-buffer' is added to
07089c84 769`find-file-hook' and `kill-buffer-hook'."
9800cbdd 770 :global t
9800cbdd 771 :group 'whitespace
07089c84 772 (if whitespace-global-mode
acc975b1 773 (progn
07089c84
SM
774 (add-hook 'find-file-hook 'whitespace-buffer)
775 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
fc333790 776 (add-hook 'kill-buffer-hook 'whitespace-buffer))
07089c84
SM
777 (remove-hook 'find-file-hook 'whitespace-buffer)
778 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
fc333790 779 (remove-hook 'kill-buffer-hook 'whitespace-buffer)))
acc975b1 780
1f8437c4
RV
781;;;###autoload
782(defun whitespace-write-file-hook ()
07089c84
SM
783 "Hook function to be called on the buffer when whitespace check is enabled.
784This is meant to be added buffer-locally to `write-file-functions'."
1f8437c4
RV
785 (interactive)
786 (let ((werr nil))
787 (if whitespace-auto-cleanup
f473c8d5 788 (whitespace-cleanup-internal)
1f8437c4
RV
789 (setq werr (whitespace-buffer)))
790 (if (and whitespace-abort-on-error werr)
791 (error (concat "Abort write due to whitespaces in "
792 buffer-file-name))))
793 nil)
794
fc333790 795(defun whitespace-unload-hook ()
07089c84 796 (remove-hook 'find-file-hook 'whitespace-buffer)
e23d264d 797 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
fc333790
DL
798 (remove-hook 'kill-buffer-hook 'whitespace-buffer))
799
fd07aeb3
RS
800(add-hook 'whitespace-unload-hook 'whitespace-unload-hook)
801
acc975b1 802(provide 'whitespace)
ab5796a9 803
c22c3db0 804;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c
acc975b1 805;;; whitespace.el ends here