;;; 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>
;; 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:
(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
: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"
;; 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)))
;; (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.")
;; 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\\|"
(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.
["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]
\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'.
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)
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)
#'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))))))
+affects all Fortran buffers, and also the default.
+If a numeric prefix argument is specified, it will be used as NCHARS,
+otherwise is a non-numeric prefix arg is specified, the length will be
+provided via the minibuffer, and otherwise the current column is used."
+ (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'."
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."))
(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))))
(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)
(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
(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)
(provide 'fortran)
-;; arch-tag: 74935096-21c4-4cab-8ee5-6ef16090dc04
;;; fortran.el ends here