# HG changeset patch # User Glenn Morris # Date 1112122742 0 # Node ID 9554f19ae0682ee066cc746ed08d8008b9f5b88e # Parent 888d43e15dfd808db244a9110260ca3bab207bd0 Reformat and update copyright years. (fortran-if-indent): Doc fix. (fortran-font-lock-keywords-2): Add "where", "elsewhere". (fortran-font-lock-keywords-4): New variable. (fortran-blocks-re, fortran-end-block-re) (fortran-start-block-re): New constants, for hideshow. (hs-special-modes-alist): Add a Fortran entry. (fortran-mode-map): Bind fortran-end-of-block, fortran-beginning-of-block to \M-\C-n, \M-\C-p. (fortran-mode): Doc fix. Add fortran-font-lock-keywords-4. (fortran-looking-at-if-then, fortran-end-of-block) (fortran-beginning-of-block): New functions, for hideshow. diff -r 888d43e15dfd -r 9554f19ae068 lisp/progmodes/fortran.el --- a/lisp/progmodes/fortran.el Tue Mar 29 18:34:22 2005 +0000 +++ b/lisp/progmodes/fortran.el Tue Mar 29 18:59:02 2005 +0000 @@ -1,7 +1,7 @@ ;;; fortran.el --- Fortran mode for GNU Emacs -;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 01, 03, 04 -;; Free Software Foundation, Inc. +;; Copyright (C) 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, +;; 2003, 2004, 2005 Free Software Foundation, Inc. ;; Author: Michael D. Prange ;; Maintainer: Glenn Morris @@ -95,7 +95,7 @@ :group 'fortran-indent) (defcustom fortran-if-indent 3 - "*Extra indentation applied to IF blocks." + "*Extra indentation applied to IF, SELECT CASE and WHERE blocks." :type 'integer :group 'fortran-indent) @@ -321,7 +321,8 @@ "while" "inquire" "stop" "return" "include" "open" "close" "read" "write" "format" "print" "select" "case" - "cycle" "exit" "rewind" "backspace") + "cycle" "exit" "rewind" "backspace" + "where" "elsewhere") 'paren) "\\>") ;; Builtin operators. (concat "\\." (regexp-opt @@ -370,6 +371,29 @@ fortran-font-lock-keywords-2))) "Gaudy level highlighting for Fortran mode.") +(defvar fortran-font-lock-keywords-4 + (append fortran-font-lock-keywords-3 + (list (list + (concat "\\<" + (regexp-opt + '("int" "ifix" "idint" "real" "float" "sngl" + "dble" "cmplx" "ichar" "char" "aint" "dint" + "anint" "dnint" "nint" "idnint" "iabs" "abs" + "dabs" "cabs" "mod" "amod" "dmod" "isign" + "sign" "dsign" "idim" "dim" "ddim" "dprod" + "max" "max0" "amax1" "dmax1" "amax0" "max1" + "min0" "amin1" "dmin1" "amin0" "min1" "len" + "index" "lge" "lgt" "lle" "llt" "aimag" + "conjg" "sqrt" "dsqrt" "csqrt" "exp" "dexp" + "cexp" "log" "alog" "dlog" "clog" "log10" + "alog10" "dlog10" "sin" "dsin" "csin" "cos" + "dcos" "ccos" "tan" "dtan" "asin" "dasin" + "acos" "dacos" "atan" "datan" "atan2" "datan2" + "sinh" "dsinh" "cosh" "dcosh" "tanh" "dtanh") + 'paren) "[ \t]*(") '(1 font-lock-builtin-face)))) + "Maximum highlighting for Fortran mode. +Consists of level 3 plus all other intrinsics not already highlighted.") + ;; 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 @@ -409,6 +433,64 @@ "Value for `imenu-generic-expression' in Fortran mode.") +;; Hideshow support. +(defconst fortran-blocks-re + (concat "block[ \t]*data\\|select[ \t]*case\\|" + (regexp-opt '("do" "if" "interface" "function" "map" "program" + "structure" "subroutine" "union" "where"))) + "Regexp potentially indicating the start or end of a Fortran \"block\". +Omits naked END statements, and DO-loops closed by anything other +than ENDDO.") + +(defconst fortran-end-block-re + ;; Do-loops terminated by things other than ENDDO cannot be handled + ;; with a regexp. This omission does not seem to matter to hideshow... + (concat "^[ \t0-9]*\\\\)\\)\\)\\ count 0) + (re-search-forward + (concat "\\(" fortran-blocks-re + (if fortran-check-all-num-for-matching-do + "\\|^[ \t]*[0-9]+" "") + "\\|continue\\|end\\)\\>") + nil 'move)) + (beginning-of-line) + (if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re)) + (fortran-looking-at-if-then) + (looking-at fortran-start-block-re)) + (setq count (1+ count)) + (if (or (looking-at fortran-end-block-re) + (and (or (looking-at "^[0-9 \t]*continue") + (and fortran-check-all-num-for-matching-do + (looking-at "[ \t]*[0-9]+"))) + (fortran-check-for-matching-do))) + (setq count (1- count)))) + (end-of-line)) + (if (> count 0) (error "Missing block end")))) + +(defun fortran-beginning-of-block (&optional num) + "Move point backwards to the start of the current code block. +With optional argument NUM, go backward that many balanced +blocks. If NUM is negative, go forward to the end of a block. +Does not check for consistency of block types. Interactively, +pushes mark before moving point." + (interactive "p") + (if (interactive-p) (push-mark (point) t)) + (and num (< num 0) (fortran-end-of-block (- num))) + (let ((case-fold-search t) + (count (or num 1))) + (beginning-of-line) + (while (and (> count 0) + (re-search-backward + (concat "\\(" fortran-blocks-re + (if fortran-check-all-num-for-matching-do + "\\|^[ \t]*[0-9]+" "") + "\\|continue\\|end\\)\\>") + nil 'move)) + (beginning-of-line) + (if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re)) + (fortran-looking-at-if-then) + (looking-at fortran-start-block-re)) + (setq count (1- count)) + (if (or (looking-at fortran-end-block-re) + (and (or (looking-at "^[0-9 \t]*continue") + (and fortran-check-all-num-for-matching-do + (looking-at "[ \t]*[0-9]+"))) + (fortran-check-for-matching-do))) + (setq count (1+ count))))) + ;; Includes an un-named main program block. + (if (> count 0) (error "Missing block start")))) + (defun fortran-blink-match (regex keyword find-begin) "From a line matching REGEX, blink matching KEYWORD statement line. @@ -1679,8 +1843,9 @@ (1+ (point))))) (if (re-search-forward "\\S\"\\s\"\\S\"" eol t) (backward-char 2)) - ;; If the current string is longer than 72 - 6 chars, - ;; break it at the fill column (else infinite loop). + ;; If the current string is longer than (fill-column + ;; - 6) chars, break it at the fill column (else + ;; infinite loop). (if (> (- (point) start) (- fill-column 6 fortran-continuation-indent)) fcpoint