update nadvice
[bpt/emacs.git] / lisp / elec-pair.el
CommitLineData
7514d3f8
SM
1;;; elec-pair.el --- Automatic parenthesis pairing -*- lexical-binding:t -*-
2
ba318903 3;; Copyright (C) 2013-2014 Free Software Foundation, Inc.
7514d3f8
SM
4
5;; Author: João Távora <joaotavora@gmail.com>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;;; Code:
25
26(require 'electric)
27
28;;; Electric pairing.
29
30(defcustom electric-pair-pairs
31 '((?\" . ?\"))
32 "Alist of pairs that should be used regardless of major mode.
33
34Pairs of delimiters in this list are a fallback in case they have
35no syntax relevant to `electric-pair-mode' in the mode's syntax
36table.
37
38See also the variable `electric-pair-text-pairs'."
39 :version "24.1"
40 :group 'electricity
41 :type '(repeat (cons character character)))
42
43;;;###autoload
44(defcustom electric-pair-text-pairs
45 '((?\" . ?\" ))
46 "Alist of pairs that should always be used in comments and strings.
47
48Pairs of delimiters in this list are a fallback in case they have
49no syntax relevant to `electric-pair-mode' in the syntax table
50defined in `electric-pair-text-syntax-table'"
51 :version "24.4"
52 :group 'electricity
53 :type '(repeat (cons character character)))
54
55(defcustom electric-pair-skip-self #'electric-pair-default-skip-self
56 "If non-nil, skip char instead of inserting a second closing paren.
57
58When inserting a closing paren character right before the same character,
59just skip that character instead, so that hitting ( followed by ) results
60in \"()\" rather than \"())\".
61
62This can be convenient for people who find it easier to hit ) than C-f.
63
64Can also be a function of one argument (the closer char just
65inserted), in which case that function's return value is
66considered instead."
67 :version "24.1"
68 :group 'electricity
69 :type '(choice
70 (const :tag "Never skip" nil)
71 (const :tag "Help balance" electric-pair-default-skip-self)
72 (const :tag "Always skip" t)
73 function))
74
75(defcustom electric-pair-inhibit-predicate
76 #'electric-pair-default-inhibit
77 "Predicate to prevent insertion of a matching pair.
78
79The function is called with a single char (the opening char just inserted).
80If it returns non-nil, then `electric-pair-mode' will not insert a matching
81closer."
82 :version "24.4"
83 :group 'electricity
84 :type '(choice
85 (const :tag "Conservative" electric-pair-conservative-inhibit)
86 (const :tag "Help balance" electric-pair-default-inhibit)
87 (const :tag "Always pair" ignore)
88 function))
89
90(defcustom electric-pair-preserve-balance t
91 "Non-nil if default pairing and skipping should help balance parentheses.
92
93The default values of `electric-pair-inhibit-predicate' and
94`electric-pair-skip-self' check this variable before delegating to other
7e99158a
PE
95predicates responsible for making decisions on whether to pair/skip some
96characters based on the actual state of the buffer's parentheses and
7514d3f8
SM
97quotes."
98 :version "24.4"
99 :group 'electricity
100 :type 'boolean)
101
102(defcustom electric-pair-delete-adjacent-pairs t
103 "If non-nil, backspacing an open paren also deletes adjacent closer.
104
105Can also be a function of no arguments, in which case that function's
106return value is considered instead."
107 :version "24.4"
108 :group 'electricity
109 :type '(choice
110 (const :tag "Yes" t)
111 (const :tag "No" nil)
112 function))
113
114(defcustom electric-pair-open-newline-between-pairs t
115 "If non-nil, a newline between adjacent parentheses opens an extra one.
116
117Can also be a function of no arguments, in which case that function's
118return value is considered instead."
119 :version "24.4"
120 :group 'electricity
121 :type '(choice
122 (const :tag "Yes" t)
123 (const :tag "No" nil)
124 function))
125
126(defcustom electric-pair-skip-whitespace t
127 "If non-nil skip whitespace when skipping over closing parens.
128
129The specific kind of whitespace skipped is given by the variable
130`electric-pair-skip-whitespace-chars'.
131
132The symbol `chomp' specifies that the skipped-over whitespace
133should be deleted.
134
135Can also be a function of no arguments, in which case that function's
136return value is considered instead."
137 :version "24.4"
138 :group 'electricity
139 :type '(choice
140 (const :tag "Yes, jump over whitespace" t)
9c61f806 141 (const :tag "Yes, and delete whitespace" chomp)
7514d3f8
SM
142 (const :tag "No, no whitespace skipping" nil)
143 function))
144
145(defcustom electric-pair-skip-whitespace-chars (list ?\t ?\s ?\n)
146 "Whitespace characters considered by `electric-pair-skip-whitespace'."
147 :version "24.4"
148 :group 'electricity
149 :type '(choice (set (const :tag "Space" ?\s)
150 (const :tag "Tab" ?\t)
151 (const :tag "Newline" ?\n))
152 (list character)))
153
154(defun electric-pair--skip-whitespace ()
155 "Skip whitespace forward, not crossing comment or string boundaries."
156 (let ((saved (point))
157 (string-or-comment (nth 8 (syntax-ppss))))
158 (skip-chars-forward (apply #'string electric-pair-skip-whitespace-chars))
159 (unless (eq string-or-comment (nth 8 (syntax-ppss)))
160 (goto-char saved))))
161
162(defvar electric-pair-text-syntax-table prog-mode-syntax-table
163 "Syntax table used when pairing inside comments and strings.
164
165`electric-pair-mode' considers this syntax table only when point in inside
025f2c81 166quotes or comments. If lookup fails here, `electric-pair-text-pairs' will
7514d3f8
SM
167be considered.")
168
7514d3f8
SM
169(defun electric-pair-conservative-inhibit (char)
170 (or
171 ;; I find it more often preferable not to pair when the
172 ;; same char is next.
173 (eq char (char-after))
174 ;; Don't pair up when we insert the second of "" or of ((.
175 (and (eq char (char-before))
176 (eq char (char-before (1- (point)))))
177 ;; I also find it often preferable not to pair next to a word.
178 (eq (char-syntax (following-char)) ?w)))
179
180(defun electric-pair-syntax-info (command-event)
181 "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START).
182
183SYNTAX is COMMAND-EVENT's syntax character. PAIR is
184COMMAND-EVENT's pair. UNCONDITIONAL indicates the variables
185`electric-pair-pairs' or `electric-pair-text-pairs' were used to
186lookup syntax. STRING-OR-COMMENT-START indicates that point is
025f2c81 187inside a comment or string."
ee0761ca
JB
188 (let* ((pre-string-or-comment (or (bobp)
189 (nth 8 (save-excursion
190 (syntax-ppss (1- (point)))))))
7514d3f8
SM
191 (post-string-or-comment (nth 8 (syntax-ppss (point))))
192 (string-or-comment (and post-string-or-comment
193 pre-string-or-comment))
194 (table (if string-or-comment
195 electric-pair-text-syntax-table
196 (syntax-table)))
197 (table-syntax-and-pair (with-syntax-table table
198 (list (char-syntax command-event)
199 (or (matching-paren command-event)
200 command-event))))
201 (fallback (if string-or-comment
202 (append electric-pair-text-pairs
203 electric-pair-pairs)
204 electric-pair-pairs))
205 (direct (assq command-event fallback))
206 (reverse (rassq command-event fallback)))
207 (cond
208 ((memq (car table-syntax-and-pair)
209 '(?\" ?\( ?\) ?\$))
210 (append table-syntax-and-pair (list nil string-or-comment)))
211 (direct (if (eq (car direct) (cdr direct))
212 (list ?\" command-event t string-or-comment)
213 (list ?\( (cdr direct) t string-or-comment)))
214 (reverse (list ?\) (car reverse) t string-or-comment)))))
215
216(defun electric-pair--insert (char)
217 (let ((last-command-event char)
218 (blink-matching-paren nil)
219 (electric-pair-mode nil))
220 (self-insert-command 1)))
221
222(defun electric-pair--syntax-ppss (&optional pos where)
223 "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'.
224
025f2c81 225WHERE is a list defaulting to '(string comment) and indicates
7514d3f8
SM
226when to fallback to `parse-partial-sexp'."
227 (let* ((pos (or pos (point)))
228 (where (or where '(string comment)))
498d3768
JT
229 (quick-ppss (syntax-ppss pos))
230 (in-string (and (nth 3 quick-ppss) (memq 'string where)))
231 (in-comment (and (nth 4 quick-ppss) (memq 'comment where)))
190f899a
JT
232 (s-or-c-start (cond (in-string
233 (1+ (nth 8 quick-ppss)))
234 (in-comment
235 (goto-char (nth 8 quick-ppss))
236 (forward-comment (- (point-max)))
237 (skip-syntax-forward " >!")
238 (point)))))
239 (if s-or-c-start
7514d3f8 240 (with-syntax-table electric-pair-text-syntax-table
190f899a 241 (parse-partial-sexp s-or-c-start pos))
7514d3f8
SM
242 ;; HACK! cc-mode apparently has some `syntax-ppss' bugs
243 (if (memq major-mode '(c-mode c++ mode))
244 (parse-partial-sexp (point-min) pos)
498d3768 245 quick-ppss))))
7514d3f8 246
025f2c81
JB
247;; Balancing means controlling pairing and skipping of parentheses
248;; so that, if possible, the buffer ends up at least as balanced as
249;; before, if not more. The algorithm is slightly complex because
250;; some situations like "()))" need pairing to occur at the end but
251;; not at the beginning. Balancing should also happen independently
252;; for different types of parentheses, so that having your {}'s
253;; unbalanced doesn't keep `electric-pair-mode' from balancing your
254;; ()'s and your []'s.
7514d3f8 255(defun electric-pair--balance-info (direction string-or-comment)
7e99158a 256 "Examine lists forward or backward according to DIRECTION's sign.
7514d3f8
SM
257
258STRING-OR-COMMENT is info suitable for running `parse-partial-sexp'.
259
7e99158a 260Return a cons of two descriptions (MATCHED-P . PAIR) for the
025f2c81 261innermost and outermost lists that enclose point. The outermost
7514d3f8 262list enclosing point is either the first top-level or first
7e99158a 263mismatched list found by listing up.
7514d3f8 264
025f2c81
JB
265If the outermost list is matched, don't rely on its PAIR.
266If point is not enclosed by any lists, return ((t) . (t))."
7514d3f8
SM
267 (let* (innermost
268 outermost
269 (table (if string-or-comment
270 electric-pair-text-syntax-table
271 (syntax-table)))
272 (at-top-level-or-equivalent-fn
025f2c81
JB
273 ;; called when `scan-sexps' ran perfectly, when it found
274 ;; a parenthesis pointing in the direction of travel.
275 ;; Also when travel started inside a comment and exited it.
7514d3f8
SM
276 #'(lambda ()
277 (setq outermost (list t))
278 (unless innermost
279 (setq innermost (list t)))))
280 (ended-prematurely-fn
281 ;; called when `scan-sexps' crashed against a parenthesis
025f2c81 282 ;; pointing opposite the direction of travel. After
7514d3f8
SM
283 ;; traversing that character, the idea is to travel one sexp
284 ;; in the opposite direction looking for a matching
285 ;; delimiter.
286 #'(lambda ()
287 (let* ((pos (point))
288 (matched
289 (save-excursion
290 (cond ((< direction 0)
291 (condition-case nil
292 (eq (char-after pos)
293 (with-syntax-table table
294 (matching-paren
295 (char-before
296 (scan-sexps (point) 1)))))
297 (scan-error nil)))
298 (t
299 ;; In this case, no need to use
300 ;; `scan-sexps', we can use some
301 ;; `electric-pair--syntax-ppss' in this
302 ;; case (which uses the quicker
303 ;; `syntax-ppss' in some cases)
304 (let* ((ppss (electric-pair--syntax-ppss
305 (1- (point))))
306 (start (car (last (nth 9 ppss))))
307 (opener (char-after start)))
308 (and start
309 (eq (char-before pos)
310 (or (with-syntax-table table
311 (matching-paren opener))
312 opener))))))))
313 (actual-pair (if (> direction 0)
314 (char-before (point))
315 (char-after (point)))))
316 (unless innermost
317 (setq innermost (cons matched actual-pair)))
318 (unless matched
319 (setq outermost (cons matched actual-pair)))))))
320 (save-excursion
321 (while (not outermost)
322 (condition-case err
323 (with-syntax-table table
324 (scan-sexps (point) (if (> direction 0)
325 (point-max)
326 (- (point-max))))
327 (funcall at-top-level-or-equivalent-fn))
328 (scan-error
329 (cond ((or
330 ;; some error happened and it is not of the "ended
190f899a 331 ;; prematurely" kind...
7514d3f8
SM
332 (not (string-match "ends prematurely" (nth 1 err)))
333 ;; ... or we were in a comment and just came out of
334 ;; it.
335 (and string-or-comment
336 (not (nth 8 (syntax-ppss)))))
337 (funcall at-top-level-or-equivalent-fn))
338 (t
339 ;; exit the sexp
340 (goto-char (nth 3 err))
341 (funcall ended-prematurely-fn)))))))
342 (cons innermost outermost)))
343
190f899a 344(defvar electric-pair-string-bound-function 'point-max
10ee3b3f 345 "Next buffer position where strings are syntactically unexpected.
190f899a
JT
346Value is a function called with no arguments and returning a
347buffer position. Major modes should set this variable
348buffer-locally if they experience slowness with
349`electric-pair-mode' when pairing quotes.")
350
351(defun electric-pair--unbalanced-strings-p (char)
352 "Return non-nil if there are unbalanced strings started by CHAR."
353 (let* ((selector-ppss (syntax-ppss))
354 (relevant-ppss (save-excursion
355 (if (nth 4 selector-ppss) ; comment
356 (electric-pair--syntax-ppss
357 (progn
358 (goto-char (nth 8 selector-ppss))
359 (forward-comment (point-max))
360 (skip-syntax-backward " >!")
361 (point)))
362 (syntax-ppss
363 (funcall electric-pair-string-bound-function)))))
528c33b5 364 (string-delim (nth 3 relevant-ppss)))
190f899a
JT
365 (or (eq t string-delim)
366 (eq char string-delim))))
7514d3f8
SM
367
368(defun electric-pair--inside-string-p (char)
025f2c81 369 "Return non-nil if point is inside a string started by CHAR.
7514d3f8
SM
370
371A comments text is parsed with `electric-pair-text-syntax-table'.
372Also consider strings within comments, but not strings within
373strings."
374 ;; FIXME: could also consider strings within strings by examining
375 ;; delimiters.
025f2c81 376 (let ((ppss (electric-pair--syntax-ppss (point) '(comment))))
7514d3f8
SM
377 (memq (nth 3 ppss) (list t char))))
378
379(defun electric-pair-inhibit-if-helps-balance (char)
380 "Return non-nil if auto-pairing of CHAR would hurt parentheses' balance.
381
382Works by first removing the character from the buffer, then doing
383some list calculations, finally restoring the situation as if nothing
384happened."
385 (pcase (electric-pair-syntax-info char)
386 (`(,syntax ,pair ,_ ,s-or-c)
387 (unwind-protect
388 (progn
389 (delete-char -1)
390 (cond ((eq ?\( syntax)
391 (let* ((pair-data
392 (electric-pair--balance-info 1 s-or-c))
393 (outermost (cdr pair-data)))
394 (cond ((car outermost)
395 nil)
396 (t
397 (eq (cdr outermost) pair)))))
398 ((eq syntax ?\")
190f899a 399 (electric-pair--unbalanced-strings-p char))))
7514d3f8
SM
400 (insert-char char)))))
401
402(defun electric-pair-skip-if-helps-balance (char)
403 "Return non-nil if skipping CHAR would benefit parentheses' balance.
404
405Works by first removing the character from the buffer, then doing
406some list calculations, finally restoring the situation as if nothing
407happened."
408 (pcase (electric-pair-syntax-info char)
409 (`(,syntax ,pair ,_ ,s-or-c)
410 (unwind-protect
411 (progn
412 (delete-char -1)
413 (cond ((eq syntax ?\))
414 (let* ((pair-data
415 (electric-pair--balance-info
416 -1 s-or-c))
417 (innermost (car pair-data))
418 (outermost (cdr pair-data)))
419 (and
420 (cond ((car outermost)
421 (car innermost))
422 ((car innermost)
423 (not (eq (cdr outermost) pair)))))))
424 ((eq syntax ?\")
425 (electric-pair--inside-string-p char))))
426 (insert-char char)))))
427
428(defun electric-pair-default-skip-self (char)
429 (if electric-pair-preserve-balance
430 (electric-pair-skip-if-helps-balance char)
431 t))
432
433(defun electric-pair-default-inhibit (char)
434 (if electric-pair-preserve-balance
435 (electric-pair-inhibit-if-helps-balance char)
436 (electric-pair-conservative-inhibit char)))
437
438(defun electric-pair-post-self-insert-function ()
439 (let* ((pos (and electric-pair-mode (electric--after-char-pos)))
440 (skip-whitespace-info))
441 (pcase (electric-pair-syntax-info last-command-event)
442 (`(,syntax ,pair ,unconditional ,_)
443 (cond
444 ((null pos) nil)
445 ;; Wrap a pair around the active region.
446 ;;
447 ((and (memq syntax '(?\( ?\) ?\" ?\$)) (use-region-p))
448 ;; FIXME: To do this right, we'd need a post-self-insert-function
449 ;; so we could add-function around it and insert the closer after
450 ;; all the rest of the hook has run.
451 (if (or (eq syntax ?\")
452 (and (eq syntax ?\))
453 (>= (point) (mark)))
454 (and (not (eq syntax ?\)))
455 (>= (mark) (point))))
456 (save-excursion
457 (goto-char (mark))
458 (electric-pair--insert pair))
459 (delete-region pos (1- pos))
460 (electric-pair--insert pair)
461 (goto-char (mark))
462 (electric-pair--insert last-command-event)))
463 ;; Backslash-escaped: no pairing, no skipping.
464 ((save-excursion
465 (goto-char (1- pos))
466 (not (zerop (% (skip-syntax-backward "\\") 2))))
467 nil)
468 ;; Skip self.
469 ((and (memq syntax '(?\) ?\" ?\$))
470 (and (or unconditional
471 (if (functionp electric-pair-skip-self)
472 (funcall electric-pair-skip-self last-command-event)
473 electric-pair-skip-self))
474 (save-excursion
89f20f76
JT
475 (when (and (not (and unconditional
476 (eq syntax ?\")))
477 (setq skip-whitespace-info
478 (if (functionp electric-pair-skip-whitespace)
479 (funcall electric-pair-skip-whitespace)
480 electric-pair-skip-whitespace)))
7514d3f8
SM
481 (electric-pair--skip-whitespace))
482 (eq (char-after) last-command-event))))
483 ;; This is too late: rather than insert&delete we'd want to only
484 ;; skip (or insert in overwrite mode). The difference is in what
485 ;; goes in the undo-log and in the intermediate state which might
486 ;; be visible to other post-self-insert-hook. We'll just have to
487 ;; live with it for now.
488 (when skip-whitespace-info
489 (electric-pair--skip-whitespace))
490 (delete-region (1- pos) (if (eq skip-whitespace-info 'chomp)
491 (point)
492 pos))
493 (forward-char))
494 ;; Insert matching pair.
495 ((and (memq syntax `(?\( ?\" ?\$))
496 (not overwrite-mode)
497 (or unconditional
498 (not (funcall electric-pair-inhibit-predicate
499 last-command-event))))
500 (save-excursion (electric-pair--insert pair)))))
501 (t
502 (when (and (if (functionp electric-pair-open-newline-between-pairs)
503 (funcall electric-pair-open-newline-between-pairs)
504 electric-pair-open-newline-between-pairs)
505 (eq last-command-event ?\n)
e9d6c46a 506 (< (1+ (point-min)) (point) (point-max))
7514d3f8
SM
507 (eq (save-excursion
508 (skip-chars-backward "\t\s")
509 (char-before (1- (point))))
510 (matching-paren (char-after))))
511 (save-excursion (newline 1 t)))))))
512
513(put 'electric-pair-post-self-insert-function 'priority 20)
514
515(defun electric-pair-will-use-region ()
516 (and (use-region-p)
517 (memq (car (electric-pair-syntax-info last-command-event))
518 '(?\( ?\) ?\" ?\$))))
519
be411138
JT
520(defun electric-pair-delete-pair (arg &optional killp)
521 "When between adjacent paired delimiters, delete both of them.
522ARG and KILLP are passed directly to
523`backward-delete-char-untabify', which see."
524 (interactive "*p\nP")
525 (delete-char 1)
526 (backward-delete-char-untabify arg killp))
527
7514d3f8
SM
528(defvar electric-pair-mode-map
529 (let ((map (make-sparse-keymap)))
be411138
JT
530 (define-key map "\177"
531 `(menu-item
532 "" electric-pair-delete-pair
533 :filter
534 ,(lambda (cmd)
535 (let* ((prev (char-before))
536 (next (char-after))
537 (syntax-info (and prev
538 (electric-pair-syntax-info prev)))
539 (syntax (car syntax-info))
540 (pair (cadr syntax-info)))
541 (and next pair
542 (memq syntax '(?\( ?\" ?\$))
543 (eq pair next)
544 (if (functionp electric-pair-delete-adjacent-pairs)
545 (funcall electric-pair-delete-adjacent-pairs)
546 electric-pair-delete-adjacent-pairs)
547 cmd)))))
7514d3f8
SM
548 map)
549 "Keymap used by `electric-pair-mode'.")
550
551;;;###autoload
552(define-minor-mode electric-pair-mode
553 "Toggle automatic parens pairing (Electric Pair mode).
554With a prefix argument ARG, enable Electric Pair mode if ARG is
555positive, and disable it otherwise. If called from Lisp, enable
556the mode if ARG is omitted or nil.
557
558Electric Pair mode is a global minor mode. When enabled, typing
559an open parenthesis automatically inserts the corresponding
025f2c81 560closing parenthesis. (Likewise for brackets, etc.)."
7514d3f8
SM
561 :global t :group 'electricity
562 (if electric-pair-mode
563 (progn
564 (add-hook 'post-self-insert-hook
565 #'electric-pair-post-self-insert-function)
566 (electric--sort-post-self-insertion-hook)
567 (add-hook 'self-insert-uses-region-functions
568 #'electric-pair-will-use-region))
569 (remove-hook 'post-self-insert-hook
570 #'electric-pair-post-self-insert-function)
571 (remove-hook 'self-insert-uses-region-functions
572 #'electric-pair-will-use-region)))
573
574(provide 'elec-pair)
575
576;;; elec-pair.el ends here