1 ;;; electric-tests.el --- tests for electric.el
3 ;; Copyright (C) 2013-2016 Free Software Foundation, Inc.
5 ;; Author: João Távora <joaotavora@gmail.com>
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.
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.
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/>.
23 ;; Tests for Electric Pair mode.
24 ;; TODO: Add tests for other Electric-* functionality
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)
42 (electric-pair-mode saved-electric
)
43 (electric-indent-mode saved-indent
)
44 (electric-layout-mode saved-layout
))))
46 (defmacro save-electric-modes
(&rest body
)
47 (declare (indent defun
) (debug t
))
48 `(call-with-saved-electric-modes #'(lambda () ,@body
)))
50 (defun electric-pair-test-for (fixture where char expected-string
51 expected-point mode bindings fixture-fn
)
56 (let ((last-command-event char
)
57 (transient-mark-mode 'lambda
))
61 (mapcar #'car bindings
)
62 (mapcar #'cdr bindings
)
63 (call-interactively (key-binding `[,last-command-event
])))))
64 (should (equal (buffer-substring-no-properties (point-min) (point-max))
66 (should (equal (point)
70 (defun electric-pair-define-test-form (name fixture
82 (let* ((expected-string-and-point
86 ;; FIXME: avoid `eval'
87 (mapcar #'car
(eval bindings
))
88 (mapcar #'cdr
(eval bindings
))
93 (cond ((eq (aref skip-pair-string pos
)
95 (insert (cadr (electric-pair-syntax-info char
)))
97 ((eq (aref skip-pair-string pos
)
102 (buffer-substring-no-properties (point-min) (point-max))
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"
117 ,(format "With |%s|, try input %c at point %d. \
118 Should %s |%s| and point at %d"
122 (if (string= fixture expected-string
)
125 (replace-regexp-in-string "\n" "\\\\n" expected-string
)
127 (electric-pair-test-for ,fixture
136 (cl-defmacro define-electric-pair-test
144 (modes '(quote (ruby-mode c
++-mode
)))
148 (fixture-fn #'(lambda ()
149 (electric-pair-mode 1))))
152 for mode in
(eval modes
) ;FIXME: avoid `eval'
155 for
(prefix suffix extra-desc
) in
156 (append (if test-in-comments
157 `((,(with-temp-buffer
160 (comment-region (point-min) (point-max))
161 (buffer-substring-no-properties (point-min)
166 `(("\"" "\"" "-in-strings")))
171 for char across input
174 collect
(electric-pair-define-test-form
189 ;;; Basic pairs and skips
191 (define-electric-pair-test balanced-situation
192 " (()) " "(((((((" :skip-pair-string
"ppppppp"
195 (define-electric-pair-test too-many-openings
196 " ((()) " "(((((((" :skip-pair-string
"ppppppp")
198 (define-electric-pair-test too-many-closings
199 " (())) " "(((((((" :skip-pair-string
"------p")
201 (define-electric-pair-test too-many-closings-2
202 "() ) " "---(---" :skip-pair-string
"-------")
204 (define-electric-pair-test too-many-closings-3
205 ")() " "(------" :skip-pair-string
"-------")
207 (define-electric-pair-test balanced-autoskipping
208 " (()) " "---))--" :skip-pair-string
"---ss--")
210 (define-electric-pair-test too-many-openings-autoskipping
211 " ((()) " "----))-" :skip-pair-string
"-------")
213 (define-electric-pair-test too-many-closings-autoskipping
214 " (())) " "---)))-" :skip-pair-string
"---sss-")
219 (define-electric-pair-test mixed-paren-1
220 " ()] " "-(-(---" :skip-pair-string
"-p-p---")
222 (define-electric-pair-test mixed-paren-2
223 " [() " "-(-()--" :skip-pair-string
"-p-ps--")
225 (define-electric-pair-test mixed-paren-3
226 " (]) " "-(-()--" :skip-pair-string
"---ps--")
228 (define-electric-pair-test mixed-paren-4
229 " ()] " "---)]--" :skip-pair-string
"---ss--")
231 (define-electric-pair-test mixed-paren-5
232 " [() " "----(--" :skip-pair-string
"----p--")
234 (define-electric-pair-test find-matching-different-paren-type
235 " ()] " "-[-----" :skip-pair-string
"-------")
237 (define-electric-pair-test find-matching-different-paren-type-inside-list
238 "( ()]) " "-[-----" :skip-pair-string
"-------")
240 (define-electric-pair-test ignore-different-nonmatching-paren-type
241 "( ()]) " "-(-----" :skip-pair-string
"-p-----")
243 (define-electric-pair-test autopair-keep-least-amount-of-mixed-unbalance
244 "( ()] " "-(-----" :skip-pair-string
"-p-----")
246 (define-electric-pair-test dont-autopair-to-resolve-mixed-unbalance
247 "( ()] " "-[-----" :skip-pair-string
"-------")
249 (define-electric-pair-test autopair-so-as-not-to-worsen-unbalance-situation
250 "( (]) " "-[-----" :skip-pair-string
"-p-----")
252 (define-electric-pair-test skip-over-partially-balanced
253 " [([]) " "-----)---" :skip-pair-string
"-----s---")
255 (define-electric-pair-test only-skip-over-at-least-partially-balanced-stuff
256 " [([()) " "-----))--" :skip-pair-string
"-----s---")
263 (define-electric-pair-test pair-some-quotes-skip-others
264 " \"\" " "-\"\"-----" :skip-pair-string
"-ps------"
266 :bindings
`((electric-pair-text-syntax-table
267 .
,prog-mode-syntax-table
)))
269 (define-electric-pair-test skip-single-quotes-in-ruby-mode
270 " '' " "--'-" :skip-pair-string
"--s-"
272 :test-in-comments nil
274 :bindings
`((electric-pair-text-syntax-table
275 .
,prog-mode-syntax-table
)))
277 (define-electric-pair-test leave-unbalanced-quotes-alone
278 " \"' " "-\"'-" :skip-pair-string
"----"
281 :bindings
`((electric-pair-text-syntax-table
282 .
,prog-mode-syntax-table
)))
284 (define-electric-pair-test leave-unbalanced-quotes-alone-2
285 " \"\\\"' " "-\"--'-" :skip-pair-string
"------"
288 :bindings
`((electric-pair-text-syntax-table
289 .
,prog-mode-syntax-table
)))
291 (define-electric-pair-test leave-unbalanced-quotes-alone-3
292 " foo\\''" "'------" :skip-pair-string
"-------"
295 :bindings
`((electric-pair-text-syntax-table
296 .
,prog-mode-syntax-table
)))
298 (define-electric-pair-test inhibit-if-strings-mismatched
300 :expected-string
"\"\"foo\"\"bar"
303 :bindings
`((electric-pair-text-syntax-table
304 .
,prog-mode-syntax-table
)))
306 (define-electric-pair-test inhibit-in-mismatched-string-inside-ruby-comments
317 :test-in-comments nil
327 :fixture-fn
#'(lambda () (goto-char (point-min)) (search-forward "bar")))
329 (define-electric-pair-test inhibit-in-mismatched-string-inside-c-comments
338 :test-in-comments nil
346 :fixture-fn
#'(lambda () (goto-char (point-min)) (search-forward "bar")))
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'.
353 (define-electric-pair-test pairing-skipping-quotes-in-code
354 " \"\" " "-\"\"-----" :skip-pair-string
"-ps------"
356 :test-in-comments nil
)
358 (define-electric-pair-test skipping-quotes-in-comments
359 " \"\" " "--\"-----" :skip-pair-string
"--s------"
360 :test-in-strings nil
)
363 ;;; Skipping over whitespace
365 (define-electric-pair-test whitespace-jumping
366 " ( ) " "--))))---" :expected-string
" ( ) " :expected-point
8
367 :bindings
'((electric-pair-skip-whitespace . t
)))
369 (define-electric-pair-test whitespace-chomping
370 " ( ) " "--)------" :expected-string
" () " :expected-point
4
371 :bindings
'((electric-pair-skip-whitespace . chomp
)))
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
)
378 (define-electric-pair-test whitespace-chomping-dont-cross-comments
379 " ( \n\t\t\n ) " "--)------" :expected-string
" () \n\t\t\n ) "
381 :bindings
'((electric-pair-skip-whitespace . chomp
))
386 (define-electric-pair-test whitespace-skipping-for-quotes-not-outside
387 " \" \"" "\"-----" :expected-string
"\"\" \" \""
389 :bindings
'((electric-pair-skip-whitespace . chomp
))
392 :test-in-comments nil
)
394 (define-electric-pair-test whitespace-skipping-for-quotes-only-inside
395 " \" \"" "---\"--" :expected-string
" \"\""
397 :bindings
'((electric-pair-skip-whitespace . chomp
))
400 :test-in-comments nil
)
402 (define-electric-pair-test whitespace-skipping-quotes-not-without-proper-syntax
403 " \" \"" "---\"--" :expected-string
" \"\"\" \""
406 :bindings
'((electric-pair-skip-whitespace . chomp
))
409 :test-in-comments nil
)
412 ;;; Pairing arbitrary characters
414 (define-electric-pair-test angle-brackets-everywhere
415 "<>" "<>" :skip-pair-string
"ps"
416 :bindings
'((electric-pair-pairs .
((?\
< . ?\
>)))))
418 (define-electric-pair-test angle-brackets-everywhere-2
419 "(<>" "-<>" :skip-pair-string
"-ps"
420 :bindings
'((electric-pair-pairs .
((?\
< . ?\
>)))))
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
)
428 (define-electric-pair-test angle-brackets-pair
429 "<>" "<" :expected-string
"<><>" :expected-point
2
431 :bindings
`((electric-pair-text-syntax-table
432 .
,electric-pair-test-angle-brackets-table
)))
434 (define-electric-pair-test angle-brackets-skip
435 "<>" "->" :expected-string
"<>" :expected-point
3
437 :bindings
`((electric-pair-text-syntax-table
438 .
,electric-pair-test-angle-brackets-table
)))
440 (define-electric-pair-test pair-backtick-and-quote-in-comments
441 ";; " "---`" :expected-string
";; `'" :expected-point
5
442 :test-in-comments nil
444 :modes
'(emacs-lisp-mode)
445 :bindings
'((electric-pair-text-pairs .
((?\
` . ?
\')))))
447 (define-electric-pair-test skip-backtick-and-quote-in-comments
448 ";; `foo'" "-------'" :expected-string
";; `foo'" :expected-point
9
449 :test-in-comments nil
451 :modes
'(emacs-lisp-mode)
452 :bindings
'((electric-pair-text-pairs .
((?\
` . ?
\')))))
454 (define-electric-pair-test pair-backtick-and-quote-in-strings
455 "\"\"" "-`" :expected-string
"\"`'\"" :expected-point
3
456 :test-in-comments nil
458 :modes
'(emacs-lisp-mode)
459 :bindings
'((electric-pair-text-pairs .
((?\
` . ?
\')))))
461 (define-electric-pair-test skip-backtick-and-quote-in-strings
462 "\"`'\"" "--'" :expected-string
"\"`'\"" :expected-point
4
463 :test-in-comments nil
465 :modes
'(emacs-lisp-mode)
466 :bindings
'((electric-pair-text-pairs .
((?\
` . ?
\')))))
468 (define-electric-pair-test skip-backtick-and-quote-in-strings-2
469 " \"`'\"" "----'" :expected-string
" \"`'\"" :expected-point
6
470 :test-in-comments nil
472 :modes
'(emacs-lisp-mode)
473 :bindings
'((electric-pair-text-pairs .
((?\
` . ?
\')))))
476 ;;; `js-mode' has `electric-layout-rules' for '{ and '}
478 (define-electric-pair-test js-mode-braces
479 "" "{" :expected-string
"{}" :expected-point
2
481 :fixture-fn
#'(lambda ()
482 (electric-pair-mode 1)))
484 (define-electric-pair-test js-mode-braces-with-layout
485 "" "{" :expected-string
"{\n\n}" :expected-point
3
487 :test-in-comments nil
489 :fixture-fn
#'(lambda ()
490 (electric-layout-mode 1)
491 (electric-pair-mode 1)))
493 (define-electric-pair-test js-mode-braces-with-layout-and-indent
494 "" "{" :expected-string
"{\n \n}" :expected-point
7
496 :test-in-comments nil
498 :fixture-fn
#'(lambda ()
499 (electric-pair-mode 1)
500 (electric-indent-mode 1)
501 (electric-layout-mode 1)))
505 ;;; TODO: better tests
507 (ert-deftest electric-pair-backspace-1
()
512 (electric-pair-delete-pair 1)
513 (should (equal "" (buffer-string))))))
516 ;;; Electric newlines between pairs
517 ;;; TODO: better tests
518 (ert-deftest electric-pair-open-extra-newline
()
522 (electric-pair-mode 1)
523 (electric-indent-mode 1)
524 (insert "int main {}")
526 (let ((c-basic-offset 4))
528 (should (equal "int main {\n \n}"
530 (should (equal (point) (- (point-max) 2)))))))
536 (define-electric-pair-test autowrapping-1
537 "foo" "(" :expected-string
"(foo)" :expected-point
2
538 :fixture-fn
#'(lambda ()
539 (electric-pair-mode 1)
542 (define-electric-pair-test autowrapping-2
543 "foo" ")" :expected-string
"(foo)" :expected-point
6
544 :fixture-fn
#'(lambda ()
545 (electric-pair-mode 1)
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 "\"")
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 "\"")
564 (define-electric-pair-test autowrapping-5
565 "foo" "\"" :expected-string
"\"foo\"" :expected-point
2
566 :fixture-fn
#'(lambda ()
567 (electric-pair-mode 1)
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 "\"")
578 (define-electric-pair-test autowrapping-7
579 "foo" "\"" :expected-string
"``foo''" :expected-point
8
581 :fixture-fn
#'(lambda ()
582 (electric-pair-mode 1)
583 (goto-char (point-max))
584 (skip-chars-backward "\"")
587 (provide 'electric-tests
)
588 ;;; electric-tests.el ends here