diff options
| author | Jim Blandy | 1991-07-15 21:21:23 +0000 |
|---|---|---|
| committer | Jim Blandy | 1991-07-15 21:21:23 +0000 |
| commit | 3dd637609876e12908bfa554b80a1c2145c98ed3 (patch) | |
| tree | fd75ddf524aea06f2a89affce3f4eb17fbba1684 | |
| parent | 9c74a0dd25800566a4afdecd0d61d073dee47b05 (diff) | |
| download | emacs-3dd637609876e12908bfa554b80a1c2145c98ed3.tar.gz emacs-3dd637609876e12908bfa554b80a1c2145c98ed3.zip | |
Initial revision
| -rw-r--r-- | lisp/progmodes/fortran.el | 997 |
1 files changed, 997 insertions, 0 deletions
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el new file mode 100644 index 00000000000..33a2da4b182 --- /dev/null +++ b/lisp/progmodes/fortran.el | |||
| @@ -0,0 +1,997 @@ | |||
| 1 | ;;; Fortran mode for GNU Emacs (version 1.28.3, July 15, 1991) | ||
| 2 | ;;; Copyright (c) 1991 Free Software Foundation, Inc. | ||
| 3 | ;;; Written by Michael D. Prange (prange@erl.mit.edu) | ||
| 4 | ;;; Maintained (as of version 1.28) by Stephen A. Wood (saw@hallc1.cebaf.gov) | ||
| 5 | ;;; This version is an update of version 1.21 (Oct 1, 1985). | ||
| 6 | ;;; Updated by Stephen A. Wood (saw@hallc1.cebaf.gov) to use tab format | ||
| 7 | ;;; continuation control and indentation. (Digit after TAB to signify | ||
| 8 | ;;; continuation line. This version also incorporates suggestions from | ||
| 9 | ;;; Richard Stallman, and the ideas in two previous unpublished versions of | ||
| 10 | ;;; fortran .el (version 1.21.1 (from gildea@expo.lcs.mit.edu) and 1.27 | ||
| 11 | ;;; (prange@erl.mit.edu).) | ||
| 12 | |||
| 13 | ;;; Notes to fortran-mode version 1.28 | ||
| 14 | ;;; 1. Fortran mode can support either fixed format or tab format. Fixed | ||
| 15 | ;;; format is where statements start in column 6 (first column is 0) | ||
| 16 | ;;; and continuation lines are denoted by a character in column 5. | ||
| 17 | ;;; In tab mode, statements follow a tab character. Continuation lines | ||
| 18 | ;;; are where the first character on a line is a tab and the second is | ||
| 19 | ;;; a digit from 1 to 9. | ||
| 20 | ;;; 2. When fortran mode is called, the buffer is analyzed to determine what | ||
| 21 | ;;; kind of formating is used. Starting at the top of the file, lines | ||
| 22 | ;;; are scanned until a line is found that begins with a tab or 6 spaces. | ||
| 23 | ;;; The mode for that buffer is then set to either tab or fixed format | ||
| 24 | ;;; based on that line. If no line starting with a tab or 6 spaces is | ||
| 25 | ;;; found before the end of the buffer or in the first 100 lines, the | ||
| 26 | ;;; mode is set from the variable `fortran-tab-mode-default'. t is tab | ||
| 27 | ;;; mode, nil is fixed format mode. By default, fixed format mode is used. | ||
| 28 | ;;; To use tabbing mode as the default, put the following line in .emacs | ||
| 29 | ;;; (setq fortran-tab-mode-default t) | ||
| 30 | ;;; This line should not be in the hook since the hook is called only | ||
| 31 | ;;; after the file is analyzed. | ||
| 32 | ;;; To force a particular mode independent of the analysis, attach | ||
| 33 | ;;; (fortran-tab-mode t) or (fortran-tab-mode nil) | ||
| 34 | ;;; to fortran-mode-hook. | ||
| 35 | ;;; 3. The command `fortran-tab-mode' will toggle between fixed and tab | ||
| 36 | ;;; formatting modes. The file will not automatically be reformatted, | ||
| 37 | ;;; but either `indent-region' or `fortran-indent-subprogram' can be | ||
| 38 | ;;; used to reformat portions of the file. | ||
| 39 | ;;; 4. Several abbreviations have been added. Abbreviation mode is turned | ||
| 40 | ;;; on by default. | ||
| 41 | ;;; 5. The routine fortran-blink-matching if has been incorporated (from | ||
| 42 | ;;; experimental version 1.27). If the variable of the same name is set | ||
| 43 | ;;; to t, the the matching if statement is blinked whenever an endif | ||
| 44 | ;;; line is indented. | ||
| 45 | ;;; 6. C-c C-w is now bound to fortran-window-create-momentarily (from | ||
| 46 | ;;; experimental version 1.27.) | ||
| 47 | ;;; 7. LFD is now bound to fortran-reindent-then-newline-and-indent. | ||
| 48 | ;;; 8. fortran-continuation-string (was fortran-continuation-char) is now | ||
| 49 | ;;; a string rather than a character. | ||
| 50 | ;;; 9. Fixed a bug from 1.21 that gave max-lisp-eval-depth exceeded when | ||
| 51 | ;;; Comments lines had !'s in them. | ||
| 52 | ;;; 10. DEC fortran recognizes a & in the first column as a continuation. | ||
| 53 | ;;; character. This mode does not recognize the & as a continuation | ||
| 54 | ;;; character. | ||
| 55 | ;;; 11. fortran-blink-matching-if still is in effect when indenting a region. | ||
| 56 | ;;; Is this a desirable effect? (It looks kind of neat) | ||
| 57 | ;;; 12. If you strike a digit and there are exactly 5 characters, all spaces | ||
| 58 | ;;; to the left of the point, the digit will be inserted in place to | ||
| 59 | ;;; serve as a continuation line marker. Similarly, if the only thing to | ||
| 60 | ;;; the left of the point is a single tab, and the last command issued | ||
| 61 | ;;; was neither fortran-indent-line (TAB) or fortran-reindent-then-newline- | ||
| 62 | ;;; and-indent (LFD), the digit is inserted as a tab format style | ||
| 63 | ;;; continuation character. | ||
| 64 | ;;; 13. Both modes should usually work with tab-width set to other than 8. | ||
| 65 | ;;; However, in tab-mode, if tab-width is less than 6, the column number | ||
| 66 | ;;; for the minimum indentation is set to 6 so that all line numbers will | ||
| 67 | ;;; have have a tab after them. This may be a bit ugly, but why would | ||
| 68 | ;;; you want to use a tab-width other than 8 anyway? | ||
| 69 | ;;; 14. When in tab mode, the fortran column ruler will not be correct if | ||
| 70 | ;;; tab-width is not 8. | ||
| 71 | |||
| 72 | ;; This file is part of GNU Emacs. | ||
| 73 | |||
| 74 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 75 | ;; it under the terms of the GNU General Public License as published by | ||
| 76 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 77 | ;; any later version. | ||
| 78 | |||
| 79 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 80 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 81 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 82 | ;; GNU General Public License for more details. | ||
| 83 | |||
| 84 | ;; You should have received a copy of the GNU General Public License | ||
| 85 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 86 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 87 | |||
| 88 | ;;; Author acknowledges help from Stephen Gildea <gildea@erl.mit.edu> | ||
| 89 | |||
| 90 | ;;; Bugs to bug-fortran-mode@erl.mit.edu | ||
| 91 | |||
| 92 | (provide 'fortran) | ||
| 93 | |||
| 94 | ;;;###autoload | ||
| 95 | (defvar fortran-tab-mode-default nil | ||
| 96 | "*Default tabbing/carriage control style for empty files in fortran mode. | ||
| 97 | t indicates that tab-digit style of continuation control will be used. | ||
| 98 | nil indicates that continuation lines are marked with a character in | ||
| 99 | column 6.") | ||
| 100 | |||
| 101 | (defvar fortran-do-indent 3 | ||
| 102 | "*Extra indentation applied to `do' blocks.") | ||
| 103 | |||
| 104 | (defvar fortran-if-indent 3 | ||
| 105 | "*Extra indentation applied to `if' blocks.") | ||
| 106 | |||
| 107 | (defvar fortran-continuation-indent 5 | ||
| 108 | "*Extra indentation applied to `continuation' lines.") | ||
| 109 | |||
| 110 | (defvar fortran-comment-indent-style 'fixed | ||
| 111 | "*nil forces comment lines not to be touched, | ||
| 112 | 'fixed produces fixed comment indentation to comment-column, | ||
| 113 | and 'relative indents to current fortran indentation plus comment-column.") | ||
| 114 | |||
| 115 | (defvar fortran-comment-line-column 6 | ||
| 116 | "*Indentation for text in comment lines.") | ||
| 117 | |||
| 118 | (defvar comment-line-start nil | ||
| 119 | "*Delimiter inserted to start new full-line comment.") | ||
| 120 | |||
| 121 | (defvar comment-line-start-skip nil | ||
| 122 | "*Regexp to match the start of a full-line comment.") | ||
| 123 | |||
| 124 | (defvar fortran-minimum-statement-indent 6 | ||
| 125 | "*Minimum indentation for fortran statements.") | ||
| 126 | |||
| 127 | ;; Note that this is documented in the v18 manuals as being a string | ||
| 128 | ;; of length one rather than a single character. | ||
| 129 | ;; The code in this file accepts either format for compatibility. | ||
| 130 | (defvar fortran-comment-indent-char " " | ||
| 131 | "*Single-character string inserted for Fortran comment indentation. | ||
| 132 | Normally a space.") | ||
| 133 | |||
| 134 | (defvar fortran-line-number-indent 1 | ||
| 135 | "*Maximum indentation for Fortran line numbers. | ||
| 136 | 5 means right-justify them within their five-column field.") | ||
| 137 | |||
| 138 | (defvar fortran-check-all-num-for-matching-do nil | ||
| 139 | "*Non-nil causes all numbered lines to be treated as possible do-loop ends.") | ||
| 140 | |||
| 141 | (defvar fortran-blink-matching-if nil | ||
| 142 | "*From a fortran `endif' statement, blink the matching `if' statement.") | ||
| 143 | |||
| 144 | (defvar fortran-continuation-string "$" | ||
| 145 | "*Single-character string used for fortran continuation lines. | ||
| 146 | In fixed format continuation style, this character is inserted in | ||
| 147 | column 6 by \\[fortran-split-line] to begin a continuation line. | ||
| 148 | Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will | ||
| 149 | convert the line into a continuation line of the appropriate style. | ||
| 150 | Normally $.") | ||
| 151 | |||
| 152 | (defvar fortran-comment-region "c$$$" | ||
| 153 | "*String inserted by \\[fortran-comment-region]\ | ||
| 154 | at start of each line in region.") | ||
| 155 | |||
| 156 | (defvar fortran-electric-line-number t | ||
| 157 | "*Non-nil causes line number digits to be moved to the correct column as\ | ||
| 158 | typed.") | ||
| 159 | |||
| 160 | (defvar fortran-startup-message t | ||
| 161 | "*Non-nil displays a startup message when Fortran mode is first called.") | ||
| 162 | |||
| 163 | (defvar fortran-column-ruler " " | ||
| 164 | "*String displayed above current line by \\[fortran-column-ruler].") | ||
| 165 | |||
| 166 | (defconst bug-fortran-mode "bug-fortran-mode@erl.mit.edu" | ||
| 167 | "Address of mailing list for Fortran mode bugs.") | ||
| 168 | |||
| 169 | (defconst fortran-mode-version "1.28.3") | ||
| 170 | |||
| 171 | (defvar fortran-mode-syntax-table nil | ||
| 172 | "Syntax table in use in Fortran mode buffers.") | ||
| 173 | |||
| 174 | (defvar fortran-analyze-depth 100 | ||
| 175 | "Number of lines to scan to determine whether to use fixed or tab format\ | ||
| 176 | style.") | ||
| 177 | |||
| 178 | (if fortran-mode-syntax-table | ||
| 179 | () | ||
| 180 | (setq fortran-mode-syntax-table (make-syntax-table)) | ||
| 181 | (modify-syntax-entry ?\; "w" fortran-mode-syntax-table) | ||
| 182 | (modify-syntax-entry ?\r " " fortran-mode-syntax-table) | ||
| 183 | (modify-syntax-entry ?+ "." fortran-mode-syntax-table) | ||
| 184 | (modify-syntax-entry ?- "." fortran-mode-syntax-table) | ||
| 185 | (modify-syntax-entry ?= "." fortran-mode-syntax-table) | ||
| 186 | (modify-syntax-entry ?* "." fortran-mode-syntax-table) | ||
| 187 | (modify-syntax-entry ?/ "." fortran-mode-syntax-table) | ||
| 188 | (modify-syntax-entry ?\' "\"" fortran-mode-syntax-table) | ||
| 189 | (modify-syntax-entry ?\" "\"" fortran-mode-syntax-table) | ||
| 190 | (modify-syntax-entry ?\\ "/" fortran-mode-syntax-table) | ||
| 191 | (modify-syntax-entry ?. "w" fortran-mode-syntax-table) | ||
| 192 | (modify-syntax-entry ?\n ">" fortran-mode-syntax-table)) | ||
| 193 | |||
| 194 | (defvar fortran-mode-map () | ||
| 195 | "Keymap used in fortran mode.") | ||
| 196 | (if fortran-mode-map | ||
| 197 | () | ||
| 198 | (setq fortran-mode-map (make-sparse-keymap)) | ||
| 199 | (define-key fortran-mode-map ";" 'fortran-abbrev-start) | ||
| 200 | (define-key fortran-mode-map "\C-c;" 'fortran-comment-region) | ||
| 201 | (define-key fortran-mode-map "\e\C-a" 'beginning-of-fortran-subprogram) | ||
| 202 | (define-key fortran-mode-map "\e\C-e" 'end-of-fortran-subprogram) | ||
| 203 | (define-key fortran-mode-map "\e;" 'fortran-indent-comment) | ||
| 204 | (define-key fortran-mode-map "\e\C-h" 'mark-fortran-subprogram) | ||
| 205 | (define-key fortran-mode-map "\e\n" 'fortran-split-line) | ||
| 206 | (define-key fortran-mode-map "\n" 'fortran-reindent-then-newline-and-indent) | ||
| 207 | (define-key fortran-mode-map "\e\C-q" 'fortran-indent-subprogram) | ||
| 208 | (define-key fortran-mode-map "\C-c\C-w" 'fortran-window-create-momentarily) | ||
| 209 | (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler) | ||
| 210 | (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement) | ||
| 211 | (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement) | ||
| 212 | (define-key fortran-mode-map "\t" 'fortran-indent-line) | ||
| 213 | (define-key fortran-mode-map "0" 'fortran-electric-line-number) | ||
| 214 | (define-key fortran-mode-map "1" 'fortran-electric-line-number) | ||
| 215 | (define-key fortran-mode-map "2" 'fortran-electric-line-number) | ||
| 216 | (define-key fortran-mode-map "3" 'fortran-electric-line-number) | ||
| 217 | (define-key fortran-mode-map "4" 'fortran-electric-line-number) | ||
| 218 | (define-key fortran-mode-map "5" 'fortran-electric-line-number) | ||
| 219 | (define-key fortran-mode-map "6" 'fortran-electric-line-number) | ||
| 220 | (define-key fortran-mode-map "7" 'fortran-electric-line-number) | ||
| 221 | (define-key fortran-mode-map "8" 'fortran-electric-line-number) | ||
| 222 | (define-key fortran-mode-map "9" 'fortran-electric-line-number)) | ||
| 223 | |||
| 224 | (defvar fortran-mode-abbrev-table nil) | ||
| 225 | (if fortran-mode-abbrev-table | ||
| 226 | () | ||
| 227 | (let ((ac abbrevs-changed)) | ||
| 228 | (define-abbrev-table 'fortran-mode-abbrev-table ()) | ||
| 229 | (define-abbrev fortran-mode-abbrev-table ";au" "automatic" nil) | ||
| 230 | (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil) | ||
| 231 | (define-abbrev fortran-mode-abbrev-table ";bl" "block data" nil) | ||
| 232 | (define-abbrev fortran-mode-abbrev-table ";ch" "character" nil) | ||
| 233 | (define-abbrev fortran-mode-abbrev-table ";cl" "close" nil) | ||
| 234 | (define-abbrev fortran-mode-abbrev-table ";c" "continue" nil) | ||
| 235 | (define-abbrev fortran-mode-abbrev-table ";cm" "common" nil) | ||
| 236 | (define-abbrev fortran-mode-abbrev-table ";cx" "complex" nil) | ||
| 237 | (define-abbrev fortran-mode-abbrev-table ";df" "define" nil) | ||
| 238 | (define-abbrev fortran-mode-abbrev-table ";di" "dimension" nil) | ||
| 239 | (define-abbrev fortran-mode-abbrev-table ";do" "double" nil) | ||
| 240 | (define-abbrev fortran-mode-abbrev-table ";dc" "double complex" nil) | ||
| 241 | (define-abbrev fortran-mode-abbrev-table ";dp" "double precision" nil) | ||
| 242 | (define-abbrev fortran-mode-abbrev-table ";dw" "do while" nil) | ||
| 243 | (define-abbrev fortran-mode-abbrev-table ";e" "else" nil) | ||
| 244 | (define-abbrev fortran-mode-abbrev-table ";ed" "enddo" nil) | ||
| 245 | (define-abbrev fortran-mode-abbrev-table ";el" "elseif" nil) | ||
| 246 | (define-abbrev fortran-mode-abbrev-table ";en" "endif" nil) | ||
| 247 | (define-abbrev fortran-mode-abbrev-table ";eq" "equivalence" nil) | ||
| 248 | (define-abbrev fortran-mode-abbrev-table ";ex" "external" nil) | ||
| 249 | (define-abbrev fortran-mode-abbrev-table ";ey" "entry" nil) | ||
| 250 | (define-abbrev fortran-mode-abbrev-table ";f" "format" nil) | ||
| 251 | (define-abbrev fortran-mode-abbrev-table ";fa" ".false." nil) | ||
| 252 | (define-abbrev fortran-mode-abbrev-table ";fu" "function" nil) | ||
| 253 | (define-abbrev fortran-mode-abbrev-table ";g" "goto" nil) | ||
| 254 | (define-abbrev fortran-mode-abbrev-table ";im" "implicit" nil) | ||
| 255 | (define-abbrev fortran-mode-abbrev-table ";ib" "implicit byte" nil) | ||
| 256 | (define-abbrev fortran-mode-abbrev-table ";ic" "implicit complex" nil) | ||
| 257 | (define-abbrev fortran-mode-abbrev-table ";ich" "implicit character" nil) | ||
| 258 | (define-abbrev fortran-mode-abbrev-table ";ii" "implicit integer" nil) | ||
| 259 | (define-abbrev fortran-mode-abbrev-table ";il" "implicit logical" nil) | ||
| 260 | (define-abbrev fortran-mode-abbrev-table ";ir" "implicit real" nil) | ||
| 261 | (define-abbrev fortran-mode-abbrev-table ";inc" "include" nil) | ||
| 262 | (define-abbrev fortran-mode-abbrev-table ";in" "integer" nil) | ||
| 263 | (define-abbrev fortran-mode-abbrev-table ";intr" "intrinsic" nil) | ||
| 264 | (define-abbrev fortran-mode-abbrev-table ";l" "logical" nil) | ||
| 265 | (define-abbrev fortran-mode-abbrev-table ";n" "namelist" nil) | ||
| 266 | (define-abbrev fortran-mode-abbrev-table ";o" "open" nil) ; was ;op | ||
| 267 | (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil) | ||
| 268 | (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil) | ||
| 269 | (define-abbrev fortran-mode-abbrev-table ";ps" "pause" nil) | ||
| 270 | (define-abbrev fortran-mode-abbrev-table ";p" "print" nil) | ||
| 271 | (define-abbrev fortran-mode-abbrev-table ";rc" "record" nil) | ||
| 272 | (define-abbrev fortran-mode-abbrev-table ";re" "real" nil) | ||
| 273 | (define-abbrev fortran-mode-abbrev-table ";r" "read" nil) | ||
| 274 | (define-abbrev fortran-mode-abbrev-table ";rt" "return" nil) | ||
| 275 | (define-abbrev fortran-mode-abbrev-table ";rw" "rewind" nil) | ||
| 276 | (define-abbrev fortran-mode-abbrev-table ";s" "stop" nil) | ||
| 277 | (define-abbrev fortran-mode-abbrev-table ";sa" "save" nil) | ||
| 278 | (define-abbrev fortran-mode-abbrev-table ";st" "structure" nil) | ||
| 279 | (define-abbrev fortran-mode-abbrev-table ";sc" "static" nil) | ||
| 280 | (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil) | ||
| 281 | (define-abbrev fortran-mode-abbrev-table ";tr" ".true." nil) | ||
| 282 | (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil) | ||
| 283 | (define-abbrev fortran-mode-abbrev-table ";vo" "volatile" nil) | ||
| 284 | (define-abbrev fortran-mode-abbrev-table ";w" "write" nil) | ||
| 285 | (setq abbrevs-changed ac))) | ||
| 286 | |||
| 287 | ;;;###autoload | ||
| 288 | (defun fortran-mode () | ||
| 289 | "Major mode for editing fortran code. | ||
| 290 | Tab indents the current fortran line correctly. | ||
| 291 | `do' statements must not share a common `continue'. | ||
| 292 | |||
| 293 | Type `;?' or `;\\[help-command]' to display a list of built-in\ | ||
| 294 | abbrevs for Fortran keywords. | ||
| 295 | |||
| 296 | Key definitions: | ||
| 297 | \\{fortran-mode-map} | ||
| 298 | |||
| 299 | Variables controlling indentation style and extra features: | ||
| 300 | |||
| 301 | comment-start | ||
| 302 | Normally nil in Fortran mode. If you want to use comments | ||
| 303 | starting with `!', set this to the string \"!\". | ||
| 304 | fortran-do-indent | ||
| 305 | Extra indentation within do blocks. (default 3) | ||
| 306 | fortran-if-indent | ||
| 307 | Extra indentation within if blocks. (default 3) | ||
| 308 | fortran-continuation-indent | ||
| 309 | Extra indentation appled to continuation statements. (default 5) | ||
| 310 | fortran-comment-line-column | ||
| 311 | Amount of indentation for text within full-line comments. (default 6) | ||
| 312 | fortran-comment-indent-style | ||
| 313 | nil means don't change indentation of text in full-line comments, | ||
| 314 | fixed means indent that text at column fortran-comment-line-column | ||
| 315 | relative means indent at fortran-comment-line-column beyond the | ||
| 316 | indentation for a line of code. | ||
| 317 | (default 'fixed) | ||
| 318 | fortran-comment-indent-char | ||
| 319 | Single-character string be inserted instead of space for | ||
| 320 | full-line comment indentation. (default \" \") | ||
| 321 | fortran-minimum-statement-indent | ||
| 322 | Minimum indentation for fortran statements. (default 6) | ||
| 323 | fortran-line-number-indent | ||
| 324 | Maximum indentation for line numbers. A line number will get | ||
| 325 | less than this much indentation if necessary to avoid reaching | ||
| 326 | column 5. (default 1) | ||
| 327 | fortran-check-all-num-for-matching-do | ||
| 328 | Non-nil causes all numbered lines to be treated as possible 'continue' | ||
| 329 | statements. (default nil) | ||
| 330 | fortran-blink-matching-if | ||
| 331 | From a fortran `endif' statement, blink the matching `if' statement. | ||
| 332 | (default nil) | ||
| 333 | fortran-continuation-string | ||
| 334 | Single-character string to be inserted in column 5 of a continuation | ||
| 335 | line. (default \"$\") | ||
| 336 | fortran-comment-region | ||
| 337 | String inserted by \\[fortran-comment-region] at start of each line in | ||
| 338 | region. (default \"c$$$\") | ||
| 339 | fortran-electric-line-number | ||
| 340 | Non-nil causes line number digits to be moved to the correct column | ||
| 341 | as typed. (default t) | ||
| 342 | fortran-startup-message | ||
| 343 | Set to nil to inhibit message first time Fortran mode is used. | ||
| 344 | |||
| 345 | Turning on Fortran mode calls the value of the variable fortran-mode-hook | ||
| 346 | with no args, if that value is non-nil." | ||
| 347 | (interactive) | ||
| 348 | (kill-all-local-variables) | ||
| 349 | (if fortran-startup-message | ||
| 350 | (message "Emacs Fortran mode version %s. Bugs to %s" | ||
| 351 | fortran-mode-version bug-fortran-mode)) | ||
| 352 | (setq fortran-startup-message nil) | ||
| 353 | (setq local-abbrev-table fortran-mode-abbrev-table) | ||
| 354 | (set-syntax-table fortran-mode-syntax-table) | ||
| 355 | (make-local-variable 'indent-line-function) | ||
| 356 | (setq indent-line-function 'fortran-indent-line) | ||
| 357 | (make-local-variable 'comment-indent-hook) | ||
| 358 | (setq comment-indent-hook 'fortran-comment-hook) | ||
| 359 | (make-local-variable 'comment-line-start-skip) | ||
| 360 | (setq comment-line-start-skip | ||
| 361 | "^[Cc*]\\(\\([^ \t\n]\\)\\1*\\)?[ \t]*") ;[^ \t\n]* handles c$$$ | ||
| 362 | (make-local-variable 'comment-line-start) | ||
| 363 | (setq comment-line-start "c") | ||
| 364 | (make-local-variable 'comment-start-skip) | ||
| 365 | (setq comment-start-skip "![ \t]*") | ||
| 366 | (make-local-variable 'comment-start) | ||
| 367 | (setq comment-start nil) | ||
| 368 | (make-local-variable 'require-final-newline) | ||
| 369 | (setq require-final-newline t) | ||
| 370 | (make-local-variable 'abbrev-all-caps) | ||
| 371 | (setq abbrev-all-caps t) | ||
| 372 | (make-local-variable 'indent-tabs-mode) | ||
| 373 | (setq indent-tabs-mode nil) | ||
| 374 | (setq abbrev-mode t) ; ?? (abbrev-mode 1) instead?? | ||
| 375 | (use-local-map fortran-mode-map) | ||
| 376 | (setq mode-name "Fortran") | ||
| 377 | (setq major-mode 'fortran-mode) | ||
| 378 | (make-local-variable 'fortran-tab-mode) | ||
| 379 | (make-local-variable 'fortran-comment-line-column) | ||
| 380 | (make-local-variable 'fortran-minimum-statement-indent) | ||
| 381 | (make-local-variable 'fortran-column-ruler) | ||
| 382 | (make-local-variable 'fortran-tab-mode-string) | ||
| 383 | (fortran-tab-mode (fortran-analyze-file-format)) | ||
| 384 | (run-hooks 'fortran-mode-hook)) | ||
| 385 | |||
| 386 | (defun fortran-comment-hook () | ||
| 387 | (save-excursion | ||
| 388 | (skip-chars-backward " \t") | ||
| 389 | (max (+ 1 (current-column)) | ||
| 390 | comment-column))) | ||
| 391 | |||
| 392 | (defun fortran-indent-comment () | ||
| 393 | "Align or create comment on current line. | ||
| 394 | Existing comments of all types are recognized and aligned. | ||
| 395 | If the line has no comment, a side-by-side comment is inserted and aligned | ||
| 396 | if the value of comment-start is not nil. | ||
| 397 | Otherwise, a separate-line comment is inserted, on this line | ||
| 398 | or on a new line inserted before this line if this line is not blank." | ||
| 399 | (interactive) | ||
| 400 | (beginning-of-line) | ||
| 401 | ;; Recognize existing comments of either kind. | ||
| 402 | (cond ((looking-at comment-line-start-skip) | ||
| 403 | (fortran-indent-line)) | ||
| 404 | ((re-search-forward comment-start-skip | ||
| 405 | (save-excursion (end-of-line) (point)) t) | ||
| 406 | (indent-for-comment)) | ||
| 407 | ;; No existing comment. | ||
| 408 | ;; If side-by-side comments are defined, insert one, | ||
| 409 | ;; unless line is now blank. | ||
| 410 | ((and comment-start (not (looking-at "^[ \t]*$"))) | ||
| 411 | (end-of-line) | ||
| 412 | (delete-horizontal-space) | ||
| 413 | (indent-to (fortran-comment-hook)) | ||
| 414 | (insert comment-start)) | ||
| 415 | ;; Else insert separate-line comment, making a new line if nec. | ||
| 416 | (t | ||
| 417 | (if (looking-at "^[ \t]*$") | ||
| 418 | (delete-horizontal-space) | ||
| 419 | (beginning-of-line) | ||
| 420 | (insert "\n") | ||
| 421 | (forward-char -1)) | ||
| 422 | (insert comment-line-start) | ||
| 423 | (insert-char (if (stringp fortran-comment-indent-char) | ||
| 424 | (aref fortran-comment-indent-char 0) | ||
| 425 | fortran-comment-indent-char) | ||
| 426 | (- (calculate-fortran-indent) (current-column)))))) | ||
| 427 | |||
| 428 | (defun fortran-comment-region (beg-region end-region arg) | ||
| 429 | "Comments every line in the region. | ||
| 430 | Puts fortran-comment-region at the beginning of every line in the region. | ||
| 431 | BEG-REGION and END-REGION are args which specify the region boundaries. | ||
| 432 | With non-nil ARG, uncomments the region." | ||
| 433 | (interactive "*r\nP") | ||
| 434 | (let ((end-region-mark (make-marker)) (save-point (point-marker))) | ||
| 435 | (set-marker end-region-mark end-region) | ||
| 436 | (goto-char beg-region) | ||
| 437 | (beginning-of-line) | ||
| 438 | (if (not arg) ;comment the region | ||
| 439 | (progn (insert fortran-comment-region) | ||
| 440 | (while (and (= (forward-line 1) 0) | ||
| 441 | (< (point) end-region-mark)) | ||
| 442 | (insert fortran-comment-region))) | ||
| 443 | (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region | ||
| 444 | (if (looking-at com) | ||
| 445 | (delete-region (point) (match-end 0))) | ||
| 446 | (while (and (= (forward-line 1) 0) | ||
| 447 | (< (point) end-region-mark)) | ||
| 448 | (if (looking-at com) | ||
| 449 | (delete-region (point) (match-end 0)))))) | ||
| 450 | (goto-char save-point) | ||
| 451 | (set-marker end-region-mark nil) | ||
| 452 | (set-marker save-point nil))) | ||
| 453 | |||
| 454 | (defun fortran-abbrev-start () | ||
| 455 | "Typing \";\\[help-command]\" or \";?\" lists all the fortran abbrevs. | ||
| 456 | Any other key combination is executed normally." | ||
| 457 | (interactive) | ||
| 458 | (let (c) | ||
| 459 | (insert last-command-char) | ||
| 460 | (if (or (= (setq c (read-char)) ??) ;insert char if not equal to `?' | ||
| 461 | (= c help-char)) | ||
| 462 | (fortran-abbrev-help) | ||
| 463 | (setq unread-command-char c)))) | ||
| 464 | |||
| 465 | (defun fortran-abbrev-help () | ||
| 466 | "List the currently defined abbrevs in Fortran mode." | ||
| 467 | (interactive) | ||
| 468 | (message "Listing abbrev table...") | ||
| 469 | (require 'abbrevlist) | ||
| 470 | (list-one-abbrev-table fortran-mode-abbrev-table "*Help*") | ||
| 471 | (message "Listing abbrev table...done")) | ||
| 472 | |||
| 473 | (defun fortran-column-ruler () | ||
| 474 | "Inserts a column ruler momentarily above current line, till next keystroke. | ||
| 475 | The ruler is defined by the value of fortran-column-ruler. | ||
| 476 | The key typed is executed unless it is SPC." | ||
| 477 | (interactive) | ||
| 478 | (momentary-string-display | ||
| 479 | fortran-column-ruler (save-excursion (beginning-of-line) (point)) | ||
| 480 | nil "Type SPC or any command to erase ruler.")) | ||
| 481 | |||
| 482 | (defun fortran-window-create () | ||
| 483 | "Makes the window 72 columns wide. | ||
| 484 | See also fortran-window-create-momentarily." | ||
| 485 | (interactive) | ||
| 486 | (condition-case error | ||
| 487 | (progn | ||
| 488 | (let ((window-min-width 2)) | ||
| 489 | (if (< (window-width) (screen-width)) | ||
| 490 | (enlarge-window-horizontally (- (screen-width) | ||
| 491 | (window-width) 1))) | ||
| 492 | (split-window-horizontally 73) | ||
| 493 | (other-window 1) | ||
| 494 | (switch-to-buffer " fortran-window-extra" t) | ||
| 495 | (select-window (previous-window)))) | ||
| 496 | (error (message "No room for fortran window.") | ||
| 497 | 'error))) | ||
| 498 | |||
| 499 | (defun fortran-window-create-momentarily (&optional arg) | ||
| 500 | "Momentarily makes the window 72 columns wide. | ||
| 501 | Optional ARG non-nil and non-unity disables the momentary feature. | ||
| 502 | See also fortran-window-create." | ||
| 503 | (interactive "p") | ||
| 504 | (if (or (not arg) | ||
| 505 | (= arg 1)) | ||
| 506 | (save-window-excursion | ||
| 507 | (if (not (equal (fortran-window-create) 'error)) | ||
| 508 | (progn (message "Type SPC to continue editing.") | ||
| 509 | (let ((char (read-char))) | ||
| 510 | (or (equal char (string-to-char " ")) | ||
| 511 | (setq unread-command-char char)))))) | ||
| 512 | (fortran-window-create))) | ||
| 513 | |||
| 514 | (defun fortran-split-line () | ||
| 515 | "Break line at point and insert continuation marker and alignment." | ||
| 516 | (interactive) | ||
| 517 | (delete-horizontal-space) | ||
| 518 | (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip)) | ||
| 519 | (insert "\n" comment-line-start " ") | ||
| 520 | (if fortran-tab-mode | ||
| 521 | (progn | ||
| 522 | (insert "\n\t") | ||
| 523 | (insert-char (fortran-numerical-continuation-char) 1)) | ||
| 524 | (insert "\n" fortran-continuation-string))) | ||
| 525 | (fortran-indent-line)) | ||
| 526 | |||
| 527 | (defun fortran-numerical-continuation-char () | ||
| 528 | "Return a digit for tab-digit style of continution lines. | ||
| 529 | If, previous line is a tab-digit continuation line, returns that digit | ||
| 530 | plus one. Otherwise return 1. Zero not allowed." | ||
| 531 | (save-excursion | ||
| 532 | (forward-line -1) | ||
| 533 | (if (looking-at "\t[1-9]") | ||
| 534 | (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9)) | ||
| 535 | ?1))) | ||
| 536 | |||
| 537 | (defun delete-horizontal-regexp (chars) | ||
| 538 | "Delete all characters in CHARS around point. | ||
| 539 | CHARS is like the inside of a [...] in a regular expression | ||
| 540 | except that ] is never special and \ quotes ^, - or \." | ||
| 541 | (interactive "*s") | ||
| 542 | (skip-chars-backward chars) | ||
| 543 | (delete-region (point) (progn (skip-chars-forward chars) (point)))) | ||
| 544 | |||
| 545 | (defun fortran-electric-line-number (arg) | ||
| 546 | "Self insert, but if part of a Fortran line number indent it automatically. | ||
| 547 | Auto-indent does not happen if a numeric arg is used." | ||
| 548 | ;The use of arg may be superfluous here since there apears to be no way to | ||
| 549 | ;prefix a digit key with an argument. | ||
| 550 | (interactive "P") | ||
| 551 | (if (or arg (not fortran-electric-line-number)) | ||
| 552 | (if arg | ||
| 553 | (self-insert-command arg) | ||
| 554 | (self-insert-command 1)) | ||
| 555 | (if (or (and (= 5 (current-column)) | ||
| 556 | (save-excursion | ||
| 557 | (beginning-of-line) | ||
| 558 | (looking-at " ")));In col 5 with only spaces to left. | ||
| 559 | (and (= fortran-minimum-statement-indent (current-column)) | ||
| 560 | (save-excursion | ||
| 561 | (beginning-of-line) | ||
| 562 | (looking-at "\t"));In col 8 with a single tab to the left. | ||
| 563 | (not (or (eq last-command 'fortran-indent-line) | ||
| 564 | (eq last-command | ||
| 565 | 'fortran-reindent-then-newline-and-indent)))) | ||
| 566 | (save-excursion | ||
| 567 | (re-search-backward "[^ \t0-9]" | ||
| 568 | (save-excursion | ||
| 569 | (beginning-of-line) | ||
| 570 | (point)) | ||
| 571 | t)) ;not a line number | ||
| 572 | (looking-at "[0-9]") ;within a line number | ||
| 573 | ) | ||
| 574 | (insert last-command-char) | ||
| 575 | (skip-chars-backward " \t") | ||
| 576 | (insert last-command-char) | ||
| 577 | (fortran-indent-line)))) | ||
| 578 | |||
| 579 | (defun beginning-of-fortran-subprogram () | ||
| 580 | "Moves point to the beginning of the current fortran subprogram." | ||
| 581 | (interactive) | ||
| 582 | (let ((case-fold-search t)) | ||
| 583 | (beginning-of-line -1) | ||
| 584 | (re-search-backward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) | ||
| 585 | (if (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]") | ||
| 586 | (forward-line 1)))) | ||
| 587 | |||
| 588 | (defun end-of-fortran-subprogram () | ||
| 589 | "Moves point to the end of the current fortran subprogram." | ||
| 590 | (interactive) | ||
| 591 | (let ((case-fold-search t)) | ||
| 592 | (beginning-of-line 2) | ||
| 593 | (re-search-forward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) | ||
| 594 | (goto-char (match-beginning 0)) | ||
| 595 | (forward-line 1))) | ||
| 596 | |||
| 597 | (defun mark-fortran-subprogram () | ||
| 598 | "Put mark at end of fortran subprogram, point at beginning. | ||
| 599 | The marks are pushed." | ||
| 600 | (interactive) | ||
| 601 | (end-of-fortran-subprogram) | ||
| 602 | (push-mark (point)) | ||
| 603 | (beginning-of-fortran-subprogram)) | ||
| 604 | |||
| 605 | (defun fortran-previous-statement () | ||
| 606 | "Moves point to beginning of the previous fortran statement. | ||
| 607 | Returns 'first-statement if that statement is the first | ||
| 608 | non-comment Fortran statement in the file, and nil otherwise." | ||
| 609 | (interactive) | ||
| 610 | (let (not-first-statement continue-test) | ||
| 611 | (beginning-of-line) | ||
| 612 | (setq continue-test | ||
| 613 | (or (looking-at | ||
| 614 | (concat "[ \t]*" (regexp-quote fortran-continuation-string))) | ||
| 615 | (or (looking-at " [^ 0\n]") | ||
| 616 | (looking-at "\t[1-9]")))) | ||
| 617 | (while (and (setq not-first-statement (= (forward-line -1) 0)) | ||
| 618 | (or (looking-at comment-line-start-skip) | ||
| 619 | (looking-at "[ \t]*$") | ||
| 620 | (looking-at " [^ 0\n]") | ||
| 621 | (looking-at "\t[1-9]") | ||
| 622 | (looking-at (concat "[ \t]*" comment-start-skip))))) | ||
| 623 | (cond ((and continue-test | ||
| 624 | (not not-first-statement)) | ||
| 625 | (message "Incomplete continuation statement.")) | ||
| 626 | (continue-test | ||
| 627 | (fortran-previous-statement)) | ||
| 628 | ((not not-first-statement) | ||
| 629 | 'first-statement)))) | ||
| 630 | |||
| 631 | (defun fortran-next-statement () | ||
| 632 | "Moves point to beginning of the next fortran statement. | ||
| 633 | Returns `last-statement' if that statement is the last | ||
| 634 | non-comment Fortran statement in the file, and nil otherwise." | ||
| 635 | (interactive) | ||
| 636 | (let (not-last-statement) | ||
| 637 | (beginning-of-line) | ||
| 638 | (while (and (setq not-last-statement (= (forward-line 1) 0)) | ||
| 639 | (or (looking-at comment-line-start-skip) | ||
| 640 | (looking-at "[ \t]*$") | ||
| 641 | (looking-at " [^ 0\n]") | ||
| 642 | (looking-at "\t[1-9]") | ||
| 643 | (looking-at (concat "[ \t]*" comment-start-skip))))) | ||
| 644 | (if (not not-last-statement) | ||
| 645 | 'last-statement))) | ||
| 646 | |||
| 647 | (defun fortran-blink-matching-if () | ||
| 648 | "From a fortran `endif' statement, blink the matching `if' statement." | ||
| 649 | (let ((count 1) (top-of-window (window-start)) matching-if | ||
| 650 | (endif-point (point)) message) | ||
| 651 | (if (save-excursion (beginning-of-line) | ||
| 652 | (skip-chars-forward " \t0-9") | ||
| 653 | (looking-at "end[ \t]*if\\b")) | ||
| 654 | (progn | ||
| 655 | (save-excursion | ||
| 656 | (while (and (not (= count 0)) | ||
| 657 | (not (eq (fortran-previous-statement) | ||
| 658 | 'first-statement)) | ||
| 659 | (not (looking-at | ||
| 660 | "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) | ||
| 661 | ; Keep local to subprogram | ||
| 662 | (skip-chars-forward " \t0-9") | ||
| 663 | (cond ((looking-at "if[ \t]*(") | ||
| 664 | (save-excursion (if (or (looking-at ".*)[ | ||
| 665 | \t]*then\\b[ \t]*[^ \t(=a-z0-9]") | ||
| 666 | (let (then-test);multi-line if-then | ||
| 667 | (while (and (= (forward-line 1) 0) | ||
| 668 | ;search forward for then | ||
| 669 | (or | ||
| 670 | (looking-at " [^ 0\n]") | ||
| 671 | |||
| 672 | (looking-at "\t[1-9]")) | ||
| 673 | (not (setq | ||
| 674 | then-test (looking-at | ||
| 675 | |||
| 676 | ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) | ||
| 677 | then-test)) | ||
| 678 | (setq count (- count 1))))) | ||
| 679 | ((looking-at "end[ \t]*if\\b") | ||
| 680 | (setq count (+ count 1))))) | ||
| 681 | (if (not (= count 0)) | ||
| 682 | (setq message "No matching if.") | ||
| 683 | (if (< (point) top-of-window) | ||
| 684 | (setq message (concat "Matches " (buffer-substring | ||
| 685 | (progn (beginning-of-line) | ||
| 686 | (point)) | ||
| 687 | (progn (end-of-line) | ||
| 688 | (point))))) | ||
| 689 | (setq matching-if (point))))) | ||
| 690 | (if message | ||
| 691 | (message message) | ||
| 692 | (goto-char matching-if) | ||
| 693 | (sit-for 1) | ||
| 694 | (goto-char endif-point)))))) | ||
| 695 | |||
| 696 | (defun fortran-indent-line () | ||
| 697 | "Indents current fortran line based on its contents and on previous lines." | ||
| 698 | (interactive) | ||
| 699 | (let ((cfi (calculate-fortran-indent))) | ||
| 700 | (save-excursion | ||
| 701 | (beginning-of-line) | ||
| 702 | (if (or (not (= cfi (fortran-current-line-indentation))) | ||
| 703 | (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t) | ||
| 704 | (not (fortran-line-number-indented-correctly-p)))) | ||
| 705 | (fortran-indent-to-column cfi) | ||
| 706 | (beginning-of-line) | ||
| 707 | (if (and (not (looking-at comment-line-start-skip)) | ||
| 708 | (re-search-forward comment-start-skip | ||
| 709 | (save-excursion (end-of-line) (point)) 'move)) | ||
| 710 | (fortran-indent-comment)))) | ||
| 711 | ;; Never leave point in left margin. | ||
| 712 | (if (< (current-column) cfi) | ||
| 713 | (move-to-column cfi)) | ||
| 714 | (if fortran-blink-matching-if | ||
| 715 | (fortran-blink-matching-if)))) | ||
| 716 | |||
| 717 | (defun fortran-reindent-then-newline-and-indent () | ||
| 718 | "Reindent the current fortran line, insert a newline and indent the newline. | ||
| 719 | An abbrev before point is expanded if abbrev-mode is non-nil." | ||
| 720 | (interactive) | ||
| 721 | (if abbrev-mode (expand-abbrev)) | ||
| 722 | (save-excursion | ||
| 723 | (beginning-of-line) | ||
| 724 | (skip-chars-forward " \t") | ||
| 725 | (if (or (looking-at "[0-9]") ;Reindent only where it is most | ||
| 726 | (looking-at "end") ;likely to be necessary | ||
| 727 | (looking-at "else") | ||
| 728 | (looking-at (regexp-quote fortran-continuation-string))) | ||
| 729 | (fortran-indent-line))) | ||
| 730 | (insert "\n") | ||
| 731 | (fortran-indent-line)) | ||
| 732 | |||
| 733 | (defun fortran-indent-subprogram () | ||
| 734 | "Properly indents the Fortran subprogram which contains point." | ||
| 735 | (interactive) | ||
| 736 | (save-excursion | ||
| 737 | (mark-fortran-subprogram) | ||
| 738 | (message "Indenting subprogram...") | ||
| 739 | (indent-region (point) (mark) nil)) | ||
| 740 | (message "Indenting subprogram...done.")) | ||
| 741 | |||
| 742 | (defun calculate-fortran-indent () | ||
| 743 | "Calculates the fortran indent column based on previous lines." | ||
| 744 | (let (icol first-statement (case-fold-search t) | ||
| 745 | (fortran-minimum-statement-indent | ||
| 746 | fortran-minimum-statement-indent)) | ||
| 747 | (save-excursion | ||
| 748 | (setq first-statement (fortran-previous-statement)) | ||
| 749 | (if first-statement | ||
| 750 | (setq icol fortran-minimum-statement-indent) | ||
| 751 | (progn | ||
| 752 | (if (= (point) (point-min)) | ||
| 753 | (setq icol fortran-minimum-statement-indent) | ||
| 754 | (setq icol (fortran-current-line-indentation))) | ||
| 755 | (skip-chars-forward " \t0-9") | ||
| 756 | (cond ((looking-at "if[ \t]*(") | ||
| 757 | (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") | ||
| 758 | (let (then-test) ;multi-line if-then | ||
| 759 | (while (and (= (forward-line 1) 0) | ||
| 760 | ;search forward for then | ||
| 761 | (or (looking-at " [^ 0\n]") | ||
| 762 | (looking-at "\t[1-9]")) | ||
| 763 | (not (setq then-test (looking-at | ||
| 764 | ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) | ||
| 765 | then-test)) | ||
| 766 | (setq icol (+ icol fortran-if-indent)))) | ||
| 767 | ((looking-at "\\(else\\|elseif\\)\\b") | ||
| 768 | (setq icol (+ icol fortran-if-indent))) | ||
| 769 | ((looking-at "do\\b") | ||
| 770 | (setq icol (+ icol fortran-do-indent))) | ||
| 771 | ((looking-at "end\\b[ \t]*[^ \t=(a-z]") | ||
| 772 | ; Previous END resets indent to minimum | ||
| 773 | (setq icol fortran-minimum-statement-indent)))))) | ||
| 774 | (save-excursion | ||
| 775 | (beginning-of-line) | ||
| 776 | (cond ((looking-at "[ \t]*$")) | ||
| 777 | ((looking-at comment-line-start-skip) | ||
| 778 | (setq fortran-minimum-statement-indent 0) | ||
| 779 | (cond ((eq fortran-comment-indent-style 'relative) | ||
| 780 | (setq icol (+ icol fortran-comment-line-column))) | ||
| 781 | ((eq fortran-comment-indent-style 'fixed) | ||
| 782 | (setq icol fortran-comment-line-column)))) | ||
| 783 | ((or (looking-at (concat "[ \t]*" | ||
| 784 | (regexp-quote fortran-continuation-string))) | ||
| 785 | (looking-at " [^ 0\n]") | ||
| 786 | (looking-at "\t[1-9]")) | ||
| 787 | (setq icol (+ icol fortran-continuation-indent))) | ||
| 788 | (first-statement) | ||
| 789 | ((and fortran-check-all-num-for-matching-do | ||
| 790 | (looking-at "[ \t]*[0-9]+") | ||
| 791 | (fortran-check-for-matching-do)) | ||
| 792 | (setq icol (- icol fortran-do-indent))) | ||
| 793 | (t | ||
| 794 | (skip-chars-forward " \t0-9") | ||
| 795 | (cond ((looking-at "end[ \t]*if\\b") | ||
| 796 | (setq icol (- icol fortran-if-indent))) | ||
| 797 | ((looking-at "\\(else\\|elseif\\)\\b") | ||
| 798 | (setq icol (- icol fortran-if-indent))) | ||
| 799 | ((and (looking-at "continue\\b") | ||
| 800 | (fortran-check-for-matching-do)) | ||
| 801 | (setq icol (- icol fortran-do-indent))) | ||
| 802 | ((looking-at "end[ \t]*do\\b") | ||
| 803 | (setq icol (- icol fortran-do-indent))) | ||
| 804 | ((and (looking-at "end\\b[ \t]*[^ \t=(a-z]") | ||
| 805 | (not (= icol fortran-minimum-statement-indent))) | ||
| 806 | (message "Warning: `end' not in column %d. Probably\ | ||
| 807 | an unclosed block." fortran-minimum-statement-indent)))))) | ||
| 808 | (max fortran-minimum-statement-indent icol))) | ||
| 809 | |||
| 810 | (defun fortran-current-line-indentation () | ||
| 811 | "Indentation of current line, ignoring Fortran line number or continuation. | ||
| 812 | This is the column position of the first non-whitespace character | ||
| 813 | aside from the line number and/or column 5/8 line-continuation character. | ||
| 814 | For comment lines, returns indentation of the first | ||
| 815 | non-indentation text within the comment." | ||
| 816 | (save-excursion | ||
| 817 | (beginning-of-line) | ||
| 818 | (cond ((looking-at comment-line-start-skip) | ||
| 819 | (goto-char (match-end 0)) | ||
| 820 | (skip-chars-forward | ||
| 821 | (if (stringp fortran-comment-indent-char) | ||
| 822 | fortran-comment-indent-char | ||
| 823 | (char-to-string fortran-comment-indent-char)))) | ||
| 824 | ((or (looking-at " [^ 0\n]") | ||
| 825 | (looking-at "\t[1-9]")) | ||
| 826 | (goto-char (match-end 0))) | ||
| 827 | (t | ||
| 828 | ;; Move past line number. | ||
| 829 | (re-search-forward "^[ \t0-9]*" (+ (point) 4) t))) | ||
| 830 | ;; Move past whitespace. | ||
| 831 | (skip-chars-forward " \t") | ||
| 832 | (current-column))) | ||
| 833 | |||
| 834 | (defun fortran-indent-to-column (col) | ||
| 835 | "Indents current line with spaces to column COL. | ||
| 836 | notes: 1) A non-zero/non-blank character in column 5 indicates a continuation | ||
| 837 | line, and this continuation character is retained on indentation; | ||
| 838 | 2) If fortran-continuation-string is the first non-whitespace character, | ||
| 839 | this is a continuation line; | ||
| 840 | 3) A non-continuation line which has a number as the first | ||
| 841 | non-whitespace character is a numbered line. | ||
| 842 | 4) A tab followed by a digit indicates a continuation line." | ||
| 843 | (save-excursion | ||
| 844 | (beginning-of-line) | ||
| 845 | (if (looking-at comment-line-start-skip) | ||
| 846 | (if fortran-comment-indent-style | ||
| 847 | (let ((char (if (stringp fortran-comment-indent-char) | ||
| 848 | (aref fortran-comment-indent-char 0) | ||
| 849 | fortran-comment-indent-char))) | ||
| 850 | (goto-char (match-end 0)) | ||
| 851 | (delete-horizontal-regexp (concat " \t" (char-to-string char))) | ||
| 852 | (insert-char char (- col (current-column))))) | ||
| 853 | (if (looking-at "\t[1-9]") | ||
| 854 | (if fortran-tab-mode | ||
| 855 | (goto-char (match-end 0)) | ||
| 856 | (delete-char 2) | ||
| 857 | (insert " ") | ||
| 858 | (insert fortran-continuation-string)) | ||
| 859 | (if (looking-at " [^ 0\n]") | ||
| 860 | (if fortran-tab-mode | ||
| 861 | (progn (delete-char 6) | ||
| 862 | (insert "\t") | ||
| 863 | (insert-char (fortran-numerical-continuation-char) 1)) | ||
| 864 | (forward-char 6)) | ||
| 865 | (delete-horizontal-space) | ||
| 866 | ;; Put line number in columns 0-4 | ||
| 867 | ;; or put continuation character in column 5. | ||
| 868 | (cond ((eobp)) | ||
| 869 | ((looking-at (regexp-quote fortran-continuation-string)) | ||
| 870 | (if fortran-tab-mode | ||
| 871 | (progn | ||
| 872 | (indent-to fortran-minimum-statement-indent) | ||
| 873 | (delete-char 1) | ||
| 874 | (insert-char (fortran-numerical-continuation-char) 1)) | ||
| 875 | (indent-to 5)) | ||
| 876 | (forward-char 1)) | ||
| 877 | ((looking-at "[0-9]+") | ||
| 878 | (let ((extra-space (- 5 (- (match-end 0) (point))))) | ||
| 879 | (if (< extra-space 0) | ||
| 880 | (message "Warning: line number exceeds 5-digit limit.") | ||
| 881 | (indent-to (min fortran-line-number-indent extra-space)))) | ||
| 882 | (skip-chars-forward "0-9"))))) | ||
| 883 | ;; Point is now after any continuation character or line number. | ||
| 884 | ;; Put body of statement where specified. | ||
| 885 | (delete-horizontal-space) | ||
| 886 | (indent-to col) | ||
| 887 | ;; Indent any comment following code on the same line. | ||
| 888 | (if (and comment-start-skip | ||
| 889 | (re-search-forward comment-start-skip | ||
| 890 | (save-excursion (end-of-line) (point)) t)) | ||
| 891 | (progn (goto-char (match-beginning 0)) | ||
| 892 | (if (not (= (current-column) (fortran-comment-hook))) | ||
| 893 | (progn (delete-horizontal-space) | ||
| 894 | (indent-to (fortran-comment-hook))))))))) | ||
| 895 | |||
| 896 | (defun fortran-line-number-indented-correctly-p () | ||
| 897 | "Return t if current line's line number is correctly indented. | ||
| 898 | Do not call if there is no line number." | ||
| 899 | (save-excursion | ||
| 900 | (beginning-of-line) | ||
| 901 | (skip-chars-forward " \t") | ||
| 902 | (and (<= (current-column) fortran-line-number-indent) | ||
| 903 | (or (= (current-column) fortran-line-number-indent) | ||
| 904 | (progn (skip-chars-forward "0-9") | ||
| 905 | (= (current-column) 5)))))) | ||
| 906 | |||
| 907 | (defun fortran-check-for-matching-do () | ||
| 908 | "When called from a numbered statement, returns t if matching 'do' is found. | ||
| 909 | Otherwise return a nil." | ||
| 910 | (let (charnum | ||
| 911 | (case-fold-search t)) | ||
| 912 | (save-excursion | ||
| 913 | (beginning-of-line) | ||
| 914 | (if (looking-at "[ \t]*[0-9]+") | ||
| 915 | (progn | ||
| 916 | (skip-chars-forward " \t") | ||
| 917 | (skip-chars-forward "0") ;skip past leading zeros | ||
| 918 | (setq charnum (buffer-substring (point) | ||
| 919 | (progn (skip-chars-forward "0-9") | ||
| 920 | (point)))) | ||
| 921 | (beginning-of-line) | ||
| 922 | (and (re-search-backward | ||
| 923 | (concat | ||
| 924 | "\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|\\(^[ \t0-9]*do[ \t]*0*" | ||
| 925 | charnum "\\b\\)\\|\\(^[ \t]*0*" charnum "\\b\\)") | ||
| 926 | nil t) | ||
| 927 | (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum)))))))) | ||
| 928 | |||
| 929 | (defun fortran-analyze-file-format () | ||
| 930 | "Return 0 if Fixed format is used, 1 if Tab formatting is used. | ||
| 931 | Use fortran-tab-mode-default if no non-comment statements are found in the | ||
| 932 | file before the end or the first fortran-analyze-depth lines." | ||
| 933 | (save-excursion | ||
| 934 | (goto-char (point-min)) | ||
| 935 | (setq i 0) | ||
| 936 | (while (not (or | ||
| 937 | (eobp) | ||
| 938 | (looking-at "\t") | ||
| 939 | (looking-at " ") | ||
| 940 | (> i fortran-analyze-depth))) | ||
| 941 | (forward-line) | ||
| 942 | (setq i (1+ i))) | ||
| 943 | (cond | ||
| 944 | ((looking-at "\t") 1) | ||
| 945 | ((looking-at " ") 0) | ||
| 946 | (fortran-tab-mode-default 1) | ||
| 947 | (t 0)))) | ||
| 948 | |||
| 949 | (defun fortran-tab-mode (arg) | ||
| 950 | "Toggle fortran-tab-mode which indicates style of continuation lines. | ||
| 951 | With no argument, toggle on/off the tabbing mode of continuation lines. | ||
| 952 | If argument is a positive number, or non-nil if not a number, fortran-tab-mode | ||
| 953 | is turned on. Otherwise | ||
| 954 | If `fortran-tab-mode' is false" | ||
| 955 | (interactive "P") | ||
| 956 | (setq fortran-tab-mode | ||
| 957 | (if (null arg) (not fortran-tab-mode) | ||
| 958 | (if (numberp arg) | ||
| 959 | (> (prefix-numeric-value arg) 0) | ||
| 960 | (arg)))) | ||
| 961 | (if fortran-tab-mode | ||
| 962 | (fortran-setup-tab-format-style) | ||
| 963 | (fortran-setup-fixed-format-style)) | ||
| 964 | (set-buffer-modified-p (buffer-modified-p))) ;No-op, but updates mode line. | ||
| 965 | |||
| 966 | (defun fortran-setup-tab-format-style () | ||
| 967 | "Set up fortran mode to use the TAB-digit mode of continuation lines. | ||
| 968 | Use the command fortran-tab-mode to toggle between this and fixed format style." | ||
| 969 | (setq fortran-comment-line-column (max tab-width 6)) | ||
| 970 | (setq fortran-minimum-statement-indent (max tab-width 6)) | ||
| 971 | (setq indent-tabs-mode t) | ||
| 972 | (setq fortran-column-ruler | ||
| 973 | (concat | ||
| 974 | "0 810 20 30 40 50 60 70\n" | ||
| 975 | "[ ]| { | | | | | | | | | | | | |}\n")) | ||
| 976 | (setq fortran-tab-mode-string " TAB-format") | ||
| 977 | (set-buffer-modified-p (buffer-modified-p))) | ||
| 978 | |||
| 979 | (defun fortran-setup-fixed-format-style () | ||
| 980 | "Set up fortran mode to use the column 6 mode of continuation lines. | ||
| 981 | Use the command fortran-tab-mode to toggle between this and tab | ||
| 982 | character format style." | ||
| 983 | (setq fortran-comment-line-column 6) | ||
| 984 | (setq fortran-minimum-statement-indent 6) | ||
| 985 | (setq indent-tabs-mode nil) | ||
| 986 | (setq fortran-column-ruler | ||
| 987 | (concat | ||
| 988 | "0 4 6 10 20 30 40 50 60 70\n" | ||
| 989 | "[ ]|{ | | | | | | | | | | | | |}\n")) | ||
| 990 | (setq fortran-tab-mode-string " Fixed-format") | ||
| 991 | (set-buffer-modified-p (buffer-modified-p))) | ||
| 992 | |||
| 993 | (or (assq 'fortran-tab-mode minor-mode-alist) | ||
| 994 | (setq minor-mode-alist (cons | ||
| 995 | '(fortran-tab-mode-string fortran-tab-mode-string) | ||
| 996 | minor-mode-alist))) | ||
| 997 | |||