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