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