]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/fortran.el
Merge branch 'emacs-25-merge'
[gnu-emacs] / lisp / progmodes / fortran.el
index eff0c2c9ce155e7a0027ef18e34803895b9aad93..33fe4b37cf84a5f54b1b55bc20646dbc2b9d7452 100644 (file)
@@ -1,8 +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, 2008, 2009, 2010, 2011, 2012
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1993-1995, 1997-2015 Free Software Foundation,
+;; Inc.
 
 ;; Author: Michael D. Prange <prange@erl.mit.edu>
 ;; Maintainer: Glenn Morris <rgm@gnu.org>
@@ -31,7 +30,7 @@
 ;; form.  For editing Fortran 90 free format source, use `f90-mode'
 ;; (f90.el).  It is meant to support the GNU Fortran language
 ;; implemented by g77 (its extensions to Fortran77 and
-;; interpretations, e.g. of blackslash in strings).
+;; interpretations, e.g. of backslash in strings).
 
 ;;; History:
 
@@ -167,7 +166,7 @@ allow trailing comments on a line."
 (defcustom fortran-directive-re
   "^[ \t]*#.*"
   "Regexp to match a directive line.
-The matching text will be fontified with `font-lock-keyword-face'.
+The matching text will be fontified with `font-lock-preprocessor-face'.
 The matching line will be given zero indentation."
   :version "22.1"
   :type    'regexp
@@ -245,8 +244,8 @@ line in region."
 (defcustom fortran-column-ruler-fixed
   "0   4 6  10        20        30        40        5\
 0        60        70\n\
-\[   ]|{   |    |    |    |    |    |    |    |    \
-\|    |    |    |    |}\n"
+[   ]|{   |    |    |    |    |    |    |    |    \
+|    |    |    |    |}\n"
   "String displayed above current line by \\[fortran-column-ruler].
 This variable is used in fixed format mode.
 See the variable `fortran-column-ruler-tab' for TAB format mode."
@@ -258,8 +257,8 @@ See the variable `fortran-column-ruler-tab' for TAB format mode."
 (defcustom fortran-column-ruler-tab
   "0       810        20        30        40        5\
 0        60        70\n\
-\[   ]|  { |    |    |    |    |    |    |    |    \
-\|    |    |    |    |}\n"
+[   ]|  { |    |    |    |    |    |    |    |    \
+|    |    |    |    |}\n"
   "String displayed above current line by \\[fortran-column-ruler].
 This variable is used in TAB format mode.
 See the variable `fortran-column-ruler-fixed' for fixed format mode."
@@ -293,7 +292,7 @@ buffer).  This corresponds to the g77 compiler option
   :type 'integer
   :safe 'integerp
   :initialize 'custom-initialize-default
-  :set (lambda (symbol value)
+  :set (lambda (_symbol value)
          ;; Do all fortran buffers, and the default.
          (fortran-line-length value t))
   :version "23.1"
@@ -454,7 +453,7 @@ The only difference is, it returns t in a case when the default returns nil."
     ;; Standard continuation character and in a TAB-formatted line.
     '("^ \\{5\\}\\([^ 0\n]\\)" 1 font-lock-string-face)
     '("^\t\\([1-9]\\)"         1 font-lock-string-face))
-   `((,fortran-directive-re (0 font-lock-keyword-face t)))
+   `((,fortran-directive-re (0 font-lock-preprocessor-face t)))
    ;; `fortran-font-lock-keywords-2' without types (see above).
    (cdr (nthcdr (length fortran-font-lock-keywords-1)
                 fortran-font-lock-keywords-2)))
@@ -488,13 +487,22 @@ Consists of level 3 plus all other intrinsics not already highlighted.")
 ;; (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.
-(defun fortran-font-lock-syntactic-keywords ()
-  "Return a value for `font-lock-syntactic-keywords' in Fortran mode.
-This varies according to the value of `fortran-line-length'.
+(defun fortran-make-syntax-propertize-function (line-length)
+  "Return a value for `syntax-propertize-function' in Fortran mode.
+This varies according to the value of LINE-LENGTH.
 This is used to fontify fixed-format Fortran comments."
-  `(("^[cd\\*]" 0 (11))
-    (,(format "^[^cd\\*\t\n].\\{%d\\}\\([^\n]+\\)" (1- fortran-line-length))
-     1 (11))))
+  ;; This results in a non-byte-compiled function.  We could pass it through
+  ;; `byte-compile', but simple benchmarks indicate that it's probably not
+  ;; worth the trouble (about 0.5% of slow down).
+  (eval                         ;I hate `eval', but it's hard to avoid it here.
+   `(syntax-propertize-rules
+     ("^[cd\\*]" (0 "<"))
+     ;; We mark all chars after line-length as "comment-start", rather than
+     ;; just the first one.  This is so that a closing ' that's past the
+     ;; line-length will indeed be ignored (and will result in a string that
+     ;; leaks into subsequent lines).
+     ((format "^[^cd\\*\t\n].\\{%d\\}\\(.+\\)" (1- line-length))
+      (1 "<")))))
 
 (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
   "Default expressions to highlight in Fortran mode.")
@@ -564,7 +572,7 @@ in the Fortran entry in `hs-special-modes-alist'.")
    ;; An alternative is to match on THEN at a line end, eg:
    ;;   ".*)[ \t]*then[ \t]*\\($\\|!\\)"
    ;; This would also match ELSE branches, though. This does not seem
-   ;; right to me, because then one has neighbouring blocks that are
+   ;; right to me, because then one has neighboring blocks that are
    ;; not nested in each other.
    "\\(if[ \t]*(\\(.*\\|"
    ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|"
@@ -593,6 +601,7 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
     (modify-syntax-entry ?=  "."  table)
     (modify-syntax-entry ?*  "."  table)
     (modify-syntax-entry ?/  "."  table)
+    (modify-syntax-entry ?%  "."  table) ; bug#8820
     (modify-syntax-entry ?\' "\"" table)
     (modify-syntax-entry ?\" "\"" table)
     ;; Consistent with GNU Fortran's default -- see the manual.
@@ -657,7 +666,7 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
          ["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"]
+          :help "Erase all customizations in buffer"]
          )
         "--"
         ["Comment Region" fortran-comment-region mark-active]
@@ -778,7 +787,7 @@ Used in the Fortran entry in `hs-special-modes-alist'.")
 
 \f
 ;;;###autoload
-(defun fortran-mode ()
+(define-derived-mode fortran-mode prog-mode "Fortran"
   "Major mode for editing Fortran code in fixed format.
 For free format code, use `f90-mode'.
 
@@ -808,15 +817,15 @@ Variables controlling indentation style and extra features:
   Amount of extra indentation for text in full-line comments (default 0).
 `fortran-comment-indent-style'
   How to indent the text in full-line comments. Allowed values are:
-  nil       don't change the indentation
-  fixed     indent to `fortran-comment-line-extra-indent' beyond the
+  nil         don't change the indentation
+  `fixed'     indent to `fortran-comment-line-extra-indent' beyond the
               value of either
                 `fortran-minimum-statement-indent-fixed' (fixed format) or
                 `fortran-minimum-statement-indent-tab' (TAB format),
               depending on the continuation format in use.
-  relative  indent to `fortran-comment-line-extra-indent' beyond the
+  `relative'  indent to `fortran-comment-line-extra-indent' beyond the
               indentation for a line of code.
-  (default 'fixed)
+  (default `fixed')
 `fortran-comment-indent-char'
   Single-character string to be inserted instead of space for
   full-line comment indentation (default \" \").
@@ -848,13 +857,9 @@ Variables controlling indentation style and extra features:
 
 Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
 with no args, if that value is non-nil."
-  (interactive)
-  (kill-all-local-variables)
-  (setq major-mode 'fortran-mode
-        mode-name "Fortran"
-        local-abbrev-table fortran-mode-abbrev-table)
-  (set-syntax-table fortran-mode-syntax-table)
-  (use-local-map fortran-mode-map)
+  :group 'fortran
+  :syntax-table fortran-mode-syntax-table
+  :abbrev-table fortran-mode-abbrev-table
   (set (make-local-variable 'indent-line-function) 'fortran-indent-line)
   (set (make-local-variable 'indent-region-function)
        (lambda (start end)
@@ -891,9 +896,9 @@ with no args, if that value is non-nil."
           fortran-font-lock-keywords-3
           fortran-font-lock-keywords-4)
          nil t ((?/ . "$/") ("_$" . "w"))
-         fortran-beginning-of-subprogram
-         (font-lock-syntactic-keywords
-          . fortran-font-lock-syntactic-keywords)))
+         fortran-beginning-of-subprogram))
+  (set (make-local-variable 'syntax-propertize-function)
+       (fortran-make-syntax-propertize-function fortran-line-length))
   (set (make-local-variable 'imenu-case-fold-search) t)
   (set (make-local-variable 'imenu-generic-expression)
        fortran-imenu-generic-expression)
@@ -906,33 +911,37 @@ with no args, if that value is non-nil."
        #'fortran-current-defun)
   (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search)
   (set (make-local-variable 'gud-find-expr-function) 'fortran-gud-find-expr)
-  (add-hook 'hack-local-variables-hook 'fortran-hack-local-variables nil t)
-  (run-mode-hooks 'fortran-mode-hook))
+  (add-hook 'hack-local-variables-hook 'fortran-hack-local-variables nil t))
 
 \f
 (defun fortran-line-length (nchars &optional global)
   "Set the length of fixed-form Fortran lines to NCHARS.
-This normally only affects the current buffer, which must be in
-Fortran mode.  If the optional argument GLOBAL is non-nil, it
-affects all Fortran buffers, and also the default."
-  (interactive "p")
-  (let (new)
-    (mapc (lambda (buff)
-            (with-current-buffer buff
-              (when (eq major-mode 'fortran-mode)
-                (setq fortran-line-length nchars
-                      fill-column fortran-line-length
-                      new (fortran-font-lock-syntactic-keywords))
-                ;; Refontify only if necessary.
-                (unless (equal new font-lock-syntactic-keywords)
-                  (setq font-lock-syntactic-keywords
-                        (fortran-font-lock-syntactic-keywords))
-                  (if font-lock-mode (font-lock-mode 1))))))
+By default this only affects the current buffer, which must be in
+Fortran mode.  If the optional argument GLOBAL is non-nil, it affects
+all Fortran buffers, and also the default.  The default value of NCHARS
+is the current column.  A numeric prefix argument specifies a value to
+use instead of the current column.  A non-numeric prefix argument prompts
+for the value to use."
+  (interactive
+   (list (cond
+          ((numberp current-prefix-arg) current-prefix-arg)
+          (current-prefix-arg
+           (read-number "Line length: " (default-value 'fortran-line-length)))
+          (t (current-column)))))
+  (dolist (buff (if global
+                    (buffer-list)
+                  (list (current-buffer))))
+    (with-current-buffer buff
+      (when (derived-mode-p 'fortran-mode)
+        (unless (eq fortran-line-length nchars)
+          (setq fortran-line-length nchars
+                fill-column fortran-line-length
+                syntax-propertize-function
+                (fortran-make-syntax-propertize-function nchars))
+          (syntax-ppss-flush-cache (point-min))
+          (if font-lock-mode (font-lock-mode 1))))))
           (if global
-              (buffer-list)
-            (list (current-buffer))))
-    (if global
-        (setq-default fortran-line-length nchars))))
+      (setq-default fortran-line-length nchars)))
 
 (defun fortran-hack-local-variables ()
   "Fortran mode adds this to `hack-local-variables-hook'."
@@ -1071,8 +1080,7 @@ The next key typed is executed unless it is SPC."
      fortran-column-ruler-fixed)
    (save-excursion
      (beginning-of-line)
-     (if (eq (window-start (selected-window))
-             (window-point (selected-window)))
+     (if (eq (window-start) (window-point))
          (line-beginning-position 2)
        (point)))
    nil "Type SPC or any command to erase ruler."))
@@ -1089,7 +1097,7 @@ See also `fortran-window-create-momentarily'."
            (scroll-bar-width (- (nth 2 window-edges)
                                 (car window-edges)
                                 (window-width))))
-      (split-window-horizontally (+ fortran-line-length scroll-bar-width)))
+      (split-window-right (+ fortran-line-length scroll-bar-width)))
     (other-window 1)
     (switch-to-buffer " fortran-window-extra" t)
     (select-window (previous-window))))
@@ -1109,7 +1117,7 @@ See also `fortran-window-create'."
           (message "Type SPC to continue editing.")
           (let ((char (read-event)))
             (or (equal char ?\s)
-                (setq unread-command-events (list char))))))
+                (push char unread-command-events)))))
     (fortran-window-create)))
 
 (defun fortran-split-line ()
@@ -1250,7 +1258,7 @@ Auto-indent does not happen if a numeric ARG is used."
 
 (defun fortran-previous-statement ()
   "Move point to beginning of the previous Fortran statement.
-Returns 'first-statement if that statement is the first
+Returns `first-statement' if that statement is the first
 non-comment Fortran statement in the file, and nil otherwise.
 Directive lines are treated as comments."
   (interactive)
@@ -1282,7 +1290,7 @@ Directive lines are treated as comments."
 
 (defun fortran-next-statement ()
   "Move point to beginning of the next Fortran statement.
-Returns 'last-statement if that statement is the last
+Returns `last-statement' if that statement is the last
 non-comment Fortran statement in the file, and nil otherwise.
 Directive lines are treated as comments."
   (interactive)
@@ -1306,8 +1314,7 @@ Directive lines are treated as comments."
     (if i
         (save-excursion
           (goto-char i)
-          (beginning-of-line)
-          (= (point) p)))))
+          (= (line-beginning-position) p)))))
 
 ;; Used in hs-special-modes-alist.
 (defun fortran-end-of-block (&optional num)
@@ -1455,7 +1462,7 @@ Return point or nil."
 
 (defun fortran-beginning-do ()
   "Search backwards for first unmatched DO [WHILE].
-Return point or nil.  Ignores labelled DO loops (ie DO 10 ... 10 CONTINUE)."
+Return point or nil.  Ignores labeled DO loops (ie DO 10 ... 10 CONTINUE)."
   (let ((case-fold-search t)
         (dostart-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]"))
     (if (save-excursion
@@ -1475,7 +1482,7 @@ Return point or nil.  Ignores labelled DO loops (ie DO 10 ... 10 CONTINUE)."
             (skip-chars-forward " \t0-9")
             (cond ((looking-at dostart-re)
                    (setq count (1- count)))
-                  ;; Note labelled loop ends not considered.
+                  ;; Note labeled loop ends not considered.
                   ((looking-at "end[ \t]*do\\b")
                    (setq count (1+ count)))))
           (and (zerop count)
@@ -2198,5 +2205,4 @@ arg DO-SPACE prevents stripping the whitespace."
 
 (provide 'fortran)
 
-;; arch-tag: 74935096-21c4-4cab-8ee5-6ef16090dc04
 ;;; fortran.el ends here