Improve on previous quote autopairing change

* lisp/elec-pair.el:
(electric-pair--syntax-ppss): When inside comments parse from
comment beginning.
(electric-pair--balance-info): Fix typo in comment.
(electric-pair--in-unterminated-string-p): Delete.
(electric-pair--unbalanced-strings-p): New function.
(electric-pair-string-bound-function): New var.
(electric-pair-inhibit-if-helps-balance): Decide quote pairing
according to `electric-pair--in-unterminated-string-p'

* test/automated/electric-tests.el (define-electric-pair-test): Don't
overtest..
(inhibit-in-mismatched-string-inside-ruby-comments): New test.
(inhibit-in-mismatched-string-inside-c-comments): New test.
This commit is contained in:
João Távora 2014-04-05 00:31:02 +01:00
parent 6b31e6b1ec
commit 5cb0cc903f
4 changed files with 98 additions and 20 deletions

View file

@ -1,3 +1,15 @@
2014-04-04 João Távora <joaotavora@gmail.com>
* elec-pair.el:
(electric-pair--syntax-ppss): When inside comments parse from
comment beginning.
(electric-pair--balance-info): Fix typo in comment.
(electric-pair--in-unterminated-string-p): Delete.
(electric-pair--unbalanced-strings-p): New function.
(electric-pair-string-bound-function): New var.
(electric-pair-inhibit-if-helps-balance): Decide quote pairing
according to `electric-pair--in-unterminated-string-p'
2014-04-04 Stefan Monnier <monnier@iro.umontreal.ca>
* textmodes/reftex-parse.el (reftex--index-tags): Rename `index-tags'.

View file

@ -257,11 +257,19 @@ when to fallback to `parse-partial-sexp'."
(let* ((pos (or pos (point)))
(where (or where '(string comment)))
(quick-ppss (syntax-ppss))
(quick-ppss-at-pos (syntax-ppss pos)))
(if (or (and (nth 3 quick-ppss) (memq 'string where))
(and (nth 4 quick-ppss) (memq 'comment where)))
(quick-ppss-at-pos (syntax-ppss pos))
(in-string (and (nth 3 quick-ppss-at-pos) (memq 'string where)))
(in-comment (and (nth 4 quick-ppss-at-pos) (memq 'comment where)))
(s-or-c-start (cond (in-string
(1+ (nth 8 quick-ppss)))
(in-comment
(goto-char (nth 8 quick-ppss))
(forward-comment (- (point-max)))
(skip-syntax-forward " >!")
(point)))))
(if s-or-c-start
(with-syntax-table electric-pair-text-syntax-table
(parse-partial-sexp (1+ (nth 8 quick-ppss)) pos))
(parse-partial-sexp s-or-c-start pos))
;; HACK! cc-mode apparently has some `syntax-ppss' bugs
(if (memq major-mode '(c-mode c++ mode))
(parse-partial-sexp (point-min) pos)
@ -351,7 +359,7 @@ If point is not enclosed by any lists, return ((t) . (t))."
(scan-error
(cond ((or
;; some error happened and it is not of the "ended
;; prematurely" kind"...
;; prematurely" kind...
(not (string-match "ends prematurely" (nth 1 err)))
;; ... or we were in a comment and just came out of
;; it.
@ -364,18 +372,29 @@ If point is not enclosed by any lists, return ((t) . (t))."
(funcall ended-prematurely-fn)))))))
(cons innermost outermost)))
(defun electric-pair--in-unterminated-string-p (char)
"Return non-nil if inside unterminated string started by CHAR"
(let* ((ppss (syntax-ppss))
(relevant-ppss (if (nth 4 ppss) ; in comment
(electric-pair--syntax-ppss)
ppss))
(defvar electric-pair-string-bound-function 'point-max
"Next buffer position where strings are syntatically unexpected.
Value is a function called with no arguments and returning a
buffer position. Major modes should set this variable
buffer-locally if they experience slowness with
`electric-pair-mode' when pairing quotes.")
(defun electric-pair--unbalanced-strings-p (char)
"Return non-nil if there are unbalanced strings started by CHAR."
(let* ((selector-ppss (syntax-ppss))
(relevant-ppss (save-excursion
(if (nth 4 selector-ppss) ; comment
(electric-pair--syntax-ppss
(progn
(goto-char (nth 8 selector-ppss))
(forward-comment (point-max))
(skip-syntax-backward " >!")
(point)))
(syntax-ppss
(funcall electric-pair-string-bound-function)))))
(string-delim (nth 3 relevant-ppss)))
(and (or (eq t string-delim)
(eq char string-delim))
(condition-case nil (progn (scan-sexps (nth 8 relevant-ppss) 1)
nil)
(scan-error t)))))
(or (eq t string-delim)
(eq char string-delim))))
(defun electric-pair--inside-string-p (char)
"Return non-nil if point is inside a string started by CHAR.
@ -408,9 +427,7 @@ happened."
(t
(eq (cdr outermost) pair)))))
((eq syntax ?\")
(save-excursion
(goto-char (point-max))
(electric-pair--in-unterminated-string-p char)))))
(electric-pair--unbalanced-strings-p char))))
(insert-char char)))))
(defun electric-pair-skip-if-helps-balance (char)

View file

@ -1,3 +1,10 @@
2014-04-04 João Távora <joaotavora@gmail.com>
* automated/electric-tests.el (define-electric-pair-test): Don't
overtest..
(inhibit-in-mismatched-string-inside-ruby-comments): New test.
(inhibit-in-mismatched-string-inside-c-comments): New test.
2014-04-02 João Távora <joaotavora@gmail.com>
* automated/electric-tests.el (inhibit-if-strings-mismatched):

View file

@ -141,7 +141,7 @@ Should %s \"%s\" and point at %d"
expected-string
expected-point
bindings
(modes '(quote (emacs-lisp-mode ruby-mode c++-mode)))
(modes '(quote (ruby-mode c++-mode)))
(test-in-comments t)
(test-in-strings t)
(test-in-code t)
@ -303,6 +303,48 @@ Should %s \"%s\" and point at %d"
:bindings `((electric-pair-text-syntax-table
. ,prog-mode-syntax-table)))
(define-electric-pair-test inhibit-in-mismatched-string-inside-ruby-comments
"foo\"\"
#
# \"bar\"
# \" \"
# \"
#
baz\"\""
"\""
:modes '(ruby-mode)
:test-in-strings nil
:test-in-comments nil
:expected-point 19
:expected-string
"foo\"\"
#
# \"bar\"\"
# \" \"
# \"
#
baz\"\""
:fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
(define-electric-pair-test inhibit-in-mismatched-string-inside-c-comments
"foo\"\"/*
\"bar\"
\" \"
\"
*/baz\"\""
"\""
:modes '(c-mode)
:test-in-strings nil
:test-in-comments nil
:expected-point 18
:expected-string
"foo\"\"/*
\"bar\"\"
\" \"
\"
*/baz\"\""
:fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
;;; More quotes, but now don't bind `electric-pair-text-syntax-table'
;;; to `prog-mode-syntax-table'. Use the defaults for