]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/fortran.el
(fortran-mode-syntax-table): Change `\' to `\'
[gnu-emacs] / lisp / progmodes / fortran.el
index 312fb68293021c70b35929d80be55ee747831ec3..bd0d0aad0046fba318f3649e0d93bb3f8e1b1f8c 100644 (file)
@@ -1,6 +1,6 @@
 ;;; fortran.el --- Fortran mode for GNU Emacs
 
-;; Copyright (c) 1986, 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
+;; Copyright (c) 1986, 93, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
 
 ;; Author: Michael D. Prange <prange@erl.mit.edu>
 ;; Maintainer: Dave Love <fx@gnu.org>
@@ -58,6 +58,7 @@
 
 (defgroup fortran nil
   "Fortran mode for Emacs"
+  :link '(custom-manual "(emacs)Fortran")
   :group 'languages)
 
 (defgroup fortran-indent nil
@@ -234,7 +235,7 @@ format style.")
   (modify-syntax-entry ?/ "." fortran-mode-syntax-table)
   (modify-syntax-entry ?\' "\"" fortran-mode-syntax-table)
   (modify-syntax-entry ?\" "\"" fortran-mode-syntax-table)
-  (modify-syntax-entry ?\\ "/" fortran-mode-syntax-table)
+  (modify-syntax-entry ?\\ "\\" fortran-mode-syntax-table)
   ;; This might be better as punctuation, as for C, but this way you
   ;; can treat floating-point numbers as symbols.
   (modify-syntax-entry ?. "_" fortran-mode-syntax-table) ; e.g. `a.ne.b'
@@ -243,10 +244,11 @@ format style.")
   (modify-syntax-entry ?\! "<" fortran-mode-syntax-table)
   (modify-syntax-entry ?\n ">" fortran-mode-syntax-table))
 
-;; Comments are real pain in Fortran because there is no way to represent the
-;; standard comment syntax in an Emacs syntax table (we can for VAX-style).
-;; Therefore an unmatched quote in a standard comment will throw fontification
-;; off on the wrong track.  So we do syntactic fontification with regexps.
+;; Comments are real pain in Fortran because there is no way to
+;; represent the standard comment syntax in an Emacs syntax table.
+;; (We can do so for F90-style).  Therefore an unmatched quote in a
+;; standard comment will throw fontification off on the wrong track.
+;; So we do syntactic fontification with regexps.
 \f
 ;; Regexps done by simon@gnu with help from Ulrik Dickow <dickow@nbi.dk> and
 ;; probably others Si's forgotten about (sorry).
@@ -260,33 +262,35 @@ format style.")
 (defconst fortran-font-lock-keywords-3 nil
   "Gaudy level highlighting for Fortran mode.")
 
-(defun fortran-fontify-string (limit)
-  (let ((match (match-string 1)))
-    (cond ((string= "'" match)
-          (re-search-forward "\\([^'\n]*'?\\)" limit))
-         ((string= "\"" match)
-          (re-search-forward "\\([^\"\n]*\"?\\)" limit)))))
+(defconst fortran-font-lock-syntactic-keywords nil
+  "`font-lock-syntactic-keywords' for Fortran.
+These get fixed-format comments fontified.")
 
-(let ((comment-chars "c!*d")           ; `d' for `debugging' comments
+(let ((comment-chars "cd")             ; `d' for `debugging' comments
       (fortran-type-types
-;       (eval-when-compile
-;         (regexp-opt
-;          (let ((simple-types '("character" "byte" "integer" "logical"
-;                                "none" "real" "complex"
-;                                "double[ \t]*precision" "double[ \t]*complex"))
-;                (structured-types '("structure" "union" "map"))
-;                (other-types '("record" "dimension" "parameter" "common" "save"
-;                               "external" "intrinsic" "data" "equivalence")))
-;            (append
-;             (mapcar (lambda (x) (concat "implicit[ \t]*" x)) simple-types)
-;             simple-types
-;             (mapcar (lambda (x) (concat "end[ \t]*" x)) structured-types)
-;             structured-types
-;             other-types))))
-       ;; Fixme:
-       ;; Derived from the above, changing the escaped `[ \t]*'s back.
-       ;; Should be done with a `replace all in string' function at compile time...
-       "byte\\|c\\(haracter\\|om\\(mon\\|plex\\)\\)\\|d\\(ata\\|imension\\|ouble[ \t]*\\(complex\\|precision\\)\\)\\|e\\(nd[ \t]*\\(map\\|structure\\|union\\)\\|quivalence\\|xternal\\)\\|i\\(mplicit[ \t]*\\(byte\\|c\\(haracter\\|omplex\\)\\|double[ \t]*\\(complex\\|precision\\)\\|integer\\|logical\\|none\\|real\\)\\|nt\\(eger\\|rinsic\\)\\)\\|logical\\|map\\|none\\|parameter\\|re\\(al\\|cord\\)\\|s\\(ave\\|tructure\\)\\|union")
+       (eval-when-compile
+        (let ((re (regexp-opt
+                   (let ((simple-types
+                          '("character" "byte" "integer" "logical"
+                            "none" "real" "complex"
+                            "double precision" "double complex"))
+                         (structured-types '("structure" "union" "map"))
+                         (other-types '("record" "dimension"
+                                        "parameter" "common" "save"
+                                        "external" "intrinsic" "data"
+                                        "equivalence")))
+                     (append
+                      (mapcar (lambda (x) (concat "implicit " x))
+                              simple-types)
+                      simple-types
+                      (mapcar (lambda (x) (concat "end " x))
+                              structured-types)
+                      structured-types
+                      other-types)))))
+          ;; In the optimized regexp above, replace spaces by regexp
+          ;; for optional whitespace, which regexp-opt would have
+          ;; escaped.
+          (mapconcat #'identity (split-string re) "[ \t]*"))))
       (fortran-keywords
        (eval-when-compile
          (regexp-opt '("continue" "format" "end" "enddo" "if" "then"
@@ -298,20 +302,17 @@ format style.")
          (regexp-opt '("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne"
                        "true" "false")))))
 
+  (setq fortran-font-lock-syntactic-keywords
+       ;; Fixed format comments.  (!-style handled normally.)
+       (list
+        (list (concat "^[" comment-chars "]") 0 '(11))
+        (list (concat "^[^" comment-chars "\t\n]" (make-string 71 ?.)
+                      "\\([^\n]+\\)")
+              1 '(11))))
+
   (setq fortran-font-lock-keywords-1
         (list
          ;;
-         ;; Fontify syntactically (assuming strings cannot be quoted
-         ;; or span lines).
-         (cons (concat "^[" comment-chars "].*") 'font-lock-comment-face)
-         '(fortran-match-!-comment . font-lock-comment-face)
-         (list (concat "^[^" comment-chars "\t\n]" (make-string 71 ?.)
-                       "\\(.*\\)")
-               '(1 font-lock-comment-face))
-        '("\\(\\s\"\\)"                ; single- or double-quoted string
-          (1 font-lock-string-face)
-          (fortran-fontify-string nil nil (1 font-lock-string-face)))
-         ;;
          ;; Program, subroutine and function declarations, plus calls.
          (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|"
                        "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?")
@@ -351,12 +352,14 @@ format style.")
                 ;; Fontify the type specifier.
                 '(1 font-lock-type-face)
                 ;; Fontify each declaration item (or just the /.../ block name).
-                '(font-lock-match-c-style-declaration-item-and-skip-to-next
+                `(font-lock-match-c-style-declaration-item-and-skip-to-next
                   ;; Start after any *(...) expression.
-                  (and (match-beginning 15)
-                      (condition-case nil
-                          (forward-sexp)
-                        (error nil)))
+                  (condition-case nil
+                     (and (and (match-beginning ,(+ 2 (regexp-opt-depth
+                                                       fortran-type-types)))
+                               (forward-sexp))
+                          (forward-sexp))
+                   (error nil))
                   ;; No need to clean up.
                   nil
                   ;; Fontify as a variable name, functions are
@@ -632,7 +635,10 @@ with no args, if that value is non-nil."
                              fortran-font-lock-keywords-1
                              fortran-font-lock-keywords-2
                              fortran-font-lock-keywords-3)
-                            t t ((?/ . "$/") ("_$" . "w"))))
+                            nil t ((?/ . "$/") ("_$" . "w"))
+                            beginning-of-fortran-subprogram))
+  (set (make-local-variable 'font-lock-syntactic-keywords)
+       fortran-font-lock-syntactic-keywords)
   (make-local-variable 'fortran-break-before-delimiters)
   (setq fortran-break-before-delimiters t)
   (make-local-variable 'indent-line-function)
@@ -808,7 +814,11 @@ See also `fortran-window-create-momentarily'."
          (if (< (window-width) (frame-width))
              (enlarge-window-horizontally (- (frame-width)
                                              (window-width) 1)))
-         (split-window-horizontally 73)
+         (let* ((window-edges (window-edges))
+                (scroll-bar-width (- (nth 2 window-edges)
+                                     (car window-edges)
+                                     (window-width))))
+           (split-window-horizontally (+ 72 scroll-bar-width)))
          (other-window 1)
          (switch-to-buffer " fortran-window-extra" t)
          (select-window (previous-window))))
@@ -939,37 +949,39 @@ Auto-indent does not happen if a numeric ARG is used."
 (defun beginning-of-fortran-subprogram ()
   "Moves point to the beginning of the current Fortran subprogram."
   (interactive)
-  (let ((case-fold-search t))
-    (beginning-of-line -1)
-    (if (catch 'ok
-         (while (re-search-backward fortran-end-prog-re nil 'move)
-           (if (fortran-check-end-prog-re)
-               (throw 'ok t))))
-       (forward-line))))
+  (save-match-data
+    (let ((case-fold-search t))
+      (beginning-of-line -1)
+      (if (catch 'ok
+           (while (re-search-backward fortran-end-prog-re nil 'move)
+             (if (fortran-check-end-prog-re)
+                 (throw 'ok t))))
+         (forward-line)))))
 
 (defun end-of-fortran-subprogram ()
   "Moves point to the end of the current Fortran subprogram."
   (interactive)
-  (let ((case-fold-search t))
-    (if (save-excursion                        ; on END
-         (beginning-of-line)
-         (and (looking-at fortran-end-prog-re)
-              (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))))
+  (save-match-data
+    (let ((case-fold-search t))
+      (if (save-excursion              ; on END
+           (beginning-of-line)
+           (and (looking-at fortran-end-prog-re)
+                (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)))))
 
 (defun mark-fortran-subprogram ()
   "Put mark at end of Fortran subprogram, point at beginning.
 The marks are pushed."
   (interactive)
   (end-of-fortran-subprogram)
-  (push-mark (point))
+  (push-mark (point) nil t)
   (beginning-of-fortran-subprogram))
 
 (defun fortran-previous-statement ()
@@ -1022,10 +1034,9 @@ non-comment Fortran statement in the file, and nil otherwise."
   "Make text outside the current subprogram invisible.
 The subprogram visible is the one that contains or follows point."
   (interactive)
-        (save-excursion
-          (mark-fortran-subprogram)
-          (narrow-to-region (region-beginning)
-                            (region-end))))
+  (save-excursion
+    (mark-fortran-subprogram)
+    (narrow-to-region (point) (mark))))
 
 (defmacro fortran-with-subprogram-narrowing (&rest forms)
   "Execute FORMS with buffer temporarily narrowed to current subprogram.
@@ -1049,7 +1060,7 @@ Doesn't push a mark."
        message)
     (if (save-excursion (beginning-of-line)
                        (skip-chars-forward " \t0-9")
-                       (looking-at "end[ \t]*if\\b"))
+                       (looking-at "e\\(nd[ \t]*if\\|lse\\([ \t]*if\\)?\\)\\b"))
        (progn
           (if (not (setq matching-if (fortran-beginning-if)))
               (setq message "No matching if.")
@@ -1581,26 +1592,6 @@ Return t if `comment-start-skip' found, nil if not."
          t))
     nil))
 
-;;From: simon@gnu (Simon Marshall)
-;; Find the next ! not in a string.
-(defun fortran-match-!-comment (limit)
-  (let (found)
-    (while (and (setq found (search-forward "!" limit t))
-                (fortran-is-in-string-p (point))))
-    (if (not found)
-       nil
-      ;; Cheaper than `looking-at' "!.*".
-      (set-match-data
-       (list (1- (point)) (progn (end-of-line) (min (point) limit))))
-      t)))
-
-;; The above function is about 10% faster than the below...
-;;(defun fortran-match-!-comment (limit)
-;;  (let (found)
-;;    (while (and (setq found (re-search-forward "!.*" limit t))
-;;                (fortran-is-in-string-p (match-beginning 0))))
-;;    found))
-
 ;;From: ralf@up3aud1.gwdg.de (Ralf Fassel)
 ;; Test if TAB format continuation lines work.
 (defun fortran-is-in-string-p (where)
@@ -1684,7 +1675,8 @@ automatically breaks the line at a previous space."
 
 (defun fortran-fill ()
   (interactive)
-  (let* ((opoint (point))
+  (let* ((auto-fill-function #'fortran-do-auto-fill)
+        (opoint (point))
         (bol (save-excursion (beginning-of-line) (point)))
         (eol (save-excursion (end-of-line) (point)))
         (bos (min eol (+ bol (fortran-current-line-indentation))))
@@ -1857,25 +1849,26 @@ Intended as the value of `fill-paragraph-function'."
 (defun fortran-fill-statement ()
   "Fill a fortran statement up to `fill-column'."
   (interactive)
-  (if (not (save-excursion
-             (beginning-of-line)
-             (or (looking-at "[ \t]*$")
-                 (looking-at comment-line-start-skip)
-                 (and comment-start-skip
-                      (looking-at (concat "[ \t]*" comment-start-skip))))))
-      (save-excursion
-        ;; Find beginning of statement.
-        (fortran-next-statement)
-        (fortran-previous-statement)
-        ;; Re-indent initially.
-        (fortran-indent-line)
-        ;; Replace newline plus continuation field plus indentation with
-        ;; single space.
-        (while (progn
-                 (forward-line)
-                 (fortran-remove-continuation)))
-        (fortran-previous-statement)))
-    (fortran-indent-line))
+  (let ((auto-fill-function #'fortran-do-auto-fill))
+    (if (not (save-excursion
+              (beginning-of-line)
+              (or (looking-at "[ \t]*$")
+                  (looking-at comment-line-start-skip)
+                  (and comment-start-skip
+                       (looking-at (concat "[ \t]*" comment-start-skip))))))
+       (save-excursion
+         ;; Find beginning of statement.
+         (fortran-next-statement)
+         (fortran-previous-statement)
+         ;; Re-indent initially.
+         (fortran-indent-line)
+         ;; Replace newline plus continuation field plus indentation with
+         ;; single space.
+         (while (progn
+                  (forward-line)
+                  (fortran-remove-continuation)))
+         (fortran-previous-statement)))
+    (fortran-indent-line)))
 
 (provide 'fortran)