comparison lisp/progmodes/fortran.el @ 21410:d68f866455c6

Use regexp-opt and eval-and-compile to build font-lock patterns. (fortran-mode): Define indent-region-function, indent-line-function. (fortran-tab-mode-string): Make buffer-local. (fortran-comment-indent-style): Custom tweak. (fortran-comment-region, fortran-electric-line-number, fortran-analyze-depth, fortran-break-before-delimiters, fortran-mode): Doc fix. (fortran-startup-message, bug-fortran-mode): Variables deleted. (fortran-font-lock-keywords-1): Add "select", "case"; allow double-quoted strings. (fortran-mode-map): Add fill-paragraph menu item. Don't define \t. (fortran-mode): Make `fill-column' buffer-local; set `fill-paragraph-function', `indent-region-function', `indent-line-function'. (calculate-fortran-indent): Renamed to: (fortran-calculate-indent): (fortran-split-line): Simplify. (fortran-remove-continuation): New function. (fortran-join-line): Use it. (fortran-end-prog-re1, fortran-end-prog-re): New variables. (beginning-of-fortran-subprogram, end-of-fortran-subprogram): Use them. (fortran-blink-matching-if, fortran-blink-matching-do, fortran-indent-new-line): Bind case-fold-search. (fortran-end-do, fortran-beginning-do, fortran-end-if, fortran-beginning-if): Bind case-fold-search. Allow labelled blocks. Use fortran-end-prog-re. (fortran-if-start-re): New variable. (fortran-calculate-indent): Allow labelled blocks. Simplify the conds. Make select case indentation work. (fortran-is-in-string-p): Ignore Emacs 18 bug kluge. (fortran-fill): Allow double quotes in check for string. (fortran-fill-paragraph): New function. (fortran-fill-statement): New function.
author Dave Love <fx@gnu.org>
date Tue, 07 Apr 1998 18:59:44 +0000
parents 1d2bd6adba38
children 79711f0f4079
comparison
equal deleted inserted replaced
21409:3e8b7782f4f5 21410:d68f866455c6
39 ;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea, 39 ;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea,
40 ;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon, 40 ;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon,
41 ;; Gary Sabot and Richard Stallman. 41 ;; Gary Sabot and Richard Stallman.
42 42
43 ;;; Code: 43 ;;; Code:
44
45 ;; Todo:
46
47 ;; * Implement insertion and removal of statement continuations in
48 ;; mixed f77/f90 style, with the first `&' past column 72 and the
49 ;; second in column 6.
50 ;; * Support other f90-style stuff grokked by GNU Fortran.
44 51
45 (require 'easymenu) 52 (require 'easymenu)
46 53
47 (defgroup fortran nil 54 (defgroup fortran nil
48 "Fortran mode for Emacs" 55 "Fortran mode for Emacs"
71 ;; Buffer local, used to display mode line. 78 ;; Buffer local, used to display mode line.
72 (defcustom fortran-tab-mode-string nil 79 (defcustom fortran-tab-mode-string nil
73 "String to appear in mode line when TAB format mode is on." 80 "String to appear in mode line when TAB format mode is on."
74 :type '(choice (const nil) string) 81 :type '(choice (const nil) string)
75 :group 'fortran-indent) 82 :group 'fortran-indent)
83 (make-variable-buffer-local 'fortran-tab-mode-string)
76 84
77 (defcustom fortran-do-indent 3 85 (defcustom fortran-do-indent 3
78 "*Extra indentation applied to DO blocks." 86 "*Extra indentation applied to DO blocks."
79 :type 'integer 87 :type 'integer
80 :group 'fortran-indent) 88 :group 'fortran-indent)
100 'fixed makes fixed comment indentation to `fortran-comment-line-extra-indent' 108 'fixed makes fixed comment indentation to `fortran-comment-line-extra-indent'
101 columns beyond `fortran-minimum-statement-indent-fixed' (for 109 columns beyond `fortran-minimum-statement-indent-fixed' (for
102 `indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for 110 `indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for
103 `indent-tabs-mode' of t), and 'relative indents to current 111 `indent-tabs-mode' of t), and 'relative indents to current
104 Fortran indentation plus `fortran-comment-line-extra-indent'." 112 Fortran indentation plus `fortran-comment-line-extra-indent'."
105 :type '(radio (const nil) (const fixed) (const relative)) 113 :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative))
106 :group 'fortran-indent) 114 :group 'fortran-indent)
107 115
108 (defcustom fortran-comment-line-extra-indent 0 116 (defcustom fortran-comment-line-extra-indent 0
109 "*Amount of extra indentation for text within full-line comments." 117 "*Amount of extra indentation for text within full-line comments."
110 :type 'integer 118 :type 'integer
166 Normally $." 174 Normally $."
167 :type 'string 175 :type 'string
168 :group 'fortran) 176 :group 'fortran)
169 177
170 (defcustom fortran-comment-region "c$$$" 178 (defcustom fortran-comment-region "c$$$"
171 "*String inserted by \\[fortran-comment-region]\ 179 "*String inserted by \\[fortran-comment-region] at start of each \
172 at start of each line in region." 180 line in region."
173 :type 'string 181 :type 'string
174 :group 'fortran-comment) 182 :group 'fortran-comment)
175 183
176 (defcustom fortran-electric-line-number t 184 (defcustom fortran-electric-line-number t
177 "*Non-nil causes line number digits to be moved to the correct column as\ 185 "*Non-nil causes line number digits to be moved to the correct \
178 typed." 186 column as typed."
179 :type 'boolean
180 :group 'fortran)
181
182 (defcustom fortran-startup-message t
183 "*Non-nil displays a startup message when Fortran mode is first called."
184 :type 'boolean 187 :type 'boolean
185 :group 'fortran) 188 :group 'fortran)
186 189
187 (defvar fortran-column-ruler-fixed 190 (defvar fortran-column-ruler-fixed
188 "0 4 6 10 20 30 40 5\ 191 "0 4 6 10 20 30 40 5\
202 205
203 (defvar fortran-mode-syntax-table nil 206 (defvar fortran-mode-syntax-table nil
204 "Syntax table in use in Fortran mode buffers.") 207 "Syntax table in use in Fortran mode buffers.")
205 208
206 (defvar fortran-analyze-depth 100 209 (defvar fortran-analyze-depth 100
207 "Number of lines to scan to determine whether to use fixed or TAB format\ 210 "Number of lines to scan to determine whether to use fixed or TAB \
208 style.") 211 format style.")
209 212
210 (defcustom fortran-break-before-delimiters t 213 (defcustom fortran-break-before-delimiters t
211 "*Non-nil causes `fortran-fill' to break lines before delimiters." 214 "*Non-nil causes filling to break lines before delimiters."
212 :type 'boolean 215 :type 'boolean
213 :group 'fortran) 216 :group 'fortran)
214 217
215 (if fortran-mode-syntax-table 218 (if fortran-mode-syntax-table
216 () 219 ()
250 "Medium level highlighting for Fortran mode.") 253 "Medium level highlighting for Fortran mode.")
251 254
252 (defconst fortran-font-lock-keywords-3 nil 255 (defconst fortran-font-lock-keywords-3 nil
253 "Gaudy level highlighting for Fortran mode.") 256 "Gaudy level highlighting for Fortran mode.")
254 257
255 (let ((comment-chars "c!*") 258 (eval-and-compile
256 (fortran-type-types 259 (let ((comment-chars "c!*")
257 ; (make-regexp 260 (fortran-type-types
258 ; (let ((simple-types '("character" "byte" "integer" "logical" 261 (regexp-opt
259 ; "none" "real" "complex" 262 (let ((simple-types '("character" "byte" "integer" "logical"
260 ; "double[ \t]*precision" "double[ \t]*complex")) 263 "none" "real" "complex"
261 ; (structured-types '("structure" "union" "map")) 264 "double[ \t]*precision" "double[ \t]*complex"))
262 ; (other-types '("record" "dimension" "parameter" "common" "save" 265 (structured-types '("structure" "union" "map"))
263 ; "external" "intrinsic" "data" "equivalence"))) 266 (other-types '("record" "dimension" "parameter" "common" "save"
264 ; (append 267 "external" "intrinsic" "data" "equivalence")))
265 ; (mapcar (lambda (x) (concat "implicit[ \t]*" x)) simple-types) 268 (append
266 ; simple-types 269 (mapcar (lambda (x) (concat "implicit[ \t]*" x)) simple-types)
267 ; (mapcar (lambda (x) (concat "end[ \t]*" x)) structured-types) 270 simple-types
268 ; structured-types 271 (mapcar (lambda (x) (concat "end[ \t]*" x)) structured-types)
269 ; other-types))) 272 structured-types
270 (concat "byte\\|c\\(haracter\\|om\\(mon\\|plex\\)\\)\\|" 273 other-types))))
271 "d\\(ata\\|imension\\|ouble" 274 (fortran-keywords
272 "[ \t]*\\(complex\\|precision\\)\\)\\|" 275 (regexp-opt '("continue" "format" "end" "enddo" "if" "then"
273 "e\\(nd[ \t]*\\(map\\|structure\\|union\\)\\|" 276 "else" "endif" "elseif" "while" "inquire" "stop"
274 "quivalence\\|xternal\\)\\|" 277 "return" "include" "open" "close" "read" "write"
275 "i\\(mplicit[ \t]*\\(byte\\|" 278 "format" "print" "select" "case")))
276 "c\\(haracter\\|omplex\\)\\|"
277 "double[ \t]*\\(complex\\|precision\\)\\|"
278 "integer\\|logical\\|none\\|real\\)\\|"
279 "nt\\(eger\\|rinsic\\)\\)\\|"
280 "logical\\|map\\|none\\|parameter\\|re\\(al\\|cord\\)\\|"
281 "s\\(ave\\|tructure\\)\\|union"))
282 (fortran-keywords
283 ; ("continue" "format" "end" "enddo" "if" "then" "else" "endif"
284 ; "elseif" "while" "inquire" "stop" "return" "include" "open"
285 ; "close" "read" "write" "format" "print")
286 (concat "c\\(lose\\|ontinue\\)\\|"
287 "e\\(lse\\(\\|if\\)\\|nd\\(\\|do\\|if\\)\\)\\|format\\|"
288 "i\\(f\\|n\\(clude\\|quire\\)\\)\\|open\\|print\\|"
289 "re\\(ad\\|turn\\)\\|stop\\|then\\|w\\(hile\\|rite\\)"))
290 (fortran-logicals 279 (fortran-logicals
291 ; ("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne" "true" "false") 280 (regexp-opt '("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne"
292 "and\\|eq\\|false\\|g[et]\\|l[et]\\|n\\(e\\|ot\\)\\|or\\|true")) 281 "true" "false"))))
293 282
294 (setq fortran-font-lock-keywords-1 283 (setq fortran-font-lock-keywords-1
295 (list 284 (list
296 ;; 285 ;;
297 ;; Fontify syntactically (assuming strings cannot be quoted or span lines). 286 ;; Fontify syntactically (assuming strings cannot be quoted
298 (cons (concat "^[" comment-chars "].*") 'font-lock-comment-face) 287 ;; or span lines).
299 '(fortran-match-!-comment . font-lock-comment-face) 288 (cons (concat "^[" comment-chars "].*") 'font-lock-comment-face)
300 (list (concat "^[^" comment-chars "\t\n]" (make-string 71 ?.) "\\(.*\\)") 289 '(fortran-match-!-comment . font-lock-comment-face)
301 '(1 font-lock-comment-face)) 290 (list (concat "^[^" comment-chars "\t\n]" (make-string 71 ?.)
302 '("'[^'\n]*'?" . font-lock-string-face) 291 "\\(.*\\)")
303 ;; 292 '(1 font-lock-comment-face))
304 ;; Program, subroutine and function declarations, plus calls. 293 '("\\(\\s\"\\)\"[^\n]*\\1?" . font-lock-string-face)
305 (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|" 294 ;;
306 "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?") 295 ;; Program, subroutine and function declarations, plus calls.
307 '(1 font-lock-keyword-face) 296 (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|"
308 '(2 font-lock-function-name-face nil t)))) 297 "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?")
309 298 '(1 font-lock-keyword-face)
310 (setq fortran-font-lock-keywords-2 299 '(2 font-lock-function-name-face nil t))))
311 (append fortran-font-lock-keywords-1 300
312 (list 301 (setq fortran-font-lock-keywords-2
313 ;; 302 (append fortran-font-lock-keywords-1
314 ;; Fontify all type specifiers (must be first; see below). 303 (list
315 (cons (concat "\\<\\(" fortran-type-types "\\)\\>") 'font-lock-type-face) 304 ;;
316 ;; 305 ;; Fontify all type specifiers (must be first; see below).
317 ;; Fontify all builtin keywords (except logical, do and goto; see below). 306 (cons (concat "\\<\\(" fortran-type-types "\\)\\>")
318 (concat "\\<\\(" fortran-keywords "\\)\\>") 307 'font-lock-type-face)
319 ;; 308 ;;
320 ;; Fontify all builtin operators. 309 ;; Fontify all builtin keywords (except logical, do
321 (concat "\\.\\(" fortran-logicals "\\)\\.") 310 ;; and goto; see below).
322 ;; 311 (concat "\\<\\(" fortran-keywords "\\)\\>")
323 ;; Fontify do/goto keywords and targets, and goto tags. 312 ;;
324 (list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?" 313 ;; Fontify all builtin operators.
325 '(1 font-lock-keyword-face) 314 (concat "\\.\\(" fortran-logicals "\\)\\.")
326 '(2 font-lock-constant-face nil t)) 315 ;;
327 (cons "^ *\\([0-9]+\\)" 'font-lock-constant-face)))) 316 ;; Fontify do/goto keywords and targets, and goto tags.
328 317 (list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
329 (setq fortran-font-lock-keywords-3 318 '(1 font-lock-keyword-face)
330 (append 319 '(2 font-lock-constant-face nil t))
331 ;; 320 (cons "^ *\\([0-9]+\\)" 'font-lock-constant-face))))
332 ;; The list `fortran-font-lock-keywords-1'. 321
333 fortran-font-lock-keywords-1 322 (setq fortran-font-lock-keywords-3
334 ;; 323 (append
335 ;; Fontify all type specifiers plus their declared items. 324 ;;
336 (list 325 ;; The list `fortran-font-lock-keywords-1'.
337 (list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?") 326 fortran-font-lock-keywords-1
338 ;; Fontify the type specifier. 327 ;;
339 '(1 font-lock-type-face) 328 ;; Fontify all type specifiers plus their declared items.
340 ;; Fontify each declaration item (or just the /.../ block name). 329 (list
341 '(font-lock-match-c-style-declaration-item-and-skip-to-next 330 (list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?")
342 ;; Start after any *(...) expression. 331 ;; Fontify the type specifier.
343 (and (match-beginning 15) (forward-sexp 1)) 332 '(1 font-lock-type-face)
344 ;; No need to clean up. 333 ;; Fontify each declaration item (or just the /.../ block name).
345 nil 334 '(font-lock-match-c-style-declaration-item-and-skip-to-next
346 ;; Fontify as a variable name, functions are fontified elsewhere. 335 ;; Start after any *(...) expression.
347 (1 font-lock-variable-name-face nil t)))) 336 (and (match-beginning 15) (forward-sexp))
348 ;; 337 ;; No need to clean up.
349 ;; Things extra to `fortran-font-lock-keywords-3' (must be done first). 338 nil
350 (list 339 ;; Fontify as a variable name, functions are
351 ;; 340 ;; fontified elsewhere.
352 ;; Fontify goto-like `err=label'/`end=label' in read/write statements. 341 (1 font-lock-variable-name-face nil t))))
353 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?" 342 ;;
354 (1 font-lock-keyword-face) (4 font-lock-constant-face nil t)) 343 ;; Things extra to `fortran-font-lock-keywords-3'
355 ;; 344 ;; (must be done first).
356 ;; Highlight standard continuation character and in a TAB-formatted line. 345 (list
357 '("^ \\([^ 0]\\)" 1 font-lock-string-face) 346 ;;
358 '("^\t\\([1-9]\\)" 1 font-lock-string-face)) 347 ;; Fontify goto-like `err=label'/`end=label' in read/write
359 ;; 348 ;; statements.
360 ;; The list `fortran-font-lock-keywords-2' less that for types (see above). 349 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
361 (cdr (nthcdr (length fortran-font-lock-keywords-1) 350 (1 font-lock-keyword-face) (4 font-lock-constant-face nil t))
362 fortran-font-lock-keywords-2)))) 351 ;;
363 ) 352 ;; Highlight standard continuation character and in a
353 ;; TAB-formatted line.
354 '("^ \\([^ 0]\\)" 1 font-lock-string-face)
355 '("^\t\\([1-9]\\)" 1 font-lock-string-face))
356 ;;
357 ;; The list `fortran-font-lock-keywords-2' less that for types
358 ;; (see above).
359 (cdr (nthcdr (length fortran-font-lock-keywords-1)
360 fortran-font-lock-keywords-2))))))
364 361
365 (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1 362 (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
366 "Default expressions to highlight in Fortran mode.") 363 "Default expressions to highlight in Fortran mode.")
367 364
368 (defvar fortran-imenu-generic-expression 365 (defvar fortran-imenu-generic-expression
376 ;; character(*), `double precision' and possible statement 373 ;; character(*), `double precision' and possible statement
377 ;; continuation; 3. untyped declarations; 4. the variable to 374 ;; continuation; 3. untyped declarations; 4. the variable to
378 ;; index. [This will be fooled by `end function' allowed by G77. 375 ;; index. [This will be fooled by `end function' allowed by G77.
379 ;; Also, it assumes sensible whitespace is employed.] 376 ;; Also, it assumes sensible whitespace is employed.]
380 (concat "^\\s-+\\(\ 377 (concat "^\\s-+\\(\
381 \\(\\sw\\|\\s-\\|[*()+]\\)*\\<function\\|\ 378 \\(\\sw\\|\\s-\\|[*()+]\\)*\
382 subroutine\\|entry\\|block\\s-*data\\|program\\)[ \t" fortran-continuation-string "]+\ 379 \\<function\\|subroutine\\|entry\\|block\\s-*data\\|program\\)\
380 [ \t" fortran-continuation-string "]+\
383 \\(\\sw+\\)") 381 \\(\\sw+\\)")
384 3) 382 3)
385 ;; Un-named block data 383 ;; Un-named block data
386 (list nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1)) 384 (list nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1))
387 "imenu generic expression for `imenu-default-create-index-function'.") 385 "imenu generic expression for `imenu-default-create-index-function'.")
404 (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler) 402 (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler)
405 (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement) 403 (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement)
406 (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement) 404 (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement)
407 (define-key fortran-mode-map "\C-c\C-d" 'fortran-join-line) 405 (define-key fortran-mode-map "\C-c\C-d" 'fortran-join-line)
408 (define-key fortran-mode-map "\C-xnd" 'fortran-narrow-to-subprogram) 406 (define-key fortran-mode-map "\C-xnd" 'fortran-narrow-to-subprogram)
409 (define-key fortran-mode-map "\t" 'fortran-indent-line) 407 ;(define-key fortran-mode-map "\t" 'fortran-indent-line)
410 (define-key fortran-mode-map "0" 'fortran-electric-line-number) 408 (define-key fortran-mode-map "0" 'fortran-electric-line-number)
411 (define-key fortran-mode-map "1" 'fortran-electric-line-number) 409 (define-key fortran-mode-map "1" 'fortran-electric-line-number)
412 (define-key fortran-mode-map "2" 'fortran-electric-line-number) 410 (define-key fortran-mode-map "2" 'fortran-electric-line-number)
413 (define-key fortran-mode-map "3" 'fortran-electric-line-number) 411 (define-key fortran-mode-map "3" 'fortran-electric-line-number)
414 (define-key fortran-mode-map "4" 'fortran-electric-line-number) 412 (define-key fortran-mode-map "4" 'fortran-electric-line-number)
450 (< (window-width) (frame-width))] 448 (< (window-width) (frame-width))]
451 ["Momentary 72-column window" fortran-window-create-momentarily t] 449 ["Momentary 72-column window" fortran-window-create-momentarily t]
452 "----" 450 "----"
453 ["Break Line at Point" fortran-split-line t] 451 ["Break Line at Point" fortran-split-line t]
454 ["Join Continuation Line" fortran-join-line t] 452 ["Join Continuation Line" fortran-join-line t]
453 ["Fill Statement/Comment" fill-paragraph t]
455 "----" 454 "----"
456 ["Add imenu menu" 455 ["Add imenu menu"
457 (progn (imenu-add-to-menubar "Index") 456 (progn (imenu-add-to-menubar "Index")
458 ;; Prod menu bar to update -- is this the right way? 457 ;; Prod menu bar to update -- is this the right way?
459 (menu-bar-mode 1)) 458 (menu-bar-mode 1))
522 (define-abbrev fortran-mode-abbrev-table ";vo" "volatile" nil) 521 (define-abbrev fortran-mode-abbrev-table ";vo" "volatile" nil)
523 (define-abbrev fortran-mode-abbrev-table ";w" "write" nil) 522 (define-abbrev fortran-mode-abbrev-table ";w" "write" nil)
524 (define-abbrev fortran-mode-abbrev-table ";wh" "where" nil) 523 (define-abbrev fortran-mode-abbrev-table ";wh" "where" nil)
525 (setq abbrevs-changed ac))) 524 (setq abbrevs-changed ac)))
526 525
527 (eval-when-compile (defvar imenu-syntax-alist nil)) ; silence compiler 526 (eval-when-compile ; silence compiler
527 (defvar imenu-case-fold-search)
528 (defvar imenu-syntax-alist))
528 529
529 ;;;###autoload 530 ;;;###autoload
530 (defun fortran-mode () 531 (defun fortran-mode ()
531 "Major mode for editing Fortran code. 532 "Major mode for editing Fortran code.
532 \\[fortran-indent-line] indents the current Fortran line correctly. 533 \\[fortran-indent-line] indents the current Fortran line correctly.
533 DO statements must not share a common CONTINUE. 534 DO statements must not share a common CONTINUE.
534 535
535 Type ;? or ;\\[help-command] to display a list of built-in\ 536 Type ;? or ;\\[help-command] to display a list of built-in abbrevs for
536 abbrevs for Fortran keywords. 537 Fortran keywords.
537 538
538 Key definitions: 539 Key definitions:
539 \\{fortran-mode-map} 540 \\{fortran-mode-map}
540 541
541 Variables controlling indentation style and extra features: 542 Variables controlling indentation style and extra features:
589 region. (default \"c$$$\") 590 region. (default \"c$$$\")
590 fortran-electric-line-number 591 fortran-electric-line-number
591 Non-nil causes line number digits to be moved to the correct column 592 Non-nil causes line number digits to be moved to the correct column
592 as typed. (default t) 593 as typed. (default t)
593 fortran-break-before-delimiters 594 fortran-break-before-delimiters
594 Non-nil causes `fortran-fill' breaks lines before delimiters. 595 Non-nil causes `fortran-fill' to break lines before delimiters.
595 (default t) 596 (default t)
596 597
597 Turning on Fortran mode calls the value of the variable `fortran-mode-hook' 598 Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
598 with no args, if that value is non-nil." 599 with no args, if that value is non-nil."
599 (interactive) 600 (interactive)
627 (make-local-variable 'abbrev-all-caps) 628 (make-local-variable 'abbrev-all-caps)
628 (setq abbrev-all-caps t) 629 (setq abbrev-all-caps t)
629 (make-local-variable 'indent-tabs-mode) 630 (make-local-variable 'indent-tabs-mode)
630 (setq indent-tabs-mode nil) 631 (setq indent-tabs-mode nil)
631 ;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead?? 632 ;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead??
632 (setq fill-column 72) ; Already local? 633 (set (make-local-variable 'fill-column) 72)
633 (use-local-map fortran-mode-map) 634 (use-local-map fortran-mode-map)
634 (setq mode-name "Fortran") 635 (setq mode-name "Fortran")
635 (setq major-mode 'fortran-mode) 636 (setq major-mode 'fortran-mode)
636 ;;;(make-local-variable 'fortran-tab-mode)
637 (make-local-variable 'fortran-comment-line-extra-indent) 637 (make-local-variable 'fortran-comment-line-extra-indent)
638 (make-local-variable 'fortran-minimum-statement-indent-fixed) 638 (make-local-variable 'fortran-minimum-statement-indent-fixed)
639 (make-local-variable 'fortran-minimum-statement-indent-tab) 639 (make-local-variable 'fortran-minimum-statement-indent-tab)
640 (make-local-variable 'fortran-column-ruler-fixed) 640 (make-local-variable 'fortran-column-ruler-fixed)
641 (make-local-variable 'fortran-column-ruler-tab) 641 (make-local-variable 'fortran-column-ruler-tab)
642 (make-local-variable 'fortran-tab-mode-string)
643 (setq fortran-tab-mode-string " TAB-format") 642 (setq fortran-tab-mode-string " TAB-format")
644 (setq indent-tabs-mode (fortran-analyze-file-format)) 643 (setq indent-tabs-mode (fortran-analyze-file-format))
645 (setq imenu-case-fold-search t) 644 (setq imenu-case-fold-search t)
646 (make-local-variable 'imenu-generic-expression) 645 (make-local-variable 'imenu-generic-expression)
647 (setq imenu-generic-expression fortran-imenu-generic-expression) 646 (setq imenu-generic-expression fortran-imenu-generic-expression)
648 (setq imenu-syntax-alist '(("_$" . "w"))) 647 (setq imenu-syntax-alist '(("_$" . "w")))
648 (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph)
649 (set (make-local-variable 'indent-line-function) 'fortran-indent-line)
650 (set (make-local-variable 'indent-region-function)
651 (lambda (start end)
652 (let (fortran-blink-matching-if ; avoid blinking delay
653 indent-region-function)
654 (indent-region start end nil))))
649 (run-hooks 'fortran-mode-hook)) 655 (run-hooks 'fortran-mode-hook))
650 656
651 (defun fortran-comment-hook () 657 (defun fortran-comment-hook ()
652 (save-excursion 658 (save-excursion
653 (skip-chars-backward " \t") 659 (skip-chars-backward " \t")
691 (forward-char -1)) 697 (forward-char -1))
692 (insert comment-line-start) 698 (insert comment-line-start)
693 (insert-char (if (stringp fortran-comment-indent-char) 699 (insert-char (if (stringp fortran-comment-indent-char)
694 (aref fortran-comment-indent-char 0) 700 (aref fortran-comment-indent-char 0)
695 fortran-comment-indent-char) 701 fortran-comment-indent-char)
696 (- (calculate-fortran-indent) (current-column)))))) 702 (- (fortran-calculate-indent) (current-column))))))
697 703
698 (defun fortran-comment-region (beg-region end-region arg) 704 (defun fortran-comment-region (beg-region end-region arg)
699 "Comments every line in the region. 705 "Comments every line in the region.
700 Puts `fortran-comment-region' at the beginning of every line in the region. 706 Puts `fortran-comment-region' at the beginning of every line in the region.
701 BEG-REGION and END-REGION are args which specify the region boundaries. 707 BEG-REGION and END-REGION are args which specify the region boundaries.
804 (interactive) 810 (interactive)
805 (delete-horizontal-space) 811 (delete-horizontal-space)
806 (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip)) 812 (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip))
807 (insert "\n" comment-line-start " ") 813 (insert "\n" comment-line-start " ")
808 (if indent-tabs-mode 814 (if indent-tabs-mode
809 (progn 815 (insert "\n\t" (fortran-numerical-continuation-char))
810 (insert "\n\t") 816 (insert "\n " fortran-continuation-string))) ; Space after \n important
811 (insert-char (fortran-numerical-continuation-char) 1)) 817 (fortran-indent-line)) ; when the cont string is C, c or *.
812 (insert "\n " fortran-continuation-string)));Space after \n important 818
813 (fortran-indent-line)) ;when the cont string is C, c or *. 819 (defun fortran-remove-continuation ()
820 (if (looking-at "\\( [^ 0\n]\\|\t[1-9]\\|&\\)")
821 (progn (replace-match "")
822 (delete-indentation)
823 t)))
814 824
815 (defun fortran-join-line () 825 (defun fortran-join-line ()
816 "Join a continuation line to the previous one and re-indent." 826 "Join a continuation line to the previous one and re-indent."
817 (interactive) 827 (interactive)
818 (save-excursion 828 (save-excursion
819 (beginning-of-line) 829 (beginning-of-line)
820 (cond ((looking-at " \\S-") 830 (if (not (fortran-remove-continuation))
821 (delete-region (1- (point)) (+ (point) 7))) 831 (error "Not a continuation line"))
822 ((looking-at "&")
823 (delete-region (1- (point)) (1+ (point))))
824 ((looking-at " *\t[1-9]")
825 (apply 'delete-region (match-data))
826 (delete-backward-char 1))
827 (t (error "This isn't a continuation line")))
828 (just-one-space)
829 (fortran-indent-line))) 832 (fortran-indent-line)))
830 833
831 (defun fortran-numerical-continuation-char () 834 (defun fortran-numerical-continuation-char ()
832 "Return a digit for tab-digit style of continuation lines. 835 "Return a digit for tab-digit style of continuation lines.
833 If, previous line is a tab-digit continuation line, returns that digit 836 If, previous line is a tab-digit continuation line, returns that digit
857 (if (or (and (= 5 (current-column)) 860 (if (or (and (= 5 (current-column))
858 (save-excursion 861 (save-excursion
859 (beginning-of-line) 862 (beginning-of-line)
860 (looking-at " ")));In col 5 with only spaces to left. 863 (looking-at " ")));In col 5 with only spaces to left.
861 (and (= (if indent-tabs-mode 864 (and (= (if indent-tabs-mode
862 fortran-minimum-statement-indent-tab 865 fortran-minimum-statement-indent-tab
863 fortran-minimum-statement-indent-fixed) (current-column)) 866 fortran-minimum-statement-indent-fixed) (current-column))
864 (save-excursion 867 (save-excursion
865 (beginning-of-line) 868 (beginning-of-line)
866 (looking-at "\t"));In col 8 with a single tab to the left. 869 (looking-at "\t"));In col 8 with a single tab to the left.
867 (not (or (eq last-command 'fortran-indent-line) 870 (not (or (eq last-command 'fortran-indent-line)
868 (eq last-command 871 (eq last-command
870 (save-excursion 873 (save-excursion
871 (re-search-backward "[^ \t0-9]" 874 (re-search-backward "[^ \t0-9]"
872 (save-excursion 875 (save-excursion
873 (beginning-of-line) 876 (beginning-of-line)
874 (point)) 877 (point))
875 t)) ;not a line number 878 t)) ;not a line number
876 (looking-at "[0-9]") ;within a line number 879 (looking-at "[0-9]")) ;within a line number
877 )
878 (self-insert-command (prefix-numeric-value arg)) 880 (self-insert-command (prefix-numeric-value arg))
879 (skip-chars-backward " \t") 881 (skip-chars-backward " \t")
880 (insert last-command-char) 882 (insert last-command-char)
881 (fortran-indent-line)))) 883 (fortran-indent-line))))
882 884
885 (defvar fortran-end-prog-re1
886 "end\\b[ \t]*\\(\\(program\\|subroutine\\|function\\)[ \t]*\\)?[^ \t=\(a-z]")
887 (defvar fortran-end-prog-re
888 (concat "^[ \t0-9]*" fortran-end-prog-re1))
889
883 (defun beginning-of-fortran-subprogram () 890 (defun beginning-of-fortran-subprogram ()
884 "Moves point to the beginning of the current Fortran subprogram." 891 "Moves point to the beginning of the current Fortran subprogram."
885 (interactive) 892 (interactive)
886 (let ((case-fold-search t)) 893 (let ((case-fold-search t))
887 (beginning-of-line -1) 894 (beginning-of-line -1)
888 (re-search-backward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) 895 (if (re-search-backward fortran-end-prog-re nil 'move)
889 (if (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]") 896 (forward-line))))
890 (forward-line 1))))
891 897
892 (defun end-of-fortran-subprogram () 898 (defun end-of-fortran-subprogram ()
893 "Moves point to the end of the current Fortran subprogram." 899 "Moves point to the end of the current Fortran subprogram."
894 (interactive) 900 (interactive)
895 (let ((case-fold-search t)) 901 (let ((case-fold-search t))
896 (beginning-of-line 2) 902 (beginning-of-line 2)
897 (re-search-forward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) 903 (re-search-forward fortran-end-prog-re nil 'move)
898 (goto-char (match-beginning 0)) 904 (goto-char (match-beginning 0))
899 (forward-line 1))) 905 (forward-line)))
900 906
901 (defun mark-fortran-subprogram () 907 (defun mark-fortran-subprogram ()
902 "Put mark at end of Fortran subprogram, point at beginning. 908 "Put mark at end of Fortran subprogram, point at beginning.
903 The marks are pushed." 909 The marks are pushed."
904 (interactive) 910 (interactive)
961 (narrow-to-region (region-beginning) 967 (narrow-to-region (region-beginning)
962 (region-end)))) 968 (region-end))))
963 969
964 (defun fortran-blink-matching-if () 970 (defun fortran-blink-matching-if ()
965 ;; From a Fortran ENDIF statement, blink the matching IF statement. 971 ;; From a Fortran ENDIF statement, blink the matching IF statement.
966 (let ((top-of-window (window-start)) matching-if 972 (let ((top-of-window (window-start))
967 (endif-point (point)) message) 973 (endif-point (point))
974 (case-fold-search t)
975 matching-if
976 message)
968 (if (save-excursion (beginning-of-line) 977 (if (save-excursion (beginning-of-line)
969 (skip-chars-forward " \t0-9") 978 (skip-chars-forward " \t0-9")
970 (looking-at "end[ \t]*if\\b")) 979 (looking-at "end[ \t]*if\\b"))
971 (progn 980 (progn
972 (if (not (setq matching-if (fortran-beginning-if))) 981 (if (not (setq matching-if (fortran-beginning-if)))
986 (goto-char endif-point)))))) 995 (goto-char endif-point))))))
987 996
988 (defun fortran-blink-matching-do () 997 (defun fortran-blink-matching-do ()
989 ;; From a Fortran ENDDO statement, blink on the matching DO or DO WHILE 998 ;; From a Fortran ENDDO statement, blink on the matching DO or DO WHILE
990 ;; statement. This is basically copied from fortran-blink-matching-if. 999 ;; statement. This is basically copied from fortran-blink-matching-if.
991 (let ((top-of-window (window-start)) matching-do 1000 (let ((top-of-window (window-start))
992 (enddo-point (point)) message) 1001 (enddo-point (point))
1002 (case-fold-search t)
1003 matching-do
1004 message)
993 (if (save-excursion (beginning-of-line) 1005 (if (save-excursion (beginning-of-line)
994 (skip-chars-forward " \t0-9") 1006 (skip-chars-forward " \t0-9")
995 (looking-at "end[ \t]*do\\b")) 1007 (looking-at "end[ \t]*do\\b"))
996 (progn 1008 (progn
997 (if (not (setq matching-do (fortran-beginning-do))) 1009 (if (not (setq matching-do (fortran-beginning-do)))
1023 (push-mark) 1035 (push-mark)
1024 (goto-char do-point))))) 1036 (goto-char do-point)))))
1025 1037
1026 (defun fortran-end-do () 1038 (defun fortran-end-do ()
1027 ;; Search forward for first unmatched ENDDO. Return point or nil. 1039 ;; Search forward for first unmatched ENDDO. Return point or nil.
1028 (if (save-excursion (beginning-of-line) 1040 (let ((case-fold-search t))
1029 (skip-chars-forward " \t0-9") 1041 (if (save-excursion (beginning-of-line)
1030 (looking-at "end[ \t]*do\\b")) 1042 (skip-chars-forward " \t0-9")
1031 ;; Sitting on one. 1043 (looking-at "end[ \t]*do\\b"))
1032 (match-beginning 0) 1044 ;; Sitting on one.
1033 ;; Search for one. 1045 (match-beginning 0)
1034 (save-excursion 1046 ;; Search for one.
1035 (let ((count 1)) 1047 (save-excursion
1048 (let ((count 1))
1036 (while (and (not (= count 0)) 1049 (while (and (not (= count 0))
1037 (not (eq (fortran-next-statement) 'last-statement)) 1050 (not (eq (fortran-next-statement) 'last-statement))
1038 ;; Keep local to subprogram 1051 ;; Keep local to subprogram
1039 (not (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) 1052 (not (looking-at fortran-end-prog-re)))
1040 1053
1041 (skip-chars-forward " \t0-9") 1054 (skip-chars-forward " \t0-9")
1042 (cond ((looking-at "end[ \t]*do\\b") 1055 (cond ((looking-at "end[ \t]*do\\b")
1043 (setq count (- count 1))) 1056 (setq count (1- count)))
1044 ((looking-at "do[ \t]+[^0-9]") 1057 ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]")
1045 (setq count (+ count 1))))) 1058 (setq count (+ count 1)))))
1046 (and (= count 0) 1059 (and (= count 0)
1047 ;; All pairs accounted for. 1060 ;; All pairs accounted for.
1048 (point)))))) 1061 (point)))))))
1049 1062
1050 (defun fortran-beginning-do () 1063 (defun fortran-beginning-do ()
1051 ;; Search backwards for first unmatched DO [WHILE]. Return point or nil. 1064 ;; Search backwards for first unmatched DO [WHILE]. Return point or nil.
1052 (if (save-excursion (beginning-of-line) 1065 (let ((case-fold-search t))
1053 (skip-chars-forward " \t0-9") 1066 (if (save-excursion (beginning-of-line)
1054 (looking-at "do[ \t]+")) 1067 (skip-chars-forward " \t0-9")
1055 ;; Sitting on one. 1068 (looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+"))
1056 (match-beginning 0) 1069 ;; Sitting on one.
1057 ;; Search for one. 1070 (match-beginning 0)
1058 (save-excursion 1071 ;; Search for one.
1059 (let ((count 1)) 1072 (save-excursion
1073 (let ((count 1))
1060 (while (and (not (= count 0)) 1074 (while (and (not (= count 0))
1061 (not (eq (fortran-previous-statement) 'first-statement)) 1075 (not (eq (fortran-previous-statement) 'first-statement))
1062 ;; Keep local to subprogram 1076 ;; Keep local to subprogram
1063 (not (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) 1077 (not (looking-at fortran-end-prog-re)))
1064 1078
1065 (skip-chars-forward " \t0-9") 1079 (skip-chars-forward " \t0-9")
1066 (cond ((looking-at "do[ \t]+[^0-9]") 1080 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]")
1067 (setq count (- count 1))) 1081 (setq count (1- count)))
1068 ((looking-at "end[ \t]*do\\b") 1082 ((looking-at "end[ \t]*do\\b")
1069 (setq count (+ count 1))))) 1083 (setq count (1+ count)))))
1070 1084
1071 (and (= count 0) 1085 (and (= count 0)
1072 ;; All pairs accounted for. 1086 ;; All pairs accounted for.
1073 (point)))))) 1087 (point)))))))
1074 1088
1075 (defun fortran-mark-if () 1089 (defun fortran-mark-if ()
1076 "Put mark at end of Fortran IF-ENDIF construct, point at beginning. 1090 "Put mark at end of Fortran IF-ENDIF construct, point at beginning.
1077 The marks are pushed." 1091 The marks are pushed."
1078 (interactive) 1092 (interactive)
1083 ;; Set mark, move point. 1097 ;; Set mark, move point.
1084 (goto-char endif-point) 1098 (goto-char endif-point)
1085 (push-mark) 1099 (push-mark)
1086 (goto-char if-point))))) 1100 (goto-char if-point)))))
1087 1101
1102 (defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")
1103
1088 (defun fortran-end-if () 1104 (defun fortran-end-if ()
1089 ;; Search forwards for first unmatched ENDIF. Return point or nil. 1105 ;; Search forwards for first unmatched ENDIF. Return point or nil.
1090 (if (save-excursion (beginning-of-line) 1106 (let ((case-fold-search t))
1091 (skip-chars-forward " \t0-9") 1107 (if (save-excursion (beginning-of-line)
1092 (looking-at "end[ \t]*if\\b")) 1108 (skip-chars-forward " \t0-9")
1093 ;; Sitting on one. 1109 (looking-at "end[ \t]*if\\b"))
1094 (match-beginning 0) 1110 ;; Sitting on one.
1095 ;; Search for one. The point has been already been moved to first 1111 (match-beginning 0)
1096 ;; letter on line but this should not cause troubles. 1112 ;; Search for one. The point has been already been moved to first
1097 (save-excursion 1113 ;; letter on line but this should not cause troubles.
1098 (let ((count 1)) 1114 (save-excursion
1115 (let ((count 1))
1099 (while (and (not (= count 0)) 1116 (while (and (not (= count 0))
1100 (not (eq (fortran-next-statement) 'last-statement)) 1117 (not (eq (fortran-next-statement) 'last-statement))
1101 ;; Keep local to subprogram. 1118 ;; Keep local to subprogram.
1102 (not (looking-at 1119 (not (looking-at fortran-end-prog-re)))
1103 "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) 1120
1104 1121 (skip-chars-forward " \t0-9")
1105 (skip-chars-forward " \t0-9") 1122 (cond ((looking-at "end[ \t]*if\\b")
1106 (cond ((looking-at "end[ \t]*if\\b")
1107 (setq count (- count 1))) 1123 (setq count (- count 1)))
1108 1124
1109 ((looking-at "if[ \t]*(") 1125 ((looking-at fortran-if-start-re)
1110 (save-excursion 1126 (save-excursion
1111 (if (or 1127 (if (or
1112 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") 1128 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1113 (let (then-test) ; Multi-line if-then. 1129 (let (then-test) ; Multi-line if-then.
1114 (while 1130 (while
1115 (and (= (forward-line 1) 0) 1131 (and (= (forward-line 1) 0)
1116 ;; Search forward for then. 1132 ;; Search forward for then.
1117 (or (looking-at " [^ 0\n]") 1133 (or (looking-at " [^ 0\n]")
1118 (looking-at "\t[1-9]")) 1134 (looking-at "\t[1-9]"))
1119 (not 1135 (not
1120 (setq then-test 1136 (setq then-test
1121 (looking-at 1137 (looking-at
1122 ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) 1138 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1123 then-test)) 1139 then-test))
1124 (setq count (+ count 1))))))) 1140 (setq count (+ count 1)))))))
1125 1141
1126 (and (= count 0) 1142 (and (= count 0)
1127 ;; All pairs accounted for. 1143 ;; All pairs accounted for.
1128 (point)))))) 1144 (point)))))))
1129 1145
1130 (defun fortran-beginning-if () 1146 (defun fortran-beginning-if ()
1131 ;; Search backwards for first unmatched IF-THEN. Return point or nil. 1147 ;; Search backwards for first unmatched IF-THEN. Return point or nil.
1132 (if (save-excursion 1148 (let ((case-fold-search t))
1133 ;; May be sitting on multi-line if-then statement, first move to 1149 (if (save-excursion
1134 ;; beginning of current statement. Note: `fortran-previous-statement' 1150 ;; May be sitting on multi-line if-then statement, first move to
1135 ;; moves to previous statement *unless* current statement is first 1151 ;; beginning of current statement. Note: `fortran-previous-statement'
1136 ;; one. Only move forward if not first-statement. 1152 ;; moves to previous statement *unless* current statement is first
1137 (if (not (eq (fortran-previous-statement) 'first-statement)) 1153 ;; one. Only move forward if not first-statement.
1138 (fortran-next-statement)) 1154 (if (not (eq (fortran-previous-statement) 'first-statement))
1139 (skip-chars-forward " \t0-9") 1155 (fortran-next-statement))
1140 (and 1156 (skip-chars-forward " \t0-9")
1141 (looking-at "if[ \t]*(") 1157 (and
1142 (save-match-data 1158 (looking-at fortran-if-start-re)
1143 (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") 1159 (save-match-data
1144 ;; Multi-line if-then. 1160 (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1145 (let (then-test) 1161 ;; Multi-line if-then.
1146 (while 1162 (let (then-test)
1163 (while
1147 (and (= (forward-line 1) 0) 1164 (and (= (forward-line 1) 0)
1148 ;; Search forward for then. 1165 ;; Search forward for then.
1149 (or (looking-at " [^ 0\n]") 1166 (or (looking-at " [^ 0\n]")
1150 (looking-at "\t[1-9]")) 1167 (looking-at "\t[1-9]"))
1151 (not 1168 (not
1152 (setq then-test 1169 (setq then-test
1153 (looking-at 1170 (looking-at
1154 ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) 1171 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1155 then-test))))) 1172 then-test)))))
1156 ;; Sitting on one. 1173 ;; Sitting on one.
1157 (match-beginning 0) 1174 (match-beginning 0)
1158 ;; Search for one. 1175 ;; Search for one.
1159 (save-excursion 1176 (save-excursion
1160 (let ((count 1)) 1177 (let ((count 1))
1161 (while (and (not (= count 0)) 1178 (while (and (not (= count 0))
1162 (not (eq (fortran-previous-statement) 'first-statement)) 1179 (not (eq (fortran-previous-statement) 'first-statement))
1163 ;; Keep local to subprogram. 1180 ;; Keep local to subprogram.
1164 (not (looking-at 1181 (not (looking-at fortran-end-prog-re)))
1165 "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) 1182
1166 1183 (skip-chars-forward " \t0-9")
1167 (skip-chars-forward " \t0-9") 1184 (cond ((looking-at fortran-if-start-re)
1168 (cond ((looking-at "if[ \t]*(") 1185 (save-excursion
1169 (save-excursion 1186 (if (or
1170 (if (or 1187 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]")
1171 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") 1188 (let (then-test) ; Multi-line if-then.
1172 (let (then-test) ; Multi-line if-then. 1189 (while
1173 (while
1174 (and (= (forward-line 1) 0) 1190 (and (= (forward-line 1) 0)
1175 ;; Search forward for then. 1191 ;; Search forward for then.
1176 (or (looking-at " [^ 0\n]") 1192 (or (looking-at " [^ 0\n]")
1177 (looking-at "\t[1-9]")) 1193 (looking-at "\t[1-9]"))
1178 (not 1194 (not
1179 (setq then-test 1195 (setq then-test
1180 (looking-at 1196 (looking-at
1181 ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) 1197 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1182 then-test)) 1198 then-test))
1183 (setq count (- count 1))))) 1199 (setq count (- count 1)))))
1184 ((looking-at "end[ \t]*if\\b") 1200 ((looking-at "end[ \t]*if\\b")
1185 (setq count (+ count 1))))) 1201 (setq count (+ count 1)))))
1186 1202
1187 (and (= count 0) 1203 (and (= count 0)
1188 ;; All pairs accounted for. 1204 ;; All pairs accounted for.
1189 (point)))))) 1205 (point)))))))
1190 1206
1191 (defun fortran-indent-line () 1207 (defun fortran-indent-line ()
1192 "Indent current Fortran line based on its contents and on previous lines." 1208 "Indent current Fortran line based on its contents and on previous lines."
1193 (interactive) 1209 (interactive)
1194 (let ((cfi (calculate-fortran-indent))) 1210 (let ((cfi (fortran-calculate-indent)))
1195 (save-excursion 1211 (save-excursion
1196 (beginning-of-line) 1212 (beginning-of-line)
1197 (if (or (not (= cfi (fortran-current-line-indentation))) 1213 (if (or (not (= cfi (fortran-current-line-indentation)))
1198 (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t) 1214 (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t)
1199 (not (fortran-line-number-indented-correctly-p)))) 1215 (not (fortran-line-number-indented-correctly-p))))
1221 (interactive) 1237 (interactive)
1222 (if abbrev-mode (expand-abbrev)) 1238 (if abbrev-mode (expand-abbrev))
1223 (save-excursion 1239 (save-excursion
1224 (beginning-of-line) 1240 (beginning-of-line)
1225 (skip-chars-forward " \t") 1241 (skip-chars-forward " \t")
1226 (if (or (looking-at "[0-9]") ;Reindent only where it is most 1242 (let ((case-fold-search t))
1227 (looking-at "end") ;likely to be necessary 1243 (if (or (looking-at "[0-9]") ;Reindent only where it is most
1228 (looking-at "else") 1244 (looking-at "end") ;likely to be necessary
1229 (looking-at (regexp-quote fortran-continuation-string))) 1245 (looking-at "else")
1230 (fortran-indent-line))) 1246 (looking-at (regexp-quote fortran-continuation-string)))
1247 (fortran-indent-line))))
1231 (newline) 1248 (newline)
1232 (fortran-indent-line)) 1249 (fortran-indent-line))
1233 1250
1234 (defun fortran-indent-subprogram () 1251 (defun fortran-indent-subprogram ()
1235 "Properly indent the Fortran subprogram which contains point." 1252 "Properly indent the Fortran subprogram which contains point."
1238 (mark-fortran-subprogram) 1255 (mark-fortran-subprogram)
1239 (message "Indenting subprogram...") 1256 (message "Indenting subprogram...")
1240 (indent-region (point) (mark) nil)) 1257 (indent-region (point) (mark) nil))
1241 (message "Indenting subprogram...done.")) 1258 (message "Indenting subprogram...done."))
1242 1259
1243 (defun calculate-fortran-indent () 1260 (defun fortran-calculate-indent ()
1244 "Calculates the Fortran indent column based on previous lines." 1261 "Calculates the Fortran indent column based on previous lines."
1245 (let (icol first-statement (case-fold-search t) 1262 (let (icol first-statement (case-fold-search t)
1246 (fortran-minimum-statement-indent 1263 (fortran-minimum-statement-indent
1247 (if indent-tabs-mode 1264 (if indent-tabs-mode
1248 fortran-minimum-statement-indent-tab 1265 fortran-minimum-statement-indent-tab
1254 (progn 1271 (progn
1255 (if (= (point) (point-min)) 1272 (if (= (point) (point-min))
1256 (setq icol fortran-minimum-statement-indent) 1273 (setq icol fortran-minimum-statement-indent)
1257 (setq icol (fortran-current-line-indentation))) 1274 (setq icol (fortran-current-line-indentation)))
1258 (skip-chars-forward " \t0-9") 1275 (skip-chars-forward " \t0-9")
1259 (cond ((looking-at "if[ \t]*(") 1276 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")
1260 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") 1277 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")
1261 (let (then-test) ;multi-line if-then 1278 (let (then-test) ;multi-line if-then
1262 (while (and (= (forward-line 1) 0) 1279 (while (and (= (forward-line 1) 0)
1263 ;;search forward for then 1280 ;;search forward for then
1264 (or (looking-at " [^ 0\n]") 1281 (or (looking-at " [^ 0\n]")
1266 (not (setq then-test (looking-at 1283 (not (setq then-test (looking-at
1267 ".*then\\b[ \t]\ 1284 ".*then\\b[ \t]\
1268 *[^ \t_$(=a-z0-9]"))))) 1285 *[^ \t_$(=a-z0-9]")))))
1269 then-test)) 1286 then-test))
1270 (setq icol (+ icol fortran-if-indent)))) 1287 (setq icol (+ icol fortran-if-indent))))
1271 ((looking-at "\\(else\\|elseif\\)\\b") 1288 ((looking-at "else\\(if\\)?\\b")
1272 (setq icol (+ icol fortran-if-indent))) 1289 (setq icol (+ icol fortran-if-indent)))
1273 ((looking-at "select[ \t]*case[ \t](.*)\\b") 1290 ((looking-at "select[ \t]*case[ \t](.*)")
1274 (setq icol (+ icol fortran-if-indent))) 1291 (setq icol (+ icol fortran-if-indent)))
1275 ((looking-at "case[ \t]*(.*)[ \t]*\n") 1292 ((looking-at "case[ \t]*(.*)")
1276 (setq icol (+ icol fortran-if-indent))) 1293 (setq icol (+ icol fortran-if-indent)))
1277 ((looking-at "case[ \t]*default\\b") 1294 ((looking-at "case[ \t]*default\\b")
1278 (setq icol (+ icol fortran-if-indent))) 1295 (setq icol (+ icol fortran-if-indent)))
1279 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") 1296 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1280 (setq icol (+ icol fortran-if-indent))) 1297 (setq icol (+ icol fortran-if-indent)))
1283 ((looking-at "do\\b") 1300 ((looking-at "do\\b")
1284 (setq icol (+ icol fortran-do-indent))) 1301 (setq icol (+ icol fortran-do-indent)))
1285 ((looking-at 1302 ((looking-at
1286 "\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]") 1303 "\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
1287 (setq icol (+ icol fortran-structure-indent))) 1304 (setq icol (+ icol fortran-structure-indent)))
1288 ((looking-at "end\\b[ \t]*[^ \t=(a-z]") 1305 ((looking-at fortran-end-prog-re1)
1289 ;; Previous END resets indent to minimum 1306 ;; Previous END resets indent to minimum
1290 (setq icol fortran-minimum-statement-indent)))))) 1307 (setq icol fortran-minimum-statement-indent))))))
1291 (save-excursion 1308 (save-excursion
1292 (beginning-of-line) 1309 (beginning-of-line)
1293 (cond ((looking-at "[ \t]*$")) 1310 (cond ((looking-at "[ \t]*$"))
1311 (looking-at "[ \t]*[0-9]+") 1328 (looking-at "[ \t]*[0-9]+")
1312 (fortran-check-for-matching-do)) 1329 (fortran-check-for-matching-do))
1313 (setq icol (- icol fortran-do-indent))) 1330 (setq icol (- icol fortran-do-indent)))
1314 (t 1331 (t
1315 (skip-chars-forward " \t0-9") 1332 (skip-chars-forward " \t0-9")
1316 (cond ((looking-at "end[ \t]*if\\b") 1333 (cond ((looking-at "end[ \t]*\\(if\\|select\\|where\\)\\b")
1317 (setq icol (- icol fortran-if-indent))) 1334 (setq icol (- icol fortran-if-indent)))
1318 ((looking-at "\\(else\\|elseif\\)\\b") 1335 ((looking-at "else\\(if\\)?\\b")
1319 (setq icol (- icol fortran-if-indent))) 1336 (setq icol (- icol fortran-if-indent)))
1320 ((looking-at "case[ \t]*(.*)[ \t]*\n") 1337 ((looking-at "case[ \t]*\\((.*)\\|default\\>\\)")
1321 (setq icol (- icol fortran-if-indent)))
1322 ((looking-at "case[ \t]*default\\b")
1323 (setq icol (- icol fortran-if-indent))) 1338 (setq icol (- icol fortran-if-indent)))
1324 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") 1339 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b")
1325 (setq icol (- icol fortran-if-indent)))
1326 ((looking-at "end[ \t]*where\\b")
1327 (setq icol (- icol fortran-if-indent))) 1340 (setq icol (- icol fortran-if-indent)))
1328 ((and (looking-at "continue\\b") 1341 ((and (looking-at "continue\\b")
1329 (fortran-check-for-matching-do)) 1342 (fortran-check-for-matching-do))
1330 (setq icol (- icol fortran-do-indent))) 1343 (setq icol (- icol fortran-do-indent)))
1331 ((looking-at "end[ \t]*do\\b") 1344 ((looking-at "end[ \t]*do\\b")
1332 (setq icol (- icol fortran-do-indent))) 1345 (setq icol (- icol fortran-do-indent)))
1333 ((looking-at 1346 ((looking-at "end[ \t]*\
1334 "end[ \t]*\
1335 \\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]") 1347 \\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]")
1336 (setq icol (- icol fortran-structure-indent))) 1348 (setq icol (- icol fortran-structure-indent)))
1337 ((looking-at 1349 ((and (looking-at fortran-end-prog-re1)
1338 "end[ \t]*select\\b[ \t]*[^ \t=(a-z]")
1339 (setq icol (- icol fortran-if-indent)))
1340 ((and (looking-at "end\\b[ \t]*[^ \t=(a-z]")
1341 (not (= icol fortran-minimum-statement-indent))) 1350 (not (= icol fortran-minimum-statement-indent)))
1342 (message "Warning: `end' not in column %d. Probably\ 1351 (message "Warning: `end' not in column %d. Probably\
1343 an unclosed block." fortran-minimum-statement-indent)))))) 1352 an unclosed block." fortran-minimum-statement-indent))))))
1344 (max fortran-minimum-statement-indent icol))) 1353 (max fortran-minimum-statement-indent icol)))
1345 1354
1457 (setq charnum (buffer-substring (point) 1466 (setq charnum (buffer-substring (point)
1458 (progn (skip-chars-forward "0-9") 1467 (progn (skip-chars-forward "0-9")
1459 (point)))) 1468 (point))))
1460 (beginning-of-line) 1469 (beginning-of-line)
1461 (and (re-search-backward 1470 (and (re-search-backward
1462 (concat "\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|" 1471 (concat "\\(" fortran-end-prog-re "\\)\\|"
1463 "\\(^[ \t0-9]*do[ \t]*0*" charnum "\\b\\)\\|" 1472 "\\(^[ \t0-9]*do[ \t]*0*" charnum "\\b\\)\\|"
1464 "\\(^[ \t]*0*" charnum "\\b\\)") 1473 "\\(^[ \t]*0*" charnum "\\b\\)")
1465 nil t) 1474 nil t)
1466 (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum)))))))) 1475 (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum))))))))
1467 1476
1468 (defun fortran-find-comment-start-skip () 1477 (defun fortran-find-comment-start-skip ()
1469 "Move to past `comment-start-skip' found on current line. 1478 "Move to past `comment-start-skip' found on current line.
1470 Return t if `comment-start-skip' found, nil if not." 1479 Return t if `comment-start-skip' found, nil if not."
1471 ;;; In order to move point only if comment-start-skip is found, 1480 ;; In order to move point only if comment-start-skip is found, this
1472 ;;; this one uses a lot of save-excursions. Note that re-search-forward 1481 ;; one uses a lot of save-excursions. Note that re-search-forward
1473 ;;; moves point even if comment-start-skip is inside a string-constant. 1482 ;; moves point even if comment-start-skip is inside a string-constant.
1474 ;;; Some code expects certain values for match-beginning and end 1483 ;; Some code expects certain values for match-beginning and end
1475 (interactive) 1484 (interactive)
1476 (if (save-excursion 1485 (if (save-excursion
1477 (re-search-forward comment-start-skip 1486 (re-search-forward comment-start-skip
1478 (save-excursion (end-of-line) (point)) t)) 1487 (save-excursion (end-of-line) (point)) t))
1479 (let ((save-match-beginning (match-beginning 0)) 1488 (let ((save-match-beginning (match-beginning 0))
1487 (save-excursion (end-of-line) (point)) t) 1496 (save-excursion (end-of-line) (point)) t)
1488 (goto-char (match-end 0)) 1497 (goto-char (match-end 0))
1489 t)) 1498 t))
1490 nil)) 1499 nil))
1491 1500
1492 ;;;From: simon@gnu (Simon Marshall) 1501 ;;From: simon@gnu (Simon Marshall)
1493 ;;; Find the next ! not in a string. 1502 ;; Find the next ! not in a string.
1494 (defun fortran-match-!-comment (limit) 1503 (defun fortran-match-!-comment (limit)
1495 (let (found) 1504 (let (found)
1496 (while (and (setq found (search-forward "!" limit t)) 1505 (while (and (setq found (search-forward "!" limit t))
1497 (fortran-is-in-string-p (point)))) 1506 (fortran-is-in-string-p (point))))
1498 (if (not found) 1507 (if (not found)
1507 ;; (let (found) 1516 ;; (let (found)
1508 ;; (while (and (setq found (re-search-forward "!.*" limit t)) 1517 ;; (while (and (setq found (re-search-forward "!.*" limit t))
1509 ;; (fortran-is-in-string-p (match-beginning 0)))) 1518 ;; (fortran-is-in-string-p (match-beginning 0))))
1510 ;; found)) 1519 ;; found))
1511 1520
1512 ;;;From: ralf@up3aud1.gwdg.de (Ralf Fassel) 1521 ;;From: ralf@up3aud1.gwdg.de (Ralf Fassel)
1513 ;;; Test if TAB format continuation lines work. 1522 ;; Test if TAB format continuation lines work.
1514 (defun fortran-is-in-string-p (where) 1523 (defun fortran-is-in-string-p (where)
1515 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string." 1524 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string."
1516 (save-excursion 1525 (save-excursion
1517 (goto-char where) 1526 (goto-char where)
1518 (cond 1527 (cond
1519 ((bolp) nil) ; bol is never inside a string 1528 ((bolp) nil) ; bol is never inside a string
1520 ((save-excursion ; comment lines too 1529 ((save-excursion ; comment lines too
1521 (beginning-of-line)(looking-at comment-line-start-skip)) nil) 1530 (beginning-of-line)
1531 (looking-at comment-line-start-skip)) nil)
1522 (t (let (;; ok, serious now. Init some local vars: 1532 (t (let (;; ok, serious now. Init some local vars:
1523 (parse-state '(0 nil nil nil nil nil 0)) 1533 (parse-state '(0 nil nil nil nil nil 0))
1524 (quoted-comment-start (if comment-start 1534 (quoted-comment-start (if comment-start
1525 (regexp-quote comment-start))) 1535 (regexp-quote comment-start)))
1526 (not-done t) 1536 (not-done t)
1540 ;; - not in a string and after comment-start? 1550 ;; - not in a string and after comment-start?
1541 (and (not (nth 3 parse-state)) 1551 (and (not (nth 3 parse-state))
1542 comment-start 1552 comment-start
1543 (equal comment-start 1553 (equal comment-start
1544 (char-to-string (preceding-char))))) 1554 (char-to-string (preceding-char)))))
1545 ;; get around a bug in forward-line in versions <= 18.57 1555 (if (> (forward-line) 0)
1546 (if (or (> (forward-line 1) 0) (eobp))
1547 (setq not-done nil)) 1556 (setq not-done nil))
1548 ;; else: 1557 ;; else:
1549 ;; if we are at beginning of code line, skip any 1558 ;; if we are at beginning of code line, skip any
1550 ;; whitespace, labels and tab continuation markers. 1559 ;; whitespace, labels and tab continuation markers.
1551 (if (bolp) (skip-chars-forward " \t0-9")) 1560 (if (bolp) (skip-chars-forward " \t0-9"))
1580 (interactive "P") 1589 (interactive "P")
1581 (prog1 (setq auto-fill-function 1590 (prog1 (setq auto-fill-function
1582 (if (if (null arg) 1591 (if (if (null arg)
1583 (not auto-fill-function) 1592 (not auto-fill-function)
1584 (> (prefix-numeric-value arg) 0)) 1593 (> (prefix-numeric-value arg) 0))
1585 'fortran-do-auto-fill 1594 #'fortran-do-auto-fill
1586 nil)) 1595 nil))
1587 (force-mode-line-update))) 1596 (force-mode-line-update)))
1588 1597
1589 (defun fortran-do-auto-fill () 1598 (defun fortran-do-auto-fill ()
1590 (if (> (current-column) fill-column) 1599 (if (> (current-column) fill-column)
1600 (save-excursion 1609 (save-excursion
1601 (goto-char bol) 1610 (goto-char bol)
1602 (if (looking-at comment-line-start-skip) 1611 (if (looking-at comment-line-start-skip)
1603 nil ; OK to break quotes on comment lines. 1612 nil ; OK to break quotes on comment lines.
1604 (move-to-column fill-column) 1613 (move-to-column fill-column)
1605 (cond ((fortran-is-in-string-p (point)) 1614 (if (fortran-is-in-string-p (point))
1606 (save-excursion (re-search-backward "[^']'[^']" bol t) 1615 (save-excursion (re-search-backward "\\S\"\\s\"\\S\"" bol t)
1607 (if fortran-break-before-delimiters 1616 (if fortran-break-before-delimiters
1608 (point) 1617 (point)
1609 (1+ (point))))) 1618 (1+ (point))))))))
1610 (t nil)))))
1611 ;;
1612 ;; decide where to split the line. If a position for a quoted 1619 ;; decide where to split the line. If a position for a quoted
1613 ;; string was found above then use that, else break the line 1620 ;; string was found above then use that, else break the line
1614 ;; before the last delimiter. 1621 ;; before the last delimiter.
1615 ;; Delimiters are whitespace, commas, and operators. 1622 ;; Delimiters are whitespace, commas, and operators.
1616 ;; Will break before a pair of *'s. 1623 ;; Will break before a pair of *'s.
1617 ;;
1618 (fill-point 1624 (fill-point
1619 (or quote 1625 (or quote
1620 (save-excursion 1626 (save-excursion
1621 (move-to-column (1+ fill-column)) 1627 (move-to-column (1+ fill-column))
1622 (skip-chars-backward "^ \t\n,'+-/*=)" 1628 (skip-chars-backward "^ \t\n,'+-/*=)"
1624 ;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)") 1630 ;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)")
1625 ) 1631 )
1626 (if (<= (point) (1+ bos)) 1632 (if (<= (point) (1+ bos))
1627 (progn 1633 (progn
1628 (move-to-column (1+ fill-column)) 1634 (move-to-column (1+ fill-column))
1629 ;;;what is this doing??? 1635 ;;what is this doing???
1630 (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t)) 1636 (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t))
1631 (goto-char bol)))) 1637 (goto-char bol))))
1632 (if (bolp) 1638 (if (bolp)
1633 (re-search-forward "[ \t]" opoint t) 1639 (re-search-forward "[ \t]" opoint t)
1634 (forward-char -1) 1640 (backward-char)
1635 (if (looking-at "'") 1641 (if (looking-at "\\s\"")
1636 (forward-char 1) 1642 (forward-char)
1637 (skip-chars-backward " \t\*"))) 1643 (skip-chars-backward " \t\*")))
1638 (if fortran-break-before-delimiters 1644 (if fortran-break-before-delimiters
1639 (point) 1645 (point)
1640 (1+ (point)))))) 1646 (1+ (point)))))))
1641 )
1642 ;; if we are in an in-line comment, don't break unless the 1647 ;; if we are in an in-line comment, don't break unless the
1643 ;; line of code is longer than it should be. Otherwise 1648 ;; line of code is longer than it should be. Otherwise
1644 ;; break the line at the column computed above. 1649 ;; break the line at the column computed above.
1645 ;; 1650 ;;
1646 ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s 1651 ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s
1661 (fortran-break-line)) 1666 (fortran-break-line))
1662 (save-excursion 1667 (save-excursion
1663 (if (> (save-excursion 1668 (if (> (save-excursion
1664 (goto-char fill-point) 1669 (goto-char fill-point)
1665 (current-column)) 1670 (current-column))
1666 (+ (calculate-fortran-indent) fortran-continuation-indent)) 1671 (+ (fortran-calculate-indent) fortran-continuation-indent))
1667 (progn 1672 (progn
1668 (goto-char fill-point) 1673 (goto-char fill-point)
1669 (fortran-break-line)))))) 1674 (fortran-break-line))))))
1670 )) 1675 ))
1671 (defun fortran-break-line () 1676 (defun fortran-break-line ()
1678 (if (and comment-start-skip (fortran-find-comment-start-skip)) 1683 (if (and comment-start-skip (fortran-find-comment-start-skip))
1679 (progn 1684 (progn
1680 (re-search-backward comment-start-skip bol t) 1685 (re-search-backward comment-start-skip bol t)
1681 (setq comment-string (buffer-substring (point) eol)) 1686 (setq comment-string (buffer-substring (point) eol))
1682 (delete-region (point) eol)))) 1687 (delete-region (point) eol))))
1683 ;;; Forward line 1 really needs to go to next non white line 1688 ;; Forward line 1 really needs to go to next non white line
1684 (if (save-excursion (forward-line 1) 1689 (if (save-excursion (forward-line)
1685 (or (looking-at " [^ 0\n]") 1690 (or (looking-at " [^ 0\n]")
1686 (looking-at "\t[1-9]"))) 1691 (looking-at "\t[1-9]")))
1687 (progn 1692 (progn
1688 (end-of-line) 1693 (end-of-line)
1689 (delete-region (point) (match-end 0)) 1694 (delete-region (point) (match-end 0))
1723 (setq minor-mode-alist (cons 1728 (setq minor-mode-alist (cons
1724 '(fortran-tab-mode-string 1729 '(fortran-tab-mode-string
1725 (indent-tabs-mode fortran-tab-mode-string)) 1730 (indent-tabs-mode fortran-tab-mode-string))
1726 minor-mode-alist))) 1731 minor-mode-alist)))
1727 1732
1733 (defun fortran-fill-paragraph (&optional justify)
1734 "Fill surrounding comment block as paragraphs, else fill statement.
1735
1736 Intended as the value of `fill-paragraph-function'."
1737 (interactive "P")
1738 (save-excursion
1739 (beginning-of-line)
1740 (if (not (looking-at "[Cc*]"))
1741 (fortran-fill-statement)
1742 ;; We're in a comment block. Find the start and end of a
1743 ;; paragraph, delimited either by non-comment lines or empty
1744 ;; comments. (Get positions as markers, since the
1745 ;; `indent-region' below can shift the block's end).
1746 (let* ((non-empty-comment (concat "\\(" comment-line-start-skip
1747 "\\)" "[^ \t\n]"))
1748 (start (save-excursion
1749 ;; Find (start of) first line.
1750 (while (and (zerop (forward-line -1))
1751 (looking-at non-empty-comment)))
1752 (or (looking-at non-empty-comment)
1753 (forward-line)) ; overshot
1754 (point-marker)))
1755 (end (save-excursion
1756 ;; Find start of first line past region to fill.
1757 (while (progn (forward-line)
1758 (looking-at non-empty-comment)))
1759 (point-marker))))
1760 ;; Indent the block, find the string comprising the effective
1761 ;; comment start skip and use that as a fill-prefix for
1762 ;; filling the region.
1763 (indent-region start end nil)
1764 (let ((paragraph-ignore-fill-prefix nil)
1765 (fill-prefix (progn (beginning-of-line)
1766 (looking-at comment-line-start-skip)
1767 (match-string 0))))
1768 (let (fill-paragraph-function)
1769 (fill-region start end justify))) ; with normal `fill-paragraph'
1770 (set-marker start nil)
1771 (set-marker end nil)))))
1772
1773 (defun fortran-fill-statement ()
1774 "Fill a fortran statement up to `fill-column'."
1775 (interactive)
1776 (if (not (save-excursion
1777 (beginning-of-line)
1778 (or (looking-at "[ \t]*$")
1779 (looking-at comment-line-start-skip)
1780 (and comment-start-skip
1781 (looking-at (concat "[ \t]*" comment-start-skip))))))
1782 (save-excursion
1783 ;; Find beginning of statement.
1784 (fortran-next-statement)
1785 (fortran-previous-statement)
1786 ;; Re-indent initially.
1787 (fortran-indent-line)
1788 ;; Replace newline plus continuation field plus indentation with
1789 ;; single space.
1790 (while (progn
1791 (forward-line)
1792 (fortran-remove-continuation)))
1793 (fortran-previous-statement)))
1794 (fortran-indent-line)
1795 t) ; must return t for fill-paragraph
1796
1728 (provide 'fortran) 1797 (provide 'fortran)
1729 1798
1730 ;;; fortran.el ends here 1799 ;;; fortran.el ends here