diff options
| -rw-r--r-- | lisp/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/elec-pair.el | 55 | ||||
| -rw-r--r-- | test/ChangeLog | 7 | ||||
| -rw-r--r-- | test/automated/electric-tests.el | 44 |
4 files changed, 98 insertions, 20 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 9d2fd9854e8..ad6805f7685 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,17 @@ | |||
| 1 | 2014-04-07 João Távora <joaotavora@gmail.com> | 1 | 2014-04-07 João Távora <joaotavora@gmail.com> |
| 2 | 2 | ||
| 3 | * elec-pair.el: | ||
| 4 | (electric-pair--syntax-ppss): When inside comments parse from | ||
| 5 | comment beginning. | ||
| 6 | (electric-pair--balance-info): Fix typo in comment. | ||
| 7 | (electric-pair--in-unterminated-string-p): Delete. | ||
| 8 | (electric-pair--unbalanced-strings-p): New function. | ||
| 9 | (electric-pair-string-bound-function): New var. | ||
| 10 | (electric-pair-inhibit-if-helps-balance): Decide quote pairing | ||
| 11 | according to `electric-pair--in-unterminated-string-p' | ||
| 12 | |||
| 13 | 2014-04-07 João Távora <joaotavora@gmail.com> | ||
| 14 | |||
| 3 | * elec-pair.el (electric-pair-inhibit-if-helps-balance): Inhibit | 15 | * elec-pair.el (electric-pair-inhibit-if-helps-balance): Inhibit |
| 4 | quote pairing if point-max is inside an unterminated string. | 16 | quote pairing if point-max is inside an unterminated string. |
| 5 | (electric-pair--looking-at-unterminated-string-p): | 17 | (electric-pair--looking-at-unterminated-string-p): |
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 2a3e4008269..c16c1141800 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el | |||
| @@ -227,11 +227,19 @@ when to fallback to `parse-partial-sexp'." | |||
| 227 | (let* ((pos (or pos (point))) | 227 | (let* ((pos (or pos (point))) |
| 228 | (where (or where '(string comment))) | 228 | (where (or where '(string comment))) |
| 229 | (quick-ppss (syntax-ppss)) | 229 | (quick-ppss (syntax-ppss)) |
| 230 | (quick-ppss-at-pos (syntax-ppss pos))) | 230 | (quick-ppss-at-pos (syntax-ppss pos)) |
| 231 | (if (or (and (nth 3 quick-ppss) (memq 'string where)) | 231 | (in-string (and (nth 3 quick-ppss-at-pos) (memq 'string where))) |
| 232 | (and (nth 4 quick-ppss) (memq 'comment where))) | 232 | (in-comment (and (nth 4 quick-ppss-at-pos) (memq 'comment where))) |
| 233 | (s-or-c-start (cond (in-string | ||
| 234 | (1+ (nth 8 quick-ppss))) | ||
| 235 | (in-comment | ||
| 236 | (goto-char (nth 8 quick-ppss)) | ||
| 237 | (forward-comment (- (point-max))) | ||
| 238 | (skip-syntax-forward " >!") | ||
| 239 | (point))))) | ||
| 240 | (if s-or-c-start | ||
| 233 | (with-syntax-table electric-pair-text-syntax-table | 241 | (with-syntax-table electric-pair-text-syntax-table |
| 234 | (parse-partial-sexp (1+ (nth 8 quick-ppss)) pos)) | 242 | (parse-partial-sexp s-or-c-start pos)) |
| 235 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs | 243 | ;; HACK! cc-mode apparently has some `syntax-ppss' bugs |
| 236 | (if (memq major-mode '(c-mode c++ mode)) | 244 | (if (memq major-mode '(c-mode c++ mode)) |
| 237 | (parse-partial-sexp (point-min) pos) | 245 | (parse-partial-sexp (point-min) pos) |
| @@ -321,7 +329,7 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 321 | (scan-error | 329 | (scan-error |
| 322 | (cond ((or | 330 | (cond ((or |
| 323 | ;; some error happened and it is not of the "ended | 331 | ;; some error happened and it is not of the "ended |
| 324 | ;; prematurely" kind"... | 332 | ;; prematurely" kind... |
| 325 | (not (string-match "ends prematurely" (nth 1 err))) | 333 | (not (string-match "ends prematurely" (nth 1 err))) |
| 326 | ;; ... or we were in a comment and just came out of | 334 | ;; ... or we were in a comment and just came out of |
| 327 | ;; it. | 335 | ;; it. |
| @@ -334,18 +342,29 @@ If point is not enclosed by any lists, return ((t) . (t))." | |||
| 334 | (funcall ended-prematurely-fn))))))) | 342 | (funcall ended-prematurely-fn))))))) |
| 335 | (cons innermost outermost))) | 343 | (cons innermost outermost))) |
| 336 | 344 | ||
| 337 | (defun electric-pair--in-unterminated-string-p (char) | 345 | (defvar electric-pair-string-bound-function 'point-max |
| 338 | "Return non-nil if inside unterminated string started by CHAR" | 346 | "Next buffer position where strings are syntatically unexpected. |
| 339 | (let* ((ppss (syntax-ppss)) | 347 | Value is a function called with no arguments and returning a |
| 340 | (relevant-ppss (if (nth 4 ppss) ; in comment | 348 | buffer position. Major modes should set this variable |
| 341 | (electric-pair--syntax-ppss) | 349 | buffer-locally if they experience slowness with |
| 342 | ppss)) | 350 | `electric-pair-mode' when pairing quotes.") |
| 351 | |||
| 352 | (defun electric-pair--unbalanced-strings-p (char) | ||
| 353 | "Return non-nil if there are unbalanced strings started by CHAR." | ||
| 354 | (let* ((selector-ppss (syntax-ppss)) | ||
| 355 | (relevant-ppss (save-excursion | ||
| 356 | (if (nth 4 selector-ppss) ; comment | ||
| 357 | (electric-pair--syntax-ppss | ||
| 358 | (progn | ||
| 359 | (goto-char (nth 8 selector-ppss)) | ||
| 360 | (forward-comment (point-max)) | ||
| 361 | (skip-syntax-backward " >!") | ||
| 362 | (point))) | ||
| 363 | (syntax-ppss | ||
| 364 | (funcall electric-pair-string-bound-function))))) | ||
| 343 | (string-delim (nth 3 relevant-ppss))) | 365 | (string-delim (nth 3 relevant-ppss))) |
| 344 | (and (or (eq t string-delim) | 366 | (or (eq t string-delim) |
| 345 | (eq char string-delim)) | 367 | (eq char string-delim)))) |
| 346 | (condition-case nil (progn (scan-sexps (nth 8 relevant-ppss) 1) | ||
| 347 | nil) | ||
| 348 | (scan-error t))))) | ||
| 349 | 368 | ||
| 350 | (defun electric-pair--inside-string-p (char) | 369 | (defun electric-pair--inside-string-p (char) |
| 351 | "Return non-nil if point is inside a string started by CHAR. | 370 | "Return non-nil if point is inside a string started by CHAR. |
| @@ -378,9 +397,7 @@ happened." | |||
| 378 | (t | 397 | (t |
| 379 | (eq (cdr outermost) pair))))) | 398 | (eq (cdr outermost) pair))))) |
| 380 | ((eq syntax ?\") | 399 | ((eq syntax ?\") |
| 381 | (save-excursion | 400 | (electric-pair--unbalanced-strings-p char)))) |
| 382 | (goto-char (point-max)) | ||
| 383 | (electric-pair--in-unterminated-string-p char))))) | ||
| 384 | (insert-char char))))) | 401 | (insert-char char))))) |
| 385 | 402 | ||
| 386 | (defun electric-pair-skip-if-helps-balance (char) | 403 | (defun electric-pair-skip-if-helps-balance (char) |
diff --git a/test/ChangeLog b/test/ChangeLog index c94bf21fd36..5aca4a1d063 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,5 +1,12 @@ | |||
| 1 | 2014-04-07 João Távora <joaotavora@gmail.com> | 1 | 2014-04-07 João Távora <joaotavora@gmail.com> |
| 2 | 2 | ||
| 3 | * automated/electric-tests.el (define-electric-pair-test): Don't | ||
| 4 | overtest.. | ||
| 5 | (inhibit-in-mismatched-string-inside-ruby-comments): New test. | ||
| 6 | (inhibit-in-mismatched-string-inside-c-comments): New test. | ||
| 7 | |||
| 8 | 2014-04-07 João Távora <joaotavora@gmail.com> | ||
| 9 | |||
| 3 | * automated/electric-tests.el (inhibit-if-strings-mismatched): | 10 | * automated/electric-tests.el (inhibit-if-strings-mismatched): |
| 4 | New test, change from `inhibit-only-of-next-is-mismatched'. | 11 | New test, change from `inhibit-only-of-next-is-mismatched'. |
| 5 | 12 | ||
diff --git a/test/automated/electric-tests.el b/test/automated/electric-tests.el index 301130747f3..bcef9cc2adb 100644 --- a/test/automated/electric-tests.el +++ b/test/automated/electric-tests.el | |||
| @@ -141,7 +141,7 @@ Should %s |%s| and point at %d" | |||
| 141 | expected-string | 141 | expected-string |
| 142 | expected-point | 142 | expected-point |
| 143 | bindings | 143 | bindings |
| 144 | (modes '(quote (emacs-lisp-mode ruby-mode c++-mode))) | 144 | (modes '(quote (ruby-mode c++-mode))) |
| 145 | (test-in-comments t) | 145 | (test-in-comments t) |
| 146 | (test-in-strings t) | 146 | (test-in-strings t) |
| 147 | (test-in-code t) | 147 | (test-in-code t) |
| @@ -303,6 +303,48 @@ Should %s |%s| and point at %d" | |||
| 303 | :bindings `((electric-pair-text-syntax-table | 303 | :bindings `((electric-pair-text-syntax-table |
| 304 | . ,prog-mode-syntax-table))) | 304 | . ,prog-mode-syntax-table))) |
| 305 | 305 | ||
| 306 | (define-electric-pair-test inhibit-in-mismatched-string-inside-ruby-comments | ||
| 307 | "foo\"\" | ||
| 308 | # | ||
| 309 | # \"bar\" | ||
| 310 | # \" \" | ||
| 311 | # \" | ||
| 312 | # | ||
| 313 | baz\"\"" | ||
| 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 | # | ||
| 326 | baz\"\"" | ||
| 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 | |||
| 306 | 348 | ||
| 307 | ;;; More quotes, but now don't bind `electric-pair-text-syntax-table' | 349 | ;;; More quotes, but now don't bind `electric-pair-text-syntax-table' |
| 308 | ;;; to `prog-mode-syntax-table'. Use the defaults for | 350 | ;;; to `prog-mode-syntax-table'. Use the defaults for |