* electric-tests.el (electric-pair-backspace-1): Replace deleted function.
[bpt/emacs.git] / test / automated / electric-tests.el
CommitLineData
3b8d5131
JT
1;;; electric-tests.el --- tests for electric.el
2
ba318903 3;; Copyright (C) 2013-2014 Free Software Foundation, Inc.
3b8d5131
JT
4
5;; Author: João Távora <joaotavora@gmail.com>
6;; Keywords:
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <http://www.gnu.org/licenses/>.
20
1f5afa8c 21;;; Commentary:
3b8d5131 22
1f5afa8c
GM
23;; Tests for Electric Pair mode.
24;; TODO: Add tests for other Electric-* functionality
3b8d5131
JT
25
26;;; Code:
27(require 'ert)
28(require 'ert-x)
29(require 'electric)
1f5afa8c 30(require 'elec-pair)
3b8d5131
JT
31(require 'cl-lib)
32
33(defun call-with-saved-electric-modes (fn)
34 (let ((saved-electric (if electric-pair-mode 1 -1))
35 (saved-layout (if electric-layout-mode 1 -1))
36 (saved-indent (if electric-indent-mode 1 -1)))
37 (electric-pair-mode -1)
38 (electric-layout-mode -1)
39 (electric-indent-mode -1)
40 (unwind-protect
41 (funcall fn)
42 (electric-pair-mode saved-electric)
43 (electric-indent-mode saved-indent)
44 (electric-layout-mode saved-layout))))
45
46(defmacro save-electric-modes (&rest body)
47 (declare (indent defun) (debug t))
48 `(call-with-saved-electric-modes #'(lambda () ,@body)))
49
50(defun electric-pair-test-for (fixture where char expected-string
51 expected-point mode bindings fixture-fn)
52 (with-temp-buffer
53 (funcall mode)
54 (insert fixture)
55 (save-electric-modes
8a6212d7
JT
56 (let ((last-command-event char)
57 (transient-mark-mode 'lambda))
3b8d5131
JT
58 (goto-char where)
59 (funcall fixture-fn)
60 (cl-progv
61 (mapcar #'car bindings)
62 (mapcar #'cdr bindings)
63 (self-insert-command 1))))
64 (should (equal (buffer-substring-no-properties (point-min) (point-max))
65 expected-string))
66 (should (equal (point)
67 expected-point))))
68
69(eval-when-compile
70 (defun electric-pair-define-test-form (name fixture
71 char
72 pos
73 expected-string
74 expected-point
75 skip-pair-string
76 prefix
77 suffix
78 extra-desc
79 mode
80 bindings
81 fixture-fn)
82 (let* ((expected-string-and-point
83 (if skip-pair-string
84 (with-temp-buffer
85 (cl-progv
86 ;; FIXME: avoid `eval'
87 (mapcar #'car (eval bindings))
88 (mapcar #'cdr (eval bindings))
89 (funcall mode)
90 (insert fixture)
91 (goto-char (1+ pos))
92 (insert char)
93 (cond ((eq (aref skip-pair-string pos)
94 ?p)
95 (insert (cadr (electric-pair-syntax-info char)))
96 (backward-char 1))
97 ((eq (aref skip-pair-string pos)
98 ?s)
99 (delete-char -1)
100 (forward-char 1)))
101 (list
102 (buffer-substring-no-properties (point-min) (point-max))
103 (point))))
104 (list expected-string expected-point)))
105 (expected-string (car expected-string-and-point))
106 (expected-point (cadr expected-string-and-point))
107 (fixture (format "%s%s%s" prefix fixture suffix))
108 (expected-string (format "%s%s%s" prefix expected-string suffix))
109 (expected-point (+ (length prefix) expected-point))
110 (pos (+ (length prefix) pos)))
111 `(ert-deftest ,(intern (format "electric-pair-%s-at-point-%s-in-%s%s"
112 name
113 (1+ pos)
114 mode
115 extra-desc))
116 ()
89f20f76
JT
117 ,(format "With |%s|, try input %c at point %d. \
118Should %s |%s| and point at %d"
3b8d5131
JT
119 fixture
120 char
121 (1+ pos)
122 (if (string= fixture expected-string)
123 "stay"
124 "become")
125 (replace-regexp-in-string "\n" "\\\\n" expected-string)
126 expected-point)
127 (electric-pair-test-for ,fixture
128 ,(1+ pos)
129 ,char
130 ,expected-string
131 ,expected-point
132 ',mode
133 ,bindings
134 ,fixture-fn)))))
135
136(cl-defmacro define-electric-pair-test
137 (name fixture
138 input
139 &key
140 skip-pair-string
141 expected-string
142 expected-point
143 bindings
190f899a 144 (modes '(quote (ruby-mode c++-mode)))
3b8d5131
JT
145 (test-in-comments t)
146 (test-in-strings t)
147 (test-in-code t)
148 (fixture-fn #'(lambda ()
149 (electric-pair-mode 1))))
150 `(progn
151 ,@(cl-loop
152 for mode in (eval modes) ;FIXME: avoid `eval'
153 append
154 (cl-loop
155 for (prefix suffix extra-desc) in
156 (append (if test-in-comments
157 `((,(with-temp-buffer
158 (funcall mode)
159 (insert "z")
160 (comment-region (point-min) (point-max))
161 (buffer-substring-no-properties (point-min)
162 (1- (point-max))))
163 ""
164 "-in-comments")))
165 (if test-in-strings
166 `(("\"" "\"" "-in-strings")))
167 (if test-in-code
168 `(("" "" ""))))
169 append
170 (cl-loop
171 for char across input
172 for pos from 0
173 unless (eq char ?-)
174 collect (electric-pair-define-test-form
175 name
176 fixture
177 (aref input pos)
178 pos
179 expected-string
180 expected-point
181 skip-pair-string
182 prefix
183 suffix
184 extra-desc
185 mode
186 bindings
187 fixture-fn))))))
188\f
7e99158a 189;;; Basic pairs and skips
3b8d5131
JT
190;;;
191(define-electric-pair-test balanced-situation
192 " (()) " "(((((((" :skip-pair-string "ppppppp"
193 :modes '(ruby-mode))
194
195(define-electric-pair-test too-many-openings
196 " ((()) " "(((((((" :skip-pair-string "ppppppp")
197
198(define-electric-pair-test too-many-closings
199 " (())) " "(((((((" :skip-pair-string "------p")
200
201(define-electric-pair-test too-many-closings-2
202 "() ) " "---(---" :skip-pair-string "-------")
203
204(define-electric-pair-test too-many-closings-3
205 ")() " "(------" :skip-pair-string "-------")
206
207(define-electric-pair-test balanced-autoskipping
208 " (()) " "---))--" :skip-pair-string "---ss--")
209
210(define-electric-pair-test too-many-openings-autoskipping
211 " ((()) " "----))-" :skip-pair-string "-------")
212
213(define-electric-pair-test too-many-closings-autoskipping
214 " (())) " "---)))-" :skip-pair-string "---sss-")
215
216\f
217;;; Mixed parens
218;;;
219(define-electric-pair-test mixed-paren-1
220 " ()] " "-(-(---" :skip-pair-string "-p-p---")
221
222(define-electric-pair-test mixed-paren-2
223 " [() " "-(-()--" :skip-pair-string "-p-ps--")
224
225(define-electric-pair-test mixed-paren-3
226 " (]) " "-(-()--" :skip-pair-string "---ps--")
227
228(define-electric-pair-test mixed-paren-4
229 " ()] " "---)]--" :skip-pair-string "---ss--")
230
231(define-electric-pair-test mixed-paren-5
232 " [() " "----(--" :skip-pair-string "----p--")
233
234(define-electric-pair-test find-matching-different-paren-type
235 " ()] " "-[-----" :skip-pair-string "-------")
236
237(define-electric-pair-test find-matching-different-paren-type-inside-list
238 "( ()]) " "-[-----" :skip-pair-string "-------")
239
7e99158a 240(define-electric-pair-test ignore-different-nonmatching-paren-type
3b8d5131
JT
241 "( ()]) " "-(-----" :skip-pair-string "-p-----")
242
243(define-electric-pair-test autopair-keep-least-amount-of-mixed-unbalance
244 "( ()] " "-(-----" :skip-pair-string "-p-----")
245
246(define-electric-pair-test dont-autopair-to-resolve-mixed-unbalance
247 "( ()] " "-[-----" :skip-pair-string "-------")
248
249(define-electric-pair-test autopair-so-as-not-to-worsen-unbalance-situation
250 "( (]) " "-[-----" :skip-pair-string "-p-----")
251
252(define-electric-pair-test skip-over-partially-balanced
253 " [([]) " "-----)---" :skip-pair-string "-----s---")
254
255(define-electric-pair-test only-skip-over-at-least-partially-balanced-stuff
256 " [([()) " "-----))--" :skip-pair-string "-----s---")
257
258
259
260\f
261;;; Quotes
262;;;
263(define-electric-pair-test pair-some-quotes-skip-others
264 " \"\" " "-\"\"-----" :skip-pair-string "-ps------"
265 :test-in-strings nil
266 :bindings `((electric-pair-text-syntax-table
267 . ,prog-mode-syntax-table)))
268
269(define-electric-pair-test skip-single-quotes-in-ruby-mode
270 " '' " "--'-" :skip-pair-string "--s-"
271 :modes '(ruby-mode)
272 :test-in-comments nil
273 :test-in-strings nil
274 :bindings `((electric-pair-text-syntax-table
275 . ,prog-mode-syntax-table)))
276
277(define-electric-pair-test leave-unbalanced-quotes-alone
278 " \"' " "-\"'-" :skip-pair-string "----"
279 :modes '(ruby-mode)
280 :test-in-strings nil
281 :bindings `((electric-pair-text-syntax-table
282 . ,prog-mode-syntax-table)))
283
284(define-electric-pair-test leave-unbalanced-quotes-alone-2
285 " \"\\\"' " "-\"--'-" :skip-pair-string "------"
286 :modes '(ruby-mode)
287 :test-in-strings nil
288 :bindings `((electric-pair-text-syntax-table
289 . ,prog-mode-syntax-table)))
290
291(define-electric-pair-test leave-unbalanced-quotes-alone-3
292 " foo\\''" "'------" :skip-pair-string "-------"
293 :modes '(ruby-mode)
294 :test-in-strings nil
295 :bindings `((electric-pair-text-syntax-table
296 . ,prog-mode-syntax-table)))
297
528c33b5 298(define-electric-pair-test inhibit-if-strings-mismatched
3b8d5131 299 "\"foo\"\"bar" "\""
528c33b5 300 :expected-string "\"\"foo\"\"bar"
3b8d5131
JT
301 :expected-point 2
302 :test-in-strings nil
303 :bindings `((electric-pair-text-syntax-table
304 . ,prog-mode-syntax-table)))
305
190f899a
JT
306(define-electric-pair-test inhibit-in-mismatched-string-inside-ruby-comments
307 "foo\"\"
308#
309# \"bar\"
310# \" \"
311# \"
312#
313baz\"\""
314 "\""
315 :modes '(ruby-mode)
316 :test-in-strings nil
317 :test-in-comments nil
318 :expected-point 19
319 :expected-string
320 "foo\"\"
321#
322# \"bar\"\"
323# \" \"
324# \"
325#
326baz\"\""
327 :fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
328
329(define-electric-pair-test inhibit-in-mismatched-string-inside-c-comments
330 "foo\"\"/*
331 \"bar\"
332 \" \"
333 \"
334*/baz\"\""
335 "\""
336 :modes '(c-mode)
337 :test-in-strings nil
338 :test-in-comments nil
339 :expected-point 18
340 :expected-string
341 "foo\"\"/*
342 \"bar\"\"
343 \" \"
344 \"
345*/baz\"\""
346 :fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
347
3b8d5131
JT
348\f
349;;; More quotes, but now don't bind `electric-pair-text-syntax-table'
350;;; to `prog-mode-syntax-table'. Use the defaults for
351;;; `electric-pair-pairs' and `electric-pair-text-pairs'.
352;;;
353(define-electric-pair-test pairing-skipping-quotes-in-code
354 " \"\" " "-\"\"-----" :skip-pair-string "-ps------"
355 :test-in-strings nil
356 :test-in-comments nil)
357
358(define-electric-pair-test skipping-quotes-in-comments
359 " \"\" " "--\"-----" :skip-pair-string "--s------"
360 :test-in-strings nil)
361
362\f
363;;; Skipping over whitespace
364;;;
365(define-electric-pair-test whitespace-jumping
366 " ( ) " "--))))---" :expected-string " ( ) " :expected-point 8
367 :bindings '((electric-pair-skip-whitespace . t)))
368
369(define-electric-pair-test whitespace-chomping
370 " ( ) " "--)------" :expected-string " () " :expected-point 4
371 :bindings '((electric-pair-skip-whitespace . chomp)))
372
373(define-electric-pair-test whitespace-chomping-2
374 " ( \n\t\t\n ) " "--)------" :expected-string " () " :expected-point 4
375 :bindings '((electric-pair-skip-whitespace . chomp))
376 :test-in-comments nil)
377
378(define-electric-pair-test whitespace-chomping-dont-cross-comments
379 " ( \n\t\t\n ) " "--)------" :expected-string " () \n\t\t\n ) "
380 :expected-point 4
381 :bindings '((electric-pair-skip-whitespace . chomp))
382 :test-in-strings nil
383 :test-in-code nil
384 :test-in-comments t)
385
89f20f76
JT
386(define-electric-pair-test whitespace-skipping-for-quotes-not-ouside
387 " \" \"" "\"-----" :expected-string "\"\" \" \""
388 :expected-point 2
389 :bindings '((electric-pair-skip-whitespace . chomp))
390 :test-in-strings nil
391 :test-in-code t
392 :test-in-comments nil)
393
394(define-electric-pair-test whitespace-skipping-for-quotes-only-inside
395 " \" \"" "---\"--" :expected-string " \"\""
396 :expected-point 5
397 :bindings '((electric-pair-skip-whitespace . chomp))
398 :test-in-strings nil
399 :test-in-code t
400 :test-in-comments nil)
401
402(define-electric-pair-test whitespace-skipping-quotes-not-without-proper-syntax
403 " \" \"" "---\"--" :expected-string " \"\"\" \""
404 :expected-point 5
405 :modes '(text-mode)
406 :bindings '((electric-pair-skip-whitespace . chomp))
407 :test-in-strings nil
408 :test-in-code t
409 :test-in-comments nil)
410
3b8d5131
JT
411\f
412;;; Pairing arbitrary characters
413;;;
414(define-electric-pair-test angle-brackets-everywhere
415 "<>" "<>" :skip-pair-string "ps"
416 :bindings '((electric-pair-pairs . ((?\< . ?\>)))))
417
418(define-electric-pair-test angle-brackets-everywhere-2
419 "(<>" "-<>" :skip-pair-string "-ps"
420 :bindings '((electric-pair-pairs . ((?\< . ?\>)))))
421
422(defvar electric-pair-test-angle-brackets-table
423 (let ((table (make-syntax-table prog-mode-syntax-table)))
424 (modify-syntax-entry ?\< "(>" table)
425 (modify-syntax-entry ?\> ")<`" table)
426 table))
427
428(define-electric-pair-test angle-brackets-pair
429 "<>" "<" :expected-string "<><>" :expected-point 2
430 :test-in-code nil
431 :bindings `((electric-pair-text-syntax-table
432 . ,electric-pair-test-angle-brackets-table)))
433
434(define-electric-pair-test angle-brackets-skip
435 "<>" "->" :expected-string "<>" :expected-point 3
436 :test-in-code nil
437 :bindings `((electric-pair-text-syntax-table
438 . ,electric-pair-test-angle-brackets-table)))
439
440(define-electric-pair-test pair-backtick-and-quote-in-comments
441 ";; " "---`" :expected-string ";; `'" :expected-point 5
442 :test-in-comments nil
443 :test-in-strings nil
444 :modes '(emacs-lisp-mode)
445 :bindings '((electric-pair-text-pairs . ((?\` . ?\')))))
446
447(define-electric-pair-test skip-backtick-and-quote-in-comments
448 ";; `foo'" "-------'" :expected-string ";; `foo'" :expected-point 9
449 :test-in-comments nil
450 :test-in-strings nil
451 :modes '(emacs-lisp-mode)
452 :bindings '((electric-pair-text-pairs . ((?\` . ?\')))))
453
454(define-electric-pair-test pair-backtick-and-quote-in-strings
455 "\"\"" "-`" :expected-string "\"`'\"" :expected-point 3
456 :test-in-comments nil
457 :test-in-strings nil
458 :modes '(emacs-lisp-mode)
459 :bindings '((electric-pair-text-pairs . ((?\` . ?\')))))
460
461(define-electric-pair-test skip-backtick-and-quote-in-strings
462 "\"`'\"" "--'" :expected-string "\"`'\"" :expected-point 4
463 :test-in-comments nil
464 :test-in-strings nil
465 :modes '(emacs-lisp-mode)
466 :bindings '((electric-pair-text-pairs . ((?\` . ?\')))))
467
468(define-electric-pair-test skip-backtick-and-quote-in-strings-2
469 " \"`'\"" "----'" :expected-string " \"`'\"" :expected-point 6
470 :test-in-comments nil
471 :test-in-strings nil
472 :modes '(emacs-lisp-mode)
473 :bindings '((electric-pair-text-pairs . ((?\` . ?\')))))
474
475\f
476;;; `js-mode' has `electric-layout-rules' for '{ and '}
477;;;
478(define-electric-pair-test js-mode-braces
479 "" "{" :expected-string "{}" :expected-point 2
480 :modes '(js-mode)
481 :fixture-fn #'(lambda ()
482 (electric-pair-mode 1)))
483
484(define-electric-pair-test js-mode-braces-with-layout
485 "" "{" :expected-string "{\n\n}" :expected-point 3
486 :modes '(js-mode)
487 :test-in-comments nil
488 :test-in-strings nil
489 :fixture-fn #'(lambda ()
490 (electric-layout-mode 1)
491 (electric-pair-mode 1)))
492
493(define-electric-pair-test js-mode-braces-with-layout-and-indent
494 "" "{" :expected-string "{\n \n}" :expected-point 7
495 :modes '(js-mode)
496 :test-in-comments nil
497 :test-in-strings nil
498 :fixture-fn #'(lambda ()
499 (electric-pair-mode 1)
500 (electric-indent-mode 1)
501 (electric-layout-mode 1)))
502
503\f
504;;; Backspacing
505;;; TODO: better tests
506;;;
507(ert-deftest electric-pair-backspace-1 ()
508 (save-electric-modes
509 (with-temp-buffer
510 (insert "()")
511 (goto-char 2)
3b7fab25 512 (electric-pair-delete-pair 1)
3b8d5131
JT
513 (should (equal "" (buffer-string))))))
514
515\f
516;;; Electric newlines between pairs
517;;; TODO: better tests
518(ert-deftest electric-pair-open-extra-newline ()
519 (save-electric-modes
520 (with-temp-buffer
521 (c-mode)
522 (electric-pair-mode 1)
523 (electric-indent-mode 1)
524 (insert "int main {}")
525 (backward-char 1)
526 (let ((c-basic-offset 4))
527 (newline 1 t)
528 (should (equal "int main {\n \n}"
529 (buffer-string)))
530 (should (equal (point) (- (point-max) 2)))))))
531
532
533\f
534;;; Autowrapping
535;;;
536(define-electric-pair-test autowrapping-1
537 "foo" "(" :expected-string "(foo)" :expected-point 2
538 :fixture-fn #'(lambda ()
539 (electric-pair-mode 1)
540 (mark-sexp 1)))
541
542(define-electric-pair-test autowrapping-2
543 "foo" ")" :expected-string "(foo)" :expected-point 6
544 :fixture-fn #'(lambda ()
545 (electric-pair-mode 1)
546 (mark-sexp 1)))
547
548(define-electric-pair-test autowrapping-3
549 "foo" ")" :expected-string "(foo)" :expected-point 6
550 :fixture-fn #'(lambda ()
551 (electric-pair-mode 1)
552 (goto-char (point-max))
553 (skip-chars-backward "\"")
554 (mark-sexp -1)))
555
556(define-electric-pair-test autowrapping-4
557 "foo" "(" :expected-string "(foo)" :expected-point 2
558 :fixture-fn #'(lambda ()
559 (electric-pair-mode 1)
560 (goto-char (point-max))
561 (skip-chars-backward "\"")
562 (mark-sexp -1)))
563
564(define-electric-pair-test autowrapping-5
565 "foo" "\"" :expected-string "\"foo\"" :expected-point 2
566 :fixture-fn #'(lambda ()
567 (electric-pair-mode 1)
568 (mark-sexp 1)))
569
570(define-electric-pair-test autowrapping-6
571 "foo" "\"" :expected-string "\"foo\"" :expected-point 6
572 :fixture-fn #'(lambda ()
573 (electric-pair-mode 1)
574 (goto-char (point-max))
575 (skip-chars-backward "\"")
576 (mark-sexp -1)))
577
578(provide 'electric-tests)
579;;; electric-tests.el ends here