Commit 6deb668e authored by João Távora's avatar João Távora

Rework electric-layout-post-self-insert-function (bug#33794)

This should now fix more problems reported in (bug#33794) regarding
insertion of newlines before and after the opening brace.  Write two
automated tests.

Also provide a new electric-layout-local-mode for testing.

* lisp/electric.el (electric-layout-post-self-insert-function-1):
New function that does the work for
electric-layout-post-self-insert-function-1.
(electric-layout-local-mode): New minor mode.

* test/lisp/electric-tests.el (electric-layout-int-main-kernel-style)
(electric-layout-int-main-allman-style): Add two tests.
parent cb1b4a8c
......@@ -376,17 +376,25 @@ If multiple rules match, they are all executed in order of
appearance.")
(defun electric-layout-post-self-insert-function ()
(let (pos)
(when electric-layout-mode
(electric-layout-post-self-insert-function-1)))
;; for edebug's sake a separate function
(defun electric-layout-post-self-insert-function-1 ()
(let (pos end)
(when (and (setq pos (electric--after-char-pos))
;; Not in a string or comment.
(not (nth 8 (save-excursion (syntax-ppss pos)))))
(goto-char pos)
(setq end (point-marker))
(dolist (rule electric-layout-rules)
(when (eq last-command-event (car rule))
(let* ((end (point-marker))
(rule (cdr rule))
(sym (if (functionp rule) (funcall rule) rule)))
(set-marker-insertion-type end (not (eq sym 'after-stay)))
(let* ((rule (cdr rule))
(sym (if (functionp rule) (funcall rule) rule))
(nl (lambda ()
(let ((electric-layout-mode nil)
(electric-pair-open-newline-between-pairs nil))
(newline 1 t)))))
(pcase sym
;; FIXME: we used `newline' down here which called
;; self-insert-command and ran post-self-insert-hook recursively.
......@@ -395,18 +403,16 @@ appearance.")
;; multiple times), but I'm not sure it's what we want.
;;
;; FIXME: check eolp before inserting \n?
('before (goto-char (1- pos)) (skip-chars-backward " \t")
(unless (bolp) (insert "\n")))
('after (insert "\n"))
('after-stay (save-excursion
(let ((electric-layout-rules nil)
(electric-pair-open-newline-between-pairs nil))
(newline 1 t))))
('before (save-excursion
(goto-char (1- pos)) (skip-chars-backward " \t")
(unless (bolp) (funcall nl))))
('after (funcall nl))
('after-stay (save-excursion (funcall nl)))
('around (save-excursion
(goto-char (1- pos)) (skip-chars-backward " \t")
(unless (bolp) (insert "\n")))
(insert "\n"))) ; FIXME: check eolp before inserting \n?
(goto-char end)))))))
(unless (bolp) (funcall nl)))
(funcall nl))) ; FIXME: check eolp before inserting \n?
))))))
(put 'electric-layout-post-self-insert-function 'priority 40)
......@@ -424,6 +430,19 @@ The variable `electric-layout-rules' says when and how to insert newlines."
(remove-hook 'post-self-insert-hook
#'electric-layout-post-self-insert-function))))
;;;###autoload
(define-minor-mode electric-layout-local-mode
"Toggle `electric-layout-mode' only in this buffer."
:variable (buffer-local-value 'electric-layout-mode (current-buffer))
(cond
((eq electric-layout-mode (default-value 'electric-layout-mode))
(kill-local-variable 'electric-layout-mode))
((not (default-value 'electric-layout-mode))
;; Locally enabled, but globally disabled.
(electric-layout-mode 1) ; Setup the hooks.
(setq-default electric-layout-mode nil) ; But keep it globally disabled.
)))
;;; Electric quoting.
(defcustom electric-quote-comment t
......
......@@ -812,5 +812,39 @@ baz\"\""
:bindings '((comment-start . "<!--") (comment-use-syntax . t))
:test-in-comments nil :test-in-strings nil)
;;; 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)
(?\{ . after-stay)))
(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)
(?\{ . after-stay)))
(insert "int main () ")
(let ((last-command-event ?\{))
(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