changeset 110164:da442f29c7b6

Use SMIE's blink-paren for octave-mode. * lisp/progmodes/octave-mod.el (octave-font-lock-close-quotes): Backslashes do not escape single-quotes, single-quotes do. (octave-block-else-regexp, octave-block-end-regexp) (octave-block-match-alist): Remove. (octave-smie-bnf-table): New var, with old content. (octave-smie-op-levels): Use it. (octave-smie-closer-alist): New var. (octave-mode): Use it. Setup smie-blink-matching and electric-indent. (octave-blink-matching-block-open): Remove. (octave-reindent-then-newline-and-indent, octave-electric-semi) (octave-electric-space): Let self-insert-command run expand-abbrev and blink parens.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Fri, 03 Sep 2010 15:28:09 +0200
parents c9b982e5aefd
children b96da2a6e0df
files lisp/ChangeLog lisp/progmodes/octave-mod.el
diffstat 2 files changed, 91 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Fri Sep 03 15:06:51 2010 +0200
+++ b/lisp/ChangeLog	Fri Sep 03 15:28:09 2010 +0200
@@ -1,5 +1,19 @@
 2010-09-03  Stefan Monnier  <monnier@iro.umontreal.ca>
 
+	Use SMIE's blink-paren for octave-mode.
+	* progmodes/octave-mod.el (octave-font-lock-close-quotes):
+	Backslashes do not escape single-quotes, single-quotes do.
+	(octave-block-else-regexp, octave-block-end-regexp)
+	(octave-block-match-alist): Remove.
+	(octave-smie-bnf-table): New var, with old content.
+	(octave-smie-op-levels): Use it.
+	(octave-smie-closer-alist): New var.
+	(octave-mode): Use it.  Setup smie-blink-matching and electric-indent.
+	(octave-blink-matching-block-open): Remove.
+	(octave-reindent-then-newline-and-indent, octave-electric-semi)
+	(octave-electric-space): Let self-insert-command run expand-abbrev and
+	blink parens.
+
 	* electric.el (electricity): New group.
 	(electric-indent-chars): New var.
 	(electric-indent-post-self-insert-function): New fun.
--- a/lisp/progmodes/octave-mod.el	Fri Sep 03 15:06:51 2010 +0200
+++ b/lisp/progmodes/octave-mod.el	Fri Sep 03 15:28:09 2010 +0200
@@ -193,10 +193,19 @@
        ((eq (nth 3 state) ?\')
         ;; A '..' string.
         (save-excursion
-          (when (and (or (looking-at "\\('\\)")
-                         (re-search-forward "[^\\]\\(?:\\\\\\\\\\)*\\('\\)"
-                                            nil t))
-                     (not (eobp)))
+          (when (re-search-forward "\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)[^']"
+                                   nil t)
+            (goto-char (1- (point)))
+            ;; Remove any syntax-table property we may have applied to
+            ;; some of the (doubled) single quotes within the string.
+            ;; Since these are the only chars on which we place properties,
+            ;; we take a shortcut and just remove all properties.
+            (remove-text-properties (1+ (nth 8 state)) (match-beginning 1)
+                                    '(syntax-table nil))
+            (when (eq (char-before (match-beginning 1)) ?\\)
+              ;; Backslash cannot escape a single quote.
+              (put-text-property (1- (match-beginning 1)) (match-beginning 1)
+                                 'syntax-table (string-to-syntax ".")))
             (put-text-property (match-beginning 1) (match-end 1)
                                'syntax-table (string-to-syntax "\"'"))))))
 
@@ -342,29 +351,6 @@
   :type 'integer
   :group 'octave)
 
-(defvar octave-block-else-regexp
-  (concat "\\<\\("
-	  (mapconcat 'identity octave-else-keywords "\\|")
-	  "\\)\\>"))
-(defvar octave-block-end-regexp
-  (concat "\\<\\("
-	  (mapconcat 'identity octave-end-keywords "\\|")
-	  "\\)\\>"))
-(defvar octave-block-else-or-end-regexp
-  (concat octave-block-else-regexp "\\|" octave-block-end-regexp))
-(defvar octave-block-match-alist
-  '(("do" . ("until"))
-    ("for" . ("end" "endfor"))
-    ("function" . ("end" "endfunction"))
-    ("if" . ("else" "elseif" "end" "endif"))
-    ("switch" . ("case" "otherwise" "end" "endswitch"))
-    ("try" . ("catch" "end" "end_try_catch"))
-    ("unwind_protect" . ("unwind_protect_cleanup" "end" "end_unwind_protect"))
-    ("while" . ("end" "endwhile")))
-  "Alist with Octave's matching block keywords.
-Has Octave's begin keywords as keys and a list of the matching else or
-end keywords as associated values.")
-
 (defvar octave-block-comment-start
   (concat (make-string 2 octave-comment-char) " ")
   "String to insert to start a new Octave comment on an empty line.")
@@ -435,43 +421,49 @@
     ;; could be convenient to treat it as one.
     (assoc "...")))
 
+(defconst octave-smie-bnf-table
+  '((atom)
+    ;; We can't distinguish the first element in a sequence with
+    ;; precedence grammars, so we can't distinguish the condition
+    ;; if the `if' from the subsequent body, for example.
+    ;; This has to be done later in the indentation rules.
+    (exp (exp "\n" exp)
+         ;; We need to mention at least one of the operators in this part
+         ;; of the grammar: if the BNF and the operator table have
+         ;; no overlap, SMIE can't know how they relate.
+         (exp ";" exp)
+         ("try" exp "catch" exp "end_try_catch")
+         ("try" exp "catch" exp "end")
+         ("unwind_protect" exp
+          "unwind_protect_cleanup" exp "end_unwind_protect")
+         ("unwind_protect" exp "unwind_protect_cleanup" exp "end")
+         ("for" exp "endfor")
+         ("for" exp "end")
+         ("do" exp "until" atom)
+         ("while" exp "endwhile")
+         ("while" exp "end")
+         ("if" exp "endif")
+         ("if" exp "else" exp "endif")
+         ("if" exp "elseif" exp "else" exp "endif")
+         ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
+         ("if" exp "elseif" exp "elseif" exp "else" exp "end")
+         ("switch" exp "case" exp "endswitch")
+         ("switch" exp "case" exp "otherwise" exp "endswitch")
+         ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
+         ("switch" exp "case" exp "case" exp "otherwise" exp "end")
+         ("function" exp "endfunction")
+         ("function" exp "end"))
+    ;; (fundesc (atom "=" atom))
+    ))
+
+(defconst octave-smie-closer-alist
+  (smie-bnf-closer-alist octave-smie-bnf-table))
+
 (defconst octave-smie-op-levels
   (smie-prec2-levels
    (smie-merge-prec2s
     (smie-bnf-precedence-table
-     '((atom)
-       ;; We can't distinguish the first element in a sequence with
-       ;; precedence grammars, so we can't distinguish the condition
-       ;; if the `if' from the subsequent body, for example.
-       ;; This has to be done later in the indentation rules.
-       (exp (exp "\n" exp)
-            ;; We need to mention at least one of the operators in this part
-            ;; of the grammar: if the BNF and the operator table have
-            ;; no overlap, SMIE can't know how they relate.
-            (exp ";" exp)
-            ("try" exp "catch" exp "end_try_catch")
-            ("try" exp "catch" exp "end")
-            ("unwind_protect" exp
-             "unwind_protect_cleanup" exp "end_unwind_protect")
-            ("unwind_protect" exp "unwind_protect_cleanup" exp "end")
-            ("for" exp "endfor")
-            ("for" exp "end")
-            ("do" exp "until" atom)
-            ("while" exp "endwhile")
-            ("while" exp "end")
-            ("if" exp "endif")
-            ("if" exp "else" exp "endif")
-            ("if" exp "elseif" exp "else" exp "endif")
-            ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
-            ("if" exp "elseif" exp "elseif" exp "else" exp "end")
-            ("switch" exp "case" exp "endswitch")
-            ("switch" exp "case" exp "otherwise" exp "endswitch")
-            ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
-            ("switch" exp "case" exp "case" exp "otherwise" exp "end")
-            ("function" exp "endfunction")
-            ("function" exp "end"))
-       ;; (fundesc (atom "=" atom))
-       )
+     octave-smie-bnf-table
      '((assoc "\n" ";")))
 
     (smie-precs-precedence-table
@@ -646,9 +638,28 @@
        'octave-smie-forward-token)
   (set (make-local-variable 'forward-sexp-function)
        'smie-forward-sexp-command)
-  (set (make-local-variable 'smie-closer-alist)
-       (mapcar (lambda (elem) (cons (car elem) (car (last elem))))
-               octave-block-match-alist))
+  (set (make-local-variable 'smie-closer-alist) octave-smie-closer-alist)
+  ;; Only needed for interactive calls to blink-matching-open.
+  (set (make-local-variable 'blink-matching-check-function)
+       #'smie-blink-matching-check)
+
+  (when octave-blink-matching-block
+    (add-hook 'post-self-insert-hook #'smie-blink-matching-open 'append 'local)
+    (set (make-local-variable 'smie-blink-matching-triggers)
+         (append smie-blink-matching-triggers '(\;)
+                 ;; Rather than wait for SPC or ; to blink, try to blink as
+                 ;; soon as we type the last char of a block ender.
+                 ;; But strip ?d from this list so that we don't blink twice
+                 ;; when the user writes "endif" (once at "end" and another
+                 ;; time at "endif").
+                 (delq ?d (delete-dups
+                           (mapcar (lambda (kw)
+                                     (aref (cdr kw) (1- (length (cdr kw)))))
+                                   smie-closer-alist))))))
+
+  ;; FIXME: maybe we should use (cons ?\; electric-indent-chars)
+  ;; since only ; is really octave-specific.
+  (set (make-local-variable 'electric-indent-chars) '(?\; ?\s ?\n))
 
   (set (make-local-variable 'comment-start) octave-comment-start)
   (set (make-local-variable 'comment-end) "")
@@ -846,54 +857,6 @@
     (backward-up-list 1))
   (mark-sexp))
 
-(defun octave-blink-matching-block-open ()
-  "Blink the matching Octave begin block keyword.
-If point is right after an Octave else or end type block keyword, move
-cursor momentarily to the corresponding begin keyword.
-Signal an error if the keywords are incompatible."
-  (interactive)
-  (let (bb-keyword bb-arg eb-keyword pos eol)
-    (if (and (octave-not-in-string-or-comment-p)
-	     (looking-at "\\>")
-	     (save-excursion
-	       (skip-syntax-backward "w")
-	       (octave-looking-at-kw octave-block-else-or-end-regexp)))
-	(save-excursion
-	  (cond
-	   ((match-end 1)
-	    (setq eb-keyword
-		  (buffer-substring-no-properties
-		   (match-beginning 1) (match-end 1)))
-	    (backward-up-list 1))
-	   ((match-end 2)
-	    (setq eb-keyword
-		  (buffer-substring-no-properties
-		   (match-beginning 2) (match-end 2)))
-	    (backward-sexp 1)))
-	  (setq pos (match-end 0)
-		bb-keyword
-		(buffer-substring-no-properties
-		 (match-beginning 0) pos)
-		pos (+ pos 1)
-		eol (line-end-position)
-		bb-arg
-		(save-excursion
-		  (save-restriction
-		    (goto-char pos)
-		    (while (and (skip-syntax-forward "^<" eol)
-				(octave-in-string-p)
-				(not (forward-char 1))))
-		    (skip-syntax-backward " ")
-		    (buffer-substring-no-properties pos (point)))))
-	  (if (member eb-keyword
-		      (cdr (assoc bb-keyword octave-block-match-alist)))
-	      (progn
-		(message "Matches `%s %s'" bb-keyword bb-arg)
-		(if (pos-visible-in-window-p)
-		    (sit-for blink-matching-delay)))
-	    (error "Block keywords `%s' and `%s' do not match"
-		   bb-keyword eb-keyword))))))
-
 (defun octave-beginning-of-defun (&optional arg)
   "Move backward to the beginning of an Octave function.
 With positive ARG, do it that many times.  Negative argument -N means
@@ -1082,9 +1045,6 @@
 If Abbrev mode is on, expand abbrevs first."
   ;; FIXME: None of this is Octave-specific.
   (interactive)
-  (if abbrev-mode (expand-abbrev))
-  (if octave-blink-matching-block
-      (octave-blink-matching-block-open))
   (reindent-then-newline-and-indent))
 
 (defun octave-electric-semi ()
@@ -1093,14 +1053,12 @@
 Reindent the line if `octave-auto-indent' is non-nil.
 Insert a newline if `octave-auto-newline' is non-nil."
   (interactive)
+  (setq last-command-event ?\;)
   (if (not (octave-not-in-string-or-comment-p))
-      (insert ";")
-    (if abbrev-mode (expand-abbrev))
-    (if octave-blink-matching-block
-	(octave-blink-matching-block-open))
+      (self-insert-command 1)
     (if octave-auto-indent
 	(indent-according-to-mode))
-    (insert ";")
+    (self-insert-command 1)
     (if octave-auto-newline
 	(newline-and-indent))))
 
@@ -1115,9 +1073,6 @@
       (progn
 	(indent-according-to-mode)
 	(self-insert-command 1))
-    (if abbrev-mode (expand-abbrev))
-    (if octave-blink-matching-block
-	(octave-blink-matching-block-open))
     (if (and octave-auto-indent
 	     (save-excursion
 	       (skip-syntax-backward " ")