changeset 110155:c62c9d6b8eef

Add blink-matching-check-function and misc cleanups. * lisp/simple.el (newline): Eliminate optimization. Use post-self-insert-hook to set hard-newline and things before running post-self-insert-hook. (blink-matching-check-mismatch): New function. (blink-matching-check-function): New variable. (blink-matching-open): Use them. Skip back forward over prefix chars skipped by forward-sexp. Don't check if the parens are backslash escaped. (blink-paren-post-self-insert-function): Check backslash escaping here.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Thu, 02 Sep 2010 23:57:08 +0200
parents dd1cdc89c51a
children a2439ed30c52 db7a9f029b0e
files lisp/ChangeLog lisp/simple.el
diffstat 2 files changed, 92 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Thu Sep 02 18:06:51 2010 +0200
+++ b/lisp/ChangeLog	Thu Sep 02 23:57:08 2010 +0200
@@ -1,7 +1,19 @@
+2010-09-02  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* simple.el (newline): Eliminate optimization.
+	Use post-self-insert-hook to set hard-newline and things before
+	running post-self-insert-hook.
+	(blink-matching-check-mismatch): New function.
+	(blink-matching-check-function): New variable.
+	(blink-matching-open): Use them.
+	Skip back forward over prefix chars skipped by forward-sexp.
+	Don't check if the parens are backslash escaped.
+	(blink-paren-post-self-insert-function): Check backslash escaping here.
+
 2010-09-02  Chong Yidong  <cyd@stupidchicken.com>
 
-	* emacs-lisp/package.el (package-menu-mode-map): Change
-	package-menu-revert bindings to revert-buffer.
+	* emacs-lisp/package.el (package-menu-mode-map):
+	Change package-menu-revert bindings to revert-buffer.
 	(package-menu-mode): Set revert-buffer-function.
 	(package-menu-revert): Doc fix.
 
--- a/lisp/simple.el	Thu Sep 02 18:06:51 2010 +0200
+++ b/lisp/simple.el	Thu Sep 02 23:57:08 2010 +0200
@@ -457,72 +457,38 @@
 than the value of `fill-column' and ARG is nil."
   (interactive "*P")
   (barf-if-buffer-read-only)
-  ;; Inserting a newline at the end of a line produces better redisplay in
-  ;; try_window_id than inserting at the beginning of a line, and the textual
-  ;; result is the same.  So, if we're at beginning of line, pretend to be at
-  ;; the end of the previous line.
-  (let ((flag (and (not (bobp))
-		   (bolp)
-		   ;; Make sure no functions want to be told about
-		   ;; the range of the changes.
-		   (not after-change-functions)
-		   (not before-change-functions)
-		   ;; Make sure there are no markers here.
-		   (not (buffer-has-markers-at (1- (point))))
-		   (not (buffer-has-markers-at (point)))
-		   ;; Make sure no text properties want to know
-		   ;; where the change was.
-		   (not (get-char-property (1- (point)) 'modification-hooks))
-		   (not (get-char-property (1- (point)) 'insert-behind-hooks))
-		   (or (eobp)
-		       (not (get-char-property (point) 'insert-in-front-hooks)))
-		   ;; Make sure the newline before point isn't intangible.
-		   (not (get-char-property (1- (point)) 'intangible))
-		   ;; Make sure the newline before point isn't read-only.
-		   (not (get-char-property (1- (point)) 'read-only))
-		   ;; Make sure the newline before point isn't invisible.
-		   (not (get-char-property (1- (point)) 'invisible))
-		   ;; Make sure the newline before point has the same
-		   ;; properties as the char before it (if any).
-		   (< (or (previous-property-change (point)) -2)
-		      (- (point) 2))))
-	(was-page-start (and (bolp)
+  (let ((was-page-start (and (bolp)
 			     (looking-at page-delimiter)))
 	(beforepos (point)))
-    (if flag (backward-char 1))
     ;; Call self-insert so that auto-fill, abbrev expansion etc. happens.
     ;; Set last-command-event to tell self-insert what to insert.
     (let ((last-command-event ?\n)
 	  ;; Don't auto-fill if we have a numeric argument.
-	  ;; Also not if flag is true (it would fill wrong line);
-	  ;; there is no need to since we're at BOL.
-	  (auto-fill-function (if (or arg flag) nil auto-fill-function)))
-      (unwind-protect
-	  (self-insert-command (prefix-numeric-value arg))
-	;; If we get an error in self-insert-command, put point at right place.
-	(if flag (forward-char 1))))
-    ;; Even if we did *not* get an error, keep that forward-char;
-    ;; all further processing should apply to the newline that the user
-    ;; thinks he inserted.
-
-    ;; Mark the newline(s) `hard'.
-    (if use-hard-newlines
-	(set-hard-newline-properties
-	 (- (point) (prefix-numeric-value arg)) (point)))
-    ;; If the newline leaves the previous line blank,
-    ;; and we have a left margin, delete that from the blank line.
-    (or flag
-	(save-excursion
-	  (goto-char beforepos)
-	  (beginning-of-line)
-	  (and (looking-at "[ \t]$")
-	       (> (current-left-margin) 0)
-	       (delete-region (point) (progn (end-of-line) (point))))))
-    ;; Indent the line after the newline, except in one case:
-    ;; when we added the newline at the beginning of a line
-    ;; which starts a page.
-    (or was-page-start
-	(move-to-left-margin nil t)))
+	  (auto-fill-function (if arg nil auto-fill-function))
+          (post-self-insert-hook post-self-insert-hook))
+      ;; Do the rest in post-self-insert-hook, because we want to do it
+      ;; *before* other functions on that hook.
+      (add-hook 'post-self-insert-hook
+                (lambda ()
+                  ;; Mark the newline(s) `hard'.
+                  (if use-hard-newlines
+                      (set-hard-newline-properties
+                       (- (point) (prefix-numeric-value arg)) (point)))
+                  ;; If the newline leaves the previous line blank, and we
+                  ;; have a left margin, delete that from the blank line.
+                  (save-excursion
+                    (goto-char beforepos)
+                    (beginning-of-line)
+                    (and (looking-at "[ \t]$")
+                         (> (current-left-margin) 0)
+                         (delete-region (point)
+                                        (line-end-position))))
+                  ;; Indent the line after the newline, except in one case:
+                  ;; when we added the newline at the beginning of a line which
+                  ;; starts a page.
+                  (or was-page-start
+                      (move-to-left-margin nil t))))
+      (self-insert-command (prefix-numeric-value arg))))
   nil)
 
 (defun set-hard-newline-properties (from to)
@@ -5503,21 +5469,40 @@
   :type 'boolean
   :group 'paren-blinking)
 
+(defun blink-matching-check-mismatch (start end)
+  "Return whether or not START...END are matching parens.
+END is the current point and START is the blink position.
+START might be nil if no matching starter was found.
+Returns non-nil if we find there is a mismatch."
+  (let* ((end-syntax (syntax-after (1- end)))
+         (matching-paren (and (consp end-syntax)
+                              (eq (syntax-class end-syntax) 5)
+                              (cdr end-syntax))))
+    ;; For self-matched chars like " and $, we can't know when they're
+    ;; mismatched or unmatched, so we can only do it for parens.
+    (when matching-paren
+      (not (and start
+                (or
+                 (eq (char-after start) matching-paren)
+                 ;; The cdr might hold a new paren-class info rather than
+                 ;; a matching-char info, in which case the two CDRs
+                 ;; should match.
+                 (eq matching-paren (cdr-safe (syntax-after start)))))))))
+
+(defvar blink-matching-check-function #'blink-matching-check-mismatch
+  "Function to check parentheses mismatches.
+The function takes two arguments (START and END) where START is the
+position just before the opening token and END is the position right after.
+START can be nil, if it was not found.
+The function should return non-nil if the two tokens do not match.")
+
 (defun blink-matching-open ()
   "Move cursor momentarily to the beginning of the sexp before point."
   (interactive)
-  (when (and (> (point) (point-min))
-	     blink-matching-paren
-	     ;; Verify an even number of quoting characters precede the close.
-	     (= 1 (logand 1 (- (point)
-			       (save-excursion
-				 (forward-char -1)
-				 (skip-syntax-backward "/\\")
-				 (point))))))
+  (when (and (not (bobp))
+	     blink-matching-paren)
     (let* ((oldpos (point))
-	   (message-log-max nil)  ; Don't log messages about paren matching.
-	   (atdollar (eq (syntax-class (syntax-after (1- oldpos))) 8))
-	   (isdollar)
+	   (message-log-max nil) ; Don't log messages about paren matching.
 	   (blinkpos
             (save-excursion
               (save-restriction
@@ -5532,38 +5517,25 @@
                   (condition-case ()
                       (progn
                         (forward-sexp -1)
+                        ;; backward-sexp skips backward over prefix chars,
+                        ;; so move back to the matching paren.
+                        (while (and (< (point) (1- oldpos))
+                                    (let ((code (car (syntax-after (point)))))
+                                      (or (eq (logand 65536 code) 6)
+                                          (eq (logand 1048576 code) 1048576))))
+                          (forward-char 1))
                         (point))
                     (error nil))))))
-	   (matching-paren
-            (and blinkpos
-                 ;; Not syntax '$'.
-                 (not (setq isdollar
-                            (eq (syntax-class (syntax-after blinkpos)) 8)))
-                 (let ((syntax (syntax-after blinkpos)))
-                   (and (consp syntax)
-                        (eq (syntax-class syntax) 4)
-                        (cdr syntax))))))
+           (mismatch (funcall blink-matching-check-function blinkpos oldpos)))
       (cond
-       ;; isdollar is for:
-       ;; http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00871.html
-       ((not (or (and isdollar blinkpos)
-                 (and atdollar (not blinkpos)) ; see below
-                 (eq matching-paren (char-before oldpos))
-                 ;; The cdr might hold a new paren-class info rather than
-                 ;; a matching-char info, in which case the two CDRs
-                 ;; should match.
-                 (eq matching-paren (cdr (syntax-after (1- oldpos))))))
-	(if (minibufferp)
-	    (minibuffer-message " [Mismatched parentheses]")
-	  (message "Mismatched parentheses")))
-       ((not blinkpos)
-        (or blink-matching-paren-distance
-            ;; Don't complain when `$' with no blinkpos, because it
-            ;; could just be the first one typed in the buffer.
-            atdollar
+       (mismatch
+        (if blinkpos
             (if (minibufferp)
-		(minibuffer-message " [Unmatched parenthesis]")
-	      (message "Unmatched parenthesis"))))
+                (minibuffer-message " [Mismatched parentheses]")
+              (message "Mismatched parentheses"))
+          (if (minibufferp)
+              (minibuffer-message " [Unmatched parenthesis]")
+            (message "Unmatched parenthesis"))))
        ((pos-visible-in-window-p blinkpos)
         ;; Matching open within window, temporarily move to blinkpos but only
         ;; if `blink-matching-paren-on-screen' is non-nil.
@@ -5615,7 +5587,13 @@
              (memq (char-syntax last-command-event) '(?\) ?\$))
              blink-paren-function
              (not executing-kbd-macro)
-             (not noninteractive))
+             (not noninteractive)
+	     ;; Verify an even number of quoting characters precede the close.
+	     (= 1 (logand 1 (- (point)
+			       (save-excursion
+				 (forward-char -1)
+				 (skip-syntax-backward "/\\")
+				 (point))))))
     (funcall blink-paren-function)))
 
 (add-hook 'post-self-insert-hook #'blink-paren-post-self-insert-function