Replace last-command-char with last-command-event.
[bpt/emacs.git] / lisp / progmodes / fortran.el
index 1954319..d729462 100644 (file)
@@ -1,7 +1,7 @@
 ;;; fortran.el --- Fortran mode for GNU Emacs
 
 ;; Copyright (C) 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-;;               2002, 2003, 2004, 2005, 2006, 2007
+;;               2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 ;;               Free Software Foundation, Inc.
 
 ;; Author: Michael D. Prange <prange@erl.mit.edu>
 
 ;; 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:
 
@@ -98,7 +96,8 @@ with a character in column 6."
                                           (interactive)
                                           (describe-variable
                                            'fortran-tab-mode-string))))
-  "String to appear in mode line in TAB format buffers."
+  "String to appear in mode line in TAB format buffers.
+See Info node `(emacs)ForIndent Cont'."
   :type  'string
   :group 'fortran-indent)
 (put 'fortran-tab-mode-string 'risky-local-variable t)
@@ -149,7 +148,8 @@ nil forces comment lines not to be touched;
 
 (defcustom fortran-comment-line-start "C"
   "Delimiter inserted to start new full-line comment.
-You might want to change this to \"*\", for instance."
+You might want to change this to \"*\", for instance; or \"!\" to
+allow trailing comments on a line."
   :version "21.1"
   :type    'string
   :group   'fortran-comment)
@@ -196,7 +196,7 @@ Normally a space."
   :type  'string
   :group 'fortran-comment)
 (put 'fortran-comment-indent-char 'safe-local-variable
-     (lambda (value) (or (char-valid-p value)
+     (lambda (value) (or (characterp value)
                          (and (stringp value)
                               (= (length value) 1)))))
 
@@ -226,7 +226,7 @@ In fixed format continuation style, this character is inserted in
 column 6 by \\[fortran-split-line] to begin a continuation line.
 Also, if \\[fortran-indent-line] finds this at the beginning of a
 line, it will convert the line into a continuation line of the
-appropriate style. Normally $."
+appropriate style.  Normally \"$\"."
   :type  'string
   :group 'fortran)
 (put 'fortran-continuation-string 'safe-local-variable
@@ -391,8 +391,8 @@ program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?"
                           'paren) "\\>")
            ;; Builtin operators.
            (concat "\\." (regexp-opt
-                          '("and" "or" "not" "lt" "le" "eq" "ge"
-                            "gt" "ne" "true" "false")
+                          '("and" "eq" "eqv" "false" "ge" "gt" "le" "lt" "ne"
+                            "neqv" "not" "or" "true")
                           'paren) "\\.")
            ;; do/goto keywords and targets, and goto tags.
            '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
@@ -560,9 +560,9 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
 \f
 (defvar fortran-mode-syntax-table
   (let ((table (make-syntax-table)))
-    ;; We might like `;' to be punctuation (g77 multi-statement
-    ;; lines), but that screws abbrevs.
-    (modify-syntax-entry ?\; "w"  table)
+    ;; Was a word-constituent (for abbrevs), now punctuation (g77
+    ;; multi-statement lines).
+    (modify-syntax-entry ?\; "."  table)
     (modify-syntax-entry ?\r " "  table)
     (modify-syntax-entry ?+  "."  table)
     (modify-syntax-entry ?-  "."  table)
@@ -619,14 +619,21 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
 
     (easy-menu-define fortran-menu map "Menu for Fortran mode."
       `("Fortran"
-        ["Manual" (info "(emacs)Fortran")]
+        ["Manual" (info "(emacs)Fortran") :active t
+         :help "Read the Emacs manual chapter on Fortran mode"]
         ("Customization"
          ,(custom-menu-create 'fortran)
-         ["Set"  Custom-set t]
-         ["Save" Custom-save t]
-         ["Reset to Current" Custom-reset-current t]
-         ["Reset to Saved"   Custom-reset-saved t]
-         ["Reset to Standard Settings" Custom-reset-standard t]
+         ;; FIXME useless?
+         ["Set"  Custom-set :active t
+          :help "Set current value of all edited settings in the buffer"]
+         ["Save" Custom-save :active t
+          :help "Set and save all edited settings"]
+         ["Reset to Current" Custom-reset-current :active t
+          :help "Reset all edited settings to current"]
+         ["Reset to Saved" Custom-reset-saved :active t
+          :help "Reset all edited or set settings to saved"]
+         ["Reset to Standard Settings" Custom-reset-standard :active t
+          :help "Erase all cusomizations in buffer"]
          )
         "--"
         ["Comment Region" fortran-comment-region mark-active]
@@ -636,9 +643,12 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
         ["Indent Region"     indent-region mark-active]
         ["Indent Subprogram" fortran-indent-subprogram t]
         "--"
-        ["Beginning of Subprogram" fortran-beginning-of-subprogram t]
-        ["End of Subprogram"       fortran-end-of-subprogram       t]
+        ["Beginning of Subprogram" fortran-beginning-of-subprogram :active t
+         :help "Move point to the start of the current subprogram"]
+        ["End of Subprogram" fortran-end-of-subprogram :active t
+         :help "Move point to the end of the current subprogram"]
         ("Mark"
+         :help "Mark a region of code"
          ["Subprogram" mark-defun      t]
          ["IF Block"   fortran-mark-if t]
          ["DO Block"   fortran-mark-do t]
@@ -646,105 +656,101 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
         ["Narrow to Subprogram" narrow-to-defun t]
         ["Widen" widen t]
         "--"
-        ["Temporary column ruler" fortran-column-ruler  t]
+        ["Temporary Column Ruler" fortran-column-ruler :active t
+         :help "Briefly display Fortran column numbers"]
         ;; May not be '72', depending on fortran-line-length, but this
         ;; seems ok for a menu item.
-        ["72-column window"       fortran-window-create t]
+        ["72-column Window" fortran-window-create :active t
+         :help "Set window width to Fortran line length"]
         ["Full Width Window"
          (enlarge-window-horizontally (- (frame-width) (window-width)))
-         (not (window-full-width-p))]
-        ["Momentary 72-column window" fortran-window-create-momentarily t]
+         :active (not (window-full-width-p))
+         :help "Make window full width"]
+        ["Momentary 72-Column Window" fortran-window-create-momentarily
+         :active t :help "Briefly set window width to Fortran line length"]
         "--"
-        ["Break Line at Point"    fortran-split-line t]
-        ["Join Line"              fortran-join-line  t]
-        ["Fill Statement/Comment" fill-paragraph     t]
+        ["Break Line at Point" fortran-split-line :active t
+         :help "Break the current line at point"]
+        ["Join Line" fortran-join-line :active t
+         :help "Join the current line to the previous one"]
+        ["Fill Statement/Comment" fill-paragraph t]
         "--"
-        ["Toggle auto-fill"   auto-fill-mode :selected auto-fill-function
-         :style toggle]
-        ["Toggle abbrev-mode" abbrev-mode    :selected abbrev-mode
-         :style toggle]
-        ["Add imenu Menu" imenu-add-menubar-index
+        ["Toggle Auto Fill" auto-fill-mode :selected auto-fill-function
+         :style toggle
+         :help "Automatically fill text while typing in this buffer"]
+        ["Toggle Abbrev Mode" abbrev-mode :selected abbrev-mode
+         :style toggle :help "Expand abbreviations while typing in this buffer"]
+        ["Add Imenu Menu" imenu-add-menubar-index
          :active   (not (lookup-key (current-local-map) [menu-bar index]))
-         :included (fboundp 'imenu-add-to-menubar)]))
+         :included (fboundp 'imenu-add-to-menubar)
+         :help "Add an index menu to the menu-bar"]))
     map)
   "Keymap used in Fortran mode.")
 
 \f
-(defvar fortran-mode-abbrev-table
-  (progn
-    (define-abbrev-table 'fortran-mode-abbrev-table nil)
-    fortran-mode-abbrev-table)
-  "Abbrev table for Fortran mode.")
-
-(let (abbrevs-changed)
-  ;; Use the 6th arg (SYSTEM-FLAG) of define-abbrev if possible.
-  ;; Only use `apply' to quieten the byte-compiler.
-  (mapc
-   (function (lambda (element)
-               (condition-case nil
-                   (apply 'define-abbrev fortran-mode-abbrev-table
-                          (append element '(nil 0 t)))
-                 (wrong-number-of-arguments
-                  (apply 'define-abbrev fortran-mode-abbrev-table
-                         (append element '(nil 0)))))))
-   '((";au"   "automatic"         )
-     (";b"    "byte"              )
-     (";bd"   "block data"        )
-     (";ch"   "character"         )
-     (";cl"   "close"             )
-     (";c"    "continue"          )
-     (";cm"   "common"            )
-     (";cx"   "complex"           )
-     (";df"   "define"            )
-     (";di"   "dimension"         )
-     (";do"   "double"            )
-     (";dc"   "double complex"    )
-     (";dp"   "double precision"  )
-     (";dw"   "do while"          )
-     (";e"    "else"              )
-     (";ed"   "enddo"             )
-     (";el"   "elseif"            )
-     (";en"   "endif"             )
-     (";eq"   "equivalence"       )
-     (";ew"   "endwhere"          )
-     (";ex"   "external"          )
-     (";ey"   "entry"             )
-     (";f"    "format"            )
-     (";fa"   ".false."           )
-     (";fu"   "function"          )
-     (";g"    "goto"              )
-     (";im"   "implicit"          )
-     (";ib"   "implicit byte"     )
-     (";ic"   "implicit complex"  )
-     (";ich"  "implicit character")
-     (";ii"   "implicit integer"  )
-     (";il"   "implicit logical"  )
-     (";ir"   "implicit real"     )
-     (";inc"  "include"           )
-     (";in"   "integer"           )
-     (";intr" "intrinsic"         )
-     (";l"    "logical"           )
-     (";n"    "namelist"          )
-     (";o"    "open"              )     ; was ;op
-     (";pa"   "parameter"         )
-     (";pr"   "program"           )
-     (";ps"   "pause"             )
-     (";p"    "print"             )
-     (";rc"   "record"            )
-     (";re"   "real"              )
-     (";r"    "read"              )
-     (";rt"   "return"            )
-     (";rw"   "rewind"            )
-     (";s"    "stop"              )
-     (";sa"   "save"              )
-     (";st"   "structure"         )
-     (";sc"   "static"            )
-     (";su"   "subroutine"        )
-     (";tr"   ".true."            )
-     (";ty"   "type"              )
-     (";vo"   "volatile"          )
-     (";w"    "write"             )
-     (";wh"   "where"             ))))
+(define-abbrev-table 'fortran-mode-abbrev-table
+  (mapcar (lambda (e) (list (car e) (cdr e) nil :system t))
+          '((";au"   . "automatic"         )
+            (";b"    . "byte"              )
+            (";bd"   . "block data"        )
+            (";ch"   . "character"         )
+            (";cl"   . "close"             )
+            (";c"    . "continue"          )
+            (";cm"   . "common"            )
+            (";cx"   . "complex"           )
+            (";df"   . "define"            )
+            (";di"   . "dimension"         )
+            (";do"   . "double"            )
+            (";dc"   . "double complex"    )
+            (";dp"   . "double precision"  )
+            (";dw"   . "do while"          )
+            (";e"    . "else"              )
+            (";ed"   . "enddo"             )
+            (";el"   . "elseif"            )
+            (";en"   . "endif"             )
+            (";eq"   . "equivalence"       )
+            (";ew"   . "endwhere"          )
+            (";ex"   . "external"          )
+            (";ey"   . "entry"             )
+            (";f"    . "format"            )
+            (";fa"   . ".false."           )
+            (";fu"   . "function"          )
+            (";g"    . "goto"              )
+            (";im"   . "implicit"          )
+            (";ib"   . "implicit byte"     )
+            (";ic"   . "implicit complex"  )
+            (";ich"  . "implicit character")
+            (";ii"   . "implicit integer"  )
+            (";il"   . "implicit logical"  )
+            (";ir"   . "implicit real"     )
+            (";inc"  . "include"           )
+            (";in"   . "integer"           )
+            (";intr" . "intrinsic"         )
+            (";l"    . "logical"           )
+            (";n"    . "namelist"          )
+            (";o"    . "open"              ) ; was ;op
+            (";pa"   . "parameter"         )
+            (";pr"   . "program"           )
+            (";ps"   . "pause"             )
+            (";p"    . "print"             )
+            (";rc"   . "record"            )
+            (";re"   . "real"              )
+            (";r"    . "read"              )
+            (";rt"   . "return"            )
+            (";rw"   . "rewind"            )
+            (";s"    . "stop"              )
+            (";sa"   . "save"              )
+            (";st"   . "structure"         )
+            (";sc"   . "static"            )
+            (";su"   . "subroutine"        )
+            (";tr"   . ".true."            )
+            (";ty"   . "type"              )
+            (";vo"   . "volatile"          )
+            (";w"    . "write"             )
+            (";wh"   . "where"             )))
+  "Abbrev table for Fortran mode."
+  ;; Accept ; as the first char of an abbrev.  Also allow _ in abbrevs.
+  :regexp "\\(?:[^[:word:]_;]\\|^\\)\\(;?[[:word:]_]+\\)[^[:word:]_]*")
 
 \f
 ;;;###autoload
@@ -863,7 +869,7 @@ with no args, if that value is non-nil."
          nil t ((?/ . "$/") ("_$" . "w"))
          fortran-beginning-of-subprogram
          (font-lock-syntactic-keywords
-          . (fortran-font-lock-syntactic-keywords))))
+          . fortran-font-lock-syntactic-keywords)))
   (set (make-local-variable 'imenu-case-fold-search) t)
   (set (make-local-variable 'imenu-generic-expression)
        fortran-imenu-generic-expression)
@@ -1000,7 +1006,7 @@ With non-nil ARG, uncomments the region."
   "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs.
 Any other key combination is executed normally."
   (interactive "*")
-  (insert last-command-char)
+  (insert last-command-event)
   (let* ((event (if (fboundp 'next-command-event) ; XEmacs
                     (next-command-event)
                   (read-event)))
@@ -1161,7 +1167,7 @@ Auto-indent does not happen if a numeric ARG is used."
             (looking-at "[0-9]"))       ; within a line number
         (self-insert-command (prefix-numeric-value arg))
       (skip-chars-backward " \t")
-      (insert last-command-char)
+      (insert last-command-event)
       (fortran-indent-line))))
 
 \f
@@ -1201,12 +1207,12 @@ Auto-indent does not happen if a numeric ARG is used."
                  (fortran-check-end-prog-re)))
           (forward-line)
         (beginning-of-line 2)
-        (catch 'ok
-          (while (re-search-forward fortran-end-prog-re nil 'move)
-            (if (fortran-check-end-prog-re)
-                (throw 'ok t))))
-        (goto-char (match-beginning 0))
-        (forward-line)))))
+        (when (catch 'ok
+                (while (re-search-forward fortran-end-prog-re nil 'move)
+                  (if (fortran-check-end-prog-re)
+                      (throw 'ok t))))
+          (goto-char (match-beginning 0))
+          (forward-line))))))
 
 (defun fortran-previous-statement ()
   "Move point to beginning of the previous Fortran statement.
@@ -1665,7 +1671,17 @@ Return point or nil."
               ((and (looking-at fortran-end-prog-re1)
                     (fortran-check-end-prog-re))
                ;; Previous END resets indent to minimum.
-               (setq icol fortran-minimum-statement-indent)))))
+               (setq icol fortran-minimum-statement-indent))
+              ;; Previous statement was a numbered DO loop without a
+              ;; closing CONTINUE or END DO, so we indented the
+              ;; terminator like the loop body.
+              ((and fortran-check-all-num-for-matching-do
+                    (not (looking-at "\\(continue\\|end[ \t]*do\\)\\>"))
+                    (progn
+                      (beginning-of-line)
+                      (and (looking-at "[ \t]*[0-9]+")
+                           (fortran-check-for-matching-do))))
+               (setq icol (- icol fortran-do-indent))))))
     (save-excursion
       (beginning-of-line)
       (cond ((looking-at "[ \t]*$"))
@@ -1690,8 +1706,12 @@ Return point or nil."
                        6
                      (+ icol fortran-continuation-indent))))
             (first-statement)
+            ;; The terminating statement is actually part of the
+            ;; loop body, so unless it is a CONTINUE or END DO, we
+            ;; indent it like the loop body (see above).
             ((and fortran-check-all-num-for-matching-do
-                  (looking-at "[ \t]*[0-9]+")
+                  (looking-at "[ \t]*[0-9]+[ \t]*\
+\\(continue\\|end[ \t]*do\\)\\>")
                   (fortran-check-for-matching-do))
              (setq icol (- icol fortran-do-indent)))
             (t