Update remaining copyright years with admin.el M-x set-copyright
[emacs.git] / lisp / whitespace.el
blobd66c894df2528cb52129498cc7bbaffe0d0f0412
1 ;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE
3 ;; Copyright (C) 2000-2017 Free Software Foundation, Inc.
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
11 ;; This file is part of GNU Emacs.
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.
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.
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/>.
26 ;;; Commentary:
28 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30 ;; Introduction
31 ;; ------------
33 ;; This package is a minor mode to visualize blanks (TAB, (HARD) SPACE
34 ;; and NEWLINE).
36 ;; whitespace uses two ways to visualize blanks: faces and display
37 ;; table.
39 ;; * Faces are used to highlight the background with a color.
40 ;; whitespace uses font-lock to highlight blank characters.
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).
46 ;; The `whitespace-style' variable selects which way blanks are
47 ;; visualized.
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.
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).
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.
67 ;; There are two ways of using whitespace: local and global.
69 ;; * Local whitespace affects only the current buffer.
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.
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.
82 ;; When global and local whitespace are on:
84 ;; * if local whitespace is turned off, whitespace is turned off for
85 ;; the current buffer only.
87 ;; * if global whitespace is turned off, whitespace continues on only
88 ;; in the buffers in which local whitespace is on.
90 ;; To use whitespace, insert in your ~/.emacs:
92 ;; (require 'whitespace)
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:
98 ;; (autoload 'whitespace-mode "whitespace"
99 ;; "Toggle whitespace visualization." t)
100 ;; (autoload 'whitespace-toggle-options "whitespace"
101 ;; "Toggle local `whitespace-mode' options." t)
103 ;; whitespace was inspired by:
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'.
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)
116 ;; whitespace-mode.el Lawrence Mitchell <wence@gmx.li>
117 ;; Major mode for editing Whitespace
118 ;; (inspired the idea to use display table)
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)
126 ;; Using whitespace
127 ;; ----------------
129 ;; There is no problem if you mix local and global minor mode usage.
131 ;; * LOCAL whitespace:
132 ;; + To toggle whitespace options locally, type:
134 ;; M-x whitespace-toggle-options RET
136 ;; + To activate whitespace locally, type:
138 ;; C-u 1 M-x whitespace-mode RET
140 ;; + To deactivate whitespace locally, type:
142 ;; C-u 0 M-x whitespace-mode RET
144 ;; + To toggle whitespace locally, type:
146 ;; M-x whitespace-mode RET
148 ;; * GLOBAL whitespace:
149 ;; + To toggle whitespace options globally, type:
151 ;; M-x global-whitespace-toggle-options RET
153 ;; + To activate whitespace globally, type:
155 ;; C-u 1 M-x global-whitespace-mode RET
157 ;; + To deactivate whitespace globally, type:
159 ;; C-u 0 M-x global-whitespace-mode RET
161 ;; + To toggle whitespace globally, type:
163 ;; M-x global-whitespace-mode RET
165 ;; There are also the following useful commands:
167 ;; `whitespace-newline-mode'
168 ;; Toggle NEWLINE minor mode visualization ("nl" on mode line).
170 ;; `global-whitespace-newline-mode'
171 ;; Toggle NEWLINE global minor mode visualization ("NL" on mode line).
173 ;; `whitespace-report'
174 ;; Report some blank problems in buffer.
176 ;; `whitespace-report-region'
177 ;; Report some blank problems in a region.
179 ;; `whitespace-cleanup'
180 ;; Cleanup some blank problems in all buffer or at region.
182 ;; `whitespace-cleanup-region'
183 ;; Cleanup some blank problems at region.
185 ;; The problems, which are cleaned up, are:
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.
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.
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.
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.
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.
225 ;; Hooks
226 ;; -----
228 ;; whitespace has the following hook variables:
230 ;; `whitespace-mode-hook'
231 ;; It is evaluated always when whitespace is turned on locally.
233 ;; `global-whitespace-mode-hook'
234 ;; It is evaluated always when whitespace is turned on globally.
236 ;; `whitespace-load-hook'
237 ;; It is evaluated after whitespace package is loaded.
240 ;; Options
241 ;; -------
243 ;; Below it's shown a brief description of whitespace options, please,
244 ;; see the options declaration in the code for a long documentation.
246 ;; `whitespace-style' Specify which kind of blank is
247 ;; visualized.
249 ;; `whitespace-space' Face used to visualize SPACE.
251 ;; `whitespace-hspace' Face used to visualize HARD SPACE.
253 ;; `whitespace-tab' Face used to visualize TAB.
255 ;; `whitespace-newline' Face used to visualize NEWLINE char
256 ;; mapping.
258 ;; `whitespace-trailing' Face used to visualize trailing
259 ;; blanks.
261 ;; `whitespace-line' Face used to visualize "long" lines.
263 ;; `whitespace-space-before-tab' Face used to visualize SPACEs
264 ;; before TAB.
266 ;; `whitespace-indentation' Face used to visualize 8 or more
267 ;; SPACEs at beginning of line.
269 ;; `whitespace-big-indent' Face used to visualize big indentation.
271 ;; `whitespace-empty' Face used to visualize empty lines at
272 ;; beginning and/or end of buffer.
274 ;; `whitespace-space-after-tab' Face used to visualize 8 or more
275 ;; SPACEs after TAB.
277 ;; `whitespace-space-regexp' Specify SPACE characters regexp.
279 ;; `whitespace-hspace-regexp' Specify HARD SPACE characters regexp.
281 ;; `whitespace-tab-regexp' Specify TAB characters regexp.
283 ;; `whitespace-trailing-regexp' Specify trailing characters regexp.
285 ;; `whitespace-space-before-tab-regexp' Specify SPACEs before TAB
286 ;; regexp.
288 ;; `whitespace-indentation-regexp' Specify regexp for 8 or more
289 ;; SPACEs at beginning of line.
291 ;; `whitespace-big-indent-regexp' Specify big indentation at beginning of line
292 ;; regexp.
294 ;; `whitespace-empty-at-bob-regexp' Specify regexp for empty lines
295 ;; at beginning of buffer.
297 ;; `whitespace-empty-at-eob-regexp' Specify regexp for empty lines
298 ;; at end of buffer.
300 ;; `whitespace-space-after-tab-regexp' Specify regexp for 8 or more
301 ;; SPACEs after TAB.
303 ;; `whitespace-line-column' Specify column beyond which the line
304 ;; is highlighted.
306 ;; `whitespace-display-mappings' Specify an alist of mappings
307 ;; for displaying characters.
309 ;; `whitespace-global-modes' Modes for which global
310 ;; `whitespace-mode' is automagically
311 ;; turned on.
313 ;; `whitespace-action' Specify which action is taken when a
314 ;; buffer is visited or written.
317 ;; Acknowledgments
318 ;; ---------------
320 ;; Thanks to felix (EmacsWiki) for keeping highlight when switching between
321 ;; major modes on a file.
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.
327 ;; Thanks to Stephen Deasey <sdeasey@gmail.com> for the
328 ;; `indent-tabs-mode' usage suggestion.
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.
334 ;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
335 ;; lines tail. See EightyColumnRule (EmacsWiki).
337 ;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
338 ;; * `define-minor-mode'.
339 ;; * `global-whitespace-*' name for global commands.
341 ;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
343 ;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
344 ;; suggestion.
346 ;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
347 ;; helping to fix `find-file-hooks' reference.
349 ;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
350 ;; indicating defface byte-compilation warnings.
352 ;; Thanks to Tim O'Callaghan (EmacsWiki) for the idea about highlight
353 ;; "long" lines. See EightyColumnRule (EmacsWiki).
355 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
356 ;; NEWLINE character mapping.
358 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
359 ;; whitespace-mode.el on XEmacs.
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).
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.
372 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
374 ;;; code:
377 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
378 ;;;; User Variables:
381 ;;; Interface to the command system
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)
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.
398 It's a list containing some or all of the following values:
400 face enable all visualization via faces (see below).
402 trailing trailing blanks are visualized via faces.
403 It has effect only if `face' (see above)
404 is present in `whitespace-style'.
406 tabs TABs are visualized via faces.
407 It has effect only if `face' (see above)
408 is present in `whitespace-style'.
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'.
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'.
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'.
434 newline NEWLINEs are visualized via faces.
435 It has effect only if `face' (see above)
436 is present in `whitespace-style'.
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'.
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'.
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'.
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'.
460 big-indent Big indentations are visualized via faces.
461 It has effect only if `face' (see above)
462 is present in `whitespace-style'.
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'.
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'.
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'.
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'.
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'.
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'.
498 space-mark SPACEs and HARD SPACEs are visualized via
499 display table.
501 tab-mark TABs are visualized via display table.
503 newline-mark NEWLINEs are visualized via display table.
505 Any other value is ignored.
507 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs via faces and
508 via display table.
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:
516 * For indentation:
517 1. indentation
518 2. indentation::tab
519 3. indentation::space
521 * For SPACEs after TABs:
522 1. space-after-tab
523 2. space-after-tab::tab
524 3. space-after-tab::space
526 * For SPACEs before TABs:
527 1. space-before-tab
528 2. space-before-tab::tab
529 3. space-before-tab::space
531 For example, if `indentation' and `indentation::space' are
532 included in `whitespace-style', the `indentation' value is used
533 instead of the `indentation::space' value.
535 One reason to not use faces to visualize spaces (i.e., not
536 include `face' in `whitespace-style') is to use `whitespace-mode'
537 only for cleaning up a buffer. See `whitespace-cleanup' and
538 `whitespace-cleanup-region'.
540 See also `whitespace-display-mappings' for documentation."
541 :type '(set :tag "Kind of Blank"
542 (const :tag "(Face) Face visualization" face)
543 (const :tag "(Face) Trailing TABs, SPACEs and HARD SPACEs"
544 trailing)
545 (const :tag "(Face) TABs" tabs)
546 (const :tag "(Face) SPACEs and HARD SPACEs" spaces)
547 (const :tag "(Face) Lines" lines)
548 (const :tag "(Face) Lines, only overlong part" lines-tail)
549 (const :tag "(Face) NEWLINEs" newline)
550 (const :tag "(Face) Empty Lines At BOB And/Or EOB" empty)
551 (const :tag "(Face) Indentation SPACEs" indentation::tab)
552 (const :tag "(Face) Indentation TABs"
553 indentation::space)
554 (const :tag "(Face) Indentation TABs or SPACEs" indentation)
555 (const :tag "(Face) Too much line indentation" big-indent)
556 (const :tag "(Face) SPACEs after TAB: SPACEs"
557 space-after-tab::tab)
558 (const :tag "(Face) SPACEs after TAB: TABs"
559 space-after-tab::space)
560 (const :tag "(Face) SPACEs after TAB" space-after-tab)
561 (const :tag "(Face) SPACEs before TAB: SPACEs"
562 space-before-tab::tab)
563 (const :tag "(Face) SPACEs before TAB: TABs"
564 space-before-tab::space)
565 (const :tag "(Face) SPACEs before TAB" space-before-tab)
566 (const :tag "(Mark) SPACEs and HARD SPACEs" space-mark)
567 (const :tag "(Mark) TABs" tab-mark)
568 (const :tag "(Mark) NEWLINEs" newline-mark))
569 :group 'whitespace)
571 (defvar whitespace-space 'whitespace-space
572 "Symbol face used to visualize SPACE.
573 Used when `whitespace-style' includes the value `spaces'.")
574 (make-obsolete-variable 'whitespace-space "use the face instead." "24.4")
577 (defface whitespace-space
578 '((((class color) (background dark))
579 :background "grey20" :foreground "darkgray")
580 (((class color) (background light))
581 :background "LightYellow" :foreground "lightgray")
582 (t :inverse-video t))
583 "Face used to visualize SPACE."
584 :group 'whitespace)
587 (defvar whitespace-hspace 'whitespace-hspace
588 "Symbol face used to visualize HARD SPACE.
589 Used when `whitespace-style' includes the value `spaces'.")
590 (make-obsolete-variable 'whitespace-hspace "use the face instead." "24.4")
592 (defface whitespace-hspace ; 'nobreak-space
593 '((((class color) (background dark))
594 :background "grey24" :foreground "darkgray")
595 (((class color) (background light))
596 :background "LemonChiffon3" :foreground "lightgray")
597 (t :inverse-video t))
598 "Face used to visualize HARD SPACE."
599 :group 'whitespace)
602 (defvar whitespace-tab 'whitespace-tab
603 "Symbol face used to visualize TAB.
604 Used when `whitespace-style' includes the value `tabs'.")
605 (make-obsolete-variable 'whitespace-tab "use the face instead." "24.4")
607 (defface whitespace-tab
608 '((((class color) (background dark))
609 :background "grey22" :foreground "darkgray")
610 (((class color) (background light))
611 :background "beige" :foreground "lightgray")
612 (t :inverse-video t))
613 "Face used to visualize TAB."
614 :group 'whitespace)
617 (defvar whitespace-newline 'whitespace-newline
618 "Symbol face used to visualize NEWLINE char mapping.
619 See `whitespace-display-mappings'.
620 Used when `whitespace-style' includes the values `newline-mark'
621 and `newline'.")
622 (make-obsolete-variable 'whitespace-newline "use the face instead." "24.4")
624 (defface whitespace-newline
625 '((default :weight normal)
626 (((class color) (background dark)) :foreground "darkgray")
627 (((class color) (min-colors 88) (background light)) :foreground "lightgray")
628 ;; Displays with 16 colors use lightgray as background, so using a
629 ;; lightgray foreground makes the newline mark invisible.
630 (((class color) (background light)) :foreground "brown")
631 (t :underline t))
632 "Face used to visualize NEWLINE char mapping.
634 See `whitespace-display-mappings'."
635 :group 'whitespace)
638 (defvar whitespace-trailing 'whitespace-trailing
639 "Symbol face used to visualize trailing blanks.
640 Used when `whitespace-style' includes the value `trailing'.")
641 (make-obsolete-variable 'whitespace-trailing "use the face instead." "24.4")
643 (defface whitespace-trailing ; 'trailing-whitespace
644 '((default :weight bold)
645 (((class mono)) :inverse-video t :underline t)
646 (t :background "red1" :foreground "yellow"))
647 "Face used to visualize trailing blanks."
648 :group 'whitespace)
651 (defvar whitespace-line 'whitespace-line
652 "Symbol face used to visualize \"long\" lines.
653 See `whitespace-line-column'.
654 Used when `whitespace-style' includes the value `line'.")
655 (make-obsolete-variable 'whitespace-line "use the face instead." "24.4")
657 (defface whitespace-line
658 '((((class mono)) :inverse-video t :weight bold :underline t)
659 (t :background "gray20" :foreground "violet"))
660 "Face used to visualize \"long\" lines.
662 See `whitespace-line-column'."
663 :group 'whitespace)
666 (defvar whitespace-space-before-tab 'whitespace-space-before-tab
667 "Symbol face used to visualize SPACEs before TAB.
668 Used when `whitespace-style' includes the value `space-before-tab'.")
669 (make-obsolete-variable 'whitespace-space-before-tab
670 "use the face instead." "24.4")
672 (defface whitespace-space-before-tab
673 '((((class mono)) :inverse-video t :weight bold :underline t)
674 (t :background "DarkOrange" :foreground "firebrick"))
675 "Face used to visualize SPACEs before TAB."
676 :group 'whitespace)
679 (defvar whitespace-indentation 'whitespace-indentation
680 "Symbol face used to visualize 8 or more SPACEs at beginning of line.
681 Used when `whitespace-style' includes the value `indentation'.")
682 (make-obsolete-variable 'whitespace-indentation "use the face instead." "24.4")
684 (defface whitespace-indentation
685 '((((class mono)) :inverse-video t :weight bold :underline t)
686 (t :background "yellow" :foreground "firebrick"))
687 "Face used to visualize 8 or more SPACEs at beginning of line."
688 :group 'whitespace)
690 (defface whitespace-big-indent
691 '((((class mono)) :inverse-video t :weight bold :underline t)
692 (t :background "red" :foreground "firebrick"))
693 "Face used to visualize big indentation."
694 :group 'whitespace)
697 (defvar whitespace-empty 'whitespace-empty
698 "Symbol face used to visualize empty lines at beginning and/or end of buffer.
699 Used when `whitespace-style' includes the value `empty'.")
700 (make-obsolete-variable 'whitespace-empty "use the face instead." "24.4")
702 (defface whitespace-empty
703 '((((class mono)) :inverse-video t :weight bold :underline t)
704 (t :background "yellow" :foreground "firebrick"))
705 "Face used to visualize empty lines at beginning and/or end of buffer."
706 :group 'whitespace)
709 (defvar whitespace-space-after-tab 'whitespace-space-after-tab
710 "Symbol face used to visualize 8 or more SPACEs after TAB.
711 Used when `whitespace-style' includes the value `space-after-tab'.")
712 (make-obsolete-variable 'whitespace-space-after-tab
713 "use the face instead." "24.4")
715 (defface whitespace-space-after-tab
716 '((((class mono)) :inverse-video t :weight bold :underline t)
717 (t :background "yellow" :foreground "firebrick"))
718 "Face used to visualize 8 or more SPACEs after TAB."
719 :group 'whitespace)
722 (defcustom whitespace-hspace-regexp
723 "\\(\u00A0+\\)"
724 "Specify HARD SPACE characters regexp.
726 Here are some examples:
728 \"\\\\(^\\xA0+\\\\)\" \
729 visualize only leading HARD SPACEs.
730 \"\\\\(\\xA0+$\\\\)\" \
731 visualize only trailing HARD SPACEs.
732 \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\" \
733 visualize leading and/or trailing HARD SPACEs.
734 \"\\t\\\\(\\xA0+\\\\)\\t\" \
735 visualize only HARD SPACEs between TABs.
737 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
738 Use exactly one pair of enclosing \\\\( and \\\\).
740 Used when `whitespace-style' includes `spaces'."
741 :type '(regexp :tag "HARD SPACE Chars")
742 :group 'whitespace)
745 (defcustom whitespace-space-regexp "\\( +\\)"
746 "Specify SPACE characters regexp.
748 If you're using `mule' package, there may be other characters
749 besides \" \" that should be considered SPACE.
751 Here are some examples:
753 \"\\\\(^ +\\\\)\" visualize only leading SPACEs.
754 \"\\\\( +$\\\\)\" visualize only trailing SPACEs.
755 \"\\\\(^ +\\\\| +$\\\\)\" \
756 visualize leading and/or trailing SPACEs.
757 \"\\t\\\\( +\\\\)\\t\" visualize only SPACEs between TABs.
759 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
760 Use exactly one pair of enclosing \\\\( and \\\\).
762 Used when `whitespace-style' includes `spaces'."
763 :type '(regexp :tag "SPACE Chars")
764 :group 'whitespace)
767 (defcustom whitespace-tab-regexp "\\(\t+\\)"
768 "Specify TAB characters regexp.
770 If you're using `mule' package, there may be other characters
771 besides \"\\t\" that should be considered TAB.
773 Here are some examples:
775 \"\\\\(^\\t+\\\\)\" visualize only leading TABs.
776 \"\\\\(\\t+$\\\\)\" visualize only trailing TABs.
777 \"\\\\(^\\t+\\\\|\\t+$\\\\)\" \
778 visualize leading and/or trailing TABs.
779 \" \\\\(\\t+\\\\) \" visualize only TABs between SPACEs.
781 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
782 Use exactly one pair of enclosing \\\\( and \\\\).
784 Used when `whitespace-style' includes `tabs'."
785 :type '(regexp :tag "TAB Chars")
786 :group 'whitespace)
789 (defcustom whitespace-trailing-regexp
790 "\\([\t \u00A0]+\\)$"
791 "Specify trailing characters regexp.
793 There may be other characters besides:
795 \" \" \"\\t\" \"\\u00A0\"
797 that should be considered blank.
799 NOTE: Enclose always by \"\\\\(\" and \"\\\\)$\" the elements to highlight.
800 Use exactly one pair of enclosing elements above.
802 Used when `whitespace-style' includes `trailing'."
803 :type '(regexp :tag "Trailing Chars")
804 :group 'whitespace)
807 (defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
808 "Specify SPACEs before TAB regexp.
810 Used when `whitespace-style' includes `space-before-tab',
811 `space-before-tab::tab' or `space-before-tab::space'."
812 :type '(regexp :tag "SPACEs Before TAB")
813 :group 'whitespace)
816 (defcustom whitespace-indentation-regexp
817 '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
818 . "^ *\\(\t+\\)[^\n]")
819 "Specify regexp for 8 or more SPACEs at beginning of line.
821 It is a cons where the cons car is used for SPACEs visualization
822 and the cons cdr is used for TABs visualization.
824 Used when `whitespace-style' includes `indentation',
825 `indentation::tab' or `indentation::space'."
826 :type '(cons (string :tag "Indentation SPACEs")
827 (string :tag "Indentation TABs"))
828 :group 'whitespace)
831 (defcustom whitespace-empty-at-bob-regexp "^\\(\\([ \t]*\n\\)+\\)"
832 "Specify regexp for empty lines at beginning of buffer.
834 Used when `whitespace-style' includes `empty'."
835 :type '(regexp :tag "Empty Lines At Beginning Of Buffer")
836 :group 'whitespace)
839 (defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)"
840 "Specify regexp for empty lines at end of buffer.
842 Used when `whitespace-style' includes `empty'."
843 :type '(regexp :tag "Empty Lines At End Of Buffer")
844 :group 'whitespace)
847 (defcustom whitespace-space-after-tab-regexp
848 '("\t+\\(\\( \\{%d\\}\\)+\\)"
849 . "\\(\t+\\) +")
850 "Specify regexp for 8 or more SPACEs after TAB.
852 It is a cons where the cons car is used for SPACEs visualization
853 and the cons cdr is used for TABs visualization.
855 Used when `whitespace-style' includes `space-after-tab',
856 `space-after-tab::tab' or `space-after-tab::space'."
857 :type '(cons (string :tag "SPACEs After TAB")
858 string)
859 :group 'whitespace)
861 (defcustom whitespace-big-indent-regexp
862 "^\\(\\(?:\t\\{4,\\}\\| \\{32,\\}\\)[\t ]*\\)"
863 "Specify big indentation regexp.
865 If you're using `mule' package, there may be other characters
866 besides \"\\t\" that should be considered TAB.
868 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
869 Use exactly one pair of enclosing \\\\( and \\\\).
871 Used when `whitespace-style' includes `big-indent'."
872 :version "25.1"
873 :type '(regexp :tag "Detect too much indentation at the beginning of a line")
874 :group 'whitespace)
877 (defcustom whitespace-line-column 80
878 "Specify column beyond which the line is highlighted.
880 It must be an integer or nil. If nil, the `fill-column' variable value is
881 used.
883 Used when `whitespace-style' includes `lines' or `lines-tail'."
884 :type '(choice :tag "Line Length Limit"
885 (integer :tag "Line Length")
886 (const :tag "Use fill-column" nil))
887 :safe 'integerp
888 :group 'whitespace)
891 ;; Hacked from `visible-whitespace-mappings' in visws.el
892 (defcustom whitespace-display-mappings
894 (space-mark ?\ [?·] [?.]) ; space - middle dot
895 (space-mark ?\xA0 [?¤] [?_]) ; hard space - currency sign
896 ;; NEWLINE is displayed using the face `whitespace-newline'
897 (newline-mark ?\n [?$ ?\n]) ; eol - dollar sign
898 ;; (newline-mark ?\n [?↵ ?\n] [?$ ?\n]) ; eol - downwards arrow
899 ;; (newline-mark ?\n [?¶ ?\n] [?$ ?\n]) ; eol - pilcrow
900 ;; (newline-mark ?\n [?¯ ?\n] [?$ ?\n]) ; eol - overscore
901 ;; (newline-mark ?\n [?¬ ?\n] [?$ ?\n]) ; eol - negation
902 ;; (newline-mark ?\n [?° ?\n] [?$ ?\n]) ; eol - degrees
904 ;; WARNING: the mapping below has a problem.
905 ;; When a TAB occupies exactly one column, it will display the
906 ;; character ?\xBB at that column followed by a TAB which goes to
907 ;; the next TAB column.
908 ;; If this is a problem for you, please, comment the line below.
909 (tab-mark ?\t [?» ?\t] [?\\ ?\t]) ; tab - right guillemet
911 "Specify an alist of mappings for displaying characters.
913 Each element has the following form:
915 (KIND CHAR VECTOR...)
917 Where:
919 KIND is the kind of character.
920 It can be one of the following symbols:
922 tab-mark for TAB character
924 space-mark for SPACE or HARD SPACE character
926 newline-mark for NEWLINE character
928 CHAR is the character to be mapped.
930 VECTOR is a vector of characters to be displayed in place of CHAR.
931 The first display vector that can be displayed is used;
932 if no display vector for a mapping can be displayed, then
933 that character is displayed unmodified.
935 The NEWLINE character is displayed using the face given by
936 `whitespace-newline' variable.
938 Used when `whitespace-style' includes `tab-mark', `space-mark' or
939 `newline-mark'."
940 :type '(repeat
941 (list :tag "Character Mapping"
942 (choice :tag "Char Kind"
943 (const :tag "Tab" tab-mark)
944 (const :tag "Space" space-mark)
945 (const :tag "Newline" newline-mark))
946 (character :tag "Char")
947 (repeat :inline t :tag "Vector List"
948 (vector :tag ""
949 (repeat :inline t
950 :tag "Vector Characters"
951 (character :tag "Char"))))))
952 :group 'whitespace)
955 (defcustom whitespace-global-modes t
956 "Modes for which global `whitespace-mode' is automagically turned on.
958 Global `whitespace-mode' is controlled by the command
959 `global-whitespace-mode'.
961 If nil, means no modes have `whitespace-mode' automatically
962 turned on.
964 If t, all modes that support `whitespace-mode' have it
965 automatically turned on.
967 Else it should be a list of `major-mode' symbol names for which
968 `whitespace-mode' should be automatically turned on. The sense
969 of the list is negated if it begins with `not'. For example:
971 (c-mode c++-mode)
973 means that `whitespace-mode' is turned on for buffers in C and
974 C++ modes only."
975 :type '(choice :tag "Global Modes"
976 (const :tag "None" nil)
977 (const :tag "All" t)
978 (set :menu-tag "Mode Specific" :tag "Modes"
979 :value (not)
980 (const :tag "Except" not)
981 (repeat :inline t
982 (symbol :tag "Mode"))))
983 :group 'whitespace)
986 (defcustom whitespace-action nil
987 "Specify which action is taken when a buffer is visited or written.
989 It's a list containing some or all of the following values:
991 nil no action is taken.
993 cleanup cleanup any bogus whitespace always when local
994 whitespace is turned on.
995 See `whitespace-cleanup' and
996 `whitespace-cleanup-region'.
998 report-on-bogus report if there is any bogus whitespace always
999 when local whitespace is turned on.
1001 auto-cleanup cleanup any bogus whitespace when buffer is
1002 written.
1003 See `whitespace-cleanup' and
1004 `whitespace-cleanup-region'.
1006 abort-on-bogus abort if there is any bogus whitespace and the
1007 buffer is written.
1009 warn-if-read-only give a warning if `cleanup' or `auto-cleanup'
1010 is included in `whitespace-action' and the
1011 buffer is read-only.
1013 Any other value is treated as nil."
1014 :type '(choice :tag "Actions"
1015 (const :tag "None" nil)
1016 (repeat :tag "Action List"
1017 (choice :tag "Action"
1018 (const :tag "Cleanup When On" cleanup)
1019 (const :tag "Report On Bogus" report-on-bogus)
1020 (const :tag "Auto Cleanup" auto-cleanup)
1021 (const :tag "Abort On Bogus" abort-on-bogus)
1022 (const :tag "Warn If Read-Only" warn-if-read-only))))
1023 :group 'whitespace)
1026 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1027 ;;;; User commands - Local mode
1030 ;;;###autoload
1031 (define-minor-mode whitespace-mode
1032 "Toggle whitespace visualization (Whitespace mode).
1033 With a prefix argument ARG, enable Whitespace mode if ARG is
1034 positive, and disable it otherwise.
1036 If called from Lisp, also enables the mode if ARG is omitted or nil,
1037 and toggles it if ARG is `toggle'.
1039 See also `whitespace-style', `whitespace-newline' and
1040 `whitespace-display-mappings'."
1041 :lighter " ws"
1042 :init-value nil
1043 :global nil
1044 :group 'whitespace
1045 (cond
1046 (noninteractive ; running a batch job
1047 (setq whitespace-mode nil))
1048 (whitespace-mode ; whitespace-mode on
1049 (whitespace-turn-on)
1050 (whitespace-action-when-on))
1051 (t ; whitespace-mode off
1052 (whitespace-turn-off))))
1055 ;;;###autoload
1056 (define-minor-mode whitespace-newline-mode
1057 "Toggle newline visualization (Whitespace Newline mode).
1058 With a prefix argument ARG, enable Whitespace Newline mode if ARG
1059 is positive, and disable it otherwise.
1061 If called from Lisp, also enables the mode if ARG is omitted or nil,
1062 and toggles it if ARG is `toggle'.
1064 Use `whitespace-newline-mode' only for NEWLINE visualization
1065 exclusively. For other visualizations, including NEWLINE
1066 visualization together with (HARD) SPACEs and/or TABs, please,
1067 use `whitespace-mode'.
1069 See also `whitespace-newline' and `whitespace-display-mappings'."
1070 :lighter " nl"
1071 :init-value nil
1072 :global nil
1073 :group 'whitespace
1074 (let ((whitespace-style '(face newline-mark newline)))
1075 (whitespace-mode (if whitespace-newline-mode
1076 1 -1)))
1077 ;; sync states (running a batch job)
1078 (setq whitespace-newline-mode whitespace-mode))
1081 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1082 ;;;; User commands - Global mode
1085 ;;;###autoload
1086 (define-minor-mode global-whitespace-mode
1087 "Toggle whitespace visualization globally (Global Whitespace mode).
1088 With a prefix argument ARG, enable Global Whitespace mode if ARG
1089 is positive, and disable it otherwise.
1091 If called from Lisp, also enables the mode if ARG is omitted or nil,
1092 and toggles it if ARG is `toggle'.
1094 See also `whitespace-style', `whitespace-newline' and
1095 `whitespace-display-mappings'."
1096 :lighter " WS"
1097 :init-value nil
1098 :global t
1099 :group 'whitespace
1100 (cond
1101 (noninteractive ; running a batch job
1102 (setq global-whitespace-mode nil))
1103 (global-whitespace-mode ; global-whitespace-mode on
1104 (save-current-buffer
1105 (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
1106 (add-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
1107 (dolist (buffer (buffer-list)) ; adjust all local mode
1108 (set-buffer buffer)
1109 (unless whitespace-mode
1110 (whitespace-turn-on-if-enabled)))))
1111 (t ; global-whitespace-mode off
1112 (save-current-buffer
1113 (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
1114 (remove-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
1115 (dolist (buffer (buffer-list)) ; adjust all local mode
1116 (set-buffer buffer)
1117 (unless whitespace-mode
1118 (whitespace-turn-off)))))))
1120 (defvar whitespace-enable-predicate
1121 (lambda ()
1122 (and (cond
1123 ((eq whitespace-global-modes t))
1124 ((listp whitespace-global-modes)
1125 (if (eq (car-safe whitespace-global-modes) 'not)
1126 (not (memq major-mode (cdr whitespace-global-modes)))
1127 (memq major-mode whitespace-global-modes)))
1128 (t nil))
1129 ;; ...we have a display (not running a batch job)
1130 (not noninteractive)
1131 ;; ...the buffer is not internal (name starts with a space)
1132 (not (eq (aref (buffer-name) 0) ?\ ))
1133 ;; ...the buffer is not special (name starts with *)
1134 (or (not (eq (aref (buffer-name) 0) ?*))
1135 ;; except the scratch buffer.
1136 (string= (buffer-name) "*scratch*"))))
1137 "Predicate to decide which buffers obey `global-whitespace-mode'.
1138 This function is called with no argument and should return non-nil
1139 if the current buffer should obey `global-whitespace-mode'.
1140 This variable is normally modified via `add-function'.")
1142 (defun whitespace-turn-on-if-enabled ()
1143 (when (funcall whitespace-enable-predicate)
1144 (whitespace-turn-on)))
1146 ;;;###autoload
1147 (define-minor-mode global-whitespace-newline-mode
1148 "Toggle global newline visualization (Global Whitespace Newline mode).
1149 With a prefix argument ARG, enable Global Whitespace Newline mode
1150 if ARG is positive, and disable it otherwise.
1152 If called from Lisp, also enables the mode if ARG is omitted or nil,
1153 and toggles it if ARG is `toggle'.
1155 Use `global-whitespace-newline-mode' only for NEWLINE
1156 visualization exclusively. For other visualizations, including
1157 NEWLINE visualization together with (HARD) SPACEs and/or TABs,
1158 please use `global-whitespace-mode'.
1160 See also `whitespace-newline' and `whitespace-display-mappings'."
1161 :lighter " NL"
1162 :init-value nil
1163 :global t
1164 :group 'whitespace
1165 (let ((whitespace-style '(newline-mark newline)))
1166 (global-whitespace-mode (if global-whitespace-newline-mode
1167 1 -1))
1168 ;; sync states (running a batch job)
1169 (setq global-whitespace-newline-mode global-whitespace-mode)))
1172 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1173 ;;;; User commands - Toggle
1176 (defconst whitespace-style-value-list
1177 '(face
1178 tabs
1179 spaces
1180 trailing
1181 lines
1182 lines-tail
1183 newline
1184 empty
1185 indentation
1186 indentation::tab
1187 indentation::space
1188 big-indent
1189 space-after-tab
1190 space-after-tab::tab
1191 space-after-tab::space
1192 space-before-tab
1193 space-before-tab::tab
1194 space-before-tab::space
1195 help-newline ; value used by `whitespace-insert-option-mark'
1196 tab-mark
1197 space-mark
1198 newline-mark
1200 "List of valid `whitespace-style' values.")
1203 (defconst whitespace-toggle-option-alist
1204 '((?f . face)
1205 (?t . tabs)
1206 (?s . spaces)
1207 (?r . trailing)
1208 (?l . lines)
1209 (?L . lines-tail)
1210 (?n . newline)
1211 (?e . empty)
1212 (?\C-i . indentation)
1213 (?I . indentation::tab)
1214 (?i . indentation::space)
1215 (?\C-t . big-indent)
1216 (?\C-a . space-after-tab)
1217 (?A . space-after-tab::tab)
1218 (?a . space-after-tab::space)
1219 (?\C-b . space-before-tab)
1220 (?B . space-before-tab::tab)
1221 (?b . space-before-tab::space)
1222 (?T . tab-mark)
1223 (?S . space-mark)
1224 (?N . newline-mark)
1225 (?x . whitespace-style)
1227 "Alist of toggle options.
1229 Each element has the form:
1231 (CHAR . SYMBOL)
1233 Where:
1235 CHAR is a char which the user will have to type.
1237 SYMBOL is a valid symbol associated with CHAR.
1238 See `whitespace-style-value-list'.")
1241 (defvar whitespace-active-style nil
1242 "Used to save locally `whitespace-style' value.")
1244 (defvar whitespace-indent-tabs-mode indent-tabs-mode
1245 "Used to save locally `indent-tabs-mode' value.")
1247 (defvar whitespace-tab-width tab-width
1248 "Used to save locally `tab-width' value.")
1250 (defvar whitespace-point (point)
1251 "Used to save locally current point value.
1252 Used by function `whitespace-trailing-regexp' (which see).")
1253 (defvar-local whitespace-point--used nil
1254 "Region whose highlighting depends on `whitespace-point'.")
1256 (defvar whitespace-font-lock-refontify nil
1257 "Used to save locally the font-lock refontify state.
1258 Used by function `whitespace-post-command-hook' (which see).")
1260 (defvar whitespace-bob-marker nil
1261 "Used to save locally the bob marker value.
1262 Used by function `whitespace-post-command-hook' (which see).")
1264 (defvar whitespace-eob-marker nil
1265 "Used to save locally the eob marker value.
1266 Used by function `whitespace-post-command-hook' (which see).")
1268 (defvar whitespace-buffer-changed nil
1269 "Used to indicate locally if buffer changed.
1270 Used by `whitespace-post-command-hook' and `whitespace-buffer-changed'
1271 functions (which see).")
1274 ;;;###autoload
1275 (defun whitespace-toggle-options (arg)
1276 "Toggle local `whitespace-mode' options.
1278 If local whitespace-mode is off, toggle the option given by ARG
1279 and turn on local whitespace-mode.
1281 If local whitespace-mode is on, toggle the option given by ARG
1282 and restart local whitespace-mode.
1284 Interactively, it reads one of the following chars:
1286 CHAR MEANING
1287 (VIA FACES)
1288 f toggle face visualization
1289 t toggle TAB visualization
1290 s toggle SPACE and HARD SPACE visualization
1291 r toggle trailing blanks visualization
1292 l toggle \"long lines\" visualization
1293 L toggle \"long lines\" tail visualization
1294 n toggle NEWLINE visualization
1295 e toggle empty line at bob and/or eob visualization
1296 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1297 I toggle indentation SPACEs visualization
1298 i toggle indentation TABs visualization
1299 C-t toggle big indentation visualization
1300 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1301 A toggle SPACEs after TAB: SPACEs visualization
1302 a toggle SPACEs after TAB: TABs visualization
1303 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1304 B toggle SPACEs before TAB: SPACEs visualization
1305 b toggle SPACEs before TAB: TABs visualization
1307 (VIA DISPLAY TABLE)
1308 T toggle TAB visualization
1309 S toggle SPACEs before TAB visualization
1310 N toggle NEWLINE visualization
1312 x restore `whitespace-style' value
1313 ? display brief help
1315 Non-interactively, ARG should be a symbol or a list of symbols.
1316 The valid symbols are:
1318 face toggle face visualization
1319 tabs toggle TAB visualization
1320 spaces toggle SPACE and HARD SPACE visualization
1321 trailing toggle trailing blanks visualization
1322 lines toggle \"long lines\" visualization
1323 lines-tail toggle \"long lines\" tail visualization
1324 newline toggle NEWLINE visualization
1325 empty toggle empty line at bob and/or eob visualization
1326 indentation toggle indentation SPACEs visualization
1327 indentation::tab toggle indentation SPACEs visualization
1328 indentation::space toggle indentation TABs visualization
1329 big-indent toggle big indentation visualization
1330 space-after-tab toggle SPACEs after TAB visualization
1331 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1332 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1333 space-before-tab toggle SPACEs before TAB visualization
1334 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1335 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1337 tab-mark toggle TAB visualization
1338 space-mark toggle SPACEs before TAB visualization
1339 newline-mark toggle NEWLINE visualization
1341 whitespace-style restore `whitespace-style' value
1343 See `whitespace-style' and `indent-tabs-mode' for documentation."
1344 (interactive (whitespace-interactive-char t))
1345 (let ((whitespace-style
1346 (whitespace-toggle-list t arg whitespace-active-style)))
1347 (whitespace-mode 0)
1348 (whitespace-mode 1)))
1351 (defvar whitespace-toggle-style nil
1352 "Used to toggle the global `whitespace-style' value.")
1355 ;;;###autoload
1356 (defun global-whitespace-toggle-options (arg)
1357 "Toggle global `whitespace-mode' options.
1359 If global whitespace-mode is off, toggle the option given by ARG
1360 and turn on global whitespace-mode.
1362 If global whitespace-mode is on, toggle the option given by ARG
1363 and restart global whitespace-mode.
1365 Interactively, it accepts one of the following chars:
1367 CHAR MEANING
1368 (VIA FACES)
1369 f toggle face visualization
1370 t toggle TAB visualization
1371 s toggle SPACE and HARD SPACE visualization
1372 r toggle trailing blanks visualization
1373 l toggle \"long lines\" visualization
1374 L toggle \"long lines\" tail visualization
1375 n toggle NEWLINE visualization
1376 e toggle empty line at bob and/or eob visualization
1377 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1378 I toggle indentation SPACEs visualization
1379 i toggle indentation TABs visualization
1380 C-t toggle big indentation visualization
1381 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1382 A toggle SPACEs after TAB: SPACEs visualization
1383 a toggle SPACEs after TAB: TABs visualization
1384 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1385 B toggle SPACEs before TAB: SPACEs visualization
1386 b toggle SPACEs before TAB: TABs visualization
1388 (VIA DISPLAY TABLE)
1389 T toggle TAB visualization
1390 S toggle SPACEs before TAB visualization
1391 N toggle NEWLINE visualization
1393 x restore `whitespace-style' value
1394 ? display brief help
1396 Non-interactively, ARG should be a symbol or a list of symbols.
1397 The valid symbols are:
1399 face toggle face visualization
1400 tabs toggle TAB visualization
1401 spaces toggle SPACE and HARD SPACE visualization
1402 trailing toggle trailing blanks visualization
1403 lines toggle \"long lines\" visualization
1404 lines-tail toggle \"long lines\" tail visualization
1405 newline toggle NEWLINE visualization
1406 empty toggle empty line at bob and/or eob visualization
1407 indentation toggle indentation SPACEs visualization
1408 indentation::tab toggle indentation SPACEs visualization
1409 indentation::space toggle indentation TABs visualization
1410 big-indent toggle big indentation visualization
1411 space-after-tab toggle SPACEs after TAB visualization
1412 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1413 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1414 space-before-tab toggle SPACEs before TAB visualization
1415 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1416 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1418 tab-mark toggle TAB visualization
1419 space-mark toggle SPACEs before TAB visualization
1420 newline-mark toggle NEWLINE visualization
1422 whitespace-style restore `whitespace-style' value
1424 See `whitespace-style' and `indent-tabs-mode' for documentation."
1425 (interactive (whitespace-interactive-char nil))
1426 (let ((whitespace-style
1427 (whitespace-toggle-list nil arg whitespace-toggle-style)))
1428 (setq whitespace-toggle-style whitespace-style)
1429 (global-whitespace-mode 0)
1430 (global-whitespace-mode 1)))
1433 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1434 ;;;; User commands - Cleanup
1437 ;;;###autoload
1438 (defun whitespace-cleanup ()
1439 "Cleanup some blank problems in all buffer or at region.
1441 It usually applies to the whole buffer, but in transient mark
1442 mode when the mark is active, it applies to the region. It also
1443 applies to the region when it is not in transient mark mode, the
1444 mark is active and \\[universal-argument] was pressed just before
1445 calling `whitespace-cleanup' interactively.
1447 See also `whitespace-cleanup-region'.
1449 The problems cleaned up are:
1451 1. empty lines at beginning of buffer.
1452 2. empty lines at end of buffer.
1453 If `whitespace-style' includes the value `empty', remove all
1454 empty lines at beginning and/or end of buffer.
1456 3. 8 or more SPACEs at beginning of line.
1457 If `whitespace-style' includes the value `indentation':
1458 replace 8 or more SPACEs at beginning of line by TABs, if
1459 `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1460 SPACEs.
1461 If `whitespace-style' includes the value `indentation::tab',
1462 replace 8 or more SPACEs at beginning of line by TABs.
1463 If `whitespace-style' includes the value `indentation::space',
1464 replace TABs by SPACEs.
1466 4. SPACEs before TAB.
1467 If `whitespace-style' includes the value `space-before-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-before-tab::tab', replace SPACEs by TABs.
1472 If `whitespace-style' includes the value
1473 `space-before-tab::space', replace TABs by SPACEs.
1475 5. SPACEs or TABs at end of line.
1476 If `whitespace-style' includes the value `trailing', remove
1477 all SPACEs or TABs at end of line.
1479 6. 8 or more SPACEs after TAB.
1480 If `whitespace-style' includes the value `space-after-tab':
1481 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1482 otherwise, replace TABs by SPACEs.
1483 If `whitespace-style' includes the value
1484 `space-after-tab::tab', replace SPACEs by TABs.
1485 If `whitespace-style' includes the value
1486 `space-after-tab::space', replace TABs by SPACEs.
1488 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1489 documentation."
1490 (interactive "@")
1491 (cond
1492 ;; read-only buffer
1493 (buffer-read-only
1494 (whitespace-warn-read-only "cleanup"))
1495 ;; region active
1496 ((and (or transient-mark-mode
1497 current-prefix-arg)
1498 mark-active)
1499 ;; PROBLEMs 1 and 2 are not handled in region
1500 ;; PROBLEM 3: 8 or more SPACEs at bol
1501 ;; PROBLEM 4: SPACEs before TAB
1502 ;; PROBLEM 5: SPACEs or TABs at eol
1503 ;; PROBLEM 6: 8 or more SPACEs after TAB
1504 (whitespace-cleanup-region (region-beginning) (region-end)))
1505 ;; whole buffer
1507 (save-excursion
1508 (save-match-data ;FIXME: Why?
1509 ;; PROBLEM 1: empty lines at bob
1510 ;; PROBLEM 2: empty lines at eob
1511 ;; ACTION: remove all empty lines at bob and/or eob
1512 (when (memq 'empty whitespace-style)
1513 (let (overwrite-mode) ; enforce no overwrite
1514 (goto-char (point-min))
1515 (when (looking-at whitespace-empty-at-bob-regexp)
1516 (delete-region (match-beginning 1) (match-end 1)))
1517 (when (re-search-forward
1518 (concat whitespace-empty-at-eob-regexp "\\'") nil t)
1519 (delete-region (match-beginning 1) (match-end 1)))))))
1520 ;; PROBLEM 3: 8 or more SPACEs at bol
1521 ;; PROBLEM 4: SPACEs before TAB
1522 ;; PROBLEM 5: SPACEs or TABs at eol
1523 ;; PROBLEM 6: 8 or more SPACEs after TAB
1524 (whitespace-cleanup-region (point-min) (point-max)))))
1526 (defun whitespace-ensure-local-variables ()
1527 "Set `whitespace-indent-tabs-mode' and `whitespace-tab-width' locally."
1528 (set (make-local-variable 'whitespace-indent-tabs-mode)
1529 indent-tabs-mode)
1530 (set (make-local-variable 'whitespace-tab-width)
1531 tab-width))
1533 ;;;###autoload
1534 (defun whitespace-cleanup-region (start end)
1535 "Cleanup some blank problems at region.
1537 The problems cleaned up are:
1539 1. 8 or more SPACEs at beginning of line.
1540 If `whitespace-style' includes the value `indentation':
1541 replace 8 or more SPACEs at beginning of line by TABs, if
1542 `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1543 SPACEs.
1544 If `whitespace-style' includes the value `indentation::tab',
1545 replace 8 or more SPACEs at beginning of line by TABs.
1546 If `whitespace-style' includes the value `indentation::space',
1547 replace TABs by SPACEs.
1549 2. SPACEs before TAB.
1550 If `whitespace-style' includes the value `space-before-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-before-tab::tab', replace SPACEs by TABs.
1555 If `whitespace-style' includes the value
1556 `space-before-tab::space', replace TABs by SPACEs.
1558 3. SPACEs or TABs at end of line.
1559 If `whitespace-style' includes the value `trailing', remove
1560 all SPACEs or TABs at end of line.
1562 4. 8 or more SPACEs after TAB.
1563 If `whitespace-style' includes the value `space-after-tab':
1564 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1565 otherwise, replace TABs by SPACEs.
1566 If `whitespace-style' includes the value
1567 `space-after-tab::tab', replace SPACEs by TABs.
1568 If `whitespace-style' includes the value
1569 `space-after-tab::space', replace TABs by SPACEs.
1571 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1572 documentation."
1573 (interactive "@r")
1574 (if buffer-read-only
1575 ;; read-only buffer
1576 (whitespace-warn-read-only "cleanup region")
1577 ;; non-read-only buffer
1578 (whitespace-ensure-local-variables)
1579 (let ((rstart (min start end))
1580 (rend (copy-marker (max start end)))
1581 (indent-tabs-mode whitespace-indent-tabs-mode)
1582 (tab-width whitespace-tab-width)
1583 overwrite-mode ; enforce no overwrite
1584 tmp)
1585 (save-excursion
1586 (save-match-data ;FIXME: Why?
1587 ;; PROBLEM 1: 8 or more SPACEs at bol
1588 (cond
1589 ;; ACTION: replace 8 or more SPACEs at bol by TABs, if
1590 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1591 ;; by SPACEs.
1592 ((memq 'indentation whitespace-style)
1593 (let ((regexp (whitespace-indentation-regexp)))
1594 (goto-char rstart)
1595 (while (re-search-forward regexp rend t)
1596 (setq tmp (current-indentation))
1597 (goto-char (match-beginning 0))
1598 (delete-horizontal-space)
1599 (unless (eolp)
1600 (indent-to tmp)))))
1601 ;; ACTION: replace 8 or more SPACEs at bol by TABs.
1602 ((memq 'indentation::tab whitespace-style)
1603 (whitespace-replace-action
1604 'tabify rstart rend
1605 (whitespace-indentation-regexp 'tab) 0))
1606 ;; ACTION: replace TABs by SPACEs.
1607 ((memq 'indentation::space whitespace-style)
1608 (whitespace-replace-action
1609 'untabify rstart rend
1610 (whitespace-indentation-regexp 'space) 0)))
1611 ;; PROBLEM 3: SPACEs or TABs at eol
1612 ;; ACTION: remove all SPACEs or TABs at eol
1613 (when (memq 'trailing whitespace-style)
1614 (whitespace-replace-action
1615 'delete-region rstart rend
1616 whitespace-trailing-regexp 1))
1617 ;; PROBLEM 4: 8 or more SPACEs after TAB
1618 (cond
1619 ;; ACTION: replace 8 or more SPACEs by TABs, if
1620 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1621 ;; by SPACEs.
1622 ((memq 'space-after-tab whitespace-style)
1623 (whitespace-replace-action
1624 (if whitespace-indent-tabs-mode 'tabify 'untabify)
1625 rstart rend (whitespace-space-after-tab-regexp) 1))
1626 ;; ACTION: replace 8 or more SPACEs by TABs.
1627 ((memq 'space-after-tab::tab whitespace-style)
1628 (whitespace-replace-action
1629 'tabify rstart rend
1630 (whitespace-space-after-tab-regexp 'tab) 1))
1631 ;; ACTION: replace TABs by SPACEs.
1632 ((memq 'space-after-tab::space whitespace-style)
1633 (whitespace-replace-action
1634 'untabify rstart rend
1635 (whitespace-space-after-tab-regexp 'space) 1)))
1636 ;; PROBLEM 2: SPACEs before TAB
1637 (cond
1638 ;; ACTION: replace SPACEs before TAB by TABs, if
1639 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1640 ;; by SPACEs.
1641 ((memq 'space-before-tab whitespace-style)
1642 (whitespace-replace-action
1643 (if whitespace-indent-tabs-mode 'tabify 'untabify)
1644 rstart rend whitespace-space-before-tab-regexp
1645 (if whitespace-indent-tabs-mode 0 2)))
1646 ;; ACTION: replace SPACEs before TAB by TABs.
1647 ((memq 'space-before-tab::tab whitespace-style)
1648 (whitespace-replace-action
1649 'tabify rstart rend
1650 whitespace-space-before-tab-regexp 0))
1651 ;; ACTION: replace TABs by SPACEs.
1652 ((memq 'space-before-tab::space whitespace-style)
1653 (whitespace-replace-action
1654 'untabify rstart rend
1655 whitespace-space-before-tab-regexp 2)))))
1656 (set-marker rend nil)))) ; point marker to nowhere
1659 (defun whitespace-replace-action (action rstart rend regexp index)
1660 "Do ACTION in the string matched by REGEXP between RSTART and REND.
1662 INDEX is the level group matched by REGEXP and used by ACTION.
1664 See also `tab-width'."
1665 (goto-char rstart)
1666 (while (re-search-forward regexp rend t)
1667 (goto-char (match-end index))
1668 (funcall action (match-beginning index) (match-end index))))
1671 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1672 ;;;; User command - report
1675 (defun whitespace-regexp (regexp &optional kind)
1676 "Return REGEXP depending on `whitespace-indent-tabs-mode'."
1677 (cond
1678 ((or (eq kind 'tab)
1679 whitespace-indent-tabs-mode)
1680 (format (car regexp) whitespace-tab-width))
1681 ((or (eq kind 'space)
1682 (not whitespace-indent-tabs-mode))
1683 (cdr regexp))))
1686 (defun whitespace-indentation-regexp (&optional kind)
1687 "Return the indentation regexp depending on `whitespace-indent-tabs-mode'."
1688 (whitespace-regexp whitespace-indentation-regexp kind))
1691 (defun whitespace-space-after-tab-regexp (&optional kind)
1692 "Return the space-after-tab regexp depending on `whitespace-indent-tabs-mode'."
1693 (whitespace-regexp whitespace-space-after-tab-regexp kind))
1696 (defconst whitespace-report-list
1697 (list
1698 (cons 'empty whitespace-empty-at-bob-regexp)
1699 (cons 'empty whitespace-empty-at-eob-regexp)
1700 (cons 'trailing whitespace-trailing-regexp)
1701 (cons 'indentation nil)
1702 (cons 'indentation::tab nil)
1703 (cons 'indentation::space nil)
1704 (cons 'space-before-tab whitespace-space-before-tab-regexp)
1705 (cons 'space-before-tab::tab whitespace-space-before-tab-regexp)
1706 (cons 'space-before-tab::space whitespace-space-before-tab-regexp)
1707 (cons 'space-after-tab nil)
1708 (cons 'space-after-tab::tab nil)
1709 (cons 'space-after-tab::space nil)
1711 "List of whitespace bogus symbol and corresponding regexp.")
1714 (defconst whitespace-report-text
1715 '( ;; `indent-tabs-mode' has non-nil value
1717 Whitespace Report
1719 Current Setting Whitespace Problem
1721 empty [] [] empty lines at beginning of buffer
1722 empty [] [] empty lines at end of buffer
1723 trailing [] [] SPACEs or TABs at end of line
1724 indentation [] [] 8 or more SPACEs at beginning of line
1725 indentation::tab [] [] 8 or more SPACEs at beginning of line
1726 indentation::space [] [] TABs at beginning of line
1727 space-before-tab [] [] SPACEs before TAB
1728 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1729 space-before-tab::space [] [] SPACEs before TAB: TABs
1730 space-after-tab [] [] 8 or more SPACEs after TAB
1731 space-after-tab::tab [] [] 8 or more SPACEs after TAB: SPACEs
1732 space-after-tab::space [] [] 8 or more SPACEs after TAB: TABs
1734 indent-tabs-mode =
1735 tab-width = \n\n"
1736 . ;; `indent-tabs-mode' has nil value
1738 Whitespace Report
1740 Current Setting Whitespace Problem
1742 empty [] [] empty lines at beginning of buffer
1743 empty [] [] empty lines at end of buffer
1744 trailing [] [] SPACEs or TABs at end of line
1745 indentation [] [] TABs at beginning of line
1746 indentation::tab [] [] 8 or more SPACEs at beginning of line
1747 indentation::space [] [] TABs at beginning of line
1748 space-before-tab [] [] SPACEs before TAB
1749 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1750 space-before-tab::space [] [] SPACEs before TAB: TABs
1751 space-after-tab [] [] 8 or more SPACEs after TAB
1752 space-after-tab::tab [] [] 8 or more SPACEs after TAB: SPACEs
1753 space-after-tab::space [] [] 8 or more SPACEs after TAB: TABs
1755 indent-tabs-mode =
1756 tab-width = \n\n")
1757 "Text for whitespace bogus report.
1759 It is a cons of strings, where the car part is used when
1760 `indent-tabs-mode' is non-nil, and the cdr part is used when
1761 `indent-tabs-mode' is nil.")
1764 (defconst whitespace-report-buffer-name "*Whitespace Report*"
1765 "The buffer name for whitespace bogus report.")
1768 ;;;###autoload
1769 (defun whitespace-report (&optional force report-if-bogus)
1770 "Report some whitespace problems in buffer.
1772 Perform `whitespace-report-region' on the current buffer."
1773 (interactive (list current-prefix-arg))
1774 (whitespace-report-region (point-min) (point-max)
1775 force report-if-bogus))
1778 ;;;###autoload
1779 (defun whitespace-report-region (start end &optional force report-if-bogus)
1780 "Report some whitespace problems in a region.
1782 Return nil if there is no whitespace problem; otherwise, return
1783 non-nil.
1785 If FORCE is non-nil or \\[universal-argument] was pressed just
1786 before calling `whitespace-report-region' interactively, it
1787 forces `whitespace-style' to have:
1789 empty
1790 trailing
1791 indentation
1792 space-before-tab
1793 space-after-tab
1795 If REPORT-IF-BOGUS is t, it reports only when there are any
1796 whitespace problems in buffer; if it is `never', it does not
1797 report problems.
1799 Report if some of the following whitespace problems exist:
1801 * If `indent-tabs-mode' is non-nil:
1802 empty 1. empty lines at beginning of buffer.
1803 empty 2. empty lines at end of buffer.
1804 trailing 3. SPACEs or TABs at end of line.
1805 indentation 4. 8 or more SPACEs at beginning of line.
1806 space-before-tab 5. SPACEs before TAB.
1807 space-after-tab 6. 8 or more SPACEs after TAB.
1809 * If `indent-tabs-mode' is nil:
1810 empty 1. empty lines at beginning of buffer.
1811 empty 2. empty lines at end of buffer.
1812 trailing 3. SPACEs or TABs at end of line.
1813 indentation 4. TABS at beginning of line.
1814 space-before-tab 5. SPACEs before TAB.
1815 space-after-tab 6. 8 or more SPACEs after TAB.
1817 See `whitespace-style' for documentation.
1818 See also `whitespace-cleanup' and `whitespace-cleanup-region' for
1819 cleaning up these problems."
1820 (interactive "r")
1821 (setq force (or current-prefix-arg force))
1822 (save-excursion
1823 (save-match-data ;FIXME: Why?
1824 (let* ((has-bogus nil)
1825 (rstart (min start end))
1826 (rend (max start end))
1827 (bogus-list
1828 (mapcar
1829 #'(lambda (option)
1830 (when force
1831 (add-to-list 'whitespace-style (car option)))
1832 (goto-char rstart)
1833 (let ((regexp
1834 (cond
1835 ((eq (car option) 'indentation)
1836 (whitespace-indentation-regexp))
1837 ((eq (car option) 'indentation::tab)
1838 (whitespace-indentation-regexp 'tab))
1839 ((eq (car option) 'indentation::space)
1840 (whitespace-indentation-regexp 'space))
1841 ((eq (car option) 'space-after-tab)
1842 (whitespace-space-after-tab-regexp))
1843 ((eq (car option) 'space-after-tab::tab)
1844 (whitespace-space-after-tab-regexp 'tab))
1845 ((eq (car option) 'space-after-tab::space)
1846 (whitespace-space-after-tab-regexp 'space))
1848 (cdr option)))))
1849 (and (re-search-forward regexp rend t)
1850 (setq has-bogus t))))
1851 whitespace-report-list)))
1852 (when (pcase report-if-bogus (`nil t) (`never nil) (_ has-bogus))
1853 (whitespace-kill-buffer whitespace-report-buffer-name)
1854 ;; `whitespace-indent-tabs-mode' is local to current buffer
1855 ;; `whitespace-tab-width' is local to current buffer
1856 (let ((ws-indent-tabs-mode whitespace-indent-tabs-mode)
1857 (ws-tab-width whitespace-tab-width))
1858 (with-current-buffer (get-buffer-create
1859 whitespace-report-buffer-name)
1860 (erase-buffer)
1861 (insert (if ws-indent-tabs-mode
1862 (car whitespace-report-text)
1863 (cdr whitespace-report-text)))
1864 (goto-char (point-min))
1865 (forward-line 3)
1866 (dolist (option whitespace-report-list)
1867 (forward-line 1)
1868 (whitespace-mark-x
1869 27 (memq (car option) whitespace-style))
1870 (whitespace-mark-x 7 (car bogus-list))
1871 (setq bogus-list (cdr bogus-list)))
1872 (forward-line 1)
1873 (whitespace-insert-value ws-indent-tabs-mode)
1874 (whitespace-insert-value ws-tab-width)
1875 (when has-bogus
1876 (goto-char (point-max))
1877 (insert (substitute-command-keys
1878 " Type `\\[whitespace-cleanup]'")
1879 " to cleanup the buffer.\n\n"
1880 (substitute-command-keys
1881 " Type `\\[whitespace-cleanup-region]'")
1882 " to cleanup a region.\n\n"))
1883 (whitespace-display-window (current-buffer)))))
1884 has-bogus))))
1887 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1888 ;;;; Internal functions
1891 (defvar whitespace-font-lock-keywords nil
1892 "Used to save the value `whitespace-color-on' adds to `font-lock-keywords'.")
1895 (defconst whitespace-help-text
1897 Whitespace Toggle Options | scroll up : SPC or > |
1898 | scroll down: M-SPC or < |
1899 FACES \\__________________________/
1900 [] f - toggle face visualization
1901 [] t - toggle TAB visualization
1902 [] s - toggle SPACE and HARD SPACE visualization
1903 [] r - toggle trailing blanks visualization
1904 [] l - toggle \"long lines\" visualization
1905 [] L - toggle \"long lines\" tail visualization
1906 [] n - toggle NEWLINE visualization
1907 [] e - toggle empty line at bob and/or eob visualization
1908 [] C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode')
1909 [] I - toggle indentation SPACEs visualization
1910 [] i - toggle indentation TABs visualization
1911 [] C-t - toggle big indentation visualization
1912 [] C-a - toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1913 [] A - toggle SPACEs after TAB: SPACEs visualization
1914 [] a - toggle SPACEs after TAB: TABs visualization
1915 [] C-b - toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1916 [] B - toggle SPACEs before TAB: SPACEs visualization
1917 [] b - toggle SPACEs before TAB: TABs visualization
1919 DISPLAY TABLE
1920 [] T - toggle TAB visualization
1921 [] S - toggle SPACE and HARD SPACE visualization
1922 [] N - toggle NEWLINE visualization
1924 x - restore `whitespace-style' value
1926 ? - display this text\n\n"
1927 "Text for whitespace toggle options.")
1930 (defconst whitespace-help-buffer-name "*Whitespace Toggle Options*"
1931 "The buffer name for whitespace toggle options.")
1934 (defun whitespace-insert-value (value)
1935 "Insert VALUE at column 20 of next line."
1936 (forward-line 1)
1937 (move-to-column 20 t)
1938 (insert (format "%s" value)))
1941 (defun whitespace-mark-x (nchars condition)
1942 "Insert the mark (`X' or ` ') after NCHARS depending on CONDITION."
1943 (forward-char nchars)
1944 (insert (if condition "X" " ")))
1947 (defun whitespace-insert-option-mark (the-list the-value)
1948 "Insert the option mark (`X' or ` ') in toggle options buffer."
1949 (goto-char (point-min))
1950 (forward-line 2)
1951 (dolist (sym the-list)
1952 (if (eq sym 'help-newline)
1953 (forward-line 2)
1954 (forward-line 1)
1955 (whitespace-mark-x 2 (memq sym the-value)))))
1958 (defun whitespace-help-on (style)
1959 "Display the whitespace toggle options."
1960 (unless (get-buffer whitespace-help-buffer-name)
1961 (delete-other-windows)
1962 (let ((buffer (get-buffer-create whitespace-help-buffer-name)))
1963 (with-current-buffer buffer
1964 (erase-buffer)
1965 (insert whitespace-help-text)
1966 (whitespace-insert-option-mark
1967 whitespace-style-value-list style)
1968 (whitespace-display-window buffer)))))
1971 (defun whitespace-display-window (buffer)
1972 "Display BUFFER in a new window."
1973 (goto-char (point-min))
1974 (set-buffer-modified-p nil)
1975 (when (< (window-height) (* 2 window-min-height))
1976 (kill-buffer buffer)
1977 (error "Window height is too small; \
1978 can't split window to display whitespace toggle options"))
1979 (let ((win (split-window)))
1980 (set-window-buffer win buffer)
1981 (shrink-window-if-larger-than-buffer win)))
1984 (defun whitespace-kill-buffer (buffer-name)
1985 "Kill buffer BUFFER-NAME and windows related with it."
1986 (let ((buffer (get-buffer buffer-name)))
1987 (when buffer
1988 (delete-windows-on buffer)
1989 (kill-buffer buffer))))
1992 (defun whitespace-help-off ()
1993 "Remove the buffer and window of the whitespace toggle options."
1994 (whitespace-kill-buffer whitespace-help-buffer-name))
1997 (defun whitespace-help-scroll (&optional up)
1998 "Scroll help window, if it exists.
2000 If UP is non-nil, scroll up; otherwise, scroll down."
2001 (condition-case nil
2002 (let ((buffer (get-buffer whitespace-help-buffer-name)))
2003 (if buffer
2004 (with-selected-window (get-buffer-window buffer)
2005 (if up
2006 (scroll-up 3)
2007 (scroll-down 3)))
2008 (ding)))
2009 ;; handler
2010 ((error)
2011 ;; just ignore error
2015 (defun whitespace-interactive-char (local-p)
2016 "Interactive function to read a char and return a symbol.
2018 If LOCAL-P is non-nil, it uses a local context; otherwise, it
2019 uses a global context.
2021 It accepts one of the following chars:
2023 CHAR MEANING
2024 (VIA FACES)
2025 f toggle face visualization
2026 t toggle TAB visualization
2027 s toggle SPACE and HARD SPACE visualization
2028 r toggle trailing blanks visualization
2029 l toggle \"long lines\" visualization
2030 L toggle \"long lines\" tail visualization
2031 n toggle NEWLINE visualization
2032 e toggle empty line at bob and/or eob visualization
2033 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
2034 I toggle indentation SPACEs visualization
2035 i toggle indentation TABs visualization
2036 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
2037 A toggle SPACEs after TAB: SPACEs visualization
2038 a toggle SPACEs after TAB: TABs visualization
2039 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
2040 B toggle SPACEs before TAB: SPACEs visualization
2041 b toggle SPACEs before TAB: TABs visualization
2043 (VIA DISPLAY TABLE)
2044 T toggle TAB visualization
2045 S toggle SPACE and HARD SPACE visualization
2046 N toggle NEWLINE visualization
2048 x restore `whitespace-style' value
2049 ? display brief help
2051 See also `whitespace-toggle-option-alist'."
2052 (let* ((is-off (not (if local-p
2053 whitespace-mode
2054 global-whitespace-mode)))
2055 (style (cond (is-off whitespace-style) ; use default value
2056 (local-p whitespace-active-style)
2057 (t whitespace-toggle-style)))
2058 (prompt
2059 (format "Whitespace Toggle %s (type ? for further options)-"
2060 (if local-p "Local" "Global")))
2061 ch sym)
2062 ;; read a valid option and get the corresponding symbol
2063 (save-window-excursion
2064 (condition-case data
2065 (progn
2066 (while
2067 ;; while condition
2068 (progn
2069 (setq ch (read-char prompt))
2070 (not
2071 (setq sym
2072 (cdr
2073 (assq ch whitespace-toggle-option-alist)))))
2074 ;; while body
2075 (cond
2076 ((eq ch ?\?) (whitespace-help-on style))
2077 ((eq ch ?\ ) (whitespace-help-scroll t))
2078 ((eq ch ?\M- ) (whitespace-help-scroll))
2079 ((eq ch ?>) (whitespace-help-scroll t))
2080 ((eq ch ?<) (whitespace-help-scroll))
2081 (t (ding))))
2082 (whitespace-help-off)
2083 (message " ")) ; clean echo area
2084 ;; handler
2085 ((quit error)
2086 (whitespace-help-off)
2087 (error (error-message-string data)))))
2088 (list sym))) ; return the appropriate symbol
2091 (defun whitespace-toggle-list (local-p arg the-list)
2092 "Toggle options in THE-LIST based on list ARG.
2094 If LOCAL-P is non-nil, it uses a local context; otherwise, it
2095 uses a global context.
2097 ARG is a list of options to be toggled.
2099 THE-LIST is a list of options. This list will be toggled and the
2100 resultant list will be returned."
2101 (unless (if local-p whitespace-mode global-whitespace-mode)
2102 (setq the-list whitespace-style))
2103 (setq the-list (copy-sequence the-list)) ; keep original list
2104 (dolist (sym (if (listp arg) arg (list arg)))
2105 (cond
2106 ;; ignore help value
2107 ((eq sym 'help-newline))
2108 ;; restore default values
2109 ((eq sym 'whitespace-style)
2110 (setq the-list whitespace-style))
2111 ;; toggle valid values
2112 ((memq sym whitespace-style-value-list)
2113 (setq the-list (if (memq sym the-list)
2114 (delq sym the-list)
2115 (cons sym the-list))))))
2116 the-list)
2119 (defvar whitespace-display-table nil
2120 "Used to save a local display table.")
2122 (defvar whitespace-display-table-was-local nil
2123 "Used to remember whether a buffer initially had a local display table.")
2125 (defun whitespace-turn-on ()
2126 "Turn on whitespace visualization."
2127 ;; prepare local hooks
2128 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
2129 ;; create whitespace local buffer environment
2130 (set (make-local-variable 'whitespace-font-lock-keywords) nil)
2131 (set (make-local-variable 'whitespace-display-table) nil)
2132 (set (make-local-variable 'whitespace-display-table-was-local) nil)
2133 (set (make-local-variable 'whitespace-active-style)
2134 (if (listp whitespace-style)
2135 whitespace-style
2136 (list whitespace-style)))
2137 (whitespace-ensure-local-variables)
2138 ;; turn on whitespace
2139 (when whitespace-active-style
2140 (whitespace-color-on)
2141 (whitespace-display-char-on)))
2144 (defun whitespace-turn-off ()
2145 "Turn off whitespace visualization."
2146 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
2147 (when whitespace-active-style
2148 (whitespace-color-off)
2149 (whitespace-display-char-off)))
2152 (defun whitespace-style-face-p ()
2153 "Return t if there is some visualization via face."
2154 (and (memq 'face whitespace-active-style)
2155 (or (memq 'tabs whitespace-active-style)
2156 (memq 'spaces whitespace-active-style)
2157 (memq 'trailing whitespace-active-style)
2158 (memq 'lines whitespace-active-style)
2159 (memq 'lines-tail whitespace-active-style)
2160 (memq 'newline whitespace-active-style)
2161 (memq 'empty whitespace-active-style)
2162 (memq 'indentation whitespace-active-style)
2163 (memq 'indentation::tab whitespace-active-style)
2164 (memq 'indentation::space whitespace-active-style)
2165 (memq 'big-indent whitespace-active-style)
2166 (memq 'space-after-tab whitespace-active-style)
2167 (memq 'space-after-tab::tab whitespace-active-style)
2168 (memq 'space-after-tab::space whitespace-active-style)
2169 (memq 'space-before-tab whitespace-active-style)
2170 (memq 'space-before-tab::tab whitespace-active-style)
2171 (memq 'space-before-tab::space whitespace-active-style))))
2174 (defun whitespace-color-on ()
2175 "Turn on color visualization."
2176 (when (whitespace-style-face-p)
2177 ;; save current point and refontify when necessary
2178 (set (make-local-variable 'whitespace-point)
2179 (point))
2180 (setq whitespace-point--used
2181 (let ((ol (make-overlay (point) (point) nil nil t)))
2182 (delete-overlay ol) ol))
2183 (set (make-local-variable 'whitespace-font-lock-refontify)
2185 (set (make-local-variable 'whitespace-bob-marker)
2186 (point-min-marker))
2187 (set (make-local-variable 'whitespace-eob-marker)
2188 (point-max-marker))
2189 (set (make-local-variable 'whitespace-buffer-changed)
2190 nil)
2191 (add-hook 'post-command-hook #'whitespace-post-command-hook nil t)
2192 (add-hook 'before-change-functions #'whitespace-buffer-changed nil t)
2193 ;; Add whitespace-mode color into font lock.
2194 (setq
2195 whitespace-font-lock-keywords
2197 (whitespace-point--flush-used)
2198 ,@(when (memq 'spaces whitespace-active-style)
2199 ;; Show SPACEs.
2200 `((,whitespace-space-regexp 1 whitespace-space t)
2201 ;; Show HARD SPACEs.
2202 (,whitespace-hspace-regexp 1 whitespace-hspace t)))
2203 ,@(when (memq 'tabs whitespace-active-style)
2204 ;; Show TABs.
2205 `((,whitespace-tab-regexp 1 whitespace-tab t)))
2206 ,@(when (memq 'trailing whitespace-active-style)
2207 ;; Show trailing blanks.
2208 `((,#'whitespace-trailing-regexp 1 whitespace-trailing t)))
2209 ,@(when (or (memq 'lines whitespace-active-style)
2210 (memq 'lines-tail whitespace-active-style))
2211 ;; Show "long" lines.
2212 `((,(let ((line-column (or whitespace-line-column fill-column)))
2213 (format
2214 "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
2215 whitespace-tab-width
2216 (1- whitespace-tab-width)
2217 (/ line-column whitespace-tab-width)
2218 (let ((rem (% line-column whitespace-tab-width)))
2219 (if (zerop rem)
2221 (format ".\\{%d\\}" rem)))))
2222 ,(if (memq 'lines whitespace-active-style)
2223 0 ; whole line
2224 2) ; line tail
2225 whitespace-line prepend)))
2226 ,@(when (or (memq 'space-before-tab whitespace-active-style)
2227 (memq 'space-before-tab::tab whitespace-active-style)
2228 (memq 'space-before-tab::space whitespace-active-style))
2229 `((,whitespace-space-before-tab-regexp
2230 ,(cond
2231 ((memq 'space-before-tab whitespace-active-style)
2232 ;; Show SPACEs before TAB (indent-tabs-mode).
2233 (if whitespace-indent-tabs-mode 1 2))
2234 ((memq 'space-before-tab::tab whitespace-active-style)
2236 ((memq 'space-before-tab::space whitespace-active-style)
2238 whitespace-space-before-tab t)))
2239 ,@(when (or (memq 'indentation whitespace-active-style)
2240 (memq 'indentation::tab whitespace-active-style)
2241 (memq 'indentation::space whitespace-active-style))
2242 `((,(cond
2243 ((memq 'indentation whitespace-active-style)
2244 ;; Show indentation SPACEs (indent-tabs-mode).
2245 (whitespace-indentation-regexp))
2246 ((memq 'indentation::tab whitespace-active-style)
2247 ;; Show indentation SPACEs (SPACEs).
2248 (whitespace-indentation-regexp 'tab))
2249 ((memq 'indentation::space whitespace-active-style)
2250 ;; Show indentation SPACEs (TABs).
2251 (whitespace-indentation-regexp 'space)))
2252 1 whitespace-indentation t)))
2253 ,@(when (memq 'big-indent whitespace-active-style)
2254 ;; Show big indentation.
2255 `((,whitespace-big-indent-regexp 1 'whitespace-big-indent t)))
2256 ,@(when (memq 'empty whitespace-active-style)
2257 ;; Show empty lines at beginning of buffer.
2258 `((,#'whitespace-empty-at-bob-regexp
2259 1 whitespace-empty t)
2260 ;; Show empty lines at end of buffer.
2261 (,#'whitespace-empty-at-eob-regexp
2262 1 whitespace-empty t)))
2263 ,@(when (or (memq 'space-after-tab whitespace-active-style)
2264 (memq 'space-after-tab::tab whitespace-active-style)
2265 (memq 'space-after-tab::space whitespace-active-style))
2266 `((,(cond
2267 ((memq 'space-after-tab whitespace-active-style)
2268 ;; Show SPACEs after TAB (indent-tabs-mode).
2269 (whitespace-space-after-tab-regexp))
2270 ((memq 'space-after-tab::tab whitespace-active-style)
2271 ;; Show SPACEs after TAB (SPACEs).
2272 (whitespace-space-after-tab-regexp 'tab))
2273 ((memq 'space-after-tab::space whitespace-active-style)
2274 ;; Show SPACEs after TAB (TABs).
2275 (whitespace-space-after-tab-regexp 'space)))
2276 1 whitespace-space-after-tab t)))))
2277 (font-lock-add-keywords nil whitespace-font-lock-keywords t)
2278 (font-lock-flush)))
2281 (defun whitespace-color-off ()
2282 "Turn off color visualization."
2283 ;; turn off font lock
2284 (kill-local-variable 'whitespace-point--used)
2285 (when (whitespace-style-face-p)
2286 (remove-hook 'post-command-hook #'whitespace-post-command-hook t)
2287 (remove-hook 'before-change-functions #'whitespace-buffer-changed t)
2288 (font-lock-remove-keywords nil whitespace-font-lock-keywords)
2289 (font-lock-flush)))
2291 (defun whitespace-point--used (start end)
2292 (let ((ostart (overlay-start whitespace-point--used)))
2293 (if ostart
2294 (move-overlay whitespace-point--used
2295 (min start ostart)
2296 (max end (overlay-end whitespace-point--used)))
2297 (move-overlay whitespace-point--used start end))))
2299 (defun whitespace-point--flush-used (limit)
2300 (let ((ostart (overlay-start whitespace-point--used)))
2301 ;; Strip parts of whitespace-point--used we're about to refresh.
2302 (when ostart
2303 (let ((oend (overlay-end whitespace-point--used)))
2304 (if (<= (point) ostart)
2305 (if (<= oend limit)
2306 (delete-overlay whitespace-point--used)
2307 (move-overlay whitespace-point--used limit oend)))
2308 (if (<= oend limit)
2309 (move-overlay whitespace-point--used ostart (point))))))
2310 nil)
2312 (defun whitespace-trailing-regexp (limit)
2313 "Match trailing spaces which do not contain the point at end of line."
2314 (let ((status t))
2315 (while (if (re-search-forward whitespace-trailing-regexp limit t)
2316 (when (= whitespace-point (match-end 1)) ; Loop if point at eol.
2317 (whitespace-point--used (match-beginning 0) (match-end 0))
2319 (setq status nil))) ;; end of buffer
2320 status))
2323 (defun whitespace-empty-at-bob-regexp (limit)
2324 "Match spaces at beginning of buffer which do not contain the point at \
2325 beginning of buffer."
2326 (let ((b (point))
2328 (cond
2329 ;; at bob
2330 ((= b 1)
2331 (setq r (and (looking-at whitespace-empty-at-bob-regexp)
2332 (or (/= whitespace-point 1)
2333 (progn (whitespace-point--used (match-beginning 0)
2334 (match-end 0))
2335 nil))))
2336 (set-marker whitespace-bob-marker (if r (match-end 1) b)))
2337 ;; inside bob empty region
2338 ((<= limit whitespace-bob-marker)
2339 (setq r (looking-at whitespace-empty-at-bob-regexp))
2340 (if r
2341 (when (< (match-end 1) limit)
2342 (set-marker whitespace-bob-marker (match-end 1)))
2343 (set-marker whitespace-bob-marker b)))
2344 ;; intersection with end of bob empty region
2345 ((<= b whitespace-bob-marker)
2346 (setq r (looking-at whitespace-empty-at-bob-regexp))
2347 (set-marker whitespace-bob-marker (if r (match-end 1) b)))
2348 ;; it is not inside bob empty region
2350 (setq r nil)))
2351 ;; move to end of matching
2352 (and r (goto-char (match-end 1)))
2356 (defsubst whitespace-looking-back (regexp limit)
2357 (save-excursion
2358 (when (/= 0 (skip-chars-backward " \t\n" limit))
2359 (unless (bolp)
2360 (forward-line 1))
2361 (looking-at regexp))))
2364 (defun whitespace-empty-at-eob-regexp (limit)
2365 "Match spaces at end of buffer which do not contain the point at end of \
2366 buffer."
2367 (let ((b (point))
2368 (e (1+ (buffer-size)))
2370 (cond
2371 ;; at eob
2372 ((= limit e)
2373 (goto-char limit)
2374 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2375 (when (and r (= whitespace-point e))
2376 (setq r nil)
2377 (whitespace-point--used (match-beginning 0) (match-end 0)))
2378 (if r
2379 (set-marker whitespace-eob-marker (match-beginning 1))
2380 (set-marker whitespace-eob-marker limit)
2381 (goto-char b))) ; return back to initial position
2382 ;; inside eob empty region
2383 ((>= b whitespace-eob-marker)
2384 (goto-char limit)
2385 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2386 (if r
2387 (when (> (match-beginning 1) b)
2388 (set-marker whitespace-eob-marker (match-beginning 1)))
2389 (set-marker whitespace-eob-marker limit)
2390 (goto-char b))) ; return back to initial position
2391 ;; intersection with beginning of eob empty region
2392 ((>= limit whitespace-eob-marker)
2393 (goto-char limit)
2394 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2395 (if r
2396 (set-marker whitespace-eob-marker (match-beginning 1))
2397 (set-marker whitespace-eob-marker limit)
2398 (goto-char b))) ; return back to initial position
2399 ;; it is not inside eob empty region
2401 (setq r nil)))
2405 (defun whitespace-buffer-changed (_beg _end)
2406 "Set `whitespace-buffer-changed' variable to t."
2407 (setq whitespace-buffer-changed t))
2410 (defun whitespace-post-command-hook ()
2411 "Save current point into `whitespace-point' variable.
2412 Also refontify when necessary."
2413 (unless (and (eq whitespace-point (point))
2414 (not whitespace-buffer-changed))
2415 (setq whitespace-point (point)) ; current point position
2416 (let ((refontify
2417 (cond
2418 ;; It is at end of buffer (eob).
2419 ((= whitespace-point (1+ (buffer-size)))
2420 (when (whitespace-looking-back whitespace-empty-at-eob-regexp
2421 nil)
2422 (match-beginning 0)))
2423 ;; It is at end of line ...
2424 ((and (eolp)
2425 ;; ... with trailing SPACE or TAB
2426 (or (memq (preceding-char) '(?\s ?\t))))
2427 (line-beginning-position))
2428 ;; It is at beginning of buffer (bob).
2429 ((and (= whitespace-point 1)
2430 (looking-at whitespace-empty-at-bob-regexp))
2431 (match-end 0))))
2432 (ostart (overlay-start whitespace-point--used)))
2433 (cond
2434 ((not refontify)
2435 ;; New point does not affect highlighting: just refresh the
2436 ;; highlighting of old point, if needed.
2437 (when ostart
2438 (font-lock-flush ostart
2439 (overlay-end whitespace-point--used))
2440 (delete-overlay whitespace-point--used)))
2441 ((not ostart)
2442 ;; Old point did not affect highlighting, but new one does: refresh the
2443 ;; highlighting of new point.
2444 (font-lock-flush (min refontify (point)) (max refontify (point))))
2445 ((save-excursion
2446 (goto-char ostart)
2447 (setq ostart (line-beginning-position))
2448 (and (<= ostart (max refontify (point)))
2449 (progn
2450 (goto-char (overlay-end whitespace-point--used))
2451 (let ((oend (line-beginning-position 2)))
2452 (<= (min refontify (point)) oend)))))
2453 ;; The old point highlighting and the new point highlighting
2454 ;; cover a contiguous region: do a single refresh.
2455 (font-lock-flush (min refontify (point) ostart)
2456 (max refontify (point)
2457 (overlay-end whitespace-point--used)))
2458 (delete-overlay whitespace-point--used))
2460 (font-lock-flush (min refontify (point))
2461 (max refontify (point)))
2462 (font-lock-flush ostart (overlay-end whitespace-point--used))
2463 (delete-overlay whitespace-point--used))))))
2466 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2467 ;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
2470 (defun whitespace-style-mark-p ()
2471 "Return t if there is some visualization via display table."
2472 (or (memq 'tab-mark whitespace-active-style)
2473 (memq 'space-mark whitespace-active-style)
2474 (memq 'newline-mark whitespace-active-style)))
2477 (defsubst whitespace-char-valid-p (char)
2478 ;; This check should be improved!!!
2479 (or (< char 256)
2480 (characterp char)))
2483 (defun whitespace-display-vector-p (vec)
2484 "Return true if every character in vector VEC can be displayed."
2485 (let ((i (length vec)))
2486 (when (> i 0)
2487 (while (and (>= (setq i (1- i)) 0)
2488 (whitespace-char-valid-p (aref vec i))))
2489 (< i 0))))
2492 (defun whitespace-display-char-on ()
2493 "Turn on character display mapping."
2494 (when (and whitespace-display-mappings
2495 (whitespace-style-mark-p))
2496 (let (vecs vec)
2497 ;; Remember whether a buffer has a local display table.
2498 (unless whitespace-display-table-was-local
2499 (setq whitespace-display-table-was-local t
2500 whitespace-display-table
2501 (copy-sequence buffer-display-table))
2502 ;; Assure `buffer-display-table' is unique
2503 ;; when two or more windows are visible.
2504 (setq buffer-display-table
2505 (copy-sequence buffer-display-table)))
2506 (unless buffer-display-table
2507 (setq buffer-display-table (make-display-table)))
2508 (dolist (entry whitespace-display-mappings)
2509 ;; check if it is to display this mark
2510 (when (memq (car entry) whitespace-style)
2511 ;; Get a displayable mapping.
2512 (setq vecs (cddr entry))
2513 (while (and vecs
2514 (not (whitespace-display-vector-p (car vecs))))
2515 (setq vecs (cdr vecs)))
2516 ;; Display a valid mapping.
2517 (when vecs
2518 (setq vec (copy-sequence (car vecs)))
2519 ;; NEWLINE char
2520 (when (and (eq (cadr entry) ?\n)
2521 (memq 'newline whitespace-active-style))
2522 ;; Only insert face bits on NEWLINE char mapping to avoid
2523 ;; obstruction of other faces like TABs and (HARD) SPACEs
2524 ;; faces, font-lock faces, etc.
2525 (dotimes (i (length vec))
2526 (or (eq (aref vec i) ?\n)
2527 (aset vec i
2528 (make-glyph-code (aref vec i)
2529 whitespace-newline)))))
2530 ;; Display mapping
2531 (aset buffer-display-table (cadr entry) vec)))))))
2534 (defun whitespace-display-char-off ()
2535 "Turn off character display mapping."
2536 (and whitespace-display-mappings
2537 (whitespace-style-mark-p)
2538 whitespace-display-table-was-local
2539 (setq whitespace-display-table-was-local nil
2540 buffer-display-table whitespace-display-table)))
2543 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2544 ;;;; Hook
2547 (defun whitespace-action-when-on ()
2548 "Action to be taken always when local whitespace is turned on."
2549 (cond ((memq 'cleanup whitespace-action)
2550 (whitespace-cleanup))
2551 ((memq 'report-on-bogus whitespace-action)
2552 (whitespace-report nil t))))
2555 (defun whitespace-write-file-hook ()
2556 "Action to be taken when buffer is written.
2557 It should be added buffer-locally to `write-file-functions'."
2558 (cond ((memq 'auto-cleanup whitespace-action)
2559 (whitespace-cleanup))
2560 ((memq 'abort-on-bogus whitespace-action)
2561 (when (whitespace-report nil t)
2562 (error "Abort write due to whitespace problems in %s"
2563 (buffer-name)))))
2564 nil) ; continue hook processing
2567 (defun whitespace-warn-read-only (msg)
2568 "Warn if buffer is read-only."
2569 (when (memq 'warn-if-read-only whitespace-action)
2570 (message "Can't %s: %s is read-only" msg (buffer-name))))
2573 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2576 (defun whitespace-unload-function ()
2577 "Unload the whitespace library."
2578 (global-whitespace-mode -1)
2579 ;; be sure all local whitespace mode is turned off
2580 (save-current-buffer
2581 (dolist (buf (buffer-list))
2582 (set-buffer buf)
2583 (whitespace-mode -1)))
2584 nil) ; continue standard unloading
2587 (provide 'whitespace)
2590 (run-hooks 'whitespace-load-hook)
2593 ;;; whitespace.el ends here