]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/f90.el
Merge from mainline.
[gnu-emacs] / lisp / progmodes / f90.el
index eda9f4e01557a33a240fb069b6fdc7231467e492..111c12754e8e7578cac59a4f345dc5f143f3f9aa 100644 (file)
@@ -1,7 +1,7 @@
 ;;; f90.el --- Fortran-90 mode (free format)
 
 ;; Copyright (C) 1995, 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005,
-;;   2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+;;   2006, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
 
 ;; Author: Torbj\"orn Einarsson <Torbjorn.Einarsson@era.ericsson.se>
 ;; Maintainer: Glenn Morris <rgm@gnu.org>
 ;; 3. Support for align.
 ;; Font-locking:
 ;; 1. OpenMP, OpenMPI?, preprocessor highlighting.
-;; 2. interface blah - Highlight "blah" in function-name face?
-;; Need to avoid "interface operator (+)" etc.
-;; 3. integer_name = 1
-;; 4. Labels for "else" statements (F2003)?
+;; 2. integer_name = 1
+;; 3. Labels for "else" statements (F2003)?
 
 (defvar comment-auto-fill-only-comments)
 (defvar font-lock-keywords)
@@ -467,22 +465,21 @@ type-name parts, respectively."
 ;;;      (1 font-lock-keyword-face) (3 font-lock-function-name-face))
    '(f90-typedef-matcher
      (1 font-lock-keyword-face) (2 font-lock-function-name-face))
-   ;; Other functions and declarations.
+    ;; F2003.  Prevent operators being highlighted as functions.
+    '("\\<\\(\\(?:end[ \t]*\\)?interface[ \t]*\\(?:assignment\\|operator\\|\
+read\\|write\\)\\)[ \t]*(" (1 font-lock-keyword-face t))
+   ;; Other functions and declarations.  Named interfaces = F2003.
    '("\\<\\(\\(?:end[ \t]*\\)?\\(program\\|module\\|function\\|associate\\|\
-subroutine\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?"
+subroutine\\|interface\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?"
      (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
    ;; F2003.
    '("\\<\\(use\\)[ \t]*,[ \t]*\\(\\(?:non_\\)?intrinsic\\)[ \t]*::[ \t]*\
 \\(\\sw+\\)"
      (1 font-lock-keyword-face) (2 font-lock-keyword-face)
      (3 font-lock-function-name-face))
-   "\\<\\(\\(end[ \t]*\\)?block[ \t]*data\\|contains\\|\
-end[ \t]*interface\\)\\>"
-   ;; "abstract interface" is F2003. Must come after previous entry.
-   '("\\<\\(\\(?:abstract[ \t]*\\)?interface\\)\\>"
-     ;; [ \t]*\\(\\(\\sw+\\)[ \t]*[^(]\\)?"
-     ;; (2) messes up "interface operator ()", etc.
-     (1 font-lock-keyword-face))) ;(2 font-lock-function-name-face nil t)))
+   "\\<\\(\\(end[ \t]*\\)?block[ \t]*data\\|contains\\)\\>"
+   ;; "abstract interface" is F2003.
+   '("\\<abstract[ \t]*interface\\>" (0 font-lock-keyword-face t)))
   "This does fairly subdued highlighting of comments and function calls.")
 
 ;; NB not explicitly handling this, yet it seems to work.
@@ -660,6 +657,7 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
     (define-key map "\C-c\C-f" 'f90-fill-region)
     (define-key map "\C-c\C-p" 'f90-previous-statement)
     (define-key map "\C-c\C-n" 'f90-next-statement)
+    (define-key map "\C-c]"    'f90-insert-end)
     (define-key map "\C-c\C-w" 'f90-insert-end)
     ;; Standard tab binding will call this, and also handle regions.
 ;;;    (define-key map "\t"       'f90-indent-line)
@@ -1011,7 +1009,7 @@ Set subexpression 1 in the match-data to the name of the type."
   :regexp "\\(?:[^[:word:]_`]\\|^\\)\\(`?[[:word:]_]+\\)[^[:word:]_]*")
 \f
 ;;;###autoload
-(defun f90-mode ()
+(define-derived-mode f90-mode prog-mode "F90"
   "Major mode for editing Fortran 90,95 code in free format.
 For fixed format code, use `fortran-mode'.
 
@@ -1068,16 +1066,10 @@ Variables controlling indentation style and extra features:
 
 Turning on F90 mode calls the value of the variable `f90-mode-hook'
 with no args, if that value is non-nil."
-  (interactive)
-  (kill-all-local-variables)
-  (setq major-mode 'f90-mode
-        mode-name "F90"
-        local-abbrev-table f90-mode-abbrev-table)
-  (set-syntax-table f90-mode-syntax-table)
-  (use-local-map f90-mode-map)
+  :group 'f90
+  :abbrev-table f90-mode-abbrev-table
   (set (make-local-variable 'indent-line-function) 'f90-indent-line)
   (set (make-local-variable 'indent-region-function) 'f90-indent-region)
-  (set (make-local-variable 'require-final-newline) mode-require-final-newline)
   (set (make-local-variable 'comment-start) "!")
   (set (make-local-variable 'comment-start-skip) "!+ *")
   (set (make-local-variable 'comment-indent-function) 'f90-comment-indent)
@@ -1097,8 +1089,7 @@ with no args, if that value is non-nil."
        'f90-beginning-of-subprogram)
   (set (make-local-variable 'end-of-defun-function) 'f90-end-of-subprogram)
   (set (make-local-variable 'add-log-current-defun-function)
-       #'f90-current-defun)
-  (run-mode-hooks 'f90-mode-hook))
+       #'f90-current-defun))
 
 \f
 ;; Inline-functions.
@@ -1229,7 +1220,7 @@ NAME is nil if the statement has no label."
 
 (defsubst f90-looking-at-type-like ()
   "Return (KIND NAME) if a type/enum/interface/block-data starts after point.
-NAME is non-nil only for type."
+NAME is non-nil only for type and certain interfaces."
   (cond
    ((save-excursion
       (and (looking-at "\\<type\\>[ \t]*")
@@ -1242,7 +1233,15 @@ NAME is non-nil only for type."
 ;;;    ((and (not (looking-at f90-typeis-re))
 ;;;          (looking-at f90-type-def-re))
 ;;;     (list (match-string 1) (match-string 2)))
-   ((looking-at "\\(enum\\|interface\\|block[ \t]*data\\)\\>")
+   ((looking-at "\\<\\(interface\\)\\>[ \t]*")
+    (list (match-string 1)
+          (save-excursion
+            (goto-char (match-end 0))
+            (if (or (looking-at "\\(operator\\|assignment\\|read\\|\
+write\\)[ \t]*([^)\n]*)")
+                    (looking-at "\\sw+"))
+                (match-string 0)))))
+   ((looking-at "\\(enum\\|block[ \t]*data\\)\\>")
     (list (match-string 1) nil))
    ((looking-at "abstract[ \t]*\\(interface\\)\\>")
     (list (match-string 1) nil))))
@@ -1270,9 +1269,12 @@ NAME is non-nil only for type."
 
 (defsubst f90-looking-at-program-block-end ()
   "Return (KIND NAME) if a block with name NAME ends after point."
-  (if (looking-at (concat "end[ \t]*" f90-blocks-re
-                          "?\\([ \t]+\\(\\sw+\\)\\)?\\>"))
-      (list (match-string 1) (match-string 3))))
+  (cond ((looking-at "end[ \t]*\\(interface\\)[ \t]*\\(\
+\\(?:assignment\\|operator\\|read\\|write\\)[ \t]*([^)\n]*)\\)")
+         (list (match-string 1) (match-string 2)))
+        ((looking-at (concat "end[ \t]*" f90-blocks-re
+                             "?\\([ \t]+\\(\\sw+\\)\\)?\\>"))
+        (list (match-string 1) (match-string 3)))))
 
 (defsubst f90-comment-indent ()
   "Return the indentation to be used for a comment starting at point.
@@ -1348,6 +1350,8 @@ if all else fails."
   (if auto-fill-function (f90-do-auto-fill) ; also updates line
     (f90-update-line)))
 
+;; Behave like self-insert-command for delete-selection-mode (bug#5593).
+(put 'f90-electric-insert 'delete-selection t)
 
 (defun f90-get-correct-indent ()
   "Get correct indent for a line starting with line number.
@@ -2201,7 +2205,7 @@ CHANGE-WORD should be one of 'upcase-word, 'downcase-word, 'capitalize-word."
 With optional argument ALL, change the default for all present
 and future F90 buffers.  F90 mode normally treats backslash as an
 escape character."
-  (or (eq major-mode 'f90-mode)
+  (or (derived-mode-p 'f90-mode)
       (error "This function should only be used in F90 buffers"))
   (when (equal (char-syntax ?\\ ) ?\\ )
     (or all (set-syntax-table (copy-syntax-table (syntax-table))))
@@ -2210,5 +2214,4 @@ escape character."
 
 (provide 'f90)
 
-;; arch-tag: fceac97c-c147-44bd-aec0-172d4b560ef8
 ;;; f90.el ends here