(mh-mime-save-parts): Add -store option to mhn (closes SF #1513140).
[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.
04f0adee 521See `whitespace-buffer' docstring for a summary of the problems."
acc975b1 522 (interactive)
f473c8d5
RV
523 (if (and transient-mark-mode mark-active)
524 (whitespace-cleanup-region (region-beginning) (region-end))
525 (whitespace-cleanup-internal)))
526
527(defun whitespace-cleanup-internal ()
acc975b1
DL
528 ;; If this buffer really contains a file, then run, else quit.
529 (whitespace-check-whitespace-mode current-prefix-arg)
530 (if (and buffer-file-name whitespace-mode)
531 (let ((whitespace-any nil)
532 (whitespace-tabwith 8)
533 (whitespace-tabwith-saved tab-width))
534
535 ;; since all printable TABS should be 8, irrespective of how
536 ;; they are displayed.
537 (setq tab-width whitespace-tabwith)
538
a3db02ad 539 (if (and whitespace-check-buffer-leading
18d51459 540 (whitespace-buffer-leading))
acc975b1
DL
541 (progn
542 (whitespace-buffer-leading-cleanup)
543 (setq whitespace-any t)))
544
a3db02ad 545 (if (and whitespace-check-buffer-trailing
18d51459 546 (whitespace-buffer-trailing))
acc975b1
DL
547 (progn
548 (whitespace-buffer-trailing-cleanup)
549 (setq whitespace-any t)))
550
a3db02ad 551 (if (and whitespace-check-buffer-indent
18d51459 552 (whitespace-buffer-search whitespace-indent-regexp))
acc975b1
DL
553 (progn
554 (whitespace-indent-cleanup)
555 (setq whitespace-any t)))
556
a3db02ad 557 (if (and whitespace-check-buffer-spacetab
18d51459 558 (whitespace-buffer-search whitespace-spacetab-regexp))
acc975b1
DL
559 (progn
560 (whitespace-buffer-cleanup whitespace-spacetab-regexp "\t")
561 (setq whitespace-any t)))
562
a3db02ad 563 (if (and whitespace-check-buffer-ateol
18d51459 564 (whitespace-buffer-search whitespace-ateol-regexp))
acc975b1
DL
565 (progn
566 (whitespace-buffer-cleanup whitespace-ateol-regexp "")
567 (setq whitespace-any t)))
568
569 ;; Call this recursively till everything is taken care of
18d51459 570 (if whitespace-any
f473c8d5 571 (whitespace-cleanup-internal)
acc975b1 572 (progn
72f295ec
RV
573 (if (not whitespace-silent)
574 (message "%s clean" buffer-file-name))
dd24f431 575 (whitespace-update-modeline)))
acc975b1
DL
576 (setq tab-width whitespace-tabwith-saved))))
577
24b72a45 578;;;###autoload
acc975b1 579(defun whitespace-cleanup-region (s e)
fc333790 580 "Whitespace cleanup on the region."
acc975b1
DL
581 (interactive "r")
582 (save-excursion
583 (save-restriction
584 (narrow-to-region s e)
f473c8d5 585 (whitespace-cleanup-internal))
acc975b1
DL
586 (whitespace-buffer t)))
587
588(defun whitespace-buffer-leading ()
589 "Check to see if there are any empty lines at the top of the file."
590 (save-excursion
591 (let ((pmin nil)
592 (pmax nil))
593 (goto-char (point-min))
594 (beginning-of-line)
595 (setq pmin (point))
596 (end-of-line)
597 (setq pmax (point))
df5e8d2c 598 (if (equal pmin pmax)
5dc2e846 599 (progn
df5e8d2c 600 (whitespace-highlight-the-space pmin (1+ pmax))
5dc2e846 601 t)
acc975b1
DL
602 nil))))
603
604(defun whitespace-buffer-leading-cleanup ()
24b72a45 605 "Remove any empty lines at the top of the file."
acc975b1 606 (save-excursion
185d43ee
RS
607 (goto-char (point-min))
608 (skip-chars-forward "\n")
609 (delete-region (point-min) (point))))
acc975b1
DL
610
611(defun whitespace-buffer-trailing ()
612 "Check to see if are is more than one empty line at the bottom."
613 (save-excursion
614 (let ((pmin nil)
615 (pmax nil))
616 (goto-char (point-max))
617 (beginning-of-line)
618 (setq pmin (point))
619 (end-of-line)
620 (setq pmax (point))
621 (if (equal pmin pmax)
622 (progn
623 (goto-char (- (point) 1))
624 (beginning-of-line)
625 (setq pmin (point))
626 (end-of-line)
627 (setq pmax (point))
df5e8d2c 628 (if (equal pmin pmax)
5dc2e846 629 (progn
df5e8d2c 630 (whitespace-highlight-the-space (- pmin 1) pmax)
5dc2e846 631 t)
acc975b1
DL
632 nil))
633 nil))))
634
635(defun whitespace-buffer-trailing-cleanup ()
636 "Delete all the empty lines at the bottom."
637 (save-excursion
185d43ee
RS
638 (goto-char (point-max))
639 (skip-chars-backward "\n")
640 (if (not (bolp))
641 (forward-char 1))
642 (delete-region (point) (point-max))))
acc975b1
DL
643
644(defun whitespace-buffer-search (regexp)
645 "Search for any given whitespace REGEXP."
646 (let ((whitespace-retval ""))
647 (save-excursion
648 (goto-char (point-min))
649 (while (re-search-forward regexp nil t)
5dc2e846
RV
650 (progn
651 (setq whitespace-retval (format "%s %s" whitespace-retval
652 (match-beginning 0)))
653 (whitespace-highlight-the-space (match-beginning 0) (match-end 0))))
acc975b1
DL
654 (if (equal "" whitespace-retval)
655 nil
656 whitespace-retval))))
657
658(defun whitespace-buffer-cleanup (regexp newregexp)
659 "Search for any given whitespace REGEXP and replace it with the NEWREGEXP."
660 (save-excursion
661 (goto-char (point-min))
662 (while (re-search-forward regexp nil t)
663 (replace-match newregexp))))
664
665(defun whitespace-indent-cleanup ()
24b72a45 666 "Search for 8/more spaces at the start of a line and replace it with tabs."
acc975b1
DL
667 (save-excursion
668 (goto-char (point-min))
669 (while (re-search-forward whitespace-indent-regexp nil t)
670 (let ((column (current-column))
671 (indent-tabs-mode t))
672 (delete-region (match-beginning 0) (point))
673 (indent-to column)))))
674
dd24f431
GM
675(defun whitespace-unchecked-whitespaces ()
676 "Return the list of whitespaces whose testing has been suppressed."
a3db02ad
RV
677 (let ((unchecked-spaces
678 (concat (if (not whitespace-check-buffer-ateol) "e")
679 (if (not whitespace-check-buffer-indent) "i")
680 (if (not whitespace-check-buffer-leading) "l")
681 (if (not whitespace-check-buffer-spacetab) "s")
682 (if (not whitespace-check-buffer-trailing) "t"))))
683 (if (not (equal unchecked-spaces ""))
684 unchecked-spaces
dd24f431
GM
685 nil)))
686
687(defun whitespace-update-modeline (&optional whitespace-err)
fc333790
DL
688 "Update modeline with whitespace errors.
689Also with whitespaces whose testing has been turned off."
dd24f431 690 (if whitespace-display-in-modeline
0e38b2a2
GM
691 (progn
692 (setq whitespace-mode-line nil)
693 ;; Whitespace errors
694 (if (and whitespace-err (not (equal whitespace-err "")))
695 (setq whitespace-mode-line whitespace-err))
696 ;; Whitespace suppressed errors
697 (let ((whitespace-unchecked (whitespace-unchecked-whitespaces)))
698 (if whitespace-unchecked
699 (setq whitespace-mode-line
700 (concat whitespace-mode-line "!" whitespace-unchecked))))
701 ;; Add the whitespace modeline prefix
702 (setq whitespace-mode-line (if whitespace-mode-line
703 (concat " W:" whitespace-mode-line)
704 nil))
5dc2e846 705 (whitespace-mode-line-update))))
18d51459 706
5dc2e846
RV
707(defun whitespace-highlight-the-space (b e)
708 "Highlight the current line, unhighlighting a previously jumped to line."
709 (if whitespace-display-spaces-in-color
c22c3db0 710 (let ((ol (whitespace-make-overlay b e)))
c22c3db0 711 (push ol whitespace-highlighted-space)
ee01ad0e 712 (whitespace-overlay-put ol 'face 'whitespace-highlight))))
5dc2e846
RV
713;; (add-hook 'pre-command-hook 'whitespace-unhighlight-the-space))
714
7dbe67a4 715(defun whitespace-unhighlight-the-space()
5dc2e846
RV
716 "Unhighlight the currently highlight line."
717 (if (and whitespace-display-spaces-in-color whitespace-highlighted-space)
c22c3db0
SM
718 (progn
719 (mapc 'whitespace-delete-overlay whitespace-highlighted-space)
5dc2e846
RV
720 (setq whitespace-highlighted-space nil))
721 (remove-hook 'pre-command-hook 'whitespace-unhighlight-the-space)))
acc975b1
DL
722
723(defun whitespace-check-buffer-list (buf-name buf-file)
24b72a45
RS
724 "Add a buffer and its file to the whitespace monitor list.
725
726The buffer named BUF-NAME and its associated file BUF-FILE are now monitored
727periodically for whitespace."
acc975b1
DL
728 (if (and whitespace-mode (not (member (list buf-file buf-name)
729 whitespace-all-buffer-files)))
730 (add-to-list 'whitespace-all-buffer-files (list buf-file buf-name))))
731
732(defun whitespace-tickle-timer ()
24b72a45
RS
733 "Tickle timer to periodically to scan qualifying files for whitespace creep.
734
735If timer is not set, then set it to scan the files in
736`whitespace-all-buffer-files' periodically (defined by
737`whitespace-rescan-timer-time') for whitespace creep."
18d51459 738 (if (and whitespace-rescan-timer-time (not whitespace-rescan-timer))
acc975b1 739 (setq whitespace-rescan-timer
fc333790
DL
740 (add-timeout whitespace-rescan-timer-time
741 'whitespace-rescan-files-in-buffers nil
742 whitespace-rescan-timer-time))))
acc975b1
DL
743
744(defun whitespace-rescan-files-in-buffers (&optional arg)
24b72a45 745 "Check monitored files for whitespace creep since last scan."
acc975b1 746 (let ((whitespace-all-my-files whitespace-all-buffer-files)
24b72a45 747 buffile bufname thiselt buf)
acc975b1
DL
748 (if (not whitespace-all-my-files)
749 (progn
fc333790 750 (disable-timeout whitespace-rescan-timer)
acc975b1
DL
751 (setq whitespace-rescan-timer nil))
752 (while whitespace-all-my-files
753 (setq thiselt (car whitespace-all-my-files))
754 (setq whitespace-all-my-files (cdr whitespace-all-my-files))
755 (setq buffile (car thiselt))
756 (setq bufname (cadr thiselt))
757 (setq buf (get-buffer bufname))
758 (if (buffer-live-p buf)
759 (save-excursion
760 ;;(message "buffer %s live" bufname)
761 (set-buffer bufname)
762 (if whitespace-mode
763 (progn
764 ;;(message "checking for whitespace in %s" bufname)
765 (if whitespace-auto-cleanup
766 (progn
767 ;;(message "cleaning up whitespace in %s" bufname)
f473c8d5 768 (whitespace-cleanup-internal))
acc975b1
DL
769 (progn
770 ;;(message "whitespace-buffer %s." (buffer-name))
771 (whitespace-buffer t))))
772 ;;(message "Removing %s from refresh list" bufname)
773 (whitespace-refresh-rescan-list buffile bufname)))
774 ;;(message "Removing %s from refresh list" bufname)
775 (whitespace-refresh-rescan-list buffile bufname))))))
776
777(defun whitespace-refresh-rescan-list (buffile bufname)
24b72a45 778 "Refresh the list of files to be rescaned for whitespace creep."
acc975b1 779 (if whitespace-all-buffer-files
fc333790
DL
780 (setq whitespace-all-buffer-files
781 (delete (list buffile bufname) whitespace-all-buffer-files))
782 (when whitespace-rescan-timer
783 (disable-timeout whitespace-rescan-timer)
784 (setq whitespace-rescan-timer nil))))
785
35bf5a4e
RS
786;;;###autoload
787(defalias 'global-whitespace-mode 'whitespace-global-mode)
788
fc333790 789;;;###autoload
07089c84 790(define-minor-mode whitespace-global-mode
fc333790 791 "Toggle using Whitespace mode in new buffers.
c98ddbe5 792With ARG, turn the mode on iff ARG is positive.
fc333790
DL
793
794When this mode is active, `whitespace-buffer' is added to
07089c84 795`find-file-hook' and `kill-buffer-hook'."
9800cbdd 796 :global t
9800cbdd 797 :group 'whitespace
07089c84 798 (if whitespace-global-mode
acc975b1 799 (progn
07089c84
SM
800 (add-hook 'find-file-hook 'whitespace-buffer)
801 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
fc333790 802 (add-hook 'kill-buffer-hook 'whitespace-buffer))
07089c84
SM
803 (remove-hook 'find-file-hook 'whitespace-buffer)
804 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
fc333790 805 (remove-hook 'kill-buffer-hook 'whitespace-buffer)))
acc975b1 806
1f8437c4
RV
807;;;###autoload
808(defun whitespace-write-file-hook ()
07089c84
SM
809 "Hook function to be called on the buffer when whitespace check is enabled.
810This is meant to be added buffer-locally to `write-file-functions'."
1f8437c4
RV
811 (interactive)
812 (let ((werr nil))
813 (if whitespace-auto-cleanup
f473c8d5 814 (whitespace-cleanup-internal)
1f8437c4
RV
815 (setq werr (whitespace-buffer)))
816 (if (and whitespace-abort-on-error werr)
817 (error (concat "Abort write due to whitespaces in "
818 buffer-file-name))))
819 nil)
820
fc333790 821(defun whitespace-unload-hook ()
07089c84 822 (remove-hook 'find-file-hook 'whitespace-buffer)
e23d264d 823 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
fc333790
DL
824 (remove-hook 'kill-buffer-hook 'whitespace-buffer))
825
fd07aeb3
RS
826(add-hook 'whitespace-unload-hook 'whitespace-unload-hook)
827
acc975b1 828(provide 'whitespace)
ab5796a9 829
c22c3db0 830;; arch-tag: 4ff44e87-b63c-402d-95a6-15e51e58bd0c
acc975b1 831;;; whitespace.el ends here