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