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