|
|
1.1 ! root 1: ;;; Fortran mode for GNU Emacs (beta test version 1.21, Oct. 1, 1985) ! 2: ;;; Copyright (c) 1986 Free Software Foundation, Inc. ! 3: ;;; Written by Michael D. Prange ([email protected]) ! 4: ! 5: ;; This file is part of GNU Emacs. ! 6: ! 7: ;; GNU Emacs is free software; you can redistribute it and/or modify ! 8: ;; it under the terms of the GNU General Public License as published by ! 9: ;; the Free Software Foundation; either version 1, or (at your option) ! 10: ;; any later version. ! 11: ! 12: ;; GNU Emacs is distributed in the hope that it will be useful, ! 13: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: ;; GNU General Public License for more details. ! 16: ! 17: ;; You should have received a copy of the GNU General Public License ! 18: ;; along with GNU Emacs; see the file COPYING. If not, write to ! 19: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 20: ! 21: ;;; Author acknowledges help from Stephen Gildea <[email protected]> ! 22: ! 23: ;;; Bugs to [email protected]. ! 24: ! 25: (defvar fortran-do-indent 3 ! 26: "*Extra indentation applied to `do' blocks.") ! 27: ! 28: (defvar fortran-if-indent 3 ! 29: "*Extra indentation applied to `if' blocks.") ! 30: ! 31: (defvar fortran-continuation-indent 5 ! 32: "*Extra indentation applied to `continuation' lines.") ! 33: ! 34: (defvar fortran-comment-indent-style 'fixed ! 35: "*nil forces comment lines not to be touched, ! 36: 'fixed produces fixed comment indentation to comment-column, ! 37: and 'relative indents to current fortran indentation plus comment-column.") ! 38: ! 39: (defvar fortran-comment-line-column 6 ! 40: "*Indentation for text in comment lines.") ! 41: ! 42: (defvar comment-line-start nil ! 43: "*Delimiter inserted to start new full-line comment.") ! 44: ! 45: (defvar comment-line-start-skip nil ! 46: "*Regexp to match the start of a full-line comment.") ! 47: ! 48: (defvar fortran-minimum-statement-indent 6 ! 49: "*Minimum indentation for fortran statements.") ! 50: ! 51: ;; Note that this is documented in the v18 manuals as being a string ! 52: ;; of length one rather than a single character. ! 53: ;; The code in this file accepts either format for compatibility. ! 54: (defvar fortran-comment-indent-char ? ! 55: "*Character to be inserted for Fortran comment indentation. ! 56: Normally a space.") ! 57: ! 58: (defvar fortran-line-number-indent 1 ! 59: "*Maximum indentation for Fortran line numbers. ! 60: 5 means right-justify them within their five-column field.") ! 61: ! 62: (defvar fortran-check-all-num-for-matching-do nil ! 63: "*Non-nil causes all numbered lines to be treated as possible do-loop ends.") ! 64: ! 65: (defvar fortran-continuation-char ?$ ! 66: "*Character which is inserted in column 5 by \\[fortran-split-line] ! 67: to begin a continuation line. Normally $.") ! 68: ! 69: (defvar fortran-comment-region "c$$$" ! 70: "*String inserted by \\[fortran-comment-region] at start of each line in region.") ! 71: ! 72: (defvar fortran-electric-line-number t ! 73: "*Non-nil causes line number digits to be moved to the correct column as typed.") ! 74: ! 75: (defvar fortran-startup-message t ! 76: "*Non-nil displays a startup message when fortran-mode is first called.") ! 77: ! 78: (defvar fortran-column-ruler ! 79: (concat "0 4 6 10 20 30 40 50 60 70\n" ! 80: "[ ]|{ | | | | | | | | | | | | |}\n") ! 81: "*String displayed above current line by \\[fortran-column-ruler].") ! 82: ! 83: (defconst fortran-mode-version "1.21") ! 84: ! 85: (defvar fortran-mode-syntax-table nil ! 86: "Syntax table in use in fortran-mode buffers.") ! 87: ! 88: (if fortran-mode-syntax-table ! 89: () ! 90: (setq fortran-mode-syntax-table (make-syntax-table)) ! 91: (modify-syntax-entry ?\; "w" fortran-mode-syntax-table) ! 92: (modify-syntax-entry ?+ "." fortran-mode-syntax-table) ! 93: (modify-syntax-entry ?- "." fortran-mode-syntax-table) ! 94: (modify-syntax-entry ?* "." fortran-mode-syntax-table) ! 95: (modify-syntax-entry ?/ "." fortran-mode-syntax-table) ! 96: (modify-syntax-entry ?\' "\"" fortran-mode-syntax-table) ! 97: (modify-syntax-entry ?\" "\"" fortran-mode-syntax-table) ! 98: (modify-syntax-entry ?\\ "/" fortran-mode-syntax-table) ! 99: (modify-syntax-entry ?. "w" fortran-mode-syntax-table) ! 100: (modify-syntax-entry ?\n ">" fortran-mode-syntax-table)) ! 101: ! 102: (defvar fortran-mode-map () ! 103: "Keymap used in fortran mode.") ! 104: ! 105: (if fortran-mode-map ! 106: () ! 107: (setq fortran-mode-map (make-sparse-keymap)) ! 108: (define-key fortran-mode-map ";" 'fortran-abbrev-start) ! 109: (define-key fortran-mode-map "\C-c;" 'fortran-comment-region) ! 110: (define-key fortran-mode-map "\e\C-a" 'beginning-of-fortran-subprogram) ! 111: (define-key fortran-mode-map "\e\C-e" 'end-of-fortran-subprogram) ! 112: (define-key fortran-mode-map "\e;" 'fortran-indent-comment) ! 113: (define-key fortran-mode-map "\e\C-h" 'mark-fortran-subprogram) ! 114: (define-key fortran-mode-map "\e\n" 'fortran-split-line) ! 115: (define-key fortran-mode-map "\e\C-q" 'fortran-indent-subprogram) ! 116: (define-key fortran-mode-map "\C-c\C-w" 'fortran-window-create) ! 117: (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler) ! 118: (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement) ! 119: (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement) ! 120: (define-key fortran-mode-map "\t" 'fortran-indent-line) ! 121: (define-key fortran-mode-map "0" 'fortran-electric-line-number) ! 122: (define-key fortran-mode-map "1" 'fortran-electric-line-number) ! 123: (define-key fortran-mode-map "2" 'fortran-electric-line-number) ! 124: (define-key fortran-mode-map "3" 'fortran-electric-line-number) ! 125: (define-key fortran-mode-map "4" 'fortran-electric-line-number) ! 126: (define-key fortran-mode-map "5" 'fortran-electric-line-number) ! 127: (define-key fortran-mode-map "6" 'fortran-electric-line-number) ! 128: (define-key fortran-mode-map "7" 'fortran-electric-line-number) ! 129: (define-key fortran-mode-map "8" 'fortran-electric-line-number) ! 130: (define-key fortran-mode-map "9" 'fortran-electric-line-number)) ! 131: ! 132: (defvar fortran-mode-abbrev-table nil) ! 133: (if fortran-mode-abbrev-table ! 134: () ! 135: (define-abbrev-table 'fortran-mode-abbrev-table ()) ! 136: (let ((abbrevs-changed nil)) ! 137: (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil) ! 138: (define-abbrev fortran-mode-abbrev-table ";ch" "character" nil) ! 139: (define-abbrev fortran-mode-abbrev-table ";cl" "close" nil) ! 140: (define-abbrev fortran-mode-abbrev-table ";c" "continue" nil) ! 141: (define-abbrev fortran-mode-abbrev-table ";cm" "common" nil) ! 142: (define-abbrev fortran-mode-abbrev-table ";cx" "complex" nil) ! 143: (define-abbrev fortran-mode-abbrev-table ";di" "dimension" nil) ! 144: (define-abbrev fortran-mode-abbrev-table ";do" "double" nil) ! 145: (define-abbrev fortran-mode-abbrev-table ";dc" "double complex" nil) ! 146: (define-abbrev fortran-mode-abbrev-table ";dp" "double precision" nil) ! 147: (define-abbrev fortran-mode-abbrev-table ";dw" "do while" nil) ! 148: (define-abbrev fortran-mode-abbrev-table ";e" "else" nil) ! 149: (define-abbrev fortran-mode-abbrev-table ";ed" "enddo" nil) ! 150: (define-abbrev fortran-mode-abbrev-table ";el" "elseif" nil) ! 151: (define-abbrev fortran-mode-abbrev-table ";en" "endif" nil) ! 152: (define-abbrev fortran-mode-abbrev-table ";eq" "equivalence" nil) ! 153: (define-abbrev fortran-mode-abbrev-table ";ex" "external" nil) ! 154: (define-abbrev fortran-mode-abbrev-table ";ey" "entry" nil) ! 155: (define-abbrev fortran-mode-abbrev-table ";f" "format" nil) ! 156: (define-abbrev fortran-mode-abbrev-table ";fu" "function" nil) ! 157: (define-abbrev fortran-mode-abbrev-table ";g" "goto" nil) ! 158: (define-abbrev fortran-mode-abbrev-table ";im" "implicit" nil) ! 159: (define-abbrev fortran-mode-abbrev-table ";ib" "implicit byte" nil) ! 160: (define-abbrev fortran-mode-abbrev-table ";ic" "implicit complex" nil) ! 161: (define-abbrev fortran-mode-abbrev-table ";ich" "implicit character" nil) ! 162: (define-abbrev fortran-mode-abbrev-table ";ii" "implicit integer" nil) ! 163: (define-abbrev fortran-mode-abbrev-table ";il" "implicit logical" nil) ! 164: (define-abbrev fortran-mode-abbrev-table ";ir" "implicit real" nil) ! 165: (define-abbrev fortran-mode-abbrev-table ";inc" "include" nil) ! 166: (define-abbrev fortran-mode-abbrev-table ";in" "integer" nil) ! 167: (define-abbrev fortran-mode-abbrev-table ";intr" "intrinsic" nil) ! 168: (define-abbrev fortran-mode-abbrev-table ";l" "logical" nil) ! 169: (define-abbrev fortran-mode-abbrev-table ";op" "open" nil) ! 170: (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil) ! 171: (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil) ! 172: (define-abbrev fortran-mode-abbrev-table ";p" "print" nil) ! 173: (define-abbrev fortran-mode-abbrev-table ";re" "real" nil) ! 174: (define-abbrev fortran-mode-abbrev-table ";r" "read" nil) ! 175: (define-abbrev fortran-mode-abbrev-table ";rt" "return" nil) ! 176: (define-abbrev fortran-mode-abbrev-table ";rw" "rewind" nil) ! 177: (define-abbrev fortran-mode-abbrev-table ";s" "stop" nil) ! 178: (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil) ! 179: (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil) ! 180: (define-abbrev fortran-mode-abbrev-table ";w" "write" nil))) ! 181: ! 182: (defun fortran-mode () ! 183: "Major mode for editing fortran code. ! 184: Tab indents the current fortran line correctly. ! 185: `do' statements must not share a common `continue'. ! 186: ! 187: Type `;?' or `;\\[help-command]' to display a list of built-in abbrevs for Fortran keywords. ! 188: ! 189: Variables controlling indentation style and extra features: ! 190: ! 191: comment-start ! 192: Normally nil in Fortran mode. If you want to use comments ! 193: starting with `!', set this to the string \"!\". ! 194: fortran-do-indent ! 195: Extra indentation within do blocks. (default 3) ! 196: fortran-if-indent ! 197: Extra indentation within if blocks. (default 3) ! 198: fortran-continuation-indent ! 199: Extra indentation appled to continuation statements. (default 5) ! 200: fortran-comment-line-column ! 201: Amount of indentation for text within full-line comments. (default 6) ! 202: fortran-comment-indent-style ! 203: nil means don't change indentation of text in full-line comments, ! 204: fixed means indent that text at column fortran-comment-line-column ! 205: relative means indent at fortran-comment-line-column beyond the ! 206: indentation for a line of code. ! 207: Default value is fixed. ! 208: fortran-comment-indent-char ! 209: Character to be inserted instead of space for full-line comment ! 210: indentation. (default is a space) ! 211: fortran-minimum-statement-indent ! 212: Minimum indentation for fortran statements. (default 6) ! 213: fortran-line-number-indent ! 214: Maximum indentation for line numbers. A line number will get ! 215: less than this much indentation if necessary to avoid reaching ! 216: column 5. (default 1) ! 217: fortran-check-all-num-for-matching-do ! 218: Non-nil causes all numbered lines to be treated as possible 'continue' ! 219: statements. (default nil) ! 220: fortran-continuation-char ! 221: character to be inserted in column 5 of a continuation line. ! 222: (default $) ! 223: fortran-comment-region ! 224: String inserted by \\[fortran-comment-region] at start of each line in ! 225: region. (default \"c$$$\") ! 226: fortran-electric-line-number ! 227: Non-nil causes line number digits to be moved to the correct column ! 228: as typed. (default t) ! 229: fortran-startup-message ! 230: Set to nil to inhibit message first time fortran-mode is used. ! 231: ! 232: Turning on Fortran mode calls the value of the variable fortran-mode-hook ! 233: with no args, if that value is non-nil. ! 234: \\{fortran-mode-map}" ! 235: (interactive) ! 236: (kill-all-local-variables) ! 237: (if fortran-startup-message ! 238: (message "Emacs Fortran mode version %s. Bugs to [email protected]" fortran-mode-version)) ! 239: (setq fortran-startup-message nil) ! 240: (setq local-abbrev-table fortran-mode-abbrev-table) ! 241: (set-syntax-table fortran-mode-syntax-table) ! 242: (make-local-variable 'indent-line-function) ! 243: (setq indent-line-function 'fortran-indent-line) ! 244: (make-local-variable 'comment-indent-hook) ! 245: (setq comment-indent-hook 'fortran-comment-hook) ! 246: (make-local-variable 'comment-line-start-skip) ! 247: (setq comment-line-start-skip "^[Cc*][^ \t\n]*[ \t]*") ;[^ \t\n]* handles comment strings such as c$$$ ! 248: (make-local-variable 'comment-line-start) ! 249: (setq comment-line-start "c") ! 250: (make-local-variable 'comment-start-skip) ! 251: (setq comment-start-skip "![ \t]*") ! 252: (make-local-variable 'comment-start) ! 253: (setq comment-start nil) ! 254: (make-local-variable 'require-final-newline) ! 255: (setq require-final-newline t) ! 256: (make-local-variable 'abbrev-all-caps) ! 257: (setq abbrev-all-caps t) ! 258: (make-local-variable 'indent-tabs-mode) ! 259: (setq indent-tabs-mode nil) ! 260: (use-local-map fortran-mode-map) ! 261: (setq mode-name "Fortran") ! 262: (setq major-mode 'fortran-mode) ! 263: (run-hooks 'fortran-mode-hook)) ! 264: ! 265: (defun fortran-comment-hook () ! 266: (save-excursion ! 267: (skip-chars-backward " \t") ! 268: (max (+ 1 (current-column)) ! 269: comment-column))) ! 270: ! 271: (defun fortran-indent-comment () ! 272: "Align or create comment on current line. ! 273: Existing comments of all types are recognized and aligned. ! 274: If the line has no comment, a side-by-side comment is inserted and aligned ! 275: if the value of comment-start is not nil. ! 276: Otherwise, a separate-line comment is inserted, on this line ! 277: or on a new line inserted before this line if this line is not blank." ! 278: (interactive) ! 279: (beginning-of-line) ! 280: ;; Recognize existing comments of either kind. ! 281: (cond ((looking-at comment-line-start-skip) ! 282: (fortran-indent-line)) ! 283: ((re-search-forward comment-start-skip ! 284: (save-excursion (end-of-line) (point)) t) ! 285: (indent-for-comment)) ! 286: ;; No existing comment. ! 287: ;; If side-by-side comments are defined, insert one, ! 288: ;; unless line is now blank. ! 289: ((and comment-start (not (looking-at "^[ \t]*$"))) ! 290: (end-of-line) ! 291: (delete-horizontal-space) ! 292: (indent-to (fortran-comment-hook)) ! 293: (insert comment-start)) ! 294: ;; Else insert separate-line comment, making a new line if nec. ! 295: (t ! 296: (if (looking-at "^[ \t]*$") ! 297: (delete-horizontal-space) ! 298: (beginning-of-line) ! 299: (insert "\n") ! 300: (forward-char -1)) ! 301: (insert comment-line-start) ! 302: (insert-char (if (stringp fortran-comment-indent-char) ! 303: (aref fortran-comment-indent-char 0) ! 304: fortran-comment-indent-char) ! 305: (- (calculate-fortran-indent) (current-column)))))) ! 306: ! 307: (defun fortran-comment-region (beg-region end-region arg) ! 308: "Comments every line in the region. ! 309: Puts fortran-comment-region at the beginning of every line in the region. ! 310: BEG-REGION and END-REGION are args which specify the region boundaries. ! 311: With non-nil ARG, uncomments the region." ! 312: (interactive "*r\nP") ! 313: (let ((end-region-mark (make-marker)) (save-point (point-marker))) ! 314: (set-marker end-region-mark end-region) ! 315: (goto-char beg-region) ! 316: (beginning-of-line) ! 317: (if (not arg) ;comment the region ! 318: (progn (insert fortran-comment-region) ! 319: (while (and (= (forward-line 1) 0) ! 320: (< (point) end-region-mark)) ! 321: (insert fortran-comment-region))) ! 322: (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region ! 323: (if (looking-at com) ! 324: (delete-region (point) (match-end 0))) ! 325: (while (and (= (forward-line 1) 0) ! 326: (< (point) end-region-mark)) ! 327: (if (looking-at com) ! 328: (delete-region (point) (match-end 0)))))) ! 329: (goto-char save-point) ! 330: (set-marker end-region-mark nil) ! 331: (set-marker save-point nil))) ! 332: ! 333: (defun fortran-abbrev-start () ! 334: "Typing \";\\[help-command]\" or \";?\" lists all the fortran abbrevs. ! 335: Any other key combination is executed normally." ;\\[help-command] is just a way to print the value of the variable help-char. ! 336: (interactive) ! 337: (let (c) ! 338: (insert last-command-char) ! 339: (if (or (= (setq c (read-char)) ??) ;insert char if not equal to `?' ! 340: (= c help-char)) ! 341: (fortran-abbrev-help) ! 342: (setq unread-command-char c)))) ! 343: ! 344: (defun fortran-abbrev-help () ! 345: "List the currently defined abbrevs in Fortran mode." ! 346: (interactive) ! 347: (message "Listing abbrev table...") ! 348: (require 'abbrevlist) ! 349: (list-one-abbrev-table fortran-mode-abbrev-table "*Help*") ! 350: (message "Listing abbrev table...done")) ! 351: ! 352: (defun fortran-column-ruler () ! 353: "Inserts a column ruler momentarily above current line, till next keystroke. ! 354: The ruler is defined by the value of fortran-column-ruler. ! 355: The key typed is executed unless it is SPC." ! 356: (interactive) ! 357: (momentary-string-display ! 358: fortran-column-ruler (save-excursion (beginning-of-line) (point)) ! 359: nil "Type SPC or any command to erase ruler.")) ! 360: ! 361: (defun fortran-window-create () ! 362: "Makes the window 72 columns wide." ! 363: (interactive) ! 364: (let ((window-min-width 2)) ! 365: (split-window-horizontally 73)) ! 366: (other-window 1) ! 367: (switch-to-buffer " fortran-window-extra" t) ! 368: (select-window (previous-window))) ! 369: ! 370: (defun fortran-split-line () ! 371: "Break line at point and insert continuation marker and alignment." ! 372: (interactive) ! 373: (delete-horizontal-space) ! 374: (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip)) ! 375: (insert "\n" comment-line-start " ") ! 376: (insert "\n " fortran-continuation-char)) ! 377: (fortran-indent-line)) ! 378: ! 379: (defun delete-horizontal-regexp (chars) ! 380: "Delete all characters in CHARS around point. ! 381: CHARS is like the inside of a [...] in a regular expression ! 382: except that ] is never special and \ quotes ^, - or \." ! 383: (interactive "*s") ! 384: (skip-chars-backward chars) ! 385: (delete-region (point) (progn (skip-chars-forward chars) (point)))) ! 386: ! 387: (defun fortran-electric-line-number (arg) ! 388: "Self insert, but if part of a Fortran line number indent it automatically. ! 389: Auto-indent does not happen if a numeric arg is used." ! 390: (interactive "P") ! 391: (if (or arg (not fortran-electric-line-number)) ! 392: (self-insert-command arg) ! 393: (if (or (save-excursion (re-search-backward "[^ \t0-9]" ! 394: (save-excursion ! 395: (beginning-of-line) ! 396: (point)) ! 397: t)) ;not a line number ! 398: (looking-at "[0-9]")) ;within a line number ! 399: (insert last-command-char) ! 400: (skip-chars-backward " \t") ! 401: (insert last-command-char) ! 402: (fortran-indent-line)))) ! 403: ! 404: (defun beginning-of-fortran-subprogram () ! 405: "Moves point to the beginning of the current fortran subprogram." ! 406: (interactive) ! 407: (let ((case-fold-search t)) ! 408: (beginning-of-line -1) ! 409: (re-search-backward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) ! 410: (if (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]") ! 411: (forward-line 1)))) ! 412: ! 413: (defun end-of-fortran-subprogram () ! 414: "Moves point to the end of the current fortran subprogram." ! 415: (interactive) ! 416: (let ((case-fold-search t)) ! 417: (beginning-of-line 2) ! 418: (re-search-forward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) ! 419: (goto-char (match-beginning 0)) ! 420: (forward-line 1))) ! 421: ! 422: (defun mark-fortran-subprogram () ! 423: "Put mark at end of fortran subprogram, point at beginning. ! 424: The marks are pushed." ! 425: (interactive) ! 426: (end-of-fortran-subprogram) ! 427: (push-mark (point)) ! 428: (beginning-of-fortran-subprogram)) ! 429: ! 430: (defun fortran-previous-statement () ! 431: "Moves point to beginning of the previous fortran statement. ! 432: Returns 'first-statement if that statement is the first ! 433: non-comment Fortran statement in the file, and nil otherwise." ! 434: (interactive) ! 435: (let (not-first-statement continue-test) ! 436: (beginning-of-line) ! 437: (setq continue-test ! 438: (or (looking-at ! 439: (concat "[ \t]*" (regexp-quote (char-to-string ! 440: fortran-continuation-char)))) ! 441: (looking-at " [^ 0\n]"))) ! 442: (while (and (setq not-first-statement (= (forward-line -1) 0)) ! 443: (or (looking-at comment-line-start-skip) ! 444: (looking-at "[ \t]*$") ! 445: (looking-at " [^ 0\n]") ! 446: (looking-at (concat "[ \t]*" comment-start-skip))))) ! 447: (cond ((and continue-test ! 448: (not not-first-statement)) ! 449: (message "Incomplete continuation statement.")) ! 450: (continue-test ! 451: (fortran-previous-statement)) ! 452: ((not not-first-statement) ! 453: 'first-statement)))) ! 454: ! 455: (defun fortran-next-statement () ! 456: "Moves point to beginning of the next fortran statement. ! 457: Returns 'last-statement if that statement is the last ! 458: non-comment Fortran statement in the file, and nil otherwise." ! 459: (interactive) ! 460: (let (not-last-statement) ! 461: (beginning-of-line) ! 462: (while (and (setq not-last-statement (= (forward-line 1) 0)) ! 463: (or (looking-at comment-line-start-skip) ! 464: (looking-at "[ \t]*$") ! 465: (looking-at " [^ 0\n]") ! 466: (looking-at (concat "[ \t]*" comment-start-skip))))) ! 467: (if (not not-last-statement) ! 468: 'last-statement))) ! 469: ! 470: (defun fortran-indent-line () ! 471: "Indents current fortran line based on its contents and on previous lines." ! 472: (interactive) ! 473: (let ((cfi (calculate-fortran-indent))) ! 474: (save-excursion ! 475: (beginning-of-line) ! 476: (if (or (not (= cfi (fortran-current-line-indentation))) ! 477: (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t) ! 478: (not (fortran-line-number-indented-correctly-p)))) ! 479: (fortran-indent-to-column cfi) ! 480: (beginning-of-line) ! 481: (if (re-search-forward comment-start-skip ! 482: (save-excursion (end-of-line) (point)) 'move) ! 483: (fortran-indent-comment)))) ! 484: ;; Never leave point in left margin. ! 485: (if (< (current-column) cfi) ! 486: (move-to-column cfi)))) ! 487: ! 488: (defun fortran-indent-subprogram () ! 489: "Properly indents the Fortran subprogram which contains point." ! 490: (interactive) ! 491: (save-excursion ! 492: (mark-fortran-subprogram) ! 493: (message "Indenting subprogram...") ! 494: (indent-region (point) (mark) nil)) ! 495: (message "Indenting subprogram...done.")) ! 496: ! 497: (defun calculate-fortran-indent () ! 498: "Calculates the fortran indent column based on previous lines." ! 499: (let (icol first-statement (case-fold-search t)) ! 500: (save-excursion ! 501: (setq first-statement (fortran-previous-statement)) ! 502: (if first-statement ! 503: (setq icol fortran-minimum-statement-indent) ! 504: (progn ! 505: (if (= (point) (point-min)) ! 506: (setq icol fortran-minimum-statement-indent) ! 507: (setq icol (fortran-current-line-indentation))) ! 508: (skip-chars-forward " \t0-9") ! 509: (cond ((looking-at "if[ \t]*(") ! 510: (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") ! 511: (let (then-test) ;multi-line if-then ! 512: (while (and (= (forward-line 1) 0) ;search forward for then ! 513: (looking-at " [^ 0]") ! 514: (not (setq then-test (looking-at ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) ! 515: then-test)) ! 516: (setq icol (+ icol fortran-if-indent)))) ! 517: ((looking-at "\\(else\\|elseif\\)\\b") ! 518: (setq icol (+ icol fortran-if-indent))) ! 519: ((looking-at "do\\b") ! 520: (setq icol (+ icol fortran-do-indent))))))) ! 521: (save-excursion ! 522: (beginning-of-line) ! 523: (cond ((looking-at "[ \t]*$")) ! 524: ((looking-at comment-line-start-skip) ! 525: (cond ((eq fortran-comment-indent-style 'relative) ! 526: (setq icol (+ icol fortran-comment-line-column))) ! 527: ((eq fortran-comment-indent-style 'fixed) ! 528: (setq icol fortran-comment-line-column)))) ! 529: ((or (looking-at (concat "[ \t]*" ! 530: (regexp-quote (char-to-string fortran-continuation-char)))) ! 531: (looking-at " [^ 0\n]")) ! 532: (setq icol (+ icol fortran-continuation-indent))) ! 533: (first-statement) ! 534: ((and fortran-check-all-num-for-matching-do ! 535: (looking-at "[ \t]*[0-9]+") ! 536: (fortran-check-for-matching-do)) ! 537: (setq icol (- icol fortran-do-indent))) ! 538: (t ! 539: (skip-chars-forward " \t0-9") ! 540: (cond ((looking-at "end[ \t]*if\\b") ! 541: (setq icol (- icol fortran-if-indent))) ! 542: ((looking-at "\\(else\\|elseif\\)\\b") ! 543: (setq icol (- icol fortran-if-indent))) ! 544: ((and (looking-at "continue\\b") ! 545: (fortran-check-for-matching-do)) ! 546: (setq icol (- icol fortran-do-indent))) ! 547: ((looking-at "end[ \t]*do\\b") ! 548: (setq icol (- icol fortran-do-indent))) ! 549: ((and (looking-at "end\\b[ \t]*[^ \t=(a-z]") ! 550: (not (= icol fortran-minimum-statement-indent))) ! 551: (message "Warning: `end' not in column %d. Probably an unclosed block." fortran-minimum-statement-indent)))))) ! 552: (max fortran-minimum-statement-indent icol))) ! 553: ! 554: (defun fortran-current-line-indentation () ! 555: "Indentation of current line, ignoring Fortran line number or continuation. ! 556: This is the column position of the first non-whitespace character ! 557: aside from the line number and/or column 5 line-continuation character. ! 558: For comment lines, returns indentation of the first ! 559: non-indentation text within the comment." ! 560: (save-excursion ! 561: (beginning-of-line) ! 562: (cond ((looking-at comment-line-start-skip) ! 563: (goto-char (match-end 0)) ! 564: (skip-chars-forward ! 565: (if (stringp fortran-comment-indent-char) ! 566: fortran-comment-indent-char ! 567: (char-to-string fortran-comment-indent-char)))) ! 568: ((looking-at " [^ 0\n]") ! 569: (goto-char (match-end 0))) ! 570: (t ! 571: ;; Move past line number. ! 572: (move-to-column 5))) ! 573: ;; Move past whitespace. ! 574: (skip-chars-forward " \t") ! 575: (current-column))) ! 576: ! 577: (defun fortran-indent-to-column (col) ! 578: "Indents current line with spaces to column COL. ! 579: notes: 1) A non-zero/non-blank character in column 5 indicates a continuation ! 580: line, and this continuation character is retained on indentation; ! 581: 2) If fortran-continuation-char is the first non-whitespace character, ! 582: this is a continuation line; ! 583: 3) A non-continuation line which has a number as the first ! 584: non-whitespace character is a numbered line." ! 585: (save-excursion ! 586: (beginning-of-line) ! 587: (if (looking-at comment-line-start-skip) ! 588: (if fortran-comment-indent-style ! 589: (let ((char (if (stringp fortran-comment-indent-char) ! 590: (aref fortran-comment-indent-char 0) ! 591: fortran-comment-indent-char))) ! 592: (goto-char (match-end 0)) ! 593: (delete-horizontal-regexp (concat " \t" (char-to-string char))) ! 594: (insert-char char (- col (current-column))))) ! 595: (if (looking-at " [^ 0\n]") ! 596: (forward-char 6) ! 597: (delete-horizontal-space) ! 598: ;; Put line number in columns 0-4 ! 599: ;; or put continuation character in column 5. ! 600: (cond ((eobp)) ! 601: ((= (following-char) fortran-continuation-char) ! 602: (indent-to 5) ! 603: (forward-char 1)) ! 604: ((looking-at "[0-9]+") ! 605: (let ((extra-space (- 5 (- (match-end 0) (point))))) ! 606: (if (< extra-space 0) ! 607: (message "Warning: line number exceeds 5-digit limit.") ! 608: (indent-to (min fortran-line-number-indent extra-space)))) ! 609: (skip-chars-forward "0-9")))) ! 610: ;; Point is now after any continuation character or line number. ! 611: ;; Put body of statement where specified. ! 612: (delete-horizontal-space) ! 613: (indent-to col) ! 614: ;; Indent any comment following code on the same line. ! 615: (if (re-search-forward comment-start-skip ! 616: (save-excursion (end-of-line) (point)) t) ! 617: (progn (goto-char (match-beginning 0)) ! 618: (if (not (= (current-column) (fortran-comment-hook))) ! 619: (progn (delete-horizontal-space) ! 620: (indent-to (fortran-comment-hook))))))))) ! 621: ! 622: (defun fortran-line-number-indented-correctly-p () ! 623: "Return t if current line's line number is correctly indente. ! 624: Do not call if there is no line number." ! 625: (save-excursion ! 626: (beginning-of-line) ! 627: (skip-chars-forward " \t") ! 628: (and (<= (current-column) fortran-line-number-indent) ! 629: (or (= (current-column) fortran-line-number-indent) ! 630: (progn (skip-chars-forward "0-9") ! 631: (= (current-column) 5)))))) ! 632: ! 633: (defun fortran-check-for-matching-do () ! 634: "When called from a numbered statement, returns t ! 635: if matching 'do' is found, and nil otherwise." ! 636: (let (charnum ! 637: (case-fold-search t)) ! 638: (save-excursion ! 639: (beginning-of-line) ! 640: (if (looking-at "[ \t]*[0-9]+") ! 641: (progn ! 642: (skip-chars-forward " \t") ! 643: (skip-chars-forward "0") ;skip past leading zeros ! 644: (setq charnum (buffer-substring (point) ! 645: (progn (skip-chars-forward "0-9") ! 646: (point)))) ! 647: (beginning-of-line) ! 648: (and (re-search-backward ! 649: (concat "\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|\\(^[ \t0-9]*do[ \t]*0*" ! 650: charnum "\\b\\)\\|\\(^[ \t]*0*" charnum "\\b\\)") ! 651: nil t) ! 652: (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum)))))))) ! 653: ! 654:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.