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