Mercurial > emacs
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 " ")