1 ;;; blank-mode.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE
3 ;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 ;; Free Software Foundation, Inc.
6 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
10 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
12 ;; This file is part of GNU Emacs.
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.
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.
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.
31 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36 ;; This package is a minor mode to visualize blanks (TAB, (HARD) SPACE
39 ;; blank-mode uses two ways to visualize blanks: faces and display
42 ;; * Faces are used to highlight the background with a color.
43 ;; blank-mode uses font-lock to highlight blank characters.
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).
49 ;; The `blank-style' and `blank-chars' variables are used to select
50 ;; which way should be used to visualize blanks.
52 ;; Note that when blank-mode is turned on, blank-mode saves the
53 ;; font-lock state, that is, if font-lock is on or off. And
54 ;; blank-mode restores the font-lock state when it is turned off. So,
55 ;; if blank-mode is turned on and font-lock is off, blank-mode also
56 ;; turns on the font-lock to highlight blanks, but the font-lock will
57 ;; be turned off when blank-mode is turned off. Thus, turn on
58 ;; font-lock before blank-mode is on, if you want that font-lock
59 ;; continues on after blank-mode is turned off.
61 ;; When blank-mode 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).
65 ;; There are two ways of using blank-mode: local and global.
67 ;; * Local blank-mode affects only the current buffer.
69 ;; * Global blank-mode affects all current and future buffers. That
70 ;; is, if you turn on global blank-mode and then create a new
71 ;; buffer, the new buffer will also have blank-mode on. The
72 ;; `blank-global-modes' variable controls which major-mode will be
73 ;; automagically turned on.
75 ;; You can mix the local and global usage without any conflict. But
76 ;; local blank-mode has priority over global blank-mode. Blank mode
77 ;; is active in a buffer if you have enabled it in that buffer or if
78 ;; you have enabled it globally.
80 ;; When global and local blank-mode are on:
82 ;; * if local blank-mode is turned off, blank-mode is turned off for
83 ;; the current buffer only.
85 ;; * if global blank-mode is turned off, blank-mode continues on only
86 ;; in the buffers in which local blank-mode is on.
88 ;; To use blank-mode, insert in your ~/.emacs:
90 ;; (require 'blank-mode)
92 ;; Or autoload at least one of the commands`blank-mode',
93 ;; `blank-toggle-options', `global-blank-mode' or
94 ;; `global-blank-toggle-options'. For example:
96 ;; (autoload 'blank-mode "blank-mode"
97 ;; "Toggle blank visualization." t)
98 ;; (autoload 'blank-toggle-options "blank-mode"
99 ;; "Toggle local `blank-mode' options." t)
101 ;; blank-mode was inspired by:
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)
107 ;; show-whitespace-mode.el Aurelien Tisne <aurelien.tisne@free.fr>
108 ;; Simple mode to highlight whitespaces
109 ;; (inspired the idea to use font-lock)
111 ;; whitespace-mode.el Lawrence Mitchell <wence@gmx.li>
112 ;; Major mode for editing Whitespace
113 ;; (inspired the idea to use display table)
115 ;; visws.el Miles Bader <miles@gnu.org>
116 ;; Make whitespace visible
117 ;; (handle display table, his code was modified, but the main
124 ;; There is no problem if you mix local and global minor mode usage.
126 ;; * LOCAL blank-mode:
127 ;; + To toggle blank-mode options locally, type:
129 ;; M-x blank-toggle-options RET
131 ;; + To activate blank-mode locally, type:
133 ;; C-u 1 M-x blank-mode RET
135 ;; + To deactivate blank-mode locally, type:
137 ;; C-u 0 M-x blank-mode RET
139 ;; + To toggle blank-mode locally, type:
141 ;; M-x blank-mode RET
143 ;; * GLOBAL blank-mode:
144 ;; + To toggle blank-mode options globally, type:
146 ;; M-x global-blank-toggle-options RET
148 ;; + To activate blank-mode globally, type:
150 ;; C-u 1 M-x global-blank-mode RET
152 ;; + To deactivate blank-mode globally, type:
154 ;; C-u 0 M-x global-blank-mode RET
156 ;; + To toggle blank-mode globally, type:
158 ;; M-x global-blank-mode RET
160 ;; There are also the following useful commands:
163 ;; Cleanup some blank problems in all buffer or at region.
165 ;; `blank-cleanup-region'
166 ;; Cleanup some blank problems at region.
168 ;; The problems, which are cleaned up, are:
170 ;; 1. empty lines at beginning of buffer.
171 ;; 2. empty lines at end of buffer.
172 ;; If `blank-chars' has `empty' as an element, remove all empty
173 ;; lines at beginning and/or end of buffer.
175 ;; 3. 8 or more SPACEs at beginning of line.
176 ;; If `blank-chars' has `indentation' as an element, replace 8 or
177 ;; more SPACEs at beginning of line by TABs.
179 ;; 4. SPACEs before TAB.
180 ;; If `blank-chars' has `space-before-tab' as an element, replace
183 ;; 5. SPACEs or TABs at end of line.
184 ;; If `blank-chars' has `trailing' as an element, remove all
185 ;; SPACEs or TABs at end of line."
187 ;; 6. 8 or more SPACEs after TAB.
188 ;; If `blank-chars' has `space-after-tab' as an element, replace
195 ;; blank-mode has the following hook variables:
198 ;; It is evaluated always when blank-mode is turned on locally.
200 ;; `global-blank-mode-hook'
201 ;; It is evaluated always when blank-mode is turned on globally.
204 ;; It is evaluated after blank-mode package is loaded.
210 ;; Below it's shown a brief description of blank-mode options, please,
211 ;; see the options declaration in the code for a long documentation.
213 ;; `blank-style' Specify the visualization style.
215 ;; `blank-chars' Specify which kind of blank is
218 ;; `blank-space' Face used to visualize SPACE.
220 ;; `blank-hspace' Face used to visualize HARD SPACE.
222 ;; `blank-tab' Face used to visualize TAB.
224 ;; `blank-newline' Face used to visualize NEWLINE char
227 ;; `blank-trailing' Face used to visualize trailing
230 ;; `blank-line' Face used to visualize "long" lines.
232 ;; `blank-space-before-tab' Face used to visualize SPACEs before
235 ;; `blank-indentation' Face used to visualize 8 or more
236 ;; SPACEs at beginning of line.
238 ;; `blank-empty' Face used to visualize empty lines at
239 ;; beginning and/or end of buffer.
241 ;; `blank-space-after-tab' Face used to visualize 8 or more
244 ;; `blank-space-regexp' Specify SPACE characters regexp.
246 ;; `blank-hspace-regexp' Specify HARD SPACE characters regexp.
248 ;; `blank-tab-regexp' Specify TAB characters regexp.
250 ;; `blank-trailing-regexp' Specify trailing characters regexp.
252 ;; `blank-space-before-tab-regexp' Specify SPACEs before TAB
255 ;; `blank-indentation-regexp' Specify regexp for 8 or more SPACEs at
256 ;; beginning of line.
258 ;; `blank-empty-at-bob-regexp' Specify regexp for empty lines at
259 ;; beginning of buffer.
261 ;; `blank-empty-at-eob-regexp' Specify regexp for empty lines at end
264 ;; `blank-space-after-tab-regexp' Specify regexp for 8 or more
267 ;; `blank-line-length' Specify length beyond which the line
270 ;; `blank-display-mappings' Specify an alist of mappings for
271 ;; displaying characters.
273 ;; `blank-global-modes' Modes for which global `blank-mode' is
274 ;; automagically turned on.
280 ;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
281 ;; * `define-minor-mode'.
282 ;; * `global-blank-*' name for global commands.
284 ;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
286 ;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
289 ;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
290 ;; helping to fix `find-file-hooks' reference.
292 ;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
293 ;; indicating defface byte-compilation warnings.
295 ;; Thanks to TimOCallaghan (EmacsWiki) for the idea about highlight
296 ;; "long" lines. See EightyColumnRule (EmacsWiki).
298 ;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
299 ;; newline character mapping.
301 ;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
302 ;; whitespace-mode on XEmacs.
304 ;; Thanks to Miles Bader <miles@gnu.org> for handling display table via
305 ;; visws.el (his code was modified, but the main idea was kept).
308 ;; Rajesh Vaidheeswarran <rv@gnu.org> whitespace.el
309 ;; Aurelien Tisne <aurelien.tisne@free.fr> show-whitespace-mode.el
310 ;; Lawrence Mitchell <wence@gmx.li> whitespace-mode.el
311 ;; Miles Bader <miles@gnu.org> visws.el
312 ;; And to all people who contributed with them.
315 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
320 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
324 ;;; Interface to the command system
328 "Visualize blanks (TAB, (HARD) SPACE and NEWLINE)."
329 :link
'(emacs-library-link :tag
"Source Lisp File" "blank-mode.el")
335 (defcustom blank-style
'(mark color
)
336 "*Specify the visualization style.
338 It's a list which element value can be:
340 mark display mappings are visualized.
342 color faces are visualized.
344 Any other value is ignored.
346 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs.
348 See also `blank-display-mappings' for documentation."
349 :type
'(repeat :tag
"Style of Blank"
350 (choice :tag
"Style of Blank"
351 (const :tag
"Display Table" mark
)
352 (const :tag
"Faces" color
)))
356 (defcustom blank-chars
357 '(tabs spaces trailing lines space-before-tab newline
358 indentation empty space-after-tab
)
359 "*Specify which kind of blank is visualized.
361 It's a list which element value can be:
363 trailing trailing blanks are visualized.
365 tabs TABs are visualized.
367 spaces SPACEs and HARD SPACEs are visualized.
369 lines lines whose length is greater than
370 `blank-line-length' are highlighted.
372 space-before-tab SPACEs before TAB are visualized.
374 newline NEWLINEs are visualized.
376 indentation 8 or more SPACEs at beginning of line are
379 empty empty lines at beginning and/or end of buffer
382 space-after-tab 8 or more SPACEs after a TAB are visualized.
384 Any other value is ignored.
386 If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs.
388 Used when `blank-style' has `color' as an element.
389 If `blank-chars' has `newline' as an element, used when `blank-style'
390 has `mark' as an element."
391 :type
'(repeat :tag
"Kind of Blank"
392 (choice :tag
"Kind of Blank"
393 (const :tag
"Trailing TABs, SPACEs and HARD SPACEs"
395 (const :tag
"SPACEs and HARD SPACEs" spaces
)
396 (const :tag
"TABs" tabs
)
397 (const :tag
"Lines" lines
)
398 (const :tag
"SPACEs before TAB"
400 (const :tag
"NEWLINEs" newline
)
401 (const :tag
"Indentation SPACEs" indentation
)
402 (const :tag
"Empty Lines At BOB And/Or EOB"
404 (const :tag
"SPACEs after TAB"
409 (defcustom blank-space
'blank-space
410 "*Symbol face used to visualize SPACE.
412 Used when `blank-style' has `color' as an element."
418 '((((class color
) (background dark
))
419 (:background
"grey20" :foreground
"aquamarine3"))
420 (((class color
) (background light
))
421 (:background
"LightYellow" :foreground
"aquamarine3"))
422 (t (:inverse-video t
)))
423 "Face used to visualize SPACE."
427 (defcustom blank-hspace
'blank-hspace
428 "*Symbol face used to visualize HARD SPACE.
430 Used when `blank-style' has `color' as an element."
435 (defface blank-hspace
; 'nobreak-space
436 '((((class color
) (background dark
))
437 (:background
"grey24" :foreground
"aquamarine3"))
438 (((class color
) (background light
))
439 (:background
"LemonChiffon3" :foreground
"aquamarine3"))
440 (t (:inverse-video t
)))
441 "Face used to visualize HARD SPACE."
445 (defcustom blank-tab
'blank-tab
446 "*Symbol face used to visualize TAB.
448 Used when `blank-style' has `color' as an element."
454 '((((class color
) (background dark
))
455 (:background
"grey22" :foreground
"aquamarine3"))
456 (((class color
) (background light
))
457 (:background
"beige" :foreground
"aquamarine3"))
458 (t (:inverse-video t
)))
459 "Face used to visualize TAB."
463 (defcustom blank-newline
'blank-newline
464 "*Symbol face used to visualize NEWLINE char mapping.
466 See `blank-display-mappings'.
468 Used when `blank-style' has `mark' and `color' as elements
469 and `blank-chars' has `newline' as an element."
474 (defface blank-newline
475 '((((class color
) (background dark
))
476 (:background
"grey26" :foreground
"aquamarine3" :bold t
))
477 (((class color
) (background light
))
478 (:background
"linen" :foreground
"aquamarine3" :bold t
))
479 (t (:bold t
:underline t
)))
480 "Face used to visualize NEWLINE char mapping.
482 See `blank-display-mappings'."
486 (defcustom blank-trailing
'blank-trailing
487 "*Symbol face used to visualize traling blanks.
489 Used when `blank-style' has `color' as an element."
494 (defface blank-trailing
; 'trailing-whitespace
495 '((((class mono
)) (:inverse-video t
:bold t
:underline t
))
496 (t (:background
"red1" :foreground
"yellow" :bold t
)))
497 "Face used to visualize trailing blanks."
501 (defcustom blank-line
'blank-line
502 "*Symbol face used to visualize \"long\" lines.
504 See `blank-line-length'.
506 Used when `blank-style' has `color' as an element."
512 '((((class mono
)) (:inverse-video t
:bold t
:underline t
))
513 (t (:background
"gray20" :foreground
"violet")))
514 "Face used to visualize \"long\" lines.
516 See `blank-line-length'."
520 (defcustom blank-space-before-tab
'blank-space-before-tab
521 "*Symbol face used to visualize SPACEs before TAB.
523 Used when `blank-style' has `color' as an element."
528 (defface blank-space-before-tab
529 '((((class mono
)) (:inverse-video t
:bold t
:underline t
))
530 (t (:background
"DarkOrange" :foreground
"firebrick")))
531 "Face used to visualize SPACEs before TAB."
535 (defcustom blank-indentation
'blank-indentation
536 "*Symbol face used to visualize 8 or more SPACEs at beginning of line.
538 Used when `blank-style' has `color' as an element."
543 (defface blank-indentation
544 '((((class mono
)) (:inverse-video t
:bold t
:underline t
))
545 (t (:background
"yellow" :foreground
"firebrick")))
546 "Face used to visualize 8 or more SPACEs at beginning of line."
550 (defcustom blank-empty
'blank-empty
551 "*Symbol face used to visualize empty lines at beginning and/or end of buffer.
553 Used when `blank-style' has `color' as an element."
559 '((((class mono
)) (:inverse-video t
:bold t
:underline t
))
560 (t (:background
"yellow" :foreground
"firebrick")))
561 "Face used to visualize empty lines at beginning and/or end of buffer."
565 (defcustom blank-space-after-tab
'blank-space-after-tab
566 "*Symbol face used to visualize 8 or more SPACEs after TAB.
568 Used when `blank-style' has `color' as an element."
573 (defface blank-space-after-tab
574 '((((class mono
)) (:inverse-video t
:bold t
:underline t
))
575 (t (:background
"yellow" :foreground
"firebrick")))
576 "Face used to visualize 8 or more SPACEs after TAB."
580 (defcustom blank-hspace-regexp
581 "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
582 "*Specify HARD SPACE characters regexp.
584 If you're using `mule' package, it may exist other characters besides:
586 \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \"\\xF20\"
588 that should be considered HARD SPACE.
590 Here are some examples:
592 \"\\\\(^\\xA0+\\\\)\" \
593 visualize only leading HARD SPACEs.
594 \"\\\\(\\xA0+$\\\\)\" \
595 visualize only trailing HARD SPACEs.
596 \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\" \
597 visualize leading and/or trailing HARD SPACEs.
598 \"\\t\\\\(\\xA0+\\\\)\\t\" \
599 visualize only HARD SPACEs between TABs.
601 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
602 Use exactly one pair of enclosing \\\\( and \\\\).
604 Used when `blank-style' has `color' as an element, and
605 `blank-chars' has `spaces' as an element."
606 :type
'(regexp :tag
"HARD SPACE Chars")
610 (defcustom blank-space-regexp
"\\( +\\)"
611 "*Specify SPACE characters regexp.
613 If you're using `mule' package, it may exist other characters
614 besides \" \" that should be considered SPACE.
616 Here are some examples:
618 \"\\\\(^ +\\\\)\" visualize only leading SPACEs.
619 \"\\\\( +$\\\\)\" visualize only trailing SPACEs.
620 \"\\\\(^ +\\\\| +$\\\\)\" \
621 visualize leading and/or trailing SPACEs.
622 \"\\t\\\\( +\\\\)\\t\" visualize only SPACEs between TABs.
624 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
625 Use exactly one pair of enclosing \\\\( and \\\\).
627 Used when `blank-style' has `color' as an element, and
628 `blank-chars' has `spaces' as an element."
629 :type
'(regexp :tag
"SPACE Chars")
633 (defcustom blank-tab-regexp
"\\(\t+\\)"
634 "*Specify TAB characters regexp.
636 If you're using `mule' package, it may exist other characters
637 besides \"\\t\" that should be considered TAB.
639 Here are some examples:
641 \"\\\\(^\\t+\\\\)\" visualize only leading TABs.
642 \"\\\\(\\t+$\\\\)\" visualize only trailing TABs.
643 \"\\\\(^\\t+\\\\|\\t+$\\\\)\" \
644 visualize leading and/or trailing TABs.
645 \" \\\\(\\t+\\\\) \" visualize only TABs between SPACEs.
647 NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
648 Use exactly one pair of enclosing \\\\( and \\\\).
650 Used when `blank-style' has `color' as an element, and
651 `blank-chars' has `tabs' as an element."
652 :type
'(regexp :tag
"TAB Chars")
656 (defcustom blank-trailing-regexp
657 "\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20"
658 "*Specify trailing characters regexp.
660 If you're using `mule' package, it may exist other characters besides:
662 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
665 that should be considered blank.
667 NOTE: DO NOT enclose by \\\\( and \\\\) the elements to highlight.
668 `blank-mode' surrounds this regexp by \"\\\\(\\\\(\" and
671 Used when `blank-style' has `color' as an element, and
672 `blank-chars' has `trailing' as an element."
673 :type
'(regexp :tag
"Trailing Chars")
677 (defcustom blank-space-before-tab-regexp
"\\( +\\)\t"
678 "*Specify SPACEs before TAB regexp.
680 If you're using `mule' package, it may exist other characters besides:
682 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
685 that should be considered blank.
687 Used when `blank-style' has `color' as an element, and
688 `blank-chars' has `space-before-tab' as an element."
689 :type
'(regexp :tag
"SPACEs Before TAB")
693 (defcustom blank-indentation-regexp
"^\t*\\(\\( \\{8\\}\\)+\\)[^\n\t]"
694 "*Specify regexp for 8 or more SPACEs at beginning of line.
696 If you're using `mule' package, it may exist other characters besides:
698 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
701 that should be considered blank.
703 Used when `blank-style' has `color' as an element, and
704 `blank-chars' has `indentation' as an element."
705 :type
'(regexp :tag
"Indentation SPACEs")
709 (defcustom blank-empty-at-bob-regexp
"\\`\\(\\([ \t]*\n\\)+\\)"
710 "*Specify regexp for empty lines at beginning of buffer.
712 If you're using `mule' package, it may exist other characters besides:
714 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
717 that should be considered blank.
719 Used when `blank-style' has `color' as an element, and
720 `blank-chars' has `empty' as an element."
721 :type
'(regexp :tag
"Empty Lines At Beginning Of Buffer")
725 (defcustom blank-empty-at-eob-regexp
"^\\([ \t\n]+\\)\\'"
726 "*Specify regexp for empty lines at end of buffer.
728 If you're using `mule' package, it may exist other characters besides:
730 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
733 that should be considered blank.
735 Used when `blank-style' has `color' as an element, and
736 `blank-chars' has `empty' as an element."
737 :type
'(regexp :tag
"Empty Lines At End Of Buffer")
741 (defcustom blank-space-after-tab-regexp
"\t\\(\\( \\{8\\}\\)+\\)"
742 "*Specify regexp for 8 or more SPACEs after TAB.
744 If you're using `mule' package, it may exist other characters besides:
746 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
749 that should be considered blank.
751 Used when `blank-style' has `color' as an element, and
752 `blank-chars' has `space-after-tab' as an element."
753 :type
'(regexp :tag
"SPACEs After TAB")
757 (defcustom blank-line-length
80
758 "*Specify length beyond which the line is highlighted.
760 Used when `blank-style' has `color' as an element, and
761 `blank-chars' has `lines' as an element."
762 :type
'(integer :tag
"Line Length")
766 ;; Hacked from `visible-whitespace-mappings' in visws.el
767 (defcustom blank-display-mappings
768 ;; Due to limitations of glyph representation, the char code can not
769 ;; be above ?\x1FFFF. Probably, this will be fixed after Emacs
772 (?\
[?
\xB7] [?.
]) ; space - centered dot
773 (?
\xA0 [?
\xA4] [?_
]) ; hard space - currency
774 (?
\x8A0 [?
\x8A4] [?_
]) ; hard space - currency
775 (?
\x920
[?
\x924
] [?_
]) ; hard space - currency
776 (?
\xE20
[?
\xE24
] [?_
]) ; hard space - currency
777 (?
\xF20
[?
\xF24
] [?_
]) ; hard space - currency
778 ;; NEWLINE is displayed using the face `blank-newline'
779 (?
\n [?$ ?
\n]) ; end-of-line - dollar sign
780 ;; (?\n [?\u21B5 ?\n] [?$ ?\n]) ; end-of-line - downwards arrow
781 ;; (?\n [?\xB6 ?\n] [?$ ?\n]) ; end-of-line - pilcrow
782 ;; (?\n [?\x8AF ?\n] [?$ ?\n]) ; end-of-line - overscore
783 ;; (?\n [?\x8AC ?\n] [?$ ?\n]) ; end-of-line - negation
784 ;; (?\n [?\x8B0 ?\n] [?$ ?\n]) ; end-of-line - grade
786 ;; WARNING: the mapping below has a problem.
787 ;; When a TAB occupies exactly one column, it will display the
788 ;; character ?\xBB at that column followed by a TAB which goes to
789 ;; the next TAB column.
790 ;; If this is a problem for you, please, comment the line below.
791 (?
\t [?
\xBB ?
\t] [?
\\ ?
\t]) ; tab - left quote mark
793 "*Specify an alist of mappings for displaying characters.
795 Each element has the following form:
801 CHAR is the character to be mapped.
803 VECTOR is a vector of characters to be displayed in place of CHAR.
804 The first display vector that can be displayed is used;
805 if no display vector for a mapping can be displayed, then
806 that character is displayed unmodified.
808 The NEWLINE character is displayed using the face given by
809 `blank-newline' variable. The characters in the vector to be
810 displayed will not have this face applied if the character code
813 Used when `blank-style' has `mark' as an element."
815 (list :tag
"Character Mapping"
816 (character :tag
"Char")
817 (repeat :inline t
:tag
"Vector List"
820 :tag
"Vector Characters"
821 (character :tag
"Char"))))))
825 (defcustom blank-global-modes t
826 "*Modes for which global `blank-mode' is automagically turned on.
828 Global `blank-mode' is controlled by the command `global-blank-mode'.
830 If nil, means no modes have `blank-mode' automatically turned on.
831 If t, all modes that support `blank-mode' have it automatically
833 Else it should be a list of `major-mode' symbol names for
834 which `blank-mode' should be automatically turned on. The sense
835 of the list is negated if it begins with `not'. For example:
839 means that `blank-mode' is turned on for buffers in C and C++
841 :type
'(choice (const :tag
"None" nil
)
843 (set :menu-tag
"Mode Specific" :tag
"Modes"
845 (const :tag
"Except" not
)
847 (symbol :tag
"Mode"))))
851 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
852 ;;;; User commands - Local mode
856 (define-minor-mode blank-mode
857 "Toggle blank minor mode visualization (\"bl\" on modeline).
859 If ARG is null, toggle blank visualization.
860 If ARG is a number greater than zero, turn on visualization;
861 otherwise, turn off visualization.
862 Only useful with a windowing system."
868 (noninteractive ; running a batch job
869 (setq blank-mode nil
))
870 (blank-mode ; blank-mode on
876 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
877 ;;;; User commands - Global mode
880 (define-minor-mode global-blank-mode
881 "Toggle blank global minor mode visualization (\"BL\" on modeline).
883 If ARG is null, toggle blank 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."
892 (noninteractive ; running a batch job
893 (setq global-blank-mode nil
))
894 (global-blank-mode ; global-blank-mode on
896 (if (boundp 'find-file-hook
)
897 (add-hook 'find-file-hook
'blank-turn-on-if-enabled t
)
898 (add-hook 'find-file-hooks
'blank-turn-on-if-enabled t
))
899 (dolist (buffer (buffer-list)) ; adjust all local mode
902 (blank-turn-on-if-enabled)))))
903 (t ; global-blank-mode off
905 (if (boundp 'find-file-hook
)
906 (remove-hook 'find-file-hook
'blank-turn-on-if-enabled
)
907 (remove-hook 'find-file-hooks
'blank-turn-on-if-enabled
))
908 (dolist (buffer (buffer-list)) ; adjust all local mode
911 (blank-turn-off)))))))
914 (defun blank-turn-on-if-enabled ()
916 ((eq blank-global-modes t
))
917 ((listp blank-global-modes
)
918 (if (eq (car-safe blank-global-modes
) 'not
)
919 (not (memq major-mode
(cdr blank-global-modes
)))
920 (memq major-mode blank-global-modes
)))
923 ;; Don't turn on blank mode if...
925 ;; ...we don't have a display (we're running a batch job)
927 ;; ...or if the buffer is invisible (name starts with a space)
928 (eq (aref (buffer-name) 0) ?\
)
929 ;; ...or if the buffer is temporary (name starts with *)
930 (and (eq (aref (buffer-name) 0) ?
*)
931 ;; except the scratch buffer.
932 (not (string= (buffer-name) "*scratch*")))
933 ;; Otherwise, turn on blank mode.
937 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
938 ;;;; User commands - Toggle
941 (defconst blank-chars-value-list
952 "List of valid `blank-chars' values.")
955 (defconst blank-style-value-list
959 "List of valid `blank-style' values.")
962 (defconst blank-toggle-option-alist
966 (?b . space-before-tab
)
971 (?a . space-after-tab
)
977 "Alist of toggle options.
979 Each element has the form:
985 CHAR is a char which the user will have to type.
987 SYMBOL is a valid symbol associated with CHAR.
988 See `blank-chars-value-list' and `blank-style-value-list'.")
991 (defvar blank-active-chars nil
992 "Used to save locally `blank-chars' value.")
993 (make-variable-buffer-local 'blank-active-chars
)
995 (defvar blank-active-style nil
996 "Used to save locally `blank-style' value.")
997 (make-variable-buffer-local 'blank-active-style
)
1001 (defun blank-toggle-options (arg)
1002 "Toggle local `blank-mode' options.
1004 If local blank-mode is off, toggle the option given by ARG and
1005 turn on local blank-mode.
1007 If local blank-mode is on, toggle the option given by ARG and
1008 restart local blank-mode.
1010 Interactively, it reads one of the following chars:
1013 t toggle TAB visualization
1014 s toggle SPACE and HARD SPACE visualization
1015 r toggle trailing blanks visualization
1016 b toggle SPACEs before TAB visualization
1017 l toggle \"long lines\" visualization
1018 n toggle NEWLINE visualization
1019 i toggle indentation SPACEs visualization
1020 e toggle empty line at bob and/or eob visualization
1021 a toggle SPACEs after TAB visualization
1022 c toggle color faces
1023 m toggle visual mark
1024 x restore `blank-chars' value
1025 z restore `blank-style' value
1026 ? display brief help
1028 Non-interactively, ARG should be a symbol or a list of symbols.
1029 The valid symbols are:
1031 tabs toggle TAB visualization
1032 spaces toggle SPACE and HARD SPACE visualization
1033 trailing toggle trailing blanks visualization
1034 space-before-tab toggle SPACEs before TAB visualization
1035 lines toggle \"long lines\" visualization
1036 newline toggle NEWLINE visualization
1037 indentation toggle indentation SPACEs visualization
1038 empty toggle empty line at bob and/or eob visualization
1039 space-after-tab toggle SPACEs after TAB visualization
1040 color toggle color faces
1041 mark toggle visual mark
1042 blank-chars restore `blank-chars' value
1043 blank-style restore `blank-style' value
1045 Only useful with a windowing system."
1046 (interactive (blank-interactive-char t
))
1048 (blank-toggle-list t arg blank-active-chars blank-chars
1049 'blank-chars blank-chars-value-list
))
1051 (blank-toggle-list t arg blank-active-style blank-style
1052 'blank-style blank-style-value-list
)))
1057 (defvar blank-toggle-chars nil
1058 "Used to toggle the global `blank-chars' value.")
1059 (defvar blank-toggle-style nil
1060 "Used to toggle the global `blank-style' value.")
1064 (defun global-blank-toggle-options (arg)
1065 "Toggle global `blank-mode' options.
1067 If global blank-mode is off, toggle the option given by ARG and
1068 turn on global blank-mode.
1070 If global blank-mode is on, toggle the option given by ARG and
1071 restart global blank-mode.
1073 Interactively, it reads one of the following chars:
1076 t toggle TAB visualization
1077 s toggle SPACE and HARD SPACE visualization
1078 r toggle trailing blanks visualization
1079 b toggle SPACEs before TAB visualization
1080 l toggle \"long lines\" visualization
1081 n toggle NEWLINE visualization
1082 i toggle indentation SPACEs visualization
1083 e toggle empty line at bob and/or eob visualization
1084 a toggle SPACEs after TAB visualization
1085 c toggle color faces
1086 m toggle visual mark
1087 x restore `blank-chars' value
1088 z restore `blank-style' value
1089 ? display brief help
1091 Non-interactively, ARG should be a symbol or a list of symbols.
1092 The valid symbols are:
1094 tabs toggle TAB visualization
1095 spaces toggle SPACE and HARD SPACE visualization
1096 trailing toggle trailing blanks visualization
1097 space-before-tab toggle SPACEs before TAB visualization
1098 lines toggle \"long lines\" visualization
1099 newline toggle NEWLINE visualization
1100 indentation toggle indentation SPACEs visualization
1101 empty toggle empty line at bob and/or eob visualization
1102 space-after-tab toggle SPACEs after TAB visualization
1103 color toggle color faces
1104 mark toggle visual mark
1105 blank-chars restore `blank-chars' value
1106 blank-style restore `blank-style' value
1108 Only useful with a windowing system."
1109 (interactive (blank-interactive-char nil
))
1111 (blank-toggle-list nil arg blank-toggle-chars blank-chars
1112 'blank-chars blank-chars-value-list
))
1114 (blank-toggle-list nil arg blank-toggle-style blank-style
1115 'blank-style blank-style-value-list
)))
1116 (setq blank-toggle-chars blank-chars
1117 blank-toggle-style blank-style
)
1118 (global-blank-mode 0)
1119 (global-blank-mode 1)))
1122 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1123 ;;;; User commands - Cleanup
1127 (defun blank-cleanup ()
1128 "Cleanup some blank problems in all buffer or at region.
1130 It usually applies to the whole buffer, but in transient mark
1131 mode when the mark is active, it applies to the region. It also
1132 applies to the region when it is not in transiente mark mode, the
1133 mark is active and it was pressed `C-u' just before calling
1134 `blank-cleanup' interactively.
1136 See also `blank-cleanup-region'.
1138 The problems, which are cleaned up, are:
1140 1. empty lines at beginning of buffer.
1141 2. empty lines at end of buffer.
1142 If `blank-chars' has `empty' as an element, remove all empty
1143 lines at beginning and/or end of buffer.
1145 3. 8 or more SPACEs at beginning of line.
1146 If `blank-chars' has `indentation' as an element, replace 8 or
1147 more SPACEs at beginning of line by TABs.
1149 4. SPACEs before TAB.
1150 If `blank-chars' has `space-before-tab' as an element, replace
1153 5. SPACEs or TABs at end of line.
1154 If `blank-chars' has `trailing' as an element, remove all
1155 SPACEs or TABs at end of line.
1157 6. 8 or more SPACEs after TAB.
1158 If `blank-chars' has `space-after-tab' as an element, replace
1161 (if (and (or transient-mark-mode
1165 ;; problems 1 and 2 are not handled in region
1166 ;; problem 3: 8 or more SPACEs at bol
1167 ;; problem 4: SPACEs before TAB
1168 ;; problem 5: SPACEs or TABs at eol
1169 ;; problem 6: 8 or more SPACEs after TAB
1170 (blank-cleanup-region (region-beginning) (region-end))
1173 ;; problem 1: empty lines at bob
1174 ;; problem 2: empty lines at eob
1175 ;; action: remove all empty lines at bob and/or eob
1176 (when (memq 'empty blank-chars
)
1177 (let (overwrite-mode) ; enforce no overwrite
1178 (goto-char (point-min))
1179 (when (re-search-forward blank-empty-at-bob-regexp nil t
)
1180 (delete-region (match-beginning 1) (match-end 1)))
1181 (when (re-search-forward blank-empty-at-eob-regexp nil t
)
1182 (delete-region (match-beginning 1) (match-end 1)))))
1183 ;; problem 3: 8 or more SPACEs at bol
1184 ;; problem 4: SPACEs before TAB
1185 ;; problem 5: SPACEs or TABs at eol
1186 ;; problem 6: 8 or more SPACEs after TAB
1187 (blank-cleanup-region (point-min) (point-max)))))
1191 (defun blank-cleanup-region (start end
)
1192 "Cleanup some blank problems at region.
1194 The problems, which are cleaned up, are:
1196 1. 8 or more SPACEs at beginning of line.
1197 If `blank-chars' has `indentation' as an element, replace 8 or
1198 more SPACEs at beginning of line by TABs.
1200 2. SPACEs before TAB.
1201 If `blank-chars' has `space-before-tab' as an element, replace
1204 3. SPACEs or TABs at end of line.
1205 If `blank-chars' has `trailing' as an element, remove all
1206 SPACEs or TABs at end of line.
1208 4. 8 or more SPACEs after TAB.
1209 If `blank-chars' has `space-after-tab' as an element, replace
1212 (let ((rstart (min start end
))
1213 (rend (copy-marker (max start end
)))
1214 (tab-width 8) ; assure TAB width
1215 (indent-tabs-mode t
) ; always insert TABs
1216 overwrite-mode
; enforce no overwrite
1219 ;; problem 1: 8 or more SPACEs at bol
1220 ;; action: replace 8 or more SPACEs at bol by TABs
1221 (when (memq 'indentation blank-chars
)
1223 (while (re-search-forward blank-indentation-regexp rend t
)
1224 (setq tmp
(current-indentation))
1225 (delete-horizontal-space)
1228 ;; problem 3: SPACEs or TABs at eol
1229 ;; action: remove all SPACEs or TABs at eol
1230 (when (memq 'trailing blank-chars
)
1232 (concat "\\(\\(" blank-trailing-regexp
"\\)+\\)$")))
1234 (while (re-search-forward regexp rend t
)
1235 (delete-region (match-beginning 1) (match-end 1)))))
1236 ;; problem 4: 8 or more SPACEs after TAB
1237 ;; action: replace 8 or more SPACEs by TABs
1238 (when (memq 'space-after-tab blank-chars
)
1240 (while (re-search-forward blank-space-after-tab-regexp rend t
)
1241 (goto-char (match-beginning 1))
1242 (let ((scol (current-column))
1243 (ecol (save-excursion
1244 (goto-char (match-end 1))
1246 (delete-region (match-beginning 1) (match-end 1))
1247 (insert-char ?
\t (/ (- ecol scol
) 8)))))
1248 ;; problem 2: SPACEs before TAB
1249 ;; action: replace SPACEs before TAB by TABs
1250 (when (memq 'space-before-tab blank-chars
)
1252 (while (re-search-forward blank-space-before-tab-regexp rend t
)
1253 (goto-char (match-beginning 1))
1254 (let* ((scol (current-column))
1255 (ecol (save-excursion
1256 (goto-char (match-end 1))
1258 (next-tab-col (* (/ (+ scol
8) 8) 8)))
1259 (delete-region (match-beginning 1) (match-end 1))
1260 (when (<= next-tab-col ecol
)
1262 (/ (- (- ecol
(% ecol
8)) ; prev end col
1263 (- scol
(% scol
8))) ; prev start col
1265 (set-marker rend nil
))) ; point marker to nowhere
1268 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1269 ;;;; Internal functions
1272 (defvar blank-font-lock-mode nil
1273 "Used to remember whether a buffer had font lock mode on or not.")
1274 (make-variable-buffer-local 'blank-font-lock-mode
)
1276 (defvar blank-font-lock nil
1277 "Used to remember whether a buffer initially had font lock on or not.")
1278 (make-variable-buffer-local 'blank-font-lock
)
1280 (defvar blank-font-lock-keywords nil
1281 "Used to save locally `font-lock-keywords' value.")
1282 (make-variable-buffer-local 'blank-font-lock-keywords
)
1285 (defconst blank-help-text
1287 blank-mode toggle options:
1289 [] t - toggle TAB visualization
1290 [] s - toggle SPACE and HARD SPACE visualization
1291 [] r - toggle trailing blanks visualization
1292 [] b - toggle SPACEs before TAB visualization
1293 [] l - toggle \"long lines\" visualization
1294 [] n - toggle NEWLINE visualization
1295 [] i - toggle indentation SPACEs visualization
1296 [] e - toggle empty line at bob and/or eob visualization
1297 [] a - toggle SPACEs after TAB visualization
1299 [] c - toggle color faces
1300 [] m - toggle visual mark
1302 x - restore `blank-chars' value
1303 z - restore `blank-style' value
1305 ? - display this text\n\n"
1306 "Text for blank toggle options.")
1309 (defconst blank-help-buffer-name
"*Blank Toggle Options*"
1310 "The buffer name for blank toggle options.")
1313 (defun blank-insert-option-mark (the-list the-value
)
1314 "Insert the option mark ('X' or ' ') in toggle options buffer."
1316 (dolist (sym the-list
)
1319 (insert (if (memq sym the-value
) "X" " "))))
1322 (defun blank-help-on (chars style
)
1323 "Display the blank toggle options."
1324 (unless (get-buffer blank-help-buffer-name
)
1325 (delete-other-windows)
1326 (let ((buffer (get-buffer-create blank-help-buffer-name
)))
1330 (insert blank-help-text
)
1331 (goto-char (point-min))
1332 (blank-insert-option-mark blank-chars-value-list chars
)
1333 (blank-insert-option-mark blank-style-value-list style
)
1334 (goto-char (point-min))
1335 (set-buffer-modified-p nil
)
1336 (let ((size (- (window-height)
1337 (max window-min-height
1338 (1+ (count-lines (point-min) (point-max)))))))
1340 (kill-buffer buffer
)
1341 (error "Frame height is too small; \
1342 can't split window to display blank toggle options"))
1343 (set-window-buffer (split-window nil size
) buffer
))))))
1346 (defun blank-help-off ()
1347 "Remove the buffer and window of the blank toggle options."
1348 (let ((buffer (get-buffer blank-help-buffer-name
)))
1350 (delete-windows-on buffer
)
1351 (kill-buffer buffer
))))
1354 (defun blank-interactive-char (local-p)
1355 "Interactive function to read a char and return a symbol.
1357 If LOCAL-P is non-nil, it uses a local context; otherwise, it
1358 uses a global context.
1360 It reads one of the following chars:
1363 t toggle TAB visualization
1364 s toggle SPACE and HARD SPACE visualization
1365 r toggle trailing blanks visualization
1366 b toggle SPACEs before TAB visualization
1367 l toggle \"long lines\" visualization
1368 n toggle NEWLINE visualization
1369 i toggle indentation SPACEs visualization
1370 e toggle empty line at bob and/or eob visualization
1371 a toggle SPACEs after TAB visualization
1372 c toggle color faces
1373 m toggle visual mark
1374 x restore `blank-chars' value
1375 z restore `blank-style' value
1376 ? display brief help
1378 See also `blank-toggle-option-alist'."
1379 (let* ((is-off (not (if local-p blank-mode global-blank-mode
)))
1380 (chars (cond (is-off blank-chars
) ; use default value
1381 (local-p blank-active-chars
)
1382 (t blank-toggle-chars
)))
1383 (style (cond (is-off blank-style
) ; use default value
1384 (local-p blank-active-style
)
1385 (t blank-toggle-style
)))
1387 (format "Blank Toggle %s (type ? for further options)-"
1388 (if local-p
"Local" "Global")))
1390 ;; read a valid option and get the corresponding symbol
1391 (save-window-excursion
1392 (condition-case data
1397 (setq ch
(read-char prompt
))
1400 (cdr (assq ch blank-toggle-option-alist
)))))
1403 (blank-help-on chars style
)
1406 (message " ")) ; clean echo area
1410 (error (error-message-string data
)))))
1411 (list sym
))) ; return the apropriate symbol
1414 (defun blank-toggle-list (local-p arg the-list default-list
1415 sym-restore sym-list
)
1416 "Toggle options in THE-LIST based on list ARG.
1418 If LOCAL-P is non-nil, it uses a local context; otherwise, it
1419 uses a global context.
1421 ARG is a list of options to be toggled.
1423 THE-LIST is a list of options. This list will be toggled and the
1424 resultant list will be returned.
1426 DEFAULT-LIST is the default list of options. It is used to
1427 restore the options in THE-LIST.
1429 SYM-RESTORE is the symbol which indicates to restore the options
1432 SYM-LIST is a list of valid options, used to check if the ARG's
1434 (unless (if local-p blank-mode global-blank-mode
)
1435 (setq the-list default-list
))
1436 (setq the-list
(copy-sequence the-list
)) ; keep original list
1437 (dolist (sym (if (listp arg
) arg
(list arg
)))
1439 ;; restore default values
1440 ((eq sym sym-restore
)
1441 (setq the-list default-list
))
1442 ;; toggle valid values
1443 ((memq sym sym-list
)
1444 (setq the-list
(if (memq sym the-list
)
1446 (cons sym the-list
))))))
1450 (defun blank-turn-on ()
1451 "Turn on blank visualization."
1452 (setq blank-active-style
(if (listp blank-style
)
1454 (list blank-style
)))
1455 (setq blank-active-chars
(if (listp blank-chars
)
1457 (list blank-chars
)))
1458 (when (memq 'color blank-active-style
)
1460 (when (memq 'mark blank-active-style
)
1461 (blank-display-char-on)))
1464 (defun blank-turn-off ()
1465 "Turn off blank visualization."
1466 (when (memq 'color blank-active-style
)
1468 (when (memq 'mark blank-active-style
)
1469 (blank-display-char-off)))
1472 (defun blank-color-on ()
1473 "Turn on color visualization."
1474 (when blank-active-chars
1475 (unless blank-font-lock
1476 (setq blank-font-lock t
1477 blank-font-lock-keywords
1478 (copy-sequence font-lock-keywords
)))
1479 ;; turn off font lock
1480 (setq blank-font-lock-mode font-lock-mode
)
1482 ;; add blank-mode color into font lock
1483 (when (memq 'spaces blank-active-chars
)
1484 (font-lock-add-keywords
1488 (list blank-space-regexp
1 blank-space t
)
1490 (list blank-hspace-regexp
1 blank-hspace t
))
1492 (when (memq 'tabs blank-active-chars
)
1493 (font-lock-add-keywords
1497 (list blank-tab-regexp
1 blank-tab t
))
1499 (when (memq 'trailing blank-active-chars
)
1500 (font-lock-add-keywords
1503 ;; Show trailing blanks
1504 (list (concat "\\(\\(" blank-trailing-regexp
"\\)+\\)$")
1505 1 blank-trailing t
))
1507 (when (memq 'lines blank-active-chars
)
1508 (font-lock-add-keywords
1511 ;; Show "long" lines
1512 (list (concat "^\\(.\\{" (int-to-string blank-line-length
)
1516 (when (memq 'space-before-tab blank-active-chars
)
1517 (font-lock-add-keywords
1520 ;; Show SPACEs before TAB
1521 (list blank-space-before-tab-regexp
1522 1 blank-space-before-tab t
))
1524 (when (memq 'indentation blank-active-chars
)
1525 (font-lock-add-keywords
1528 ;; Show indentation SPACEs
1529 (list blank-indentation-regexp
1530 1 blank-indentation t
))
1532 (when (memq 'empty blank-active-chars
)
1533 (font-lock-add-keywords
1536 ;; Show empty lines at beginning of buffer
1537 (list blank-empty-at-bob-regexp
1540 (font-lock-add-keywords
1543 ;; Show empty lines at end of buffer
1544 (list blank-empty-at-eob-regexp
1547 (when (memq 'space-after-tab blank-active-chars
)
1548 (font-lock-add-keywords
1551 ;; Show SPACEs after TAB
1552 (list blank-space-after-tab-regexp
1553 1 blank-space-after-tab t
))
1555 ;; now turn on font lock and highlight blanks
1556 (font-lock-mode 1)))
1559 (defun blank-color-off ()
1560 "Turn off color visualization."
1561 (when blank-active-chars
1562 ;; turn off font lock
1564 (when blank-font-lock
1565 (setq blank-font-lock nil
1566 font-lock-keywords blank-font-lock-keywords
))
1567 ;; restore original font lock state
1568 (font-lock-mode blank-font-lock-mode
)))
1571 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1572 ;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
1575 (defvar blank-display-table nil
1576 "Used to save a local display table.")
1577 (make-variable-buffer-local 'blank-display-table
)
1579 (defvar blank-display-table-was-local nil
1580 "Used to remember whether a buffer initially had a local display table or not.")
1581 (make-variable-buffer-local 'blank-display-table-was-local
)
1584 (defsubst blank-char-valid-p
(char)
1585 ;; This check should be improved!!!
1587 (char-valid-p char
)))
1590 (defun blank-legal-display-vector-p (vec)
1591 "Return true if every character in vector VEC can be displayed."
1592 (let ((i (length vec
)))
1594 (while (and (>= (setq i
(1- i
)) 0)
1595 (blank-char-valid-p (aref vec i
))))
1599 (defun blank-display-char-on ()
1600 "Turn on character display mapping."
1601 (when blank-display-mappings
1603 ;; Remember whether a buffer has a local display table.
1604 (unless blank-display-table-was-local
1605 (setq blank-display-table-was-local t
1607 (copy-sequence buffer-display-table
)))
1608 (unless buffer-display-table
1609 (setq buffer-display-table
(make-display-table)))
1610 (dolist (entry blank-display-mappings
)
1611 (setq vecs
(cdr entry
))
1612 ;; Get a displayable mapping.
1614 (not (blank-legal-display-vector-p (car vecs
))))
1615 (setq vecs
(cdr vecs
)))
1616 ;; Display a valid mapping.
1618 (setq vec
(copy-sequence (car vecs
)))
1620 ;; Any char except newline
1621 ((not (eq (car entry
) ?
\n))
1622 (aset buffer-display-table
(car entry
) vec
))
1623 ;; Newline char - display it
1624 ((memq 'newline blank-active-chars
)
1625 ;; Only insert face bits on NEWLINE char mapping to avoid
1626 ;; obstruction of other faces like TABs and (HARD) SPACEs
1627 ;; faces, font-lock faces, etc.
1628 (when (memq 'color blank-active-style
)
1629 (dotimes (i (length vec
))
1630 ;; Due to limitations of glyph representation, the char
1631 ;; code can not be above ?\x1FFFF. Probably, this will
1632 ;; be fixed after Emacs unicode merging.
1633 (or (eq (aref vec i
) ?
\n)
1634 (> (aref vec i
) #x1FFFF
)
1635 (aset vec i
(make-glyph-code (aref vec i
)
1638 (aset buffer-display-table
(car entry
) vec
))
1639 ;; Newline char - don't display it
1645 (defun blank-display-char-off ()
1646 "Turn off character display mapping."
1647 (and blank-display-mappings
1648 blank-display-table-was-local
1649 (setq blank-display-table-was-local nil
1650 buffer-display-table blank-display-table
)))
1653 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1656 (provide 'blank-mode
)
1659 (run-hooks 'blank-load-hook
)
1662 ;; arch-tag: 1b1e2500-dbd4-4a26-8f7a-5a5edfd3c97e
1663 ;;; blank-mode.el ends here