Use SMIE for octave-mode.
* test/indent/octave.m: New file. * lisp/progmodes/octave-mod.el (octave-font-lock-keywords): Use regexp-opt. (octave-mode-map): Remove special bindings for forward/backward-block and octave-backward-up-block. Use smie-close-block. (octave-continuation-marker-regexp): New var. (octave-continuation-regexp): Use it. (octave-operator-table, octave-smie-op-levels) (octave-operator-regexp, octave-smie-indent-rules): New vars. (octave-smie-backward-token, octave-smie-forward-token): New funs. (octave-mode): Use SMIE. (octave-close-block): Delete.
This commit is contained in:
parent
42b6a73bc7
commit
e17b68ed83
5 changed files with 2497 additions and 41 deletions
|
|
@ -1,3 +1,16 @@
|
|||
2010-08-30 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* progmodes/octave-mod.el (octave-font-lock-keywords): Use regexp-opt.
|
||||
(octave-mode-map): Remove special bindings for forward/backward-block
|
||||
and octave-backward-up-block. Use smie-close-block.
|
||||
(octave-continuation-marker-regexp): New var.
|
||||
(octave-continuation-regexp): Use it.
|
||||
(octave-operator-table, octave-smie-op-levels)
|
||||
(octave-operator-regexp, octave-smie-indent-rules): New vars.
|
||||
(octave-smie-backward-token, octave-smie-forward-token): New funs.
|
||||
(octave-mode): Use SMIE.
|
||||
(octave-close-block): Delete.
|
||||
|
||||
2010-08-30 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* menu-bar.el (menu-bar-edit-menu) <"Paste">: Check selection in
|
||||
|
|
|
|||
|
|
@ -161,8 +161,8 @@ parenthetical grouping.")
|
|||
(list
|
||||
;; Fontify all builtin keywords.
|
||||
(cons (concat "\\<\\("
|
||||
(mapconcat 'identity octave-reserved-words "\\|")
|
||||
(mapconcat 'identity octave-text-functions "\\|")
|
||||
(regexp-opt (append octave-reserved-words
|
||||
octave-text-functions))
|
||||
"\\)\\>")
|
||||
'font-lock-keyword-face)
|
||||
;; Fontify all builtin operators.
|
||||
|
|
@ -223,13 +223,10 @@ parenthetical grouping.")
|
|||
(define-key map "\C-c\C-n" 'octave-next-code-line)
|
||||
(define-key map "\C-c\C-a" 'octave-beginning-of-line)
|
||||
(define-key map "\C-c\C-e" 'octave-end-of-line)
|
||||
(define-key map "\C-c\M-\C-n" 'octave-forward-block)
|
||||
(define-key map "\C-c\M-\C-p" 'octave-backward-block)
|
||||
(define-key map "\C-c\M-\C-u" 'octave-backward-up-block)
|
||||
(define-key map "\C-c\M-\C-d" 'octave-down-block)
|
||||
(define-key map "\C-c\M-\C-h" 'octave-mark-block)
|
||||
(define-key map "\C-c]" 'octave-close-block)
|
||||
(define-key map "\C-c/" 'octave-close-block)
|
||||
(define-key map "\C-c]" 'smie-close-block)
|
||||
(define-key map "\C-c/" 'smie-close-block)
|
||||
(define-key map "\C-c\C-f" 'octave-insert-defun)
|
||||
(define-key map "\C-c\C-h" 'octave-help)
|
||||
(define-key map "\C-c\C-il" 'octave-send-line)
|
||||
|
|
@ -261,12 +258,9 @@ parenthetical grouping.")
|
|||
["End of Continuation" octave-end-of-line t]
|
||||
["Split Line at Point" octave-indent-new-comment-line t])
|
||||
("Blocks"
|
||||
["Next Block" octave-forward-block t]
|
||||
["Previous Block" octave-backward-block t]
|
||||
["Down Block" octave-down-block t]
|
||||
["Up Block" octave-backward-up-block t]
|
||||
["Mark Block" octave-mark-block t]
|
||||
["Close Block" octave-close-block t])
|
||||
["Close Block" smie-close-block t])
|
||||
("Functions"
|
||||
["Indent Function" octave-indent-defun t]
|
||||
["Insert Function" octave-insert-defun t])
|
||||
|
|
@ -386,8 +380,11 @@ end keywords as associated values.")
|
|||
"Extra indentation applied to Octave continuation lines."
|
||||
:type 'integer
|
||||
:group 'octave)
|
||||
(eval-and-compile
|
||||
(defconst octave-continuation-marker-regexp "\\\\\\|\\.\\.\\."))
|
||||
(defvar octave-continuation-regexp
|
||||
"[^#%\n]*\\(\\\\\\|\\.\\.\\.\\)\\s-*\\(\\s<.*\\)?$")
|
||||
(concat "[^#%\n]*\\(" octave-continuation-marker-regexp
|
||||
"\\)\\s-*\\(\\s<.*\\)?$"))
|
||||
(defcustom octave-continuation-string "\\"
|
||||
"Character string used for Octave continuation lines. Normally \\."
|
||||
:type 'string
|
||||
|
|
@ -425,6 +422,143 @@ Non-nil means always go to the next Octave code line after sending."
|
|||
:group 'octave)
|
||||
|
||||
|
||||
;;; SMIE indentation
|
||||
|
||||
(require 'smie)
|
||||
|
||||
(defconst octave-operator-table
|
||||
'((assoc ";" "\n") (assoc ",") ; The doc claims they have equal precedence!?
|
||||
(right "=" "+=" "-=" "*=" "/=")
|
||||
(assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
|
||||
(assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
|
||||
(nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
|
||||
(nonassoc ":") ;No idea what this is.
|
||||
(assoc "+" "-")
|
||||
(assoc "*" "/" "\\" ".\\" ".*" "./")
|
||||
(nonassoc "'" ".'")
|
||||
(nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
|
||||
(right "^" "**" ".^" ".**")
|
||||
;; It's not really an operator, but for indentation purposes it
|
||||
;; could be convenient to treat it as one.
|
||||
(assoc "...")))
|
||||
|
||||
(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))
|
||||
)
|
||||
'((assoc "\n" ";")))
|
||||
|
||||
(smie-precs-precedence-table
|
||||
(append octave-operator-table
|
||||
'((nonassoc " -dummy- "))) ;Bogus anchor at the end.
|
||||
))))
|
||||
|
||||
;; Tokenizing needs to be refined so that ";;" is treated as two
|
||||
;; tokens and also so as to recognize the \n separator (and
|
||||
;; corresponding continuation lines).
|
||||
|
||||
(defconst octave-operator-regexp
|
||||
(regexp-opt (apply 'append (mapcar 'cdr octave-operator-table))))
|
||||
|
||||
(defun octave-smie-backward-token ()
|
||||
(let ((pos (point)))
|
||||
(forward-comment (- (point)))
|
||||
(cond
|
||||
((and (not (eq (char-before) ?\;)) ;Coalesce ";" and "\n".
|
||||
(> pos (line-end-position))
|
||||
(if (looking-back octave-continuation-marker-regexp (- (point) 3))
|
||||
(progn
|
||||
(goto-char (match-beginning 0))
|
||||
(forward-comment (- (point)))
|
||||
nil)
|
||||
t)
|
||||
;; Ignore it if it's within parentheses.
|
||||
(let ((ppss (syntax-ppss)))
|
||||
(not (and (nth 1 ppss)
|
||||
(eq ?\( (char-after (nth 1 ppss)))))))
|
||||
(skip-chars-forward " \t")
|
||||
;; Why bother distinguishing \n and ;?
|
||||
";") ;;"\n"
|
||||
((and (looking-back octave-operator-regexp (- (point) 3) 'greedy)
|
||||
;; Don't mistake a string quote for a transpose.
|
||||
(not (looking-back "\\s\"" (1- (point)))))
|
||||
(goto-char (match-beginning 0))
|
||||
(match-string-no-properties 0))
|
||||
(t
|
||||
(smie-default-backward-token)))))
|
||||
|
||||
(defun octave-smie-forward-token ()
|
||||
(skip-chars-forward " \t")
|
||||
(when (looking-at (eval-when-compile
|
||||
(concat "\\(" octave-continuation-marker-regexp
|
||||
"\\)[ \t]*\\($\\|[%#]\\)")))
|
||||
(goto-char (match-end 1))
|
||||
(forward-comment 1))
|
||||
(cond
|
||||
((and (looking-at "$\\|[%#]")
|
||||
;; Ignore it if it's within parentheses.
|
||||
(prog1 (let ((ppss (syntax-ppss)))
|
||||
(not (and (nth 1 ppss)
|
||||
(eq ?\( (char-after (nth 1 ppss))))))
|
||||
(forward-comment (point-max))))
|
||||
;; Why bother distinguishing \n and ;?
|
||||
";") ;;"\n"
|
||||
((looking-at ";[ \t]*\\($\\|[%#]\\)")
|
||||
;; Combine the ; with the subsequent \n.
|
||||
(goto-char (match-beginning 1))
|
||||
(forward-comment 1)
|
||||
";")
|
||||
((and (looking-at octave-operator-regexp)
|
||||
;; Don't mistake a string quote for a transpose.
|
||||
(not (looking-at "\\s\"")))
|
||||
(goto-char (match-end 0))
|
||||
(match-string-no-properties 0))
|
||||
(t
|
||||
(smie-default-forward-token))))
|
||||
|
||||
(defconst octave-smie-indent-rules
|
||||
'((";"
|
||||
(:parent ("function" "if" "while" "else" "elseif" "for" "otherwise"
|
||||
"case" "try" "catch" "unwind_protect" "unwind_protect_cleanup")
|
||||
;; FIXME: don't hardcode 2.
|
||||
(+ parent octave-block-offset))
|
||||
;; (:parent "switch" 4) ;For (invalid) code between switch and case.
|
||||
0)
|
||||
((:before . "case") octave-block-offset)))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode octave-mode prog-mode "Octave"
|
||||
"Major mode for editing Octave code.
|
||||
|
|
@ -511,7 +645,17 @@ already added. You just need to add a description of the problem,
|
|||
including a reproducible test case and send the message."
|
||||
(setq local-abbrev-table octave-abbrev-table)
|
||||
|
||||
(set (make-local-variable 'indent-line-function) 'octave-indent-line)
|
||||
(smie-setup octave-smie-op-levels octave-smie-indent-rules)
|
||||
(set (make-local-variable 'smie-indent-basic) 'octave-block-offset)
|
||||
(set (make-local-variable 'smie-backward-token-function)
|
||||
'octave-smie-backward-token)
|
||||
(set (make-local-variable 'smie-forward-token-function)
|
||||
'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 'comment-start) octave-comment-start)
|
||||
(set (make-local-variable 'comment-end) "")
|
||||
|
|
@ -924,29 +1068,6 @@ The block marked is the one that contains point or follows point."
|
|||
(goto-char pos)
|
||||
(message "No block to mark found"))))
|
||||
|
||||
(defun octave-close-block ()
|
||||
"Close the current Octave block on a separate line.
|
||||
An error is signaled if no block to close is found."
|
||||
(interactive)
|
||||
(let (bb-keyword)
|
||||
(condition-case nil
|
||||
(progn
|
||||
(save-excursion
|
||||
(octave-backward-up-block 1)
|
||||
(setq bb-keyword (buffer-substring-no-properties
|
||||
(match-beginning 1) (match-end 1))))
|
||||
(if (save-excursion
|
||||
(beginning-of-line)
|
||||
(looking-at "^\\s-*$"))
|
||||
(indent-according-to-mode)
|
||||
(octave-reindent-then-newline-and-indent))
|
||||
(insert (car (reverse
|
||||
(assoc bb-keyword
|
||||
octave-block-match-alist))))
|
||||
(octave-reindent-then-newline-and-indent)
|
||||
t)
|
||||
(error (message "No block to close found")))))
|
||||
|
||||
(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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
2010-08-30 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* indent/octave.m: New file.
|
||||
|
||||
2010-08-08 Ulf Jasper <ulf.jasper@web.de>
|
||||
|
||||
* icalendar-testsuite.el (icalendar-testsuite-run): Added internal tests.
|
||||
* icalendar-testsuite.el (icalendar-testsuite-run): Add internal tests.
|
||||
(icalendar-testsuite--trim, icalendar-testsuite--compare-strings)
|
||||
(icalendar-testsuite--run-internal-tests): New.
|
||||
(icalendar-testsuite--test-convert-ordinary-to-ical)
|
||||
|
|
@ -13,7 +17,7 @@
|
|||
(icalendar-testsuite--do-test-cycle): Use icalendar-testsuite--compare-strings
|
||||
(icalendar-testsuite--run-import-tests): Comment added.
|
||||
(icalendar-testsuite--run-import-tests)
|
||||
(icalendar-testsuite--run-real-world-tests): Fixed expected results.
|
||||
(icalendar-testsuite--run-real-world-tests): Fix expected results.
|
||||
|
||||
2010-06-25 Chong Yidong <cyd@stupidchicken.com>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ clean:
|
|||
# - mark the places where the indentation is known to be incorrect,
|
||||
# and allow either ignoring those errors or not.
|
||||
%.test: %
|
||||
-$(RM) $<.test
|
||||
-$(RM) $<.new
|
||||
$(EMACS) --batch $< \
|
||||
--eval '(indent-region (point-min) (point-max) nil)' \
|
||||
--eval '(write-region (point-min) (point-max) "$<.test")'
|
||||
diff -u -B $< $<.test
|
||||
--eval '(write-region (point-min) (point-max) "$<.new")'
|
||||
diff -u -B $< $<.new
|
||||
|
|
|
|||
2318
test/indent/octave.m
Normal file
2318
test/indent/octave.m
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue