]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/octave-mod.el
Merge from emacs-23
[gnu-emacs] / lisp / progmodes / octave-mod.el
index ce18a7032d7bfe5b4e4446dff2235a54de62a6c0..12f561c68148392338efd6416df47f0962e4d485 100644 (file)
@@ -1,6 +1,6 @@
 ;;; octave-mod.el --- editing Octave source files under Emacs
 
-;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
 ;; Free Software Foundation, Inc.
 
 ;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,9 +21,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
   "Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>, bug-gnu-emacs@gnu.org"
   "Current maintainer of the Emacs Octave package.")
 
-(defvar octave-abbrev-table nil
+(define-abbrev-table 'octave-abbrev-table
+  (mapcar (lambda (e) (append e '(nil 0 t)))
+          '(("`a" "all_va_args")
+            ("`b" "break")
+            ("`cs" "case")
+            ("`ca" "catch")
+            ("`c" "continue")
+            ("`el" "else")
+            ("`eli" "elseif")
+            ("`et" "end_try_catch")
+            ("`eu" "end_unwind_protect")
+            ("`ef" "endfor")
+            ("`efu" "endfunction")
+            ("`ei" "endif")
+            ("`es" "endswitch")
+            ("`ew" "endwhile")
+            ("`f" "for")
+            ("`fu" "function")
+            ("`gl" "global")
+            ("`gp" "gplot")
+            ("`gs" "gsplot")
+            ("`if" "if ()")
+            ("`o" "otherwise")
+            ("`rp" "replot")
+            ("`r" "return")
+            ("`s" "switch")
+            ("`t" "try")
+            ("`u" "until ()")
+            ("`up" "unwind_protect")
+            ("`upc" "unwind_protect_cleanup")
+            ("`w" "while ()")))
   "Abbrev table for Octave's reserved words.
 Used in `octave-mode' and inferior-octave-mode buffers.
-All Octave abbrevs start with a grave accent (`).")
-(unless octave-abbrev-table
-  (define-abbrev-table 'octave-abbrev-table ()))
-
-(let ((abbrevs-changed abbrevs-changed))
-  (define-abbrev octave-abbrev-table "`a" "all_va_args" nil 0 t)
-  (define-abbrev octave-abbrev-table "`b" "break" nil 0 t)
-  (define-abbrev octave-abbrev-table "`cs" "case" nil 0 t)
-  (define-abbrev octave-abbrev-table "`ca" "catch" nil 0 t)
-  (define-abbrev octave-abbrev-table "`c" "continue" nil 0 t)
-  (define-abbrev octave-abbrev-table "`el" "else" nil 0 t)
-  (define-abbrev octave-abbrev-table "`eli" "elseif" nil 0 t)
-  (define-abbrev octave-abbrev-table "`et" "end_try_catch" nil 0 t)
-  (define-abbrev octave-abbrev-table "`eu" "end_unwind_protect" nil 0 t)
-  (define-abbrev octave-abbrev-table "`ef" "endfor" nil 0 t)
-  (define-abbrev octave-abbrev-table "`efu" "endfunction" nil 0 t)
-  (define-abbrev octave-abbrev-table "`ei" "endif" nil 0 t)
-  (define-abbrev octave-abbrev-table "`es" "endswitch" nil 0 t)
-  (define-abbrev octave-abbrev-table "`ew" "endwhile" nil 0 t)
-  (define-abbrev octave-abbrev-table "`f" "for" nil 0 t)
-  (define-abbrev octave-abbrev-table "`fu" "function" nil 0 t)
-  (define-abbrev octave-abbrev-table "`gl" "global" nil 0 t)
-  (define-abbrev octave-abbrev-table "`gp" "gplot" nil 0 t)
-  (define-abbrev octave-abbrev-table "`gs" "gsplot" nil 0 t)
-  (define-abbrev octave-abbrev-table "`if" "if ()" nil 0 t)
-  (define-abbrev octave-abbrev-table "`o" "otherwise" nil 0 t)
-  (define-abbrev octave-abbrev-table "`rp" "replot" nil 0 t)
-  (define-abbrev octave-abbrev-table "`r" "return" nil 0 t)
-  (define-abbrev octave-abbrev-table "`s" "switch" nil 0 t)
-  (define-abbrev octave-abbrev-table "`t" "try" nil 0 t)
-  (define-abbrev octave-abbrev-table "`u" "until ()" nil 0 t)
-  (define-abbrev octave-abbrev-table "`up" "unwind_protect" nil 0 t)
-  (define-abbrev octave-abbrev-table "`upc" "unwind_protect_cleanup" nil 0 t)
-  (define-abbrev octave-abbrev-table "`w" "while ()" nil 0 t))
+All Octave abbrevs start with a grave accent (`)."
+  :regexp "\\(?:[^`]\\|^\\)\\(\\(?:\\<\\|`\\)\\w+\\)\\W*")
 
 (defvar octave-comment-char ?#
   "Character to start an Octave comment.")
@@ -105,11 +101,9 @@ All Octave abbrevs start with a grave accent (`).")
   '("do" "for" "function" "if" "switch" "try" "unwind_protect" "while"))
 (defvar octave-else-keywords
   '("case" "catch" "else" "elseif" "otherwise" "unwind_protect_cleanup"))
-;; FIXME: only use specific "end" tokens here to avoid confusion when "end"
-;; is used in indexing (the real fix is much more complex).
 (defvar octave-end-keywords
   '("endfor" "endfunction" "endif" "endswitch" "end_try_catch"
-    "end_unwind_protect" "endwhile" "until"))
+    "end_unwind_protect" "endwhile" "until" "end"))
 
 (defvar octave-reserved-words
   (append octave-begin-keywords
@@ -220,6 +214,7 @@ parenthetical grouping.")
     (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\C-f" 'octave-insert-defun)
     (define-key map "\C-c\C-h" 'octave-help)
     (define-key map "\C-c\C-il" 'octave-send-line)
@@ -242,27 +237,27 @@ parenthetical grouping.")
 
 (defvar octave-mode-menu
   '("Octave"
-    '("Lines"
+    ("Lines"
       ["Previous Code Line"    octave-previous-code-line t]
       ["Next Code Line"                octave-next-code-line t]
       ["Begin of Continuation" octave-beginning-of-line t]
       ["End of Continuation"   octave-end-of-line t]
       ["Split Line at Point"   octave-indent-new-comment-line t])
-    '("Blocks"
+    ("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])
-    '("Functions"
+    ("Functions"
       ["Begin of Function"     octave-beginning-of-defun t]
       ["End of Function"       octave-end-of-defun t]
       ["Mark Function"         octave-mark-defun t]
       ["Indent Function"       octave-indent-defun t]
       ["Insert Function"       octave-insert-defun t])
     "-"
-    '("Debug"
+    ("Debug"
       ["Send Current Line"     octave-send-line t]
       ["Send Current Block"    octave-send-block t]
       ["Send Current Function" octave-send-defun t]
@@ -298,7 +293,8 @@ parenthetical grouping.")
     (modify-syntax-entry ?! "."   table)
     (modify-syntax-entry ?\\ "\\" table)
     (modify-syntax-entry ?\' "."  table)
-    (modify-syntax-entry ?\` "w"  table)
+    ;; Was "w" for abbrevs, but now that it's not necessary any more,
+    (modify-syntax-entry ?\` "."  table)
     (modify-syntax-entry ?\" "\"" table)
     (modify-syntax-entry ?. "w"   table)
     (modify-syntax-entry ?_ "w"   table)
@@ -345,17 +341,15 @@ newline or semicolon after an else or end keyword."
   (concat octave-block-begin-regexp "\\|" octave-block-end-regexp))
 (defvar octave-block-else-or-end-regexp
   (concat octave-block-else-regexp "\\|" octave-block-end-regexp))
-;; FIXME: only use specific "end" tokens here to avoid confusion when "end"
-;; is used in indexing (the real fix is much more complex).
 (defvar octave-block-match-alist
   '(("do" . ("until"))
-    ("for" . ("endfor"))
+    ("for" . ("endfor" "end"))
     ("function" . ("endfunction"))
-    ("if" . ("else" "elseif" "endif"))
-    ("switch" . ("case" "otherwise" "endswitch"))
+    ("if" . ("else" "elseif" "endif" "end"))
+    ("switch" . ("case" "otherwise" "endswitch" "end"))
     ("try" . ("catch" "end_try_catch"))
     ("unwind_protect" . ("unwind_protect_cleanup" "end_unwind_protect"))
-    ("while" . ("endwhile")))
+    ("while" . ("endwhile" "end")))
   "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.")
@@ -413,7 +407,7 @@ Non-nil means always go to the next Octave code line after sending."
 
 This mode makes it easier to write Octave code by helping with
 indentation, doing some of the typing for you (with Abbrev mode) and by
-showing keywords, comments, strings, etc.. in different faces (with
+showing keywords, comments, strings, etc. in different faces (with
 Font Lock mode on terminals that support it).
 
 Octave itself is a high-level language, primarily intended for numerical
@@ -683,7 +677,10 @@ level."
                        (if (= bot (point))
                            (setq icol (+ icol octave-block-offset))))
                       ((octave-looking-at-kw octave-block-end-regexp)
-                       (if (not (= bot (point)))
+                       (if (and (not (= bot (point)))
+                                ;; special case for `end' keyword,
+                                ;; applied to all keywords
+                                (not (octave-end-as-array-index-p)))
                            (setq icol (- icol
                                          (octave-block-end-offset)))))))
                  (forward-char)))
@@ -705,6 +702,15 @@ level."
        (setq icol (list comment-column icol)))))
     icol))
 
+;; FIXME: this should probably also make sure we are actually looking
+;; at the "end" keyword.
+(defun octave-end-as-array-index-p ()
+  (save-excursion
+    (condition-case nil
+       ;; Check if point is between parens
+       (progn (up-list 1) t)
+      (error nil))))
+
 (defun octave-block-end-offset ()
   (save-excursion
     (octave-backward-up-block 1)
@@ -1240,43 +1246,10 @@ otherwise."
   "Perform completion on Octave symbol preceding point.
 Compare that symbol against Octave's reserved words and builtin
 variables."
-  ;; This code taken from lisp-complete-symbol
   (interactive)
   (let* ((end (point))
-        (beg (save-excursion (backward-sexp 1) (point)))
-        (string (buffer-substring-no-properties beg end))
-        (completion (try-completion string octave-completion-alist)))
-    (cond ((eq completion t))          ; ???
-         ((null completion)
-          (message "Can't find completion for \"%s\"" string)
-          (ding))
-         ((not (string= string completion))
-           (delete-region beg end)
-           (insert completion))
-         (t
-          (let ((list (all-completions string octave-completion-alist))
-                (conf (current-window-configuration)))
-            ;; Taken from comint.el
-            (message "Making completion list...")
-            (with-output-to-temp-buffer "*Completions*"
-              (display-completion-list list string))
-            (message "Hit space to flush")
-            (let (key first)
-              (if (with-current-buffer (get-buffer "*Completions*")
-                    (setq key (read-key-sequence nil)
-                          first (aref key 0))
-                    (and (consp first) (consp (event-start first))
-                         (eq (window-buffer (posn-window (event-start
-                                                          first)))
-                             (get-buffer "*Completions*"))
-                         (eq (key-binding key) 'mouse-choose-completion)))
-                  (progn
-                    (mouse-choose-completion first)
-                    (set-window-configuration conf))
-                (if (eq first ?\ )
-                    (set-window-configuration conf)
-                  (setq unread-command-events
-                        (listify-key-sequence key))))))))))
+        (beg (save-excursion (backward-sexp 1) (point))))
+    (completion-in-region beg end octave-completion-alist)))
 
 \f
 ;;; Electric characters && friends
@@ -1296,7 +1269,7 @@ If Abbrev mode is on, expand abbrevs first."
 (defun octave-electric-semi ()
   "Insert a semicolon in Octave mode.
 Maybe expand abbrevs and blink matching block open keywords.
-Reindent the line of `octave-auto-indent' is non-nil.
+Reindent the line if `octave-auto-indent' is non-nil.
 Insert a newline if `octave-auto-newline' is non-nil."
   (interactive)
   (if (not (octave-not-in-string-or-comment-p))
@@ -1313,9 +1286,9 @@ Insert a newline if `octave-auto-newline' is non-nil."
 (defun octave-electric-space ()
   "Insert a space in Octave mode.
 Maybe expand abbrevs and blink matching block open keywords.
-Reindent the line of `octave-auto-indent' is non-nil."
+Reindent the line if `octave-auto-indent' is non-nil."
   (interactive)
-  (setq last-command-char ? )
+  (setq last-command-event ? )
   (if (and octave-auto-indent
           (not (octave-not-in-string-or-comment-p)))
       (progn
@@ -1341,7 +1314,7 @@ Note that all Octave mode abbrevs start with a grave accent."
   (if (not abbrev-mode)
       (self-insert-command 1)
     (let (c)
-      (insert last-command-char)
+      (insert last-command-event)
       (if (if (featurep 'xemacs)
              (or (eq (event-to-character (setq c (next-event))) ??)
                  (eq (event-to-character c) help-char))