(define-ccl-program): Add `doc-string' declaration.
[bpt/emacs.git] / lisp / whitespace.el
CommitLineData
c9dff4e3 1;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE
30d0ade9
VJL
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
2788143d 9;; Version: 11.1
30d0ade9
VJL
10;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
11
12;; This file is part of GNU Emacs.
13
eb3fa2cf
GM
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 by
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
30d0ade9 18
eb3fa2cf
GM
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
30d0ade9
VJL
23
24;; You should have received a copy of the GNU General Public License
eb3fa2cf 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
30d0ade9
VJL
26
27;;; Commentary:
28
29;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30;;
31;; Introduction
32;; ------------
33;;
040f578c 34;; This package is a minor mode to visualize blanks (TAB, (HARD) SPACE
30d0ade9
VJL
35;; and NEWLINE).
36;;
c9dff4e3 37;; whitespace uses two ways to visualize blanks: faces and display
30d0ade9
VJL
38;; table.
39;;
40;; * Faces are used to highlight the background with a color.
c9dff4e3 41;; whitespace uses font-lock to highlight blank characters.
30d0ade9
VJL
42;;
43;; * Display table changes the way a character is displayed, that is,
44;; it provides a visual mark for characters, for example, at the end
45;; of line (?\xB6), at SPACEs (?\xB7) and at TABs (?\xBB).
46;;
556885cd
VJL
47;; The `whitespace-style' variable selects which way blanks are
48;; visualized.
30d0ade9 49;;
c9dff4e3 50;; Note that when whitespace is turned on, whitespace saves the
30d0ade9 51;; font-lock state, that is, if font-lock is on or off. And
c9dff4e3
VJL
52;; whitespace restores the font-lock state when it is turned off. So,
53;; if whitespace is turned on and font-lock is off, whitespace also
30d0ade9 54;; turns on the font-lock to highlight blanks, but the font-lock will
c9dff4e3
VJL
55;; be turned off when whitespace is turned off. Thus, turn on
56;; font-lock before whitespace is on, if you want that font-lock
57;; continues on after whitespace is turned off.
30d0ade9 58;;
c9dff4e3 59;; When whitespace is on, it takes care of highlighting some special
30d0ade9
VJL
60;; characters over the default mechanism of `nobreak-char-display'
61;; (which see) and `show-trailing-whitespace' (which see).
62;;
c9dff4e3 63;; There are two ways of using whitespace: local and global.
30d0ade9 64;;
c9dff4e3 65;; * Local whitespace affects only the current buffer.
30d0ade9 66;;
c9dff4e3
VJL
67;; * Global whitespace affects all current and future buffers. That
68;; is, if you turn on global whitespace and then create a new
69;; buffer, the new buffer will also have whitespace on. The
70;; `whitespace-global-modes' variable controls which major-mode will
71;; be automagically turned on.
30d0ade9
VJL
72;;
73;; You can mix the local and global usage without any conflict. But
c9dff4e3
VJL
74;; local whitespace has priority over global whitespace. Whitespace
75;; mode is active in a buffer if you have enabled it in that buffer or
76;; if you have enabled it globally.
30d0ade9 77;;
c9dff4e3 78;; When global and local whitespace are on:
30d0ade9 79;;
c9dff4e3 80;; * if local whitespace is turned off, whitespace is turned off for
30d0ade9
VJL
81;; the current buffer only.
82;;
c9dff4e3
VJL
83;; * if global whitespace is turned off, whitespace continues on only
84;; in the buffers in which local whitespace is on.
30d0ade9 85;;
c9dff4e3 86;; To use whitespace, insert in your ~/.emacs:
30d0ade9 87;;
c9dff4e3 88;; (require 'whitespace-mode)
30d0ade9 89;;
c9dff4e3
VJL
90;; Or autoload at least one of the commands`whitespace-mode',
91;; `whitespace-toggle-options', `global-whitespace-mode' or
92;; `global-whitespace-toggle-options'. For example:
30d0ade9 93;;
c9dff4e3
VJL
94;; (autoload 'whitespace-mode "whitespace"
95;; "Toggle whitespace visualization." t)
96;; (autoload 'whitespace-toggle-options "whitespace"
97;; "Toggle local `whitespace-mode' options." t)
30d0ade9 98;;
c9dff4e3 99;; whitespace was inspired by:
30d0ade9 100;;
97a739d5
VJL
101;; whitespace.el Rajesh Vaidheeswarran <rv@gnu.org>
102;; Warn about and clean bogus whitespaces in the file
103;; (inspired the idea to warn and clean some blanks)
c9dff4e3
VJL
104;; This was the original `whitespace.el' which was replaced by
105;; `blank-mode.el'. And later `blank-mode.el' was renamed to
106;; `whitespace.el'.
97a739d5 107;;
30d0ade9
VJL
108;; show-whitespace-mode.el Aurelien Tisne <aurelien.tisne@free.fr>
109;; Simple mode to highlight whitespaces
110;; (inspired the idea to use font-lock)
111;;
112;; whitespace-mode.el Lawrence Mitchell <wence@gmx.li>
113;; Major mode for editing Whitespace
114;; (inspired the idea to use display table)
115;;
116;; visws.el Miles Bader <miles@gnu.org>
117;; Make whitespace visible
118;; (handle display table, his code was modified, but the main
119;; idea was kept)
120;;
121;;
c9dff4e3 122;; Using whitespace
30d0ade9
VJL
123;; ----------------
124;;
125;; There is no problem if you mix local and global minor mode usage.
126;;
c9dff4e3
VJL
127;; * LOCAL whitespace:
128;; + To toggle whitespace options locally, type:
30d0ade9 129;;
c9dff4e3 130;; M-x whitespace-toggle-options RET
30d0ade9 131;;
c9dff4e3 132;; + To activate whitespace locally, type:
30d0ade9 133;;
c9dff4e3 134;; C-u 1 M-x whitespace-mode RET
30d0ade9 135;;
c9dff4e3 136;; + To deactivate whitespace locally, type:
30d0ade9 137;;
c9dff4e3 138;; C-u 0 M-x whitespace-mode RET
30d0ade9 139;;
c9dff4e3 140;; + To toggle whitespace locally, type:
30d0ade9 141;;
c9dff4e3 142;; M-x whitespace-mode RET
30d0ade9 143;;
c9dff4e3
VJL
144;; * GLOBAL whitespace:
145;; + To toggle whitespace options globally, type:
30d0ade9 146;;
c9dff4e3 147;; M-x global-whitespace-toggle-options RET
30d0ade9 148;;
c9dff4e3 149;; + To activate whitespace globally, type:
30d0ade9 150;;
c9dff4e3 151;; C-u 1 M-x global-whitespace-mode RET
30d0ade9 152;;
c9dff4e3 153;; + To deactivate whitespace globally, type:
30d0ade9 154;;
c9dff4e3 155;; C-u 0 M-x global-whitespace-mode RET
30d0ade9 156;;
c9dff4e3 157;; + To toggle whitespace globally, type:
30d0ade9 158;;
c9dff4e3 159;; M-x global-whitespace-mode RET
30d0ade9 160;;
97a739d5
VJL
161;; There are also the following useful commands:
162;;
94dc593f
VJL
163;; `whitespace-report'
164;; Report some blank problems in buffer.
165;;
166;; `whitespace-report-region'
167;; Report some blank problems in a region.
168;;
c9dff4e3 169;; `whitespace-cleanup'
97a739d5
VJL
170;; Cleanup some blank problems in all buffer or at region.
171;;
c9dff4e3 172;; `whitespace-cleanup-region'
97a739d5
VJL
173;; Cleanup some blank problems at region.
174;;
175;; The problems, which are cleaned up, are:
176;;
177;; 1. empty lines at beginning of buffer.
178;; 2. empty lines at end of buffer.
ae68f2d8
VJL
179;; If `whitespace-style' includes the value `empty', remove all
180;; empty lines at beginning and/or end of buffer.
97a739d5
VJL
181;;
182;; 3. 8 or more SPACEs at beginning of line.
ae68f2d8 183;; If `whitespace-style' includes the value `indentation':
55d1cfe8
VJL
184;; replace 8 or more SPACEs at beginning of line by TABs, if
185;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
186;; SPACEs.
ae68f2d8
VJL
187;; If `whitespace-style' includes the value `indentation::tab',
188;; replace 8 or more SPACEs at beginning of line by TABs.
189;; If `whitespace-style' includes the value `indentation::space',
190;; replace TABs by SPACEs.
97a739d5
VJL
191;;
192;; 4. SPACEs before TAB.
ae68f2d8
VJL
193;; If `whitespace-style' includes the value `space-before-tab':
194;; replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
195;; otherwise, replace TABs by SPACEs.
196;; If `whitespace-style' includes the value
55d1cfe8 197;; `space-before-tab::tab', replace SPACEs by TABs.
ae68f2d8 198;; If `whitespace-style' includes the value
55d1cfe8 199;; `space-before-tab::space', replace TABs by SPACEs.
97a739d5
VJL
200;;
201;; 5. SPACEs or TABs at end of line.
ae68f2d8
VJL
202;; If `whitespace-style' includes the value `trailing', remove all
203;; SPACEs or TABs at end of line.
97a739d5
VJL
204;;
205;; 6. 8 or more SPACEs after TAB.
ae68f2d8
VJL
206;; If `whitespace-style' includes the value `space-after-tab':
207;; replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
208;; otherwise, replace TABs by SPACEs.
209;; If `whitespace-style' includes the value `space-after-tab::tab',
210;; replace SPACEs by TABs.
211;; If `whitespace-style' includes the value
55d1cfe8 212;; `space-after-tab::space', replace TABs by SPACEs.
97a739d5 213;;
30d0ade9
VJL
214;;
215;; Hooks
216;; -----
217;;
c9dff4e3 218;; whitespace has the following hook variables:
30d0ade9 219;;
c9dff4e3
VJL
220;; `whitespace-mode-hook'
221;; It is evaluated always when whitespace is turned on locally.
30d0ade9 222;;
c9dff4e3
VJL
223;; `global-whitespace-mode-hook'
224;; It is evaluated always when whitespace is turned on globally.
30d0ade9 225;;
c9dff4e3
VJL
226;; `whitespace-load-hook'
227;; It is evaluated after whitespace package is loaded.
30d0ade9
VJL
228;;
229;;
230;; Options
231;; -------
232;;
c9dff4e3 233;; Below it's shown a brief description of whitespace options, please,
30d0ade9
VJL
234;; see the options declaration in the code for a long documentation.
235;;
ae68f2d8
VJL
236;; `whitespace-style' Specify which kind of blank is
237;; visualized.
30d0ade9 238;;
c9dff4e3 239;; `whitespace-space' Face used to visualize SPACE.
30d0ade9 240;;
c9dff4e3 241;; `whitespace-hspace' Face used to visualize HARD SPACE.
30d0ade9 242;;
c9dff4e3 243;; `whitespace-tab' Face used to visualize TAB.
30d0ade9 244;;
c9dff4e3 245;; `whitespace-newline' Face used to visualize NEWLINE char
30d0ade9
VJL
246;; mapping.
247;;
c9dff4e3 248;; `whitespace-trailing' Face used to visualize trailing
30d0ade9
VJL
249;; blanks.
250;;
c9dff4e3 251;; `whitespace-line' Face used to visualize "long" lines.
30d0ade9 252;;
c9dff4e3
VJL
253;; `whitespace-space-before-tab' Face used to visualize SPACEs
254;; before TAB.
30d0ade9 255;;
c9dff4e3 256;; `whitespace-indentation' Face used to visualize 8 or more
97a739d5
VJL
257;; SPACEs at beginning of line.
258;;
c9dff4e3 259;; `whitespace-empty' Face used to visualize empty lines at
97a739d5
VJL
260;; beginning and/or end of buffer.
261;;
c9dff4e3 262;; `whitespace-space-after-tab' Face used to visualize 8 or more
97a739d5
VJL
263;; SPACEs after TAB.
264;;
c9dff4e3 265;; `whitespace-space-regexp' Specify SPACE characters regexp.
30d0ade9 266;;
c9dff4e3 267;; `whitespace-hspace-regexp' Specify HARD SPACE characters regexp.
30d0ade9 268;;
c9dff4e3 269;; `whitespace-tab-regexp' Specify TAB characters regexp.
30d0ade9 270;;
c9dff4e3 271;; `whitespace-trailing-regexp' Specify trailing characters regexp.
30d0ade9 272;;
c9dff4e3 273;; `whitespace-space-before-tab-regexp' Specify SPACEs before TAB
30d0ade9
VJL
274;; regexp.
275;;
c9dff4e3
VJL
276;; `whitespace-indentation-regexp' Specify regexp for 8 or more
277;; SPACEs at beginning of line.
97a739d5 278;;
c9dff4e3
VJL
279;; `whitespace-empty-at-bob-regexp' Specify regexp for empty lines
280;; at beginning of buffer.
97a739d5 281;;
c9dff4e3
VJL
282;; `whitespace-empty-at-eob-regexp' Specify regexp for empty lines
283;; at end of buffer.
97a739d5 284;;
c9dff4e3 285;; `whitespace-space-after-tab-regexp' Specify regexp for 8 or more
97a739d5
VJL
286;; SPACEs after TAB.
287;;
c9dff4e3 288;; `whitespace-line-column' Specify column beyond which the line
30d0ade9
VJL
289;; is highlighted.
290;;
c9dff4e3
VJL
291;; `whitespace-display-mappings' Specify an alist of mappings
292;; for displaying characters.
30d0ade9 293;;
4a4b61e2
VJL
294;; `whitespace-global-modes' Modes for which global
295;; `whitespace-mode' is automagically
296;; turned on.
30d0ade9 297;;
94dc593f
VJL
298;; `whitespace-action' Specify which action is taken when a
299;; buffer is visited, killed or written.
300;;
30d0ade9
VJL
301;;
302;; Acknowledgements
303;; ----------------
304;;
55d1cfe8
VJL
305;; Thanks to Stephen Deasey <sdeasey@gmail.com> for the
306;; `indent-tabs-mode' usage suggestion.
307;;
308;; Thanks to Eric Cooper <ecc@cmu.edu> for the suggestion to have hook
309;; actions when buffer is written or killed as the original whitespace
310;; package had.
94dc593f 311;;
9f3b76d5
VJL
312;; Thanks to nschum (EmacsWiki) for the idea about highlight "long"
313;; lines tail. See EightyColumnRule (EmacsWiki).
314;;
30d0ade9
VJL
315;; Thanks to Juri Linkov <juri@jurta.org> for suggesting:
316;; * `define-minor-mode'.
c9dff4e3 317;; * `global-whitespace-*' name for global commands.
30d0ade9
VJL
318;;
319;; Thanks to Robert J. Chassell <bob@gnu.org> for doc fix and testing.
320;;
321;; Thanks to Drew Adams <drew.adams@oracle.com> for toggle commands
322;; suggestion.
323;;
324;; Thanks to Antti Kaihola <antti.kaihola@linux-aktivaattori.org> for
325;; helping to fix `find-file-hooks' reference.
326;;
327;; Thanks to Andreas Roehler <andreas.roehler@easy-emacs.de> for
328;; indicating defface byte-compilation warnings.
329;;
330;; Thanks to TimOCallaghan (EmacsWiki) for the idea about highlight
9f3b76d5 331;; "long" lines. See EightyColumnRule (EmacsWiki).
30d0ade9
VJL
332;;
333;; Thanks to Yanghui Bian <yanghuibian@gmail.com> for indicating a new
334;; newline character mapping.
335;;
336;; Thanks to Pete Forman <pete.forman@westgeo.com> for indicating
c9dff4e3 337;; whitespace-mode.el on XEmacs.
30d0ade9
VJL
338;;
339;; Thanks to Miles Bader <miles@gnu.org> for handling display table via
340;; visws.el (his code was modified, but the main idea was kept).
341;;
342;; Thanks to:
c9dff4e3 343;; Rajesh Vaidheeswarran <rv@gnu.org> (original) whitespace.el
30d0ade9
VJL
344;; Aurelien Tisne <aurelien.tisne@free.fr> show-whitespace-mode.el
345;; Lawrence Mitchell <wence@gmx.li> whitespace-mode.el
346;; Miles Bader <miles@gnu.org> visws.el
347;; And to all people who contributed with them.
348;;
349;;
350;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
351
352;;; code:
353
354\f
355;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
356;;;; User Variables:
357
358
359;;; Interface to the command system
360
361
c9dff4e3 362(defgroup whitespace nil
040f578c 363 "Visualize blanks (TAB, (HARD) SPACE and NEWLINE)."
c9dff4e3 364 :link '(emacs-library-link :tag "Source Lisp File" "whitespace.el")
b502217b 365 :version "23.1"
30d0ade9
VJL
366 :group 'wp
367 :group 'data)
368
369
ae68f2d8 370(defcustom whitespace-style
97a739d5 371 '(tabs spaces trailing lines space-before-tab newline
ae68f2d8
VJL
372 indentation empty space-after-tab
373 space-mark tab-mark newline-mark)
374 "*Specify which kind of blank is visualized.
30d0ade9 375
b502217b 376It's a list containing some or all of the following values:
30d0ade9 377
ae68f2d8 378 trailing trailing blanks are visualized via faces.
30d0ade9 379
ae68f2d8 380 tabs TABs are visualized via faces.
30d0ade9 381
ae68f2d8
VJL
382 spaces SPACEs and HARD SPACEs are visualized via
383 faces.
30d0ade9 384
9f3b76d5 385 lines lines whose have columns beyond
ae68f2d8
VJL
386 `whitespace-line-column' are highlighted via
387 faces .
9f3b76d5 388 Whole line is highlighted.
ae68f2d8
VJL
389 It has precedence over `lines-tail' (see
390 below).
9f3b76d5
VJL
391
392 lines-tail lines whose have columns beyond
ae68f2d8
VJL
393 `whitespace-line-column' are highlighted via
394 faces.
9f3b76d5 395 But only the part of line which goes
c9dff4e3 396 beyond `whitespace-line-column' column.
9f3b76d5 397 It has effect only if `lines' (see above)
ae68f2d8 398 is not present in `whitespace-style'.
30d0ade9 399
ae68f2d8 400 newline NEWLINEs are visualized via faces.
30d0ade9 401
97a739d5 402 empty empty lines at beginning and/or end of buffer
ae68f2d8 403 are visualized via faces.
97a739d5 404
55d1cfe8 405 indentation::tab 8 or more SPACEs at beginning of line are
ae68f2d8 406 visualized via faces.
55d1cfe8 407
ae68f2d8
VJL
408 indentation::space TABs at beginning of line are visualized via
409 faces.
97a739d5 410
55d1cfe8
VJL
411 indentation 8 or more SPACEs at beginning of line are
412 visualized, if `indent-tabs-mode' (which see)
413 is non-nil; otherwise, TABs at beginning of
ae68f2d8 414 line are visualized via faces.
55d1cfe8
VJL
415
416 space-after-tab::tab 8 or more SPACEs after a TAB are
ae68f2d8 417 visualized via faces.
55d1cfe8
VJL
418
419 space-after-tab::space TABs are visualized when occurs 8 or
ae68f2d8 420 more SPACEs after a TAB via faces.
55d1cfe8
VJL
421
422 space-after-tab 8 or more SPACEs after a TAB are
423 visualized, if `indent-tabs-mode'
424 (which see) is non-nil; otherwise,
ae68f2d8 425 the TABs are visualized via faces.
55d1cfe8 426
ae68f2d8
VJL
427 space-before-tab::tab SPACEs before TAB are visualized via
428 faces.
30d0ade9 429
55d1cfe8 430 space-before-tab::space TABs are visualized when occurs SPACEs
ae68f2d8 431 before TAB via faces.
30d0ade9 432
55d1cfe8
VJL
433 space-before-tab SPACEs before TAB are visualized, if
434 `indent-tabs-mode' (which see) is
435 non-nil; otherwise, the TABs are
ae68f2d8
VJL
436 visualized via faces.
437
438 space-mark SPACEs and HARD SPACEs are visualized via
439 display table.
440
441 tab-mark TABs are visualized via display table.
442
443 newline-mark NEWLINEs are visualized via display table.
55d1cfe8
VJL
444
445Any other value is ignored.
446
ae68f2d8
VJL
447If nil, don't visualize TABs, (HARD) SPACEs and NEWLINEs via faces and
448via display table.
55d1cfe8
VJL
449
450There is an evaluation order for some values, if some values are
ae68f2d8 451included in `whitespace-style' list. For example, if
55d1cfe8 452indentation, indentation::tab and/or indentation::space are
ae68f2d8
VJL
453included in `whitespace-style' list. The evaluation order for
454these values is:
55d1cfe8
VJL
455
456 * For indentation:
457 1. indentation
458 2. indentation::tab
459 3. indentation::space
460
461 * For SPACEs after TABs:
462 1. space-after-tab
463 2. space-after-tab::tab
464 3. space-after-tab::space
465
466 * For SPACEs before TABs:
467 1. space-before-tab
468 2. space-before-tab::tab
469 3. space-before-tab::space
470
471So, for example, if indentation and indentation::space are
ae68f2d8
VJL
472included in `whitespace-style' list, the indentation value is
473evaluated instead of indentation::space value.
474
475See also `whitespace-display-mappings' for documentation."
476 :type '(repeat :tag "Kind of Blank"
55d1cfe8 477 (choice :tag "Kind of Blank Face"
ae68f2d8 478 (const :tag "(Face) Trailing TABs, SPACEs and HARD SPACEs"
30d0ade9 479 trailing)
ae68f2d8
VJL
480 (const :tag "(Face) SPACEs and HARD SPACEs"
481 spaces)
482 (const :tag "(Face) TABs" tabs)
483 (const :tag "(Face) Lines" lines)
484 (const :tag "(Face) SPACEs before TAB"
30d0ade9 485 space-before-tab)
ae68f2d8
VJL
486 (const :tag "(Face) NEWLINEs" newline)
487 (const :tag "(Face) Indentation SPACEs"
488 indentation)
489 (const :tag "(Face) Empty Lines At BOB And/Or EOB"
97a739d5 490 empty)
ae68f2d8
VJL
491 (const :tag "(Face) SPACEs after TAB"
492 space-after-tab)
493 (const :tag "(Mark) SPACEs and HARD SPACEs"
494 space-mark)
495 (const :tag "(Mark) TABs" tab-mark)
496 (const :tag "(Mark) NEWLINEs" newline-mark)))
c9dff4e3 497 :group 'whitespace)
30d0ade9
VJL
498
499
c9dff4e3 500(defcustom whitespace-space 'whitespace-space
040f578c 501 "*Symbol face used to visualize SPACE.
30d0ade9 502
ae68f2d8 503Used when `whitespace-style' includes the value `spaces'."
30d0ade9 504 :type 'face
c9dff4e3 505 :group 'whitespace)
30d0ade9
VJL
506
507
c9dff4e3 508(defface whitespace-space
30d0ade9
VJL
509 '((((class color) (background dark))
510 (:background "grey20" :foreground "aquamarine3"))
511 (((class color) (background light))
512 (:background "LightYellow" :foreground "aquamarine3"))
513 (t (:inverse-video t)))
040f578c 514 "Face used to visualize SPACE."
c9dff4e3 515 :group 'whitespace)
30d0ade9
VJL
516
517
c9dff4e3 518(defcustom whitespace-hspace 'whitespace-hspace
040f578c 519 "*Symbol face used to visualize HARD SPACE.
30d0ade9 520
ae68f2d8 521Used when `whitespace-style' includes the value `spaces'."
30d0ade9 522 :type 'face
c9dff4e3 523 :group 'whitespace)
30d0ade9
VJL
524
525
c9dff4e3 526(defface whitespace-hspace ; 'nobreak-space
30d0ade9
VJL
527 '((((class color) (background dark))
528 (:background "grey24" :foreground "aquamarine3"))
529 (((class color) (background light))
530 (:background "LemonChiffon3" :foreground "aquamarine3"))
531 (t (:inverse-video t)))
040f578c 532 "Face used to visualize HARD SPACE."
c9dff4e3 533 :group 'whitespace)
30d0ade9
VJL
534
535
c9dff4e3 536(defcustom whitespace-tab 'whitespace-tab
040f578c 537 "*Symbol face used to visualize TAB.
30d0ade9 538
ae68f2d8 539Used when `whitespace-style' includes the value `tabs'."
30d0ade9 540 :type 'face
c9dff4e3 541 :group 'whitespace)
30d0ade9
VJL
542
543
c9dff4e3 544(defface whitespace-tab
30d0ade9
VJL
545 '((((class color) (background dark))
546 (:background "grey22" :foreground "aquamarine3"))
547 (((class color) (background light))
548 (:background "beige" :foreground "aquamarine3"))
549 (t (:inverse-video t)))
040f578c 550 "Face used to visualize TAB."
c9dff4e3 551 :group 'whitespace)
30d0ade9
VJL
552
553
c9dff4e3 554(defcustom whitespace-newline 'whitespace-newline
040f578c 555 "*Symbol face used to visualize NEWLINE char mapping.
30d0ade9 556
c9dff4e3 557See `whitespace-display-mappings'.
30d0ade9 558
ae68f2d8
VJL
559Used when `whitespace-style' includes the values `newline-mark'
560and `newline'."
30d0ade9 561 :type 'face
c9dff4e3 562 :group 'whitespace)
30d0ade9
VJL
563
564
c9dff4e3 565(defface whitespace-newline
30d0ade9
VJL
566 '((((class color) (background dark))
567 (:background "grey26" :foreground "aquamarine3" :bold t))
568 (((class color) (background light))
569 (:background "linen" :foreground "aquamarine3" :bold t))
570 (t (:bold t :underline t)))
040f578c 571 "Face used to visualize NEWLINE char mapping.
30d0ade9 572
c9dff4e3
VJL
573See `whitespace-display-mappings'."
574 :group 'whitespace)
30d0ade9
VJL
575
576
c9dff4e3 577(defcustom whitespace-trailing 'whitespace-trailing
f5c06341 578 "*Symbol face used to visualize trailing blanks.
30d0ade9 579
ae68f2d8 580Used when `whitespace-style' includes the value `trailing'."
30d0ade9 581 :type 'face
c9dff4e3 582 :group 'whitespace)
30d0ade9
VJL
583
584
c9dff4e3 585(defface whitespace-trailing ; 'trailing-whitespace
30d0ade9
VJL
586 '((((class mono)) (:inverse-video t :bold t :underline t))
587 (t (:background "red1" :foreground "yellow" :bold t)))
040f578c 588 "Face used to visualize trailing blanks."
c9dff4e3 589 :group 'whitespace)
30d0ade9
VJL
590
591
c9dff4e3 592(defcustom whitespace-line 'whitespace-line
040f578c 593 "*Symbol face used to visualize \"long\" lines.
30d0ade9 594
c9dff4e3 595See `whitespace-line-column'.
30d0ade9 596
ae68f2d8 597Used when `whitespace-style' includes the value `line'."
30d0ade9 598 :type 'face
c9dff4e3 599 :group 'whitespace)
30d0ade9
VJL
600
601
c9dff4e3 602(defface whitespace-line
30d0ade9
VJL
603 '((((class mono)) (:inverse-video t :bold t :underline t))
604 (t (:background "gray20" :foreground "violet")))
040f578c 605 "Face used to visualize \"long\" lines.
30d0ade9 606
c9dff4e3
VJL
607See `whitespace-line-column'."
608 :group 'whitespace)
30d0ade9
VJL
609
610
c9dff4e3 611(defcustom whitespace-space-before-tab 'whitespace-space-before-tab
040f578c 612 "*Symbol face used to visualize SPACEs before TAB.
30d0ade9 613
ae68f2d8 614Used when `whitespace-style' includes the value `space-before-tab'."
30d0ade9 615 :type 'face
c9dff4e3 616 :group 'whitespace)
30d0ade9
VJL
617
618
c9dff4e3 619(defface whitespace-space-before-tab
30d0ade9
VJL
620 '((((class mono)) (:inverse-video t :bold t :underline t))
621 (t (:background "DarkOrange" :foreground "firebrick")))
040f578c 622 "Face used to visualize SPACEs before TAB."
c9dff4e3 623 :group 'whitespace)
30d0ade9
VJL
624
625
c9dff4e3 626(defcustom whitespace-indentation 'whitespace-indentation
97a739d5
VJL
627 "*Symbol face used to visualize 8 or more SPACEs at beginning of line.
628
ae68f2d8 629Used when `whitespace-style' includes the value `indentation'."
97a739d5 630 :type 'face
c9dff4e3 631 :group 'whitespace)
97a739d5
VJL
632
633
c9dff4e3 634(defface whitespace-indentation
97a739d5
VJL
635 '((((class mono)) (:inverse-video t :bold t :underline t))
636 (t (:background "yellow" :foreground "firebrick")))
637 "Face used to visualize 8 or more SPACEs at beginning of line."
c9dff4e3 638 :group 'whitespace)
97a739d5
VJL
639
640
c9dff4e3 641(defcustom whitespace-empty 'whitespace-empty
97a739d5
VJL
642 "*Symbol face used to visualize empty lines at beginning and/or end of buffer.
643
ae68f2d8 644Used when `whitespace-style' includes the value `empty'."
97a739d5 645 :type 'face
c9dff4e3 646 :group 'whitespace)
97a739d5
VJL
647
648
c9dff4e3 649(defface whitespace-empty
97a739d5
VJL
650 '((((class mono)) (:inverse-video t :bold t :underline t))
651 (t (:background "yellow" :foreground "firebrick")))
652 "Face used to visualize empty lines at beginning and/or end of buffer."
c9dff4e3 653 :group 'whitespace)
97a739d5
VJL
654
655
c9dff4e3 656(defcustom whitespace-space-after-tab 'whitespace-space-after-tab
97a739d5
VJL
657 "*Symbol face used to visualize 8 or more SPACEs after TAB.
658
ae68f2d8 659Used when `whitespace-style' includes the value `space-after-tab'."
97a739d5 660 :type 'face
c9dff4e3 661 :group 'whitespace)
97a739d5
VJL
662
663
c9dff4e3 664(defface whitespace-space-after-tab
97a739d5
VJL
665 '((((class mono)) (:inverse-video t :bold t :underline t))
666 (t (:background "yellow" :foreground "firebrick")))
667 "Face used to visualize 8 or more SPACEs after TAB."
c9dff4e3 668 :group 'whitespace)
97a739d5
VJL
669
670
c9dff4e3 671(defcustom whitespace-hspace-regexp
30d0ade9
VJL
672 "\\(\\(\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)"
673 "*Specify HARD SPACE characters regexp.
674
b502217b 675If you're using `mule' package, there may be other characters besides:
30d0ade9
VJL
676
677 \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \"\\xF20\"
678
040f578c 679that should be considered HARD SPACE.
30d0ade9
VJL
680
681Here are some examples:
682
683 \"\\\\(^\\xA0+\\\\)\" \
040f578c 684visualize only leading HARD SPACEs.
30d0ade9 685 \"\\\\(\\xA0+$\\\\)\" \
040f578c 686visualize only trailing HARD SPACEs.
30d0ade9 687 \"\\\\(^\\xA0+\\\\|\\xA0+$\\\\)\" \
040f578c 688visualize leading and/or trailing HARD SPACEs.
30d0ade9 689 \"\\t\\\\(\\xA0+\\\\)\\t\" \
040f578c 690visualize only HARD SPACEs between TABs.
30d0ade9
VJL
691
692NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
693 Use exactly one pair of enclosing \\\\( and \\\\).
694
ae68f2d8 695Used when `whitespace-style' includes `spaces'."
30d0ade9 696 :type '(regexp :tag "HARD SPACE Chars")
c9dff4e3 697 :group 'whitespace)
30d0ade9
VJL
698
699
c9dff4e3 700(defcustom whitespace-space-regexp "\\( +\\)"
30d0ade9
VJL
701 "*Specify SPACE characters regexp.
702
b502217b 703If you're using `mule' package, there may be other characters
040f578c 704besides \" \" that should be considered SPACE.
30d0ade9
VJL
705
706Here are some examples:
707
040f578c
VJL
708 \"\\\\(^ +\\\\)\" visualize only leading SPACEs.
709 \"\\\\( +$\\\\)\" visualize only trailing SPACEs.
30d0ade9 710 \"\\\\(^ +\\\\| +$\\\\)\" \
040f578c
VJL
711visualize leading and/or trailing SPACEs.
712 \"\\t\\\\( +\\\\)\\t\" visualize only SPACEs between TABs.
30d0ade9
VJL
713
714NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
715 Use exactly one pair of enclosing \\\\( and \\\\).
716
ae68f2d8 717Used when `whitespace-style' includes `spaces'."
30d0ade9 718 :type '(regexp :tag "SPACE Chars")
c9dff4e3 719 :group 'whitespace)
30d0ade9
VJL
720
721
c9dff4e3 722(defcustom whitespace-tab-regexp "\\(\t+\\)"
30d0ade9
VJL
723 "*Specify TAB characters regexp.
724
b502217b 725If you're using `mule' package, there may be other characters
040f578c 726besides \"\\t\" that should be considered TAB.
30d0ade9
VJL
727
728Here are some examples:
729
040f578c
VJL
730 \"\\\\(^\\t+\\\\)\" visualize only leading TABs.
731 \"\\\\(\\t+$\\\\)\" visualize only trailing TABs.
30d0ade9 732 \"\\\\(^\\t+\\\\|\\t+$\\\\)\" \
040f578c
VJL
733visualize leading and/or trailing TABs.
734 \" \\\\(\\t+\\\\) \" visualize only TABs between SPACEs.
30d0ade9
VJL
735
736NOTE: Enclose always by \\\\( and \\\\) the elements to highlight.
737 Use exactly one pair of enclosing \\\\( and \\\\).
738
ae68f2d8 739Used when `whitespace-style' includes `tabs'."
30d0ade9 740 :type '(regexp :tag "TAB Chars")
c9dff4e3 741 :group 'whitespace)
30d0ade9
VJL
742
743
c9dff4e3 744(defcustom whitespace-trailing-regexp
2788143d 745 "\\(\\(\t\\| \\|\xA0\\|\x8A0\\|\x920\\|\xE20\\|\xF20\\)+\\)$"
30d0ade9
VJL
746 "*Specify trailing characters regexp.
747
b502217b 748If you're using `mule' package, there may be other characters besides:
30d0ade9
VJL
749
750 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
751\"\\xF20\"
752
040f578c 753that should be considered blank.
30d0ade9 754
385da4e7 755NOTE: Enclose always by \"\\\\(\" and \"\\\\)$\" the elements to highlight.
2788143d 756 Use exactly one pair of enclosing elements above.
30d0ade9 757
ae68f2d8 758Used when `whitespace-style' includes `trailing'."
30d0ade9 759 :type '(regexp :tag "Trailing Chars")
c9dff4e3 760 :group 'whitespace)
30d0ade9
VJL
761
762
55d1cfe8 763(defcustom whitespace-space-before-tab-regexp "\\( +\\)\\(\t+\\)"
30d0ade9
VJL
764 "*Specify SPACEs before TAB regexp.
765
b502217b 766If you're using `mule' package, there may be other characters besides:
30d0ade9
VJL
767
768 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
769\"\\xF20\"
770
040f578c 771that should be considered blank.
30d0ade9 772
ae68f2d8 773Used when `whitespace-style' includes `space-before-tab',
55d1cfe8 774`space-before-tab::tab' or `space-before-tab::space'."
30d0ade9 775 :type '(regexp :tag "SPACEs Before TAB")
c9dff4e3 776 :group 'whitespace)
30d0ade9
VJL
777
778
c9dff4e3 779(defcustom whitespace-indentation-regexp
55d1cfe8
VJL
780 '("^\t*\\(\\( \\{%d\\}\\)+\\)[^\n\t]"
781 . "^ *\\(\t+\\)[^\n]")
97a739d5
VJL
782 "*Specify regexp for 8 or more SPACEs at beginning of line.
783
55d1cfe8
VJL
784It is a cons where the cons car is used for SPACEs visualization
785and the cons cdr is used for TABs visualization.
786
b502217b 787If you're using `mule' package, there may be other characters besides:
97a739d5
VJL
788
789 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
790\"\\xF20\"
791
792that should be considered blank.
793
ae68f2d8 794Used when `whitespace-style' includes `indentation',
55d1cfe8
VJL
795`indentation::tab' or `indentation::space'."
796 :type '(cons (regexp :tag "Indentation SPACEs")
797 (regexp :tag "Indentation TABs"))
c9dff4e3 798 :group 'whitespace)
97a739d5
VJL
799
800
c9dff4e3 801(defcustom whitespace-empty-at-bob-regexp "\\`\\(\\([ \t]*\n\\)+\\)"
97a739d5
VJL
802 "*Specify regexp for empty lines at beginning of buffer.
803
b502217b 804If you're using `mule' package, there may be other characters besides:
97a739d5
VJL
805
806 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
807\"\\xF20\"
808
809that should be considered blank.
810
ae68f2d8 811Used when `whitespace-style' includes `empty'."
97a739d5 812 :type '(regexp :tag "Empty Lines At Beginning Of Buffer")
c9dff4e3 813 :group 'whitespace)
97a739d5
VJL
814
815
c9dff4e3 816(defcustom whitespace-empty-at-eob-regexp "^\\([ \t\n]+\\)\\'"
97a739d5
VJL
817 "*Specify regexp for empty lines at end of buffer.
818
b502217b 819If you're using `mule' package, there may be other characters besides:
97a739d5
VJL
820
821 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
822\"\\xF20\"
823
824that should be considered blank.
825
ae68f2d8 826Used when `whitespace-style' includes `empty'."
97a739d5 827 :type '(regexp :tag "Empty Lines At End Of Buffer")
c9dff4e3 828 :group 'whitespace)
97a739d5
VJL
829
830
55d1cfe8
VJL
831(defcustom whitespace-space-after-tab-regexp
832 '("\t+\\(\\( \\{%d\\}\\)+\\)"
833 . "\\(\t+\\) +")
97a739d5
VJL
834 "*Specify regexp for 8 or more SPACEs after TAB.
835
55d1cfe8
VJL
836It is a cons where the cons car is used for SPACEs visualization
837and the cons cdr is used for TABs visualization.
838
b502217b 839If you're using `mule' package, there may be other characters besides:
97a739d5
VJL
840
841 \" \" \"\\t\" \"\\xA0\" \"\\x8A0\" \"\\x920\" \"\\xE20\" \
842\"\\xF20\"
843
844that should be considered blank.
845
ae68f2d8 846Used when `whitespace-style' includes `space-after-tab',
55d1cfe8 847`space-after-tab::tab' or `space-after-tab::space'."
97a739d5 848 :type '(regexp :tag "SPACEs After TAB")
c9dff4e3 849 :group 'whitespace)
97a739d5
VJL
850
851
c9dff4e3 852(defcustom whitespace-line-column 80
9f3b76d5 853 "*Specify column beyond which the line is highlighted.
30d0ade9 854
ae68f2d8 855Used when `whitespace-style' includes `lines' or `lines-tail'."
30d0ade9 856 :type '(integer :tag "Line Length")
c9dff4e3 857 :group 'whitespace)
30d0ade9
VJL
858
859
860;; Hacked from `visible-whitespace-mappings' in visws.el
c9dff4e3 861(defcustom whitespace-display-mappings
30d0ade9 862 '(
55d1cfe8
VJL
863 (space-mark ?\ [?\xB7] [?.]) ; space - centered dot
864 (space-mark ?\xA0 [?\xA4] [?_]) ; hard space - currency
865 (space-mark ?\x8A0 [?\x8A4] [?_]) ; hard space - currency
866 (space-mark ?\x920 [?\x924] [?_]) ; hard space - currency
867 (space-mark ?\xE20 [?\xE24] [?_]) ; hard space - currency
868 (space-mark ?\xF20 [?\xF24] [?_]) ; hard space - currency
c9dff4e3 869 ;; NEWLINE is displayed using the face `whitespace-newline'
55d1cfe8
VJL
870 (newline-mark ?\n [?$ ?\n]) ; eol - dollar sign
871 ;; (newline-mark ?\n [?\u21B5 ?\n] [?$ ?\n]) ; eol - downwards arrow
872 ;; (newline-mark ?\n [?\xB6 ?\n] [?$ ?\n]) ; eol - pilcrow
873 ;; (newline-mark ?\n [?\x8AF ?\n] [?$ ?\n]) ; eol - overscore
874 ;; (newline-mark ?\n [?\x8AC ?\n] [?$ ?\n]) ; eol - negation
875 ;; (newline-mark ?\n [?\x8B0 ?\n] [?$ ?\n]) ; eol - grade
30d0ade9
VJL
876 ;;
877 ;; WARNING: the mapping below has a problem.
878 ;; When a TAB occupies exactly one column, it will display the
879 ;; character ?\xBB at that column followed by a TAB which goes to
880 ;; the next TAB column.
881 ;; If this is a problem for you, please, comment the line below.
55d1cfe8 882 (tab-mark ?\t [?\xBB ?\t] [?\\ ?\t]) ; tab - left quote mark
30d0ade9
VJL
883 )
884 "*Specify an alist of mappings for displaying characters.
885
886Each element has the following form:
887
55d1cfe8 888 (KIND CHAR VECTOR...)
30d0ade9
VJL
889
890Where:
891
55d1cfe8
VJL
892KIND is the kind of character.
893 It can be one of the following symbols:
894
895 tab-mark for TAB character
896
897 space-mark for SPACE or HARD SPACE character
898
899 newline-mark for NEWLINE character
900
30d0ade9
VJL
901CHAR is the character to be mapped.
902
903VECTOR is a vector of characters to be displayed in place of CHAR.
904 The first display vector that can be displayed is used;
905 if no display vector for a mapping can be displayed, then
906 that character is displayed unmodified.
907
908The NEWLINE character is displayed using the face given by
55d1cfe8 909`whitespace-newline' variable.
30d0ade9 910
ae68f2d8
VJL
911Used when `whitespace-style' includes `tab-mark', `space-mark' or
912`newline-mark'."
30d0ade9
VJL
913 :type '(repeat
914 (list :tag "Character Mapping"
55d1cfe8
VJL
915 (choice :tag "Char Kind"
916 (const :tag "Tab" tab-mark)
917 (const :tag "Space" space-mark)
918 (const :tag "Newline" newline-mark))
30d0ade9
VJL
919 (character :tag "Char")
920 (repeat :inline t :tag "Vector List"
921 (vector :tag ""
922 (repeat :inline t
923 :tag "Vector Characters"
924 (character :tag "Char"))))))
c9dff4e3 925 :group 'whitespace)
30d0ade9
VJL
926
927
c9dff4e3
VJL
928(defcustom whitespace-global-modes t
929 "*Modes for which global `whitespace-mode' is automagically turned on.
30d0ade9 930
c9dff4e3
VJL
931Global `whitespace-mode' is controlled by the command
932`global-whitespace-mode'.
30d0ade9 933
c9dff4e3 934If nil, means no modes have `whitespace-mode' automatically
30d0ade9 935turned on.
c9dff4e3
VJL
936
937If t, all modes that support `whitespace-mode' have it
938automatically turned on.
939
940Else it should be a list of `major-mode' symbol names for which
941`whitespace-mode' should be automatically turned on. The sense
30d0ade9
VJL
942of the list is negated if it begins with `not'. For example:
943
944 (c-mode c++-mode)
945
c9dff4e3
VJL
946means that `whitespace-mode' is turned on for buffers in C and
947C++ modes only."
94dc593f
VJL
948 :type '(choice :tag "Global Modes"
949 (const :tag "None" nil)
97a739d5
VJL
950 (const :tag "All" t)
951 (set :menu-tag "Mode Specific" :tag "Modes"
30d0ade9
VJL
952 :value (not)
953 (const :tag "Except" not)
954 (repeat :inline t
97a739d5 955 (symbol :tag "Mode"))))
c9dff4e3 956 :group 'whitespace)
30d0ade9 957
94dc593f
VJL
958
959(defcustom whitespace-action nil
960 "*Specify which action is taken when a buffer is visited, killed or written.
961
962It's a list containing some or all of the following values:
963
964 nil no action is taken.
965
966 cleanup cleanup any bogus whitespace always when local
967 whitespace is turned on.
968 See `whitespace-cleanup' and
969 `whitespace-cleanup-region'.
970
971 report-on-bogus report if there is any bogus whitespace always
972 when local whitespace is turned on.
973
974 auto-cleanup cleanup any bogus whitespace when buffer is
ae68f2d8 975 written or killed.
94dc593f
VJL
976 See `whitespace-cleanup' and
977 `whitespace-cleanup-region'.
978
979 abort-on-bogus abort if there is any bogus whitespace and the
980 buffer is written or killed.
981
982Any other value is treated as nil."
983 :type '(choice :tag "Actions"
984 (const :tag "None" nil)
985 (repeat :tag "Action List"
986 (choice :tag "Action"
987 (const :tag "Cleanup When On" cleanup)
988 (const :tag "Report On Bogus" report-on-bogus)
989 (const :tag "Auto Cleanup" auto-cleanup)
990 (const :tag "Abort On Bogus" abort-on-bogus))))
991 :group 'whitespace)
992
30d0ade9
VJL
993\f
994;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
995;;;; User commands - Local mode
996
997
998;;;###autoload
c9dff4e3
VJL
999(define-minor-mode whitespace-mode
1000 "Toggle whitespace minor mode visualization (\"ws\" on modeline).
30d0ade9 1001
c9dff4e3 1002If ARG is null, toggle whitespace visualization.
040f578c
VJL
1003If ARG is a number greater than zero, turn on visualization;
1004otherwise, turn off visualization.
30d0ade9 1005Only useful with a windowing system."
c9dff4e3 1006 :lighter " ws"
30d0ade9
VJL
1007 :init-value nil
1008 :global nil
c9dff4e3 1009 :group 'whitespace
30d0ade9
VJL
1010 (cond
1011 (noninteractive ; running a batch job
c9dff4e3
VJL
1012 (setq whitespace-mode nil))
1013 (whitespace-mode ; whitespace-mode on
94dc593f
VJL
1014 (whitespace-turn-on)
1015 (whitespace-action-when-on))
c9dff4e3
VJL
1016 (t ; whitespace-mode off
1017 (whitespace-turn-off))))
30d0ade9
VJL
1018
1019\f
1020;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1021;;;; User commands - Global mode
1022
1023
55d1cfe8 1024;;;###autoload
c9dff4e3
VJL
1025(define-minor-mode global-whitespace-mode
1026 "Toggle whitespace global minor mode visualization (\"WS\" on modeline).
30d0ade9 1027
c9dff4e3 1028If ARG is null, toggle whitespace visualization.
040f578c
VJL
1029If ARG is a number greater than zero, turn on visualization;
1030otherwise, turn off visualization.
30d0ade9 1031Only useful with a windowing system."
acaf02dd 1032 :lighter " WS"
30d0ade9
VJL
1033 :init-value nil
1034 :global t
c9dff4e3 1035 :group 'whitespace
30d0ade9
VJL
1036 (cond
1037 (noninteractive ; running a batch job
c9dff4e3
VJL
1038 (setq global-whitespace-mode nil))
1039 (global-whitespace-mode ; global-whitespace-mode on
30d0ade9 1040 (save-excursion
94dc593f 1041 (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
30d0ade9
VJL
1042 (dolist (buffer (buffer-list)) ; adjust all local mode
1043 (set-buffer buffer)
c9dff4e3
VJL
1044 (unless whitespace-mode
1045 (whitespace-turn-on-if-enabled)))))
1046 (t ; global-whitespace-mode off
30d0ade9 1047 (save-excursion
4a4b61e2 1048 (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
30d0ade9
VJL
1049 (dolist (buffer (buffer-list)) ; adjust all local mode
1050 (set-buffer buffer)
e5403637 1051 (unless whitespace-mode
c9dff4e3 1052 (whitespace-turn-off)))))))
30d0ade9
VJL
1053
1054
c9dff4e3 1055(defun whitespace-turn-on-if-enabled ()
30d0ade9 1056 (when (cond
c9dff4e3
VJL
1057 ((eq whitespace-global-modes t))
1058 ((listp whitespace-global-modes)
1059 (if (eq (car-safe whitespace-global-modes) 'not)
1060 (not (memq major-mode (cdr whitespace-global-modes)))
1061 (memq major-mode whitespace-global-modes)))
30d0ade9
VJL
1062 (t nil))
1063 (let (inhibit-quit)
c9dff4e3 1064 ;; Don't turn on whitespace mode if...
30d0ade9
VJL
1065 (or
1066 ;; ...we don't have a display (we're running a batch job)
1067 noninteractive
1068 ;; ...or if the buffer is invisible (name starts with a space)
1069 (eq (aref (buffer-name) 0) ?\ )
1070 ;; ...or if the buffer is temporary (name starts with *)
1071 (and (eq (aref (buffer-name) 0) ?*)
1072 ;; except the scratch buffer.
1073 (not (string= (buffer-name) "*scratch*")))
c9dff4e3
VJL
1074 ;; Otherwise, turn on whitespace mode.
1075 (whitespace-turn-on)))))
30d0ade9
VJL
1076
1077\f
1078;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1079;;;; User commands - Toggle
1080
1081
ae68f2d8 1082(defconst whitespace-style-value-list
30d0ade9
VJL
1083 '(tabs
1084 spaces
1085 trailing
30d0ade9 1086 lines
9f3b76d5 1087 lines-tail
30d0ade9 1088 newline
97a739d5 1089 empty
55d1cfe8
VJL
1090 indentation
1091 indentation::tab
1092 indentation::space
97a739d5 1093 space-after-tab
55d1cfe8
VJL
1094 space-after-tab::tab
1095 space-after-tab::space
1096 space-before-tab
1097 space-before-tab::tab
1098 space-before-tab::space
ae68f2d8
VJL
1099 help-newline ; value used by `whitespace-insert-option-mark'
1100 tab-mark
55d1cfe8
VJL
1101 space-mark
1102 newline-mark
30d0ade9 1103 )
ae68f2d8 1104 "List of valid `whitespace-style' values.")
30d0ade9
VJL
1105
1106
c9dff4e3 1107(defconst whitespace-toggle-option-alist
ae68f2d8 1108 '((?t . tabs)
55d1cfe8
VJL
1109 (?s . spaces)
1110 (?r . trailing)
1111 (?l . lines)
1112 (?L . lines-tail)
1113 (?n . newline)
1114 (?e . empty)
1115 (?\C-i . indentation)
1116 (?I . indentation::tab)
1117 (?i . indentation::space)
1118 (?\C-a . space-after-tab)
1119 (?A . space-after-tab::tab)
1120 (?a . space-after-tab::space)
1121 (?\C-b . space-before-tab)
1122 (?B . space-before-tab::tab)
1123 (?b . space-before-tab::space)
55d1cfe8
VJL
1124 (?T . tab-mark)
1125 (?S . space-mark)
1126 (?N . newline-mark)
ae68f2d8 1127 (?x . whitespace-style)
30d0ade9
VJL
1128 )
1129 "Alist of toggle options.
1130
1131Each element has the form:
1132
1133 (CHAR . SYMBOL)
1134
1135Where:
1136
1137CHAR is a char which the user will have to type.
1138
1139SYMBOL is a valid symbol associated with CHAR.
ae68f2d8 1140 See `whitespace-style-value-list'.")
30d0ade9
VJL
1141
1142
ae68f2d8
VJL
1143(defvar whitespace-active-style nil
1144 "Used to save locally `whitespace-style' value.")
30d0ade9 1145
55d1cfe8
VJL
1146(defvar whitespace-indent-tabs-mode indent-tabs-mode
1147 "Used to save locally `indent-tabs-mode' value.")
1148
1149(defvar whitespace-tab-width tab-width
1150 "Used to save locally `tab-width' value.")
30d0ade9
VJL
1151
1152
1153;;;###autoload
c9dff4e3
VJL
1154(defun whitespace-toggle-options (arg)
1155 "Toggle local `whitespace-mode' options.
30d0ade9 1156
c9dff4e3
VJL
1157If local whitespace-mode is off, toggle the option given by ARG
1158and turn on local whitespace-mode.
30d0ade9 1159
c9dff4e3
VJL
1160If local whitespace-mode is on, toggle the option given by ARG
1161and restart local whitespace-mode.
30d0ade9
VJL
1162
1163Interactively, it reads one of the following chars:
1164
1165 CHAR MEANING
55d1cfe8 1166 (VIA FACES)
040f578c
VJL
1167 t toggle TAB visualization
1168 s toggle SPACE and HARD SPACE visualization
1169 r toggle trailing blanks visualization
040f578c 1170 l toggle \"long lines\" visualization
9f3b76d5 1171 L toggle \"long lines\" tail visualization
040f578c 1172 n toggle NEWLINE visualization
97a739d5 1173 e toggle empty line at bob and/or eob visualization
55d1cfe8
VJL
1174 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1175 I toggle indentation SPACEs visualization
1176 i toggle indentation TABs visualization
1177 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1178 A toggle SPACEs after TAB: SPACEs visualization
1179 a toggle SPACEs after TAB: TABs visualization
1180 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1181 B toggle SPACEs before TAB: SPACEs visualization
1182 b toggle SPACEs before TAB: TABs visualization
1183
1184 (VIA DISPLAY TABLE)
1185 T toggle TAB visualization
1186 S toggle SPACEs before TAB visualization
1187 N toggle NEWLINE visualization
1188
ae68f2d8 1189 x restore `whitespace-style' value
30d0ade9
VJL
1190 ? display brief help
1191
040f578c 1192Non-interactively, ARG should be a symbol or a list of symbols.
30d0ade9
VJL
1193The valid symbols are:
1194
040f578c
VJL
1195 tabs toggle TAB visualization
1196 spaces toggle SPACE and HARD SPACE visualization
1197 trailing toggle trailing blanks visualization
040f578c 1198 lines toggle \"long lines\" visualization
9f3b76d5 1199 lines-tail toggle \"long lines\" tail visualization
040f578c 1200 newline toggle NEWLINE visualization
97a739d5 1201 empty toggle empty line at bob and/or eob visualization
55d1cfe8
VJL
1202 indentation toggle indentation SPACEs visualization
1203 indentation::tab toggle indentation SPACEs visualization
1204 indentation::space toggle indentation TABs visualization
1205 space-after-tab toggle SPACEs after TAB visualization
1206 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1207 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1208 space-before-tab toggle SPACEs before TAB visualization
1209 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1210 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1211
1212 tab-mark toggle TAB visualization
1213 space-mark toggle SPACEs before TAB visualization
1214 newline-mark toggle NEWLINE visualization
1215
ae68f2d8 1216 whitespace-style restore `whitespace-style' value
55d1cfe8
VJL
1217
1218Only useful with a windowing system.
1219
ae68f2d8 1220See `whitespace-style' and `indent-tabs-mode' for documentation."
c9dff4e3 1221 (interactive (whitespace-interactive-char t))
ae68f2d8
VJL
1222 (let ((whitespace-style
1223 (whitespace-toggle-list t arg whitespace-active-style)))
c9dff4e3
VJL
1224 (whitespace-mode 0)
1225 (whitespace-mode 1)))
30d0ade9
VJL
1226
1227
ae68f2d8
VJL
1228(defvar whitespace-toggle-style nil
1229 "Used to toggle the global `whitespace-style' value.")
30d0ade9
VJL
1230
1231
1232;;;###autoload
c9dff4e3
VJL
1233(defun global-whitespace-toggle-options (arg)
1234 "Toggle global `whitespace-mode' options.
30d0ade9 1235
c9dff4e3
VJL
1236If global whitespace-mode is off, toggle the option given by ARG
1237and turn on global whitespace-mode.
30d0ade9 1238
c9dff4e3
VJL
1239If global whitespace-mode is on, toggle the option given by ARG
1240and restart global whitespace-mode.
30d0ade9 1241
b502217b 1242Interactively, it accepts one of the following chars:
30d0ade9
VJL
1243
1244 CHAR MEANING
55d1cfe8 1245 (VIA FACES)
040f578c
VJL
1246 t toggle TAB visualization
1247 s toggle SPACE and HARD SPACE visualization
1248 r toggle trailing blanks visualization
040f578c 1249 l toggle \"long lines\" visualization
9f3b76d5 1250 L toggle \"long lines\" tail visualization
040f578c 1251 n toggle NEWLINE visualization
97a739d5 1252 e toggle empty line at bob and/or eob visualization
55d1cfe8
VJL
1253 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1254 I toggle indentation SPACEs visualization
1255 i toggle indentation TABs visualization
1256 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1257 A toggle SPACEs after TAB: SPACEs visualization
1258 a toggle SPACEs after TAB: TABs visualization
1259 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1260 B toggle SPACEs before TAB: SPACEs visualization
1261 b toggle SPACEs before TAB: TABs visualization
1262
1263 (VIA DISPLAY TABLE)
1264 T toggle TAB visualization
1265 S toggle SPACEs before TAB visualization
1266 N toggle NEWLINE visualization
1267
ae68f2d8 1268 x restore `whitespace-style' value
30d0ade9
VJL
1269 ? display brief help
1270
040f578c 1271Non-interactively, ARG should be a symbol or a list of symbols.
30d0ade9
VJL
1272The valid symbols are:
1273
040f578c
VJL
1274 tabs toggle TAB visualization
1275 spaces toggle SPACE and HARD SPACE visualization
1276 trailing toggle trailing blanks visualization
040f578c 1277 lines toggle \"long lines\" visualization
9f3b76d5 1278 lines-tail toggle \"long lines\" tail visualization
040f578c 1279 newline toggle NEWLINE visualization
97a739d5 1280 empty toggle empty line at bob and/or eob visualization
55d1cfe8
VJL
1281 indentation toggle indentation SPACEs visualization
1282 indentation::tab toggle indentation SPACEs visualization
1283 indentation::space toggle indentation TABs visualization
1284 space-after-tab toggle SPACEs after TAB visualization
1285 space-after-tab::tab toggle SPACEs after TAB: SPACEs visualization
1286 space-after-tab::space toggle SPACEs after TAB: TABs visualization
1287 space-before-tab toggle SPACEs before TAB visualization
1288 space-before-tab::tab toggle SPACEs before TAB: SPACEs visualization
1289 space-before-tab::space toggle SPACEs before TAB: TABs visualization
1290
1291 tab-mark toggle TAB visualization
1292 space-mark toggle SPACEs before TAB visualization
1293 newline-mark toggle NEWLINE visualization
1294
ae68f2d8 1295 whitespace-style restore `whitespace-style' value
55d1cfe8
VJL
1296
1297Only useful with a windowing system.
1298
ae68f2d8 1299See `whitespace-style' and `indent-tabs-mode' for documentation."
c9dff4e3 1300 (interactive (whitespace-interactive-char nil))
ae68f2d8
VJL
1301 (let ((whitespace-style
1302 (whitespace-toggle-list nil arg whitespace-toggle-style)))
1303 (setq whitespace-toggle-style whitespace-style)
c9dff4e3
VJL
1304 (global-whitespace-mode 0)
1305 (global-whitespace-mode 1)))
30d0ade9
VJL
1306
1307\f
97a739d5
VJL
1308;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1309;;;; User commands - Cleanup
1310
1311
1312;;;###autoload
c9dff4e3 1313(defun whitespace-cleanup ()
97a739d5
VJL
1314 "Cleanup some blank problems in all buffer or at region.
1315
1316It usually applies to the whole buffer, but in transient mark
1317mode when the mark is active, it applies to the region. It also
1318applies to the region when it is not in transiente mark mode, the
55d1cfe8
VJL
1319mark is active and \\[universal-argument] was pressed just before
1320calling `whitespace-cleanup' interactively.
97a739d5 1321
c9dff4e3 1322See also `whitespace-cleanup-region'.
97a739d5 1323
b502217b 1324The problems cleaned up are:
97a739d5
VJL
1325
13261. empty lines at beginning of buffer.
13272. empty lines at end of buffer.
ae68f2d8 1328 If `whitespace-style' includes the value `empty', remove all
c9dff4e3 1329 empty lines at beginning and/or end of buffer.
97a739d5
VJL
1330
13313. 8 or more SPACEs at beginning of line.
ae68f2d8 1332 If `whitespace-style' includes the value `indentation':
55d1cfe8
VJL
1333 replace 8 or more SPACEs at beginning of line by TABs, if
1334 `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1335 SPACEs.
ae68f2d8
VJL
1336 If `whitespace-style' includes the value `indentation::tab',
1337 replace 8 or more SPACEs at beginning of line by TABs.
1338 If `whitespace-style' includes the value `indentation::space',
1339 replace TABs by SPACEs.
97a739d5
VJL
1340
13414. SPACEs before TAB.
ae68f2d8 1342 If `whitespace-style' includes the value `space-before-tab':
55d1cfe8
VJL
1343 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1344 otherwise, replace TABs by SPACEs.
ae68f2d8 1345 If `whitespace-style' includes the value
55d1cfe8 1346 `space-before-tab::tab', replace SPACEs by TABs.
ae68f2d8 1347 If `whitespace-style' includes the value
55d1cfe8 1348 `space-before-tab::space', replace TABs by SPACEs.
97a739d5
VJL
1349
13505. SPACEs or TABs at end of line.
ae68f2d8 1351 If `whitespace-style' includes the value `trailing', remove
55d1cfe8 1352 all SPACEs or TABs at end of line.
97a739d5
VJL
1353
13546. 8 or more SPACEs after TAB.
ae68f2d8 1355 If `whitespace-style' includes the value `space-after-tab':
55d1cfe8
VJL
1356 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1357 otherwise, replace TABs by SPACEs.
ae68f2d8 1358 If `whitespace-style' includes the value
55d1cfe8 1359 `space-after-tab::tab', replace SPACEs by TABs.
ae68f2d8 1360 If `whitespace-style' includes the value
55d1cfe8
VJL
1361 `space-after-tab::space', replace TABs by SPACEs.
1362
ae68f2d8
VJL
1363See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1364documentation."
97a739d5
VJL
1365 (interactive "@*")
1366 (if (and (or transient-mark-mode
1367 current-prefix-arg)
1368 mark-active)
1369 ;; region active
55d1cfe8
VJL
1370 ;; PROBLEMs 1 and 2 are not handled in region
1371 ;; PROBLEM 3: 8 or more SPACEs at bol
1372 ;; PROBLEM 4: SPACEs before TAB
1373 ;; PROBLEM 5: SPACEs or TABs at eol
1374 ;; PROBLEM 6: 8 or more SPACEs after TAB
c9dff4e3 1375 (whitespace-cleanup-region (region-beginning) (region-end))
97a739d5
VJL
1376 ;; whole buffer
1377 (save-excursion
9f3b76d5 1378 (save-match-data
55d1cfe8
VJL
1379 ;; PROBLEM 1: empty lines at bob
1380 ;; PROBLEM 2: empty lines at eob
1381 ;; ACTION: remove all empty lines at bob and/or eob
ae68f2d8 1382 (when (memq 'empty whitespace-style)
9f3b76d5
VJL
1383 (let (overwrite-mode) ; enforce no overwrite
1384 (goto-char (point-min))
c9dff4e3
VJL
1385 (when (re-search-forward
1386 whitespace-empty-at-bob-regexp nil t)
9f3b76d5 1387 (delete-region (match-beginning 1) (match-end 1)))
c9dff4e3
VJL
1388 (when (re-search-forward
1389 whitespace-empty-at-eob-regexp nil t)
9f3b76d5 1390 (delete-region (match-beginning 1) (match-end 1)))))))
55d1cfe8
VJL
1391 ;; PROBLEM 3: 8 or more SPACEs at bol
1392 ;; PROBLEM 4: SPACEs before TAB
1393 ;; PROBLEM 5: SPACEs or TABs at eol
1394 ;; PROBLEM 6: 8 or more SPACEs after TAB
c9dff4e3 1395 (whitespace-cleanup-region (point-min) (point-max))))
97a739d5
VJL
1396
1397
1398;;;###autoload
c9dff4e3 1399(defun whitespace-cleanup-region (start end)
97a739d5
VJL
1400 "Cleanup some blank problems at region.
1401
b502217b 1402The problems cleaned up are:
97a739d5
VJL
1403
14041. 8 or more SPACEs at beginning of line.
ae68f2d8 1405 If `whitespace-style' includes the value `indentation':
55d1cfe8
VJL
1406 replace 8 or more SPACEs at beginning of line by TABs, if
1407 `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1408 SPACEs.
ae68f2d8
VJL
1409 If `whitespace-style' includes the value `indentation::tab',
1410 replace 8 or more SPACEs at beginning of line by TABs.
1411 If `whitespace-style' includes the value `indentation::space',
1412 replace TABs by SPACEs.
97a739d5
VJL
1413
14142. SPACEs before TAB.
ae68f2d8 1415 If `whitespace-style' includes the value `space-before-tab':
55d1cfe8
VJL
1416 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1417 otherwise, replace TABs by SPACEs.
ae68f2d8 1418 If `whitespace-style' includes the value
55d1cfe8 1419 `space-before-tab::tab', replace SPACEs by TABs.
ae68f2d8 1420 If `whitespace-style' includes the value
55d1cfe8 1421 `space-before-tab::space', replace TABs by SPACEs.
97a739d5
VJL
1422
14233. SPACEs or TABs at end of line.
ae68f2d8 1424 If `whitespace-style' includes the value `trailing', remove
55d1cfe8 1425 all SPACEs or TABs at end of line.
97a739d5
VJL
1426
14274. 8 or more SPACEs after TAB.
ae68f2d8 1428 If `whitespace-style' includes the value `space-after-tab':
55d1cfe8
VJL
1429 replace SPACEs by TABs, if `indent-tabs-mode' is non-nil;
1430 otherwise, replace TABs by SPACEs.
ae68f2d8 1431 If `whitespace-style' includes the value
55d1cfe8 1432 `space-after-tab::tab', replace SPACEs by TABs.
ae68f2d8 1433 If `whitespace-style' includes the value
55d1cfe8
VJL
1434 `space-after-tab::space', replace TABs by SPACEs.
1435
ae68f2d8
VJL
1436See `whitespace-style', `indent-tabs-mode' and `tab-width' for
1437documentation."
97a739d5
VJL
1438 (interactive "@*r")
1439 (let ((rstart (min start end))
1440 (rend (copy-marker (max start end)))
55d1cfe8
VJL
1441 (indent-tabs-mode whitespace-indent-tabs-mode)
1442 (tab-width whitespace-tab-width)
97a739d5
VJL
1443 overwrite-mode ; enforce no overwrite
1444 tmp)
1445 (save-excursion
9f3b76d5 1446 (save-match-data
55d1cfe8
VJL
1447 ;; PROBLEM 1: 8 or more SPACEs at bol
1448 (cond
1449 ;; ACTION: replace 8 or more SPACEs at bol by TABs, if
1450 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1451 ;; SPACEs.
ae68f2d8 1452 ((memq 'indentation whitespace-style)
55d1cfe8 1453 (let ((regexp (whitespace-indentation-regexp)))
9f3b76d5
VJL
1454 (goto-char rstart)
1455 (while (re-search-forward regexp rend t)
55d1cfe8
VJL
1456 (setq tmp (current-indentation))
1457 (goto-char (match-beginning 0))
1458 (delete-horizontal-space)
1459 (unless (eolp)
1460 (indent-to tmp)))))
1461 ;; ACTION: replace 8 or more SPACEs at bol by TABs.
ae68f2d8 1462 ((memq 'indentation::tab whitespace-style)
55d1cfe8
VJL
1463 (whitespace-replace-action
1464 'tabify rstart rend
1465 (whitespace-indentation-regexp 'tab) 0))
1466 ;; ACTION: replace TABs by SPACEs.
ae68f2d8 1467 ((memq 'indentation::space whitespace-style)
55d1cfe8
VJL
1468 (whitespace-replace-action
1469 'untabify rstart rend
1470 (whitespace-indentation-regexp 'space) 0)))
1471 ;; PROBLEM 3: SPACEs or TABs at eol
1472 ;; ACTION: remove all SPACEs or TABs at eol
ae68f2d8 1473 (when (memq 'trailing whitespace-style)
55d1cfe8
VJL
1474 (whitespace-replace-action
1475 'delete-region rstart rend
2788143d 1476 whitespace-trailing-regexp 1))
55d1cfe8
VJL
1477 ;; PROBLEM 4: 8 or more SPACEs after TAB
1478 (cond
1479 ;; ACTION: replace 8 or more SPACEs by TABs, if
1480 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1481 ;; SPACEs.
ae68f2d8 1482 ((memq 'space-after-tab whitespace-style)
55d1cfe8
VJL
1483 (whitespace-replace-action
1484 (if whitespace-indent-tabs-mode 'tabify 'untabify)
1485 rstart rend (whitespace-space-after-tab-regexp) 1))
1486 ;; ACTION: replace 8 or more SPACEs by TABs.
ae68f2d8 1487 ((memq 'space-after-tab::tab whitespace-style)
55d1cfe8
VJL
1488 (whitespace-replace-action
1489 'tabify rstart rend
1490 (whitespace-space-after-tab-regexp 'tab) 1))
1491 ;; ACTION: replace TABs by SPACEs.
ae68f2d8 1492 ((memq 'space-after-tab::space whitespace-style)
55d1cfe8
VJL
1493 (whitespace-replace-action
1494 'untabify rstart rend
1495 (whitespace-space-after-tab-regexp 'space) 1)))
1496 ;; PROBLEM 2: SPACEs before TAB
1497 (cond
1498 ;; ACTION: replace SPACEs before TAB by TABs, if
1499 ;; `indent-tabs-mode' is non-nil; otherwise, replace TABs by
1500 ;; SPACEs.
ae68f2d8 1501 ((memq 'space-before-tab whitespace-style)
55d1cfe8
VJL
1502 (whitespace-replace-action
1503 (if whitespace-indent-tabs-mode 'tabify 'untabify)
1504 rstart rend whitespace-space-before-tab-regexp
1505 (if whitespace-indent-tabs-mode 1 2)))
1506 ;; ACTION: replace SPACEs before TAB by TABs.
ae68f2d8 1507 ((memq 'space-before-tab::tab whitespace-style)
55d1cfe8
VJL
1508 (whitespace-replace-action
1509 'tabify rstart rend
1510 whitespace-space-before-tab-regexp 1))
1511 ;; ACTION: replace TABs by SPACEs.
ae68f2d8 1512 ((memq 'space-before-tab::space whitespace-style)
55d1cfe8
VJL
1513 (whitespace-replace-action
1514 'untabify rstart rend
1515 whitespace-space-before-tab-regexp 2)))))
97a739d5
VJL
1516 (set-marker rend nil))) ; point marker to nowhere
1517
9f3b76d5 1518
55d1cfe8
VJL
1519(defun whitespace-replace-action (action rstart rend regexp index)
1520 "Do ACTION in the string matched by REGEXP between RSTART and REND.
1521
1522INDEX is the level group matched by REGEXP and used by ACTION.
1523
1524See also `tab-width'."
9f3b76d5
VJL
1525 (goto-char rstart)
1526 (while (re-search-forward regexp rend t)
55d1cfe8
VJL
1527 (goto-char (match-end index))
1528 (funcall action (match-beginning index) (match-end index))))
9f3b76d5 1529
97a739d5 1530\f
c9dff4e3 1531;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
94dc593f
VJL
1532;;;; User command - report
1533
1534
55d1cfe8
VJL
1535(defun whitespace-regexp (regexp &optional kind)
1536 "Return REGEXP depending on `whitespace-indent-tabs-mode'."
1537 (cond
1538 ((or (eq kind 'tab)
1539 whitespace-indent-tabs-mode)
1540 (format (car regexp) whitespace-tab-width))
1541 ((or (eq kind 'space)
1542 (not whitespace-indent-tabs-mode))
1543 (cdr regexp))))
1544
1545
1546(defun whitespace-indentation-regexp (&optional kind)
1547 "Return the indentation regexp depending on `whitespace-indent-tabs-mode'."
1548 (whitespace-regexp whitespace-indentation-regexp kind))
1549
1550
1551(defun whitespace-space-after-tab-regexp (&optional kind)
1552 "Return the space-after-tab regexp depending on `whitespace-indent-tabs-mode'."
1553 (whitespace-regexp whitespace-space-after-tab-regexp kind))
1554
1555
94dc593f
VJL
1556(defconst whitespace-report-list
1557 (list
55d1cfe8
VJL
1558 (cons 'empty whitespace-empty-at-bob-regexp)
1559 (cons 'empty whitespace-empty-at-eob-regexp)
2788143d 1560 (cons 'trailing whitespace-trailing-regexp)
55d1cfe8
VJL
1561 (cons 'indentation nil)
1562 (cons 'indentation::tab nil)
1563 (cons 'indentation::space nil)
1564 (cons 'space-before-tab whitespace-space-before-tab-regexp)
1565 (cons 'space-before-tab::tab whitespace-space-before-tab-regexp)
1566 (cons 'space-before-tab::space whitespace-space-before-tab-regexp)
1567 (cons 'space-after-tab nil)
1568 (cons 'space-after-tab::tab nil)
1569 (cons 'space-after-tab::space nil)
94dc593f
VJL
1570 )
1571 "List of whitespace bogus symbol and corresponding regexp.")
1572
1573
1574(defconst whitespace-report-text
55d1cfe8
VJL
1575 '( ;; `indent-tabs-mode' has non-nil value
1576 "\
1577 Whitespace Report
1578
1579 Current Setting Whitespace Problem
1580
1581 empty [] [] empty lines at beginning of buffer
1582 empty [] [] empty lines at end of buffer
1583 trailing [] [] SPACEs or TABs at end of line
1584 indentation [] [] 8 or more SPACEs at beginning of line
1585 indentation::tab [] [] 8 or more SPACEs at beginning of line
1586 indentation::space [] [] TABs at beginning of line
1587 space-before-tab [] [] SPACEs before TAB
1588 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1589 space-before-tab::space [] [] SPACEs before TAB: TABs
1590 space-after-tab [] [] 8 or more SPACEs after TAB
1591 space-after-tab::tab [] [] 8 or more SPACEs after TAB: SPACEs
1592 space-after-tab::space [] [] 8 or more SPACEs after TAB: TABs
1593
1594 indent-tabs-mode =
1595 tab-width = \n\n"
1596 . ;; `indent-tabs-mode' has nil value
1597 "\
1598 Whitespace Report
1599
1600 Current Setting Whitespace Problem
1601
1602 empty [] [] empty lines at beginning of buffer
1603 empty [] [] empty lines at end of buffer
1604 trailing [] [] SPACEs or TABs at end of line
1605 indentation [] [] TABs at beginning of line
1606 indentation::tab [] [] 8 or more SPACEs at beginning of line
1607 indentation::space [] [] TABs at beginning of line
1608 space-before-tab [] [] SPACEs before TAB
1609 space-before-tab::tab [] [] SPACEs before TAB: SPACEs
1610 space-before-tab::space [] [] SPACEs before TAB: TABs
1611 space-after-tab [] [] 8 or more SPACEs after TAB
1612 space-after-tab::tab [] [] 8 or more SPACEs after TAB: SPACEs
1613 space-after-tab::space [] [] 8 or more SPACEs after TAB: TABs
1614
1615 indent-tabs-mode =
1616 tab-width = \n\n")
1617 "Text for whitespace bogus report.
1618
1619It is a cons of strings, where the car part is used when
1620`indent-tabs-mode' is non-nil, and the cdr part is used when
1621`indent-tabs-mode' is nil.")
94dc593f
VJL
1622
1623
1624(defconst whitespace-report-buffer-name "*Whitespace Report*"
1625 "The buffer name for whitespace bogus report.")
c9dff4e3
VJL
1626
1627
1628;;;###autoload
94dc593f
VJL
1629(defun whitespace-report (&optional force report-if-bogus)
1630 "Report some whitespace problems in buffer.
c9dff4e3 1631
94dc593f
VJL
1632Return nil if there is no whitespace problem; otherwise, return
1633non-nil.
c9dff4e3 1634
55d1cfe8
VJL
1635If FORCE is non-nil or \\[universal-argument] was pressed just
1636before calling `whitespace-report' interactively, it forces
ae68f2d8 1637`whitespace-style' to have:
c9dff4e3 1638
94dc593f 1639 empty
55d1cfe8 1640 trailing
c9dff4e3
VJL
1641 indentation
1642 space-before-tab
94dc593f
VJL
1643 space-after-tab
1644
1645If REPORT-IF-BOGUS is non-nil, it reports only when there are any
1646whitespace problems in buffer.
1647
1648Report if some of the following whitespace problems exist:
1649
55d1cfe8 1650* If `indent-tabs-mode' is non-nil:
94dc593f
VJL
1651 empty 1. empty lines at beginning of buffer.
1652 empty 2. empty lines at end of buffer.
55d1cfe8
VJL
1653 trailing 3. SPACEs or TABs at end of line.
1654 indentation 4. 8 or more SPACEs at beginning of line.
1655 space-before-tab 5. SPACEs before TAB.
94dc593f
VJL
1656 space-after-tab 6. 8 or more SPACEs after TAB.
1657
55d1cfe8
VJL
1658* If `indent-tabs-mode' is nil:
1659 empty 1. empty lines at beginning of buffer.
1660 empty 2. empty lines at end of buffer.
1661 trailing 3. SPACEs or TABs at end of line.
1662 indentation 4. TABS at beginning of line.
1663 space-before-tab 5. SPACEs before TAB.
1664 space-after-tab 6. 8 or more SPACEs after TAB.
1665
ae68f2d8 1666See `whitespace-style' for documentation.
94dc593f
VJL
1667See also `whitespace-cleanup' and `whitespace-cleanup-region' for
1668cleaning up these problems."
1669 (interactive (list current-prefix-arg))
1670 (whitespace-report-region (point-min) (point-max)
1671 force report-if-bogus))
1672
1673
1674;;;###autoload
1675(defun whitespace-report-region (start end &optional force report-if-bogus)
1676 "Report some whitespace problems in a region.
1677
1678Return nil if there is no whitespace problem; otherwise, return
1679non-nil.
1680
55d1cfe8
VJL
1681If FORCE is non-nil or \\[universal-argument] was pressed just
1682before calling `whitespace-report-region' interactively, it
ae68f2d8 1683forces `whitespace-style' to have:
94dc593f 1684
c9dff4e3 1685 empty
94dc593f
VJL
1686 indentation
1687 space-before-tab
1688 trailing
c9dff4e3
VJL
1689 space-after-tab
1690
94dc593f
VJL
1691If REPORT-IF-BOGUS is non-nil, it reports only when there are any
1692whitespace problems in buffer.
1693
1694Report if some of the following whitespace problems exist:
c9dff4e3 1695
55d1cfe8
VJL
1696* If `indent-tabs-mode' is non-nil:
1697 empty 1. empty lines at beginning of buffer.
1698 empty 2. empty lines at end of buffer.
1699 trailing 3. SPACEs or TABs at end of line.
1700 indentation 4. 8 or more SPACEs at beginning of line.
1701 space-before-tab 5. SPACEs before TAB.
1702 space-after-tab 6. 8 or more SPACEs after TAB.
1703
1704* If `indent-tabs-mode' is nil:
c9dff4e3
VJL
1705 empty 1. empty lines at beginning of buffer.
1706 empty 2. empty lines at end of buffer.
55d1cfe8
VJL
1707 trailing 3. SPACEs or TABs at end of line.
1708 indentation 4. TABS at beginning of line.
1709 space-before-tab 5. SPACEs before TAB.
c9dff4e3
VJL
1710 space-after-tab 6. 8 or more SPACEs after TAB.
1711
ae68f2d8 1712See `whitespace-style' for documentation.
c9dff4e3
VJL
1713See also `whitespace-cleanup' and `whitespace-cleanup-region' for
1714cleaning up these problems."
94dc593f
VJL
1715 (interactive "r")
1716 (setq force (or current-prefix-arg force))
1717 (save-excursion
1718 (save-match-data
55d1cfe8
VJL
1719 (let* ((has-bogus nil)
1720 (rstart (min start end))
1721 (rend (max start end))
1722 (bogus-list
1723 (mapcar
1724 #'(lambda (option)
1725 (when force
ae68f2d8 1726 (add-to-list 'whitespace-style (car option)))
55d1cfe8
VJL
1727 (goto-char rstart)
1728 (let ((regexp
1729 (cond
1730 ((eq (car option) 'indentation)
1731 (whitespace-indentation-regexp))
1732 ((eq (car option) 'indentation::tab)
1733 (whitespace-indentation-regexp 'tab))
1734 ((eq (car option) 'indentation::space)
1735 (whitespace-indentation-regexp 'space))
1736 ((eq (car option) 'space-after-tab)
1737 (whitespace-space-after-tab-regexp))
1738 ((eq (car option) 'space-after-tab::tab)
1739 (whitespace-space-after-tab-regexp 'tab))
1740 ((eq (car option) 'space-after-tab::space)
1741 (whitespace-space-after-tab-regexp 'space))
1742 (t
1743 (cdr option)))))
1744 (and (re-search-forward regexp rend t)
1745 (setq has-bogus t))))
1746 whitespace-report-list)))
94dc593f 1747 (when (if report-if-bogus has-bogus t)
55d1cfe8
VJL
1748 (whitespace-kill-buffer whitespace-report-buffer-name)
1749 ;; `whitespace-indent-tabs-mode' is local to current buffer
ce203001
VJL
1750 ;; `whitespace-tab-width' is local to current buffer
1751 (let ((ws-indent-tabs-mode whitespace-indent-tabs-mode)
1752 (ws-tab-width whitespace-tab-width))
55d1cfe8
VJL
1753 (with-current-buffer (get-buffer-create
1754 whitespace-report-buffer-name)
1755 (erase-buffer)
1756 (insert (if ws-indent-tabs-mode
1757 (car whitespace-report-text)
1758 (cdr whitespace-report-text)))
1759 (goto-char (point-min))
1760 (forward-line 3)
1761 (dolist (option whitespace-report-list)
1762 (forward-line 1)
1763 (whitespace-mark-x
ae68f2d8 1764 27 (memq (car option) whitespace-style))
55d1cfe8
VJL
1765 (whitespace-mark-x 7 (car bogus-list))
1766 (setq bogus-list (cdr bogus-list)))
94dc593f 1767 (forward-line 1)
55d1cfe8 1768 (whitespace-insert-value ws-indent-tabs-mode)
ce203001 1769 (whitespace-insert-value ws-tab-width)
55d1cfe8
VJL
1770 (when has-bogus
1771 (goto-char (point-max))
1772 (insert " Type `M-x whitespace-cleanup'"
1773 " to cleanup the buffer.\n\n"
1774 " Type `M-x whitespace-cleanup-region'"
1775 " to cleanup a region.\n\n"))
1776 (whitespace-display-window (current-buffer)))))
94dc593f 1777 has-bogus))))
c9dff4e3
VJL
1778
1779\f
30d0ade9
VJL
1780;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1781;;;; Internal functions
1782
1783
c9dff4e3 1784(defvar whitespace-font-lock-mode nil
30d0ade9 1785 "Used to remember whether a buffer had font lock mode on or not.")
30d0ade9 1786
c9dff4e3 1787(defvar whitespace-font-lock nil
30d0ade9 1788 "Used to remember whether a buffer initially had font lock on or not.")
30d0ade9 1789
c9dff4e3 1790(defvar whitespace-font-lock-keywords nil
30d0ade9 1791 "Used to save locally `font-lock-keywords' value.")
30d0ade9
VJL
1792
1793
c9dff4e3 1794(defconst whitespace-help-text
30d0ade9 1795 "\
55d1cfe8
VJL
1796 Whitespace Toggle Options
1797
1798 FACES
1799 [] t - toggle TAB visualization
1800 [] s - toggle SPACE and HARD SPACE visualization
1801 [] r - toggle trailing blanks visualization
1802 [] l - toggle \"long lines\" visualization
1803 [] L - toggle \"long lines\" tail visualization
1804 [] n - toggle NEWLINE visualization
1805 [] e - toggle empty line at bob and/or eob visualization
1806 [] C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode')
1807 [] I - toggle indentation SPACEs visualization
1808 [] i - toggle indentation TABs visualization
1809 [] C-a - toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1810 [] A - toggle SPACEs after TAB: SPACEs visualization
1811 [] a - toggle SPACEs after TAB: TABs visualization
1812 [] C-b - toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1813 [] B - toggle SPACEs before TAB: SPACEs visualization
1814 [] b - toggle SPACEs before TAB: TABs visualization
1815
1816 DISPLAY TABLE
1817 [] T - toggle TAB visualization
1818 [] S - toggle SPACE and HARD SPACE visualization
1819 [] N - toggle NEWLINE visualization
1820
ae68f2d8 1821 x - restore `whitespace-style' value
30d0ade9
VJL
1822
1823 ? - display this text\n\n"
c9dff4e3 1824 "Text for whitespace toggle options.")
30d0ade9
VJL
1825
1826
c9dff4e3
VJL
1827(defconst whitespace-help-buffer-name "*Whitespace Toggle Options*"
1828 "The buffer name for whitespace toggle options.")
30d0ade9
VJL
1829
1830
55d1cfe8
VJL
1831(defun whitespace-insert-value (value)
1832 "Insert VALUE at column 20 of next line."
1833 (forward-line 1)
1834 (move-to-column 20 t)
1835 (insert (format "%s" value)))
1836
1837
94dc593f
VJL
1838(defun whitespace-mark-x (nchars condition)
1839 "Insert the mark ('X' or ' ') after NCHARS depending on CONDITION."
1840 (forward-char nchars)
1841 (insert (if condition "X" " ")))
1842
1843
c9dff4e3 1844(defun whitespace-insert-option-mark (the-list the-value)
30d0ade9 1845 "Insert the option mark ('X' or ' ') in toggle options buffer."
ae68f2d8 1846 (goto-char (point-min))
55d1cfe8 1847 (forward-line 2)
30d0ade9 1848 (dolist (sym the-list)
ae68f2d8
VJL
1849 (if (eq sym 'help-newline)
1850 (forward-line 2)
1851 (forward-line 1)
1852 (whitespace-mark-x 2 (memq sym the-value)))))
30d0ade9
VJL
1853
1854
ae68f2d8 1855(defun whitespace-help-on (style)
c9dff4e3
VJL
1856 "Display the whitespace toggle options."
1857 (unless (get-buffer whitespace-help-buffer-name)
30d0ade9 1858 (delete-other-windows)
c9dff4e3 1859 (let ((buffer (get-buffer-create whitespace-help-buffer-name)))
30d0ade9
VJL
1860 (save-excursion
1861 (set-buffer buffer)
1862 (erase-buffer)
c9dff4e3 1863 (insert whitespace-help-text)
c9dff4e3 1864 (whitespace-insert-option-mark
ae68f2d8 1865 whitespace-style-value-list style)
94dc593f
VJL
1866 (whitespace-display-window buffer)))))
1867
1868
1869(defun whitespace-display-window (buffer)
1870 "Display BUFFER in a new window."
1871 (goto-char (point-min))
1872 (set-buffer-modified-p nil)
1873 (let ((size (- (window-height)
1874 (max window-min-height
1875 (1+ (count-lines (point-min)
1876 (point-max)))))))
1877 (when (<= size 0)
1878 (kill-buffer buffer)
1879 (error "Frame height is too small; \
c9dff4e3 1880can't split window to display whitespace toggle options"))
94dc593f 1881 (set-window-buffer (split-window nil size) buffer)))
30d0ade9
VJL
1882
1883
55d1cfe8
VJL
1884(defun whitespace-kill-buffer (buffer-name)
1885 "Kill buffer BUFFER-NAME and windows related with it."
1886 (let ((buffer (get-buffer buffer-name)))
30d0ade9
VJL
1887 (when buffer
1888 (delete-windows-on buffer)
1889 (kill-buffer buffer))))
1890
1891
55d1cfe8
VJL
1892(defun whitespace-help-off ()
1893 "Remove the buffer and window of the whitespace toggle options."
1894 (whitespace-kill-buffer whitespace-help-buffer-name))
1895
1896
c9dff4e3 1897(defun whitespace-interactive-char (local-p)
30d0ade9
VJL
1898 "Interactive function to read a char and return a symbol.
1899
1900If LOCAL-P is non-nil, it uses a local context; otherwise, it
1901uses a global context.
1902
b502217b 1903It accepts one of the following chars:
30d0ade9
VJL
1904
1905 CHAR MEANING
55d1cfe8 1906 (VIA FACES)
040f578c
VJL
1907 t toggle TAB visualization
1908 s toggle SPACE and HARD SPACE visualization
1909 r toggle trailing blanks visualization
040f578c 1910 l toggle \"long lines\" visualization
9f3b76d5 1911 L toggle \"long lines\" tail visualization
040f578c 1912 n toggle NEWLINE visualization
97a739d5 1913 e toggle empty line at bob and/or eob visualization
55d1cfe8
VJL
1914 C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
1915 I toggle indentation SPACEs visualization
1916 i toggle indentation TABs visualization
1917 C-a toggle SPACEs after TAB visualization (via `indent-tabs-mode')
1918 A toggle SPACEs after TAB: SPACEs visualization
1919 a toggle SPACEs after TAB: TABs visualization
1920 C-b toggle SPACEs before TAB visualization (via `indent-tabs-mode')
1921 B toggle SPACEs before TAB: SPACEs visualization
1922 b toggle SPACEs before TAB: TABs visualization
1923
1924 (VIA DISPLAY TABLE)
1925 T toggle TAB visualization
1926 S toggle SPACE and HARD SPACE visualization
1927 N toggle NEWLINE visualization
1928
ae68f2d8 1929 x restore `whitespace-style' value
30d0ade9
VJL
1930 ? display brief help
1931
c9dff4e3
VJL
1932See also `whitespace-toggle-option-alist'."
1933 (let* ((is-off (not (if local-p
1934 whitespace-mode
1935 global-whitespace-mode)))
ae68f2d8
VJL
1936 (style (cond (is-off whitespace-style) ; use default value
1937 (local-p whitespace-active-style)
1938 (t whitespace-toggle-style)))
30d0ade9 1939 (prompt
c9dff4e3 1940 (format "Whitespace Toggle %s (type ? for further options)-"
30d0ade9
VJL
1941 (if local-p "Local" "Global")))
1942 ch sym)
1943 ;; read a valid option and get the corresponding symbol
1944 (save-window-excursion
1945 (condition-case data
1946 (progn
1947 (while
1948 ;; while condition
1949 (progn
1950 (setq ch (read-char prompt))
1951 (not
1952 (setq sym
c9dff4e3
VJL
1953 (cdr
1954 (assq ch whitespace-toggle-option-alist)))))
30d0ade9
VJL
1955 ;; while body
1956 (if (eq ch ?\?)
ae68f2d8 1957 (whitespace-help-on style)
30d0ade9 1958 (ding)))
c9dff4e3 1959 (whitespace-help-off)
30d0ade9
VJL
1960 (message " ")) ; clean echo area
1961 ;; handler
1962 ((quit error)
c9dff4e3 1963 (whitespace-help-off)
30d0ade9
VJL
1964 (error (error-message-string data)))))
1965 (list sym))) ; return the apropriate symbol
1966
1967
ae68f2d8 1968(defun whitespace-toggle-list (local-p arg the-list)
30d0ade9
VJL
1969 "Toggle options in THE-LIST based on list ARG.
1970
1971If LOCAL-P is non-nil, it uses a local context; otherwise, it
1972uses a global context.
1973
1974ARG is a list of options to be toggled.
1975
1976THE-LIST is a list of options. This list will be toggled and the
ae68f2d8 1977resultant list will be returned."
c9dff4e3 1978 (unless (if local-p whitespace-mode global-whitespace-mode)
ae68f2d8 1979 (setq the-list whitespace-style))
30d0ade9
VJL
1980 (setq the-list (copy-sequence the-list)) ; keep original list
1981 (dolist (sym (if (listp arg) arg (list arg)))
1982 (cond
ae68f2d8
VJL
1983 ;; ignore help value
1984 ((eq sym 'help-newline))
30d0ade9 1985 ;; restore default values
ae68f2d8
VJL
1986 ((eq sym 'whitespace-style)
1987 (setq the-list whitespace-style))
30d0ade9 1988 ;; toggle valid values
ae68f2d8 1989 ((memq sym whitespace-style-value-list)
30d0ade9
VJL
1990 (setq the-list (if (memq sym the-list)
1991 (delq sym the-list)
1992 (cons sym the-list))))))
1993 the-list)
1994
ae68f2d8 1995
1ed216db
GM
1996(defvar whitespace-display-table nil
1997 "Used to save a local display table.")
1998
1999(defvar whitespace-display-table-was-local nil
2000 "Used to remember whether a buffer initially had a local display table.")
30d0ade9 2001
ae68f2d8 2002
c9dff4e3
VJL
2003(defun whitespace-turn-on ()
2004 "Turn on whitespace visualization."
55d1cfe8 2005 ;; prepare local hooks
94dc593f 2006 (whitespace-add-local-hook)
55d1cfe8
VJL
2007 ;; create whitespace local buffer environment
2008 (set (make-local-variable 'whitespace-font-lock-mode) nil)
2009 (set (make-local-variable 'whitespace-font-lock) nil)
2010 (set (make-local-variable 'whitespace-font-lock-keywords) nil)
2011 (set (make-local-variable 'whitespace-display-table) nil)
2012 (set (make-local-variable 'whitespace-display-table-was-local) nil)
ae68f2d8
VJL
2013 (set (make-local-variable 'whitespace-active-style)
2014 (if (listp whitespace-style)
2015 whitespace-style
2016 (list whitespace-style)))
55d1cfe8
VJL
2017 (set (make-local-variable 'whitespace-indent-tabs-mode)
2018 indent-tabs-mode)
2019 (set (make-local-variable 'whitespace-tab-width)
2020 tab-width)
2021 ;; turn on whitespace
ae68f2d8
VJL
2022 (when whitespace-active-style
2023 (whitespace-color-on)
c9dff4e3 2024 (whitespace-display-char-on)))
30d0ade9
VJL
2025
2026
c9dff4e3 2027(defun whitespace-turn-off ()
b502217b 2028 "Turn off whitespace visualization."
94dc593f 2029 (whitespace-remove-local-hook)
ae68f2d8
VJL
2030 (when whitespace-active-style
2031 (whitespace-color-off)
c9dff4e3 2032 (whitespace-display-char-off)))
30d0ade9
VJL
2033
2034
ae68f2d8
VJL
2035(defun whitespace-style-face-p ()
2036 "Return t if there is some visualization via face."
2037 (or (memq 'tabs whitespace-active-style)
2038 (memq 'spaces whitespace-active-style)
2039 (memq 'trailing whitespace-active-style)
2040 (memq 'lines whitespace-active-style)
2041 (memq 'lines-tail whitespace-active-style)
2042 (memq 'newline whitespace-active-style)
2043 (memq 'empty whitespace-active-style)
2044 (memq 'indentation whitespace-active-style)
2045 (memq 'indentation::tab whitespace-active-style)
2046 (memq 'indentation::space whitespace-active-style)
2047 (memq 'space-after-tab whitespace-active-style)
2048 (memq 'space-after-tab::tab whitespace-active-style)
2049 (memq 'space-after-tab::space whitespace-active-style)
2050 (memq 'space-before-tab whitespace-active-style)
2051 (memq 'space-before-tab::tab whitespace-active-style)
2052 (memq 'space-before-tab::space whitespace-active-style)))
2053
2054
c9dff4e3 2055(defun whitespace-color-on ()
040f578c 2056 "Turn on color visualization."
ae68f2d8 2057 (when (whitespace-style-face-p)
c9dff4e3
VJL
2058 (unless whitespace-font-lock
2059 (setq whitespace-font-lock t
2060 whitespace-font-lock-keywords
30d0ade9
VJL
2061 (copy-sequence font-lock-keywords)))
2062 ;; turn off font lock
55d1cfe8
VJL
2063 (set (make-local-variable 'whitespace-font-lock-mode)
2064 font-lock-mode)
30d0ade9 2065 (font-lock-mode 0)
c9dff4e3 2066 ;; add whitespace-mode color into font lock
ae68f2d8 2067 (when (memq 'spaces whitespace-active-style)
30d0ade9
VJL
2068 (font-lock-add-keywords
2069 nil
2070 (list
2071 ;; Show SPACEs
c9dff4e3 2072 (list whitespace-space-regexp 1 whitespace-space t)
30d0ade9 2073 ;; Show HARD SPACEs
c9dff4e3 2074 (list whitespace-hspace-regexp 1 whitespace-hspace t))
30d0ade9 2075 t))
ae68f2d8 2076 (when (memq 'tabs whitespace-active-style)
30d0ade9
VJL
2077 (font-lock-add-keywords
2078 nil
2079 (list
2080 ;; Show TABs
c9dff4e3 2081 (list whitespace-tab-regexp 1 whitespace-tab t))
30d0ade9 2082 t))
ae68f2d8 2083 (when (memq 'trailing whitespace-active-style)
30d0ade9
VJL
2084 (font-lock-add-keywords
2085 nil
2086 (list
2087 ;; Show trailing blanks
2788143d 2088 (list whitespace-trailing-regexp 1 whitespace-trailing t))
30d0ade9 2089 t))
ae68f2d8
VJL
2090 (when (or (memq 'lines whitespace-active-style)
2091 (memq 'lines-tail whitespace-active-style))
30d0ade9
VJL
2092 (font-lock-add-keywords
2093 nil
2094 (list
2095 ;; Show "long" lines
9f3b76d5
VJL
2096 (list
2097 (format
2098 "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
55d1cfe8 2099 whitespace-tab-width (1- whitespace-tab-width)
c9dff4e3 2100 (/ whitespace-line-column tab-width)
55d1cfe8 2101 (let ((rem (% whitespace-line-column whitespace-tab-width)))
9f3b76d5
VJL
2102 (if (zerop rem)
2103 ""
2104 (format ".\\{%d\\}" rem))))
ae68f2d8 2105 (if (memq 'lines whitespace-active-style)
9f3b76d5
VJL
2106 0 ; whole line
2107 2) ; line tail
c9dff4e3 2108 whitespace-line t))
30d0ade9 2109 t))
55d1cfe8 2110 (cond
ae68f2d8 2111 ((memq 'space-before-tab whitespace-active-style)
55d1cfe8
VJL
2112 (font-lock-add-keywords
2113 nil
2114 (list
2115 ;; Show SPACEs before TAB (indent-tabs-mode)
2116 (list whitespace-space-before-tab-regexp
2117 (if whitespace-indent-tabs-mode 1 2)
2118 whitespace-space-before-tab t))
2119 t))
ae68f2d8 2120 ((memq 'space-before-tab::tab whitespace-active-style)
30d0ade9
VJL
2121 (font-lock-add-keywords
2122 nil
2123 (list
55d1cfe8 2124 ;; Show SPACEs before TAB (SPACEs)
c9dff4e3
VJL
2125 (list whitespace-space-before-tab-regexp
2126 1 whitespace-space-before-tab t))
30d0ade9 2127 t))
ae68f2d8 2128 ((memq 'space-before-tab::space whitespace-active-style)
97a739d5
VJL
2129 (font-lock-add-keywords
2130 nil
2131 (list
55d1cfe8
VJL
2132 ;; Show SPACEs before TAB (TABs)
2133 (list whitespace-space-before-tab-regexp
2134 2 whitespace-space-before-tab t))
2135 t)))
2136 (cond
ae68f2d8 2137 ((memq 'indentation whitespace-active-style)
55d1cfe8
VJL
2138 (font-lock-add-keywords
2139 nil
2140 (list
2141 ;; Show indentation SPACEs (indent-tabs-mode)
2142 (list (whitespace-indentation-regexp)
c9dff4e3 2143 1 whitespace-indentation t))
97a739d5 2144 t))
ae68f2d8 2145 ((memq 'indentation::tab whitespace-active-style)
55d1cfe8
VJL
2146 (font-lock-add-keywords
2147 nil
2148 (list
2149 ;; Show indentation SPACEs (SPACEs)
2150 (list (whitespace-indentation-regexp 'tab)
2151 1 whitespace-indentation t))
2152 t))
ae68f2d8 2153 ((memq 'indentation::space whitespace-active-style)
55d1cfe8
VJL
2154 (font-lock-add-keywords
2155 nil
2156 (list
2157 ;; Show indentation SPACEs (TABs)
2158 (list (whitespace-indentation-regexp 'space)
2159 1 whitespace-indentation t))
2160 t)))
ae68f2d8 2161 (when (memq 'empty whitespace-active-style)
97a739d5
VJL
2162 (font-lock-add-keywords
2163 nil
2164 (list
2165 ;; Show empty lines at beginning of buffer
c9dff4e3
VJL
2166 (list whitespace-empty-at-bob-regexp
2167 1 whitespace-empty t))
97a739d5
VJL
2168 t)
2169 (font-lock-add-keywords
2170 nil
2171 (list
2172 ;; Show empty lines at end of buffer
c9dff4e3
VJL
2173 (list whitespace-empty-at-eob-regexp
2174 1 whitespace-empty t))
97a739d5 2175 t))
55d1cfe8 2176 (cond
ae68f2d8 2177 ((memq 'space-after-tab whitespace-active-style)
97a739d5
VJL
2178 (font-lock-add-keywords
2179 nil
2180 (list
55d1cfe8
VJL
2181 ;; Show SPACEs after TAB (indent-tabs-mode)
2182 (list (whitespace-space-after-tab-regexp)
c9dff4e3 2183 1 whitespace-space-after-tab t))
97a739d5 2184 t))
ae68f2d8 2185 ((memq 'space-after-tab::tab whitespace-active-style)
55d1cfe8
VJL
2186 (font-lock-add-keywords
2187 nil
2188 (list
2189 ;; Show SPACEs after TAB (SPACEs)
2190 (list (whitespace-space-after-tab-regexp 'tab)
2191 1 whitespace-space-after-tab t))
2192 t))
ae68f2d8 2193 ((memq 'space-after-tab::space whitespace-active-style)
55d1cfe8
VJL
2194 (font-lock-add-keywords
2195 nil
2196 (list
2197 ;; Show SPACEs after TAB (TABs)
2198 (list (whitespace-space-after-tab-regexp 'space)
2199 1 whitespace-space-after-tab t))
2200 t)))
30d0ade9
VJL
2201 ;; now turn on font lock and highlight blanks
2202 (font-lock-mode 1)))
2203
2204
c9dff4e3 2205(defun whitespace-color-off ()
040f578c 2206 "Turn off color visualization."
ae68f2d8
VJL
2207 ;; turn off font lock
2208 (when (whitespace-style-face-p)
040f578c 2209 (font-lock-mode 0)
c9dff4e3
VJL
2210 (when whitespace-font-lock
2211 (setq whitespace-font-lock nil
2212 font-lock-keywords whitespace-font-lock-keywords))
30d0ade9 2213 ;; restore original font lock state
c9dff4e3 2214 (font-lock-mode whitespace-font-lock-mode)))
30d0ade9
VJL
2215
2216\f
2217;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2218;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
2219
2220
ae68f2d8
VJL
2221(defun whitespace-style-mark-p ()
2222 "Return t if there is some visualization via display table."
2223 (or (memq 'tab-mark whitespace-active-style)
2224 (memq 'space-mark whitespace-active-style)
2225 (memq 'newline-mark whitespace-active-style)))
2226
2227
c9dff4e3 2228(defsubst whitespace-char-valid-p (char)
30d0ade9
VJL
2229 ;; This check should be improved!!!
2230 (or (< char 256)
434b9acb 2231 (characterp char)))
30d0ade9
VJL
2232
2233
c9dff4e3 2234(defun whitespace-display-vector-p (vec)
30d0ade9
VJL
2235 "Return true if every character in vector VEC can be displayed."
2236 (let ((i (length vec)))
2237 (when (> i 0)
2238 (while (and (>= (setq i (1- i)) 0)
c9dff4e3 2239 (whitespace-char-valid-p (aref vec i))))
30d0ade9
VJL
2240 (< i 0))))
2241
2242
c9dff4e3 2243(defun whitespace-display-char-on ()
30d0ade9 2244 "Turn on character display mapping."
ae68f2d8
VJL
2245 (when (and whitespace-display-mappings
2246 (whitespace-style-mark-p))
30d0ade9
VJL
2247 (let (vecs vec)
2248 ;; Remember whether a buffer has a local display table.
c9dff4e3
VJL
2249 (unless whitespace-display-table-was-local
2250 (setq whitespace-display-table-was-local t
2251 whitespace-display-table
30d0ade9
VJL
2252 (copy-sequence buffer-display-table)))
2253 (unless buffer-display-table
2254 (setq buffer-display-table (make-display-table)))
c9dff4e3 2255 (dolist (entry whitespace-display-mappings)
55d1cfe8 2256 ;; check if it is to display this mark
ae68f2d8 2257 (when (memq (car entry) whitespace-style)
55d1cfe8
VJL
2258 ;; Get a displayable mapping.
2259 (setq vecs (cddr entry))
2260 (while (and vecs
2261 (not (whitespace-display-vector-p (car vecs))))
2262 (setq vecs (cdr vecs)))
2263 ;; Display a valid mapping.
2264 (when vecs
2265 (setq vec (copy-sequence (car vecs)))
2266 ;; NEWLINE char
2267 (when (and (eq (cadr entry) ?\n)
ae68f2d8 2268 (memq 'newline whitespace-active-style))
55d1cfe8
VJL
2269 ;; Only insert face bits on NEWLINE char mapping to avoid
2270 ;; obstruction of other faces like TABs and (HARD) SPACEs
2271 ;; faces, font-lock faces, etc.
30d0ade9 2272 (dotimes (i (length vec))
30d0ade9 2273 (or (eq (aref vec i) ?\n)
c9dff4e3
VJL
2274 (aset vec i
2275 (make-glyph-code (aref vec i)
2276 whitespace-newline)))))
30d0ade9 2277 ;; Display mapping
55d1cfe8 2278 (aset buffer-display-table (cadr entry) vec)))))))
30d0ade9
VJL
2279
2280
c9dff4e3 2281(defun whitespace-display-char-off ()
30d0ade9 2282 "Turn off character display mapping."
c9dff4e3 2283 (and whitespace-display-mappings
ae68f2d8 2284 (whitespace-style-mark-p)
c9dff4e3
VJL
2285 whitespace-display-table-was-local
2286 (setq whitespace-display-table-was-local nil
2287 buffer-display-table whitespace-display-table)))
596c0ee1
VJL
2288
2289\f
94dc593f
VJL
2290;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2291;;;; Hook
2292
2293
2294(defun whitespace-action-when-on ()
2295 "Action to be taken always when local whitespace is turned on."
2296 (cond ((memq 'cleanup whitespace-action)
2297 (whitespace-cleanup))
2298 ((memq 'report-on-bogus whitespace-action)
2299 (whitespace-report nil t))))
2300
2301
2302(defun whitespace-add-local-hook ()
2303 "Add some whitespace hooks locally."
2304 (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
2305 (add-hook 'kill-buffer-hook 'whitespace-kill-buffer-hook nil t))
2306
2307
2308(defun whitespace-remove-local-hook ()
2309 "Remove some whitespace hooks locally."
2310 (remove-hook 'write-file-functions 'whitespace-write-file-hook t)
2311 (remove-hook 'kill-buffer-hook 'whitespace-kill-buffer-hook t))
2312
2313
2314(defun whitespace-write-file-hook ()
2315 "Action to be taken when buffer is written.
2316It should be added buffer-locally to `write-file-functions'."
2317 (when (whitespace-action)
2318 (error "Abort write due to whitespace problems in %s"
2319 (buffer-name)))
2320 nil) ; continue hook processing
2321
2322
2323(defun whitespace-kill-buffer-hook ()
2324 "Action to be taken when buffer is killed.
2325It should be added buffer-locally to `kill-buffer-hook'."
2326 (whitespace-action)
55d1cfe8 2327 nil) ; continue hook processing
94dc593f
VJL
2328
2329
2330(defun whitespace-action ()
2331 "Action to be taken when buffer is killed or written.
2332Return t when the action should be aborted."
2333 (cond ((memq 'auto-cleanup whitespace-action)
2334 (whitespace-cleanup)
2335 nil)
2336 ((memq 'abort-on-bogus whitespace-action)
2337 (whitespace-report nil t))
2338 (t
2339 nil)))
2340
2341\f
30d0ade9
VJL
2342;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2343
2344
1e2b96c2 2345(defun whitespace-unload-function ()
94dc593f
VJL
2346 "Unload the whitespace library."
2347 (global-whitespace-mode -1)
2348 ;; be sure all local whitespace mode is turned off
2349 (save-current-buffer
2350 (dolist (buf (buffer-list))
2351 (set-buffer buf)
2352 (whitespace-mode -1)))
2353 nil) ; continue standard unloading
2354
1e2b96c2 2355
c9dff4e3 2356(provide 'whitespace)
30d0ade9
VJL
2357
2358
c9dff4e3 2359(run-hooks 'whitespace-load-hook)
30d0ade9
VJL
2360
2361
17f6865b 2362;; arch-tag: 1b1e2500-dbd4-4a26-8f7a-5a5edfd3c97e
c9dff4e3 2363;;; whitespace.el ends here