aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Love1998-04-07 18:59:44 +0000
committerDave Love1998-04-07 18:59:44 +0000
commit1eb6bf70dcd005d90b0049ea9f9b74881a2e335e (patch)
treedbc1d24704f7510a4893a86e5f8521188cb7314e
parent15171a06d35ecbe33a98aa48751e47a717684bcd (diff)
downloademacs-1eb6bf70dcd005d90b0049ea9f9b74881a2e335e.tar.gz
emacs-1eb6bf70dcd005d90b0049ea9f9b74881a2e335e.zip
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.
-rw-r--r--lisp/progmodes/fortran.el737
1 files changed, 403 insertions, 334 deletions
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index 4b38c30cd0b..a20b42a19b5 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -42,6 +42,13 @@
42 42
43;;; Code: 43;;; Code:
44 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.
51
45(require 'easymenu) 52(require 'easymenu)
46 53
47(defgroup fortran nil 54(defgroup fortran nil
@@ -73,6 +80,7 @@ with a character in column 6."
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."
@@ -102,7 +110,7 @@ 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
104Fortran indentation plus `fortran-comment-line-extra-indent'." 112Fortran 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
@@ -168,19 +176,14 @@ Normally $."
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 \
172at start of each line in region." 180line 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 \
178typed." 186column 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
@@ -204,11 +207,11 @@ This variable used in TAB format mode.")
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 \
208style.") 211format 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
@@ -252,115 +255,109 @@ style.")
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.")
@@ -378,8 +375,9 @@ style.")
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-\\|[*()+]\\)*\
382subroutine\\|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
@@ -406,7 +404,7 @@ subroutine\\|entry\\|block\\s-*data\\|program\\)[ \t" fortran-continuation-strin
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)
@@ -452,6 +450,7 @@ subroutine\\|entry\\|block\\s-*data\\|program\\)[ \t" fortran-continuation-strin
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")
@@ -524,7 +523,9 @@ subroutine\\|entry\\|block\\s-*data\\|program\\)[ \t" fortran-continuation-strin
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 ()
@@ -532,8 +533,8 @@ subroutine\\|entry\\|block\\s-*data\\|program\\)[ \t" fortran-continuation-strin
532\\[fortran-indent-line] indents the current Fortran line correctly. 533\\[fortran-indent-line] indents the current Fortran line correctly.
533DO statements must not share a common CONTINUE. 534DO statements must not share a common CONTINUE.
534 535
535Type ;? or ;\\[help-command] to display a list of built-in\ 536Type ;? or ;\\[help-command] to display a list of built-in abbrevs for
536 abbrevs for Fortran keywords. 537Fortran keywords.
537 538
538Key definitions: 539Key definitions:
539\\{fortran-mode-map} 540\\{fortran-mode-map}
@@ -591,7 +592,7 @@ Variables controlling indentation style and extra features:
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
597Turning on Fortran mode calls the value of the variable `fortran-mode-hook' 598Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
@@ -629,23 +630,28 @@ with no args, if that value is non-nil."
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 ()
@@ -693,7 +699,7 @@ or on a new line inserted before this line if this line is not blank."
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.
@@ -806,26 +812,23 @@ See also `fortran-window-create'."
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 ()
@@ -859,8 +862,8 @@ Auto-indent does not happen if a numeric ARG is used."
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.
@@ -872,31 +875,34 @@ Auto-indent does not happen if a numeric ARG is used."
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.
@@ -963,8 +969,11 @@ The subprogram visible is the one that contains or follows point."
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"))
@@ -988,8 +997,11 @@ The subprogram visible is the one that contains or follows point."
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"))
@@ -1025,52 +1037,54 @@ The marks are pushed."
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.
@@ -1085,113 +1099,115 @@ The marks are pushed."
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]")))
1104 1120
1105 (skip-chars-forward " \t0-9") 1121 (skip-chars-forward " \t0-9")
1106 (cond ((looking-at "end[ \t]*if\\b") 1122 (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)))
@@ -1223,11 +1239,12 @@ An abbrev before point is expanded if `abbrev-mode' is non-nil."
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
@@ -1240,7 +1257,7 @@ An abbrev before point is expanded if `abbrev-mode' is non-nil."
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
@@ -1256,7 +1273,7 @@ An abbrev before point is expanded if `abbrev-mode' is non-nil."
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)
@@ -1268,11 +1285,11 @@ An abbrev before point is expanded if `abbrev-mode' is non-nil."
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)))
@@ -1285,7 +1302,7 @@ An abbrev before point is expanded if `abbrev-mode' is non-nil."
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
@@ -1313,31 +1330,23 @@ An abbrev before point is expanded if `abbrev-mode' is non-nil."
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)))
1318 ((looking-at "\\(else\\|elseif\\)\\b")
1319 (setq icol (- icol fortran-if-indent))) 1334 (setq icol (- icol fortran-if-indent)))
1320 ((looking-at "case[ \t]*(.*)[ \t]*\n") 1335 ((looking-at "else\\(if\\)?\\b")
1321 (setq icol (- icol fortran-if-indent))) 1336 (setq icol (- icol fortran-if-indent)))
1322 ((looking-at "case[ \t]*default\\b") 1337 ((looking-at "case[ \t]*\\((.*)\\|default\\>\\)")
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))) 1340 (setq icol (- icol fortran-if-indent)))
1326 ((looking-at "end[ \t]*where\\b")
1327 (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))))))
@@ -1459,7 +1468,7 @@ Otherwise return nil."
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)
@@ -1468,10 +1477,10 @@ Otherwise return nil."
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.
1470Return t if `comment-start-skip' found, nil if not." 1479Return 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
@@ -1489,8 +1498,8 @@ Return t if `comment-start-skip' found, nil if not."
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))
@@ -1509,8 +1518,8 @@ Return t if `comment-start-skip' found, nil if not."
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
@@ -1518,7 +1527,8 @@ Return t if `comment-start-skip' found, nil if not."
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
@@ -1542,8 +1552,7 @@ Return t if `comment-start-skip' found, nil if not."
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
@@ -1582,7 +1591,7 @@ automatically breaks the line at a previous space."
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
@@ -1602,19 +1611,16 @@ automatically breaks the line at a previous space."
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
@@ -1626,19 +1632,18 @@ automatically breaks the line at a previous space."
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.
@@ -1663,7 +1668,7 @@ automatically breaks the line at a previous space."
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))))))
@@ -1680,8 +1685,8 @@ automatically breaks the line at a previous space."
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
@@ -1725,6 +1730,70 @@ file before the end or the first `fortran-analyze-depth' lines."
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
1736Intended 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