diff options
| author | Glenn Morris | 2005-03-29 18:59:02 +0000 |
|---|---|---|
| committer | Glenn Morris | 2005-03-29 18:59:02 +0000 |
| commit | 8cb8832f2534c294c670e49b055f1e8bfcb12bf3 (patch) | |
| tree | f8654604d1de4f14444e7255339a69f3a5141963 | |
| parent | fcca5273e598fdf7813dd3adc077bd8c4cc05df5 (diff) | |
| download | emacs-8cb8832f2534c294c670e49b055f1e8bfcb12bf3.tar.gz emacs-8cb8832f2534c294c670e49b055f1e8bfcb12bf3.zip | |
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.
| -rw-r--r-- | lisp/progmodes/fortran.el | 183 |
1 files changed, 174 insertions, 9 deletions
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el index 768012c736c..30e1977d28d 100644 --- a/lisp/progmodes/fortran.el +++ b/lisp/progmodes/fortran.el | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | ;;; fortran.el --- Fortran mode for GNU Emacs | 1 | ;;; fortran.el --- Fortran mode for GNU Emacs |
| 2 | 2 | ||
| 3 | ;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 01, 03, 04 | 3 | ;; Copyright (C) 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, |
| 4 | ;; Free Software Foundation, Inc. | 4 | ;; 2003, 2004, 2005 Free Software Foundation, Inc. |
| 5 | 5 | ||
| 6 | ;; Author: Michael D. Prange <prange@erl.mit.edu> | 6 | ;; Author: Michael D. Prange <prange@erl.mit.edu> |
| 7 | ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> | 7 | ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> |
| @@ -95,7 +95,7 @@ with a character in column 6." | |||
| 95 | :group 'fortran-indent) | 95 | :group 'fortran-indent) |
| 96 | 96 | ||
| 97 | (defcustom fortran-if-indent 3 | 97 | (defcustom fortran-if-indent 3 |
| 98 | "*Extra indentation applied to IF blocks." | 98 | "*Extra indentation applied to IF, SELECT CASE and WHERE blocks." |
| 99 | :type 'integer | 99 | :type 'integer |
| 100 | :group 'fortran-indent) | 100 | :group 'fortran-indent) |
| 101 | 101 | ||
| @@ -321,7 +321,8 @@ program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?" | |||
| 321 | "while" "inquire" "stop" "return" | 321 | "while" "inquire" "stop" "return" |
| 322 | "include" "open" "close" "read" | 322 | "include" "open" "close" "read" |
| 323 | "write" "format" "print" "select" "case" | 323 | "write" "format" "print" "select" "case" |
| 324 | "cycle" "exit" "rewind" "backspace") | 324 | "cycle" "exit" "rewind" "backspace" |
| 325 | "where" "elsewhere") | ||
| 325 | 'paren) "\\>") | 326 | 'paren) "\\>") |
| 326 | ;; Builtin operators. | 327 | ;; Builtin operators. |
| 327 | (concat "\\." (regexp-opt | 328 | (concat "\\." (regexp-opt |
| @@ -370,6 +371,29 @@ program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?" | |||
| 370 | fortran-font-lock-keywords-2))) | 371 | fortran-font-lock-keywords-2))) |
| 371 | "Gaudy level highlighting for Fortran mode.") | 372 | "Gaudy level highlighting for Fortran mode.") |
| 372 | 373 | ||
| 374 | (defvar fortran-font-lock-keywords-4 | ||
| 375 | (append fortran-font-lock-keywords-3 | ||
| 376 | (list (list | ||
| 377 | (concat "\\<" | ||
| 378 | (regexp-opt | ||
| 379 | '("int" "ifix" "idint" "real" "float" "sngl" | ||
| 380 | "dble" "cmplx" "ichar" "char" "aint" "dint" | ||
| 381 | "anint" "dnint" "nint" "idnint" "iabs" "abs" | ||
| 382 | "dabs" "cabs" "mod" "amod" "dmod" "isign" | ||
| 383 | "sign" "dsign" "idim" "dim" "ddim" "dprod" | ||
| 384 | "max" "max0" "amax1" "dmax1" "amax0" "max1" | ||
| 385 | "min0" "amin1" "dmin1" "amin0" "min1" "len" | ||
| 386 | "index" "lge" "lgt" "lle" "llt" "aimag" | ||
| 387 | "conjg" "sqrt" "dsqrt" "csqrt" "exp" "dexp" | ||
| 388 | "cexp" "log" "alog" "dlog" "clog" "log10" | ||
| 389 | "alog10" "dlog10" "sin" "dsin" "csin" "cos" | ||
| 390 | "dcos" "ccos" "tan" "dtan" "asin" "dasin" | ||
| 391 | "acos" "dacos" "atan" "datan" "atan2" "datan2" | ||
| 392 | "sinh" "dsinh" "cosh" "dcosh" "tanh" "dtanh") | ||
| 393 | 'paren) "[ \t]*(") '(1 font-lock-builtin-face)))) | ||
| 394 | "Maximum highlighting for Fortran mode. | ||
| 395 | Consists of level 3 plus all other intrinsics not already highlighted.") | ||
| 396 | |||
| 373 | ;; Comments are real pain in Fortran because there is no way to | 397 | ;; Comments are real pain in Fortran because there is no way to |
| 374 | ;; represent the standard comment syntax in an Emacs syntax table. | 398 | ;; represent the standard comment syntax in an Emacs syntax table. |
| 375 | ;; (We can do so for F90-style). Therefore an unmatched quote in a | 399 | ;; (We can do so for F90-style). Therefore an unmatched quote in a |
| @@ -409,6 +433,64 @@ These get fixed-format comments fontified.") | |||
| 409 | "Value for `imenu-generic-expression' in Fortran mode.") | 433 | "Value for `imenu-generic-expression' in Fortran mode.") |
| 410 | 434 | ||
| 411 | 435 | ||
| 436 | ;; Hideshow support. | ||
| 437 | (defconst fortran-blocks-re | ||
| 438 | (concat "block[ \t]*data\\|select[ \t]*case\\|" | ||
| 439 | (regexp-opt '("do" "if" "interface" "function" "map" "program" | ||
| 440 | "structure" "subroutine" "union" "where"))) | ||
| 441 | "Regexp potentially indicating the start or end of a Fortran \"block\". | ||
| 442 | Omits naked END statements, and DO-loops closed by anything other | ||
| 443 | than ENDDO.") | ||
| 444 | |||
| 445 | (defconst fortran-end-block-re | ||
| 446 | ;; Do-loops terminated by things other than ENDDO cannot be handled | ||
| 447 | ;; with a regexp. This omission does not seem to matter to hideshow... | ||
| 448 | (concat "^[ \t0-9]*\\<end[ \t]*\\(" | ||
| 449 | fortran-blocks-re | ||
| 450 | ;; Naked END statement. | ||
| 451 | "\\|!\\|$\\)") | ||
| 452 | "Regexp matching the end of a Fortran \"block\", from the line start. | ||
| 453 | Note that only ENDDO is handled for the end of a DO-loop. Used | ||
| 454 | in the Fortran entry in `hs-special-modes-alist'.") | ||
| 455 | |||
| 456 | (defconst fortran-start-block-re | ||
| 457 | (concat | ||
| 458 | "^[ \t0-9]*\\(" ; statement number | ||
| 459 | ;; Structure label for DO, IF, SELECT, WHERE. | ||
| 460 | "\\(\\(\\sw+[ \t]*:[ \t]*\\)?" | ||
| 461 | ;; IF blocks are a nuisance: | ||
| 462 | ;; IF ( ... ) foo is not a block, but a single statement. | ||
| 463 | ;; IF ( ... ) THEN can be split over multiple lines. | ||
| 464 | ;; [So can, eg, a DO WHILE (... ), but that is less common, I hope.] | ||
| 465 | ;; The regexp below allows for it to be split over at most 2 lines. | ||
| 466 | ;; That leads to the problem of not matching two consecutive IF | ||
| 467 | ;; statements as one, eg: | ||
| 468 | ;; IF ( ... ) foo | ||
| 469 | ;; IF ( ... ) THEN | ||
| 470 | ;; It simply is not possible to do this in a 100% correct fashion | ||
| 471 | ;; using a regexp - see the functions fortran-end-if, | ||
| 472 | ;; fortran-beginning-if for the hoops we have to go through. | ||
| 473 | ;; An alternative is to match on THEN at a line end, eg: | ||
| 474 | ;; ".*)[ \t]*then[ \t]*\\($\\|!\\)" | ||
| 475 | ;; This would also match ELSE branches, though. This does not seem | ||
| 476 | ;; right to me, because then one has neighbouring blocks that are | ||
| 477 | ;; not nested in each other. | ||
| 478 | "\\(if[ \t]*(\\(.*\\|" | ||
| 479 | ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|" | ||
| 480 | "do\\|select[ \t]*case\\|where\\)\\)\\|" | ||
| 481 | (regexp-opt '("interface" "function" "map" "program" | ||
| 482 | "structure" "subroutine" "union")) | ||
| 483 | "\\|block[ \t]*data\\)[ \t]*") | ||
| 484 | "Regexp matching the start of a Fortran \"block\", from the line start. | ||
| 485 | A simple regexp cannot do this in fully correct fashion, so this | ||
| 486 | tries to strike a compromise between complexity and flexibility. | ||
| 487 | Used in the Fortran entry in `hs-special-modes-alist'.") | ||
| 488 | |||
| 489 | (add-to-list 'hs-special-modes-alist | ||
| 490 | `(fortran-mode ,fortran-start-block-re ,fortran-end-block-re | ||
| 491 | "^[cC*!]" fortran-end-of-block nil)) | ||
| 492 | |||
| 493 | |||
| 412 | (defvar fortran-mode-syntax-table | 494 | (defvar fortran-mode-syntax-table |
| 413 | (let ((table (make-syntax-table))) | 495 | (let ((table (make-syntax-table))) |
| 414 | ;; We might like `;' to be punctuation (g77 multi-statement | 496 | ;; We might like `;' to be punctuation (g77 multi-statement |
| @@ -422,7 +504,8 @@ These get fixed-format comments fontified.") | |||
| 422 | (modify-syntax-entry ?/ "." table) | 504 | (modify-syntax-entry ?/ "." table) |
| 423 | (modify-syntax-entry ?\' "\"" table) | 505 | (modify-syntax-entry ?\' "\"" table) |
| 424 | (modify-syntax-entry ?\" "\"" table) | 506 | (modify-syntax-entry ?\" "\"" table) |
| 425 | ;; Consistent with GNU Fortran -- see the manual. | 507 | ;; Consistent with GNU Fortran's default -- see the manual. |
| 508 | ;; The F77 standard imposes no rule on this issue. | ||
| 426 | (modify-syntax-entry ?\\ "\\" table) | 509 | (modify-syntax-entry ?\\ "\\" table) |
| 427 | ;; This might be better as punctuation, as for C, but this way you | 510 | ;; This might be better as punctuation, as for C, but this way you |
| 428 | ;; can treat floating-point numbers as symbols. | 511 | ;; can treat floating-point numbers as symbols. |
| @@ -446,6 +529,8 @@ These get fixed-format comments fontified.") | |||
| 446 | (define-key map "\C-c;" 'fortran-comment-region) | 529 | (define-key map "\C-c;" 'fortran-comment-region) |
| 447 | (define-key map "\M-;" 'fortran-indent-comment) | 530 | (define-key map "\M-;" 'fortran-indent-comment) |
| 448 | (define-key map "\M-\n" 'fortran-split-line) | 531 | (define-key map "\M-\n" 'fortran-split-line) |
| 532 | (define-key map "\M-\C-n" 'fortran-end-of-block) | ||
| 533 | (define-key map "\M-\C-p" 'fortran-beginning-of-block) | ||
| 449 | (define-key map "\M-\C-q" 'fortran-indent-subprogram) | 534 | (define-key map "\M-\C-q" 'fortran-indent-subprogram) |
| 450 | (define-key map "\C-c\C-w" 'fortran-window-create-momentarily) | 535 | (define-key map "\C-c\C-w" 'fortran-window-create-momentarily) |
| 451 | (define-key map "\C-c\C-r" 'fortran-column-ruler) | 536 | (define-key map "\C-c\C-r" 'fortran-column-ruler) |
| @@ -606,7 +691,7 @@ Key definitions: | |||
| 606 | 691 | ||
| 607 | Variables controlling indentation style and extra features: | 692 | Variables controlling indentation style and extra features: |
| 608 | 693 | ||
| 609 | `comment-start' | 694 | `fortran-comment-line-start' |
| 610 | To use comments starting with `!', set this to the string \"!\". | 695 | To use comments starting with `!', set this to the string \"!\". |
| 611 | `fortran-do-indent' | 696 | `fortran-do-indent' |
| 612 | Extra indentation within DO blocks (default 3). | 697 | Extra indentation within DO blocks (default 3). |
| @@ -696,7 +781,8 @@ with no args, if that value is non-nil." | |||
| 696 | '((fortran-font-lock-keywords | 781 | '((fortran-font-lock-keywords |
| 697 | fortran-font-lock-keywords-1 | 782 | fortran-font-lock-keywords-1 |
| 698 | fortran-font-lock-keywords-2 | 783 | fortran-font-lock-keywords-2 |
| 699 | fortran-font-lock-keywords-3) | 784 | fortran-font-lock-keywords-3 |
| 785 | fortran-font-lock-keywords-4) | ||
| 700 | nil t ((?/ . "$/") ("_$" . "w")) | 786 | nil t ((?/ . "$/") ("_$" . "w")) |
| 701 | fortran-beginning-of-subprogram)) | 787 | fortran-beginning-of-subprogram)) |
| 702 | (set (make-local-variable 'font-lock-syntactic-keywords) | 788 | (set (make-local-variable 'font-lock-syntactic-keywords) |
| @@ -1059,6 +1145,84 @@ Directive lines are treated as comments." | |||
| 1059 | (if (not not-last-statement) | 1145 | (if (not not-last-statement) |
| 1060 | 'last-statement))) | 1146 | 'last-statement))) |
| 1061 | 1147 | ||
| 1148 | (defun fortran-looking-at-if-then () | ||
| 1149 | "Return non-nil if at the start of a line with an IF ... THEN statement." | ||
| 1150 | ;; cf f90-looking-at-if-then. | ||
| 1151 | (let ((p (point)) | ||
| 1152 | (i (fortran-beginning-if))) | ||
| 1153 | (if i | ||
| 1154 | (save-excursion | ||
| 1155 | (goto-char i) | ||
| 1156 | (beginning-of-line) | ||
| 1157 | (= (point) p))))) | ||
| 1158 | |||
| 1159 | ;; Used in hs-special-modes-alist. | ||
| 1160 | (defun fortran-end-of-block (&optional num) | ||
| 1161 | "Move point forward to the end of the current code block. | ||
| 1162 | With optional argument NUM, go forward that many balanced blocks. | ||
| 1163 | If NUM is negative, go backward to the start of a block. Does | ||
| 1164 | not check for consistency of block types. Interactively, pushes | ||
| 1165 | mark before moving point." | ||
| 1166 | (interactive "p") | ||
| 1167 | (if (interactive-p) (push-mark (point) t)) | ||
| 1168 | (and num (< num 0) (fortran-beginning-of-block (- num))) | ||
| 1169 | (let ((case-fold-search t) | ||
| 1170 | (count (or num 1))) | ||
| 1171 | (end-of-line) | ||
| 1172 | (while (and (> count 0) | ||
| 1173 | (re-search-forward | ||
| 1174 | (concat "\\(" fortran-blocks-re | ||
| 1175 | (if fortran-check-all-num-for-matching-do | ||
| 1176 | "\\|^[ \t]*[0-9]+" "") | ||
| 1177 | "\\|continue\\|end\\)\\>") | ||
| 1178 | nil 'move)) | ||
| 1179 | (beginning-of-line) | ||
| 1180 | (if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re)) | ||
| 1181 | (fortran-looking-at-if-then) | ||
| 1182 | (looking-at fortran-start-block-re)) | ||
| 1183 | (setq count (1+ count)) | ||
| 1184 | (if (or (looking-at fortran-end-block-re) | ||
| 1185 | (and (or (looking-at "^[0-9 \t]*continue") | ||
| 1186 | (and fortran-check-all-num-for-matching-do | ||
| 1187 | (looking-at "[ \t]*[0-9]+"))) | ||
| 1188 | (fortran-check-for-matching-do))) | ||
| 1189 | (setq count (1- count)))) | ||
| 1190 | (end-of-line)) | ||
| 1191 | (if (> count 0) (error "Missing block end")))) | ||
| 1192 | |||
| 1193 | (defun fortran-beginning-of-block (&optional num) | ||
| 1194 | "Move point backwards to the start of the current code block. | ||
| 1195 | With optional argument NUM, go backward that many balanced | ||
| 1196 | blocks. If NUM is negative, go forward to the end of a block. | ||
| 1197 | Does not check for consistency of block types. Interactively, | ||
| 1198 | pushes mark before moving point." | ||
| 1199 | (interactive "p") | ||
| 1200 | (if (interactive-p) (push-mark (point) t)) | ||
| 1201 | (and num (< num 0) (fortran-end-of-block (- num))) | ||
| 1202 | (let ((case-fold-search t) | ||
| 1203 | (count (or num 1))) | ||
| 1204 | (beginning-of-line) | ||
| 1205 | (while (and (> count 0) | ||
| 1206 | (re-search-backward | ||
| 1207 | (concat "\\(" fortran-blocks-re | ||
| 1208 | (if fortran-check-all-num-for-matching-do | ||
| 1209 | "\\|^[ \t]*[0-9]+" "") | ||
| 1210 | "\\|continue\\|end\\)\\>") | ||
| 1211 | nil 'move)) | ||
| 1212 | (beginning-of-line) | ||
| 1213 | (if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re)) | ||
| 1214 | (fortran-looking-at-if-then) | ||
| 1215 | (looking-at fortran-start-block-re)) | ||
| 1216 | (setq count (1- count)) | ||
| 1217 | (if (or (looking-at fortran-end-block-re) | ||
| 1218 | (and (or (looking-at "^[0-9 \t]*continue") | ||
| 1219 | (and fortran-check-all-num-for-matching-do | ||
| 1220 | (looking-at "[ \t]*[0-9]+"))) | ||
| 1221 | (fortran-check-for-matching-do))) | ||
| 1222 | (setq count (1+ count))))) | ||
| 1223 | ;; Includes an un-named main program block. | ||
| 1224 | (if (> count 0) (error "Missing block start")))) | ||
| 1225 | |||
| 1062 | 1226 | ||
| 1063 | (defun fortran-blink-match (regex keyword find-begin) | 1227 | (defun fortran-blink-match (regex keyword find-begin) |
| 1064 | "From a line matching REGEX, blink matching KEYWORD statement line. | 1228 | "From a line matching REGEX, blink matching KEYWORD statement line. |
| @@ -1679,8 +1843,9 @@ If ALL is nil, only match comments that start in column > 0." | |||
| 1679 | (1+ (point))))) | 1843 | (1+ (point))))) |
| 1680 | (if (re-search-forward "\\S\"\\s\"\\S\"" eol t) | 1844 | (if (re-search-forward "\\S\"\\s\"\\S\"" eol t) |
| 1681 | (backward-char 2)) | 1845 | (backward-char 2)) |
| 1682 | ;; If the current string is longer than 72 - 6 chars, | 1846 | ;; If the current string is longer than (fill-column |
| 1683 | ;; break it at the fill column (else infinite loop). | 1847 | ;; - 6) chars, break it at the fill column (else |
| 1848 | ;; infinite loop). | ||
| 1684 | (if (> (- (point) start) | 1849 | (if (> (- (point) start) |
| 1685 | (- fill-column 6 fortran-continuation-indent)) | 1850 | (- fill-column 6 fortran-continuation-indent)) |
| 1686 | fcpoint | 1851 | fcpoint |