]> code.delx.au - gnu-emacs/blob - lisp/whitespace.el
Revert previous accidental commit
[gnu-emacs] / lisp / whitespace.el
1 ;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE
2
3 ;; Copyright (C) 2000-2014 Free Software Foundation, Inc.
4
5 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
6 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7 ;; Keywords: data, wp
8 ;; Version: 13.2.2
9 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software: you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation, either version 3 of the License, or
16 ;; (at your option) any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25
26 ;;; Commentary:
27
28 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29 ;;
30 ;; Introduction
31 ;; ------------
32 ;;
33 ;; This package is a minor mode to visualize blanks (TAB, (HARD) SPACE
34 ;; and NEWLINE).
35 ;;
36 ;; whitespace uses two ways to visualize blanks: faces and display
37 ;; table.
38 ;;
39 ;; * Faces are used to highlight the background with a color.
40 ;; whitespace uses font-lock to highlight blank characters.
41 ;;
42 ;; * Display table changes the way a character is displayed, that is,
43 ;; it provides a visual mark for characters, for example, at the end
44 ;; of line (?\xB6), at SPACEs (?\xB7) and at TABs (?\xBB).
45 ;;
46 ;; The `whitespace-style' variable selects which way blanks are
47 ;; visualized.
48 ;;
49 ;; Note that when whitespace is turned on, whitespace saves the
50 ;; font-lock state, that is, if font-lock is on or off. And
51 ;; whitespace restores the font-lock state when it is turned off. So,
52 ;; if whitespace is turned on and font-lock is off, whitespace also
53 ;; turns on the font-lock to highlight blanks, but the font-lock will
54 ;; be turned off when whitespace is turned off. Thus, turn on
55 ;; font-lock before whitespace is on, if you want that font-lock
56 ;; continues on after whitespace is turned off.
57 ;;
58 ;; When whitespace is on, it takes care of highlighting some special
59 ;; characters over the default mechanism of `nobreak-char-display'
60 ;; (which see) and `show-trailing-whitespace' (which see).
61 ;;
62 ;; The trailing spaces are not highlighted while point is at end of line.
63 ;; Also the spaces at beginning of buffer are not highlighted while point is at
64 ;; beginning of buffer; and the spaces at end of buffer are not highlighted
65 ;; while point is at end of buffer.
66 ;;
67 ;; There are two ways of using whitespace: local and global.
68 ;;
69 ;; * Local whitespace affects only the current buffer.
70 ;;
71 ;; * Global whitespace affects all current and future buffers. That
72 ;; is, if you turn on global whitespace and then create a new
73 ;; buffer, the new buffer will also have whitespace on. The
74 ;; `whitespace-global-modes' variable controls which major-mode will
75 ;; be automagically turned on.
76 ;;
77 ;; You can mix the local and global usage without any conflict. But
78 ;; local whitespace has priority over global whitespace. Whitespace
79 ;; mode is active in a buffer if you have enabled it in that buffer or
80 ;; if you have enabled it globally.
81 ;;
82 ;; When global and local whitespace are on:
83 ;;
84 ;; * if local whitespace is turned off, whitespace is turned off for
85 ;; the current buffer only.
86 ;;
87 ;; * if global whitespace is turned off, whitespace continues on only
88 ;; in the buffers in which local whitespace is on.
89 ;;
90 ;; To use whitespace, insert in your ~/.emacs:
91 ;;
92 ;; (require 'whitespace)
93 ;;
94 ;; Or autoload at least one of the commands`whitespace-mode',
95 ;; `whitespace-toggle-options', `global-whitespace-mode' or
96 ;; `global-whitespace-toggle-options'. For example:
97 ;;
98 ;; (autoload 'whitespace-mode "whitespace"
99 ;; "Toggle whitespace visualization." t)
100 ;; (autoload 'whitespace-toggle-options "whitespace"
101 ;; "Toggle local `whitespace-mode' options." t)
102 ;;
103 ;; whitespace was inspired by:
104 ;;
105 ;; whitespace.el Rajesh Vaidheeswarran <rv@gnu.org>
106 ;; Warn about and clean bogus whitespaces in the file
107 ;; (inspired the idea to warn and clean some blanks)
108 ;; This was the original `whitespace.el' which was replaced by
109 ;; `blank-mode.el'. And later `blank-mode.el' was renamed to
110 ;; `whitespace.el'.
111 ;;
112 ;; show-whitespace-mode.el Aurelien Tisne <aurelien.tisne@free.fr>
113 ;; Simple mode to highlight whitespaces
114 ;; (inspired the idea to use font-lock)
115 ;;
116 ;; whitespace-mode.el Lawrence Mitchell <wence@gmx.li>
117 ;; Major mode for editing Whitespace
118 ;; (inspired the idea to use display table)
119 ;;
120 ;; visws.el Miles Bader <miles@gnu.org>
121 ;; Make whitespace visible
122 ;; (handle display table, his code was modified, but the main
123 ;; idea was kept)
124 ;;
125 ;;
126 ;; Using whitespace
127 ;; ----------------
128 ;;
129 ;; There is no problem if you mix local and global minor mode usage.
130 ;;
131 ;; * LOCAL whitespace:
132 ;; + To toggle whitespace options locally, type:
133 ;;
134 ;; M-x whitespace-toggle-options RET
135 ;;
136 ;; + To activate whitespace locally, type:
137 ;;
138 ;; C-u 1 M-x whitespace-mode RET
139 ;;
140 ;; + To deactivate whitespace locally, type:
141 ;;
142 ;; C-u 0 M-x whitespace-mode RET
143 ;;
144 ;; + To toggle whitespace locally, type:
145 ;;
146 ;; M-x whitespace-mode RET
147 ;;
148 ;; * GLOBAL whitespace:
149 ;; + To toggle whitespace options globally, type:
150 ;;
151 ;; M-x global-whitespace-toggle-options RET
152 ;;
153 ;; + To activate whitespace globally, type:
154 ;;
155 ;; C-u 1 M-x global-whitespace-mode RET
156 ;;
157 ;; + To deactivate whitespace globally, type:
158 ;;
159 ;; C-u 0 M-x global-whitespace-mode RET
160 ;;
161 ;; + To toggle whitespace globally, type:
162 ;;
163 ;; M-x global-whitespace-mode RET
164 ;;
165 ;; There are also the following useful commands:
166 ;;
167 ;; `whitespace-newline-mode'
168 ;; Toggle NEWLINE minor mode visualization ("nl" on mode line).
169 ;;
170 ;; `global-whitespace-newline-mode'
171 ;; Toggle NEWLINE global minor mode visualization ("NL" on mode line).
172 ;;
173 ;; `whitespace-report'
174 ;; Report some blank problems in buffer.
175 ;;
176 ;; `whitespace-report-region'
177 ;; Report some blank problems in a region.
178 ;;
179 ;; `whitespace-cleanup'
180 ;; Cleanup some blank problems in all buffer or at region.
181 ;;
182 ;; `whitespace-cleanup-region'
183 ;; Cleanup some blank problems at region.
184 ;;
185 ;; The problems, which are cleaned up, are:
186 ;;
187 ;; 1. empty lines at beginning of buffer.
188 ;; 2. empty lines at end of buffer.
189 ;; If `whitespace-style' includes the value `empty', remove all
190 ;; empty lines at beginning and/or end of buffer.
191 ;;
192 ;; 3. 8 or more SPACEs at beginning of line.
193 ;; If `whitespace-style' includes the value `indentation':
194 ;; replace 8 or more SPACEs at beginning of line by TABs, if
195 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
196 ;; SPACEs.
197 ;; If `whitespace-style' includes the value `indentation::tab',
198 ;; replace 8 or more SPACEs at beginning of line by TABs.
199 ;; If `whitespace-style' includes the value `indentation::space',
200 ;; replace TABs by SPACEs.
201 ;;
202 ;; 4. SPACEs before TAB.
203 ;; If `whitespace-style' includes the value `space-before-tab':
204 ;; replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
205 ;; otherwise, replace TABs by SPACEs.
206 ;; If `whitespace-style' includes the value
207 ;; `space-before-tab::tab', replace SPACEs by TABs.
208 ;; If `whitespace-style' includes the value
209 ;; `space-before-tab::space', replace TABs by SPACEs.
210 ;;
211 ;; 5. SPACEs or TABs at end of line.
212 ;; If `whitespace-style' includes the value `trailing', remove all
213 ;; SPACEs or TABs at end of line.
214 ;;
215 ;; 6. 8 or more SPACEs after TAB.
216 ;; If `whitespace-style' includes the value `space-after-tab':
217 ;; replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
218 ;; otherwise, replace TABs by SPACEs.
219 ;; If `whitespace-style' includes the value `space-after-tab::tab',
220 ;; replace SPACEs by TABs.
221 ;; If `whitespace-style' includes the value
222 ;; `space-after-tab::space', replace TABs by SPACEs.
223 ;;
224 ;;
225 ;; Hooks
226 ;; -----
227 ;;
228 ;; whitespace has the following hook variables:
229 ;;
230 ;; `whitespace-mode-hook'
231 ;; It is evaluated always when whitespace is turned on locally.
232 ;;
233 ;; `global-whitespace-mode-hook'
234 ;; It is evaluated always when whitespace is turned on globally.
235 ;;
236 ;; `whitespace-load-hook'
237 ;; It is evaluated after whitespace package is loaded.
238 ;;
239 ;;
240 ;; Options
241 ;; -------
242 ;;
243 ;; Below it's shown a brief description of whitespace options, please,
244 ;; see the options declaration in the code for a long documentation.
245 ;;
246 ;; `whitespace-style' Specify which kind of blank is
247 ;; visualized.
248 ;;
249 ;; `whitespace-space' Face used to visualize SPACE.
250 ;;
251 ;; `whitespace-hspace' Face used to visualize HARD SPACE.
252 ;;
253 ;; `whitespace-tab' Face used to visualize TAB.
254 ;;
255 ;; `whitespace-newline' Face used to visualize NEWLINE char
256 ;; mapping.
257 ;;
258 ;; `whitespace-trailing' Face used to visualize trailing
259 ;; blanks.
260 ;;
261 ;; `whitespace-line' Face used to visualize "long" lines.
262 ;;
263 ;; `whitespace-space-before-tab' Face used to visualize SPACEs
264 ;; before TAB.
265 ;;
266 ;; `whitespace-indentation' Face used to visualize 8 or more
267 ;; SPACEs at beginning of line.
268 ;;
269 ;; `whitespace-big-indent' Face used to visualize big indentation.
270 ;;
271 ;; `whitespace-empty' Face used to visualize empty lines at
272 ;; beginning and/or end of buffer.
273 ;;
274 ;; `whitespace-space-after-tab' Face used to visualize 8 or more
275 ;; SPACEs after TAB.
276 ;;
277 ;; `whitespace-space-regexp' Specify SPACE characters regexp.
278 ;;
279 ;; `whitespace-hspace-regexp' Specify HARD SPACE characters regexp.
280 ;;
281 ;; `whitespace-tab-regexp' Specify TAB characters regexp.
282 ;;
283 ;; `whitespace-trailing-regexp' Specify trailing characters regexp.
284 ;;
285 ;; `whitespace-space-before-tab-regexp' Specify SPACEs before TAB
286 ;; regexp.
287 ;;
288 ;; `whitespace-indentation-regexp' Specify regexp for 8 or more
289 ;; SPACEs at beginning of line.
290 ;;
291 ;; `whitespace-big-indent-regexp' Specify big indentation at beginning of line
292 ;; regexp.
293 ;;
294 ;; `whitespace-empty-at-bob-regexp' Specify regexp for empty lines
295 ;; at beginning of buffer.
296 ;;
297 ;; `whitespace-empty-at-eob-regexp' Specify regexp for empty lines
298 ;; at end of buffer.
299 ;;
300 ;; `whitespace-space-after-tab-regexp' Specify regexp for 8 or more
301 ;; SPACEs after TAB.
302 ;;
303 ;; `whitespace-line-column' Specify column beyond which the line
304 ;; is highlighted.
305 ;;
306 ;; `whitespace-display-mappings' Specify an alist of mappings
307 ;; for displaying characters.
308 ;;
309 ;; `whitespace-global-modes' Modes for which global
310 ;; `whitespace-mode' is automagically
311 ;; turned on.
312 ;;
313 ;; `whitespace-action' Specify which action is taken when a
314 ;; buffer is visited or written.
315 ;;
316 ;;
317 ;; Acknowledgments
318 ;; ---------------
319 ;;
320 ;; Thanks to felix (EmacsWiki) for keeping highlight when switching between
321 ;; major modes on a file.
322 ;;
323 ;; Thanks to David Reitter <david.reitter@gmail.com> for suggesting a
324 ;; `whitespace-newline' initialization with low contrast relative to
325 ;; the background color.
326 ;;
327 ;; Thanks to Stephen Deasey <sdeasey@gmail.com> for the
328 ;; `indent-tabs-mode' usage suggestion.
329 ;;
330 ;; Thanks to Eric Cooper <ecc@cmu.edu> for the suggestion to have hook
331 ;; actions when buffer is written as the original whitespace package
332 ;; had.
333 ;;
334 ;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
335 ;; lines tail. See EightyColumnRule (EmacsWiki).
336 ;;
337 ;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
338 ;; * `define-minor-mode'.
339 ;; * `global-whitespace-*' name for global commands.
340 ;;
341 ;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
342 ;;
343 ;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
344 ;; suggestion.
345 ;;
346 ;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
347 ;; helping to fix `find-file-hooks' reference.
348 ;;
349 ;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
350 ;; indicating defface byte-compilation warnings.
351 ;;
352 ;; Thanks to Tim O'Callaghan (EmacsWiki) for the idea about highlight
353 ;; "long" lines. See EightyColumnRule (EmacsWiki).
354 ;;
355 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
356 ;; NEWLINE character mapping.
357 ;;
358 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
359 ;; whitespace-mode.el on XEmacs.
360 ;;
361 ;; Thanks to Miles Bader <miles@gnu.org> for handling display table via
362 ;; visws.el (his code was modified, but the main idea was kept).
363 ;;
364 ;; Thanks to:
365 ;; Rajesh Vaidheeswarran <rv@gnu.org> (original) whitespace.el
366 ;; Aurelien Tisne <aurelien.tisne@free.fr> show-whitespace-mode.el
367 ;; Lawrence Mitchell <wence@gmx.li> whitespace-mode.el
368 ;; Miles Bader <miles@gnu.org> visws.el
369 ;; And to all people who contributed with them.
370 ;;
371 ;;
372 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
373
374 ;;; code:
375
376 \f
377 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
378 ;;;; User Variables:
379
380
381 ;;; Interface to the command system
382
383
384 (defgroup whitespace nil
385 "Visualize blanks (TAB, (HARD) SPACE and NEWLINE)."
386 :link '(emacs-library-link :tag "Source Lisp File" "whitespace.el")
387 :version "23.1"
388 :group 'convenience)
389
390
391 (defcustom whitespace-style
392 '(face
393 tabs spaces trailing lines space-before-tab newline
394 indentation empty space-after-tab
395 space-mark tab-mark newline-mark)
396 "Specify which kind of blank is visualized.
397
398 It's a list containing some or all of the following values:
399
400 face enable all visualization via faces (see below).
401
402 trailing trailing blanks are visualized via faces.
403 It has effect only if `face' (see above)
404 is present in `whitespace-style'.
405
406 tabs TABs are visualized via faces.
407 It has effect only if `face' (see above)
408 is present in `whitespace-style'.
409
410 spaces SPACEs and HARD SPACEs are visualized via
411 faces.
412 It has effect only if `face' (see above)
413 is present in `whitespace-style'.
414
415 lines lines which have columns beyond
416 `whitespace-line-column' are highlighted via
417 faces.
418 Whole line is highlighted.
419 It has precedence over `lines-tail' (see
420 below).
421 It has effect only if `face' (see above)
422 is present in `whitespace-style'.
423
424 lines-tail lines which have columns beyond
425 `whitespace-line-column' are highlighted via
426 faces.
427 But only the part of line which goes
428 beyond `whitespace-line-column' column.
429 It has effect only if `lines' (see above)
430 is not present in `whitespace-style'
431 and if `face' (see above) is present in
432 `whitespace-style'.
433
434 newline NEWLINEs are visualized via faces.
435 It has effect only if `face' (see above)
436 is present in `whitespace-style'.
437
438 empty empty lines at beginning and/or end of buffer
439 are visualized via faces.
440 It has effect only if `face' (see above)
441 is present in `whitespace-style'.
442
443 indentation::tab 8 or more SPACEs at beginning of line are
444 visualized via faces.
445 It has effect only if `face' (see above)
446 is present in `whitespace-style'.
447
448 indentation::space TABs at beginning of line are visualized via
449 faces.
450 It has effect only if `face' (see above)
451 is present in `whitespace-style'.
452
453 indentation 8 or more SPACEs at beginning of line are
454 visualized, if `indent-tabs-mode' (which see)
455 is non-nil; otherwise, TABs at beginning of
456 line are visualized via faces.
457 It has effect only if `face' (see above)
458 is present in `whitespace-style'.
459
460 big-indent Big indentations are visualized via faces.
461 It has effect only if `face' (see above)
462 is present in `whitespace-style'.
463
464 space-after-tab::tab 8 or more SPACEs after a TAB are
465 visualized via faces.
466 It has effect only if `face' (see above)
467 is present in `whitespace-style'.
468
469 space-after-tab::space TABs are visualized when 8 or more
470 SPACEs occur after a TAB, via faces.
471 It has effect only if `face' (see above)
472 is present in `whitespace-style'.
473
474 space-after-tab 8 or more SPACEs after a TAB are
475 visualized, if `indent-tabs-mode'
476 (which see) is non-nil; otherwise,
477 the TABs are visualized via faces.
478 It has effect only if `face' (see above)
479 is present in `whitespace-style'.
480
481 space-before-tab::tab SPACEs before TAB are visualized via
482 faces.
483 It has effect only if `face' (see above)
484 is present in `whitespace-style'.
485
486 space-before-tab::space TABs are visualized when SPACEs occur
487 before TAB, via faces.
488 It has effect only if `face' (see above)
489 is present in `whitespace-style'.
490
491 space-before-tab SPACEs before TAB are visualized, if
492 `indent-tabs-mode' (which see) is
493 non-nil; otherwise, the TABs are
494 visualized via faces.
495 It has effect only if `face' (see above)
496 is present in `whitespace-style'.
497
498 space-mark SPACEs and HARD SPACEs are visualized via
499 display table.
500
501 tab-mark TABs are visualized via display table.
502
503 newline-mark NEWLINEs are visualized via display table.
504
505 Any other value is ignored.
506
507 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs via faces and
508 via display table.
509
510 There is an evaluation order for some values, if they are
511 included in `whitespace-style' list. For example, if
512 indentation, indentation::tab and/or indentation::space are
513 included in `whitespace-style' list. The evaluation order for
514 these values is:
515
516 * For indentation:
517 1. indentation
518 2. indentation::tab
519 3. indentation::space
520
521 * For SPACEs after TABs:
522 1. space-after-tab
523 2. space-after-tab::tab
524 3. space-after-tab::space
525
526 * For SPACEs before TABs:
527 1. space-before-tab
528 2. space-before-tab::tab
529 3. space-before-tab::space
530
531 So, for example, if indentation and indentation::space are
532 included in `whitespace-style' list, the indentation value is
533 evaluated instead of indentation::space value.
534
535 One reason for not visualize spaces via faces (if `face' is not
536 included in `whitespace-style') is to use exclusively for
537 cleaning up a buffer. See `whitespace-cleanup' and
538 `whitespace-cleanup-region' for documentation.
539
540 See also `whitespace-display-mappings' for documentation."
541 :type '(repeat :tag "Kind of Blank"
542 (choice :tag "Kind of Blank Face"
543 (const :tag "(Face) Face visualization"
544 face)
545 (const :tag "(Face) Trailing TABs, SPACEs and HARD SPACEs"
546 trailing)
547 (const :tag "(Face) SPACEs and HARD SPACEs"
548 spaces)
549 (const :tag "(Face) TABs" tabs)
550 (const :tag "(Face) Lines" lines)
551 (const :tag "(Face) SPACEs before TAB"
552 space-before-tab)
553 (const :tag "(Face) NEWLINEs" newline)
554 (const :tag "(Face) Indentation SPACEs"
555 indentation)
556 (const :tag "(Face) Too much line indentation"
557 big-indent)
558 (const :tag "(Face) Empty Lines At BOB And/Or EOB"
559 empty)
560 (const :tag "(Face) SPACEs after TAB"
561 space-after-tab)
562 (const :tag "(Mark) SPACEs and HARD SPACEs"
563 space-mark)
564 (const :tag "(Mark) TABs" tab-mark)
565 (const :tag "(Mark) NEWLINEs" newline-mark)))
566 :group 'whitespace)
567
568 (defvar whitespace-space 'whitespace-space
569 "Symbol face used to visualize SPACE.
570 Used when `whitespace-style' includes the value `spaces'.")
571 (make-obsolete-variable 'whitespace-space "use the face instead." "24.4")
572
573
574 (defface whitespace-space
575 '((((class color) (background dark))
576 :background "grey20" :foreground "darkgray")
577 (((class color) (background light))
578 :background "LightYellow" :foreground "lightgray")
579 (t :inverse-video t))
580 "Face used to visualize SPACE."
581 :group 'whitespace)
582
583
584 (defvar whitespace-hspace 'whitespace-hspace
585 "Symbol face used to visualize HARD SPACE.
586 Used when `whitespace-style' includes the value `spaces'.")
587 (make-obsolete-variable 'whitespace-hspace "use the face instead." "24.4")
588
589 (defface whitespace-hspace ; 'nobreak-space
590 '((((class color) (background dark))
591 :background "grey24" :foreground "darkgray")
592 (((class color) (background light))
593 :background "LemonChiffon3" :foreground "lightgray")
594 (t :inverse-video t))
595 "Face used to visualize HARD SPACE."
596 :group 'whitespace)
597
598
599 (defvar whitespace-tab 'whitespace-tab
600 "Symbol face used to visualize TAB.
601 Used when `whitespace-style' includes the value `tabs'.")
602 (make-obsolete-variable 'whitespace-tab "use the face instead." "24.4")
603
604 (defface whitespace-tab
605 '((((class color) (background dark))
606 :background "grey22" :foreground "darkgray")
607 (((class color) (background light))
608 :background "beige" :foreground "lightgray")
609 (t :inverse-video t))
610 "Face used to visualize TAB."
611 :group 'whitespace)
612
613
614 (defvar whitespace-newline 'whitespace-newline
615 "Symbol face used to visualize NEWLINE char mapping.
616 See `whitespace-display-mappings'.
617 Used when `whitespace-style' includes the values `newline-mark'
618 and `newline'.")
619 (make-obsolete-variable 'whitespace-newline "use the face instead." "24.4")
620
621 (defface whitespace-newline
622 '((default :weight normal)
623 (((class color) (background dark)) :foreground "darkgray")
624 (((class color) (min-colors 88) (background light)) :foreground "lightgray")
625 ;; Displays with 16 colors use lightgray as background, so using a
626 ;; lightgray foreground makes the newline mark invisible.
627 (((class color) (background light)) :foreground "brown")
628 (t :underline t))
629 "Face used to visualize NEWLINE char mapping.
630
631 See `whitespace-display-mappings'."
632 :group 'whitespace)
633
634
635 (defvar whitespace-trailing 'whitespace-trailing
636 "Symbol face used to visualize trailing blanks.
637 Used when `whitespace-style' includes the value `trailing'.")
638 (make-obsolete-variable 'whitespace-trailing "use the face instead." "24.4")
639
640 (defface whitespace-trailing ; 'trailing-whitespace
641 '((default :weight bold)
642 (((class mono)) :inverse-video t :underline t)
643 (t :background "red1" :foreground "yellow"))
644 "Face used to visualize trailing blanks."
645 :group 'whitespace)
646
647
648 (defvar whitespace-line 'whitespace-line
649 "Symbol face used to visualize \"long\" lines.
650 See `whitespace-line-column'.
651 Used when `whitespace-style' includes the value `line'.")
652 (make-obsolete-variable 'whitespace-line "use the face instead." "24.4")
653
654 (defface whitespace-line
655 '((((class mono)) :inverse-video t :weight bold :underline t)
656 (t :background "gray20" :foreground "violet"))
657 "Face used to visualize \"long\" lines.
658
659 See `whitespace-line-column'."
660 :group 'whitespace)
661
662
663 (defvar whitespace-space-before-tab 'whitespace-space-before-tab
664 "Symbol face used to visualize SPACEs before TAB.
665 Used when `whitespace-style' includes the value `space-before-tab'.")
666 (make-obsolete-variable 'whitespace-space-before-tab
667 "use the face instead." "24.4")
668
669 (defface whitespace-space-before-tab
670 '((((class mono)) :inverse-video t :weight bold :underline t)
671 (t :background "DarkOrange" :foreground "firebrick"))
672 "Face used to visualize SPACEs before TAB."
673 :group 'whitespace)
674
675
676 (defvar whitespace-indentation 'whitespace-indentation
677 "Symbol face used to visualize 8 or more SPACEs at beginning of line.
678 Used when `whitespace-style' includes the value `indentation'.")
679 (make-obsolete-variable 'whitespace-indentation "use the face instead." "24.4")
680
681 (defface whitespace-indentation
682 '((((class mono)) :inverse-video t :weight bold :underline t)
683 (t :background "yellow" :foreground "firebrick"))
684 "Face used to visualize 8 or more SPACEs at beginning of line."
685 :group 'whitespace)
686
687 (defface whitespace-big-indent
688 '((((class mono)) :inverse-video t :weight bold :underline t)
689 (t :background "red" :foreground "firebrick"))
690 "Face used to visualize big indentation."
691 :group 'whitespace)
692
693
694 (defvar whitespace-empty 'whitespace-empty
695 "Symbol face used to visualize empty lines at beginning and/or end of buffer.
696 Used when `whitespace-style' includes the value `empty'.")
697 (make-obsolete-variable 'whitespace-empty "use the face instead." "24.4")
698
699 (defface whitespace-empty
700 '((((class mono)) :inverse-video t :weight bold :underline t)
701 (t :background "yellow" :foreground "firebrick"))
702 "Face used to visualize empty lines at beginning and/or end of buffer."
703 :group 'whitespace)
704
705
706 (defvar whitespace-space-after-tab 'whitespace-space-after-tab
707 "Symbol face used to visualize 8 or more SPACEs after TAB.
708 Used when `whitespace-style' includes the value `space-after-tab'.")
709 (make-obsolete-variable 'whitespace-space-after-tab
710 "use the face instead." "24.4")
711
712 (defface whitespace-space-after-tab
713 '((((class mono)) :inverse-video t :weight bold :underline t)
714 (t :background "yellow" :foreground "firebrick"))
715 "Face used to visualize 8 or more SPACEs after TAB."
716 :group 'whitespace)
717
718
719 (defcustom whitespace-hspace-regexp
720 "\\(\u00A0+\\)"
721 "Specify HARD SPACE characters regexp.
722
723 Here are some examples:
724
725 \"\\\\(^\\xA0+\\\\)\" \
726 visualize only leading HARD SPACEs.
727 \"\\\\(\\xA0+$\\\\)\" \
728 visualize only trailing HARD SPACEs.
729 \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\" \
730 visualize leading and/or trailing HARD SPACEs.
731 \"\\t\\\\(\\xA0+\\\\)\\t\" \
732 visualize only HARD SPACEs between TABs.
733
734 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
735 Use exactly one pair of enclosing \\\\( and \\\\).
736
737 Used when `whitespace-style' includes `spaces'."
738 :type '(regexp :tag "HARD SPACE Chars")
739 :group 'whitespace)
740
741
742 (defcustom whitespace-space-regexp "\\( +\\)"
743 "Specify SPACE characters regexp.
744
745 If you're using `mule' package, there may be other characters
746 besides \" \" that should be considered SPACE.
747
748 Here are some examples:
749
750 \"\\\\(^ +\\\\)\" visualize only leading SPACEs.
751 \"\\\\( +$\\\\)\" visualize only trailing SPACEs.
752 \"\\\\(^ +\\\\| +$\\\\)\" \
753 visualize leading and/or trailing SPACEs.
754 \"\\t\\\\( +\\\\)\\t\" visualize only SPACEs between TABs.
755
756 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
757 Use exactly one pair of enclosing \\\\( and \\\\).
758
759 Used when `whitespace-style' includes `spaces'."
760 :type '(regexp :tag "SPACE Chars")
761 :group 'whitespace)
762
763
764 (defcustom whitespace-tab-regexp "\\(\t+\\)"
765 "Specify TAB characters regexp.
766
767 If you're using `mule' package, there may be other characters
768 besides \"\\t\" that should be considered TAB.
769
770 Here are some examples:
771
772 \"\\\\(^\\t+\\\\)\" visualize only leading TABs.
773 \"\\\\(\\t+$\\\\)\" visualize only trailing TABs.
774 \"\\\\(^\\t+\\\\|\\t+$\\\\)\" \
775 visualize leading and/or trailing TABs.
776 \" \\\\(\\t+\\\\) \" visualize only TABs between SPACEs.
777
778 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
779 Use exactly one pair of enclosing \\\\( and \\\\).
780
781 Used when `whitespace-style' includes `tabs'."
782 :type '(regexp :tag "TAB Chars")
783 :group 'whitespace)
784
785
786 (defcustom whitespace-trailing-regexp
787 "\\([\t \u00A0]+\\)$"
788 "Specify trailing characters regexp.
789
790 There may be other characters besides:
791
792 \" \" \"\\t\" \"\\u00A0\"
793
794 that should be considered blank.
795
796 NOTE: Enclose always by \"\\\\(\" and \"\\\\)$\" the elements to highlight.
797 Use exactly one pair of enclosing elements above.
798
799 Used when `whitespace-style' includes `trailing'."
800 :type '(regexp :tag "Trailing Chars")
801 :group 'whitespace)
802
803
804 (defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
805 "Specify SPACEs before TAB regexp.
806
807 Used when `whitespace-style' includes `space-before-tab',
808 `space-before-tab::tab' or `space-before-tab::space'."
809 :type '(regexp :tag "SPACEs Before TAB")
810 :group 'whitespace)
811
812
813 (defcustom whitespace-indentation-regexp
814 '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
815 . "^ *\\(\t+\\)[^\n]")
816 "Specify regexp for 8 or more SPACEs at beginning of line.
817
818 It is a cons where the cons car is used for SPACEs visualization
819 and the cons cdr is used for TABs visualization.
820
821 Used when `whitespace-style' includes `indentation',
822 `indentation::tab' or `indentation::space'."
823 :type '(cons (string :tag "Indentation SPACEs")
824 (string :tag "Indentation TABs"))
825 :group 'whitespace)
826
827
828 (defcustom whitespace-empty-at-bob-regexp "^\\(\\([ \t]*\n\\)+\\)"
829 "Specify regexp for empty lines at beginning of buffer.
830
831 Used when `whitespace-style' includes `empty'."
832 :type '(regexp :tag "Empty Lines At Beginning Of Buffer")
833 :group 'whitespace)
834
835
836 (defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)"
837 "Specify regexp for empty lines at end of buffer.
838
839 Used when `whitespace-style' includes `empty'."
840 :type '(regexp :tag "Empty Lines At End Of Buffer")
841 :group 'whitespace)
842
843
844 (defcustom whitespace-space-after-tab-regexp
845 '("\t+\\(\\( \\{%d\\}\\)+\\)"
846 . "\\(\t+\\) +")
847 "Specify regexp for 8 or more SPACEs after TAB.
848
849 It is a cons where the cons car is used for SPACEs visualization
850 and the cons cdr is used for TABs visualization.
851
852 Used when `whitespace-style' includes `space-after-tab',
853 `space-after-tab::tab' or `space-after-tab::space'."
854 :type '(cons (string :tag "SPACEs After TAB")
855 string)
856 :group 'whitespace)
857
858 (defcustom whitespace-big-indent-regexp
859 "^\\(\\(?:\t\\{4,\\}\\| \\{32,\\}\\)[\t ]*\\)"
860 "Specify big indentation regexp.
861
862 If you're using `mule' package, there may be other characters
863 besides \"\\t\" that should be considered TAB.
864
865 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
866 Use exactly one pair of enclosing \\\\( and \\\\).
867
868 Used when `whitespace-style' includes `big-indent'."
869 :type '(regexp :tag "Detect too much indentation at the beginning of a line")
870 :group 'whitespace)
871
872
873 (defcustom whitespace-line-column 80
874 "Specify column beyond which the line is highlighted.
875
876 It must be an integer or nil. If nil, the `fill-column' variable value is
877 used.
878
879 Used when `whitespace-style' includes `lines' or `lines-tail'."
880 :type '(choice :tag "Line Length Limit"
881 (integer :tag "Line Length")
882 (const :tag "Use fill-column" nil))
883 :group 'whitespace)
884
885
886 ;; Hacked from `visible-whitespace-mappings' in visws.el
887 (defcustom whitespace-display-mappings
888 '(
889 (space-mark ?\ [?\u00B7] [?.]) ; space - centered dot
890 (space-mark ?\xA0 [?\u00A4] [?_]) ; hard space - currency
891 ;; NEWLINE is displayed using the face `whitespace-newline'
892 (newline-mark ?\n [?$ ?\n]) ; eol - dollar sign
893 ;; (newline-mark ?\n [?\u21B5 ?\n] [?$ ?\n]) ; eol - downwards arrow
894 ;; (newline-mark ?\n [?\u00B6 ?\n] [?$ ?\n]) ; eol - pilcrow
895 ;; (newline-mark ?\n [?\u00AF ?\n] [?$ ?\n]) ; eol - overscore
896 ;; (newline-mark ?\n [?\u00AC ?\n] [?$ ?\n]) ; eol - negation
897 ;; (newline-mark ?\n [?\u00B0 ?\n] [?$ ?\n]) ; eol - degrees
898 ;;
899 ;; WARNING: the mapping below has a problem.
900 ;; When a TAB occupies exactly one column, it will display the
901 ;; character ?\xBB at that column followed by a TAB which goes to
902 ;; the next TAB column.
903 ;; If this is a problem for you, please, comment the line below.
904 (tab-mark ?\t [?\u00BB ?\t] [?\\ ?\t]) ; tab - left quote mark
905 )
906 "Specify an alist of mappings for displaying characters.
907
908 Each element has the following form:
909
910 (KIND CHAR VECTOR...)
911
912 Where:
913
914 KIND is the kind of character.
915 It can be one of the following symbols:
916
917 tab-mark for TAB character
918
919 space-mark for SPACE or HARD SPACE character
920
921 newline-mark for NEWLINE character
922
923 CHAR is the character to be mapped.
924
925 VECTOR is a vector of characters to be displayed in place of CHAR.
926 The first display vector that can be displayed is used;
927 if no display vector for a mapping can be displayed, then
928 that character is displayed unmodified.
929
930 The NEWLINE character is displayed using the face given by
931 `whitespace-newline' variable.
932
933 Used when `whitespace-style' includes `tab-mark', `space-mark' or
934 `newline-mark'."
935 :type '(repeat
936 (list :tag "Character Mapping"
937 (choice :tag "Char Kind"
938 (const :tag "Tab" tab-mark)
939 (const :tag "Space" space-mark)
940 (const :tag "Newline" newline-mark))
941 (character :tag "Char")
942 (repeat :inline t :tag "Vector List"
943 (vector :tag ""
944 (repeat :inline t
945 :tag "Vector Characters"
946 (character :tag "Char"))))))
947 :group 'whitespace)
948
949
950 (defcustom whitespace-global-modes t
951 "Modes for which global `whitespace-mode' is automagically turned on.
952
953 Global `whitespace-mode' is controlled by the command
954 `global-whitespace-mode'.
955
956 If nil, means no modes have `whitespace-mode' automatically
957 turned on.
958
959 If t, all modes that support `whitespace-mode' have it
960 automatically turned on.
961
962 Else it should be a list of `major-mode' symbol names for which
963 `whitespace-mode' should be automatically turned on. The sense
964 of the list is negated if it begins with `not'. For example:
965
966 (c-mode c++-mode)
967
968 means that `whitespace-mode' is turned on for buffers in C and
969 C++ modes only."
970 :type '(choice :tag "Global Modes"
971 (const :tag "None" nil)
972 (const :tag "All" t)
973 (set :menu-tag "Mode Specific" :tag "Modes"
974 :value (not)
975 (const :tag "Except" not)
976 (repeat :inline t
977 (symbol :tag "Mode"))))
978 :group 'whitespace)
979
980
981 (defcustom whitespace-action nil
982 "Specify which action is taken when a buffer is visited or written.
983
984 It's a list containing some or all of the following values:
985
986 nil no action is taken.
987
988 cleanup cleanup any bogus whitespace always when local
989 whitespace is turned on.
990 See `whitespace-cleanup' and
991 `whitespace-cleanup-region'.
992
993 report-on-bogus report if there is any bogus whitespace always
994 when local whitespace is turned on.
995
996 auto-cleanup cleanup any bogus whitespace when buffer is
997 written.
998 See `whitespace-cleanup' and
999 `whitespace-cleanup-region'.
1000
1001 abort-on-bogus abort if there is any bogus whitespace and the
1002 buffer is written.
1003
1004 warn-if-read-only give a warning if `cleanup' or `auto-cleanup'
1005 is included in `whitespace-action' and the
1006 buffer is read-only.
1007
1008 Any other value is treated as nil."
1009 :type '(choice :tag "Actions"
1010 (const :tag "None" nil)
1011 (repeat :tag "Action List"
1012 (choice :tag "Action"
1013 (const :tag "Cleanup When On" cleanup)
1014 (const :tag "Report On Bogus" report-on-bogus)
1015 (const :tag "Auto Cleanup" auto-cleanup)
1016 (const :tag "Abort On Bogus" abort-on-bogus)
1017 (const :tag "Warn If Read-Only" warn-if-read-only))))
1018 :group 'whitespace)
1019
1020 \f
1021 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1022 ;;;; User commands - Local mode
1023
1024
1025 ;;;###autoload
1026 (define-minor-mode whitespace-mode
1027 "Toggle whitespace visualization (Whitespace mode).
1028 With a prefix argument ARG, enable Whitespace mode if ARG is
1029 positive, and disable it otherwise. If called from Lisp, enable
1030 the mode if ARG is omitted or nil.
1031
1032 See also `whitespace-style', `whitespace-newline' and
1033 `whitespace-display-mappings'."
1034 :lighter " ws"
1035 :init-value nil
1036 :global nil
1037 :group 'whitespace
1038 (cond
1039 (noninteractive ; running a batch job
1040 (setq whitespace-mode nil))
1041 (whitespace-mode ; whitespace-mode on
1042 (whitespace-turn-on)
1043 (whitespace-action-when-on))
1044 (t ; whitespace-mode off
1045 (whitespace-turn-off))))
1046
1047
1048 ;;;###autoload
1049 (define-minor-mode whitespace-newline-mode
1050 "Toggle newline visualization (Whitespace Newline mode).
1051 With a prefix argument ARG, enable Whitespace Newline mode if ARG
1052 is positive, and disable it otherwise. If called from Lisp,
1053 enable the mode if ARG is omitted or nil.
1054
1055 Use `whitespace-newline-mode' only for NEWLINE visualization
1056 exclusively. For other visualizations, including NEWLINE
1057 visualization together with (HARD) SPACEs and/or TABs, please,
1058 use `whitespace-mode'.
1059
1060 See also `whitespace-newline' and `whitespace-display-mappings'."
1061 :lighter " nl"
1062 :init-value nil
1063 :global nil
1064 :group 'whitespace
1065 (let ((whitespace-style '(face newline-mark newline)))
1066 (whitespace-mode (if whitespace-newline-mode
1067 1 -1)))
1068 ;; sync states (running a batch job)
1069 (setq whitespace-newline-mode whitespace-mode))
1070
1071 \f
1072 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1073 ;;;; User commands - Global mode
1074
1075
1076 ;;;###autoload
1077 (define-minor-mode global-whitespace-mode
1078 "Toggle whitespace visualization globally (Global Whitespace mode).
1079 With a prefix argument ARG, enable Global Whitespace mode if ARG
1080 is positive, and disable it otherwise. If called from Lisp,
1081 enable it if ARG is omitted or nil.
1082
1083 See also `whitespace-style', `whitespace-newline' and
1084 `whitespace-display-mappings'."
1085 :lighter " WS"
1086 :init-value nil
1087 :global t
1088 :group 'whitespace
1089 (cond
1090 (noninteractive ; running a batch job
1091 (setq global-whitespace-mode nil))
1092 (global-whitespace-mode ; global-whitespace-mode on
1093 (save-current-buffer
1094 (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
1095 (add-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
1096 (dolist (buffer (buffer-list)) ; adjust all local mode
1097 (set-buffer buffer)
1098 (unless whitespace-mode
1099 (whitespace-turn-on-if-enabled)))))
1100 (t ; global-whitespace-mode off
1101 (save-current-buffer
1102 (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
1103 (remove-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
1104 (dolist (buffer (buffer-list)) ; adjust all local mode
1105 (set-buffer buffer)
1106 (unless whitespace-mode
1107 (whitespace-turn-off)))))))
1108
1109 (defvar whitespace-enable-predicate
1110 (lambda ()
1111 (and (cond
1112 ((eq whitespace-global-modes t))
1113 ((listp whitespace-global-modes)
1114 (if (eq (car-safe whitespace-global-modes) 'not)
1115 (not (memq major-mode (cdr whitespace-global-modes)))
1116 (memq major-mode whitespace-global-modes)))
1117 (t nil))
1118 ;; ...we have a display (not running a batch job)
1119 (not noninteractive)
1120 ;; ...the buffer is not internal (name starts with a space)
1121 (not (eq (aref (buffer-name) 0) ?\ ))
1122 ;; ...the buffer is not special (name starts with *)
1123 (or (not (eq (aref (buffer-name) 0) ?*))
1124 ;; except the scratch buffer.
1125 (string= (buffer-name) "*scratch*"))))
1126 "Predicate to decide which buffers obey `global-whitespace-mode'.
1127 This function is called with no argument and should return non-nil
1128 if the current buffer should obey `global-whitespace-mode'.
1129 This variable is normally modified via `add-function'.")
1130
1131 (defun whitespace-turn-on-if-enabled ()
1132 (when (funcall whitespace-enable-predicate)
1133 (whitespace-turn-on)))
1134
1135 ;;;###autoload
1136 (define-minor-mode global-whitespace-newline-mode
1137 "Toggle global newline visualization (Global Whitespace Newline mode).
1138 With a prefix argument ARG, enable Global Whitespace Newline mode
1139 if ARG is positive, and disable it otherwise. If called from
1140 Lisp, enable it if ARG is omitted or nil.
1141
1142 Use `global-whitespace-newline-mode' only for NEWLINE
1143 visualization exclusively. For other visualizations, including
1144 NEWLINE visualization together with (HARD) SPACEs and/or TABs,
1145 please use `global-whitespace-mode'.
1146
1147 See also `whitespace-newline' and `whitespace-display-mappings'."
1148 :lighter " NL"
1149 :init-value nil
1150 :global t
1151 :group 'whitespace
1152 (let ((whitespace-style '(newline-mark newline)))
1153 (global-whitespace-mode (if global-whitespace-newline-mode
1154 1 -1))
1155 ;; sync states (running a batch job)
1156 (setq global-whitespace-newline-mode global-whitespace-mode)))
1157
1158 \f
1159 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1160 ;;;; User commands - Toggle
1161
1162
1163 (defconst whitespace-style-value-list
1164 '(face
1165 tabs
1166 spaces
1167 trailing
1168 lines
1169 lines-tail
1170 newline
1171 empty
1172 indentation
1173 indentation::tab
1174 indentation::space
1175 big-indent
1176 space-after-tab
1177 space-after-tab::tab
1178 space-after-tab::space
1179 space-before-tab
1180 space-before-tab::tab
1181 space-before-tab::space
1182 help-newline ; value used by `whitespace-insert-option-mark'
1183 tab-mark
1184 space-mark
1185 newline-mark
1186 )
1187 "List of valid `whitespace-style' values.")
1188
1189
1190 (defconst whitespace-toggle-option-alist
1191 '((?f . face)
1192 (?t . tabs)
1193 (?s . spaces)
1194 (?r . trailing)
1195 (?l . lines)
1196 (?L . lines-tail)
1197 (?n . newline)
1198 (?e . empty)
1199 (?\C-i . indentation)
1200 (?I . indentation::tab)
1201 (?i . indentation::space)
1202 (?\C-t . big-indent)
1203 (?\C-a . space-after-tab)
1204 (?A . space-after-tab::tab)
1205 (?a . space-after-tab::space)
1206 (?\C-b . space-before-tab)
1207 (?B . space-before-tab::tab)
1208 (?b . space-before-tab::space)
1209 (?T . tab-mark)
1210 (?S . space-mark)
1211 (?N . newline-mark)
1212 (?x . whitespace-style)
1213 )
1214 "Alist of toggle options.
1215
1216 Each element has the form:
1217
1218 (CHAR . SYMBOL)
1219
1220 Where:
1221
1222 CHAR is a char which the user will have to type.
1223
1224 SYMBOL is a valid symbol associated with CHAR.
1225 See `whitespace-style-value-list'.")
1226
1227
1228 (defvar whitespace-active-style nil
1229 "Used to save locally `whitespace-style' value.")
1230
1231 (defvar whitespace-indent-tabs-mode indent-tabs-mode
1232 "Used to save locally `indent-tabs-mode' value.")
1233
1234 (defvar whitespace-tab-width tab-width
1235 "Used to save locally `tab-width' value.")
1236
1237 (defvar whitespace-point (point)
1238 "Used to save locally current point value.
1239 Used by function `whitespace-trailing-regexp' (which see).")
1240 (defvar-local whitespace-point--used nil
1241 "Region whose highlighting depends on `whitespace-point'.")
1242
1243 (defvar whitespace-font-lock-refontify nil
1244 "Used to save locally the font-lock refontify state.
1245 Used by function `whitespace-post-command-hook' (which see).")
1246
1247 (defvar whitespace-bob-marker nil
1248 "Used to save locally the bob marker value.
1249 Used by function `whitespace-post-command-hook' (which see).")
1250
1251 (defvar whitespace-eob-marker nil
1252 "Used to save locally the eob marker value.
1253 Used by function `whitespace-post-command-hook' (which see).")
1254
1255 (defvar whitespace-buffer-changed nil
1256 "Used to indicate locally if buffer changed.
1257 Used by `whitespace-post-command-hook' and `whitespace-buffer-changed'
1258 functions (which see).")
1259
1260
1261 ;;;###autoload
1262 (defun whitespace-toggle-options (arg)
1263 "Toggle local `whitespace-mode' options.
1264
1265 If local whitespace-mode is off, toggle the option given by ARG
1266 and turn on local whitespace-mode.
1267
1268 If local whitespace-mode is on, toggle the option given by ARG
1269 and restart local whitespace-mode.
1270
1271 Interactively, it reads one of the following chars:
1272
1273 CHAR MEANING
1274 (VIA FACES)
1275 f toggle face visualization
1276 t toggle TAB visualization
1277 s toggle SPACE and HARD SPACE visualization
1278 r toggle trailing blanks visualization
1279 l toggle \"long lines\" visualization
1280 L toggle \"long lines\" tail visualization
1281 n toggle NEWLINE visualization
1282 e toggle empty line at bob and/or eob visualization
1283 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1284 I toggle indentation SPACEs visualization
1285 i toggle indentation TABs visualization
1286 C-t toggle big indentation visualization
1287 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1288 A toggle SPACEs after TAB: SPACEs visualization
1289 a toggle SPACEs after TAB: TABs visualization
1290 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1291 B toggle SPACEs before TAB: SPACEs visualization
1292 b toggle SPACEs before TAB: TABs visualization
1293
1294 (VIA DISPLAY TABLE)
1295 T toggle TAB visualization
1296 S toggle SPACEs before TAB visualization
1297 N toggle NEWLINE visualization
1298
1299 x restore `whitespace-style' value
1300 ? display brief help
1301
1302 Non-interactively, ARG should be a symbol or a list of symbols.
1303 The valid symbols are:
1304
1305 face toggle face visualization
1306 tabs toggle TAB visualization
1307 spaces toggle SPACE and HARD SPACE visualization
1308 trailing toggle trailing blanks visualization
1309 lines toggle \"long lines\" visualization
1310 lines-tail toggle \"long lines\" tail visualization
1311 newline toggle NEWLINE visualization
1312 empty toggle empty line at bob and/or eob visualization
1313 indentation toggle indentation SPACEs visualization
1314 indentation::tab toggle indentation SPACEs visualization
1315 indentation::space toggle indentation TABs visualization
1316 big-indent toggle big indentation visualization
1317 space-after-tab toggle SPACEs after TAB visualization
1318 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1319 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1320 space-before-tab toggle SPACEs before TAB visualization
1321 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1322 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1323
1324 tab-mark toggle TAB visualization
1325 space-mark toggle SPACEs before TAB visualization
1326 newline-mark toggle NEWLINE visualization
1327
1328 whitespace-style restore `whitespace-style' value
1329
1330 See `whitespace-style' and `indent-tabs-mode' for documentation."
1331 (interactive (whitespace-interactive-char t))
1332 (let ((whitespace-style
1333 (whitespace-toggle-list t arg whitespace-active-style)))
1334 (whitespace-mode 0)
1335 (whitespace-mode 1)))
1336
1337
1338 (defvar whitespace-toggle-style nil
1339 "Used to toggle the global `whitespace-style' value.")
1340
1341
1342 ;;;###autoload
1343 (defun global-whitespace-toggle-options (arg)
1344 "Toggle global `whitespace-mode' options.
1345
1346 If global whitespace-mode is off, toggle the option given by ARG
1347 and turn on global whitespace-mode.
1348
1349 If global whitespace-mode is on, toggle the option given by ARG
1350 and restart global whitespace-mode.
1351
1352 Interactively, it accepts one of the following chars:
1353
1354 CHAR MEANING
1355 (VIA FACES)
1356 f toggle face visualization
1357 t toggle TAB visualization
1358 s toggle SPACE and HARD SPACE visualization
1359 r toggle trailing blanks visualization
1360 l toggle \"long lines\" visualization
1361 L toggle \"long lines\" tail visualization
1362 n toggle NEWLINE visualization
1363 e toggle empty line at bob and/or eob visualization
1364 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1365 I toggle indentation SPACEs visualization
1366 i toggle indentation TABs visualization
1367 C-t toggle big indentation visualization
1368 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1369 A toggle SPACEs after TAB: SPACEs visualization
1370 a toggle SPACEs after TAB: TABs visualization
1371 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1372 B toggle SPACEs before TAB: SPACEs visualization
1373 b toggle SPACEs before TAB: TABs visualization
1374
1375 (VIA DISPLAY TABLE)
1376 T toggle TAB visualization
1377 S toggle SPACEs before TAB visualization
1378 N toggle NEWLINE visualization
1379
1380 x restore `whitespace-style' value
1381 ? display brief help
1382
1383 Non-interactively, ARG should be a symbol or a list of symbols.
1384 The valid symbols are:
1385
1386 face toggle face visualization
1387 tabs toggle TAB visualization
1388 spaces toggle SPACE and HARD SPACE visualization
1389 trailing toggle trailing blanks visualization
1390 lines toggle \"long lines\" visualization
1391 lines-tail toggle \"long lines\" tail visualization
1392 newline toggle NEWLINE visualization
1393 empty toggle empty line at bob and/or eob visualization
1394 indentation toggle indentation SPACEs visualization
1395 indentation::tab toggle indentation SPACEs visualization
1396 indentation::space toggle indentation TABs visualization
1397 big-indent toggle big indentation visualization
1398 space-after-tab toggle SPACEs after TAB visualization
1399 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1400 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1401 space-before-tab toggle SPACEs before TAB visualization
1402 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1403 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1404
1405 tab-mark toggle TAB visualization
1406 space-mark toggle SPACEs before TAB visualization
1407 newline-mark toggle NEWLINE visualization
1408
1409 whitespace-style restore `whitespace-style' value
1410
1411 See `whitespace-style' and `indent-tabs-mode' for documentation."
1412 (interactive (whitespace-interactive-char nil))
1413 (let ((whitespace-style
1414 (whitespace-toggle-list nil arg whitespace-toggle-style)))
1415 (setq whitespace-toggle-style whitespace-style)
1416 (global-whitespace-mode 0)
1417 (global-whitespace-mode 1)))
1418
1419 \f
1420 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1421 ;;;; User commands - Cleanup
1422
1423
1424 ;;;###autoload
1425 (defun whitespace-cleanup ()
1426 "Cleanup some blank problems in all buffer or at region.
1427
1428 It usually applies to the whole buffer, but in transient mark
1429 mode when the mark is active, it applies to the region. It also
1430 applies to the region when it is not in transient mark mode, the
1431 mark is active and \\[universal-argument] was pressed just before
1432 calling `whitespace-cleanup' interactively.
1433
1434 See also `whitespace-cleanup-region'.
1435
1436 The problems cleaned up are:
1437
1438 1. empty lines at beginning of buffer.
1439 2. empty lines at end of buffer.
1440 If `whitespace-style' includes the value `empty', remove all
1441 empty lines at beginning and/or end of buffer.
1442
1443 3. 8 or more SPACEs at beginning of line.
1444 If `whitespace-style' includes the value `indentation':
1445 replace 8 or more SPACEs at beginning of line by TABs, if
1446 `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1447 SPACEs.
1448 If `whitespace-style' includes the value `indentation::tab',
1449 replace 8 or more SPACEs at beginning of line by TABs.
1450 If `whitespace-style' includes the value `indentation::space',
1451 replace TABs by SPACEs.
1452
1453 4. SPACEs before TAB.
1454 If `whitespace-style' includes the value `space-before-tab':
1455 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1456 otherwise, replace TABs by SPACEs.
1457 If `whitespace-style' includes the value
1458 `space-before-tab::tab', replace SPACEs by TABs.
1459 If `whitespace-style' includes the value
1460 `space-before-tab::space', replace TABs by SPACEs.
1461
1462 5. SPACEs or TABs at end of line.
1463 If `whitespace-style' includes the value `trailing', remove
1464 all SPACEs or TABs at end of line.
1465
1466 6. 8 or more SPACEs after TAB.
1467 If `whitespace-style' includes the value `space-after-tab':
1468 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1469 otherwise, replace TABs by SPACEs.
1470 If `whitespace-style' includes the value
1471 `space-after-tab::tab', replace SPACEs by TABs.
1472 If `whitespace-style' includes the value
1473 `space-after-tab::space', replace TABs by SPACEs.
1474
1475 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1476 documentation."
1477 (interactive "@")
1478 (cond
1479 ;; read-only buffer
1480 (buffer-read-only
1481 (whitespace-warn-read-only "cleanup"))
1482 ;; region active
1483 ((and (or transient-mark-mode
1484 current-prefix-arg)
1485 mark-active)
1486 ;; PROBLEMs 1 and 2 are not handled in region
1487 ;; PROBLEM 3: 8 or more SPACEs at bol
1488 ;; PROBLEM 4: SPACEs before TAB
1489 ;; PROBLEM 5: SPACEs or TABs at eol
1490 ;; PROBLEM 6: 8 or more SPACEs after TAB
1491 (whitespace-cleanup-region (region-beginning) (region-end)))
1492 ;; whole buffer
1493 (t
1494 (save-excursion
1495 (save-match-data ;FIXME: Why?
1496 ;; PROBLEM 1: empty lines at bob
1497 ;; PROBLEM 2: empty lines at eob
1498 ;; ACTION: remove all empty lines at bob and/or eob
1499 (when (memq 'empty whitespace-style)
1500 (let (overwrite-mode) ; enforce no overwrite
1501 (goto-char (point-min))
1502 (when (looking-at whitespace-empty-at-bob-regexp)
1503 (delete-region (match-beginning 1) (match-end 1)))
1504 (when (re-search-forward
1505 (concat whitespace-empty-at-eob-regexp "\\'") nil t)
1506 (delete-region (match-beginning 1) (match-end 1)))))))
1507 ;; PROBLEM 3: 8 or more SPACEs at bol
1508 ;; PROBLEM 4: SPACEs before TAB
1509 ;; PROBLEM 5: SPACEs or TABs at eol
1510 ;; PROBLEM 6: 8 or more SPACEs after TAB
1511 (whitespace-cleanup-region (point-min) (point-max)))))
1512
1513 (defun whitespace-ensure-local-variables ()
1514 "Set `whitespace-indent-tabs-mode' and `whitespace-tab-width' locally."
1515 (set (make-local-variable 'whitespace-indent-tabs-mode)
1516 indent-tabs-mode)
1517 (set (make-local-variable 'whitespace-tab-width)
1518 tab-width))
1519
1520 ;;;###autoload
1521 (defun whitespace-cleanup-region (start end)
1522 "Cleanup some blank problems at region.
1523
1524 The problems cleaned up are:
1525
1526 1. 8 or more SPACEs at beginning of line.
1527 If `whitespace-style' includes the value `indentation':
1528 replace 8 or more SPACEs at beginning of line by TABs, if
1529 `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1530 SPACEs.
1531 If `whitespace-style' includes the value `indentation::tab',
1532 replace 8 or more SPACEs at beginning of line by TABs.
1533 If `whitespace-style' includes the value `indentation::space',
1534 replace TABs by SPACEs.
1535
1536 2. SPACEs before TAB.
1537 If `whitespace-style' includes the value `space-before-tab':
1538 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1539 otherwise, replace TABs by SPACEs.
1540 If `whitespace-style' includes the value
1541 `space-before-tab::tab', replace SPACEs by TABs.
1542 If `whitespace-style' includes the value
1543 `space-before-tab::space', replace TABs by SPACEs.
1544
1545 3. SPACEs or TABs at end of line.
1546 If `whitespace-style' includes the value `trailing', remove
1547 all SPACEs or TABs at end of line.
1548
1549 4. 8 or more SPACEs after TAB.
1550 If `whitespace-style' includes the value `space-after-tab':
1551 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1552 otherwise, replace TABs by SPACEs.
1553 If `whitespace-style' includes the value
1554 `space-after-tab::tab', replace SPACEs by TABs.
1555 If `whitespace-style' includes the value
1556 `space-after-tab::space', replace TABs by SPACEs.
1557
1558 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1559 documentation."
1560 (interactive "@r")
1561 (if buffer-read-only
1562 ;; read-only buffer
1563 (whitespace-warn-read-only "cleanup region")
1564 ;; non-read-only buffer
1565 (whitespace-ensure-local-variables)
1566 (let ((rstart (min start end))
1567 (rend (copy-marker (max start end)))
1568 (indent-tabs-mode whitespace-indent-tabs-mode)
1569 (tab-width whitespace-tab-width)
1570 overwrite-mode ; enforce no overwrite
1571 tmp)
1572 (save-excursion
1573 (save-match-data ;FIXME: Why?
1574 ;; PROBLEM 1: 8 or more SPACEs at bol
1575 (cond
1576 ;; ACTION: replace 8 or more SPACEs at bol by TABs, if
1577 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1578 ;; by SPACEs.
1579 ((memq 'indentation whitespace-style)
1580 (let ((regexp (whitespace-indentation-regexp)))
1581 (goto-char rstart)
1582 (while (re-search-forward regexp rend t)
1583 (setq tmp (current-indentation))
1584 (goto-char (match-beginning 0))
1585 (delete-horizontal-space)
1586 (unless (eolp)
1587 (indent-to tmp)))))
1588 ;; ACTION: replace 8 or more SPACEs at bol by TABs.
1589 ((memq 'indentation::tab whitespace-style)
1590 (whitespace-replace-action
1591 'tabify rstart rend
1592 (whitespace-indentation-regexp 'tab) 0))
1593 ;; ACTION: replace TABs by SPACEs.
1594 ((memq 'indentation::space whitespace-style)
1595 (whitespace-replace-action
1596 'untabify rstart rend
1597 (whitespace-indentation-regexp 'space) 0)))
1598 ;; PROBLEM 3: SPACEs or TABs at eol
1599 ;; ACTION: remove all SPACEs or TABs at eol
1600 (when (memq 'trailing whitespace-style)
1601 (whitespace-replace-action
1602 'delete-region rstart rend
1603 whitespace-trailing-regexp 1))
1604 ;; PROBLEM 4: 8 or more SPACEs after TAB
1605 (cond
1606 ;; ACTION: replace 8 or more SPACEs by TABs, if
1607 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1608 ;; by SPACEs.
1609 ((memq 'space-after-tab whitespace-style)
1610 (whitespace-replace-action
1611 (if whitespace-indent-tabs-mode 'tabify 'untabify)
1612 rstart rend (whitespace-space-after-tab-regexp) 1))
1613 ;; ACTION: replace 8 or more SPACEs by TABs.
1614 ((memq 'space-after-tab::tab whitespace-style)
1615 (whitespace-replace-action
1616 'tabify rstart rend
1617 (whitespace-space-after-tab-regexp 'tab) 1))
1618 ;; ACTION: replace TABs by SPACEs.
1619 ((memq 'space-after-tab::space whitespace-style)
1620 (whitespace-replace-action
1621 'untabify rstart rend
1622 (whitespace-space-after-tab-regexp 'space) 1)))
1623 ;; PROBLEM 2: SPACEs before TAB
1624 (cond
1625 ;; ACTION: replace SPACEs before TAB by TABs, if
1626 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1627 ;; by SPACEs.
1628 ((memq 'space-before-tab whitespace-style)
1629 (whitespace-replace-action
1630 (if whitespace-indent-tabs-mode 'tabify 'untabify)
1631 rstart rend whitespace-space-before-tab-regexp
1632 (if whitespace-indent-tabs-mode 0 2)))
1633 ;; ACTION: replace SPACEs before TAB by TABs.
1634 ((memq 'space-before-tab::tab whitespace-style)
1635 (whitespace-replace-action
1636 'tabify rstart rend
1637 whitespace-space-before-tab-regexp 0))
1638 ;; ACTION: replace TABs by SPACEs.
1639 ((memq 'space-before-tab::space whitespace-style)
1640 (whitespace-replace-action
1641 'untabify rstart rend
1642 whitespace-space-before-tab-regexp 2)))))
1643 (set-marker rend nil)))) ; point marker to nowhere
1644
1645
1646 (defun whitespace-replace-action (action rstart rend regexp index)
1647 "Do ACTION in the string matched by REGEXP between RSTART and REND.
1648
1649 INDEX is the level group matched by REGEXP and used by ACTION.
1650
1651 See also `tab-width'."
1652 (goto-char rstart)
1653 (while (re-search-forward regexp rend t)
1654 (goto-char (match-end index))
1655 (funcall action (match-beginning index) (match-end index))))
1656
1657 \f
1658 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1659 ;;;; User command - report
1660
1661
1662 (defun whitespace-regexp (regexp &optional kind)
1663 "Return REGEXP depending on `whitespace-indent-tabs-mode'."
1664 (cond
1665 ((or (eq kind 'tab)
1666 whitespace-indent-tabs-mode)
1667 (format (car regexp) whitespace-tab-width))
1668 ((or (eq kind 'space)
1669 (not whitespace-indent-tabs-mode))
1670 (cdr regexp))))
1671
1672
1673 (defun whitespace-indentation-regexp (&optional kind)
1674 "Return the indentation regexp depending on `whitespace-indent-tabs-mode'."
1675 (whitespace-regexp whitespace-indentation-regexp kind))
1676
1677
1678 (defun whitespace-space-after-tab-regexp (&optional kind)
1679 "Return the space-after-tab regexp depending on `whitespace-indent-tabs-mode'."
1680 (whitespace-regexp whitespace-space-after-tab-regexp kind))
1681
1682
1683 (defconst whitespace-report-list
1684 (list
1685 (cons 'empty whitespace-empty-at-bob-regexp)
1686 (cons 'empty whitespace-empty-at-eob-regexp)
1687 (cons 'trailing whitespace-trailing-regexp)
1688 (cons 'indentation nil)
1689 (cons 'indentation::tab nil)
1690 (cons 'indentation::space nil)
1691 (cons 'space-before-tab whitespace-space-before-tab-regexp)
1692 (cons 'space-before-tab::tab whitespace-space-before-tab-regexp)
1693 (cons 'space-before-tab::space whitespace-space-before-tab-regexp)
1694 (cons 'space-after-tab nil)
1695 (cons 'space-after-tab::tab nil)
1696 (cons 'space-after-tab::space nil)
1697 )
1698 "List of whitespace bogus symbol and corresponding regexp.")
1699
1700
1701 (defconst whitespace-report-text
1702 '( ;; `indent-tabs-mode' has non-nil value
1703 "\
1704 Whitespace Report
1705
1706 Current Setting Whitespace Problem
1707
1708 empty [] [] empty lines at beginning of buffer
1709 empty [] [] empty lines at end of buffer
1710 trailing [] [] SPACEs or TABs at end of line
1711 indentation [] [] 8 or more SPACEs at beginning of line
1712 indentation::tab [] [] 8 or more SPACEs at beginning of line
1713 indentation::space [] [] TABs at beginning of line
1714 space-before-tab [] [] SPACEs before TAB
1715 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1716 space-before-tab::space [] [] SPACEs before TAB: TABs
1717 space-after-tab [] [] 8 or more SPACEs after TAB
1718 space-after-tab::tab [] [] 8 or more SPACEs after TAB: SPACEs
1719 space-after-tab::space [] [] 8 or more SPACEs after TAB: TABs
1720
1721 indent-tabs-mode =
1722 tab-width = \n\n"
1723 . ;; `indent-tabs-mode' has nil value
1724 "\
1725 Whitespace Report
1726
1727 Current Setting Whitespace Problem
1728
1729 empty [] [] empty lines at beginning of buffer
1730 empty [] [] empty lines at end of buffer
1731 trailing [] [] SPACEs or TABs at end of line
1732 indentation [] [] TABs at beginning of line
1733 indentation::tab [] [] 8 or more SPACEs at beginning of line
1734 indentation::space [] [] TABs at beginning of line
1735 space-before-tab [] [] SPACEs before TAB
1736 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1737 space-before-tab::space [] [] SPACEs before TAB: TABs
1738 space-after-tab [] [] 8 or more SPACEs after TAB
1739 space-after-tab::tab [] [] 8 or more SPACEs after TAB: SPACEs
1740 space-after-tab::space [] [] 8 or more SPACEs after TAB: TABs
1741
1742 indent-tabs-mode =
1743 tab-width = \n\n")
1744 "Text for whitespace bogus report.
1745
1746 It is a cons of strings, where the car part is used when
1747 `indent-tabs-mode' is non-nil, and the cdr part is used when
1748 `indent-tabs-mode' is nil.")
1749
1750
1751 (defconst whitespace-report-buffer-name "*Whitespace Report*"
1752 "The buffer name for whitespace bogus report.")
1753
1754
1755 ;;;###autoload
1756 (defun whitespace-report (&optional force report-if-bogus)
1757 "Report some whitespace problems in buffer.
1758
1759 Perform `whitespace-report-region' on the current buffer."
1760 (interactive (list current-prefix-arg))
1761 (whitespace-report-region (point-min) (point-max)
1762 force report-if-bogus))
1763
1764
1765 ;;;###autoload
1766 (defun whitespace-report-region (start end &optional force report-if-bogus)
1767 "Report some whitespace problems in a region.
1768
1769 Return nil if there is no whitespace problem; otherwise, return
1770 non-nil.
1771
1772 If FORCE is non-nil or \\[universal-argument] was pressed just
1773 before calling `whitespace-report-region' interactively, it
1774 forces `whitespace-style' to have:
1775
1776 empty
1777 trailing
1778 indentation
1779 space-before-tab
1780 space-after-tab
1781
1782 If REPORT-IF-BOGUS is t, it reports only when there are any
1783 whitespace problems in buffer; if it is `never', it does not
1784 report problems.
1785
1786 Report if some of the following whitespace problems exist:
1787
1788 * If `indent-tabs-mode' is non-nil:
1789 empty 1. empty lines at beginning of buffer.
1790 empty 2. empty lines at end of buffer.
1791 trailing 3. SPACEs or TABs at end of line.
1792 indentation 4. 8 or more SPACEs at beginning of line.
1793 space-before-tab 5. SPACEs before TAB.
1794 space-after-tab 6. 8 or more SPACEs after TAB.
1795
1796 * If `indent-tabs-mode' is nil:
1797 empty 1. empty lines at beginning of buffer.
1798 empty 2. empty lines at end of buffer.
1799 trailing 3. SPACEs or TABs at end of line.
1800 indentation 4. TABS at beginning of line.
1801 space-before-tab 5. SPACEs before TAB.
1802 space-after-tab 6. 8 or more SPACEs after TAB.
1803
1804 See `whitespace-style' for documentation.
1805 See also `whitespace-cleanup' and `whitespace-cleanup-region' for
1806 cleaning up these problems."
1807 (interactive "r")
1808 (setq force (or current-prefix-arg force))
1809 (save-excursion
1810 (save-match-data ;FIXME: Why?
1811 (let* ((has-bogus nil)
1812 (rstart (min start end))
1813 (rend (max start end))
1814 (bogus-list
1815 (mapcar
1816 #'(lambda (option)
1817 (when force
1818 (add-to-list 'whitespace-style (car option)))
1819 (goto-char rstart)
1820 (let ((regexp
1821 (cond
1822 ((eq (car option) 'indentation)
1823 (whitespace-indentation-regexp))
1824 ((eq (car option) 'indentation::tab)
1825 (whitespace-indentation-regexp 'tab))
1826 ((eq (car option) 'indentation::space)
1827 (whitespace-indentation-regexp 'space))
1828 ((eq (car option) 'space-after-tab)
1829 (whitespace-space-after-tab-regexp))
1830 ((eq (car option) 'space-after-tab::tab)
1831 (whitespace-space-after-tab-regexp 'tab))
1832 ((eq (car option) 'space-after-tab::space)
1833 (whitespace-space-after-tab-regexp 'space))
1834 (t
1835 (cdr option)))))
1836 (and (re-search-forward regexp rend t)
1837 (setq has-bogus t))))
1838 whitespace-report-list)))
1839 (when (pcase report-if-bogus (`nil t) (`never nil) (_ has-bogus))
1840 (whitespace-kill-buffer whitespace-report-buffer-name)
1841 ;; `whitespace-indent-tabs-mode' is local to current buffer
1842 ;; `whitespace-tab-width' is local to current buffer
1843 (let ((ws-indent-tabs-mode whitespace-indent-tabs-mode)
1844 (ws-tab-width whitespace-tab-width))
1845 (with-current-buffer (get-buffer-create
1846 whitespace-report-buffer-name)
1847 (erase-buffer)
1848 (insert (if ws-indent-tabs-mode
1849 (car whitespace-report-text)
1850 (cdr whitespace-report-text)))
1851 (goto-char (point-min))
1852 (forward-line 3)
1853 (dolist (option whitespace-report-list)
1854 (forward-line 1)
1855 (whitespace-mark-x
1856 27 (memq (car option) whitespace-style))
1857 (whitespace-mark-x 7 (car bogus-list))
1858 (setq bogus-list (cdr bogus-list)))
1859 (forward-line 1)
1860 (whitespace-insert-value ws-indent-tabs-mode)
1861 (whitespace-insert-value ws-tab-width)
1862 (when has-bogus
1863 (goto-char (point-max))
1864 (insert " Type `M-x whitespace-cleanup'"
1865 " to cleanup the buffer.\n\n"
1866 " Type `M-x whitespace-cleanup-region'"
1867 " to cleanup a region.\n\n"))
1868 (whitespace-display-window (current-buffer)))))
1869 has-bogus))))
1870
1871 \f
1872 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1873 ;;;; Internal functions
1874
1875
1876 (defvar whitespace-font-lock-keywords nil
1877 "Used to save the value `whitespace-color-on' adds to `font-lock-keywords'.")
1878
1879
1880 (defconst whitespace-help-text
1881 "\
1882 Whitespace Toggle Options | scroll up : SPC or > |
1883 | scroll down: M-SPC or < |
1884 FACES \\__________________________/
1885 [] f - toggle face visualization
1886 [] t - toggle TAB visualization
1887 [] s - toggle SPACE and HARD SPACE visualization
1888 [] r - toggle trailing blanks visualization
1889 [] l - toggle \"long lines\" visualization
1890 [] L - toggle \"long lines\" tail visualization
1891 [] n - toggle NEWLINE visualization
1892 [] e - toggle empty line at bob and/or eob visualization
1893 [] C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode')
1894 [] I - toggle indentation SPACEs visualization
1895 [] i - toggle indentation TABs visualization
1896 [] C-t - toggle big indentation visualization
1897 [] C-a - toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1898 [] A - toggle SPACEs after TAB: SPACEs visualization
1899 [] a - toggle SPACEs after TAB: TABs visualization
1900 [] C-b - toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1901 [] B - toggle SPACEs before TAB: SPACEs visualization
1902 [] b - toggle SPACEs before TAB: TABs visualization
1903
1904 DISPLAY TABLE
1905 [] T - toggle TAB visualization
1906 [] S - toggle SPACE and HARD SPACE visualization
1907 [] N - toggle NEWLINE visualization
1908
1909 x - restore `whitespace-style' value
1910
1911 ? - display this text\n\n"
1912 "Text for whitespace toggle options.")
1913
1914
1915 (defconst whitespace-help-buffer-name "*Whitespace Toggle Options*"
1916 "The buffer name for whitespace toggle options.")
1917
1918
1919 (defun whitespace-insert-value (value)
1920 "Insert VALUE at column 20 of next line."
1921 (forward-line 1)
1922 (move-to-column 20 t)
1923 (insert (format "%s" value)))
1924
1925
1926 (defun whitespace-mark-x (nchars condition)
1927 "Insert the mark ('X' or ' ') after NCHARS depending on CONDITION."
1928 (forward-char nchars)
1929 (insert (if condition "X" " ")))
1930
1931
1932 (defun whitespace-insert-option-mark (the-list the-value)
1933 "Insert the option mark ('X' or ' ') in toggle options buffer."
1934 (goto-char (point-min))
1935 (forward-line 2)
1936 (dolist (sym the-list)
1937 (if (eq sym 'help-newline)
1938 (forward-line 2)
1939 (forward-line 1)
1940 (whitespace-mark-x 2 (memq sym the-value)))))
1941
1942
1943 (defun whitespace-help-on (style)
1944 "Display the whitespace toggle options."
1945 (unless (get-buffer whitespace-help-buffer-name)
1946 (delete-other-windows)
1947 (let ((buffer (get-buffer-create whitespace-help-buffer-name)))
1948 (with-current-buffer buffer
1949 (erase-buffer)
1950 (insert whitespace-help-text)
1951 (whitespace-insert-option-mark
1952 whitespace-style-value-list style)
1953 (whitespace-display-window buffer)))))
1954
1955
1956 (defun whitespace-display-window (buffer)
1957 "Display BUFFER in a new window."
1958 (goto-char (point-min))
1959 (set-buffer-modified-p nil)
1960 (when (< (window-height) (* 2 window-min-height))
1961 (kill-buffer buffer)
1962 (error "Window height is too small; \
1963 can't split window to display whitespace toggle options"))
1964 (let ((win (split-window)))
1965 (set-window-buffer win buffer)
1966 (shrink-window-if-larger-than-buffer win)))
1967
1968
1969 (defun whitespace-kill-buffer (buffer-name)
1970 "Kill buffer BUFFER-NAME and windows related with it."
1971 (let ((buffer (get-buffer buffer-name)))
1972 (when buffer
1973 (delete-windows-on buffer)
1974 (kill-buffer buffer))))
1975
1976
1977 (defun whitespace-help-off ()
1978 "Remove the buffer and window of the whitespace toggle options."
1979 (whitespace-kill-buffer whitespace-help-buffer-name))
1980
1981
1982 (defun whitespace-help-scroll (&optional up)
1983 "Scroll help window, if it exists.
1984
1985 If UP is non-nil, scroll up; otherwise, scroll down."
1986 (condition-case nil
1987 (let ((buffer (get-buffer whitespace-help-buffer-name)))
1988 (if buffer
1989 (with-selected-window (get-buffer-window buffer)
1990 (if up
1991 (scroll-up 3)
1992 (scroll-down 3)))
1993 (ding)))
1994 ;; handler
1995 ((error)
1996 ;; just ignore error
1997 )))
1998
1999
2000 (defun whitespace-interactive-char (local-p)
2001 "Interactive function to read a char and return a symbol.
2002
2003 If LOCAL-P is non-nil, it uses a local context; otherwise, it
2004 uses a global context.
2005
2006 It accepts one of the following chars:
2007
2008 CHAR MEANING
2009 (VIA FACES)
2010 f toggle face visualization
2011 t toggle TAB visualization
2012 s toggle SPACE and HARD SPACE visualization
2013 r toggle trailing blanks visualization
2014 l toggle \"long lines\" visualization
2015 L toggle \"long lines\" tail visualization
2016 n toggle NEWLINE visualization
2017 e toggle empty line at bob and/or eob visualization
2018 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
2019 I toggle indentation SPACEs visualization
2020 i toggle indentation TABs visualization
2021 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
2022 A toggle SPACEs after TAB: SPACEs visualization
2023 a toggle SPACEs after TAB: TABs visualization
2024 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
2025 B toggle SPACEs before TAB: SPACEs visualization
2026 b toggle SPACEs before TAB: TABs visualization
2027
2028 (VIA DISPLAY TABLE)
2029 T toggle TAB visualization
2030 S toggle SPACE and HARD SPACE visualization
2031 N toggle NEWLINE visualization
2032
2033 x restore `whitespace-style' value
2034 ? display brief help
2035
2036 See also `whitespace-toggle-option-alist'."
2037 (let* ((is-off (not (if local-p
2038 whitespace-mode
2039 global-whitespace-mode)))
2040 (style (cond (is-off whitespace-style) ; use default value
2041 (local-p whitespace-active-style)
2042 (t whitespace-toggle-style)))
2043 (prompt
2044 (format "Whitespace Toggle %s (type ? for further options)-"
2045 (if local-p "Local" "Global")))
2046 ch sym)
2047 ;; read a valid option and get the corresponding symbol
2048 (save-window-excursion
2049 (condition-case data
2050 (progn
2051 (while
2052 ;; while condition
2053 (progn
2054 (setq ch (read-char prompt))
2055 (not
2056 (setq sym
2057 (cdr
2058 (assq ch whitespace-toggle-option-alist)))))
2059 ;; while body
2060 (cond
2061 ((eq ch ?\?) (whitespace-help-on style))
2062 ((eq ch ?\ ) (whitespace-help-scroll t))
2063 ((eq ch ?\M- ) (whitespace-help-scroll))
2064 ((eq ch ?>) (whitespace-help-scroll t))
2065 ((eq ch ?<) (whitespace-help-scroll))
2066 (t (ding))))
2067 (whitespace-help-off)
2068 (message " ")) ; clean echo area
2069 ;; handler
2070 ((quit error)
2071 (whitespace-help-off)
2072 (error (error-message-string data)))))
2073 (list sym))) ; return the appropriate symbol
2074
2075
2076 (defun whitespace-toggle-list (local-p arg the-list)
2077 "Toggle options in THE-LIST based on list ARG.
2078
2079 If LOCAL-P is non-nil, it uses a local context; otherwise, it
2080 uses a global context.
2081
2082 ARG is a list of options to be toggled.
2083
2084 THE-LIST is a list of options. This list will be toggled and the
2085 resultant list will be returned."
2086 (unless (if local-p whitespace-mode global-whitespace-mode)
2087 (setq the-list whitespace-style))
2088 (setq the-list (copy-sequence the-list)) ; keep original list
2089 (dolist (sym (if (listp arg) arg (list arg)))
2090 (cond
2091 ;; ignore help value
2092 ((eq sym 'help-newline))
2093 ;; restore default values
2094 ((eq sym 'whitespace-style)
2095 (setq the-list whitespace-style))
2096 ;; toggle valid values
2097 ((memq sym whitespace-style-value-list)
2098 (setq the-list (if (memq sym the-list)
2099 (delq sym the-list)
2100 (cons sym the-list))))))
2101 the-list)
2102
2103
2104 (defvar whitespace-display-table nil
2105 "Used to save a local display table.")
2106
2107 (defvar whitespace-display-table-was-local nil
2108 "Used to remember whether a buffer initially had a local display table.")
2109
2110 (defun whitespace-turn-on ()
2111 "Turn on whitespace visualization."
2112 ;; prepare local hooks
2113 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
2114 ;; create whitespace local buffer environment
2115 (set (make-local-variable 'whitespace-font-lock-keywords) nil)
2116 (set (make-local-variable 'whitespace-display-table) nil)
2117 (set (make-local-variable 'whitespace-display-table-was-local) nil)
2118 (set (make-local-variable 'whitespace-active-style)
2119 (if (listp whitespace-style)
2120 whitespace-style
2121 (list whitespace-style)))
2122 (whitespace-ensure-local-variables)
2123 ;; turn on whitespace
2124 (when whitespace-active-style
2125 (whitespace-color-on)
2126 (whitespace-display-char-on)))
2127
2128
2129 (defun whitespace-turn-off ()
2130 "Turn off whitespace visualization."
2131 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
2132 (when whitespace-active-style
2133 (whitespace-color-off)
2134 (whitespace-display-char-off)))
2135
2136
2137 (defun whitespace-style-face-p ()
2138 "Return t if there is some visualization via face."
2139 (and (memq 'face whitespace-active-style)
2140 (or (memq 'tabs whitespace-active-style)
2141 (memq 'spaces whitespace-active-style)
2142 (memq 'trailing whitespace-active-style)
2143 (memq 'lines whitespace-active-style)
2144 (memq 'lines-tail whitespace-active-style)
2145 (memq 'newline whitespace-active-style)
2146 (memq 'empty whitespace-active-style)
2147 (memq 'indentation whitespace-active-style)
2148 (memq 'indentation::tab whitespace-active-style)
2149 (memq 'indentation::space whitespace-active-style)
2150 (memq 'big-indent whitespace-active-style)
2151 (memq 'space-after-tab whitespace-active-style)
2152 (memq 'space-after-tab::tab whitespace-active-style)
2153 (memq 'space-after-tab::space whitespace-active-style)
2154 (memq 'space-before-tab whitespace-active-style)
2155 (memq 'space-before-tab::tab whitespace-active-style)
2156 (memq 'space-before-tab::space whitespace-active-style))))
2157
2158
2159 (defun whitespace-color-on ()
2160 "Turn on color visualization."
2161 (when (whitespace-style-face-p)
2162 ;; save current point and refontify when necessary
2163 (set (make-local-variable 'whitespace-point)
2164 (point))
2165 (setq whitespace-point--used
2166 (let ((ol (make-overlay (point) (point) nil nil t)))
2167 (delete-overlay ol) ol))
2168 (set (make-local-variable 'whitespace-font-lock-refontify)
2169 0)
2170 (set (make-local-variable 'whitespace-bob-marker)
2171 (point-min-marker))
2172 (set (make-local-variable 'whitespace-eob-marker)
2173 (point-max-marker))
2174 (set (make-local-variable 'whitespace-buffer-changed)
2175 nil)
2176 (add-hook 'post-command-hook #'whitespace-post-command-hook nil t)
2177 (add-hook 'before-change-functions #'whitespace-buffer-changed nil t)
2178 ;; Add whitespace-mode color into font lock.
2179 (setq
2180 whitespace-font-lock-keywords
2181 `(
2182 (whitespace-point--flush-used)
2183 ,@(when (memq 'spaces whitespace-active-style)
2184 ;; Show SPACEs.
2185 `((,whitespace-space-regexp 1 whitespace-space t)
2186 ;; Show HARD SPACEs.
2187 (,whitespace-hspace-regexp 1 whitespace-hspace t)))
2188 ,@(when (memq 'tabs whitespace-active-style)
2189 ;; Show TABs.
2190 `((,whitespace-tab-regexp 1 whitespace-tab t)))
2191 ,@(when (memq 'trailing whitespace-active-style)
2192 ;; Show trailing blanks.
2193 `((,#'whitespace-trailing-regexp 1 whitespace-trailing t)))
2194 ,@(when (or (memq 'lines whitespace-active-style)
2195 (memq 'lines-tail whitespace-active-style))
2196 ;; Show "long" lines.
2197 `((,(let ((line-column (or whitespace-line-column fill-column)))
2198 (format
2199 "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
2200 whitespace-tab-width
2201 (1- whitespace-tab-width)
2202 (/ line-column whitespace-tab-width)
2203 (let ((rem (% line-column whitespace-tab-width)))
2204 (if (zerop rem)
2205 ""
2206 (format ".\\{%d\\}" rem)))))
2207 ,(if (memq 'lines whitespace-active-style)
2208 0 ; whole line
2209 2) ; line tail
2210 whitespace-line prepend)))
2211 ,@(when (or (memq 'space-before-tab whitespace-active-style)
2212 (memq 'space-before-tab::tab whitespace-active-style)
2213 (memq 'space-before-tab::space whitespace-active-style))
2214 `((,whitespace-space-before-tab-regexp
2215 ,(cond
2216 ((memq 'space-before-tab whitespace-active-style)
2217 ;; Show SPACEs before TAB (indent-tabs-mode).
2218 (if whitespace-indent-tabs-mode 1 2))
2219 ((memq 'space-before-tab::tab whitespace-active-style)
2220 1)
2221 ((memq 'space-before-tab::space whitespace-active-style)
2222 2))
2223 whitespace-space-before-tab t)))
2224 ,@(when (or (memq 'indentation whitespace-active-style)
2225 (memq 'indentation::tab whitespace-active-style)
2226 (memq 'indentation::space whitespace-active-style))
2227 `((,(cond
2228 ((memq 'indentation whitespace-active-style)
2229 ;; Show indentation SPACEs (indent-tabs-mode).
2230 (whitespace-indentation-regexp))
2231 ((memq 'indentation::tab whitespace-active-style)
2232 ;; Show indentation SPACEs (SPACEs).
2233 (whitespace-indentation-regexp 'tab))
2234 ((memq 'indentation::space whitespace-active-style)
2235 ;; Show indentation SPACEs (TABs).
2236 (whitespace-indentation-regexp 'space)))
2237 1 whitespace-indentation t)))
2238 ,@(when (memq 'big-indent whitespace-active-style)
2239 ;; Show big indentation.
2240 `((,whitespace-big-indent-regexp 1 'whitespace-big-indent t)))
2241 ,@(when (memq 'empty whitespace-active-style)
2242 ;; Show empty lines at beginning of buffer.
2243 `((,#'whitespace-empty-at-bob-regexp
2244 1 whitespace-empty t)
2245 ;; Show empty lines at end of buffer.
2246 (,#'whitespace-empty-at-eob-regexp
2247 1 whitespace-empty t)))
2248 ,@(when (or (memq 'space-after-tab whitespace-active-style)
2249 (memq 'space-after-tab::tab whitespace-active-style)
2250 (memq 'space-after-tab::space whitespace-active-style))
2251 `((,(cond
2252 ((memq 'space-after-tab whitespace-active-style)
2253 ;; Show SPACEs after TAB (indent-tabs-mode).
2254 (whitespace-space-after-tab-regexp))
2255 ((memq 'space-after-tab::tab whitespace-active-style)
2256 ;; Show SPACEs after TAB (SPACEs).
2257 (whitespace-space-after-tab-regexp 'tab))
2258 ((memq 'space-after-tab::space whitespace-active-style)
2259 ;; Show SPACEs after TAB (TABs).
2260 (whitespace-space-after-tab-regexp 'space)))
2261 1 whitespace-space-after-tab t)))))
2262 (font-lock-add-keywords nil whitespace-font-lock-keywords t)
2263 (font-lock-flush)))
2264
2265
2266 (defun whitespace-color-off ()
2267 "Turn off color visualization."
2268 ;; turn off font lock
2269 (kill-local-variable 'whitespace-point--used)
2270 (when (whitespace-style-face-p)
2271 (remove-hook 'post-command-hook #'whitespace-post-command-hook t)
2272 (remove-hook 'before-change-functions #'whitespace-buffer-changed t)
2273 (font-lock-remove-keywords nil whitespace-font-lock-keywords)
2274 (font-lock-flush)))
2275
2276 (defun whitespace-point--used (start end)
2277 (let ((ostart (overlay-start whitespace-point--used)))
2278 (if ostart
2279 (move-overlay whitespace-point--used
2280 (min start ostart)
2281 (max end (overlay-end whitespace-point--used)))
2282 (move-overlay whitespace-point--used start end))))
2283
2284 (defun whitespace-point--flush-used (limit)
2285 (let ((ostart (overlay-start whitespace-point--used)))
2286 ;; Strip parts of whitespace-point--used we're about to refresh.
2287 (when ostart
2288 (let ((oend (overlay-end whitespace-point--used)))
2289 (if (<= (point) ostart)
2290 (if (<= oend limit)
2291 (delete-overlay whitespace-point--used)
2292 (move-overlay whitespace-point--used limit oend)))
2293 (if (<= oend limit)
2294 (move-overlay whitespace-point--used ostart (point))))))
2295 nil)
2296
2297 (defun whitespace-trailing-regexp (limit)
2298 "Match trailing spaces which do not contain the point at end of line."
2299 (let ((status t))
2300 (while (if (re-search-forward whitespace-trailing-regexp limit t)
2301 (when (= whitespace-point (match-end 1)) ; Loop if point at eol.
2302 (whitespace-point--used (match-beginning 0) (match-end 0))
2303 t)
2304 (setq status nil))) ;; end of buffer
2305 status))
2306
2307
2308 (defun whitespace-empty-at-bob-regexp (limit)
2309 "Match spaces at beginning of buffer which do not contain the point at \
2310 beginning of buffer."
2311 (let ((b (point))
2312 r)
2313 (cond
2314 ;; at bob
2315 ((= b 1)
2316 (setq r (and (looking-at whitespace-empty-at-bob-regexp)
2317 (or (/= whitespace-point 1)
2318 (progn (whitespace-point--used (match-beginning 0)
2319 (match-end 0))
2320 nil))))
2321 (set-marker whitespace-bob-marker (if r (match-end 1) b)))
2322 ;; inside bob empty region
2323 ((<= limit whitespace-bob-marker)
2324 (setq r (looking-at whitespace-empty-at-bob-regexp))
2325 (if r
2326 (when (< (match-end 1) limit)
2327 (set-marker whitespace-bob-marker (match-end 1)))
2328 (set-marker whitespace-bob-marker b)))
2329 ;; intersection with end of bob empty region
2330 ((<= b whitespace-bob-marker)
2331 (setq r (looking-at whitespace-empty-at-bob-regexp))
2332 (set-marker whitespace-bob-marker (if r (match-end 1) b)))
2333 ;; it is not inside bob empty region
2334 (t
2335 (setq r nil)))
2336 ;; move to end of matching
2337 (and r (goto-char (match-end 1)))
2338 r))
2339
2340
2341 (defsubst whitespace-looking-back (regexp limit)
2342 (save-excursion
2343 (when (/= 0 (skip-chars-backward " \t\n" limit))
2344 (unless (bolp)
2345 (forward-line 1))
2346 (looking-at regexp))))
2347
2348
2349 (defun whitespace-empty-at-eob-regexp (limit)
2350 "Match spaces at end of buffer which do not contain the point at end of \
2351 buffer."
2352 (let ((b (point))
2353 (e (1+ (buffer-size)))
2354 r)
2355 (cond
2356 ;; at eob
2357 ((= limit e)
2358 (goto-char limit)
2359 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2360 (when (and r (= whitespace-point e))
2361 (setq r nil)
2362 (whitespace-point--used (match-beginning 0) (match-end 0)))
2363 (if r
2364 (set-marker whitespace-eob-marker (match-beginning 1))
2365 (set-marker whitespace-eob-marker limit)
2366 (goto-char b))) ; return back to initial position
2367 ;; inside eob empty region
2368 ((>= b whitespace-eob-marker)
2369 (goto-char limit)
2370 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2371 (if r
2372 (when (> (match-beginning 1) b)
2373 (set-marker whitespace-eob-marker (match-beginning 1)))
2374 (set-marker whitespace-eob-marker limit)
2375 (goto-char b))) ; return back to initial position
2376 ;; intersection with beginning of eob empty region
2377 ((>= limit whitespace-eob-marker)
2378 (goto-char limit)
2379 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2380 (if r
2381 (set-marker whitespace-eob-marker (match-beginning 1))
2382 (set-marker whitespace-eob-marker limit)
2383 (goto-char b))) ; return back to initial position
2384 ;; it is not inside eob empty region
2385 (t
2386 (setq r nil)))
2387 r))
2388
2389
2390 (defun whitespace-buffer-changed (_beg _end)
2391 "Set `whitespace-buffer-changed' variable to t."
2392 (setq whitespace-buffer-changed t))
2393
2394
2395 (defun whitespace-post-command-hook ()
2396 "Save current point into `whitespace-point' variable.
2397 Also refontify when necessary."
2398 (unless (and (eq whitespace-point (point))
2399 (not whitespace-buffer-changed))
2400 (setq whitespace-point (point)) ; current point position
2401 (let ((refontify
2402 (cond
2403 ;; It is at end of buffer (eob).
2404 ((= whitespace-point (1+ (buffer-size)))
2405 (when (whitespace-looking-back whitespace-empty-at-eob-regexp
2406 nil)
2407 (match-beginning 0)))
2408 ;; It is at end of line ...
2409 ((and (eolp)
2410 ;; ... with trailing SPACE or TAB
2411 (or (memq (preceding-char) '(?\s ?\t))))
2412 (line-beginning-position))
2413 ;; It is at beginning of buffer (bob).
2414 ((and (= whitespace-point 1)
2415 (looking-at whitespace-empty-at-bob-regexp))
2416 (match-end 0))))
2417 (ostart (overlay-start whitespace-point--used)))
2418 (cond
2419 ((not refontify)
2420 ;; New point does not affect highlighting: just refresh the
2421 ;; highlighting of old point, if needed.
2422 (when ostart
2423 (font-lock-flush ostart
2424 (overlay-end whitespace-point--used))
2425 (delete-overlay whitespace-point--used)))
2426 ((not ostart)
2427 ;; Old point did not affect highlighting, but new one does: refresh the
2428 ;; highlighting of new point.
2429 (font-lock-flush (min refontify (point)) (max refontify (point))))
2430 ((save-excursion
2431 (goto-char ostart)
2432 (setq ostart (line-beginning-position))
2433 (and (<= ostart (max refontify (point)))
2434 (progn
2435 (goto-char (overlay-end whitespace-point--used))
2436 (let ((oend (line-beginning-position 2)))
2437 (<= (min refontify (point)) oend)))))
2438 ;; The old point highlighting and the new point highlighting
2439 ;; cover a contiguous region: do a single refresh.
2440 (font-lock-flush (min refontify (point) ostart)
2441 (max refontify (point)
2442 (overlay-end whitespace-point--used)))
2443 (delete-overlay whitespace-point--used))
2444 (t
2445 (font-lock-flush (min refontify (point))
2446 (max refontify (point)))
2447 (font-lock-flush ostart (overlay-end whitespace-point--used))
2448 (delete-overlay whitespace-point--used))))))
2449
2450 \f
2451 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2452 ;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
2453
2454
2455 (defun whitespace-style-mark-p ()
2456 "Return t if there is some visualization via display table."
2457 (or (memq 'tab-mark whitespace-active-style)
2458 (memq 'space-mark whitespace-active-style)
2459 (memq 'newline-mark whitespace-active-style)))
2460
2461
2462 (defsubst whitespace-char-valid-p (char)
2463 ;; This check should be improved!!!
2464 (or (< char 256)
2465 (characterp char)))
2466
2467
2468 (defun whitespace-display-vector-p (vec)
2469 "Return true if every character in vector VEC can be displayed."
2470 (let ((i (length vec)))
2471 (when (> i 0)
2472 (while (and (>= (setq i (1- i)) 0)
2473 (whitespace-char-valid-p (aref vec i))))
2474 (< i 0))))
2475
2476
2477 (defun whitespace-display-char-on ()
2478 "Turn on character display mapping."
2479 (when (and whitespace-display-mappings
2480 (whitespace-style-mark-p))
2481 (let (vecs vec)
2482 ;; Remember whether a buffer has a local display table.
2483 (unless whitespace-display-table-was-local
2484 (setq whitespace-display-table-was-local t
2485 whitespace-display-table
2486 (copy-sequence buffer-display-table))
2487 ;; Assure `buffer-display-table' is unique
2488 ;; when two or more windows are visible.
2489 (setq buffer-display-table
2490 (copy-sequence buffer-display-table)))
2491 (unless buffer-display-table
2492 (setq buffer-display-table (make-display-table)))
2493 (dolist (entry whitespace-display-mappings)
2494 ;; check if it is to display this mark
2495 (when (memq (car entry) whitespace-style)
2496 ;; Get a displayable mapping.
2497 (setq vecs (cddr entry))
2498 (while (and vecs
2499 (not (whitespace-display-vector-p (car vecs))))
2500 (setq vecs (cdr vecs)))
2501 ;; Display a valid mapping.
2502 (when vecs
2503 (setq vec (copy-sequence (car vecs)))
2504 ;; NEWLINE char
2505 (when (and (eq (cadr entry) ?\n)
2506 (memq 'newline whitespace-active-style))
2507 ;; Only insert face bits on NEWLINE char mapping to avoid
2508 ;; obstruction of other faces like TABs and (HARD) SPACEs
2509 ;; faces, font-lock faces, etc.
2510 (dotimes (i (length vec))
2511 (or (eq (aref vec i) ?\n)
2512 (aset vec i
2513 (make-glyph-code (aref vec i)
2514 whitespace-newline)))))
2515 ;; Display mapping
2516 (aset buffer-display-table (cadr entry) vec)))))))
2517
2518
2519 (defun whitespace-display-char-off ()
2520 "Turn off character display mapping."
2521 (and whitespace-display-mappings
2522 (whitespace-style-mark-p)
2523 whitespace-display-table-was-local
2524 (setq whitespace-display-table-was-local nil
2525 buffer-display-table whitespace-display-table)))
2526
2527 \f
2528 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2529 ;;;; Hook
2530
2531
2532 (defun whitespace-action-when-on ()
2533 "Action to be taken always when local whitespace is turned on."
2534 (cond ((memq 'cleanup whitespace-action)
2535 (whitespace-cleanup))
2536 ((memq 'report-on-bogus whitespace-action)
2537 (whitespace-report nil t))))
2538
2539
2540 (defun whitespace-write-file-hook ()
2541 "Action to be taken when buffer is written.
2542 It should be added buffer-locally to `write-file-functions'."
2543 (cond ((memq 'auto-cleanup whitespace-action)
2544 (whitespace-cleanup))
2545 ((memq 'abort-on-bogus whitespace-action)
2546 (when (whitespace-report nil t)
2547 (error "Abort write due to whitespace problems in %s"
2548 (buffer-name)))))
2549 nil) ; continue hook processing
2550
2551
2552 (defun whitespace-warn-read-only (msg)
2553 "Warn if buffer is read-only."
2554 (when (memq 'warn-if-read-only whitespace-action)
2555 (message "Can't %s: %s is read-only" msg (buffer-name))))
2556
2557 \f
2558 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2559
2560
2561 (defun whitespace-unload-function ()
2562 "Unload the whitespace library."
2563 (global-whitespace-mode -1)
2564 ;; be sure all local whitespace mode is turned off
2565 (save-current-buffer
2566 (dolist (buf (buffer-list))
2567 (set-buffer buf)
2568 (whitespace-mode -1)))
2569 nil) ; continue standard unloading
2570
2571
2572 (provide 'whitespace)
2573
2574
2575 (run-hooks 'whitespace-load-hook)
2576
2577
2578 ;;; whitespace.el ends here