Commit 1173d509 authored by João Távora's avatar João Távora

Slightly more powerful electric-layout-rules

* lisp/electric.el (electric-layout-rules): Expand slightly.
(electric-layout-post-self-insert-function-1): Accept new rules.

* test/lisp/electric-tests.el (electric-pair-mode-newline-between-parens)
(electric-layout-mode-newline-between-parens-without-e-p-m): New
(failing) tests.
parent fae3e7c0
......@@ -363,9 +363,15 @@ use `electric-indent-local-mode'."
(defvar electric-layout-rules nil
"List of rules saying where to automatically insert newlines.
Each rule has the form (CHAR . WHERE) where CHAR is the char that
was just inserted and WHERE specifies where to insert newlines
and can be:
Each rule has the form (MATCHER . WHERE) where MATCHER examines
the state of the buffer after a certain character was inserted
and WHERE specifies where to insert newlines.
MATCHER can be a character CHAR or a boolean function of no
arguments. The rule matches if the character just inserted was
CHAR or if the function return non-nil.
WHERE and can be:
* one of the symbols `before', `after', `around' and `after-stay';
......@@ -375,9 +381,10 @@ and can be:
* a function of no arguments that returns one of the previous
values.
Each symbol specifies where in relation to CHAR the newline
character(s) should be inserted. `after-stay' means insert a
newline after CHAR but stay in the same place.
Each symbol specifies where, in relation to the position POS of
the character inserted, the newline character(s) should be
inserted. `after-stay' means insert a newline after POS but stay
in the same place.
If multiple rules match, only first one is executed.")
......@@ -387,8 +394,19 @@ If multiple rules match, only first one is executed.")
;; for edebug's sake, a separate function
(defun electric-layout-post-self-insert-function-1 ()
(let (pos
(rule (cdr (assq last-command-event electric-layout-rules))))
(let* (pos
probe
(rules electric-layout-rules)
(rule
(catch 'done
(while (setq probe (pop rules))
(cond ((and (consp probe)
(or (eq (car probe) last-command-event)
(and (functionp (car probe))
(funcall (car probe)))))
(throw 'done (cdr probe)))
((functionp probe)
(throw 'done (funcall probe))))))))
(when (and rule
(setq pos (electric--after-char-pos))
;; Not in a string or comment.
......
......@@ -816,51 +816,89 @@ baz\"\""
;;; tests for `electric-layout-mode'
(ert-deftest electric-layout-int-main-kernel-style ()
(save-electric-modes
(ert-with-test-buffer ()
(c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode 1)
(electric-indent-local-mode 1)
(setq-local electric-layout-rules
'((?\{ . (after-stay after))))
(insert "int main () ")
(let ((last-command-event ?\{))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main () {\n \n}")))))
(ert-with-test-buffer ()
(c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode 1)
(electric-indent-local-mode 1)
(setq-local electric-layout-rules
'((?\{ . (after-stay after))))
(insert "int main () ")
(let ((last-command-event ?\{))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main () {\n \n}"))))
(ert-deftest electric-layout-int-main-allman-style ()
(save-electric-modes
(ert-with-test-buffer ()
(c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode 1)
(electric-indent-local-mode 1)
(setq-local electric-layout-rules
'((?\{ . (before after-stay after))))
(insert "int main () ")
(let ((last-command-event ?\{))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main ()\n{\n \n}")))))
(ert-with-test-buffer ()
(c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode 1)
(electric-indent-local-mode 1)
(setq-local electric-layout-rules
'((?\{ . (before after-stay after))))
(insert "int main () ")
(let ((last-command-event ?\{))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main ()\n{\n \n}"))))
(define-derived-mode plainer-c-mode c-mode "pC"
"A plainer C-mode")
"A plainer/saner C-mode with no internal electric machinery."
(c-toggle-electric-state -1)
(setq-local electric-indent-local-mode-hook nil)
(setq-local electric-indent-mode-hook nil)
(electric-indent-local-mode 1)
(dolist (key '(?\" ?\' ?\{ ?\} ?\( ?\) ?\[ ?\]))
(local-set-key (vector key) 'self-insert-command)))
(ert-deftest electric-modes-in-c-mode-with-self-insert-command ()
(save-electric-modes
(ert-with-test-buffer ()
(plainer-c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode 1)
(electric-indent-local-mode 1)
(dolist (key '(?\" ?\' ?\{ ?\} ?\( ?\) ?\[ ?\]))
(local-set-key (vector key) 'self-insert-command))
(setq-local electric-layout-rules
'((?\{ . (before after-stay after))))
(insert "int main () ")
(let ((last-command-event ?\{))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main ()\n{\n \n}")))))
(ert-with-test-buffer ()
(plainer-c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode 1)
(electric-indent-local-mode 1)
(setq-local electric-layout-rules
'((?\{ . (before after-stay after))))
(insert "int main () ")
(let ((last-command-event ?\{))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main ()\n{\n \n}"))))
;; FIXME: The two following tests fail, because the newline simulation
;; fails to indent the new line. Interactively, they work fine.
;; Don't know why...
(ert-deftest electric-pair-mode-newline-between-parens ()
:expected-result :failed
(ert-with-test-buffer (:name "electric-pair-mode-newline-between-parens")
(plainer-c-mode)
(electric-layout-local-mode -1) ;; ensure e-l-m mode is off
(electric-pair-local-mode 1)
(insert-before-markers "int main () {}")
(backward-char 1)
(let ((last-command-event ?\n))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main ()\n{\n \n}"))))
(ert-deftest electric-layout-mode-newline-between-parens-without-e-p-m ()
:expected-result :failed
(ert-with-test-buffer (:name "electric-pair-mode-newline-between-parens")
(plainer-c-mode)
(electric-layout-local-mode 1)
(electric-pair-local-mode -1) ;; ensure e-p-m mode is off
(electric-indent-local-mode 1)
(setq-local electric-layout-rules
'((?\n
.
(lambda ()
(when (eq (save-excursion
(skip-chars-backward "\t\s")
(char-before (1- (point))))
(matching-paren (char-after)))
'(after-stay))))))
(insert "int main () {}")
(backward-char 1)
(let ((last-command-event ?\n))
(call-interactively (key-binding `[,last-command-event])))
(should (equal (buffer-string) "int main ()\n{\n \n}"))))
(provide 'electric-tests)
;;; electric-tests.el ends here
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment