comparison lisp/whitespace.el @ 88097:1662791e8fd8

Rename blank-mode.el to whitespace.el and obsolete/whitespace.el to obsolete/old-whitespace.el
author Vinicius Jose Latorre <viniciusjl@ig.com.br>
date Thu, 31 Jan 2008 16:08:29 +0000
parents
children f28a6a84ac3e
comparison
equal deleted inserted replaced
88096:41c3a568ba86 88097:1662791e8fd8
1 ;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE
2
3 ;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
8 ;; Keywords: data, wp
9 ;; Version: 9.2
10 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
11
12 ;; This file is part of GNU Emacs.
13
14 ;; GNU Emacs is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published
16 ;; by the Free Software Foundation; either version 3, or (at your
17 ;; option) any later version.
18
19 ;; GNU Emacs is distributed in the hope that it will be useful, but
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 ;; General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 ;; Boston, MA 02110-1301, USA.
28
29 ;;; Commentary:
30
31 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;;
33 ;; Introduction
34 ;; ------------
35 ;;
36 ;; This package is a minor mode to visualize blanks (TAB, (HARD) SPACE
37 ;; and NEWLINE).
38 ;;
39 ;; whitespace uses two ways to visualize blanks: faces and display
40 ;; table.
41 ;;
42 ;; * Faces are used to highlight the background with a color.
43 ;; whitespace uses font-lock to highlight blank characters.
44 ;;
45 ;; * Display table changes the way a character is displayed, that is,
46 ;; it provides a visual mark for characters, for example, at the end
47 ;; of line (?\xB6), at SPACEs (?\xB7) and at TABs (?\xBB).
48 ;;
49 ;; The `whitespace-style' and `whitespace-chars' variables are used to
50 ;; select which way should be used to visualize blanks.
51 ;;
52 ;; Note that when whitespace is turned on, whitespace saves the
53 ;; font-lock state, that is, if font-lock is on or off. And
54 ;; whitespace restores the font-lock state when it is turned off. So,
55 ;; if whitespace is turned on and font-lock is off, whitespace also
56 ;; turns on the font-lock to highlight blanks, but the font-lock will
57 ;; be turned off when whitespace is turned off. Thus, turn on
58 ;; font-lock before whitespace is on, if you want that font-lock
59 ;; continues on after whitespace is turned off.
60 ;;
61 ;; When whitespace is on, it takes care of highlighting some special
62 ;; characters over the default mechanism of `nobreak-char-display'
63 ;; (which see) and `show-trailing-whitespace' (which see).
64 ;;
65 ;; There are two ways of using whitespace: local and global.
66 ;;
67 ;; * Local whitespace affects only the current buffer.
68 ;;
69 ;; * Global whitespace affects all current and future buffers. That
70 ;; is, if you turn on global whitespace and then create a new
71 ;; buffer, the new buffer will also have whitespace on. The
72 ;; `whitespace-global-modes' variable controls which major-mode will
73 ;; be automagically turned on.
74 ;;
75 ;; You can mix the local and global usage without any conflict. But
76 ;; local whitespace has priority over global whitespace. Whitespace
77 ;; mode is active in a buffer if you have enabled it in that buffer or
78 ;; if you have enabled it globally.
79 ;;
80 ;; When global and local whitespace are on:
81 ;;
82 ;; * if local whitespace is turned off, whitespace is turned off for
83 ;; the current buffer only.
84 ;;
85 ;; * if global whitespace is turned off, whitespace continues on only
86 ;; in the buffers in which local whitespace is on.
87 ;;
88 ;; To use whitespace, insert in your ~/.emacs:
89 ;;
90 ;; (require 'whitespace-mode)
91 ;;
92 ;; Or autoload at least one of the commands`whitespace-mode',
93 ;; `whitespace-toggle-options', `global-whitespace-mode' or
94 ;; `global-whitespace-toggle-options'. For example:
95 ;;
96 ;; (autoload 'whitespace-mode "whitespace"
97 ;; "Toggle whitespace visualization." t)
98 ;; (autoload 'whitespace-toggle-options "whitespace"
99 ;; "Toggle local `whitespace-mode' options." t)
100 ;;
101 ;; whitespace was inspired by:
102 ;;
103 ;; whitespace.el Rajesh Vaidheeswarran <rv@gnu.org>
104 ;; Warn about and clean bogus whitespaces in the file
105 ;; (inspired the idea to warn and clean some blanks)
106 ;; This was the original `whitespace.el' which was replaced by
107 ;; `blank-mode.el'. And later `blank-mode.el' was renamed to
108 ;; `whitespace.el'.
109 ;;
110 ;; show-whitespace-mode.el Aurelien Tisne <aurelien.tisne@free.fr>
111 ;; Simple mode to highlight whitespaces
112 ;; (inspired the idea to use font-lock)
113 ;;
114 ;; whitespace-mode.el Lawrence Mitchell <wence@gmx.li>
115 ;; Major mode for editing Whitespace
116 ;; (inspired the idea to use display table)
117 ;;
118 ;; visws.el Miles Bader <miles@gnu.org>
119 ;; Make whitespace visible
120 ;; (handle display table, his code was modified, but the main
121 ;; idea was kept)
122 ;;
123 ;;
124 ;; Using whitespace
125 ;; ----------------
126 ;;
127 ;; There is no problem if you mix local and global minor mode usage.
128 ;;
129 ;; * LOCAL whitespace:
130 ;; + To toggle whitespace options locally, type:
131 ;;
132 ;; M-x whitespace-toggle-options RET
133 ;;
134 ;; + To activate whitespace locally, type:
135 ;;
136 ;; C-u 1 M-x whitespace-mode RET
137 ;;
138 ;; + To deactivate whitespace locally, type:
139 ;;
140 ;; C-u 0 M-x whitespace-mode RET
141 ;;
142 ;; + To toggle whitespace locally, type:
143 ;;
144 ;; M-x whitespace-mode RET
145 ;;
146 ;; * GLOBAL whitespace:
147 ;; + To toggle whitespace options globally, type:
148 ;;
149 ;; M-x global-whitespace-toggle-options RET
150 ;;
151 ;; + To activate whitespace globally, type:
152 ;;
153 ;; C-u 1 M-x global-whitespace-mode RET
154 ;;
155 ;; + To deactivate whitespace globally, type:
156 ;;
157 ;; C-u 0 M-x global-whitespace-mode RET
158 ;;
159 ;; + To toggle whitespace globally, type:
160 ;;
161 ;; M-x global-whitespace-mode RET
162 ;;
163 ;; There are also the following useful commands:
164 ;;
165 ;; `whitespace-cleanup'
166 ;; Cleanup some blank problems in all buffer or at region.
167 ;;
168 ;; `whitespace-cleanup-region'
169 ;; Cleanup some blank problems at region.
170 ;;
171 ;; `whitespace-buffer'
172 ;; Turn on `whitespace-mode' forcing some settings.
173 ;;
174 ;; The problems, which are cleaned up, are:
175 ;;
176 ;; 1. empty lines at beginning of buffer.
177 ;; 2. empty lines at end of buffer.
178 ;; If `whitespace-chars' has `empty' as an element, remove all
179 ;; empty lines at beginning and/or end of buffer.
180 ;;
181 ;; 3. 8 or more SPACEs at beginning of line.
182 ;; If `whitespace-chars' has `indentation' as an element, replace 8
183 ;; or more SPACEs at beginning of line by TABs.
184 ;;
185 ;; 4. SPACEs before TAB.
186 ;; If `whitespace-chars' has `space-before-tab' as an element,
187 ;; replace SPACEs by TABs.
188 ;;
189 ;; 5. SPACEs or TABs at end of line.
190 ;; If `whitespace-chars' has `trailing' as an element, remove all
191 ;; SPACEs or TABs at end of line."
192 ;;
193 ;; 6. 8 or more SPACEs after TAB.
194 ;; If `whitespace-chars' has `space-after-tab' as an element,
195 ;; replace SPACEs by TABs.
196 ;;
197 ;;
198 ;; Hooks
199 ;; -----
200 ;;
201 ;; whitespace has the following hook variables:
202 ;;
203 ;; `whitespace-mode-hook'
204 ;; It is evaluated always when whitespace is turned on locally.
205 ;;
206 ;; `global-whitespace-mode-hook'
207 ;; It is evaluated always when whitespace is turned on globally.
208 ;;
209 ;; `whitespace-load-hook'
210 ;; It is evaluated after whitespace package is loaded.
211 ;;
212 ;;
213 ;; Options
214 ;; -------
215 ;;
216 ;; Below it's shown a brief description of whitespace options, please,
217 ;; see the options declaration in the code for a long documentation.
218 ;;
219 ;; `whitespace-style' Specify the visualization style.
220 ;;
221 ;; `whitespace-chars' Specify which kind of blank is
222 ;; visualized.
223 ;;
224 ;; `whitespace-space' Face used to visualize SPACE.
225 ;;
226 ;; `whitespace-hspace' Face used to visualize HARD SPACE.
227 ;;
228 ;; `whitespace-tab' Face used to visualize TAB.
229 ;;
230 ;; `whitespace-newline' Face used to visualize NEWLINE char
231 ;; mapping.
232 ;;
233 ;; `whitespace-trailing' Face used to visualize trailing
234 ;; blanks.
235 ;;
236 ;; `whitespace-line' Face used to visualize "long" lines.
237 ;;
238 ;; `whitespace-space-before-tab' Face used to visualize SPACEs
239 ;; before TAB.
240 ;;
241 ;; `whitespace-indentation' Face used to visualize 8 or more
242 ;; SPACEs at beginning of line.
243 ;;
244 ;; `whitespace-empty' Face used to visualize empty lines at
245 ;; beginning and/or end of buffer.
246 ;;
247 ;; `whitespace-space-after-tab' Face used to visualize 8 or more
248 ;; SPACEs after TAB.
249 ;;
250 ;; `whitespace-space-regexp' Specify SPACE characters regexp.
251 ;;
252 ;; `whitespace-hspace-regexp' Specify HARD SPACE characters regexp.
253 ;;
254 ;; `whitespace-tab-regexp' Specify TAB characters regexp.
255 ;;
256 ;; `whitespace-trailing-regexp' Specify trailing characters regexp.
257 ;;
258 ;; `whitespace-space-before-tab-regexp' Specify SPACEs before TAB
259 ;; regexp.
260 ;;
261 ;; `whitespace-indentation-regexp' Specify regexp for 8 or more
262 ;; SPACEs at beginning of line.
263 ;;
264 ;; `whitespace-empty-at-bob-regexp' Specify regexp for empty lines
265 ;; at beginning of buffer.
266 ;;
267 ;; `whitespace-empty-at-eob-regexp' Specify regexp for empty lines
268 ;; at end of buffer.
269 ;;
270 ;; `whitespace-space-after-tab-regexp' Specify regexp for 8 or more
271 ;; SPACEs after TAB.
272 ;;
273 ;; `whitespace-line-column' Specify column beyond which the line
274 ;; is highlighted.
275 ;;
276 ;; `whitespace-display-mappings' Specify an alist of mappings
277 ;; for displaying characters.
278 ;;
279 ;; `whitespace-global-modes' Modes for which global `whitespace-mode' is
280 ;; automagically turned on.
281 ;;
282 ;;
283 ;; Acknowledgements
284 ;; ----------------
285 ;;
286 ;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
287 ;; lines tail. See EightyColumnRule (EmacsWiki).
288 ;;
289 ;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
290 ;; * `define-minor-mode'.
291 ;; * `global-whitespace-*' name for global commands.
292 ;;
293 ;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
294 ;;
295 ;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
296 ;; suggestion.
297 ;;
298 ;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
299 ;; helping to fix `find-file-hooks' reference.
300 ;;
301 ;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
302 ;; indicating defface byte-compilation warnings.
303 ;;
304 ;; Thanks to TimOCallaghan (EmacsWiki) for the idea about highlight
305 ;; "long" lines. See EightyColumnRule (EmacsWiki).
306 ;;
307 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
308 ;; newline character mapping.
309 ;;
310 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
311 ;; whitespace-mode.el on XEmacs.
312 ;;
313 ;; Thanks to Miles Bader <miles@gnu.org> for handling display table via
314 ;; visws.el (his code was modified, but the main idea was kept).
315 ;;
316 ;; Thanks to:
317 ;; Rajesh Vaidheeswarran <rv@gnu.org> (original) whitespace.el
318 ;; Aurelien Tisne <aurelien.tisne@free.fr> show-whitespace-mode.el
319 ;; Lawrence Mitchell <wence@gmx.li> whitespace-mode.el
320 ;; Miles Bader <miles@gnu.org> visws.el
321 ;; And to all people who contributed with them.
322 ;;
323 ;;
324 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
325
326 ;;; code:
327
328
329 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
330 ;;;; User Variables:
331
332
333 ;;; Interface to the command system
334
335
336 (defgroup whitespace nil
337 "Visualize blanks (TAB, (HARD) SPACE and NEWLINE)."
338 :link '(emacs-library-link :tag "Source Lisp File" "whitespace.el")
339 :version "22.2"
340 :group 'wp
341 :group 'data)
342
343
344 (defcustom whitespace-style '(mark color)
345 "*Specify the visualization style.
346
347 It's a list which element value can be:
348
349 mark display mappings are visualized.
350
351 color faces are visualized.
352
353 Any other value is ignored.
354
355 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs.
356
357 See also `whitespace-display-mappings' for documentation."
358 :type '(repeat :tag "Style of Blank"
359 (choice :tag "Style of Blank"
360 (const :tag "Display Table" mark)
361 (const :tag "Faces" color)))
362 :group 'whitespace)
363
364
365 (defcustom whitespace-chars
366 '(tabs spaces trailing lines space-before-tab newline
367 indentation empty space-after-tab)
368 "*Specify which kind of blank is visualized.
369
370 It's a list which element value can be:
371
372 trailing trailing blanks are visualized.
373
374 tabs TABs are visualized.
375
376 spaces SPACEs and HARD SPACEs are visualized.
377
378 lines lines whose have columns beyond
379 `whitespace-line-column' are highlighted.
380 Whole line is highlighted.
381 It has precedence over
382 `lines-tail' (see below).
383
384 lines-tail lines whose have columns beyond
385 `whitespace-line-column' are highlighted.
386 But only the part of line which goes
387 beyond `whitespace-line-column' column.
388 It has effect only if `lines' (see above)
389 is not present in `whitespace-chars'.
390
391 space-before-tab SPACEs before TAB are visualized.
392
393 newline NEWLINEs are visualized.
394
395 indentation 8 or more SPACEs at beginning of line are
396 visualized.
397
398 empty empty lines at beginning and/or end of buffer
399 are visualized.
400
401 space-after-tab 8 or more SPACEs after a TAB are visualized.
402
403 Any other value is ignored.
404
405 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs.
406
407 Used when `whitespace-style' has `color' as an element.
408 Used also when `whitespace-chars' has `newline' as an element and
409 `whitespace-style' has `mark' as an element."
410 :type '(repeat :tag "Kind of Blank"
411 (choice :tag "Kind of Blank"
412 (const :tag "Trailing TABs, SPACEs and HARD SPACEs"
413 trailing)
414 (const :tag "SPACEs and HARD SPACEs" spaces)
415 (const :tag "TABs" tabs)
416 (const :tag "Lines" lines)
417 (const :tag "SPACEs before TAB"
418 space-before-tab)
419 (const :tag "NEWLINEs" newline)
420 (const :tag "Indentation SPACEs" indentation)
421 (const :tag "Empty Lines At BOB And/Or EOB"
422 empty)
423 (const :tag "SPACEs after TAB"
424 space-after-tab)))
425 :group 'whitespace)
426
427
428 (defcustom whitespace-space 'whitespace-space
429 "*Symbol face used to visualize SPACE.
430
431 Used when `whitespace-style' has `color' as an element."
432 :type 'face
433 :group 'whitespace)
434
435
436 (defface whitespace-space
437 '((((class color) (background dark))
438 (:background "grey20" :foreground "aquamarine3"))
439 (((class color) (background light))
440 (:background "LightYellow" :foreground "aquamarine3"))
441 (t (:inverse-video t)))
442 "Face used to visualize SPACE."
443 :group 'whitespace)
444
445
446 (defcustom whitespace-hspace 'whitespace-hspace
447 "*Symbol face used to visualize HARD SPACE.
448
449 Used when `whitespace-style' has `color' as an element."
450 :type 'face
451 :group 'whitespace)
452
453
454 (defface whitespace-hspace ; 'nobreak-space
455 '((((class color) (background dark))
456 (:background "grey24" :foreground "aquamarine3"))
457 (((class color) (background light))
458 (:background "LemonChiffon3" :foreground "aquamarine3"))
459 (t (:inverse-video t)))
460 "Face used to visualize HARD SPACE."
461 :group 'whitespace)
462
463
464 (defcustom whitespace-tab 'whitespace-tab
465 "*Symbol face used to visualize TAB.
466
467 Used when `whitespace-style' has `color' as an element."
468 :type 'face
469 :group 'whitespace)
470
471
472 (defface whitespace-tab
473 '((((class color) (background dark))
474 (:background "grey22" :foreground "aquamarine3"))
475 (((class color) (background light))
476 (:background "beige" :foreground "aquamarine3"))
477 (t (:inverse-video t)))
478 "Face used to visualize TAB."
479 :group 'whitespace)
480
481
482 (defcustom whitespace-newline 'whitespace-newline
483 "*Symbol face used to visualize NEWLINE char mapping.
484
485 See `whitespace-display-mappings'.
486
487 Used when `whitespace-style' has `mark' and `color' as elements
488 and `whitespace-chars' has `newline' as an element."
489 :type 'face
490 :group 'whitespace)
491
492
493 (defface whitespace-newline
494 '((((class color) (background dark))
495 (:background "grey26" :foreground "aquamarine3" :bold t))
496 (((class color) (background light))
497 (:background "linen" :foreground "aquamarine3" :bold t))
498 (t (:bold t :underline t)))
499 "Face used to visualize NEWLINE char mapping.
500
501 See `whitespace-display-mappings'."
502 :group 'whitespace)
503
504
505 (defcustom whitespace-trailing 'whitespace-trailing
506 "*Symbol face used to visualize traling blanks.
507
508 Used when `whitespace-style' has `color' as an element."
509 :type 'face
510 :group 'whitespace)
511
512
513 (defface whitespace-trailing ; 'trailing-whitespace
514 '((((class mono)) (:inverse-video t :bold t :underline t))
515 (t (:background "red1" :foreground "yellow" :bold t)))
516 "Face used to visualize trailing blanks."
517 :group 'whitespace)
518
519
520 (defcustom whitespace-line 'whitespace-line
521 "*Symbol face used to visualize \"long\" lines.
522
523 See `whitespace-line-column'.
524
525 Used when `whitespace-style' has `color' as an element."
526 :type 'face
527 :group 'whitespace)
528
529
530 (defface whitespace-line
531 '((((class mono)) (:inverse-video t :bold t :underline t))
532 (t (:background "gray20" :foreground "violet")))
533 "Face used to visualize \"long\" lines.
534
535 See `whitespace-line-column'."
536 :group 'whitespace)
537
538
539 (defcustom whitespace-space-before-tab 'whitespace-space-before-tab
540 "*Symbol face used to visualize SPACEs before TAB.
541
542 Used when `whitespace-style' has `color' as an element."
543 :type 'face
544 :group 'whitespace)
545
546
547 (defface whitespace-space-before-tab
548 '((((class mono)) (:inverse-video t :bold t :underline t))
549 (t (:background "DarkOrange" :foreground "firebrick")))
550 "Face used to visualize SPACEs before TAB."
551 :group 'whitespace)
552
553
554 (defcustom whitespace-indentation 'whitespace-indentation
555 "*Symbol face used to visualize 8 or more SPACEs at beginning of line.
556
557 Used when `whitespace-style' has `color' as an element."
558 :type 'face
559 :group 'whitespace)
560
561
562 (defface whitespace-indentation
563 '((((class mono)) (:inverse-video t :bold t :underline t))
564 (t (:background "yellow" :foreground "firebrick")))
565 "Face used to visualize 8 or more SPACEs at beginning of line."
566 :group 'whitespace)
567
568
569 (defcustom whitespace-empty 'whitespace-empty
570 "*Symbol face used to visualize empty lines at beginning and/or end of buffer.
571
572 Used when `whitespace-style' has `color' as an element."
573 :type 'face
574 :group 'whitespace)
575
576
577 (defface whitespace-empty
578 '((((class mono)) (:inverse-video t :bold t :underline t))
579 (t (:background "yellow" :foreground "firebrick")))
580 "Face used to visualize empty lines at beginning and/or end of buffer."
581 :group 'whitespace)
582
583
584 (defcustom whitespace-space-after-tab 'whitespace-space-after-tab
585 "*Symbol face used to visualize 8 or more SPACEs after TAB.
586
587 Used when `whitespace-style' has `color' as an element."
588 :type 'face
589 :group 'whitespace)
590
591
592 (defface whitespace-space-after-tab
593 '((((class mono)) (:inverse-video t :bold t :underline t))
594 (t (:background "yellow" :foreground "firebrick")))
595 "Face used to visualize 8 or more SPACEs after TAB."
596 :group 'whitespace)
597
598
599 (defcustom whitespace-hspace-regexp
600 "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
601 "*Specify HARD SPACE characters regexp.
602
603 If you're using `mule' package, it may exist other characters besides:
604
605 \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \"\\xF20\"
606
607 that should be considered HARD SPACE.
608
609 Here are some examples:
610
611 \"\\\\(^\\xA0+\\\\)\" \
612 visualize only leading HARD SPACEs.
613 \"\\\\(\\xA0+$\\\\)\" \
614 visualize only trailing HARD SPACEs.
615 \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\" \
616 visualize leading and/or trailing HARD SPACEs.
617 \"\\t\\\\(\\xA0+\\\\)\\t\" \
618 visualize only HARD SPACEs between TABs.
619
620 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
621 Use exactly one pair of enclosing \\\\( and \\\\).
622
623 Used when `whitespace-style' has `color' as an element, and
624 `whitespace-chars' has `spaces' as an element."
625 :type '(regexp :tag "HARD SPACE Chars")
626 :group 'whitespace)
627
628
629 (defcustom whitespace-space-regexp "\\( +\\)"
630 "*Specify SPACE characters regexp.
631
632 If you're using `mule' package, it may exist other characters
633 besides \" \" that should be considered SPACE.
634
635 Here are some examples:
636
637 \"\\\\(^ +\\\\)\" visualize only leading SPACEs.
638 \"\\\\( +$\\\\)\" visualize only trailing SPACEs.
639 \"\\\\(^ +\\\\| +$\\\\)\" \
640 visualize leading and/or trailing SPACEs.
641 \"\\t\\\\( +\\\\)\\t\" visualize only SPACEs between TABs.
642
643 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
644 Use exactly one pair of enclosing \\\\( and \\\\).
645
646 Used when `whitespace-style' has `color' as an element, and
647 `whitespace-chars' has `spaces' as an element."
648 :type '(regexp :tag "SPACE Chars")
649 :group 'whitespace)
650
651
652 (defcustom whitespace-tab-regexp "\\(\t+\\)"
653 "*Specify TAB characters regexp.
654
655 If you're using `mule' package, it may exist other characters
656 besides \"\\t\" that should be considered TAB.
657
658 Here are some examples:
659
660 \"\\\\(^\\t+\\\\)\" visualize only leading TABs.
661 \"\\\\(\\t+$\\\\)\" visualize only trailing TABs.
662 \"\\\\(^\\t+\\\\|\\t+$\\\\)\" \
663 visualize leading and/or trailing TABs.
664 \" \\\\(\\t+\\\\) \" visualize only TABs between SPACEs.
665
666 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
667 Use exactly one pair of enclosing \\\\( and \\\\).
668
669 Used when `whitespace-style' has `color' as an element, and
670 `whitespace-chars' has `tabs' as an element."
671 :type '(regexp :tag "TAB Chars")
672 :group 'whitespace)
673
674
675 (defcustom whitespace-trailing-regexp
676 "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
677 "*Specify trailing characters regexp.
678
679 If you're using `mule' package, it may exist other characters besides:
680
681 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
682 \"\\xF20\"
683
684 that should be considered blank.
685
686 NOTE: DO NOT enclose by \\\\( and \\\\) the elements to highlight.
687 `whitespace-mode' surrounds this regexp by \"\\\\(\\\\(\" and
688 \"\\\\)+\\\\)$\".
689
690 Used when `whitespace-style' has `color' as an element, and
691 `whitespace-chars' has `trailing' as an element."
692 :type '(regexp :tag "Trailing Chars")
693 :group 'whitespace)
694
695
696 (defcustom whitespace-space-before-tab-regexp "\\( +\\)\t"
697 "*Specify SPACEs before TAB regexp.
698
699 If you're using `mule' package, it may exist other characters besides:
700
701 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
702 \"\\xF20\"
703
704 that should be considered blank.
705
706 Used when `whitespace-style' has `color' as an element, and
707 `whitespace-chars' has `space-before-tab' as an element."
708 :type '(regexp :tag "SPACEs Before TAB")
709 :group 'whitespace)
710
711
712 (defcustom whitespace-indentation-regexp
713 "^\t*\\(\\( \\{8\\}\\)+\\)[^\n\t]"
714 "*Specify regexp for 8 or more SPACEs at beginning of line.
715
716 If you're using `mule' package, it may exist other characters besides:
717
718 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
719 \"\\xF20\"
720
721 that should be considered blank.
722
723 Used when `whitespace-style' has `color' as an element, and
724 `whitespace-chars' has `indentation' as an element."
725 :type '(regexp :tag "Indentation SPACEs")
726 :group 'whitespace)
727
728
729 (defcustom whitespace-empty-at-bob-regexp "\\`\\(\\([ \t]*\n\\)+\\)"
730 "*Specify regexp for empty lines at beginning of buffer.
731
732 If you're using `mule' package, it may exist other characters besides:
733
734 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
735 \"\\xF20\"
736
737 that should be considered blank.
738
739 Used when `whitespace-style' has `color' as an element, and
740 `whitespace-chars' has `empty' as an element."
741 :type '(regexp :tag "Empty Lines At Beginning Of Buffer")
742 :group 'whitespace)
743
744
745 (defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)\\'"
746 "*Specify regexp for empty lines at end of buffer.
747
748 If you're using `mule' package, it may exist other characters besides:
749
750 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
751 \"\\xF20\"
752
753 that should be considered blank.
754
755 Used when `whitespace-style' has `color' as an element, and
756 `whitespace-chars' has `empty' as an element."
757 :type '(regexp :tag "Empty Lines At End Of Buffer")
758 :group 'whitespace)
759
760
761 (defcustom whitespace-space-after-tab-regexp "\t\\(\\( \\{8\\}\\)+\\)"
762 "*Specify regexp for 8 or more SPACEs after TAB.
763
764 If you're using `mule' package, it may exist other characters besides:
765
766 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
767 \"\\xF20\"
768
769 that should be considered blank.
770
771 Used when `whitespace-style' has `color' as an element, and
772 `whitespace-chars' has `space-after-tab' as an element."
773 :type '(regexp :tag "SPACEs After TAB")
774 :group 'whitespace)
775
776
777 (defcustom whitespace-line-column 80
778 "*Specify column beyond which the line is highlighted.
779
780 Used when `whitespace-style' has `color' as an element, and
781 `whitespace-chars' has `lines' or `lines-tail' as an element."
782 :type '(integer :tag "Line Length")
783 :group 'whitespace)
784
785
786 ;; Hacked from `visible-whitespace-mappings' in visws.el
787 (defcustom whitespace-display-mappings
788 ;; Due to limitations of glyph representation, the char code can not
789 ;; be above ?\x1FFFF. Probably, this will be fixed after Emacs
790 ;; unicode merging.
791 '(
792 (?\ [?\xB7] [?.]) ; space - centered dot
793 (?\xA0 [?\xA4] [?_]) ; hard space - currency
794 (?\x8A0 [?\x8A4] [?_]) ; hard space - currency
795 (?\x920 [?\x924] [?_]) ; hard space - currency
796 (?\xE20 [?\xE24] [?_]) ; hard space - currency
797 (?\xF20 [?\xF24] [?_]) ; hard space - currency
798 ;; NEWLINE is displayed using the face `whitespace-newline'
799 (?\n [?$ ?\n]) ; end-of-line - dollar sign
800 ;; (?\n [?\u21B5 ?\n] [?$ ?\n]) ; end-of-line - downwards arrow
801 ;; (?\n [?\xB6 ?\n] [?$ ?\n]) ; end-of-line - pilcrow
802 ;; (?\n [?\x8AF ?\n] [?$ ?\n]) ; end-of-line - overscore
803 ;; (?\n [?\x8AC ?\n] [?$ ?\n]) ; end-of-line - negation
804 ;; (?\n [?\x8B0 ?\n] [?$ ?\n]) ; end-of-line - grade
805 ;;
806 ;; WARNING: the mapping below has a problem.
807 ;; When a TAB occupies exactly one column, it will display the
808 ;; character ?\xBB at that column followed by a TAB which goes to
809 ;; the next TAB column.
810 ;; If this is a problem for you, please, comment the line below.
811 (?\t [?\xBB ?\t] [?\\ ?\t]) ; tab - left quote mark
812 )
813 "*Specify an alist of mappings for displaying characters.
814
815 Each element has the following form:
816
817 (CHAR VECTOR...)
818
819 Where:
820
821 CHAR is the character to be mapped.
822
823 VECTOR is a vector of characters to be displayed in place of CHAR.
824 The first display vector that can be displayed is used;
825 if no display vector for a mapping can be displayed, then
826 that character is displayed unmodified.
827
828 The NEWLINE character is displayed using the face given by
829 `whitespace-newline' variable. The characters in the vector to
830 be displayed will not have this face applied if the character
831 code is above #x1FFFF.
832
833 Used when `whitespace-style' has `mark' as an element."
834 :type '(repeat
835 (list :tag "Character Mapping"
836 (character :tag "Char")
837 (repeat :inline t :tag "Vector List"
838 (vector :tag ""
839 (repeat :inline t
840 :tag "Vector Characters"
841 (character :tag "Char"))))))
842 :group 'whitespace)
843
844
845 (defcustom whitespace-global-modes t
846 "*Modes for which global `whitespace-mode' is automagically turned on.
847
848 Global `whitespace-mode' is controlled by the command
849 `global-whitespace-mode'.
850
851 If nil, means no modes have `whitespace-mode' automatically
852 turned on.
853
854 If t, all modes that support `whitespace-mode' have it
855 automatically turned on.
856
857 Else it should be a list of `major-mode' symbol names for which
858 `whitespace-mode' should be automatically turned on. The sense
859 of the list is negated if it begins with `not'. For example:
860
861 (c-mode c++-mode)
862
863 means that `whitespace-mode' is turned on for buffers in C and
864 C++ modes only."
865 :type '(choice (const :tag "None" nil)
866 (const :tag "All" t)
867 (set :menu-tag "Mode Specific" :tag "Modes"
868 :value (not)
869 (const :tag "Except" not)
870 (repeat :inline t
871 (symbol :tag "Mode"))))
872 :group 'whitespace)
873
874
875 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
876 ;;;; User commands - Local mode
877
878
879 ;;;###autoload
880 (define-minor-mode whitespace-mode
881 "Toggle whitespace minor mode visualization (\"ws\" on modeline).
882
883 If ARG is null, toggle whitespace visualization.
884 If ARG is a number greater than zero, turn on visualization;
885 otherwise, turn off visualization.
886 Only useful with a windowing system."
887 :lighter " ws"
888 :init-value nil
889 :global nil
890 :group 'whitespace
891 (cond
892 (noninteractive ; running a batch job
893 (setq whitespace-mode nil))
894 (whitespace-mode ; whitespace-mode on
895 (whitespace-turn-on))
896 (t ; whitespace-mode off
897 (whitespace-turn-off))))
898
899
900 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
901 ;;;; User commands - Global mode
902
903
904 (define-minor-mode global-whitespace-mode
905 "Toggle whitespace global minor mode visualization (\"WS\" on modeline).
906
907 If ARG is null, toggle whitespace visualization.
908 If ARG is a number greater than zero, turn on visualization;
909 otherwise, turn off visualization.
910 Only useful with a windowing system."
911 :lighter " BL"
912 :init-value nil
913 :global t
914 :group 'whitespace
915 (cond
916 (noninteractive ; running a batch job
917 (setq global-whitespace-mode nil))
918 (global-whitespace-mode ; global-whitespace-mode on
919 (save-excursion
920 (if (boundp 'find-file-hook)
921 (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled t)
922 (add-hook 'find-file-hooks 'whitespace-turn-on-if-enabled t))
923 (dolist (buffer (buffer-list)) ; adjust all local mode
924 (set-buffer buffer)
925 (unless whitespace-mode
926 (whitespace-turn-on-if-enabled)))))
927 (t ; global-whitespace-mode off
928 (save-excursion
929 (if (boundp 'find-file-hook)
930 (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
931 (remove-hook 'find-file-hooks 'whitespace-turn-on-if-enabled))
932 (dolist (buffer (buffer-list)) ; adjust all local mode
933 (set-buffer buffer)
934 (unless whitespace-mode
935 (whitespace-turn-off)))))))
936
937
938 (defun whitespace-turn-on-if-enabled ()
939 (when (cond
940 ((eq whitespace-global-modes t))
941 ((listp whitespace-global-modes)
942 (if (eq (car-safe whitespace-global-modes) 'not)
943 (not (memq major-mode (cdr whitespace-global-modes)))
944 (memq major-mode whitespace-global-modes)))
945 (t nil))
946 (let (inhibit-quit)
947 ;; Don't turn on whitespace mode if...
948 (or
949 ;; ...we don't have a display (we're running a batch job)
950 noninteractive
951 ;; ...or if the buffer is invisible (name starts with a space)
952 (eq (aref (buffer-name) 0) ?\ )
953 ;; ...or if the buffer is temporary (name starts with *)
954 (and (eq (aref (buffer-name) 0) ?*)
955 ;; except the scratch buffer.
956 (not (string= (buffer-name) "*scratch*")))
957 ;; Otherwise, turn on whitespace mode.
958 (whitespace-turn-on)))))
959
960
961 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
962 ;;;; User commands - Toggle
963
964
965 (defconst whitespace-chars-value-list
966 '(tabs
967 spaces
968 trailing
969 space-before-tab
970 lines
971 lines-tail
972 newline
973 indentation
974 empty
975 space-after-tab
976 )
977 "List of valid `whitespace-chars' values.")
978
979
980 (defconst whitespace-style-value-list
981 '(color
982 mark
983 )
984 "List of valid `whitespace-style' values.")
985
986
987 (defconst whitespace-toggle-option-alist
988 '((?t . tabs)
989 (?s . spaces)
990 (?r . trailing)
991 (?b . space-before-tab)
992 (?l . lines)
993 (?L . lines-tail)
994 (?n . newline)
995 (?i . indentation)
996 (?e . empty)
997 (?a . space-after-tab)
998 (?c . color)
999 (?m . mark)
1000 (?x . whitespace-chars)
1001 (?z . whitespace-style)
1002 )
1003 "Alist of toggle options.
1004
1005 Each element has the form:
1006
1007 (CHAR . SYMBOL)
1008
1009 Where:
1010
1011 CHAR is a char which the user will have to type.
1012
1013 SYMBOL is a valid symbol associated with CHAR.
1014 See `whitespace-chars-value-list' and
1015 `whitespace-style-value-list'.")
1016
1017
1018 (defvar whitespace-active-chars nil
1019 "Used to save locally `whitespace-chars' value.")
1020 (make-variable-buffer-local 'whitespace-active-chars)
1021
1022 (defvar whitespace-active-style nil
1023 "Used to save locally `whitespace-style' value.")
1024 (make-variable-buffer-local 'whitespace-active-style)
1025
1026
1027 ;;;###autoload
1028 (defun whitespace-toggle-options (arg)
1029 "Toggle local `whitespace-mode' options.
1030
1031 If local whitespace-mode is off, toggle the option given by ARG
1032 and turn on local whitespace-mode.
1033
1034 If local whitespace-mode is on, toggle the option given by ARG
1035 and restart local whitespace-mode.
1036
1037 Interactively, it reads one of the following chars:
1038
1039 CHAR MEANING
1040 t toggle TAB visualization
1041 s toggle SPACE and HARD SPACE visualization
1042 r toggle trailing blanks visualization
1043 b toggle SPACEs before TAB visualization
1044 l toggle \"long lines\" visualization
1045 L toggle \"long lines\" tail visualization
1046 n toggle NEWLINE visualization
1047 i toggle indentation SPACEs visualization
1048 e toggle empty line at bob and/or eob visualization
1049 a toggle SPACEs after TAB visualization
1050 c toggle color faces
1051 m toggle visual mark
1052 x restore `whitespace-chars' value
1053 z restore `whitespace-style' value
1054 ? display brief help
1055
1056 Non-interactively, ARG should be a symbol or a list of symbols.
1057 The valid symbols are:
1058
1059 tabs toggle TAB visualization
1060 spaces toggle SPACE and HARD SPACE visualization
1061 trailing toggle trailing blanks visualization
1062 space-before-tab toggle SPACEs before TAB visualization
1063 lines toggle \"long lines\" visualization
1064 lines-tail toggle \"long lines\" tail visualization
1065 newline toggle NEWLINE visualization
1066 indentation toggle indentation SPACEs visualization
1067 empty toggle empty line at bob and/or eob visualization
1068 space-after-tab toggle SPACEs after TAB visualization
1069 color toggle color faces
1070 mark toggle visual mark
1071 whitespace-chars restore `whitespace-chars' value
1072 whitespace-style restore `whitespace-style' value
1073
1074 Only useful with a windowing system."
1075 (interactive (whitespace-interactive-char t))
1076 (let ((whitespace-chars
1077 (whitespace-toggle-list
1078 t arg whitespace-active-chars whitespace-chars
1079 'whitespace-chars whitespace-chars-value-list))
1080 (whitespace-style
1081 (whitespace-toggle-list
1082 t arg whitespace-active-style whitespace-style
1083 'whitespace-style whitespace-style-value-list)))
1084 (whitespace-mode 0)
1085 (whitespace-mode 1)))
1086
1087
1088 (defvar whitespace-toggle-chars nil
1089 "Used to toggle the global `whitespace-chars' value.")
1090 (defvar whitespace-toggle-style nil
1091 "Used to toggle the global `whitespace-style' value.")
1092
1093
1094 ;;;###autoload
1095 (defun global-whitespace-toggle-options (arg)
1096 "Toggle global `whitespace-mode' options.
1097
1098 If global whitespace-mode is off, toggle the option given by ARG
1099 and turn on global whitespace-mode.
1100
1101 If global whitespace-mode is on, toggle the option given by ARG
1102 and restart global whitespace-mode.
1103
1104 Interactively, it reads one of the following chars:
1105
1106 CHAR MEANING
1107 t toggle TAB visualization
1108 s toggle SPACE and HARD SPACE visualization
1109 r toggle trailing blanks visualization
1110 b toggle SPACEs before TAB visualization
1111 l toggle \"long lines\" visualization
1112 L toggle \"long lines\" tail visualization
1113 n toggle NEWLINE visualization
1114 i toggle indentation SPACEs visualization
1115 e toggle empty line at bob and/or eob visualization
1116 a toggle SPACEs after TAB visualization
1117 c toggle color faces
1118 m toggle visual mark
1119 x restore `whitespace-chars' value
1120 z restore `whitespace-style' value
1121 ? display brief help
1122
1123 Non-interactively, ARG should be a symbol or a list of symbols.
1124 The valid symbols are:
1125
1126 tabs toggle TAB visualization
1127 spaces toggle SPACE and HARD SPACE visualization
1128 trailing toggle trailing blanks visualization
1129 space-before-tab toggle SPACEs before TAB visualization
1130 lines toggle \"long lines\" visualization
1131 lines-tail toggle \"long lines\" tail visualization
1132 newline toggle NEWLINE visualization
1133 indentation toggle indentation SPACEs visualization
1134 empty toggle empty line at bob and/or eob visualization
1135 space-after-tab toggle SPACEs after TAB visualization
1136 color toggle color faces
1137 mark toggle visual mark
1138 whitespace-chars restore `whitespace-chars' value
1139 whitespace-style restore `whitespace-style' value
1140
1141 Only useful with a windowing system."
1142 (interactive (whitespace-interactive-char nil))
1143 (let ((whitespace-chars
1144 (whitespace-toggle-list
1145 nil arg whitespace-toggle-chars whitespace-chars
1146 'whitespace-chars whitespace-chars-value-list))
1147 (whitespace-style
1148 (whitespace-toggle-list
1149 nil arg whitespace-toggle-style whitespace-style
1150 'whitespace-style whitespace-style-value-list)))
1151 (setq whitespace-toggle-chars whitespace-chars
1152 whitespace-toggle-style whitespace-style)
1153 (global-whitespace-mode 0)
1154 (global-whitespace-mode 1)))
1155
1156
1157 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1158 ;;;; User commands - Cleanup
1159
1160
1161 ;;;###autoload
1162 (defun whitespace-cleanup ()
1163 "Cleanup some blank problems in all buffer or at region.
1164
1165 It usually applies to the whole buffer, but in transient mark
1166 mode when the mark is active, it applies to the region. It also
1167 applies to the region when it is not in transiente mark mode, the
1168 mark is active and it was pressed `C-u' just before calling
1169 `whitespace-cleanup' interactively.
1170
1171 See also `whitespace-cleanup-region'.
1172
1173 The problems, which are cleaned up, are:
1174
1175 1. empty lines at beginning of buffer.
1176 2. empty lines at end of buffer.
1177 If `whitespace-chars' has `empty' as an element, remove all
1178 empty lines at beginning and/or end of buffer.
1179
1180 3. 8 or more SPACEs at beginning of line.
1181 If `whitespace-chars' has `indentation' as an element, replace
1182 8 or more SPACEs at beginning of line by TABs.
1183
1184 4. SPACEs before TAB.
1185 If `whitespace-chars' has `space-before-tab' as an element,
1186 replace SPACEs by TABs.
1187
1188 5. SPACEs or TABs at end of line.
1189 If `whitespace-chars' has `trailing' as an element, remove all
1190 SPACEs or TABs at end of line.
1191
1192 6. 8 or more SPACEs after TAB.
1193 If `whitespace-chars' has `space-after-tab' as an element,
1194 replace SPACEs by TABs."
1195 (interactive "@*")
1196 (if (and (or transient-mark-mode
1197 current-prefix-arg)
1198 mark-active)
1199 ;; region active
1200 ;; problems 1 and 2 are not handled in region
1201 ;; problem 3: 8 or more SPACEs at bol
1202 ;; problem 4: SPACEs before TAB
1203 ;; problem 5: SPACEs or TABs at eol
1204 ;; problem 6: 8 or more SPACEs after TAB
1205 (whitespace-cleanup-region (region-beginning) (region-end))
1206 ;; whole buffer
1207 (save-excursion
1208 (save-match-data
1209 ;; problem 1: empty lines at bob
1210 ;; problem 2: empty lines at eob
1211 ;; action: remove all empty lines at bob and/or eob
1212 (when (memq 'empty whitespace-chars)
1213 (let (overwrite-mode) ; enforce no overwrite
1214 (goto-char (point-min))
1215 (when (re-search-forward
1216 whitespace-empty-at-bob-regexp nil t)
1217 (delete-region (match-beginning 1) (match-end 1)))
1218 (when (re-search-forward
1219 whitespace-empty-at-eob-regexp nil t)
1220 (delete-region (match-beginning 1) (match-end 1)))))))
1221 ;; problem 3: 8 or more SPACEs at bol
1222 ;; problem 4: SPACEs before TAB
1223 ;; problem 5: SPACEs or TABs at eol
1224 ;; problem 6: 8 or more SPACEs after TAB
1225 (whitespace-cleanup-region (point-min) (point-max))))
1226
1227
1228 ;;;###autoload
1229 (defun whitespace-cleanup-region (start end)
1230 "Cleanup some blank problems at region.
1231
1232 The problems, which are cleaned up, are:
1233
1234 1. 8 or more SPACEs at beginning of line.
1235 If `whitespace-chars' has `indentation' as an element, replace
1236 8 or more SPACEs at beginning of line by TABs.
1237
1238 2. SPACEs before TAB.
1239 If `whitespace-chars' has `space-before-tab' as an element,
1240 replace SPACEs by TABs.
1241
1242 3. SPACEs or TABs at end of line.
1243 If `whitespace-chars' has `trailing' as an element, remove all
1244 SPACEs or TABs at end of line.
1245
1246 4. 8 or more SPACEs after TAB.
1247 If `whitespace-chars' has `space-after-tab' as an element,
1248 replace SPACEs by TABs."
1249 (interactive "@*r")
1250 (let ((rstart (min start end))
1251 (rend (copy-marker (max start end)))
1252 (tab-width 8) ; assure TAB width
1253 (indent-tabs-mode t) ; always insert TABs
1254 overwrite-mode ; enforce no overwrite
1255 tmp)
1256 (save-excursion
1257 (save-match-data
1258 ;; problem 1: 8 or more SPACEs at bol
1259 ;; action: replace 8 or more SPACEs at bol by TABs
1260 (when (memq 'indentation whitespace-chars)
1261 (goto-char rstart)
1262 (while (re-search-forward
1263 whitespace-indentation-regexp rend t)
1264 (setq tmp (current-indentation))
1265 (delete-horizontal-space)
1266 (unless (eolp)
1267 (indent-to tmp))))
1268 ;; problem 3: SPACEs or TABs at eol
1269 ;; action: remove all SPACEs or TABs at eol
1270 (when (memq 'trailing whitespace-chars)
1271 (let ((regexp (concat "\\(\\(" whitespace-trailing-regexp
1272 "\\)+\\)$")))
1273 (goto-char rstart)
1274 (while (re-search-forward regexp rend t)
1275 (delete-region (match-beginning 1) (match-end 1)))))
1276 ;; problem 4: 8 or more SPACEs after TAB
1277 ;; action: replace 8 or more SPACEs by TABs
1278 (when (memq 'space-after-tab whitespace-chars)
1279 (whitespace-replace-spaces-by-tabs
1280 rstart rend whitespace-space-after-tab-regexp))
1281 ;; problem 2: SPACEs before TAB
1282 ;; action: replace SPACEs before TAB by TABs
1283 (when (memq 'space-before-tab whitespace-chars)
1284 (whitespace-replace-spaces-by-tabs
1285 rstart rend whitespace-space-before-tab-regexp))))
1286 (set-marker rend nil))) ; point marker to nowhere
1287
1288
1289 (defun whitespace-replace-spaces-by-tabs (rstart rend regexp)
1290 "Replace all SPACEs by TABs matched by REGEXP between RSTART and REND."
1291 (goto-char rstart)
1292 (while (re-search-forward regexp rend t)
1293 (goto-char (match-beginning 1))
1294 (let* ((scol (current-column))
1295 (ecol (save-excursion
1296 (goto-char (match-end 1))
1297 (current-column))))
1298 (delete-region (match-beginning 1) (match-end 1))
1299 (insert-char ?\t
1300 (/ (- (- ecol (% ecol 8)) ; prev end col
1301 (- scol (% scol 8))) ; prev start col
1302 8)))))
1303
1304
1305 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1306 ;;;; User command - old whitespace compatibility
1307
1308
1309 ;;;###autoload
1310 (defun whitespace-buffer ()
1311 "Turn on `whitespace-mode' forcing some settings.
1312
1313 It forces `whitespace-style' to have `color'.
1314
1315 It also forces `whitespace-chars' to have:
1316
1317 trailing
1318 indentation
1319 space-before-tab
1320 empty
1321 space-after-tab
1322
1323 So, it is possible to visualize the following problems:
1324
1325 empty 1. empty lines at beginning of buffer.
1326 empty 2. empty lines at end of buffer.
1327 indentation 3. 8 or more SPACEs at beginning of line.
1328 space-before-tab 4. SPACEs before TAB.
1329 trailing 5. SPACEs or TABs at end of line.
1330 space-after-tab 6. 8 or more SPACEs after TAB.
1331
1332 See `whitespace-chars' and `whitespace-style' for documentation.
1333 See also `whitespace-cleanup' and `whitespace-cleanup-region' for
1334 cleaning up these problems."
1335 (interactive)
1336 (whitespace-mode 0) ; assure is off
1337 ;; keep original values
1338 (let ((whitespace-style (copy-sequence whitespace-style))
1339 (whitespace-chars (copy-sequence whitespace-chars)))
1340 ;; adjust options for whitespace bogus blanks
1341 (add-to-list 'whitespace-style 'color)
1342 (mapc #'(lambda (option)
1343 (add-to-list 'whitespace-chars option))
1344 '(trailing
1345 indentation
1346 space-before-tab
1347 empty
1348 space-after-tab))
1349 (whitespace-mode 1))) ; turn on
1350
1351
1352 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1353 ;;;; Internal functions
1354
1355
1356 (defvar whitespace-font-lock-mode nil
1357 "Used to remember whether a buffer had font lock mode on or not.")
1358 (make-variable-buffer-local 'whitespace-font-lock-mode)
1359
1360 (defvar whitespace-font-lock nil
1361 "Used to remember whether a buffer initially had font lock on or not.")
1362 (make-variable-buffer-local 'whitespace-font-lock)
1363
1364 (defvar whitespace-font-lock-keywords nil
1365 "Used to save locally `font-lock-keywords' value.")
1366 (make-variable-buffer-local 'whitespace-font-lock-keywords)
1367
1368
1369 (defconst whitespace-help-text
1370 "\
1371 whitespace-mode toggle options:
1372
1373 [] t - toggle TAB visualization
1374 [] s - toggle SPACE and HARD SPACE visualization
1375 [] r - toggle trailing blanks visualization
1376 [] b - toggle SPACEs before TAB visualization
1377 [] l - toggle \"long lines\" visualization
1378 [] L - toggle \"long lines\" tail visualization
1379 [] n - toggle NEWLINE visualization
1380 [] i - toggle indentation SPACEs visualization
1381 [] e - toggle empty line at bob and/or eob visualization
1382 [] a - toggle SPACEs after TAB visualization
1383
1384 [] c - toggle color faces
1385 [] m - toggle visual mark
1386
1387 x - restore `whitespace-chars' value
1388 z - restore `whitespace-style' value
1389
1390 ? - display this text\n\n"
1391 "Text for whitespace toggle options.")
1392
1393
1394 (defconst whitespace-help-buffer-name "*Whitespace Toggle Options*"
1395 "The buffer name for whitespace toggle options.")
1396
1397
1398 (defun whitespace-insert-option-mark (the-list the-value)
1399 "Insert the option mark ('X' or ' ') in toggle options buffer."
1400 (forward-line 1)
1401 (dolist (sym the-list)
1402 (forward-line 1)
1403 (forward-char 2)
1404 (insert (if (memq sym the-value) "X" " "))))
1405
1406
1407 (defun whitespace-help-on (chars style)
1408 "Display the whitespace toggle options."
1409 (unless (get-buffer whitespace-help-buffer-name)
1410 (delete-other-windows)
1411 (let ((buffer (get-buffer-create whitespace-help-buffer-name)))
1412 (save-excursion
1413 (set-buffer buffer)
1414 (erase-buffer)
1415 (insert whitespace-help-text)
1416 (goto-char (point-min))
1417 (whitespace-insert-option-mark
1418 whitespace-chars-value-list chars)
1419 (whitespace-insert-option-mark
1420 whitespace-style-value-list style)
1421 (goto-char (point-min))
1422 (set-buffer-modified-p nil)
1423 (let ((size (- (window-height)
1424 (max window-min-height
1425 (1+ (count-lines (point-min)
1426 (point-max)))))))
1427 (when (<= size 0)
1428 (kill-buffer buffer)
1429 (error "Frame height is too small; \
1430 can't split window to display whitespace toggle options"))
1431 (set-window-buffer (split-window nil size) buffer))))))
1432
1433
1434 (defun whitespace-help-off ()
1435 "Remove the buffer and window of the whitespace toggle options."
1436 (let ((buffer (get-buffer whitespace-help-buffer-name)))
1437 (when buffer
1438 (delete-windows-on buffer)
1439 (kill-buffer buffer))))
1440
1441
1442 (defun whitespace-interactive-char (local-p)
1443 "Interactive function to read a char and return a symbol.
1444
1445 If LOCAL-P is non-nil, it uses a local context; otherwise, it
1446 uses a global context.
1447
1448 It reads one of the following chars:
1449
1450 CHAR MEANING
1451 t toggle TAB visualization
1452 s toggle SPACE and HARD SPACE visualization
1453 r toggle trailing blanks visualization
1454 b toggle SPACEs before TAB visualization
1455 l toggle \"long lines\" visualization
1456 L toggle \"long lines\" tail visualization
1457 n toggle NEWLINE visualization
1458 i toggle indentation SPACEs visualization
1459 e toggle empty line at bob and/or eob visualization
1460 a toggle SPACEs after TAB visualization
1461 c toggle color faces
1462 m toggle visual mark
1463 x restore `whitespace-chars' value
1464 z restore `whitespace-style' value
1465 ? display brief help
1466
1467 See also `whitespace-toggle-option-alist'."
1468 (let* ((is-off (not (if local-p
1469 whitespace-mode
1470 global-whitespace-mode)))
1471 (chars (cond (is-off whitespace-chars) ; use default value
1472 (local-p whitespace-active-chars)
1473 (t whitespace-toggle-chars)))
1474 (style (cond (is-off whitespace-style) ; use default value
1475 (local-p whitespace-active-style)
1476 (t whitespace-toggle-style)))
1477 (prompt
1478 (format "Whitespace Toggle %s (type ? for further options)-"
1479 (if local-p "Local" "Global")))
1480 ch sym)
1481 ;; read a valid option and get the corresponding symbol
1482 (save-window-excursion
1483 (condition-case data
1484 (progn
1485 (while
1486 ;; while condition
1487 (progn
1488 (setq ch (read-char prompt))
1489 (not
1490 (setq sym
1491 (cdr
1492 (assq ch whitespace-toggle-option-alist)))))
1493 ;; while body
1494 (if (eq ch ?\?)
1495 (whitespace-help-on chars style)
1496 (ding)))
1497 (whitespace-help-off)
1498 (message " ")) ; clean echo area
1499 ;; handler
1500 ((quit error)
1501 (whitespace-help-off)
1502 (error (error-message-string data)))))
1503 (list sym))) ; return the apropriate symbol
1504
1505
1506 (defun whitespace-toggle-list (local-p arg the-list default-list
1507 sym-restore sym-list)
1508 "Toggle options in THE-LIST based on list ARG.
1509
1510 If LOCAL-P is non-nil, it uses a local context; otherwise, it
1511 uses a global context.
1512
1513 ARG is a list of options to be toggled.
1514
1515 THE-LIST is a list of options. This list will be toggled and the
1516 resultant list will be returned.
1517
1518 DEFAULT-LIST is the default list of options. It is used to
1519 restore the options in THE-LIST.
1520
1521 SYM-RESTORE is the symbol which indicates to restore the options
1522 in THE-LIST.
1523
1524 SYM-LIST is a list of valid options, used to check if the ARG's
1525 options are valid."
1526 (unless (if local-p whitespace-mode global-whitespace-mode)
1527 (setq the-list default-list))
1528 (setq the-list (copy-sequence the-list)) ; keep original list
1529 (dolist (sym (if (listp arg) arg (list arg)))
1530 (cond
1531 ;; restore default values
1532 ((eq sym sym-restore)
1533 (setq the-list default-list))
1534 ;; toggle valid values
1535 ((memq sym sym-list)
1536 (setq the-list (if (memq sym the-list)
1537 (delq sym the-list)
1538 (cons sym the-list))))))
1539 the-list)
1540
1541
1542 (defun whitespace-turn-on ()
1543 "Turn on whitespace visualization."
1544 (setq whitespace-active-style (if (listp whitespace-style)
1545 whitespace-style
1546 (list whitespace-style)))
1547 (setq whitespace-active-chars (if (listp whitespace-chars)
1548 whitespace-chars
1549 (list whitespace-chars)))
1550 (when (memq 'color whitespace-active-style)
1551 (whitespace-color-on))
1552 (when (memq 'mark whitespace-active-style)
1553 (whitespace-display-char-on)))
1554
1555
1556 (defun whitespace-turn-off ()
1557 "Turn off whitesapce visualization."
1558 (when (memq 'color whitespace-active-style)
1559 (whitespace-color-off))
1560 (when (memq 'mark whitespace-active-style)
1561 (whitespace-display-char-off)))
1562
1563
1564 (defun whitespace-color-on ()
1565 "Turn on color visualization."
1566 (when whitespace-active-chars
1567 (unless whitespace-font-lock
1568 (setq whitespace-font-lock t
1569 whitespace-font-lock-keywords
1570 (copy-sequence font-lock-keywords)))
1571 ;; turn off font lock
1572 (setq whitespace-font-lock-mode font-lock-mode)
1573 (font-lock-mode 0)
1574 ;; add whitespace-mode color into font lock
1575 (when (memq 'spaces whitespace-active-chars)
1576 (font-lock-add-keywords
1577 nil
1578 (list
1579 ;; Show SPACEs
1580 (list whitespace-space-regexp 1 whitespace-space t)
1581 ;; Show HARD SPACEs
1582 (list whitespace-hspace-regexp 1 whitespace-hspace t))
1583 t))
1584 (when (memq 'tabs whitespace-active-chars)
1585 (font-lock-add-keywords
1586 nil
1587 (list
1588 ;; Show TABs
1589 (list whitespace-tab-regexp 1 whitespace-tab t))
1590 t))
1591 (when (memq 'trailing whitespace-active-chars)
1592 (font-lock-add-keywords
1593 nil
1594 (list
1595 ;; Show trailing blanks
1596 (list (concat "\\(\\(" whitespace-trailing-regexp "\\)+\\)$")
1597 1 whitespace-trailing t))
1598 t))
1599 (when (or (memq 'lines whitespace-active-chars)
1600 (memq 'lines-tail whitespace-active-chars))
1601 (font-lock-add-keywords
1602 nil
1603 (list
1604 ;; Show "long" lines
1605 (list
1606 (format
1607 "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
1608 tab-width (1- tab-width)
1609 (/ whitespace-line-column tab-width)
1610 (let ((rem (% whitespace-line-column tab-width)))
1611 (if (zerop rem)
1612 ""
1613 (format ".\\{%d\\}" rem))))
1614 (if (memq 'lines whitespace-active-chars)
1615 0 ; whole line
1616 2) ; line tail
1617 whitespace-line t))
1618 t))
1619 (when (memq 'space-before-tab whitespace-active-chars)
1620 (font-lock-add-keywords
1621 nil
1622 (list
1623 ;; Show SPACEs before TAB
1624 (list whitespace-space-before-tab-regexp
1625 1 whitespace-space-before-tab t))
1626 t))
1627 (when (memq 'indentation whitespace-active-chars)
1628 (font-lock-add-keywords
1629 nil
1630 (list
1631 ;; Show indentation SPACEs
1632 (list whitespace-indentation-regexp
1633 1 whitespace-indentation t))
1634 t))
1635 (when (memq 'empty whitespace-active-chars)
1636 (font-lock-add-keywords
1637 nil
1638 (list
1639 ;; Show empty lines at beginning of buffer
1640 (list whitespace-empty-at-bob-regexp
1641 1 whitespace-empty t))
1642 t)
1643 (font-lock-add-keywords
1644 nil
1645 (list
1646 ;; Show empty lines at end of buffer
1647 (list whitespace-empty-at-eob-regexp
1648 1 whitespace-empty t))
1649 t))
1650 (when (memq 'space-after-tab whitespace-active-chars)
1651 (font-lock-add-keywords
1652 nil
1653 (list
1654 ;; Show SPACEs after TAB
1655 (list whitespace-space-after-tab-regexp
1656 1 whitespace-space-after-tab t))
1657 t))
1658 ;; now turn on font lock and highlight blanks
1659 (font-lock-mode 1)))
1660
1661
1662 (defun whitespace-color-off ()
1663 "Turn off color visualization."
1664 (when whitespace-active-chars
1665 ;; turn off font lock
1666 (font-lock-mode 0)
1667 (when whitespace-font-lock
1668 (setq whitespace-font-lock nil
1669 font-lock-keywords whitespace-font-lock-keywords))
1670 ;; restore original font lock state
1671 (font-lock-mode whitespace-font-lock-mode)))
1672
1673
1674 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1675 ;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
1676
1677
1678 (defvar whitespace-display-table nil
1679 "Used to save a local display table.")
1680 (make-variable-buffer-local 'whitespace-display-table)
1681
1682 (defvar whitespace-display-table-was-local nil
1683 "Used to remember whether a buffer initially had a local display table.")
1684 (make-variable-buffer-local 'whitespace-display-table-was-local)
1685
1686
1687 (defsubst whitespace-char-valid-p (char)
1688 ;; This check should be improved!!!
1689 (or (< char 256)
1690 (char-valid-p char)))
1691
1692
1693 (defun whitespace-display-vector-p (vec)
1694 "Return true if every character in vector VEC can be displayed."
1695 (let ((i (length vec)))
1696 (when (> i 0)
1697 (while (and (>= (setq i (1- i)) 0)
1698 (whitespace-char-valid-p (aref vec i))))
1699 (< i 0))))
1700
1701
1702 (defun whitespace-display-char-on ()
1703 "Turn on character display mapping."
1704 (when whitespace-display-mappings
1705 (let (vecs vec)
1706 ;; Remember whether a buffer has a local display table.
1707 (unless whitespace-display-table-was-local
1708 (setq whitespace-display-table-was-local t
1709 whitespace-display-table
1710 (copy-sequence buffer-display-table)))
1711 (unless buffer-display-table
1712 (setq buffer-display-table (make-display-table)))
1713 (dolist (entry whitespace-display-mappings)
1714 (setq vecs (cdr entry))
1715 ;; Get a displayable mapping.
1716 (while (and vecs
1717 (not (whitespace-display-vector-p (car vecs))))
1718 (setq vecs (cdr vecs)))
1719 ;; Display a valid mapping.
1720 (when vecs
1721 (setq vec (copy-sequence (car vecs)))
1722 (cond
1723 ;; Any char except newline
1724 ((not (eq (car entry) ?\n))
1725 (aset buffer-display-table (car entry) vec))
1726 ;; Newline char - display it
1727 ((memq 'newline whitespace-active-chars)
1728 ;; Only insert face bits on NEWLINE char mapping to avoid
1729 ;; obstruction of other faces like TABs and (HARD) SPACEs
1730 ;; faces, font-lock faces, etc.
1731 (when (memq 'color whitespace-active-style)
1732 (dotimes (i (length vec))
1733 ;; Due to limitations of glyph representation, the char
1734 ;; code can not be above ?\x1FFFF. Probably, this will
1735 ;; be fixed after Emacs unicode merging.
1736 (or (eq (aref vec i) ?\n)
1737 (> (aref vec i) #x1FFFF)
1738 (aset vec i
1739 (make-glyph-code (aref vec i)
1740 whitespace-newline)))))
1741 ;; Display mapping
1742 (aset buffer-display-table (car entry) vec))
1743 ;; Newline char - don't display it
1744 (t
1745 ;; Do nothing
1746 )))))))
1747
1748
1749 (defun whitespace-display-char-off ()
1750 "Turn off character display mapping."
1751 (and whitespace-display-mappings
1752 whitespace-display-table-was-local
1753 (setq whitespace-display-table-was-local nil
1754 buffer-display-table whitespace-display-table)))
1755
1756
1757 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1758
1759
1760 (provide 'whitespace)
1761
1762
1763 (run-hooks 'whitespace-load-hook)
1764
1765
1766 ;;; whitespace.el ends here