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