(fortran-fill): Use local var `bol' rather than duplicate call to
[emacs.git] / lisp / progmodes / fortran.el
blob88d41650c0721a4fa3433bd682a86295310d2158
1 ;;; fortran.el --- Fortran mode for GNU Emacs
3 ;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 01, 03, 04
4 ;; Free Software Foundation, Inc.
6 ;; Author: Michael D. Prange <prange@erl.mit.edu>
7 ;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk>
8 ;; Keywords: fortran, languages
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
27 ;;; Commentary:
29 ;; This mode is documented in the Emacs manual.
31 ;; Note that it is for editing Fortran77 or Fortran90 fixed source
32 ;; form. For editing Fortran 90 free format source, use `f90-mode'
33 ;; (f90.el). It is meant to support the GNU Fortran language
34 ;; implemented by g77 (its extensions to Fortran77 and
35 ;; interpretations, e.g. of blackslash in strings).
37 ;;; History:
39 ;; Fortran mode was upgraded by Stephen A. Wood (saw@cebaf.gov).
41 ;; We acknowledge many contributions and valuable suggestions by
42 ;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea,
43 ;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon,
44 ;; Gary Sabot and Richard Stallman.
46 ;;; Code:
48 ;; Todo:
50 ;; * Tidy it all up (more)!
51 ;; * Implement insertion and removal of statement continuations in
52 ;; mixed f77/f90 style, with the first `&' past column 72 and the
53 ;; second in column 6.
54 ;; * Support any other extensions to f77 grokked by GNU Fortran I've missed.
56 (eval-when-compile ; silence compiler
57 (defvar dabbrev-case-fold-search)
58 (defvar imenu-case-fold-search)
59 (defvar imenu-syntax-alist))
62 (defgroup fortran nil
63 "Major mode for editing fixed format Fortran code."
64 :link '(custom-manual "(emacs)Fortran")
65 :group 'languages)
67 (defgroup fortran-indent nil
68 "Indentation variables in Fortran mode."
69 :prefix "fortran-"
70 :group 'fortran)
72 (defgroup fortran-comment nil
73 "Comment-handling variables in Fortran mode."
74 :prefix "fortran-"
75 :group 'fortran)
78 ;;;###autoload
79 (defcustom fortran-tab-mode-default nil
80 "*Default tabbing/carriage control style for empty files in Fortran mode.
81 A non-nil value specifies tab-digit style of continuation control.
82 A value of nil specifies that continuation lines are marked
83 with a character in column 6."
84 :type 'boolean
85 :group 'fortran-indent)
87 (defcustom fortran-tab-mode-string "/t"
88 "*String to appear in mode line in TAB format buffers."
89 :type 'string
90 :group 'fortran-indent)
92 (defcustom fortran-do-indent 3
93 "*Extra indentation applied to DO blocks."
94 :type 'integer
95 :group 'fortran-indent)
97 (defcustom fortran-if-indent 3
98 "*Extra indentation applied to IF blocks."
99 :type 'integer
100 :group 'fortran-indent)
102 (defcustom fortran-structure-indent 3
103 "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks."
104 :type 'integer
105 :group 'fortran-indent)
107 (defcustom fortran-continuation-indent 5
108 "*Extra indentation applied to continuation lines."
109 :type 'integer
110 :group 'fortran-indent)
112 (defcustom fortran-comment-indent-style 'fixed
113 "*How to indent comments.
114 nil forces comment lines not to be touched;
115 `fixed' indents to `fortran-comment-line-extra-indent' columns beyond
116 `fortran-minimum-statement-indent-fixed' (if `indent-tabs-mode' nil), or
117 `fortran-minimum-statement-indent-tab' (if `indent-tabs-mode' non-nil);
118 `relative' indents to current Fortran indentation plus
119 `fortran-comment-line-extra-indent'."
120 :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative))
121 :group 'fortran-indent)
123 (defcustom fortran-comment-line-extra-indent 0
124 "*Amount of extra indentation for text within full-line comments."
125 :type 'integer
126 :group 'fortran-indent
127 :group 'fortran-comment)
129 (defcustom fortran-comment-line-start "C"
130 "*Delimiter inserted to start new full-line comment.
131 You might want to change this to \"*\", for instance."
132 :version "21.1"
133 :type 'string
134 :group 'fortran-comment)
136 ;; This used to match preprocessor lines too, but that messes up
137 ;; filling and doesn't seem to be necessary.
138 (defcustom fortran-comment-line-start-skip
139 "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*"
140 "*Regexp to match the start of a full-line comment."
141 :version "21.1"
142 :type 'regexp
143 :group 'fortran-comment)
145 (defcustom fortran-directive-re
146 "^[ \t]*#.*"
147 "*Regexp to match a directive line.
148 The matching text will be fontified with `font-lock-keyword-face'.
149 The matching line will be given zero indentation."
150 :version "21.4"
151 :type 'regexp
152 :group 'fortran-indent)
154 (defcustom fortran-minimum-statement-indent-fixed 6
155 "*Minimum statement indentation for fixed format continuation style."
156 :type 'integer
157 :group 'fortran-indent)
159 (defcustom fortran-minimum-statement-indent-tab (max tab-width 6)
160 "*Minimum statement indentation for TAB format continuation style."
161 :type 'integer
162 :group 'fortran-indent)
164 ;; Note that this is documented in the v18 manuals as being a string
165 ;; of length one rather than a single character.
166 ;; The code in this file accepts either format for compatibility.
167 (defcustom fortran-comment-indent-char " "
168 "*Single-character string inserted for Fortran comment indentation.
169 Normally a space."
170 :type 'string
171 :group 'fortran-comment)
173 (defcustom fortran-line-number-indent 1
174 "*Maximum indentation for Fortran line numbers.
175 5 means right-justify them within their five-column field."
176 :type 'integer
177 :group 'fortran-indent)
179 (defcustom fortran-check-all-num-for-matching-do nil
180 "*Non-nil causes all numbered lines to be treated as possible DO loop ends."
181 :type 'boolean
182 :group 'fortran)
184 (defcustom fortran-blink-matching-if nil
185 "*Non-nil causes \\[fortran-indent-line] on ENDIF to blink on matching IF.
186 Also, from an ENDDO statement blink on matching DO [WHILE] statement."
187 :type 'boolean
188 :group 'fortran)
190 (defcustom fortran-continuation-string "$"
191 "*Single-character string used for Fortran continuation lines.
192 In fixed format continuation style, this character is inserted in
193 column 6 by \\[fortran-split-line] to begin a continuation line.
194 Also, if \\[fortran-indent-line] finds this at the beginning of a
195 line, it will convert the line into a continuation line of the
196 appropriate style. Normally $."
197 :type 'string
198 :group 'fortran)
200 (defcustom fortran-comment-region "c$$$"
201 "*String inserted by \\[fortran-comment-region] at start of each \
202 line in region."
203 :type 'string
204 :group 'fortran-comment)
206 (defcustom fortran-electric-line-number t
207 "*Non-nil causes line numbers to be moved to the correct column as typed."
208 :type 'boolean
209 :group 'fortran)
211 (defcustom fortran-column-ruler-fixed
212 "0 4 6 10 20 30 40 5\
213 0 60 70\n\
214 \[ ]|{ | | | | | | | | \
215 \| | | | |}\n"
216 "String displayed above current line by \\[fortran-column-ruler].
217 This variable is used in fixed format mode.
218 See the variable `fortran-column-ruler-tab' for TAB format mode."
219 :type 'string
220 :group 'fortran)
222 (defcustom fortran-column-ruler-tab
223 "0 810 20 30 40 5\
224 0 60 70\n\
225 \[ ]| { | | | | | | | | \
226 \| | | | |}\n"
227 "String displayed above current line by \\[fortran-column-ruler].
228 This variable is used in TAB format mode.
229 See the variable `fortran-column-ruler-fixed' for fixed format mode."
230 :type 'string
231 :group 'fortran)
233 (defcustom fortran-analyze-depth 100
234 "Number of lines to scan to identify fixed or TAB format style."
235 :type 'integer
236 :group 'fortran)
238 (defcustom fortran-break-before-delimiters t
239 "*Non-nil causes filling to break lines before delimiters.
240 Delimiters are characters matching the regexp `fortran-break-delimiters-re'."
241 :type 'boolean
242 :group 'fortran)
244 (defconst fortran-break-delimiters-re "[-+*/><=, \t]"
245 "Regexp matching delimiter characters at which lines may be broken.
246 There are certain tokens comprised entirely of characters
247 matching this regexp that should not be split, and these are
248 specified by the constant `fortran-no-break-re'.")
250 ;; The ">=", etc F77 extensions are supported by g77.
251 (defconst fortran-no-break-re
252 (regexp-opt '("**" "//" "=>" ">=" "<=" "==" "/=") 'paren)
253 "Regexp specifying where not to break lines when filling.
254 This regexp matches certain tokens comprised entirely of
255 characters matching the regexp `fortran-break-delimiters-re' that should
256 not be split by filling. Each element is assumed to be two
257 characters long.")
259 (defcustom fortran-mode-hook nil
260 "Hook run when entering Fortran mode."
261 :type 'hook
262 :group 'fortran)
265 (defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*("
266 "Regexp matching the start of an IF statement.")
268 (defvar fortran-end-prog-re1
269 "end\
270 \\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\
271 \\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?"
272 "Regexp possibly matching the end of a subprogram.")
274 (defvar fortran-end-prog-re
275 (concat "^[ \t0-9]*" fortran-end-prog-re1)
276 "Regexp possibly matching the end of a subprogram, from the line start.
277 See also `fortran-end-prog-re1'.")
279 (defconst fortran-type-types
280 (concat "\\<"
281 (mapconcat 'identity ; " " -> "[ \t]*"
282 (split-string
283 (regexp-opt
284 (let ((simple-types
285 '("character" "byte" "integer" "logical"
286 "none" "real" "complex"
287 "double precision" "double complex"))
288 (structured-types '("structure" "union" "map"))
289 (other-types '("record" "dimension"
290 "parameter" "common" "save"
291 "external" "intrinsic" "data"
292 "equivalence")))
293 (append
294 (mapcar (lambda (x) (concat "implicit " x))
295 simple-types)
296 simple-types
297 (mapcar (lambda (x) (concat "end " x))
298 structured-types)
299 structured-types
300 other-types)) 'paren))
301 "[ \t]*") "\\>")
302 "Regexp matching Fortran types.")
304 (defvar fortran-font-lock-keywords-1
305 ;; Program, subroutine and function declarations, plus calls.
306 '(("\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|\
307 program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?"
308 (1 font-lock-keyword-face)
309 (2 font-lock-function-name-face nil t)))
310 "Subdued level highlighting for Fortran mode.")
312 (defvar fortran-font-lock-keywords-2
313 (append fortran-font-lock-keywords-1
314 (list
315 ;; Fontify all type specifiers (must be first - see below).
316 (cons fortran-type-types 'font-lock-type-face)
317 ;; Builtin keywords (except logical, do and goto - see below).
318 (concat "\\<" (regexp-opt
319 '("continue" "format" "end" "enddo"
320 "if" "then" "else" "endif" "elseif"
321 "while" "inquire" "stop" "return"
322 "include" "open" "close" "read"
323 "write" "format" "print" "select" "case"
324 "cycle" "exit" "rewind" "backspace")
325 'paren) "\\>")
326 ;; Builtin operators.
327 (concat "\\." (regexp-opt
328 '("and" "or" "not" "lt" "le" "eq" "ge"
329 "gt" "ne" "true" "false")
330 'paren) "\\.")
331 ;; do/goto keywords and targets, and goto tags.
332 '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
333 (1 font-lock-keyword-face)
334 (2 font-lock-constant-face nil t))
335 '("^ *\\([0-9]+\\)" . font-lock-constant-face)))
336 "Medium level highlighting for Fortran mode.")
338 (defvar fortran-font-lock-keywords-3
339 (append
340 fortran-font-lock-keywords-1
341 ;; All type specifiers plus their declared items.
342 (list
343 (list (concat fortran-type-types "[ \t(/]*\\(*\\)?")
344 ;; Type specifier.
345 '(1 font-lock-type-face)
346 ;; Declaration item (or just /.../ block name).
347 `(font-lock-match-c-style-declaration-item-and-skip-to-next
348 ;; Start after any *(...) expression.
349 (condition-case nil
350 (and (match-beginning ,(1+ (regexp-opt-depth
351 fortran-type-types)))
352 (forward-sexp)
353 (forward-sexp))
354 (error nil))
355 ;; No need to clean up.
357 ;; Fontify as a variable name, functions fontified elsewhere.
358 (1 font-lock-variable-name-face nil t))))
359 ;; Things extra to `fortran-font-lock-keywords-3' (must be done first).
360 (list
361 ;; Goto-like `err=label'/`end=label' in read/write statements.
362 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
363 (1 font-lock-keyword-face) (4 font-lock-constant-face nil t))
364 ;; Standard continuation character and in a TAB-formatted line.
365 '("^ \\{5\\}\\([^ 0\n]\\)" 1 font-lock-string-face)
366 '("^\t\\([1-9]\\)" 1 font-lock-string-face))
367 `((,fortran-directive-re (0 font-lock-keyword-face t)))
368 ;; `fortran-font-lock-keywords-2' without types (see above).
369 (cdr (nthcdr (length fortran-font-lock-keywords-1)
370 fortran-font-lock-keywords-2)))
371 "Gaudy level highlighting for Fortran mode.")
373 ;; Comments are real pain in Fortran because there is no way to
374 ;; represent the standard comment syntax in an Emacs syntax table.
375 ;; (We can do so for F90-style). Therefore an unmatched quote in a
376 ;; standard comment will throw fontification off on the wrong track.
377 ;; So we do syntactic fontification with regexps.
378 (defvar fortran-font-lock-syntactic-keywords
379 '(("^[cd\\*]" 0 (11))
380 ("^[^cd\\*\t\n].\\{71\\}\\([^\n]+\\)" 1 (11)))
381 "`font-lock-syntactic-keywords' for Fortran.
382 These get fixed-format comments fontified.")
384 (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
385 "Default expressions to highlight in Fortran mode.")
387 (defvar fortran-imenu-generic-expression
388 ;; These patterns could be confused by sequence nos. in cols 72+ and
389 ;; don't allow continuations everywhere.
390 (list
391 (list
393 ;; [This will be fooled by `end function' allowed by G77. Also,
394 ;; it assumes sensible whitespace is employed.]
395 (concat
396 ;; leading whitespace:
397 "^\\s-+\\("
398 ;; function declaration with optional type, e.g. `real',
399 ;; `real*4', character(*), `double precision':
400 "\\(\\sw\\|\\s-\\|[*()+]\\)*"
401 "\\<function\\|subroutine\\|entry\\|block\\s-*data\\|program\\)"
402 ;; Possible statement continuation:
403 "[ \t" fortran-continuation-string "]+"
404 ;; Variable to index:
405 "\\(\\sw+\\)")
407 ;; Un-named block data.
408 '(nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1))
409 "Value for `imenu-generic-expression' in Fortran mode.")
412 (defvar fortran-mode-syntax-table
413 (let ((table (make-syntax-table)))
414 ;; We might like `;' to be punctuation (g77 multi-statement
415 ;; lines), but that screws abbrevs.
416 (modify-syntax-entry ?\; "w" table)
417 (modify-syntax-entry ?\r " " table)
418 (modify-syntax-entry ?+ "." table)
419 (modify-syntax-entry ?- "." table)
420 (modify-syntax-entry ?= "." table)
421 (modify-syntax-entry ?* "." table)
422 (modify-syntax-entry ?/ "." table)
423 (modify-syntax-entry ?\' "\"" table)
424 (modify-syntax-entry ?\" "\"" table)
425 ;; Consistent with GNU Fortran -- see the manual.
426 (modify-syntax-entry ?\\ "\\" table)
427 ;; This might be better as punctuation, as for C, but this way you
428 ;; can treat floating-point numbers as symbols.
429 (modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b'
430 (modify-syntax-entry ?_ "_" table)
431 (modify-syntax-entry ?$ "_" table) ; esp. VMSisms
432 (modify-syntax-entry ?\! "<" table)
433 (modify-syntax-entry ?\n ">" table)
434 table)
435 "Syntax table used in Fortran mode.")
437 (defvar fortran-gud-syntax-table
438 (let ((st (make-syntax-table fortran-mode-syntax-table)))
439 (modify-syntax-entry ?\n "." st)
441 "Syntax table used to parse Fortran expressions for printing in GUD.")
443 (defvar fortran-mode-map
444 (let ((map (make-sparse-keymap)))
445 (define-key map ";" 'fortran-abbrev-start)
446 (define-key map "\C-c;" 'fortran-comment-region)
447 (define-key map "\M-;" 'fortran-indent-comment)
448 (define-key map "\M-\n" 'fortran-split-line)
449 (define-key map "\M-\C-q" 'fortran-indent-subprogram)
450 (define-key map "\C-c\C-w" 'fortran-window-create-momentarily)
451 (define-key map "\C-c\C-r" 'fortran-column-ruler)
452 (define-key map "\C-c\C-p" 'fortran-previous-statement)
453 (define-key map "\C-c\C-n" 'fortran-next-statement)
454 (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90
455 (define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation
456 (define-key map "0" 'fortran-electric-line-number)
457 (define-key map "1" 'fortran-electric-line-number)
458 (define-key map "2" 'fortran-electric-line-number)
459 (define-key map "3" 'fortran-electric-line-number)
460 (define-key map "4" 'fortran-electric-line-number)
461 (define-key map "5" 'fortran-electric-line-number)
462 (define-key map "6" 'fortran-electric-line-number)
463 (define-key map "7" 'fortran-electric-line-number)
464 (define-key map "8" 'fortran-electric-line-number)
465 (define-key map "9" 'fortran-electric-line-number)
467 (easy-menu-define fortran-menu map "Menu for Fortran mode."
468 `("Fortran"
469 ["Manual" (info "(emacs)Fortran")]
470 ("Customization"
471 ,(custom-menu-create 'fortran)
472 ["Set" Custom-set t]
473 ["Save" Custom-save t]
474 ["Reset to Current" Custom-reset-current t]
475 ["Reset to Saved" Custom-reset-saved t]
476 ["Reset to Standard Settings" Custom-reset-standard t]
478 "--"
479 ["Comment Region" fortran-comment-region mark-active]
480 ["Uncomment Region"
481 (fortran-comment-region (region-beginning) (region-end) 1)
482 mark-active]
483 ["Indent Region" indent-region mark-active]
484 ["Indent Subprogram" fortran-indent-subprogram t]
485 "--"
486 ["Beginning of Subprogram" fortran-beginning-of-subprogram t]
487 ["End of Subprogram" fortran-end-of-subprogram t]
488 ("Mark"
489 ["Subprogram" mark-defun t]
490 ["IF Block" fortran-mark-if t]
491 ["DO Block" fortran-mark-do t]
493 ["Narrow to Subprogram" narrow-to-defun t]
494 ["Widen" widen t]
495 "--"
496 ["Temporary column ruler" fortran-column-ruler t]
497 ["72-column window" fortran-window-create t]
498 ["Full Width Window"
499 (enlarge-window-horizontally (- (frame-width) (window-width)))
500 (< (window-width) (frame-width))]
501 ["Momentary 72-column window" fortran-window-create-momentarily t]
502 "--"
503 ["Break Line at Point" fortran-split-line t]
504 ["Join Line" fortran-join-line t]
505 ["Fill Statement/Comment" fill-paragraph t]
506 "--"
507 ["Toggle auto-fill" auto-fill-mode :selected auto-fill-function
508 :style toggle]
509 ["Toggle abbrev-mode" abbrev-mode :selected abbrev-mode
510 :style toggle]
511 ["Add imenu Menu" imenu-add-menubar-index
512 :active (not (lookup-key (current-local-map) [menu-bar index]))
513 :included (fboundp 'imenu-add-to-menubar)]))
514 map)
515 "Keymap used in Fortran mode.")
518 (defvar fortran-mode-abbrev-table
519 (let (abbrevs-changed)
520 (define-abbrev-table 'fortran-mode-abbrev-table nil)
521 ;; Use the 6th arg (SYSTEM-FLAG) of define-abbrev if possible.
522 ;; Only use `apply' to quieten the byte-compiler.
523 (mapcar
524 (function (lambda (element)
525 (condition-case nil
526 (apply 'define-abbrev fortran-mode-abbrev-table
527 (append element '(nil 0 t)))
528 (wrong-number-of-arguments
529 (apply 'define-abbrev fortran-mode-abbrev-table
530 (append element '(nil 0)))))))
531 '((";au" "automatic" )
532 (";b" "byte" )
533 (";bd" "block data" )
534 (";ch" "character" )
535 (";cl" "close" )
536 (";c" "continue" )
537 (";cm" "common" )
538 (";cx" "complex" )
539 (";df" "define" )
540 (";di" "dimension" )
541 (";do" "double" )
542 (";dc" "double complex" )
543 (";dp" "double precision" )
544 (";dw" "do while" )
545 (";e" "else" )
546 (";ed" "enddo" )
547 (";el" "elseif" )
548 (";en" "endif" )
549 (";eq" "equivalence" )
550 (";ew" "endwhere" )
551 (";ex" "external" )
552 (";ey" "entry" )
553 (";f" "format" )
554 (";fa" ".false." )
555 (";fu" "function" )
556 (";g" "goto" )
557 (";im" "implicit" )
558 (";ib" "implicit byte" )
559 (";ic" "implicit complex" )
560 (";ich" "implicit character")
561 (";ii" "implicit integer" )
562 (";il" "implicit logical" )
563 (";ir" "implicit real" )
564 (";inc" "include" )
565 (";in" "integer" )
566 (";intr" "intrinsic" )
567 (";l" "logical" )
568 (";n" "namelist" )
569 (";o" "open" ) ; was ;op
570 (";pa" "parameter" )
571 (";pr" "program" )
572 (";ps" "pause" )
573 (";p" "print" )
574 (";rc" "record" )
575 (";re" "real" )
576 (";r" "read" )
577 (";rt" "return" )
578 (";rw" "rewind" )
579 (";s" "stop" )
580 (";sa" "save" )
581 (";st" "structure" )
582 (";sc" "static" )
583 (";su" "subroutine" )
584 (";tr" ".true." )
585 (";ty" "type" )
586 (";vo" "volatile" )
587 (";w" "write" )
588 (";wh" "where" )))
589 fortran-mode-abbrev-table))
593 ;;;###autoload
594 (defun fortran-mode ()
595 "Major mode for editing Fortran code in fixed format.
596 For free format code, use `f90-mode'.
598 \\[fortran-indent-line] indents the current Fortran line correctly.
599 Note that DO statements must not share a common CONTINUE.
601 Type ;? or ;\\[help-command] to display a list of built-in abbrevs for\
602 Fortran keywords.
604 Key definitions:
605 \\{fortran-mode-map}
607 Variables controlling indentation style and extra features:
609 `comment-start'
610 To use comments starting with `!', set this to the string \"!\".
611 `fortran-do-indent'
612 Extra indentation within DO blocks (default 3).
613 `fortran-if-indent'
614 Extra indentation within IF blocks (default 3).
615 `fortran-structure-indent'
616 Extra indentation within STRUCTURE, UNION, MAP and INTERFACE blocks.
617 (default 3)
618 `fortran-continuation-indent'
619 Extra indentation applied to continuation statements (default 5).
620 `fortran-comment-line-extra-indent'
621 Amount of extra indentation for text in full-line comments (default 0).
622 `fortran-comment-indent-style'
623 How to indent the text in full-line comments. Allowed values are:
624 nil don't change the indentation
625 fixed indent to `fortran-comment-line-extra-indent' beyond the
626 value of either
627 `fortran-minimum-statement-indent-fixed' (fixed format) or
628 `fortran-minimum-statement-indent-tab' (TAB format),
629 depending on the continuation format in use.
630 relative indent to `fortran-comment-line-extra-indent' beyond the
631 indentation for a line of code.
632 (default 'fixed)
633 `fortran-comment-indent-char'
634 Single-character string to be inserted instead of space for
635 full-line comment indentation (default \" \").
636 `fortran-minimum-statement-indent-fixed'
637 Minimum indentation for statements in fixed format mode (default 6).
638 `fortran-minimum-statement-indent-tab'
639 Minimum indentation for statements in TAB format mode (default 9).
640 `fortran-line-number-indent'
641 Maximum indentation for line numbers (default 1). A line number will
642 get less than this much indentation if necessary to avoid reaching
643 column 5.
644 `fortran-check-all-num-for-matching-do'
645 Non-nil causes all numbered lines to be treated as possible \"continue\"
646 statements (default nil).
647 `fortran-blink-matching-if'
648 Non-nil causes \\[fortran-indent-line] on an ENDIF (or ENDDO) statement
649 to blink on the matching IF (or DO [WHILE]). (default nil)
650 `fortran-continuation-string'
651 Single-character string to be inserted in column 5 of a continuation
652 line (default \"$\").
653 `fortran-comment-region'
654 String inserted by \\[fortran-comment-region] at start of each line in
655 the region (default \"c$$$\").
656 `fortran-electric-line-number'
657 Non-nil causes line number digits to be moved to the correct column
658 as typed (default t).
659 `fortran-break-before-delimiters'
660 Non-nil causes lines to be broken before delimiters (default t).
662 Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
663 with no args, if that value is non-nil."
664 (interactive)
665 (kill-all-local-variables)
666 (setq major-mode 'fortran-mode
667 mode-name "Fortran"
668 local-abbrev-table fortran-mode-abbrev-table)
669 (set-syntax-table fortran-mode-syntax-table)
670 (use-local-map fortran-mode-map)
671 (set (make-local-variable 'indent-line-function) 'fortran-indent-line)
672 (set (make-local-variable 'indent-region-function)
673 (lambda (start end)
674 (let (fortran-blink-matching-if ; avoid blinking delay
675 indent-region-function)
676 (indent-region start end nil))))
677 (set (make-local-variable 'require-final-newline) t)
678 ;; The syntax tables don't understand the column-0 comment-markers.
679 (set (make-local-variable 'comment-use-syntax) nil)
680 (set (make-local-variable 'comment-padding) "$$$")
681 (set (make-local-variable 'comment-start) fortran-comment-line-start)
682 (set (make-local-variable 'comment-start-skip)
683 ;; We can't reuse `fortran-comment-line-start-skip' directly because
684 ;; it contains backrefs whereas we need submatch-1 to end at the
685 ;; beginning of the comment delimiter.
686 ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)")
687 "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*")
688 (set (make-local-variable 'comment-indent-function) 'fortran-comment-indent)
689 (set (make-local-variable 'abbrev-all-caps) t)
690 (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill)
691 (set (make-local-variable 'indent-tabs-mode) (fortran-analyze-file-format))
692 (setq mode-line-process '(indent-tabs-mode fortran-tab-mode-string))
693 (set (make-local-variable 'fill-column) 72)
694 (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph)
695 (set (make-local-variable 'font-lock-defaults)
696 '((fortran-font-lock-keywords
697 fortran-font-lock-keywords-1
698 fortran-font-lock-keywords-2
699 fortran-font-lock-keywords-3)
700 nil t ((?/ . "$/") ("_$" . "w"))
701 fortran-beginning-of-subprogram))
702 (set (make-local-variable 'font-lock-syntactic-keywords)
703 fortran-font-lock-syntactic-keywords)
704 (set (make-local-variable 'imenu-case-fold-search) t)
705 (set (make-local-variable 'imenu-generic-expression)
706 fortran-imenu-generic-expression)
707 (set (make-local-variable 'imenu-syntax-alist) '(("_$" . "w")))
708 (set (make-local-variable 'beginning-of-defun-function)
709 #'fortran-beginning-of-subprogram)
710 (set (make-local-variable 'end-of-defun-function)
711 #'fortran-end-of-subprogram)
712 (set (make-local-variable 'add-log-current-defun-function)
713 #'fortran-current-defun)
714 (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search)
715 (set (make-local-variable 'gud-find-expr-function) 'fortran-gud-find-expr)
716 (run-hooks 'fortran-mode-hook))
719 (defun fortran-gud-find-expr ()
720 ;; Consider \n as punctuation (end of expression).
721 (with-syntax-table fortran-gud-syntax-table
722 (gud-find-c-expr)))
724 (defsubst fortran-comment-indent ()
725 "Return the indentation appropriate for the current comment line.
726 This is 0 for a line matching `fortran-comment-line-start-skip', else
727 the value of `comment-column' (leaving at least one space after code)."
728 (if (looking-at fortran-comment-line-start-skip) 0
729 (save-excursion
730 (skip-chars-backward " \t")
731 (max (1+ (current-column)) comment-column))))
733 (defun fortran-indent-comment ()
734 "Align or create comment on current line.
735 Existing comments of all types are recognized and aligned.
736 If the line has no comment, a side-by-side comment is inserted and aligned,
737 if the value of `comment-start' is not nil and allows such comments.
738 Otherwise, a separate-line comment is inserted, on this line
739 or on a new line inserted before this line if this line is not blank."
740 (interactive "*")
741 (beginning-of-line)
742 ;; Recognize existing comments of either kind.
743 (cond ((fortran-find-comment-start-skip 'all)
744 (goto-char (match-beginning 0))
745 (if (bolp)
746 (fortran-indent-line)
747 (unless (= (current-column) (fortran-comment-indent))
748 (delete-horizontal-space)
749 (indent-to (fortran-comment-indent)))))
750 ;; No existing comment.
751 ;; If side-by-side comments are defined, insert one,
752 ;; unless line is now blank.
753 ((and comment-start (not (looking-at "[ \t]*$"))
754 (string-match comment-start-skip (concat " " comment-start)))
755 (end-of-line)
756 (delete-horizontal-space)
757 (indent-to (fortran-comment-indent))
758 (insert comment-start))
759 ;; Else insert separate-line comment, making a new line if nec.
761 (if (looking-at "^[ \t]*$")
762 (delete-horizontal-space)
763 (beginning-of-line)
764 (insert ?\n)
765 (forward-char -1))
766 (insert fortran-comment-line-start)
767 (insert-char (if (stringp fortran-comment-indent-char)
768 (aref fortran-comment-indent-char 0)
769 fortran-comment-indent-char)
770 (- (fortran-calculate-indent) (current-column))))))
772 (defun fortran-comment-region (beg-region end-region arg)
773 "Comment every line in the region.
774 Inserts the string variable `fortran-comment-region' at the beginning of
775 every line in the region.
776 BEG-REGION and END-REGION specify the region boundaries.
777 With non-nil ARG, uncomments the region."
778 (interactive "*r\nP")
779 (let ((end-region-mark (copy-marker end-region))
780 (save-point (point-marker)))
781 (goto-char beg-region)
782 (beginning-of-line)
783 (if arg
784 (let ((com (regexp-quote fortran-comment-region))) ; uncomment
785 (if (looking-at com)
786 (delete-region (point) (match-end 0)))
787 (while (and (zerop (forward-line 1))
788 (< (point) end-region-mark))
789 (if (looking-at com)
790 (delete-region (point) (match-end 0)))))
791 (insert fortran-comment-region) ; comment
792 (while (and (zerop (forward-line 1))
793 (< (point) end-region-mark))
794 (insert fortran-comment-region)))
795 (goto-char save-point)
796 (set-marker end-region-mark nil)
797 (set-marker save-point nil)))
800 (defun fortran-abbrev-start ()
801 "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs.
802 Any other key combination is executed normally."
803 (interactive "*")
804 (insert last-command-char)
805 (let (char event)
806 (if (fboundp 'next-command-event) ; XEmacs
807 (setq event (next-command-event)
808 char (event-to-character event))
809 (setq event (read-event)
810 char event))
811 ;; Insert char if not equal to `?', or if abbrev-mode is off.
812 (if (and abbrev-mode (or (eq char ??) (eq char help-char)))
813 (fortran-abbrev-help)
814 (setq unread-command-events (list event)))))
816 (defun fortran-abbrev-help ()
817 "List the currently defined abbrevs in Fortran mode."
818 (interactive)
819 (message "Listing abbrev table...")
820 (display-buffer (fortran-prepare-abbrev-list-buffer))
821 (message "Listing abbrev table...done"))
823 (defun fortran-prepare-abbrev-list-buffer ()
824 "Create a buffer listing the Fortran mode abbreviations."
825 (save-excursion
826 (set-buffer (get-buffer-create "*Abbrevs*"))
827 (erase-buffer)
828 (insert-abbrev-table-description 'fortran-mode-abbrev-table t)
829 (goto-char (point-min))
830 (set-buffer-modified-p nil)
831 (edit-abbrevs-mode))
832 (get-buffer-create "*Abbrevs*"))
834 (defun fortran-column-ruler ()
835 "Insert a column ruler momentarily above current line, till next keystroke.
836 The ruler is defined by the value of `fortran-column-ruler-fixed' in fixed
837 format mode, and `fortran-column-ruler-tab' in TAB format mode.
838 The next key typed is executed unless it is SPC."
839 (interactive)
840 (momentary-string-display
841 (if indent-tabs-mode
842 fortran-column-ruler-tab
843 fortran-column-ruler-fixed)
844 (save-excursion
845 (beginning-of-line)
846 (if (eq (window-start (selected-window))
847 (window-point (selected-window)))
848 (line-beginning-position 2)
849 (point)))
850 nil "Type SPC or any command to erase ruler."))
852 (defun fortran-window-create ()
853 "Make the window 72 columns wide.
854 See also `fortran-window-create-momentarily'."
855 (interactive)
856 (let ((window-min-width 2))
857 (if (< (window-width) (frame-width))
858 (enlarge-window-horizontally (- (frame-width)
859 (window-width) 1)))
860 (let* ((window-edges (window-edges))
861 (scroll-bar-width (- (nth 2 window-edges)
862 (car window-edges)
863 (window-width))))
864 (split-window-horizontally (+ 72 scroll-bar-width)))
865 (other-window 1)
866 (switch-to-buffer " fortran-window-extra" t)
867 (select-window (previous-window))))
869 (defun fortran-window-create-momentarily (&optional arg)
870 "Momentarily make the window 72 columns wide.
871 Optional ARG non-nil and non-unity disables the momentary feature.
872 See also `fortran-window-create'."
873 (interactive "p")
874 (if (or (not arg)
875 (= arg 1))
876 (save-window-excursion
877 (progn
878 (condition-case nil
879 (fortran-window-create)
880 (error (error "No room for Fortran window")))
881 (message "Type SPC to continue editing.")
882 (let ((char (read-event)))
883 (or (equal char (string-to-char " "))
884 (setq unread-command-events (list char))))))
885 (fortran-window-create)))
887 (defun fortran-split-line ()
888 "Break line at point and insert continuation marker and alignment."
889 (interactive "*")
890 (delete-horizontal-space)
891 (if (save-excursion
892 (let ((pos (point)))
893 (beginning-of-line)
894 (and (fortran-find-comment-start-skip 'all)
895 (< (match-beginning 0) pos))))
896 (insert ?\n (match-string 0))
897 (if indent-tabs-mode
898 (insert ?\n ?\t (fortran-numerical-continuation-char))
899 (insert "\n " fortran-continuation-string))) ; space after \n important
900 (fortran-indent-line)) ; when cont string is C, c or *
902 (defun fortran-remove-continuation ()
903 "Delete any Fortran continuation characters at point.
904 Returns t if anything actually deleted."
905 (when (looking-at "\\( \\{5\\}[^ 0\n]\\|\t[1-9]\\|&\\)")
906 (replace-match "")
907 (delete-indentation)
910 (defun fortran-join-line (arg)
911 "Join current line to the previous one and re-indent.
912 With a prefix argument, repeat this operation that many times.
913 If the prefix argument ARG is negative, join the next -ARG lines.
914 Continuation lines are correctly handled."
915 (interactive "*p")
916 (save-excursion
917 (when (> 0 arg)
918 (setq arg (- arg))
919 (forward-line arg))
920 (while (not (zerop arg))
921 (beginning-of-line)
922 (or (fortran-remove-continuation)
923 (delete-indentation))
924 (setq arg (1- arg)))
925 (fortran-indent-line)))
927 (defun fortran-numerical-continuation-char ()
928 "Return a digit for tab-digit style of continuation lines.
929 If previous line is a tab-digit continuation line, return that digit
930 plus one, otherwise return 1. Zero not allowed."
931 (save-excursion
932 (forward-line -1)
933 (if (looking-at "\t[1-9]")
934 (+ ?1 (% (- (char-after (1+ (point))) ?0) 9))
935 ?1)))
937 (put 'fortran-electric-line-number 'delete-selection t)
938 (defun fortran-electric-line-number (arg)
939 "Self insert, but if part of a Fortran line number indent it automatically.
940 Auto-indent does not happen if a numeric ARG is used."
941 (interactive "*P")
942 (if (or arg (not fortran-electric-line-number))
943 (if arg
944 (self-insert-command (prefix-numeric-value arg))
945 (self-insert-command 1))
946 (if (or (and (= 5 (current-column))
947 (save-excursion
948 (beginning-of-line)
949 ;; In col 5 with only spaces to the left.
950 (looking-at " \\{5\\}")))
951 (and (= (if indent-tabs-mode
952 fortran-minimum-statement-indent-tab
953 fortran-minimum-statement-indent-fixed) (current-column))
954 ;; In col 8 with a single tab to the left.
955 (eq ?\t (char-after (line-beginning-position)))
956 (not (or (eq last-command 'fortran-indent-line)
957 (eq last-command
958 'fortran-indent-new-line))))
959 (save-excursion
960 (re-search-backward "[^ \t0-9]"
961 (line-beginning-position)
962 t)) ; not a line number
963 (looking-at "[0-9]")) ; within a line number
964 (self-insert-command (prefix-numeric-value arg))
965 (skip-chars-backward " \t")
966 (insert last-command-char)
967 (fortran-indent-line))))
970 (defun fortran-check-end-prog-re ()
971 "Check a preliminary match against `fortran-end-prog-re'."
972 ;; Having got a possible match for the subprogram end, we need a
973 ;; match of whitespace, avoiding possible column 73+ stuff.
974 (save-match-data
975 (string-match "^\\s-*\\(\\'\\|\\s<\\)"
976 (buffer-substring (match-end 0)
977 (min (line-end-position)
978 (+ 72 (line-beginning-position)))))))
980 ;; Note that you can't just check backwards for `subroutine' &c in
981 ;; case of un-marked main programs not at the start of the file.
982 (defun fortran-beginning-of-subprogram ()
983 "Move point to the beginning of the current Fortran subprogram."
984 (interactive)
985 (save-match-data
986 (let ((case-fold-search t))
987 (beginning-of-line -1)
988 (if (catch 'ok
989 (while (re-search-backward fortran-end-prog-re nil 'move)
990 (if (fortran-check-end-prog-re)
991 (throw 'ok t))))
992 (forward-line)))))
994 (defun fortran-end-of-subprogram ()
995 "Move point to the end of the current Fortran subprogram."
996 (interactive)
997 (save-match-data
998 (let ((case-fold-search t))
999 (if (save-excursion ; on END
1000 (beginning-of-line)
1001 (and (looking-at fortran-end-prog-re)
1002 (fortran-check-end-prog-re)))
1003 (forward-line)
1004 (beginning-of-line 2)
1005 (catch 'ok
1006 (while (re-search-forward fortran-end-prog-re nil 'move)
1007 (if (fortran-check-end-prog-re)
1008 (throw 'ok t))))
1009 (goto-char (match-beginning 0))
1010 (forward-line)))))
1012 (defun fortran-previous-statement ()
1013 "Move point to beginning of the previous Fortran statement.
1014 Returns 'first-statement if that statement is the first
1015 non-comment Fortran statement in the file, and nil otherwise.
1016 Directive lines are treated as comments."
1017 (interactive)
1018 (let (not-first-statement continue-test)
1019 (beginning-of-line)
1020 (setq continue-test
1021 (and
1022 (not (looking-at fortran-comment-line-start-skip))
1023 (not (looking-at fortran-directive-re))
1024 (or (looking-at
1025 (concat "[ \t]*"
1026 (regexp-quote fortran-continuation-string)))
1027 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))))
1028 (while (and (setq not-first-statement (zerop (forward-line -1)))
1029 (or (looking-at fortran-comment-line-start-skip)
1030 (looking-at fortran-directive-re)
1031 (looking-at
1032 (concat "[ \t]*"
1033 (regexp-quote fortran-continuation-string)))
1034 (looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]")
1035 (looking-at (concat "[ \t]*" comment-start-skip)))))
1036 (cond ((and continue-test
1037 (not not-first-statement))
1038 (message "Incomplete continuation statement."))
1039 (continue-test
1040 (fortran-previous-statement))
1041 ((not not-first-statement)
1042 'first-statement))))
1044 (defun fortran-next-statement ()
1045 "Move point to beginning of the next Fortran statement.
1046 Returns 'last-statement if that statement is the last
1047 non-comment Fortran statement in the file, and nil otherwise.
1048 Directive lines are treated as comments."
1049 (interactive)
1050 (let (not-last-statement)
1051 (beginning-of-line)
1052 (while (and (setq not-last-statement
1053 (and (zerop (forward-line 1))
1054 (not (eobp))))
1055 (or (looking-at fortran-comment-line-start-skip)
1056 (looking-at fortran-directive-re)
1057 (looking-at "[ \t]*$\\| [^ 0\n]\\|\t[1-9]")
1058 (looking-at (concat "[ \t]*" comment-start-skip)))))
1059 (if (not not-last-statement)
1060 'last-statement)))
1063 (defun fortran-blink-match (regex keyword find-begin)
1064 "From a line matching REGEX, blink matching KEYWORD statement line.
1065 Use function FIND-BEGIN to match it."
1066 (let ((top-of-window (window-start))
1067 (end-point (point))
1068 (case-fold-search t)
1069 matching
1070 message)
1071 (when (save-excursion
1072 (beginning-of-line)
1073 (skip-chars-forward " \t0-9")
1074 (looking-at regex))
1075 (if (not (setq matching (funcall find-begin)))
1076 (setq message (concat "No matching " keyword "."))
1077 (if (< matching top-of-window)
1078 (save-excursion
1079 (goto-char matching)
1080 (beginning-of-line)
1081 (setq message
1082 (concat "Matches "
1083 (buffer-substring (point)
1084 (line-end-position)))))))
1085 (if message
1086 (message "%s" message)
1087 (goto-char matching)
1088 (sit-for 1)
1089 (goto-char end-point)))))
1091 (defun fortran-blink-matching-if ()
1092 "From an ENDIF or ELSE statement, blink the matching IF statement."
1093 (fortran-blink-match "e\\(nd[ \t]*if\\|lse\\([ \t]*if\\)?\\)\\b"
1094 "if" #'fortran-beginning-if))
1096 (defun fortran-blink-matching-do ()
1097 "From an ENDDO statement, blink the matching DO or DO WHILE statement."
1098 (fortran-blink-match "end[ \t]*do\\b" "do" #'fortran-beginning-do))
1100 (defun fortran-mark-do ()
1101 "Put mark at end of Fortran DO [WHILE]-ENDDO construct, point at beginning.
1102 The marks are pushed."
1103 (interactive)
1104 (let (enddo-point do-point)
1105 (if (setq enddo-point (fortran-end-do))
1106 (if (not (setq do-point (fortran-beginning-do)))
1107 (message "No matching do.")
1108 (goto-char enddo-point)
1109 (push-mark)
1110 (goto-char do-point)))))
1112 (defun fortran-end-do ()
1113 "Search forward for first unmatched ENDDO.
1114 Return point or nil."
1115 (let ((case-fold-search t))
1116 (if (save-excursion (beginning-of-line)
1117 (skip-chars-forward " \t0-9")
1118 (looking-at "end[ \t]*do\\b"))
1119 ;; Sitting on one.
1120 (match-beginning 0)
1121 ;; Search for one.
1122 (save-excursion
1123 (let ((count 1))
1124 (while (and (not (zerop count))
1125 (not (eq (fortran-next-statement) 'last-statement))
1126 ;; Keep local to subprogram.
1127 (not (and (looking-at fortran-end-prog-re)
1128 (fortran-check-end-prog-re))))
1129 (skip-chars-forward " \t0-9")
1130 (cond ((looking-at "end[ \t]*do\\b")
1131 (setq count (1- count)))
1132 ((looking-at
1133 "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]")
1134 (setq count (1+ count)))))
1135 (and (zerop count)
1136 ;; All pairs accounted for.
1137 (point)))))))
1139 (defun fortran-beginning-do ()
1140 "Search backwards for first unmatched DO [WHILE].
1141 Return point or nil. Ignores labelled DO loops (ie DO 10 ... 10 CONTINUE)."
1142 (let ((case-fold-search t)
1143 (dostart-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]"))
1144 (if (save-excursion
1145 (beginning-of-line)
1146 (skip-chars-forward " \t0-9")
1147 (looking-at dostart-re))
1148 ;; Sitting on one.
1149 (match-beginning 0)
1150 ;; Search for one.
1151 (save-excursion
1152 (let ((count 1))
1153 (while (and (not (zerop count))
1154 (not (eq (fortran-previous-statement) 'first-statement))
1155 ;; Keep local to subprogram.
1156 (not (and (looking-at fortran-end-prog-re)
1157 (fortran-check-end-prog-re))))
1158 (skip-chars-forward " \t0-9")
1159 (cond ((looking-at dostart-re)
1160 (setq count (1- count)))
1161 ;; Note labelled loop ends not considered.
1162 ((looking-at "end[ \t]*do\\b")
1163 (setq count (1+ count)))))
1164 (and (zerop count)
1165 ;; All pairs accounted for.
1166 (point)))))))
1168 (defun fortran-mark-if ()
1169 "Put mark at end of Fortran IF-ENDIF construct, point at beginning.
1170 The marks are pushed."
1171 (interactive)
1172 (let (endif-point if-point)
1173 (if (setq endif-point (fortran-end-if))
1174 (if (not (setq if-point (fortran-beginning-if)))
1175 (message "No matching if.")
1176 ;; Set mark, move point.
1177 (goto-char endif-point)
1178 (push-mark)
1179 (goto-char if-point)))))
1181 (defun fortran-end-if ()
1182 "Search forwards for first unmatched ENDIF.
1183 Return point or nil."
1184 (let ((case-fold-search t))
1185 (if (save-excursion (beginning-of-line)
1186 (skip-chars-forward " \t0-9")
1187 (looking-at "end[ \t]*if\\b"))
1188 ;; Sitting on one.
1189 (match-beginning 0)
1190 ;; Search for one. The point has been already been moved to first
1191 ;; letter on line but this should not cause troubles.
1192 (save-excursion
1193 (let ((count 1))
1194 (while (and (not (zerop count))
1195 (not (eq (fortran-next-statement) 'last-statement))
1196 ;; Keep local to subprogram.
1197 (not (and (looking-at fortran-end-prog-re)
1198 (fortran-check-end-prog-re))))
1199 (skip-chars-forward " \t0-9")
1200 (cond ((looking-at "end[ \t]*if\\b")
1201 (setq count (1- count)))
1202 ((looking-at fortran-if-start-re)
1203 (save-excursion
1204 (if (or
1205 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1206 (let (then-test) ; multi-line if-then
1207 (while
1208 (and
1209 (zerop (forward-line 1))
1210 ;; Search forward for then.
1211 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1212 (not
1213 (setq then-test
1214 (looking-at
1215 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1216 then-test))
1217 (setq count (1+ count)))))))
1218 (and (zerop count)
1219 ;; All pairs accounted for.
1220 (point)))))))
1222 (defun fortran-beginning-if ()
1223 "Search backwards for first unmatched IF-THEN.
1224 Return point or nil."
1225 (let ((case-fold-search t))
1226 (if (save-excursion
1227 ;; May be sitting on multi-line if-then statement, first
1228 ;; move to beginning of current statement. Note:
1229 ;; `fortran-previous-statement' moves to previous statement
1230 ;; *unless* current statement is first one. Only move
1231 ;; forward if not first-statement.
1232 (if (not (eq (fortran-previous-statement) 'first-statement))
1233 (fortran-next-statement))
1234 (skip-chars-forward " \t0-9")
1235 (and
1236 (looking-at fortran-if-start-re)
1237 (save-match-data
1238 (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1239 ;; Multi-line if-then.
1240 (let (then-test)
1241 (while
1242 (and (zerop (forward-line 1))
1243 ;; Search forward for then.
1244 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1245 (not
1246 (setq then-test
1247 (looking-at
1248 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1249 then-test)))))
1250 ;; Sitting on one.
1251 (match-beginning 0)
1252 ;; Search for one.
1253 (save-excursion
1254 (let ((count 1))
1255 (while (and (not (zerop count))
1256 (not (eq (fortran-previous-statement) 'first-statement))
1257 ;; Keep local to subprogram.
1258 (not (and (looking-at fortran-end-prog-re)
1259 (fortran-check-end-prog-re))))
1260 (skip-chars-forward " \t0-9")
1261 (cond ((looking-at fortran-if-start-re)
1262 (save-excursion
1263 (if (or
1264 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1265 (let (then-test) ; multi-line if-then
1266 (while
1267 (and
1268 (zerop (forward-line 1))
1269 ;; Search forward for then.
1270 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1271 (not
1272 (setq then-test
1273 (looking-at
1274 (concat ".*then\\b[ \t]*"
1275 "[^ \t(=a-z0-9]"))))))
1276 then-test))
1277 (setq count (1- count)))))
1278 ((looking-at "end[ \t]*if\\b")
1279 (setq count (1+ count)))))
1280 (and (zerop count)
1281 ;; All pairs accounted for.
1282 (point)))))))
1285 (defun fortran-indent-line ()
1286 "Indent current Fortran line based on its contents and on previous lines."
1287 (interactive "*")
1288 (let ((cfi (fortran-calculate-indent)))
1289 (save-excursion
1290 (beginning-of-line)
1291 (if (or (not (= cfi (fortran-current-line-indentation)))
1292 (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t)
1293 (not (fortran-line-number-indented-correctly-p))))
1294 (fortran-indent-to-column cfi)
1295 (beginning-of-line)
1296 (if (fortran-find-comment-start-skip)
1297 (fortran-indent-comment))))
1298 ;; Never leave point in left margin.
1299 (if (< (current-column) cfi)
1300 (move-to-column cfi))
1301 (and auto-fill-function
1302 (> (save-excursion (end-of-line) (current-column))
1303 fill-column)
1304 (save-excursion
1305 (end-of-line)
1306 (fortran-fill)))
1307 (when fortran-blink-matching-if
1308 (fortran-blink-matching-if)
1309 (fortran-blink-matching-do))))
1311 (defun fortran-auto-fill ()
1312 "Function to use for `normal-auto-fill-function' in Fortran mode."
1313 (if (> (current-column) (current-fill-column))
1314 (let ((cfi (fortran-calculate-indent)))
1315 (save-excursion
1316 (beginning-of-line)
1317 (if (or (not (= cfi (fortran-current-line-indentation)))
1318 (and (re-search-forward "^[ \t]*[0-9]+"
1319 (+ (point) 4) t)
1320 (not (fortran-line-number-indented-correctly-p))))
1321 (fortran-indent-to-column cfi)
1322 (beginning-of-line)
1323 (if (fortran-find-comment-start-skip)
1324 (fortran-indent-comment))))
1325 (fortran-fill)
1326 ;; Never leave point in left margin.
1327 (if (< (current-column) cfi)
1328 (move-to-column cfi)))))
1330 ;; Historically this was a separate function which advertised itself
1331 ;; as reindenting but only did so where `most likely to be necessary'.
1332 (defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent)
1334 (defun fortran-indent-subprogram ()
1335 "Properly indent the Fortran subprogram containing point."
1336 (interactive "*")
1337 (save-excursion
1338 (mark-defun)
1339 (message "Indenting subprogram...")
1340 (indent-region (point) (mark) nil))
1341 (message "Indenting subprogram...done."))
1343 (defun fortran-calculate-indent ()
1344 "Calculates the Fortran indent column based on previous lines."
1345 (let (icol first-statement (case-fold-search t)
1346 (fortran-minimum-statement-indent
1347 (if indent-tabs-mode
1348 fortran-minimum-statement-indent-tab
1349 fortran-minimum-statement-indent-fixed)))
1350 (save-excursion
1351 (setq first-statement (fortran-previous-statement))
1352 (if first-statement
1353 (setq icol fortran-minimum-statement-indent)
1354 (if (= (point) (point-min))
1355 (setq icol fortran-minimum-statement-indent)
1356 (setq icol (fortran-current-line-indentation)))
1357 (skip-chars-forward " \t0-9")
1358 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")
1359 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")
1360 (let (then-test) ; multi-line if-then
1361 (while (and (zerop (forward-line 1))
1362 ;; Search forward for then.
1363 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1364 (not (setq then-test
1365 (looking-at
1366 ".*then\\b[ \t]\
1367 *[^ \t_$(=a-z0-9]")))))
1368 then-test))
1369 (setq icol (+ icol fortran-if-indent))))
1370 ((looking-at "else\\(if\\)?\\b")
1371 (setq icol (+ icol fortran-if-indent)))
1372 ((looking-at "select[ \t]*case[ \t](.*)")
1373 (setq icol (+ icol fortran-if-indent)))
1374 ((looking-at "case[ \t]*(.*)")
1375 (setq icol (+ icol fortran-if-indent)))
1376 ((looking-at "case[ \t]*default\\b")
1377 (setq icol (+ icol fortran-if-indent)))
1378 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1379 (setq icol (+ icol fortran-if-indent)))
1380 ((looking-at "where[ \t]*(.*)[ \t]*\n")
1381 (setq icol (+ icol fortran-if-indent)))
1382 ((looking-at "do\\b")
1383 (setq icol (+ icol fortran-do-indent)))
1384 ((looking-at
1385 "\\(structure\\|union\\|map\\|interface\\)\
1386 \\b[ \t]*[^ \t=(a-z]")
1387 (setq icol (+ icol fortran-structure-indent)))
1388 ((and (looking-at fortran-end-prog-re1)
1389 (fortran-check-end-prog-re))
1390 ;; Previous END resets indent to minimum.
1391 (setq icol fortran-minimum-statement-indent)))))
1392 (save-excursion
1393 (beginning-of-line)
1394 (cond ((looking-at "[ \t]*$"))
1395 ;; Check for directive before comment, so as not to indent.
1396 ((looking-at fortran-directive-re)
1397 (setq fortran-minimum-statement-indent 0 icol 0))
1398 ((looking-at fortran-comment-line-start-skip)
1399 (cond ((eq fortran-comment-indent-style 'relative)
1400 (setq icol (+ icol fortran-comment-line-extra-indent)))
1401 ((eq fortran-comment-indent-style 'fixed)
1402 (setq icol (+ fortran-minimum-statement-indent
1403 fortran-comment-line-extra-indent))))
1404 (setq fortran-minimum-statement-indent 0))
1405 ((or (looking-at (concat "[ \t]*"
1406 (regexp-quote
1407 fortran-continuation-string)))
1408 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))
1409 (skip-chars-forward " \t")
1410 ;; Do not introduce extra whitespace into a broken string.
1411 (setq icol
1412 (if (fortran-is-in-string-p (point))
1414 (+ icol fortran-continuation-indent))))
1415 (first-statement)
1416 ((and fortran-check-all-num-for-matching-do
1417 (looking-at "[ \t]*[0-9]+")
1418 (fortran-check-for-matching-do))
1419 (setq icol (- icol fortran-do-indent)))
1421 (skip-chars-forward " \t0-9")
1422 (cond ((looking-at "end[ \t]*\\(if\\|select\\|where\\)\\b")
1423 (setq icol (- icol fortran-if-indent)))
1424 ((looking-at "else\\(if\\)?\\b")
1425 (setq icol (- icol fortran-if-indent)))
1426 ((looking-at "case[ \t]*\\((.*)\\|default\\>\\)")
1427 (setq icol (- icol fortran-if-indent)))
1428 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1429 (setq icol (- icol fortran-if-indent)))
1430 ((and (looking-at "continue\\b")
1431 (fortran-check-for-matching-do))
1432 (setq icol (- icol fortran-do-indent)))
1433 ((looking-at "end[ \t]*do\\b")
1434 (setq icol (- icol fortran-do-indent)))
1435 ((looking-at "end[ \t]*\
1436 \\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
1437 (setq icol (- icol fortran-structure-indent)))
1438 ((and (looking-at fortran-end-prog-re1)
1439 (fortran-check-end-prog-re)
1440 (not (= icol fortran-minimum-statement-indent)))
1441 (message "Warning: `end' not in column %d. Probably\
1442 an unclosed block." fortran-minimum-statement-indent))))))
1443 (max fortran-minimum-statement-indent icol)))
1446 (defun fortran-current-line-indentation ()
1447 "Indentation of current line, ignoring Fortran line number or continuation.
1448 This is the column position of the first non-whitespace character
1449 aside from the line number and/or column 5/8 line-continuation character.
1450 For comment lines, returns indentation of the first
1451 non-indentation text within the comment."
1452 (save-excursion
1453 (beginning-of-line)
1454 (cond ((looking-at fortran-comment-line-start-skip)
1455 (goto-char (match-end 0))
1456 (skip-chars-forward
1457 (if (stringp fortran-comment-indent-char)
1458 fortran-comment-indent-char
1459 (char-to-string fortran-comment-indent-char))))
1460 ((or (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))
1461 (goto-char (match-end 0)))
1463 ;; Move past line number.
1464 (skip-chars-forward "[ \t0-9]")))
1465 ;; Move past whitespace.
1466 (skip-chars-forward " \t")
1467 (current-column)))
1469 (defun fortran-indent-to-column (col)
1470 "Indent current line to column COL.
1471 notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
1472 line, and this continuation character is retained on indentation;
1473 2) If `fortran-continuation-string' is the first non-whitespace
1474 character, this is a continuation line;
1475 3) A non-continuation line which has a number as the first
1476 non-whitespace character is a numbered line.
1477 4) A TAB followed by a digit indicates a continuation line."
1478 (save-excursion
1479 (beginning-of-line)
1480 (if (looking-at fortran-comment-line-start-skip)
1481 (if fortran-comment-indent-style
1482 (let* ((char (if (stringp fortran-comment-indent-char)
1483 (aref fortran-comment-indent-char 0)
1484 fortran-comment-indent-char))
1485 (chars (string ? ?\t char)))
1486 (goto-char (match-end 0))
1487 (skip-chars-backward chars)
1488 (delete-region (point) (progn (skip-chars-forward chars)
1489 (point)))
1490 (insert-char char (- col (current-column)))))
1491 (if (looking-at "\t[1-9]")
1492 (if indent-tabs-mode
1493 (goto-char (match-end 0))
1494 (delete-char 2)
1495 (insert-char ? 5)
1496 (insert fortran-continuation-string))
1497 (if (looking-at " \\{5\\}[^ 0\n]")
1498 (if indent-tabs-mode
1499 (progn (delete-char 6)
1500 (insert ?\t (fortran-numerical-continuation-char) 1))
1501 (forward-char 6))
1502 (delete-horizontal-space)
1503 ;; Put line number in columns 0-4, or
1504 ;; continuation character in column 5.
1505 (cond ((eobp))
1506 ((looking-at (regexp-quote fortran-continuation-string))
1507 (if indent-tabs-mode
1508 (progn
1509 (indent-to
1510 (if indent-tabs-mode
1511 fortran-minimum-statement-indent-tab
1512 fortran-minimum-statement-indent-fixed))
1513 (delete-char 1)
1514 (insert-char (fortran-numerical-continuation-char) 1))
1515 (indent-to 5)
1516 (forward-char 1)))
1517 ((looking-at "[0-9]+")
1518 (let ((extra-space (- 5 (- (match-end 0) (point)))))
1519 (if (< extra-space 0)
1520 (message "Warning: line number exceeds 5-digit limit.")
1521 (indent-to (min fortran-line-number-indent extra-space))))
1522 (skip-chars-forward "0-9")))))
1523 ;; Point is now after any continuation character or line number.
1524 ;; Put body of statement where specified.
1525 (delete-horizontal-space)
1526 (indent-to col)
1527 ;; Indent any comment following code on the same line.
1528 (when (fortran-find-comment-start-skip)
1529 (goto-char (match-beginning 0))
1530 (unless (= (current-column) (fortran-comment-indent))
1531 (delete-horizontal-space)
1532 (indent-to (fortran-comment-indent)))))))
1534 (defun fortran-line-number-indented-correctly-p ()
1535 "Return t if current line's line number is correctly indented.
1536 Do not call if there is no line number."
1537 (save-excursion
1538 (beginning-of-line)
1539 (skip-chars-forward " \t")
1540 (and (<= (current-column) fortran-line-number-indent)
1541 (or (= (current-column) fortran-line-number-indent)
1542 (progn (skip-chars-forward "0-9")
1543 (= (current-column) 5))))))
1545 (defun fortran-check-for-matching-do ()
1546 "When called from a numbered statement, return t if matching DO is found.
1547 Otherwise return nil."
1548 (let ((case-fold-search t)
1549 charnum)
1550 (save-excursion
1551 (beginning-of-line)
1552 (when (looking-at "[ \t]*[0-9]+")
1553 (skip-chars-forward " \t")
1554 (skip-chars-forward "0") ; skip past leading zeros
1555 (setq charnum
1556 (buffer-substring (point) (progn
1557 (skip-chars-forward "0-9")
1558 (point))))
1559 (beginning-of-line)
1560 (save-restriction
1561 (save-excursion
1562 (narrow-to-defun)
1563 (and (re-search-backward
1564 (concat
1565 "\\(^[ \t0-9]*do[ \t]*0*"
1566 charnum "\\b\\)\\|" "\\(^[ \t]*0*"
1567 charnum "\\b\\)")
1568 nil t)
1569 (looking-at
1570 (concat "^[ \t0-9]*do[ \t]*0*"
1571 charnum)))))))))
1573 (defun fortran-find-comment-start-skip (&optional all)
1574 "Move to past `comment-start-skip' found on current line.
1575 Return non-nil if `comment-start-skip' found, nil if not.
1576 If ALL is nil, only match comments that start in column > 0."
1577 ;; Hopefully at some point we can just use the line below! -stef
1578 ;; (comment-search-forward (line-end-position) t))
1579 (when (or all comment-start-skip)
1580 (let ((pos (point))
1581 (css (if comment-start-skip
1582 (concat fortran-comment-line-start-skip
1583 "\\|" comment-start-skip)
1584 fortran-comment-line-start-skip)))
1585 (when (re-search-forward css (line-end-position) t)
1586 (if (and (or all (> (match-beginning 0) (line-beginning-position)))
1587 (or (save-match-data
1588 (not (fortran-is-in-string-p (match-beginning 0))))
1589 ;; Recurse for rest of line.
1590 (fortran-find-comment-start-skip all)))
1591 (point)
1592 (goto-char pos)
1593 nil)))))
1595 ;; From: ralf@up3aud1.gwdg.de (Ralf Fassel)
1596 ;; Test if TAB format continuation lines work.
1597 (defun fortran-is-in-string-p (where)
1598 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string."
1599 (save-excursion
1600 (goto-char where)
1601 (cond
1602 ((bolp) nil) ; bol is never inside a string
1603 ((save-excursion ; comment lines too
1604 (beginning-of-line)
1605 (looking-at fortran-comment-line-start-skip)) nil)
1606 (t (let ((parse-state '(0 nil nil nil nil nil 0))
1607 (quoted-comment-start (if comment-start
1608 (regexp-quote comment-start)))
1609 (not-done t)
1610 parse-limit end-of-line)
1611 ;; Move to start of current statement.
1612 (fortran-next-statement)
1613 (fortran-previous-statement)
1614 ;; Now parse up to WHERE.
1615 (while not-done
1616 (if (or ;; Skip to next line if:
1617 ;; - comment line?
1618 (looking-at fortran-comment-line-start-skip)
1619 ;; - at end of line?
1620 (eolp)
1621 ;; - not in a string and after comment-start?
1622 (and (not (nth 3 parse-state))
1623 comment-start
1624 (equal comment-start
1625 (char-to-string (preceding-char)))))
1626 (if (> (forward-line) 0)
1627 (setq not-done nil))
1628 ;; else:
1629 ;; If we are at beginning of code line, skip any
1630 ;; whitespace, labels and tab continuation markers.
1631 (if (bolp) (skip-chars-forward " \t0-9"))
1632 ;; If we are in column <= 5 now, check for continuation char.
1633 (cond ((= 5 (current-column)) (forward-char 1))
1634 ((and (< (current-column) 5)
1635 (equal fortran-continuation-string
1636 (char-to-string (following-char)))
1637 (forward-char 1))))
1638 ;; Find out parse-limit from here.
1639 (setq end-of-line (line-end-position))
1640 (setq parse-limit (min where end-of-line))
1641 ;; Parse max up to comment-start, if non-nil and in current line.
1642 (if comment-start
1643 (save-excursion
1644 (if (re-search-forward quoted-comment-start end-of-line t)
1645 (setq parse-limit (min (point) parse-limit)))))
1646 ;; Now parse if still in limits.
1647 (if (< (point) where)
1648 (setq parse-state (parse-partial-sexp
1649 (point) parse-limit nil nil parse-state))
1650 (setq not-done nil))))
1651 ;; Result.
1652 (nth 3 parse-state))))))
1654 ;; From old version.
1655 (defalias 'fortran-auto-fill-mode 'auto-fill-mode)
1657 (defun fortran-fill ()
1658 "Fill the current line at an appropriate point(s)."
1659 (let* ((auto-fill-function #'fortran-auto-fill)
1660 (opoint (point))
1661 (bol (line-beginning-position))
1662 (eol (line-end-position))
1663 (bos (min eol (+ bol (fortran-current-line-indentation))))
1664 ;; If in a string at fill-column, break it either before the
1665 ;; initial quote, or at fill-col (if string is too long).
1666 (quote
1667 (save-excursion
1668 (goto-char bol)
1669 ;; OK to break quotes on comment lines.
1670 (unless (looking-at fortran-comment-line-start-skip)
1671 (let (fcpoint start)
1672 (move-to-column fill-column)
1673 (when (fortran-is-in-string-p (setq fcpoint (point)))
1674 (save-excursion
1675 (re-search-backward "\\S\"\\s\"\\S\"?" bol t)
1676 (setq start
1677 (if fortran-break-before-delimiters
1678 (point)
1679 (1+ (point)))))
1680 (if (re-search-forward "\\S\"\\s\"\\S\"" eol t)
1681 (backward-char 2))
1682 ;; If the current string is longer than 72 - 6 chars,
1683 ;; break it at the fill column (else infinite loop).
1684 (if (> (- (point) start)
1685 (- fill-column 6 fortran-continuation-indent))
1686 fcpoint
1687 start))))))
1688 ;; Decide where to split the line. If a position for a quoted
1689 ;; string was found above then use that, else break the line
1690 ;; before/after the last delimiter.
1691 (fill-point
1692 (or quote
1693 (save-excursion
1694 ;; If f-b-b-d is t, have an extra column to play with,
1695 ;; since delimiter gets shifted to new line.
1696 (move-to-column (if fortran-break-before-delimiters
1697 (1+ fill-column)
1698 fill-column))
1699 (let ((repeat t))
1700 (while repeat
1701 (setq repeat nil)
1702 ;; Adapted from f90-find-breakpoint.
1703 (re-search-backward fortran-break-delimiters-re bol)
1704 (if (not fortran-break-before-delimiters)
1705 (if (looking-at fortran-no-break-re)
1706 ;; Deal with cases such as "**" split over
1707 ;; fill-col. Simpler alternative would be
1708 ;; to start from (1- fill-column) above.
1709 (if (> (+ 2 (current-column)) fill-column)
1710 (setq repeat t)
1711 (forward-char 2))
1712 (forward-char 1))
1713 (backward-char)
1714 (or (looking-at fortran-no-break-re)
1715 (forward-char)))))
1716 ;; Line indented beyond fill-column?
1717 (when (<= (point) bos)
1718 (move-to-column (1+ fill-column))
1719 ;; What is this doing???
1720 (or (re-search-forward "[\t\n,'+-/*)=]" eol t)
1721 (goto-char bol)))
1722 (if (bolp)
1723 (re-search-forward "[ \t]" opoint t))
1724 (point)))))
1725 ;; If we are in an in-line comment, don't break unless the
1726 ;; line of code is longer than it should be. Otherwise
1727 ;; break the line at the column computed above.
1729 ;; Need to use fortran-find-comment-start-skip to make sure that
1730 ;; quoted !'s don't prevent a break.
1731 (when (and (save-excursion
1732 (beginning-of-line)
1733 (if (not (fortran-find-comment-start-skip))
1735 (goto-char (match-beginning 0))
1736 (>= (point) fill-point)))
1737 (save-excursion
1738 (goto-char fill-point)
1739 (not (bolp)))
1740 (> (save-excursion
1741 (goto-char opoint)
1742 (current-column))
1743 (min (1+ fill-column)
1744 (+ (fortran-calculate-indent)
1745 fortran-continuation-indent))))
1746 (goto-char fill-point)
1747 (fortran-break-line)
1748 (end-of-line))))
1750 (defun fortran-break-line ()
1751 "Call `fortran-split-line'. Joins continuation lines first, then refills."
1752 (let ((opoint (point))
1753 (bol (line-beginning-position))
1754 (comment-string
1755 (save-excursion
1756 (if (fortran-find-comment-start-skip)
1757 (delete-and-extract-region
1758 (match-beginning 0) (line-end-position))))))
1759 ;; Forward line 1 really needs to go to next non white line.
1760 (if (save-excursion (forward-line)
1761 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))
1762 (progn
1763 (end-of-line)
1764 (delete-region (point) (match-end 0))
1765 (delete-horizontal-space)
1766 (fortran-fill))
1767 (fortran-split-line))
1768 (if comment-string
1769 (save-excursion
1770 (goto-char bol)
1771 (end-of-line)
1772 (delete-horizontal-space)
1773 (indent-to (fortran-comment-indent))
1774 (insert comment-string)))))
1776 (defun fortran-analyze-file-format ()
1777 "Return nil if fixed format is used, t if TAB formatting is used.
1778 Use `fortran-tab-mode-default' if no non-comment statements are found
1779 before the end or in the first `fortran-analyze-depth' lines."
1780 (let ((i 0))
1781 (save-excursion
1782 (goto-char (point-min))
1783 (while (not (or
1784 (eobp)
1785 (eq (char-after) ?\t)
1786 (looking-at " \\{6\\}")
1787 (> i fortran-analyze-depth)))
1788 (forward-line)
1789 (setq i (1+ i)))
1790 (cond
1791 ((eq (char-after) ?\t) t)
1792 ((looking-at " \\{6\\}") nil)
1793 (t fortran-tab-mode-default)))))
1795 (defun fortran-fill-paragraph (&optional justify)
1796 "Fill surrounding comment block as paragraphs, else fill statement.
1797 Intended as the value of `fill-paragraph-function'.
1798 A comment block is filled by calling `fill-comment-paragraph' with
1799 argument JUSTIFY, otherwise `fortran-fill-statement' is called.
1800 Always returns non-nil (to prevent `fill-paragraph' being called)."
1801 (interactive "*P")
1802 (or (fill-comment-paragraph justify)
1803 (fortran-fill-statement)
1806 (defun fortran-fill-statement ()
1807 "Fill a Fortran statement up to `fill-column'."
1808 (interactive "*")
1809 (let ((auto-fill-function #'fortran-auto-fill))
1810 (unless (save-excursion
1811 (beginning-of-line)
1812 (or (looking-at "[ \t]*$")
1813 (looking-at fortran-comment-line-start-skip)
1814 (and comment-start-skip
1815 (looking-at (concat "[ \t]*" comment-start-skip)))))
1816 (save-excursion
1817 ;; Find beginning of statement.
1818 (fortran-next-statement)
1819 (fortran-previous-statement)
1820 ;; Re-indent initially.
1821 (fortran-indent-line)
1822 ;; Replace newline plus continuation field plus indentation with
1823 ;; single space.
1824 (while (progn
1825 (forward-line)
1826 (fortran-remove-continuation)))
1827 (fortran-previous-statement)))
1828 (fortran-indent-line)))
1830 (defun fortran-strip-sequence-nos (&optional do-space)
1831 "Delete all text in column 72 and up (assumed to be sequence numbers).
1832 Normally also deletes trailing whitespace after stripping such text.
1833 Supplying prefix arg DO-SPACE prevents stripping the whitespace."
1834 (interactive "*p")
1835 (save-excursion
1836 (goto-char (point-min))
1837 (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t)
1838 (replace-match "" nil nil nil 1)
1839 (unless do-space (delete-horizontal-space)))))
1841 ;; This code used to live in add-log.el, but this is a better place
1842 ;; for it.
1843 (defun fortran-current-defun ()
1844 "Function to use for `add-log-current-defun-function' in Fortran mode."
1845 (save-excursion
1846 ;; We must be inside function body for this to work.
1847 (fortran-beginning-of-subprogram)
1848 (let ((case-fold-search t)) ; case-insensitive
1849 ;; Search for fortran subprogram start.
1850 (if (re-search-forward
1851 (concat "^[ \t]*\\(program\\|subroutine\\|function"
1852 "\\|[ \ta-z0-9*()]*[ \t]+function\\|"
1853 "\\(block[ \t]*data\\)\\)")
1854 (save-excursion (fortran-end-of-subprogram)
1855 (point))
1857 (or (match-string-no-properties 2)
1858 (progn
1859 ;; Move to EOL or before first left paren.
1860 (if (re-search-forward "[(\n]" nil t)
1861 (progn (backward-char)
1862 (skip-chars-backward " \t"))
1863 (end-of-line))
1864 ;; Use the name preceding that.
1865 (buffer-substring-no-properties (point) (progn (backward-sexp)
1866 (point)))))
1867 "main"))))
1869 (provide 'fortran)
1871 ;;; arch-tag: 74935096-21c4-4cab-8ee5-6ef16090dc04
1872 ;;; fortran.el ends here