* etags.c (CNL_SAVE_DEFINEDEF): Set linecharno for use by readline.
[bpt/emacs.git] / lisp / paren.el
CommitLineData
5e28918b 1;;; paren.el --- highlight matching paren.
b578f267 2
673cc3c5 3;; Copyright (C) 1993, 1996 Free Software Foundation, Inc.
5e28918b 4
e4c37df7
JB
5;; Author: rms@gnu.ai.mit.edu
6;; Maintainer: FSF
7;; Keywords: languages, faces
5e2325c9 8
5e28918b
JB
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
5e28918b
JB
25
26;;; Commentary:
27
28;; Load this and it will display highlighting on whatever
29;; paren matches the one before or after point.
30
31;;; Code:
32
eb0d9f08 33;; This is the overlay used to highlight the matching paren.
d1475aa1 34(defvar show-paren-overlay nil)
673cc3c5 35;; This is the overlay used to highlight the closeparen right before point.
eb0d9f08
RS
36(defvar show-paren-overlay-1 nil)
37
673cc3c5
RS
38(defvar show-paren-mode nil)
39(defvar show-paren-idle-timer nil)
40
eb0d9f08 41(defvar show-paren-mismatch-face nil)
5e28918b 42
673cc3c5
RS
43(defvar show-paren-delay (if (featurep 'lisp-float-type) 0.125 1)
44 "*Time in seconds to delay before showing the matching paren.")
45
30322a27 46(defvar show-paren-face 'region
673cc3c5
RS
47 "*Name of the face to use for showing the matching paren.")
48
49;;;###autoload
50(defun show-paren-mode (&optional arg)
51 "Toggle Show Paren mode.
52With prefix ARG, turn Show Paren mode on if and only if ARG is positive.
53Returns the new status of Show Paren mode (non-nil means on).
54
55When Show Paren mode is enabled, any matching parenthesis is highlighted
56after `show-paren-delay' seconds of Emacs idle time."
57 (interactive "P")
58 (if window-system
59 (let ((on-p (if arg
60 (> (prefix-numeric-value arg) 0)
61 (not show-paren-mode))))
62 (setq blink-matching-paren-on-screen (not on-p))
63 (and show-paren-idle-timer (cancel-timer show-paren-idle-timer))
64 (if on-p
65 (setq show-paren-idle-timer (run-with-idle-timer show-paren-delay t
66 'show-paren-function))
67 (and show-paren-overlay (overlay-buffer show-paren-overlay)
68 (delete-overlay show-paren-overlay))
69 (and show-paren-overlay-1 (overlay-buffer show-paren-overlay-1)
70 (delete-overlay show-paren-overlay-1)))
71 (setq show-paren-mode on-p))))
30322a27 72
d1475aa1
JB
73;; Find the place to show, if there is one,
74;; and show it until input arrives.
673cc3c5 75(defun show-paren-function ()
bac79b51 76 ;; Do nothing if no window system to display results with.
e4b93bab 77 ;; Do nothing if executing keyboard macro.
bac79b51 78 ;; Do nothing if input is pending.
26ee1a5d 79 (if window-system
80e16738 80 (let (pos dir mismatch (oldpos (point))
30322a27 81 (face show-paren-face))
cde4c890
RS
82 (cond ((eq (char-syntax (preceding-char)) ?\))
83 (setq dir -1))
84 ((eq (char-syntax (following-char)) ?\()
85 (setq dir 1)))
eb0d9f08
RS
86 (if dir
87 (save-excursion
88 (save-restriction
89 ;; Determine the range within which to look for a match.
90 (if blink-matching-paren-distance
91 (narrow-to-region (max (point-min)
92 (- (point) blink-matching-paren-distance))
93 (min (point-max)
94 (+ (point) blink-matching-paren-distance))))
95 ;; Scan across one sexp within that range.
96 (condition-case ()
97 (setq pos (scan-sexps (point) dir))
98 (error nil))
99 ;; See if the "matching" paren is the right kind of paren
100 ;; to match the one we started at.
101 (if pos
102 (let ((beg (min pos oldpos)) (end (max pos oldpos)))
103 (and (/= (char-syntax (char-after beg)) ?\$)
104 (setq mismatch
080d320d
RS
105 (not (eq (char-after (1- end))
106 ;; This can give nil.
107 (matching-paren (char-after beg))))))))
eb0d9f08
RS
108 ;; If they don't properly match, use a different face,
109 ;; or print a message.
110 (if mismatch
111 (progn
112 (and (null show-paren-mismatch-face)
113 (x-display-color-p)
00b05a42 114 (progn
fee7c89d
KH
115 (add-to-list 'facemenu-unlisted-faces
116 'paren-mismatch)
00b05a42
RS
117 (make-face 'paren-mismatch)
118 (or (face-nontrivial-p 'paren-mismatch t)
119 (progn
120 (set-face-background 'paren-mismatch
121 "purple")
122 (set-face-foreground 'paren-mismatch
123 "white")))
124 (setq show-paren-mismatch-face 'paren-mismatch)))
eb0d9f08
RS
125 (if show-paren-mismatch-face
126 (setq face show-paren-mismatch-face)
127 (message "Paren mismatch"))))
128 )))
80e16738 129 (cond (pos
eb0d9f08
RS
130 (if (= dir -1)
131 ;; If matching backwards, highlight the closeparen
132 ;; before point as well as its matching open.
133 (progn
134 (if show-paren-overlay-1
776b7d5a
RS
135 (move-overlay show-paren-overlay-1
136 (+ (point) dir) (point)
137 (current-buffer))
eb0d9f08 138 (setq show-paren-overlay-1
6f554752 139 (make-overlay (+ (point) dir) (point))))
329ff3a4
RS
140 ;; Always set the overlay face, since it varies.
141 (overlay-put show-paren-overlay-1 'face face))
eb0d9f08
RS
142 ;; Otherwise, turn off any such highlighting.
143 (and show-paren-overlay-1
144 (overlay-buffer show-paren-overlay-1)
145 (delete-overlay show-paren-overlay-1)))
146 ;; Turn on highlighting for the matching paren.
80e16738 147 (if show-paren-overlay
776b7d5a
RS
148 (move-overlay show-paren-overlay (- pos dir) pos
149 (current-buffer))
80e16738 150 (setq show-paren-overlay
329ff3a4
RS
151 (make-overlay (- pos dir) pos)))
152 ;; Always set the overlay face, since it varies.
153 (overlay-put show-paren-overlay 'face face))
80e16738 154 (t
eb0d9f08
RS
155 ;; If not at a paren that has a match,
156 ;; turn off any previous paren highlighting.
80e16738 157 (and show-paren-overlay (overlay-buffer show-paren-overlay)
eb0d9f08
RS
158 (delete-overlay show-paren-overlay))
159 (and show-paren-overlay-1 (overlay-buffer show-paren-overlay-1)
160 (delete-overlay show-paren-overlay-1)))))))
5e28918b 161
673cc3c5 162;;; For back compatibility we turn ourselves on if we're dumped or loaded.
625d837e 163(add-hook 'window-setup-hook '(lambda () (show-paren-mode t)))
673cc3c5
RS
164(show-paren-mode t)
165
3a3236d2
JB
166(provide 'paren)
167
168;;; paren.el ends here