Output alists with dotted pair notation in .dir-locals.el
[emacs.git] / lisp / whitespace.el
blobd8249316e4b893a712e50f043966c569a363ad39
1 ;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE -*- lexical-binding: t -*-
3 ;; Copyright (C) 2000-2018 Free Software Foundation, Inc.
5 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
6 ;; Maintainer: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
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 <https://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.
181 ;; See the function's docstring for more information.
183 ;; `whitespace-cleanup-region'
184 ;; Cleanup some blank problems at region.
187 ;; Options
188 ;; -------
190 ;; Whitespace's behavior can be changed with `M-x customize-group
191 ;; whitespace', which see for the full list of options.
194 ;; Hooks
195 ;; -----
197 ;; whitespace has the following hook variables:
199 ;; `whitespace-mode-hook'
200 ;; It is evaluated always when whitespace is turned on locally.
202 ;; `global-whitespace-mode-hook'
203 ;; It is evaluated always when whitespace is turned on globally.
205 ;; `whitespace-load-hook'
206 ;; It is evaluated after whitespace package is loaded.
209 ;; Acknowledgments
210 ;; ---------------
212 ;; Thanks to felix (EmacsWiki) for keeping highlight when switching between
213 ;; major modes on a file.
215 ;; Thanks to David Reitter <david.reitter@gmail.com> for suggesting a
216 ;; `whitespace-newline' initialization with low contrast relative to
217 ;; the background color.
219 ;; Thanks to Stephen Deasey <sdeasey@gmail.com> for the
220 ;; `indent-tabs-mode' usage suggestion.
222 ;; Thanks to Eric Cooper <ecc@cmu.edu> for the suggestion to have hook
223 ;; actions when buffer is written as the original whitespace package
224 ;; had.
226 ;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
227 ;; lines tail. See EightyColumnRule (EmacsWiki).
229 ;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
230 ;; * `define-minor-mode'.
231 ;; * `global-whitespace-*' name for global commands.
233 ;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
235 ;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
236 ;; suggestion.
238 ;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
239 ;; helping to fix `find-file-hooks' reference.
241 ;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
242 ;; indicating defface byte-compilation warnings.
244 ;; Thanks to Tim O'Callaghan (EmacsWiki) for the idea about highlight
245 ;; "long" lines. See EightyColumnRule (EmacsWiki).
247 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
248 ;; NEWLINE character mapping.
250 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
251 ;; whitespace-mode.el on XEmacs.
253 ;; Thanks to Miles Bader <miles@gnu.org> for handling display table via
254 ;; visws.el (his code was modified, but the main idea was kept).
256 ;; Thanks to:
257 ;; Rajesh Vaidheeswarran <rv@gnu.org> (original) whitespace.el
258 ;; Aurelien Tisne <aurelien.tisne@free.fr> show-whitespace-mode.el
259 ;; Lawrence Mitchell <wence@gmx.li> whitespace-mode.el
260 ;; Miles Bader <miles@gnu.org> visws.el
261 ;; And to all people who contributed with them.
264 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
266 ;;; code:
269 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
270 ;;;; User Variables:
273 ;;; Interface to the command system
276 (defgroup whitespace nil
277 "Visualize blanks (TAB, (HARD) SPACE and NEWLINE)."
278 :link '(emacs-library-link :tag "Source Lisp File" "whitespace.el")
279 :version "23.1"
280 :group 'convenience)
283 (defcustom whitespace-style
284 '(face
285 tabs spaces trailing lines space-before-tab newline
286 indentation empty space-after-tab
287 space-mark tab-mark newline-mark)
288 "Specify which kind of blank is visualized.
290 It's a list containing some or all of the following values:
292 face enable all visualization via faces (see below).
294 trailing trailing blanks are visualized via faces.
295 It has effect only if `face' (see above)
296 is present in `whitespace-style'.
298 tabs TABs are visualized via faces.
299 It has effect only if `face' (see above)
300 is present in `whitespace-style'.
302 spaces SPACEs and HARD SPACEs are visualized via
303 faces.
304 It has effect only if `face' (see above)
305 is present in `whitespace-style'.
307 lines lines which have columns beyond
308 `whitespace-line-column' are highlighted via
309 faces.
310 Whole line is highlighted.
311 It has precedence over `lines-tail' (see
312 below).
313 It has effect only if `face' (see above)
314 is present in `whitespace-style'.
316 lines-tail lines which have columns beyond
317 `whitespace-line-column' are highlighted via
318 faces.
319 But only the part of line which goes
320 beyond `whitespace-line-column' column.
321 It has effect only if `lines' (see above)
322 is not present in `whitespace-style'
323 and if `face' (see above) is present in
324 `whitespace-style'.
326 newline NEWLINEs are visualized via faces.
327 It has effect only if `face' (see above)
328 is present in `whitespace-style'.
330 empty empty lines at beginning and/or end of buffer
331 are visualized via faces.
332 It has effect only if `face' (see above)
333 is present in `whitespace-style'.
335 indentation::tab `tab-width' or more SPACEs at beginning of line
336 are visualized via faces.
337 It has effect only if `face' (see above)
338 is present in `whitespace-style'.
340 indentation::space TABs at beginning of line are visualized via
341 faces.
342 It has effect only if `face' (see above)
343 is present in `whitespace-style'.
345 indentation `tab-width' or more SPACEs at beginning of line
346 are visualized, if `indent-tabs-mode' (which
347 see) is non-nil; otherwise, TABs at beginning
348 of line are visualized via faces.
349 It has effect only if `face' (see above)
350 is present in `whitespace-style'.
352 big-indent Big indentations are visualized via faces.
353 It has effect only if `face' (see above)
354 is present in `whitespace-style'.
356 space-after-tab::tab `tab-width' or more SPACEs after a TAB
357 are visualized via faces.
358 It has effect only if `face' (see above)
359 is present in `whitespace-style'.
361 space-after-tab::space TABs are visualized when `tab-width' or
362 more SPACEs occur after a TAB, via
363 faces.
364 It has effect only if `face' (see above)
365 is present in `whitespace-style'.
367 space-after-tab `tab-width' or more SPACEs after a TAB
368 are visualized, if `indent-tabs-mode'
369 (which see) is non-nil; otherwise,
370 the TABs are visualized via faces.
371 It has effect only if `face' (see above)
372 is present in `whitespace-style'.
374 space-before-tab::tab SPACEs before TAB are visualized via
375 faces.
376 It has effect only if `face' (see above)
377 is present in `whitespace-style'.
379 space-before-tab::space TABs are visualized when SPACEs occur
380 before TAB, via faces.
381 It has effect only if `face' (see above)
382 is present in `whitespace-style'.
384 space-before-tab SPACEs before TAB are visualized, if
385 `indent-tabs-mode' (which see) is
386 non-nil; otherwise, the TABs are
387 visualized via faces.
388 It has effect only if `face' (see above)
389 is present in `whitespace-style'.
391 space-mark SPACEs and HARD SPACEs are visualized via
392 display table.
394 tab-mark TABs are visualized via display table.
396 newline-mark NEWLINEs are visualized via display table.
398 Any other value is ignored.
400 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs via faces and
401 via display table.
403 There is an evaluation order for some values, if they are
404 included in `whitespace-style' list. For example, if
405 indentation, indentation::tab and/or indentation::space are
406 included in `whitespace-style' list. The evaluation order for
407 these values is:
409 * For indentation:
410 1. indentation
411 2. indentation::tab
412 3. indentation::space
414 * For SPACEs after TABs:
415 1. space-after-tab
416 2. space-after-tab::tab
417 3. space-after-tab::space
419 * For SPACEs before TABs:
420 1. space-before-tab
421 2. space-before-tab::tab
422 3. space-before-tab::space
424 For example, if `indentation' and `indentation::space' are
425 included in `whitespace-style', the `indentation' value is used
426 instead of the `indentation::space' value.
428 One reason to not use faces to visualize spaces (i.e., not
429 include `face' in `whitespace-style') is to use `whitespace-mode'
430 only for cleaning up a buffer. See `whitespace-cleanup' and
431 `whitespace-cleanup-region'.
433 See also `whitespace-display-mappings' for documentation."
434 :type '(set :tag "Kind of Blank"
435 (const :tag "(Face) Face visualization" face)
436 (const :tag "(Face) Trailing TABs, SPACEs and HARD SPACEs"
437 trailing)
438 (const :tag "(Face) TABs" tabs)
439 (const :tag "(Face) SPACEs and HARD SPACEs" spaces)
440 (const :tag "(Face) Lines" lines)
441 (const :tag "(Face) Lines, only overlong part" lines-tail)
442 (const :tag "(Face) NEWLINEs" newline)
443 (const :tag "(Face) Empty Lines At BOB And/Or EOB" empty)
444 (const :tag "(Face) Indentation SPACEs" indentation::tab)
445 (const :tag "(Face) Indentation TABs"
446 indentation::space)
447 (const :tag "(Face) Indentation TABs or SPACEs" indentation)
448 (const :tag "(Face) Too much line indentation" big-indent)
449 (const :tag "(Face) SPACEs after TAB: SPACEs"
450 space-after-tab::tab)
451 (const :tag "(Face) SPACEs after TAB: TABs"
452 space-after-tab::space)
453 (const :tag "(Face) SPACEs after TAB" space-after-tab)
454 (const :tag "(Face) SPACEs before TAB: SPACEs"
455 space-before-tab::tab)
456 (const :tag "(Face) SPACEs before TAB: TABs"
457 space-before-tab::space)
458 (const :tag "(Face) SPACEs before TAB" space-before-tab)
459 (const :tag "(Mark) SPACEs and HARD SPACEs" space-mark)
460 (const :tag "(Mark) TABs" tab-mark)
461 (const :tag "(Mark) NEWLINEs" newline-mark))
462 :group 'whitespace)
464 (defvar whitespace-space 'whitespace-space
465 "Symbol face used to visualize SPACE.
466 Used when `whitespace-style' includes the value `spaces'.")
467 (make-obsolete-variable 'whitespace-space "use the face instead." "24.4")
470 (defface whitespace-space
471 '((((class color) (background dark))
472 :background "grey20" :foreground "darkgray")
473 (((class color) (background light))
474 :background "LightYellow" :foreground "lightgray")
475 (t :inverse-video t))
476 "Face used to visualize SPACE."
477 :group 'whitespace)
480 (defvar whitespace-hspace 'whitespace-hspace
481 "Symbol face used to visualize HARD SPACE.
482 Used when `whitespace-style' includes the value `spaces'.")
483 (make-obsolete-variable 'whitespace-hspace "use the face instead." "24.4")
485 (defface whitespace-hspace ; 'nobreak-space
486 '((((class color) (background dark))
487 :background "grey24" :foreground "darkgray")
488 (((class color) (background light))
489 :background "LemonChiffon3" :foreground "lightgray")
490 (t :inverse-video t))
491 "Face used to visualize HARD SPACE."
492 :group 'whitespace)
495 (defvar whitespace-tab 'whitespace-tab
496 "Symbol face used to visualize TAB.
497 Used when `whitespace-style' includes the value `tabs'.")
498 (make-obsolete-variable 'whitespace-tab
499 "customize the face `whitespace-tab' instead." "24.4")
501 (defface whitespace-tab
502 '((((class color) (background dark))
503 :background "grey22" :foreground "darkgray")
504 (((class color) (background light))
505 :background "beige" :foreground "lightgray")
506 (t :inverse-video t))
507 "Face used to visualize TAB."
508 :group 'whitespace)
511 (defvar whitespace-newline 'whitespace-newline
512 "Symbol face used to visualize NEWLINE char mapping.
513 See `whitespace-display-mappings'.
514 Used when `whitespace-style' includes the values `newline-mark'
515 and `newline'.")
516 (make-obsolete-variable 'whitespace-newline "use the face instead." "24.4")
518 (defface whitespace-newline
519 '((default :weight normal)
520 (((class color) (background dark)) :foreground "darkgray")
521 (((class color) (min-colors 88) (background light)) :foreground "lightgray")
522 ;; Displays with 16 colors use lightgray as background, so using a
523 ;; lightgray foreground makes the newline mark invisible.
524 (((class color) (background light)) :foreground "brown")
525 (t :underline t))
526 "Face used to visualize NEWLINE char mapping.
528 See `whitespace-display-mappings'."
529 :group 'whitespace)
532 (defvar whitespace-trailing 'whitespace-trailing
533 "Symbol face used to visualize trailing blanks.
534 Used when `whitespace-style' includes the value `trailing'.")
535 (make-obsolete-variable 'whitespace-trailing "use the face instead." "24.4")
537 (defface whitespace-trailing ; 'trailing-whitespace
538 '((default :weight bold)
539 (((class mono)) :inverse-video t :underline t)
540 (t :background "red1" :foreground "yellow"))
541 "Face used to visualize trailing blanks."
542 :group 'whitespace)
545 (defvar whitespace-line 'whitespace-line
546 "Symbol face used to visualize \"long\" lines.
547 See `whitespace-line-column'.
548 Used when `whitespace-style' includes the value `line'.")
549 (make-obsolete-variable 'whitespace-line "use the face instead." "24.4")
551 (defface whitespace-line
552 '((((class mono)) :inverse-video t :weight bold :underline t)
553 (t :background "gray20" :foreground "violet"))
554 "Face used to visualize \"long\" lines.
556 See `whitespace-line-column'."
557 :group 'whitespace)
560 (defvar whitespace-space-before-tab 'whitespace-space-before-tab
561 "Symbol face used to visualize SPACEs before TAB.
562 Used when `whitespace-style' includes the value `space-before-tab'.")
563 (make-obsolete-variable 'whitespace-space-before-tab
564 "use the face instead." "24.4")
566 (defface whitespace-space-before-tab
567 '((((class mono)) :inverse-video t :weight bold :underline t)
568 (t :background "DarkOrange" :foreground "firebrick"))
569 "Face used to visualize SPACEs before TAB."
570 :group 'whitespace)
573 (defvar whitespace-indentation 'whitespace-indentation
574 "Symbol face used to visualize `tab-width' or more SPACEs at beginning of
575 line. Used when `whitespace-style' includes the value `indentation'.")
576 (make-obsolete-variable 'whitespace-indentation "use the face instead." "24.4")
578 (defface whitespace-indentation
579 '((((class mono)) :inverse-video t :weight bold :underline t)
580 (t :background "yellow" :foreground "firebrick"))
581 "Face used to visualize `tab-width' or more SPACEs at beginning of line."
582 :group 'whitespace)
584 (defface whitespace-big-indent
585 '((((class mono)) :inverse-video t :weight bold :underline t)
586 (t :background "red" :foreground "firebrick"))
587 "Face used to visualize big indentation."
588 :group 'whitespace)
591 (defvar whitespace-empty 'whitespace-empty
592 "Symbol face used to visualize empty lines at beginning and/or end of buffer.
593 Used when `whitespace-style' includes the value `empty'.")
594 (make-obsolete-variable 'whitespace-empty "use the face instead." "24.4")
596 (defface whitespace-empty
597 '((((class mono)) :inverse-video t :weight bold :underline t)
598 (t :background "yellow" :foreground "firebrick"))
599 "Face used to visualize empty lines at beginning and/or end of buffer."
600 :group 'whitespace)
603 (defvar whitespace-space-after-tab 'whitespace-space-after-tab
604 "Symbol face used to visualize `tab-width' or more SPACEs after TAB.
605 Used when `whitespace-style' includes the value `space-after-tab'.")
606 (make-obsolete-variable 'whitespace-space-after-tab
607 "use the face instead." "24.4")
609 (defface whitespace-space-after-tab
610 '((((class mono)) :inverse-video t :weight bold :underline t)
611 (t :background "yellow" :foreground "firebrick"))
612 "Face used to visualize `tab-width' or more SPACEs after TAB."
613 :group 'whitespace)
616 (defcustom whitespace-hspace-regexp
617 "\\(\u00A0+\\)"
618 "Specify HARD SPACE characters regexp.
620 Here are some examples:
622 \"\\\\(^\\xA0+\\\\)\" \
623 visualize only leading HARD SPACEs.
624 \"\\\\(\\xA0+$\\\\)\" \
625 visualize only trailing HARD SPACEs.
626 \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\" \
627 visualize leading and/or trailing HARD SPACEs.
628 \"\\t\\\\(\\xA0+\\\\)\\t\" \
629 visualize only HARD SPACEs between TABs.
631 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
632 Use exactly one pair of enclosing \\\\( and \\\\).
634 Used when `whitespace-style' includes `spaces'."
635 :type '(regexp :tag "HARD SPACE Chars")
636 :group 'whitespace)
639 (defcustom whitespace-space-regexp "\\( +\\)"
640 "Specify SPACE characters regexp.
642 If you're using `mule' package, there may be other characters
643 besides \" \" that should be considered SPACE.
645 Here are some examples:
647 \"\\\\(^ +\\\\)\" visualize only leading SPACEs.
648 \"\\\\( +$\\\\)\" visualize only trailing SPACEs.
649 \"\\\\(^ +\\\\| +$\\\\)\" \
650 visualize leading and/or trailing SPACEs.
651 \"\\t\\\\( +\\\\)\\t\" visualize only SPACEs between TABs.
653 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
654 Use exactly one pair of enclosing \\\\( and \\\\).
656 Used when `whitespace-style' includes `spaces'."
657 :type '(regexp :tag "SPACE Chars")
658 :group 'whitespace)
661 (defcustom whitespace-tab-regexp "\\(\t+\\)"
662 "Specify TAB characters regexp.
664 If you're using `mule' package, there may be other characters
665 besides \"\\t\" that should be considered TAB.
667 Here are some examples:
669 \"\\\\(^\\t+\\\\)\" visualize only leading TABs.
670 \"\\\\(\\t+$\\\\)\" visualize only trailing TABs.
671 \"\\\\(^\\t+\\\\|\\t+$\\\\)\" \
672 visualize leading and/or trailing TABs.
673 \" \\\\(\\t+\\\\) \" visualize only TABs between SPACEs.
675 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
676 Use exactly one pair of enclosing \\\\( and \\\\).
678 Used when `whitespace-style' includes `tabs'."
679 :type '(regexp :tag "TAB Chars")
680 :group 'whitespace)
683 (defcustom whitespace-trailing-regexp
684 "\\([\t \u00A0]+\\)$"
685 "Specify trailing characters regexp.
687 There may be other characters besides:
689 \" \" \"\\t\" \"\\u00A0\"
691 that should be considered blank.
693 NOTE: Enclose always by \"\\\\(\" and \"\\\\)$\" the elements to highlight.
694 Use exactly one pair of enclosing elements above.
696 Used when `whitespace-style' includes `trailing'."
697 :type '(regexp :tag "Trailing Chars")
698 :group 'whitespace)
701 (defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
702 "Specify SPACEs before TAB regexp.
704 Used when `whitespace-style' includes `space-before-tab',
705 `space-before-tab::tab' or `space-before-tab::space'."
706 :type '(regexp :tag "SPACEs Before TAB")
707 :group 'whitespace)
710 (defcustom whitespace-indentation-regexp
711 '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
712 . "^ *\\(\t+\\)[^\n]")
713 "Specify regexp for `tab-width' or more SPACEs at beginning of line.
715 It is a cons where the cons car is used for SPACEs visualization
716 and the cons cdr is used for TABs visualization.
718 Used when `whitespace-style' includes `indentation',
719 `indentation::tab' or `indentation::space'."
720 :type '(cons (string :tag "Indentation SPACEs")
721 (string :tag "Indentation TABs"))
722 :group 'whitespace)
725 (defcustom whitespace-empty-at-bob-regexp "\\`\\(\\([ \t]*\n\\)+\\)"
726 "Specify regexp for empty lines at beginning of buffer.
728 Used when `whitespace-style' includes `empty'."
729 :type '(regexp :tag "Empty Lines At Beginning Of Buffer")
730 :group 'whitespace)
733 (defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)\\'"
734 "Specify regexp for empty lines at end of buffer.
736 Used when `whitespace-style' includes `empty'."
737 :type '(regexp :tag "Empty Lines At End Of Buffer")
738 :group 'whitespace)
741 (defcustom whitespace-space-after-tab-regexp
742 '("\t+\\(\\( \\{%d,\\}\\)+\\)"
743 . "\\(\t+\\) \\{%d,\\}")
744 "Specify regexp for `tab-width' or more SPACEs after TAB.
746 It is a cons where the cons car is used for SPACEs visualization
747 and the cons cdr is used for TABs visualization.
749 Used when `whitespace-style' includes `space-after-tab',
750 `space-after-tab::tab' or `space-after-tab::space'."
751 :type '(cons (string :tag "SPACEs After TAB")
752 string)
753 :group 'whitespace)
755 (defcustom whitespace-big-indent-regexp
756 "^\\(\\(?:\t\\{4,\\}\\| \\{32,\\}\\)[\t ]*\\)"
757 "Specify big indentation regexp.
759 If you're using `mule' package, there may be other characters
760 besides \"\\t\" that should be considered TAB.
762 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
763 Use exactly one pair of enclosing \\\\( and \\\\).
765 Used when `whitespace-style' includes `big-indent'."
766 :version "25.1"
767 :type '(regexp :tag "Detect too much indentation at the beginning of a line")
768 :group 'whitespace)
771 (defcustom whitespace-line-column 80
772 "Specify column beyond which the line is highlighted.
774 It must be an integer or nil. If nil, the `fill-column' variable value is
775 used.
777 Used when `whitespace-style' includes `lines' or `lines-tail'."
778 :type '(choice :tag "Line Length Limit"
779 (integer :tag "Line Length")
780 (const :tag "Use fill-column" nil))
781 :safe 'integerp
782 :group 'whitespace)
785 ;; Hacked from `visible-whitespace-mappings' in visws.el
786 (defcustom whitespace-display-mappings
788 (space-mark ?\ [?·] [?.]) ; space - middle dot
789 (space-mark ?\xA0 [?¤] [?_]) ; hard space - currency sign
790 ;; NEWLINE is displayed using the face `whitespace-newline'
791 (newline-mark ?\n [?$ ?\n]) ; eol - dollar sign
792 ;; (newline-mark ?\n [?↵ ?\n] [?$ ?\n]) ; eol - downwards arrow
793 ;; (newline-mark ?\n [?¶ ?\n] [?$ ?\n]) ; eol - pilcrow
794 ;; (newline-mark ?\n [?¯ ?\n] [?$ ?\n]) ; eol - overscore
795 ;; (newline-mark ?\n [?¬ ?\n] [?$ ?\n]) ; eol - negation
796 ;; (newline-mark ?\n [?° ?\n] [?$ ?\n]) ; eol - degrees
798 ;; WARNING: the mapping below has a problem.
799 ;; When a TAB occupies exactly one column, it will display the
800 ;; character ?\xBB at that column followed by a TAB which goes to
801 ;; the next TAB column.
802 ;; If this is a problem for you, please, comment the line below.
803 (tab-mark ?\t [?» ?\t] [?\\ ?\t]) ; tab - right guillemet
805 "Specify an alist of mappings for displaying characters.
807 Each element has the following form:
809 (KIND CHAR VECTOR...)
811 Where:
813 KIND is the kind of character.
814 It can be one of the following symbols:
816 tab-mark for TAB character
818 space-mark for SPACE or HARD SPACE character
820 newline-mark for NEWLINE character
822 CHAR is the character to be mapped.
824 VECTOR is a vector of characters to be displayed in place of CHAR.
825 The first display vector that can be displayed is used;
826 if no display vector for a mapping can be displayed, then
827 that character is displayed unmodified.
829 The NEWLINE character is displayed using the face given by
830 `whitespace-newline' variable.
832 Used when `whitespace-style' includes `tab-mark', `space-mark' or
833 `newline-mark'."
834 :type '(repeat
835 (list :tag "Character Mapping"
836 (choice :tag "Char Kind"
837 (const :tag "Tab" tab-mark)
838 (const :tag "Space" space-mark)
839 (const :tag "Newline" newline-mark))
840 (character :tag "Char")
841 (repeat :inline t :tag "Vector List"
842 (vector :tag ""
843 (repeat :inline t
844 :tag "Vector Characters"
845 (character :tag "Char"))))))
846 :group 'whitespace)
849 (defcustom whitespace-global-modes t
850 "Modes for which global `whitespace-mode' is automagically turned on.
852 Global `whitespace-mode' is controlled by the command
853 `global-whitespace-mode'.
855 If nil, means no modes have `whitespace-mode' automatically
856 turned on.
858 If t, all modes that support `whitespace-mode' have it
859 automatically turned on.
861 Else it should be a list of `major-mode' symbol names for which
862 `whitespace-mode' should be automatically turned on. The sense
863 of the list is negated if it begins with `not'. For example:
865 (c-mode c++-mode)
867 means that `whitespace-mode' is turned on for buffers in C and
868 C++ modes only."
869 :type '(choice :tag "Global Modes"
870 (const :tag "None" nil)
871 (const :tag "All" t)
872 (set :menu-tag "Mode Specific" :tag "Modes"
873 :value (not)
874 (const :tag "Except" not)
875 (repeat :inline t
876 (symbol :tag "Mode"))))
877 :group 'whitespace)
880 (defcustom whitespace-action nil
881 "Specify which action is taken when a buffer is visited or written.
883 It's a list containing some or all of the following values:
885 nil no action is taken.
887 cleanup cleanup any bogus whitespace always when local
888 whitespace is turned on.
889 See `whitespace-cleanup' and
890 `whitespace-cleanup-region'.
892 report-on-bogus report if there is any bogus whitespace always
893 when local whitespace is turned on.
895 auto-cleanup cleanup any bogus whitespace when buffer is
896 written.
897 See `whitespace-cleanup' and
898 `whitespace-cleanup-region'.
900 abort-on-bogus abort if there is any bogus whitespace and the
901 buffer is written.
903 warn-if-read-only give a warning if `cleanup' or `auto-cleanup'
904 is included in `whitespace-action' and the
905 buffer is read-only.
907 Any other value is treated as nil."
908 :type '(choice :tag "Actions"
909 (const :tag "None" nil)
910 (repeat :tag "Action List"
911 (choice :tag "Action"
912 (const :tag "Cleanup When On" cleanup)
913 (const :tag "Report On Bogus" report-on-bogus)
914 (const :tag "Auto Cleanup" auto-cleanup)
915 (const :tag "Abort On Bogus" abort-on-bogus)
916 (const :tag "Warn If Read-Only" warn-if-read-only))))
917 :group 'whitespace)
920 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
921 ;;;; User commands - Local mode
924 ;;;###autoload
925 (define-minor-mode whitespace-mode
926 "Toggle whitespace visualization (Whitespace mode).
928 See also `whitespace-style', `whitespace-newline' and
929 `whitespace-display-mappings'."
930 :lighter " ws"
931 :init-value nil
932 :global nil
933 :group 'whitespace
934 (cond
935 (noninteractive ; running a batch job
936 (setq whitespace-mode nil))
937 (whitespace-mode ; whitespace-mode on
938 (whitespace-turn-on)
939 (whitespace-action-when-on))
940 (t ; whitespace-mode off
941 (whitespace-turn-off))))
944 ;;;###autoload
945 (define-minor-mode whitespace-newline-mode
946 "Toggle newline visualization (Whitespace Newline mode).
948 Use `whitespace-newline-mode' only for NEWLINE visualization
949 exclusively. For other visualizations, including NEWLINE
950 visualization together with (HARD) SPACEs and/or TABs, please,
951 use `whitespace-mode'.
953 See also `whitespace-newline' and `whitespace-display-mappings'."
954 :lighter " nl"
955 :init-value nil
956 :global nil
957 :group 'whitespace
958 (let ((whitespace-style '(face newline-mark newline)))
959 (whitespace-mode (if whitespace-newline-mode
960 1 -1)))
961 ;; sync states (running a batch job)
962 (setq whitespace-newline-mode whitespace-mode))
965 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
966 ;;;; User commands - Global mode
969 ;;;###autoload
970 (define-minor-mode global-whitespace-mode
971 "Toggle whitespace visualization globally (Global Whitespace mode).
973 See also `whitespace-style', `whitespace-newline' and
974 `whitespace-display-mappings'."
975 :lighter " WS"
976 :init-value nil
977 :global t
978 :group 'whitespace
979 (cond
980 (noninteractive ; running a batch job
981 (setq global-whitespace-mode nil))
982 (global-whitespace-mode ; global-whitespace-mode on
983 (save-current-buffer
984 (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
985 (add-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
986 (dolist (buffer (buffer-list)) ; adjust all local mode
987 (set-buffer buffer)
988 (unless whitespace-mode
989 (whitespace-turn-on-if-enabled)))))
990 (t ; global-whitespace-mode off
991 (save-current-buffer
992 (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
993 (remove-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
994 (dolist (buffer (buffer-list)) ; adjust all local mode
995 (set-buffer buffer)
996 (unless whitespace-mode
997 (whitespace-turn-off)))))))
999 (defvar whitespace-enable-predicate
1000 (lambda ()
1001 (and (cond
1002 ((eq whitespace-global-modes t))
1003 ((listp whitespace-global-modes)
1004 (if (eq (car-safe whitespace-global-modes) 'not)
1005 (not (memq major-mode (cdr whitespace-global-modes)))
1006 (memq major-mode whitespace-global-modes)))
1007 (t nil))
1008 ;; ...we have a display (not running a batch job)
1009 (not noninteractive)
1010 ;; ...the buffer is not internal (name starts with a space)
1011 (not (eq (aref (buffer-name) 0) ?\ ))
1012 ;; ...the buffer is not special (name starts with *)
1013 (or (not (eq (aref (buffer-name) 0) ?*))
1014 ;; except the scratch buffer.
1015 (string= (buffer-name) "*scratch*"))))
1016 "Predicate to decide which buffers obey `global-whitespace-mode'.
1017 This function is called with no argument and should return non-nil
1018 if the current buffer should obey `global-whitespace-mode'.
1019 This variable is normally modified via `add-function'.")
1021 (defun whitespace-turn-on-if-enabled ()
1022 (when (funcall whitespace-enable-predicate)
1023 (whitespace-turn-on)))
1025 ;;;###autoload
1026 (define-minor-mode global-whitespace-newline-mode
1027 "Toggle global newline visualization (Global Whitespace Newline mode).
1029 Use `global-whitespace-newline-mode' only for NEWLINE
1030 visualization exclusively. For other visualizations, including
1031 NEWLINE visualization together with (HARD) SPACEs and/or TABs,
1032 please use `global-whitespace-mode'.
1034 See also `whitespace-newline' and `whitespace-display-mappings'."
1035 :lighter " NL"
1036 :init-value nil
1037 :global t
1038 :group 'whitespace
1039 (let ((whitespace-style '(newline-mark newline)))
1040 (global-whitespace-mode (if global-whitespace-newline-mode
1041 1 -1))
1042 ;; sync states (running a batch job)
1043 (setq global-whitespace-newline-mode global-whitespace-mode)))
1046 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1047 ;;;; User commands - Toggle
1050 (defconst whitespace-style-value-list
1051 '(face
1052 tabs
1053 spaces
1054 trailing
1055 lines
1056 lines-tail
1057 newline
1058 empty
1059 indentation
1060 indentation::tab
1061 indentation::space
1062 big-indent
1063 space-after-tab
1064 space-after-tab::tab
1065 space-after-tab::space
1066 space-before-tab
1067 space-before-tab::tab
1068 space-before-tab::space
1069 help-newline ; value used by `whitespace-insert-option-mark'
1070 tab-mark
1071 space-mark
1072 newline-mark
1074 "List of valid `whitespace-style' values.")
1077 (defconst whitespace-toggle-option-alist
1078 '((?f . face)
1079 (?t . tabs)
1080 (?s . spaces)
1081 (?r . trailing)
1082 (?l . lines)
1083 (?L . lines-tail)
1084 (?n . newline)
1085 (?e . empty)
1086 (?\C-i . indentation)
1087 (?I . indentation::tab)
1088 (?i . indentation::space)
1089 (?\C-t . big-indent)
1090 (?\C-a . space-after-tab)
1091 (?A . space-after-tab::tab)
1092 (?a . space-after-tab::space)
1093 (?\C-b . space-before-tab)
1094 (?B . space-before-tab::tab)
1095 (?b . space-before-tab::space)
1096 (?T . tab-mark)
1097 (?S . space-mark)
1098 (?N . newline-mark)
1099 (?x . whitespace-style)
1101 "Alist of toggle options.
1103 Each element has the form:
1105 (CHAR . SYMBOL)
1107 Where:
1109 CHAR is a char which the user will have to type.
1111 SYMBOL is a valid symbol associated with CHAR.
1112 See `whitespace-style-value-list'.")
1115 (defvar whitespace-active-style nil
1116 "Used to save locally `whitespace-style' value.")
1118 (defvar whitespace-point (point)
1119 "Used to save locally current point value.
1120 Used by function `whitespace-trailing-regexp' (which see).")
1121 (defvar-local whitespace-point--used nil
1122 "Region whose highlighting depends on `whitespace-point'.")
1124 (defvar whitespace-font-lock-refontify nil
1125 "Used to save locally the font-lock refontify state.
1126 Used by function `whitespace-post-command-hook' (which see).")
1128 (defvar whitespace-bob-marker nil
1129 "Used to save locally the bob marker value.
1130 Used by function `whitespace-post-command-hook' (which see).")
1132 (defvar whitespace-eob-marker nil
1133 "Used to save locally the eob marker value.
1134 Used by function `whitespace-post-command-hook' (which see).")
1136 (defvar whitespace-buffer-changed nil
1137 "Used to indicate locally if buffer changed.
1138 Used by `whitespace-post-command-hook' and `whitespace-buffer-changed'
1139 functions (which see).")
1142 ;;;###autoload
1143 (defun whitespace-toggle-options (arg)
1144 "Toggle local `whitespace-mode' options.
1146 If local whitespace-mode is off, toggle the option given by ARG
1147 and turn on local whitespace-mode.
1149 If local whitespace-mode is on, toggle the option given by ARG
1150 and restart local whitespace-mode.
1152 Interactively, it reads one of the following chars:
1154 CHAR MEANING
1155 (VIA FACES)
1156 f toggle face visualization
1157 t toggle TAB visualization
1158 s toggle SPACE and HARD SPACE visualization
1159 r toggle trailing blanks visualization
1160 l toggle \"long lines\" visualization
1161 L toggle \"long lines\" tail visualization
1162 n toggle NEWLINE visualization
1163 e toggle empty line at bob and/or eob visualization
1164 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1165 I toggle indentation SPACEs visualization
1166 i toggle indentation TABs visualization
1167 C-t toggle big indentation visualization
1168 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1169 A toggle SPACEs after TAB: SPACEs visualization
1170 a toggle SPACEs after TAB: TABs visualization
1171 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1172 B toggle SPACEs before TAB: SPACEs visualization
1173 b toggle SPACEs before TAB: TABs visualization
1175 (VIA DISPLAY TABLE)
1176 T toggle TAB visualization
1177 S toggle SPACEs before TAB visualization
1178 N toggle NEWLINE visualization
1180 x restore `whitespace-style' value
1181 ? display brief help
1183 Non-interactively, ARG should be a symbol or a list of symbols.
1184 The valid symbols are:
1186 face toggle face visualization
1187 tabs toggle TAB visualization
1188 spaces toggle SPACE and HARD SPACE visualization
1189 trailing toggle trailing blanks visualization
1190 lines toggle \"long lines\" visualization
1191 lines-tail toggle \"long lines\" tail visualization
1192 newline toggle NEWLINE visualization
1193 empty toggle empty line at bob and/or eob visualization
1194 indentation toggle indentation SPACEs visualization
1195 indentation::tab toggle indentation SPACEs visualization
1196 indentation::space toggle indentation TABs visualization
1197 big-indent toggle big indentation visualization
1198 space-after-tab toggle SPACEs after TAB visualization
1199 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1200 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1201 space-before-tab toggle SPACEs before TAB visualization
1202 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1203 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1205 tab-mark toggle TAB visualization
1206 space-mark toggle SPACEs before TAB visualization
1207 newline-mark toggle NEWLINE visualization
1209 whitespace-style restore `whitespace-style' value
1211 See `whitespace-style' and `indent-tabs-mode' for documentation."
1212 (interactive (whitespace-interactive-char t))
1213 (let ((whitespace-style
1214 (whitespace-toggle-list t arg whitespace-active-style)))
1215 (whitespace-mode 0)
1216 (whitespace-mode 1)))
1219 (defvar whitespace-toggle-style nil
1220 "Used to toggle the global `whitespace-style' value.")
1223 ;;;###autoload
1224 (defun global-whitespace-toggle-options (arg)
1225 "Toggle global `whitespace-mode' options.
1227 If global whitespace-mode is off, toggle the option given by ARG
1228 and turn on global whitespace-mode.
1230 If global whitespace-mode is on, toggle the option given by ARG
1231 and restart global whitespace-mode.
1233 Interactively, it accepts one of the following chars:
1235 CHAR MEANING
1236 (VIA FACES)
1237 f toggle face visualization
1238 t toggle TAB visualization
1239 s toggle SPACE and HARD SPACE visualization
1240 r toggle trailing blanks visualization
1241 l toggle \"long lines\" visualization
1242 L toggle \"long lines\" tail visualization
1243 n toggle NEWLINE visualization
1244 e toggle empty line at bob and/or eob visualization
1245 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1246 I toggle indentation SPACEs visualization
1247 i toggle indentation TABs visualization
1248 C-t toggle big indentation visualization
1249 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1250 A toggle SPACEs after TAB: SPACEs visualization
1251 a toggle SPACEs after TAB: TABs visualization
1252 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1253 B toggle SPACEs before TAB: SPACEs visualization
1254 b toggle SPACEs before TAB: TABs visualization
1256 (VIA DISPLAY TABLE)
1257 T toggle TAB visualization
1258 S toggle SPACEs before TAB visualization
1259 N toggle NEWLINE visualization
1261 x restore `whitespace-style' value
1262 ? display brief help
1264 Non-interactively, ARG should be a symbol or a list of symbols.
1265 The valid symbols are:
1267 face toggle face visualization
1268 tabs toggle TAB visualization
1269 spaces toggle SPACE and HARD SPACE visualization
1270 trailing toggle trailing blanks visualization
1271 lines toggle \"long lines\" visualization
1272 lines-tail toggle \"long lines\" tail visualization
1273 newline toggle NEWLINE visualization
1274 empty toggle empty line at bob and/or eob visualization
1275 indentation toggle indentation SPACEs visualization
1276 indentation::tab toggle indentation SPACEs visualization
1277 indentation::space toggle indentation TABs visualization
1278 big-indent toggle big indentation visualization
1279 space-after-tab toggle SPACEs after TAB visualization
1280 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1281 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1282 space-before-tab toggle SPACEs before TAB visualization
1283 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1284 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1286 tab-mark toggle TAB visualization
1287 space-mark toggle SPACEs before TAB visualization
1288 newline-mark toggle NEWLINE visualization
1290 whitespace-style restore `whitespace-style' value
1292 See `whitespace-style' and `indent-tabs-mode' for documentation."
1293 (interactive (whitespace-interactive-char nil))
1294 (let ((whitespace-style
1295 (whitespace-toggle-list nil arg whitespace-toggle-style)))
1296 (setq whitespace-toggle-style whitespace-style)
1297 (global-whitespace-mode 0)
1298 (global-whitespace-mode 1)))
1301 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1302 ;;;; User commands - Cleanup
1305 ;;;###autoload
1306 (defun whitespace-cleanup ()
1307 "Cleanup some blank problems in all buffer or at region.
1309 It usually applies to the whole buffer, but in transient mark
1310 mode when the mark is active, it applies to the region. It also
1311 applies to the region when it is not in transient mark mode, the
1312 mark is active and \\[universal-argument] was pressed just before
1313 calling `whitespace-cleanup' interactively.
1315 See also `whitespace-cleanup-region'.
1317 The problems cleaned up are:
1319 1. empty lines at beginning of buffer.
1320 2. empty lines at end of buffer.
1321 If `whitespace-style' includes the value `empty', remove all
1322 empty lines at beginning and/or end of buffer.
1324 3. `tab-width' or more SPACEs at beginning of line.
1325 If `whitespace-style' includes the value `indentation':
1326 replace `tab-width' or more SPACEs at beginning of line by
1327 TABs, if `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1328 SPACEs.
1329 If `whitespace-style' includes the value `indentation::tab',
1330 replace `tab-width' or more SPACEs at beginning of line by TABs.
1331 If `whitespace-style' includes the value `indentation::space',
1332 replace TABs by SPACEs.
1334 4. SPACEs before TAB.
1335 If `whitespace-style' includes the value `space-before-tab':
1336 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1337 otherwise, replace TABs by SPACEs.
1338 If `whitespace-style' includes the value
1339 `space-before-tab::tab', replace SPACEs by TABs.
1340 If `whitespace-style' includes the value
1341 `space-before-tab::space', replace TABs by SPACEs.
1343 5. SPACEs or TABs at end of line.
1344 If `whitespace-style' includes the value `trailing', remove
1345 all SPACEs or TABs at end of line.
1347 6. `tab-width' or more SPACEs after TAB.
1348 If `whitespace-style' includes the value `space-after-tab':
1349 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1350 otherwise, replace TABs by SPACEs.
1351 If `whitespace-style' includes the value
1352 `space-after-tab::tab', replace SPACEs by TABs.
1353 If `whitespace-style' includes the value
1354 `space-after-tab::space', replace TABs by SPACEs.
1356 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1357 documentation."
1358 (interactive "@")
1359 (cond
1360 ;; read-only buffer
1361 (buffer-read-only
1362 (whitespace-warn-read-only "cleanup"))
1363 ;; region active
1364 ((and (or transient-mark-mode
1365 current-prefix-arg)
1366 mark-active)
1367 ;; PROBLEMs 1 and 2 are not handled in region
1368 ;; PROBLEM 3: `tab-width' or more SPACEs at bol
1369 ;; PROBLEM 4: SPACEs before TAB
1370 ;; PROBLEM 5: SPACEs or TABs at eol
1371 ;; PROBLEM 6: `tab-width' or more SPACEs after TAB
1372 (whitespace-cleanup-region (region-beginning) (region-end)))
1373 ;; whole buffer
1375 (save-excursion
1376 ;; PROBLEM 1: empty lines at bob
1377 ;; PROBLEM 2: empty lines at eob
1378 ;; ACTION: remove all empty lines at bob and/or eob
1379 (when (memq 'empty whitespace-style)
1380 (let (overwrite-mode) ; enforce no overwrite
1381 (goto-char (point-min))
1382 (when (looking-at whitespace-empty-at-bob-regexp)
1383 (delete-region (match-beginning 1) (match-end 1)))
1384 (when (re-search-forward
1385 whitespace-empty-at-eob-regexp nil t)
1386 (delete-region (match-beginning 1) (match-end 1))))))
1387 ;; PROBLEM 3: `tab-width' or more SPACEs at bol
1388 ;; PROBLEM 4: SPACEs before TAB
1389 ;; PROBLEM 5: SPACEs or TABs at eol
1390 ;; PROBLEM 6: `tab-width' or more SPACEs after TAB
1391 (whitespace-cleanup-region (point-min) (point-max)))))
1394 ;;;###autoload
1395 (defun whitespace-cleanup-region (start end)
1396 "Cleanup some blank problems at region.
1398 The problems cleaned up are:
1400 1. `tab-width' or more SPACEs at beginning of line.
1401 If `whitespace-style' includes the value `indentation':
1402 replace `tab-width' or more SPACEs at beginning of line by TABs,
1403 if `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1404 SPACEs.
1405 If `whitespace-style' includes the value `indentation::tab',
1406 replace `tab-width' or more SPACEs at beginning of line by TABs.
1407 If `whitespace-style' includes the value `indentation::space',
1408 replace TABs by SPACEs.
1410 2. SPACEs before TAB.
1411 If `whitespace-style' includes the value `space-before-tab':
1412 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1413 otherwise, replace TABs by SPACEs.
1414 If `whitespace-style' includes the value
1415 `space-before-tab::tab', replace SPACEs by TABs.
1416 If `whitespace-style' includes the value
1417 `space-before-tab::space', replace TABs by SPACEs.
1419 3. SPACEs or TABs at end of line.
1420 If `whitespace-style' includes the value `trailing', remove
1421 all SPACEs or TABs at end of line.
1423 4. `tab-width' or more SPACEs after TAB.
1424 If `whitespace-style' includes the value `space-after-tab':
1425 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1426 otherwise, replace TABs by SPACEs.
1427 If `whitespace-style' includes the value
1428 `space-after-tab::tab', replace SPACEs by TABs.
1429 If `whitespace-style' includes the value
1430 `space-after-tab::space', replace TABs by SPACEs.
1432 See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1433 documentation."
1434 (interactive "@r")
1435 (if buffer-read-only
1436 ;; read-only buffer
1437 (whitespace-warn-read-only "cleanup region")
1438 ;; non-read-only buffer
1439 (let ((rstart (min start end))
1440 (rend (copy-marker (max start end)))
1441 overwrite-mode ; enforce no overwrite
1442 tmp)
1443 (save-excursion
1444 ;; PROBLEM 1: `tab-width' or more SPACEs at bol
1445 (cond
1446 ;; ACTION: replace `tab-width' or more SPACEs at bol by TABs, if
1447 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1448 ;; by SPACEs.
1449 ((memq 'indentation whitespace-style)
1450 (let ((regexp (whitespace-indentation-regexp)))
1451 (goto-char rstart)
1452 (while (re-search-forward regexp rend t)
1453 (setq tmp (current-indentation))
1454 (goto-char (match-beginning 0))
1455 (delete-horizontal-space)
1456 (unless (eolp)
1457 (indent-to tmp)))))
1458 ;; ACTION: replace `tab-width' or more SPACEs at bol by TABs.
1459 ((memq 'indentation::tab whitespace-style)
1460 (whitespace-replace-action
1461 'tabify rstart rend
1462 (whitespace-indentation-regexp 'tab) 0))
1463 ;; ACTION: replace TABs by SPACEs.
1464 ((memq 'indentation::space whitespace-style)
1465 (whitespace-replace-action
1466 'untabify rstart rend
1467 (whitespace-indentation-regexp 'space) 0)))
1468 ;; PROBLEM 3: SPACEs or TABs at eol
1469 ;; ACTION: remove all SPACEs or TABs at eol
1470 (when (memq 'trailing whitespace-style)
1471 (whitespace-replace-action
1472 'delete-region rstart rend
1473 whitespace-trailing-regexp 1))
1474 ;; PROBLEM 4: `tab-width' or more SPACEs after TAB
1475 (cond
1476 ;; ACTION: replace `tab-width' or more SPACEs by TABs, if
1477 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1478 ;; by SPACEs.
1479 ((memq 'space-after-tab whitespace-style)
1480 (whitespace-replace-action
1481 (if indent-tabs-mode 'tabify 'untabify)
1482 rstart rend (whitespace-space-after-tab-regexp) 1))
1483 ;; ACTION: replace `tab-width' or more SPACEs by TABs.
1484 ((memq 'space-after-tab::tab whitespace-style)
1485 (whitespace-replace-action
1486 'tabify rstart rend
1487 (whitespace-space-after-tab-regexp 'tab) 1))
1488 ;; ACTION: replace TABs by SPACEs.
1489 ((memq 'space-after-tab::space whitespace-style)
1490 (whitespace-replace-action
1491 'untabify rstart rend
1492 (whitespace-space-after-tab-regexp 'space) 1)))
1493 ;; PROBLEM 2: SPACEs before TAB
1494 (cond
1495 ;; ACTION: replace SPACEs before TAB by TABs, if
1496 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs
1497 ;; by SPACEs.
1498 ((memq 'space-before-tab whitespace-style)
1499 (whitespace-replace-action
1500 (if indent-tabs-mode 'tabify 'untabify)
1501 rstart rend whitespace-space-before-tab-regexp
1502 (if indent-tabs-mode 0 2)))
1503 ;; ACTION: replace SPACEs before TAB by TABs.
1504 ((memq 'space-before-tab::tab whitespace-style)
1505 (whitespace-replace-action
1506 'tabify rstart rend
1507 whitespace-space-before-tab-regexp 0))
1508 ;; ACTION: replace TABs by SPACEs.
1509 ((memq 'space-before-tab::space whitespace-style)
1510 (whitespace-replace-action
1511 'untabify rstart rend
1512 whitespace-space-before-tab-regexp 2))))
1513 (set-marker rend nil)))) ; point marker to nowhere
1516 (defun whitespace-replace-action (action rstart rend regexp index)
1517 "Do ACTION in the string matched by REGEXP between RSTART and REND.
1519 INDEX is the level group matched by REGEXP and used by ACTION.
1521 See also `tab-width'."
1522 (goto-char rstart)
1523 (while (re-search-forward regexp rend t)
1524 (goto-char (match-end index))
1525 (funcall action (match-beginning index) (match-end index))))
1528 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1529 ;;;; User command - report
1532 (defun whitespace-regexp (regexp &optional kind)
1533 "Return REGEXP depending on `indent-tabs-mode'."
1534 (format
1535 (cond
1536 ((or (eq kind 'tab)
1537 indent-tabs-mode)
1538 (car regexp))
1539 ((or (eq kind 'space)
1540 (not indent-tabs-mode))
1541 (cdr regexp)))
1542 tab-width))
1545 (defun whitespace-indentation-regexp (&optional kind)
1546 "Return the indentation regexp depending on `indent-tabs-mode'."
1547 (whitespace-regexp whitespace-indentation-regexp kind))
1550 (defun whitespace-space-after-tab-regexp (&optional kind)
1551 "Return the space-after-tab regexp depending on `indent-tabs-mode'."
1552 (whitespace-regexp whitespace-space-after-tab-regexp kind))
1555 (defconst whitespace-report-list
1556 (list
1557 (cons 'empty whitespace-empty-at-bob-regexp)
1558 (cons 'empty whitespace-empty-at-eob-regexp)
1559 (cons 'trailing whitespace-trailing-regexp)
1560 (cons 'indentation nil)
1561 (cons 'indentation::tab nil)
1562 (cons 'indentation::space nil)
1563 (cons 'space-before-tab whitespace-space-before-tab-regexp)
1564 (cons 'space-before-tab::tab whitespace-space-before-tab-regexp)
1565 (cons 'space-before-tab::space whitespace-space-before-tab-regexp)
1566 (cons 'space-after-tab nil)
1567 (cons 'space-after-tab::tab nil)
1568 (cons 'space-after-tab::space nil)
1570 "List of whitespace bogus symbol and corresponding regexp.")
1573 (defconst whitespace-report-text
1574 '( ;; `indent-tabs-mode' has non-nil value
1576 Whitespace Report
1578 Current Setting Whitespace Problem
1580 empty [] [] empty lines at beginning of buffer
1581 empty [] [] empty lines at end of buffer
1582 trailing [] [] SPACEs or TABs at end of line
1583 indentation [] [] >= `tab-width' SPACEs at beginning of line
1584 indentation::tab [] [] >= `tab-width' SPACEs at beginning of line
1585 indentation::space [] [] TABs at beginning of line
1586 space-before-tab [] [] SPACEs before TAB
1587 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1588 space-before-tab::space [] [] SPACEs before TAB: TABs
1589 space-after-tab [] [] >= `tab-width' SPACEs after TAB
1590 space-after-tab::tab [] [] >= `tab-width' SPACEs after TAB: SPACEs
1591 space-after-tab::space [] [] >= `tab-width' SPACEs after TAB: TABs
1593 indent-tabs-mode =
1594 tab-width = \n\n"
1595 . ;; `indent-tabs-mode' has nil value
1597 Whitespace Report
1599 Current Setting Whitespace Problem
1601 empty [] [] empty lines at beginning of buffer
1602 empty [] [] empty lines at end of buffer
1603 trailing [] [] SPACEs or TABs at end of line
1604 indentation [] [] TABs at beginning of line
1605 indentation::tab [] [] >= `tab-width' SPACEs at beginning of line
1606 indentation::space [] [] TABs at beginning of line
1607 space-before-tab [] [] SPACEs before TAB
1608 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1609 space-before-tab::space [] [] SPACEs before TAB: TABs
1610 space-after-tab [] [] >= `tab-width' SPACEs after TAB
1611 space-after-tab::tab [] [] >= `tab-width' SPACEs after TAB: SPACEs
1612 space-after-tab::space [] [] >= `tab-width' SPACEs after TAB: TABs
1614 indent-tabs-mode =
1615 tab-width = \n\n")
1616 "Text for whitespace bogus report.
1618 It is a cons of strings, where the car part is used when
1619 `indent-tabs-mode' is non-nil, and the cdr part is used when
1620 `indent-tabs-mode' is nil.")
1623 (defconst whitespace-report-buffer-name "*Whitespace Report*"
1624 "The buffer name for whitespace bogus report.")
1627 ;;;###autoload
1628 (defun whitespace-report (&optional force report-if-bogus)
1629 "Report some whitespace problems in buffer.
1631 Perform `whitespace-report-region' on the current buffer."
1632 (interactive (list current-prefix-arg))
1633 (whitespace-report-region (point-min) (point-max)
1634 force report-if-bogus))
1637 ;;;###autoload
1638 (defun whitespace-report-region (start end &optional force report-if-bogus)
1639 "Report some whitespace problems in a region.
1641 Return nil if there is no whitespace problem; otherwise, return
1642 non-nil.
1644 If FORCE is non-nil or \\[universal-argument] was pressed just
1645 before calling `whitespace-report-region' interactively, it
1646 forces all classes of whitespace problem to be considered
1647 significant.
1649 If REPORT-IF-BOGUS is t, it reports only when there are any
1650 whitespace problems in buffer; if it is `never', it does not
1651 report problems.
1653 Report if some of the following whitespace problems exist:
1655 * If `indent-tabs-mode' is non-nil:
1656 empty 1. empty lines at beginning of buffer.
1657 empty 2. empty lines at end of buffer.
1658 trailing 3. SPACEs or TABs at end of line.
1659 indentation 4. line starts with `tab-width' or more SPACEs.
1660 space-before-tab 5. SPACEs before TAB.
1661 space-after-tab 6. `tab-width' or more SPACEs after TAB.
1663 * If `indent-tabs-mode' is nil:
1664 empty 1. empty lines at beginning of buffer.
1665 empty 2. empty lines at end of buffer.
1666 trailing 3. SPACEs or TABs at end of line.
1667 indentation 4. TABS at beginning of line.
1668 space-before-tab 5. SPACEs before TAB.
1669 space-after-tab 6. `tab-width' or more SPACEs after TAB.
1671 See `whitespace-style' for documentation.
1672 See also `whitespace-cleanup' and `whitespace-cleanup-region' for
1673 cleaning up these problems."
1674 (interactive "r")
1675 (setq force (or current-prefix-arg force))
1676 (save-excursion
1677 (let* ((has-bogus nil)
1678 (rstart (min start end))
1679 (rend (max start end))
1680 ;; Fall back to whitespace-style so we can run before
1681 ;; before the mode is active.
1682 (style (copy-sequence
1683 (or whitespace-active-style whitespace-style)))
1684 (bogus-list
1685 (mapcar
1686 #'(lambda (option)
1687 (when force
1688 (add-to-list 'style (car option)))
1689 (goto-char rstart)
1690 (let ((regexp
1691 (cond
1692 ((eq (car option) 'indentation)
1693 (whitespace-indentation-regexp))
1694 ((eq (car option) 'indentation::tab)
1695 (whitespace-indentation-regexp 'tab))
1696 ((eq (car option) 'indentation::space)
1697 (whitespace-indentation-regexp 'space))
1698 ((eq (car option) 'space-after-tab)
1699 (whitespace-space-after-tab-regexp))
1700 ((eq (car option) 'space-after-tab::tab)
1701 (whitespace-space-after-tab-regexp 'tab))
1702 ((eq (car option) 'space-after-tab::space)
1703 (whitespace-space-after-tab-regexp 'space))
1705 (cdr option)))))
1706 (when (re-search-forward regexp rend t)
1707 (unless has-bogus
1708 (setq has-bogus (memq (car option) style)))
1709 t)))
1710 whitespace-report-list)))
1711 (when (pcase report-if-bogus (`nil t) (`never nil) (_ has-bogus))
1712 (whitespace-kill-buffer whitespace-report-buffer-name)
1713 ;; `indent-tabs-mode' may be local to current buffer
1714 ;; `tab-width' may be local to current buffer
1715 (let ((ws-indent-tabs-mode indent-tabs-mode)
1716 (ws-tab-width tab-width))
1717 (with-current-buffer (get-buffer-create
1718 whitespace-report-buffer-name)
1719 (erase-buffer)
1720 (insert (if ws-indent-tabs-mode
1721 (car whitespace-report-text)
1722 (cdr whitespace-report-text)))
1723 (goto-char (point-min))
1724 (forward-line 3)
1725 (dolist (option whitespace-report-list)
1726 (forward-line 1)
1727 (whitespace-mark-x
1728 27 (memq (car option) style))
1729 (whitespace-mark-x 7 (car bogus-list))
1730 (setq bogus-list (cdr bogus-list)))
1731 (forward-line 1)
1732 (whitespace-insert-value ws-indent-tabs-mode)
1733 (whitespace-insert-value ws-tab-width)
1734 (when has-bogus
1735 (goto-char (point-max))
1736 (insert (substitute-command-keys
1737 " Type `\\[whitespace-cleanup]'")
1738 " to cleanup the buffer.\n\n"
1739 (substitute-command-keys
1740 " Type `\\[whitespace-cleanup-region]'")
1741 " to cleanup a region.\n\n"))
1742 (whitespace-display-window (current-buffer)))))
1743 has-bogus)))
1746 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1747 ;;;; Internal functions
1750 (defvar whitespace-font-lock-keywords nil
1751 "Used to save the value `whitespace-color-on' adds to `font-lock-keywords'.")
1754 (defconst whitespace-help-text
1756 Whitespace Toggle Options | scroll up : SPC or > |
1757 | scroll down: M-SPC or < |
1758 FACES \\__________________________/
1759 [] f - toggle face visualization
1760 [] t - toggle TAB visualization
1761 [] s - toggle SPACE and HARD SPACE visualization
1762 [] r - toggle trailing blanks visualization
1763 [] l - toggle \"long lines\" visualization
1764 [] L - toggle \"long lines\" tail visualization
1765 [] n - toggle NEWLINE visualization
1766 [] e - toggle empty line at bob and/or eob visualization
1767 [] C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode')
1768 [] I - toggle indentation SPACEs visualization
1769 [] i - toggle indentation TABs visualization
1770 [] C-t - toggle big indentation visualization
1771 [] C-a - toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1772 [] A - toggle SPACEs after TAB: SPACEs visualization
1773 [] a - toggle SPACEs after TAB: TABs visualization
1774 [] C-b - toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1775 [] B - toggle SPACEs before TAB: SPACEs visualization
1776 [] b - toggle SPACEs before TAB: TABs visualization
1778 DISPLAY TABLE
1779 [] T - toggle TAB visualization
1780 [] S - toggle SPACE and HARD SPACE visualization
1781 [] N - toggle NEWLINE visualization
1783 x - restore `whitespace-style' value
1785 ? - display this text\n\n"
1786 "Text for whitespace toggle options.")
1789 (defconst whitespace-help-buffer-name "*Whitespace Toggle Options*"
1790 "The buffer name for whitespace toggle options.")
1793 (defun whitespace-insert-value (value)
1794 "Insert VALUE at column 20 of next line."
1795 (forward-line 1)
1796 (move-to-column 20 t)
1797 (insert (format "%s" value)))
1800 (defun whitespace-mark-x (nchars condition)
1801 "Insert the mark (`X' or ` ') after NCHARS depending on CONDITION."
1802 (forward-char nchars)
1803 (insert (if condition "X" " ")))
1806 (defun whitespace-insert-option-mark (the-list the-value)
1807 "Insert the option mark (`X' or ` ') in toggle options buffer."
1808 (goto-char (point-min))
1809 (forward-line 2)
1810 (dolist (sym the-list)
1811 (if (eq sym 'help-newline)
1812 (forward-line 2)
1813 (forward-line 1)
1814 (whitespace-mark-x 2 (memq sym the-value)))))
1817 (defun whitespace-help-on (style)
1818 "Display the whitespace toggle options."
1819 (unless (get-buffer whitespace-help-buffer-name)
1820 (delete-other-windows)
1821 (let ((buffer (get-buffer-create whitespace-help-buffer-name)))
1822 (with-current-buffer buffer
1823 (erase-buffer)
1824 (insert whitespace-help-text)
1825 (whitespace-insert-option-mark
1826 whitespace-style-value-list style)
1827 (whitespace-display-window buffer)))))
1830 (defun whitespace-display-window (buffer)
1831 "Display BUFFER in a new window."
1832 (goto-char (point-min))
1833 (set-buffer-modified-p nil)
1834 (when (< (window-height) (* 2 window-min-height))
1835 (kill-buffer buffer)
1836 (error "Window height is too small; \
1837 can't split window to display whitespace toggle options"))
1838 (let ((win (split-window)))
1839 (set-window-buffer win buffer)
1840 (shrink-window-if-larger-than-buffer win)))
1843 (defun whitespace-kill-buffer (buffer-name)
1844 "Kill buffer BUFFER-NAME and windows related with it."
1845 (let ((buffer (get-buffer buffer-name)))
1846 (when buffer
1847 (delete-windows-on buffer)
1848 (kill-buffer buffer))))
1851 (defun whitespace-help-off ()
1852 "Remove the buffer and window of the whitespace toggle options."
1853 (whitespace-kill-buffer whitespace-help-buffer-name))
1856 (defun whitespace-help-scroll (&optional up)
1857 "Scroll help window, if it exists.
1859 If UP is non-nil, scroll up; otherwise, scroll down."
1860 (condition-case nil
1861 (let ((buffer (get-buffer whitespace-help-buffer-name)))
1862 (if buffer
1863 (with-selected-window (get-buffer-window buffer)
1864 (if up
1865 (scroll-up 3)
1866 (scroll-down 3)))
1867 (ding)))
1868 ;; handler
1869 ((error)
1870 ;; just ignore error
1874 (defun whitespace-interactive-char (local-p)
1875 "Interactive function to read a char and return a symbol.
1877 If LOCAL-P is non-nil, it uses a local context; otherwise, it
1878 uses a global context.
1880 It accepts one of the following chars:
1882 CHAR MEANING
1883 (VIA FACES)
1884 f toggle face visualization
1885 t toggle TAB visualization
1886 s toggle SPACE and HARD SPACE visualization
1887 r toggle trailing blanks visualization
1888 l toggle \"long lines\" visualization
1889 L toggle \"long lines\" tail visualization
1890 n toggle NEWLINE visualization
1891 e toggle empty line at bob and/or eob visualization
1892 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1893 I toggle indentation SPACEs visualization
1894 i toggle indentation TABs visualization
1895 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1896 A toggle SPACEs after TAB: SPACEs visualization
1897 a toggle SPACEs after TAB: TABs visualization
1898 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1899 B toggle SPACEs before TAB: SPACEs visualization
1900 b toggle SPACEs before TAB: TABs visualization
1902 (VIA DISPLAY TABLE)
1903 T toggle TAB visualization
1904 S toggle SPACE and HARD SPACE visualization
1905 N toggle NEWLINE visualization
1907 x restore `whitespace-style' value
1908 ? display brief help
1910 See also `whitespace-toggle-option-alist'."
1911 (let* ((is-off (not (if local-p
1912 whitespace-mode
1913 global-whitespace-mode)))
1914 (style (cond (is-off whitespace-style) ; use default value
1915 (local-p whitespace-active-style)
1916 (t whitespace-toggle-style)))
1917 (prompt
1918 (format "Whitespace Toggle %s (type ? for further options)-"
1919 (if local-p "Local" "Global")))
1920 ch sym)
1921 ;; read a valid option and get the corresponding symbol
1922 (save-window-excursion
1923 (condition-case data
1924 (progn
1925 (while
1926 ;; while condition
1927 (progn
1928 (setq ch (read-char prompt))
1929 (not
1930 (setq sym
1931 (cdr
1932 (assq ch whitespace-toggle-option-alist)))))
1933 ;; while body
1934 (cond
1935 ((eq ch ?\?) (whitespace-help-on style))
1936 ((eq ch ?\ ) (whitespace-help-scroll t))
1937 ((eq ch ?\M- ) (whitespace-help-scroll))
1938 ((eq ch ?>) (whitespace-help-scroll t))
1939 ((eq ch ?<) (whitespace-help-scroll))
1940 (t (ding))))
1941 (whitespace-help-off)
1942 (message " ")) ; clean echo area
1943 ;; handler
1944 ((quit error)
1945 (whitespace-help-off)
1946 (error (error-message-string data)))))
1947 (list sym))) ; return the appropriate symbol
1950 (defun whitespace-toggle-list (local-p arg the-list)
1951 "Toggle options in THE-LIST based on list ARG.
1953 If LOCAL-P is non-nil, it uses a local context; otherwise, it
1954 uses a global context.
1956 ARG is a list of options to be toggled.
1958 THE-LIST is a list of options. This list will be toggled and the
1959 resultant list will be returned."
1960 (unless (if local-p whitespace-mode global-whitespace-mode)
1961 (setq the-list whitespace-style))
1962 (setq the-list (copy-sequence the-list)) ; keep original list
1963 (dolist (sym (if (listp arg) arg (list arg)))
1964 (cond
1965 ;; ignore help value
1966 ((eq sym 'help-newline))
1967 ;; restore default values
1968 ((eq sym 'whitespace-style)
1969 (setq the-list whitespace-style))
1970 ;; toggle valid values
1971 ((memq sym whitespace-style-value-list)
1972 (setq the-list (if (memq sym the-list)
1973 (delq sym the-list)
1974 (cons sym the-list))))))
1975 the-list)
1978 (defvar whitespace-display-table nil
1979 "Used to save a local display table.")
1981 (defvar whitespace-display-table-was-local nil
1982 "Used to remember whether a buffer initially had a local display table.")
1984 (defun whitespace-turn-on ()
1985 "Turn on whitespace visualization."
1986 ;; prepare local hooks
1987 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
1988 ;; create whitespace local buffer environment
1989 (set (make-local-variable 'whitespace-font-lock-keywords) nil)
1990 (set (make-local-variable 'whitespace-display-table) nil)
1991 (set (make-local-variable 'whitespace-display-table-was-local) nil)
1992 (set (make-local-variable 'whitespace-active-style)
1993 (if (listp whitespace-style)
1994 whitespace-style
1995 (list whitespace-style)))
1996 ;; turn on whitespace
1997 (when whitespace-active-style
1998 (whitespace-color-on)
1999 (whitespace-display-char-on)))
2002 (defun whitespace-turn-off ()
2003 "Turn off whitespace visualization."
2004 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
2005 (when whitespace-active-style
2006 (whitespace-color-off)
2007 (whitespace-display-char-off)))
2010 (defun whitespace-style-face-p ()
2011 "Return t if there is some visualization via face."
2012 (and (memq 'face whitespace-active-style)
2013 (or (memq 'tabs whitespace-active-style)
2014 (memq 'spaces whitespace-active-style)
2015 (memq 'trailing whitespace-active-style)
2016 (memq 'lines whitespace-active-style)
2017 (memq 'lines-tail whitespace-active-style)
2018 (memq 'newline whitespace-active-style)
2019 (memq 'empty whitespace-active-style)
2020 (memq 'indentation whitespace-active-style)
2021 (memq 'indentation::tab whitespace-active-style)
2022 (memq 'indentation::space whitespace-active-style)
2023 (memq 'big-indent whitespace-active-style)
2024 (memq 'space-after-tab whitespace-active-style)
2025 (memq 'space-after-tab::tab whitespace-active-style)
2026 (memq 'space-after-tab::space whitespace-active-style)
2027 (memq 'space-before-tab whitespace-active-style)
2028 (memq 'space-before-tab::tab whitespace-active-style)
2029 (memq 'space-before-tab::space whitespace-active-style))))
2032 (defun whitespace-color-on ()
2033 "Turn on color visualization."
2034 (when (whitespace-style-face-p)
2035 ;; save current point and refontify when necessary
2036 (set (make-local-variable 'whitespace-point)
2037 (point))
2038 (setq whitespace-point--used
2039 (let ((ol (make-overlay (point) (point) nil nil t)))
2040 (delete-overlay ol) ol))
2041 (set (make-local-variable 'whitespace-font-lock-refontify)
2043 (set (make-local-variable 'whitespace-bob-marker)
2044 (point-min-marker))
2045 (set (make-local-variable 'whitespace-eob-marker)
2046 (point-max-marker))
2047 (set (make-local-variable 'whitespace-buffer-changed)
2048 nil)
2049 (add-hook 'post-command-hook #'whitespace-post-command-hook nil t)
2050 (add-hook 'before-change-functions #'whitespace-buffer-changed nil t)
2051 ;; Add whitespace-mode color into font lock.
2052 (setq
2053 whitespace-font-lock-keywords
2055 (whitespace-point--flush-used)
2056 ,@(when (memq 'spaces whitespace-active-style)
2057 ;; Show SPACEs.
2058 `((,whitespace-space-regexp 1 whitespace-space t)
2059 ;; Show HARD SPACEs.
2060 (,whitespace-hspace-regexp 1 whitespace-hspace t)))
2061 ,@(when (memq 'tabs whitespace-active-style)
2062 ;; Show TABs.
2063 `((,whitespace-tab-regexp 1 whitespace-tab t)))
2064 ,@(when (memq 'trailing whitespace-active-style)
2065 ;; Show trailing blanks.
2066 `((,#'whitespace-trailing-regexp 1 whitespace-trailing t)))
2067 ,@(when (or (memq 'lines whitespace-active-style)
2068 (memq 'lines-tail whitespace-active-style))
2069 ;; Show "long" lines.
2070 `((,(let ((line-column (or whitespace-line-column fill-column)))
2071 (format
2072 "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
2073 tab-width
2074 (1- tab-width)
2075 (/ line-column tab-width)
2076 (let ((rem (% line-column tab-width)))
2077 (if (zerop rem)
2079 (format ".\\{%d\\}" rem)))))
2080 ,(if (memq 'lines whitespace-active-style)
2081 0 ; whole line
2082 2) ; line tail
2083 whitespace-line prepend)))
2084 ,@(when (or (memq 'space-before-tab whitespace-active-style)
2085 (memq 'space-before-tab::tab whitespace-active-style)
2086 (memq 'space-before-tab::space whitespace-active-style))
2087 `((,whitespace-space-before-tab-regexp
2088 ,(cond
2089 ((memq 'space-before-tab whitespace-active-style)
2090 ;; Show SPACEs before TAB (indent-tabs-mode).
2091 (if indent-tabs-mode 1 2))
2092 ((memq 'space-before-tab::tab whitespace-active-style)
2094 ((memq 'space-before-tab::space whitespace-active-style)
2096 whitespace-space-before-tab t)))
2097 ,@(when (or (memq 'indentation whitespace-active-style)
2098 (memq 'indentation::tab whitespace-active-style)
2099 (memq 'indentation::space whitespace-active-style))
2100 `((,(cond
2101 ((memq 'indentation whitespace-active-style)
2102 ;; Show indentation SPACEs (indent-tabs-mode).
2103 (whitespace-indentation-regexp))
2104 ((memq 'indentation::tab whitespace-active-style)
2105 ;; Show indentation SPACEs (SPACEs).
2106 (whitespace-indentation-regexp 'tab))
2107 ((memq 'indentation::space whitespace-active-style)
2108 ;; Show indentation SPACEs (TABs).
2109 (whitespace-indentation-regexp 'space)))
2110 1 whitespace-indentation t)))
2111 ,@(when (memq 'big-indent whitespace-active-style)
2112 ;; Show big indentation.
2113 `((,whitespace-big-indent-regexp 1 'whitespace-big-indent t)))
2114 ,@(when (memq 'empty whitespace-active-style)
2115 ;; Show empty lines at beginning of buffer.
2116 `((,#'whitespace-empty-at-bob-regexp
2117 1 whitespace-empty t)
2118 ;; Show empty lines at end of buffer.
2119 (,#'whitespace-empty-at-eob-regexp
2120 1 whitespace-empty t)))
2121 ,@(when (or (memq 'space-after-tab whitespace-active-style)
2122 (memq 'space-after-tab::tab whitespace-active-style)
2123 (memq 'space-after-tab::space whitespace-active-style))
2124 `((,(cond
2125 ((memq 'space-after-tab whitespace-active-style)
2126 ;; Show SPACEs after TAB (indent-tabs-mode).
2127 (whitespace-space-after-tab-regexp))
2128 ((memq 'space-after-tab::tab whitespace-active-style)
2129 ;; Show SPACEs after TAB (SPACEs).
2130 (whitespace-space-after-tab-regexp 'tab))
2131 ((memq 'space-after-tab::space whitespace-active-style)
2132 ;; Show SPACEs after TAB (TABs).
2133 (whitespace-space-after-tab-regexp 'space)))
2134 1 whitespace-space-after-tab t)))))
2135 (font-lock-add-keywords nil whitespace-font-lock-keywords t)
2136 (font-lock-flush)))
2139 (defun whitespace-color-off ()
2140 "Turn off color visualization."
2141 ;; turn off font lock
2142 (kill-local-variable 'whitespace-point--used)
2143 (when (whitespace-style-face-p)
2144 (remove-hook 'post-command-hook #'whitespace-post-command-hook t)
2145 (remove-hook 'before-change-functions #'whitespace-buffer-changed t)
2146 (font-lock-remove-keywords nil whitespace-font-lock-keywords)
2147 (font-lock-flush)))
2149 (defun whitespace-point--used (start end)
2150 (let ((ostart (overlay-start whitespace-point--used)))
2151 (if ostart
2152 (move-overlay whitespace-point--used
2153 (min start ostart)
2154 (max end (overlay-end whitespace-point--used)))
2155 (move-overlay whitespace-point--used start end))))
2157 (defun whitespace-point--flush-used (limit)
2158 (let ((ostart (overlay-start whitespace-point--used)))
2159 ;; Strip parts of whitespace-point--used we're about to refresh.
2160 (when ostart
2161 (let ((oend (overlay-end whitespace-point--used)))
2162 (if (<= (point) ostart)
2163 (if (<= oend limit)
2164 (delete-overlay whitespace-point--used)
2165 (move-overlay whitespace-point--used limit oend)))
2166 (if (<= oend limit)
2167 (move-overlay whitespace-point--used ostart (point))))))
2168 nil)
2170 (defun whitespace-trailing-regexp (limit)
2171 "Match trailing spaces which do not contain the point at end of line."
2172 (let ((status t))
2173 (while (if (re-search-forward whitespace-trailing-regexp limit t)
2174 (when (= whitespace-point (match-end 1)) ; Loop if point at eol.
2175 (whitespace-point--used (match-beginning 0) (match-end 0))
2177 (setq status nil))) ;; end of buffer
2178 status))
2181 (defun whitespace-empty-at-bob-regexp (limit)
2182 "Match spaces at beginning of buffer which do not contain the point at \
2183 beginning of buffer."
2184 (let ((b (point))
2186 (cond
2187 ;; at bob
2188 ((= b 1)
2189 (setq r (and (looking-at whitespace-empty-at-bob-regexp)
2190 (or (/= whitespace-point 1)
2191 (progn (whitespace-point--used (match-beginning 0)
2192 (match-end 0))
2193 nil))))
2194 (set-marker whitespace-bob-marker (if r (match-end 1) b)))
2195 ;; inside bob empty region
2196 ((<= limit whitespace-bob-marker)
2197 (setq r (looking-at whitespace-empty-at-bob-regexp))
2198 (if r
2199 (when (< (match-end 1) limit)
2200 (set-marker whitespace-bob-marker (match-end 1)))
2201 (set-marker whitespace-bob-marker b)))
2202 ;; intersection with end of bob empty region
2203 ((<= b whitespace-bob-marker)
2204 (setq r (looking-at whitespace-empty-at-bob-regexp))
2205 (set-marker whitespace-bob-marker (if r (match-end 1) b)))
2206 ;; it is not inside bob empty region
2208 (setq r nil)))
2209 ;; move to end of matching
2210 (and r (goto-char (match-end 1)))
2214 (defsubst whitespace-looking-back (regexp limit)
2215 (save-excursion
2216 (when (/= 0 (skip-chars-backward " \t\n" limit))
2217 (unless (bolp)
2218 (forward-line 1))
2219 (looking-at regexp))))
2222 (defun whitespace-empty-at-eob-regexp (limit)
2223 "Match spaces at end of buffer which do not contain the point at end of \
2224 buffer."
2225 (let ((b (point))
2226 (e (1+ (buffer-size)))
2228 (cond
2229 ;; at eob
2230 ((= limit e)
2231 (goto-char limit)
2232 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2233 (when (and r (= whitespace-point e))
2234 (setq r nil)
2235 (whitespace-point--used (match-beginning 0) (match-end 0)))
2236 (if r
2237 (set-marker whitespace-eob-marker (match-beginning 1))
2238 (set-marker whitespace-eob-marker limit)
2239 (goto-char b))) ; return back to initial position
2240 ;; inside eob empty region
2241 ((>= b whitespace-eob-marker)
2242 (goto-char limit)
2243 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2244 (if r
2245 (when (> (match-beginning 1) b)
2246 (set-marker whitespace-eob-marker (match-beginning 1)))
2247 (set-marker whitespace-eob-marker limit)
2248 (goto-char b))) ; return back to initial position
2249 ;; intersection with beginning of eob empty region
2250 ((>= limit whitespace-eob-marker)
2251 (goto-char limit)
2252 (setq r (whitespace-looking-back whitespace-empty-at-eob-regexp b))
2253 (if r
2254 (set-marker whitespace-eob-marker (match-beginning 1))
2255 (set-marker whitespace-eob-marker limit)
2256 (goto-char b))) ; return back to initial position
2257 ;; it is not inside eob empty region
2259 (setq r nil)))
2263 (defun whitespace-buffer-changed (_beg _end)
2264 "Set `whitespace-buffer-changed' variable to t."
2265 (setq whitespace-buffer-changed t))
2268 (defun whitespace-post-command-hook ()
2269 "Save current point into `whitespace-point' variable.
2270 Also refontify when necessary."
2271 (unless (and (eq whitespace-point (point))
2272 (not whitespace-buffer-changed))
2273 (setq whitespace-point (point)) ; current point position
2274 (let ((refontify
2275 (cond
2276 ;; It is at end of buffer (eob).
2277 ((= whitespace-point (1+ (buffer-size)))
2278 (when (whitespace-looking-back whitespace-empty-at-eob-regexp
2279 nil)
2280 (match-beginning 0)))
2281 ;; It is at end of line ...
2282 ((and (eolp)
2283 ;; ... with trailing SPACE or TAB
2284 (or (memq (preceding-char) '(?\s ?\t))))
2285 (line-beginning-position))
2286 ;; It is at beginning of buffer (bob).
2287 ((and (= whitespace-point 1)
2288 (looking-at whitespace-empty-at-bob-regexp))
2289 (match-end 0))))
2290 (ostart (overlay-start whitespace-point--used)))
2291 (cond
2292 ((not refontify)
2293 ;; New point does not affect highlighting: just refresh the
2294 ;; highlighting of old point, if needed.
2295 (when ostart
2296 (font-lock-flush ostart
2297 (overlay-end whitespace-point--used))
2298 (delete-overlay whitespace-point--used)))
2299 ((not ostart)
2300 ;; Old point did not affect highlighting, but new one does: refresh the
2301 ;; highlighting of new point.
2302 (font-lock-flush (min refontify (point)) (max refontify (point))))
2303 ((save-excursion
2304 (goto-char ostart)
2305 (setq ostart (line-beginning-position))
2306 (and (<= ostart (max refontify (point)))
2307 (progn
2308 (goto-char (overlay-end whitespace-point--used))
2309 (let ((oend (line-beginning-position 2)))
2310 (<= (min refontify (point)) oend)))))
2311 ;; The old point highlighting and the new point highlighting
2312 ;; cover a contiguous region: do a single refresh.
2313 (font-lock-flush (min refontify (point) ostart)
2314 (max refontify (point)
2315 (overlay-end whitespace-point--used)))
2316 (delete-overlay whitespace-point--used))
2318 (font-lock-flush (min refontify (point))
2319 (max refontify (point)))
2320 (font-lock-flush ostart (overlay-end whitespace-point--used))
2321 (delete-overlay whitespace-point--used))))))
2324 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2325 ;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
2328 (defun whitespace-style-mark-p ()
2329 "Return t if there is some visualization via display table."
2330 (or (memq 'tab-mark whitespace-active-style)
2331 (memq 'space-mark whitespace-active-style)
2332 (memq 'newline-mark whitespace-active-style)))
2335 (defsubst whitespace-char-valid-p (char)
2336 ;; This check should be improved!!!
2337 (or (< char 256)
2338 (characterp char)))
2341 (defun whitespace-display-vector-p (vec)
2342 "Return true if every character in vector VEC can be displayed."
2343 (let ((i (length vec)))
2344 (when (> i 0)
2345 (while (and (>= (setq i (1- i)) 0)
2346 (whitespace-char-valid-p (aref vec i))))
2347 (< i 0))))
2350 (defun whitespace-display-char-on ()
2351 "Turn on character display mapping."
2352 (when (and whitespace-display-mappings
2353 (whitespace-style-mark-p))
2354 (let (vecs vec)
2355 ;; Remember whether a buffer has a local display table.
2356 (unless whitespace-display-table-was-local
2357 (setq whitespace-display-table-was-local t)
2358 (unless (or whitespace-mode global-whitespace-mode)
2359 (setq whitespace-display-table
2360 (copy-sequence buffer-display-table)))
2361 ;; Assure `buffer-display-table' is unique
2362 ;; when two or more windows are visible.
2363 (setq buffer-display-table
2364 (copy-sequence buffer-display-table)))
2365 (unless buffer-display-table
2366 (setq buffer-display-table (make-display-table)))
2367 (dolist (entry whitespace-display-mappings)
2368 ;; check if it is to display this mark
2369 (when (memq (car entry) whitespace-style)
2370 ;; Get a displayable mapping.
2371 (setq vecs (cddr entry))
2372 (while (and vecs
2373 (not (whitespace-display-vector-p (car vecs))))
2374 (setq vecs (cdr vecs)))
2375 ;; Display a valid mapping.
2376 (when vecs
2377 (setq vec (copy-sequence (car vecs)))
2378 ;; NEWLINE char
2379 (when (and (eq (cadr entry) ?\n)
2380 (memq 'newline whitespace-active-style))
2381 ;; Only insert face bits on NEWLINE char mapping to avoid
2382 ;; obstruction of other faces like TABs and (HARD) SPACEs
2383 ;; faces, font-lock faces, etc.
2384 (dotimes (i (length vec))
2385 (or (eq (aref vec i) ?\n)
2386 (aset vec i
2387 (make-glyph-code (aref vec i)
2388 whitespace-newline)))))
2389 ;; Display mapping
2390 (aset buffer-display-table (cadr entry) vec)))))))
2393 (defun whitespace-display-char-off ()
2394 "Turn off character display mapping."
2395 (and whitespace-display-mappings
2396 (whitespace-style-mark-p)
2397 whitespace-display-table-was-local
2398 (setq whitespace-display-table-was-local nil
2399 buffer-display-table whitespace-display-table)))
2402 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2403 ;;;; Hook
2406 (defun whitespace-action-when-on ()
2407 "Action to be taken always when local whitespace is turned on."
2408 (cond ((memq 'cleanup whitespace-action)
2409 (whitespace-cleanup))
2410 ((memq 'report-on-bogus whitespace-action)
2411 (whitespace-report nil t))))
2414 (defun whitespace-write-file-hook ()
2415 "Action to be taken when buffer is written.
2416 It should be added buffer-locally to `write-file-functions'."
2417 (cond ((memq 'auto-cleanup whitespace-action)
2418 (whitespace-cleanup))
2419 ((memq 'abort-on-bogus whitespace-action)
2420 (when (whitespace-report nil t)
2421 (error "Abort write due to whitespace problems in %s"
2422 (buffer-name)))))
2423 nil) ; continue hook processing
2426 (defun whitespace-warn-read-only (msg)
2427 "Warn if buffer is read-only."
2428 (when (memq 'warn-if-read-only whitespace-action)
2429 (message "Can't %s: %s is read-only" msg (buffer-name))))
2432 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2435 (defun whitespace-unload-function ()
2436 "Unload the whitespace library."
2437 (global-whitespace-mode -1)
2438 ;; be sure all local whitespace mode is turned off
2439 (save-current-buffer
2440 (dolist (buf (buffer-list))
2441 (set-buffer buf)
2442 (whitespace-mode -1)))
2443 nil) ; continue standard unloading
2446 (provide 'whitespace)
2449 (run-hooks 'whitespace-load-hook)
2452 ;;; whitespace.el ends here