aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2003-04-15 19:22:31 +0000
committerGlenn Morris2003-04-15 19:22:31 +0000
commit5b04210ced179062b2779a85055a612e8b12fe70 (patch)
tree3928c259baba9d19825202ef24192c8ee0b00ead
parenta729409a9638dd446014238160a2f9155709f6f3 (diff)
downloademacs-5b04210ced179062b2779a85055a612e8b12fe70.tar.gz
emacs-5b04210ced179062b2779a85055a612e8b12fe70.zip
Whitespace changes, some re-ordering of code, trivial commentary change.
(fortran, fortran-indent, fortran-comment) (fortran-tab-mode-default, fortran-continuation-indent) (fortran-comment-indent-style, fortran-blink-matching-if) (fortran-continuation-string, fortran-electric-line-number) (fortran-break-before-delimiters, fortran-mode-hook) (fortran-end-prog-re, fortran-imenu-generic-expression): Minor doc changes. (fortran-tab-mode-minor-mode-string): New variable. (fortran-tab-mode-string): Now customization is meaningful. (fortran-column-ruler-fixed, fortran-column-ruler-tab) (fortran-analyze-depth): Use defcustom. (fortran-if-start-re, fortran-end-prog-re1, fortran-fill) (fortran-break-line, fortran-prepare-abbrev-list-buffer) (fortran-auto-fill): Add doc string. (fortran-type-types): New constant (was local to let binding). (fortran-font-lock-keywords-1, fortran-font-lock-keywords-2) (fortran-font-lock-syntactic-keywords): Initialize in defvar. (fortran-font-lock-keywords-3): Initialize in defvar. Use 1+ now depth of fortran-type-types has changed. Remove extra and. (fortran-mode-menu): Minor re-organization. Use lookup-key. (fortran-mode): Doc changes. Some re-organization. Use fortran-tab-mode-minor-mode-string. (fortran-comment-indent): Add doc string. Move save-excursion. Use 1+. (fortran-indent-comment, fortran-fill-statement): Change interactive spec. Use unless. (fortran-comment-region): Doc change. Reverse logic of arg test. Use zerop. (fortran-abbrev-start, fortran-split-line) (fortran-electric-line-number, fortran-indent-subprogram) (fortran-strip-sequence-nos): Change interactive spec. (fortran-remove-continuation): Add doc string. Use when. (fortran-numerical-continuation-char): Doc change. Use 1+. (fortran-previous-statement, fortran-next-statement) (fortran-beginning-do, fortran-calculate-indent) (fortran-end-do, fortran-end-if, fortran-beginning-if): Use zerop, 1+, 1-. (fortran-blink-match, fortran-check-for-matching-do): Use when. (fortran-indent-line): Change interactive spec. Remove un-needed if. Use when. (fortran-indent-to-column): Doc change. Use when, unless. (fortran-find-comment-start-skip): No longer interactive. (fortran-analyze-file-format): Minor doc change. Remove un-needed setq. (minor-mode-alist): Use add-to-list. (fortran-fill-paragraph): Change interactive spec, doc string.
-rw-r--r--lisp/ChangeLog66
-rw-r--r--lisp/progmodes/fortran.el1056
2 files changed, 593 insertions, 529 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a84f61b73f3..4c977f57757 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,69 @@
12003-04-15 Glenn Morris <gmorris@ast.cam.ac.uk>
2
3 * progmodes/fortran.el: Whitespace changes, some re-ordering of
4 code, trivial commentary change.
5 (fortran, fortran-indent, fortran-comment)
6 (fortran-tab-mode-default, fortran-continuation-indent)
7 (fortran-comment-indent-style, fortran-blink-matching-if)
8 (fortran-continuation-string, fortran-electric-line-number)
9 (fortran-break-before-delimiters, fortran-mode-hook)
10 (fortran-end-prog-re, fortran-imenu-generic-expression): Minor
11 doc changes.
12 (fortran-tab-mode-minor-mode-string): New variable.
13 (fortran-tab-mode-string): Now customization is meaningful.
14 (fortran-column-ruler-fixed, fortran-column-ruler-tab)
15 (fortran-analyze-depth): Use defcustom.
16 (fortran-if-start-re, fortran-end-prog-re1, fortran-fill)
17 (fortran-break-line, fortran-prepare-abbrev-list-buffer)
18 (fortran-auto-fill): Add doc string.
19 (fortran-type-types): New constant (was local to let binding).
20 (fortran-font-lock-keywords-1, fortran-font-lock-keywords-2)
21 (fortran-font-lock-syntactic-keywords): Initialize in defvar.
22 (fortran-font-lock-keywords-3): Initialize in defvar. Use 1+ now
23 depth of fortran-type-types has changed. Remove extra and.
24 (fortran-mode-menu): Minor re-organization. Use lookup-key.
25 (fortran-mode): Doc changes. Some re-organization. Use
26 fortran-tab-mode-minor-mode-string.
27 (fortran-comment-indent): Add doc string. Move save-excursion.
28 Use 1+.
29 (fortran-indent-comment, fortran-fill-statement): Change
30 interactive spec. Use unless.
31 (fortran-comment-region): Doc change. Reverse logic of arg
32 test. Use zerop.
33 (fortran-abbrev-start, fortran-split-line)
34 (fortran-electric-line-number, fortran-indent-subprogram)
35 (fortran-strip-sequence-nos): Change interactive spec.
36 (fortran-remove-continuation): Add doc string. Use when.
37 (fortran-numerical-continuation-char): Doc change. Use 1+.
38 (fortran-previous-statement, fortran-next-statement)
39 (fortran-beginning-do, fortran-calculate-indent)
40 (fortran-end-do, fortran-end-if, fortran-beginning-if): Use
41 zerop, 1+, 1-.
42 (fortran-blink-match, fortran-check-for-matching-do): Use when.
43 (fortran-indent-line): Change interactive spec. Remove un-needed
44 if. Use when.
45 (fortran-indent-to-column): Doc change. Use when, unless.
46 (fortran-find-comment-start-skip): No longer interactive.
47 (fortran-analyze-file-format): Minor doc change. Remove
48 un-needed setq.
49 (minor-mode-alist): Use add-to-list.
50 (fortran-fill-paragraph): Change interactive spec, doc string.
51
52 * progmodes/f90.el: Whitespace changes, trivial commentary
53 changes.
54 (f90, f90-indent, f90-program-indent, f90-continuation-indent)
55 (f90-indented-comment-re, f90-imenu-generic-expression)
56 (f90-mark-subprogram, f90-join-lines): Minor doc changes.
57 (f90-menu): Shift definition to initialization of f90-mode-map.
58 Add customization section.
59 (f90-mode): Minor doc change. Do not call easy-menu-add.
60 Set `beginning-of-defun-function' and `end-of-defun-function' to
61 appropriate F90 functions.
62 (f90-indent-line, f90-indent-line, f90-indent-subprogram)
63 (f90-break-line, f90-do-auto-fill, f90-insert-end)
64 (f90-upcase-keywords, f90-capitalize-keywords)
65 (f90-downcase-keywords): Change interactive spec.
66
12003-04-14 Andrew Choi <akochoi@shaw.ca> 672003-04-14 Andrew Choi <akochoi@shaw.ca>
2 68
3 * term/mac-win.el: Unconditionally set process-connection-type to 69 * term/mac-win.el: Unconditionally set process-connection-type to
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index 0f7bfa4d576..ecbe9a0241e 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -5,7 +5,7 @@
5 5
6;; Author: Michael D. Prange <prange@erl.mit.edu> 6;; Author: Michael D. Prange <prange@erl.mit.edu>
7;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> 7;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk>
8;; Keywords: languages 8;; Keywords: fortran, languages
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
11 11
@@ -53,73 +53,86 @@
53;; second in column 6. 53;; second in column 6.
54;; * Support any other extensions to f77 grokked by GNU Fortran I've missed. 54;; * Support any other extensions to f77 grokked by GNU Fortran I've missed.
55 55
56(eval-when-compile ; silence compiler
57 (defvar imenu-case-fold-search)
58 (defvar imenu-syntax-alist))
59
60
56(defgroup fortran nil 61(defgroup fortran nil
57 "Fortran mode for Emacs" 62 "Major mode for editing fixed format Fortran code."
58 :link '(custom-manual "(emacs)Fortran") 63 :link '(custom-manual "(emacs)Fortran")
59 :group 'languages) 64 :group 'languages)
60 65
61(defgroup fortran-indent nil 66(defgroup fortran-indent nil
62 "Indentation variables in Fortran mode" 67 "Indentation variables in Fortran mode."
63 :prefix "fortran-" 68 :prefix "fortran-"
64 :group 'fortran) 69 :group 'fortran)
65 70
66(defgroup fortran-comment nil 71(defgroup fortran-comment nil
67 "Comment-handling variables in Fortran mode" 72 "Comment-handling variables in Fortran mode."
68 :prefix "fortran-" 73 :prefix "fortran-"
69 :group 'fortran) 74 :group 'fortran)
70 75
71 76
72;;;###autoload 77;;;###autoload
73(defcustom fortran-tab-mode-default nil 78(defcustom fortran-tab-mode-default nil
74 "*Default tabbing/carriage control style for empty files in Fortran mode. 79 "*Default tabbing/carriage control style for empty files in Fortran mode.
75A value of t specifies tab-digit style of continuation control. 80A non-nil value specifies tab-digit style of continuation control.
76A value of nil specifies that continuation lines are marked 81A value of nil specifies that continuation lines are marked
77with a character in column 6." 82with a character in column 6."
78 :type 'boolean 83 :type 'boolean
79 :group 'fortran-indent) 84 :group 'fortran-indent)
80 85
81;; Buffer local, used to display mode line. 86(defcustom fortran-tab-mode-string " TAB"
82(defcustom fortran-tab-mode-string nil 87 "*String to appear in mode line in TAB format buffers.
83 "String to appear in mode line when TAB format mode is on." 88Should have a leading space."
84 :type '(choice (const nil) string) 89 :type 'string
85 :group 'fortran-indent) 90 :group 'fortran-indent)
86(make-variable-buffer-local 'fortran-tab-mode-string) 91
92(defvar fortran-tab-mode-minor-mode-string nil
93 "Internal variable used for `minor-mode-alist' in Fortran mode.
94Do not change the value of this variable - edit `fortran-tab-mode-string'
95instead.")
96(make-variable-buffer-local 'fortran-tab-mode-minor-mode-string)
97
98(add-to-list 'minor-mode-alist
99 '(fortran-tab-mode-minor-mode-string
100 (indent-tabs-mode fortran-tab-mode-minor-mode-string)))
87 101
88(defcustom fortran-do-indent 3 102(defcustom fortran-do-indent 3
89 "*Extra indentation applied to DO blocks." 103 "*Extra indentation applied to DO blocks."
90 :type 'integer 104 :type 'integer
91 :group 'fortran-indent) 105 :group 'fortran-indent)
92 106
93(defcustom fortran-if-indent 3 107(defcustom fortran-if-indent 3
94 "*Extra indentation applied to IF blocks." 108 "*Extra indentation applied to IF blocks."
95 :type 'integer 109 :type 'integer
96 :group 'fortran-indent) 110 :group 'fortran-indent)
97 111
98(defcustom fortran-structure-indent 3 112(defcustom fortran-structure-indent 3
99 "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks." 113 "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks."
100 :type 'integer 114 :type 'integer
101 :group 'fortran-indent) 115 :group 'fortran-indent)
102 116
103(defcustom fortran-continuation-indent 5 117(defcustom fortran-continuation-indent 5
104 "*Extra indentation applied to Fortran continuation lines." 118 "*Extra indentation applied to continuation lines."
105 :type 'integer 119 :type 'integer
106 :group 'fortran-indent) 120 :group 'fortran-indent)
107 121
108(defcustom fortran-comment-indent-style 'fixed 122(defcustom fortran-comment-indent-style 'fixed
109 "*How to indent comments. 123 "*How to indent comments.
110nil forces comment lines not to be touched, 124nil forces comment lines not to be touched;
111`fixed' makes fixed comment indentation to `fortran-comment-line-extra-indent' 125`fixed' indents to `fortran-comment-line-extra-indent' columns beyond
112 columns beyond `fortran-minimum-statement-indent-fixed' (for 126 `fortran-minimum-statement-indent-fixed' (if `indent-tabs-mode' nil), or
113 `indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for 127 `fortran-minimum-statement-indent-tab' (if `indent-tabs-mode' non-nil);
114 `indent-tabs-mode' of t), and
115`relative' indents to current Fortran indentation plus 128`relative' indents to current Fortran indentation plus
116 `fortran-comment-line-extra-indent'." 129 `fortran-comment-line-extra-indent'."
117 :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative)) 130 :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative))
118 :group 'fortran-indent) 131 :group 'fortran-indent)
119 132
120(defcustom fortran-comment-line-extra-indent 0 133(defcustom fortran-comment-line-extra-indent 0
121 "*Amount of extra indentation for text within full-line comments." 134 "*Amount of extra indentation for text within full-line comments."
122 :type 'integer 135 :type 'integer
123 :group 'fortran-indent 136 :group 'fortran-indent
124 :group 'fortran-comment) 137 :group 'fortran-comment)
125 138
@@ -127,8 +140,8 @@ nil forces comment lines not to be touched,
127 "*Delimiter inserted to start new full-line comment. 140 "*Delimiter inserted to start new full-line comment.
128You might want to change this to \"*\", for instance." 141You might want to change this to \"*\", for instance."
129 :version "21.1" 142 :version "21.1"
130 :type 'string 143 :type 'string
131 :group 'fortran-comment) 144 :group 'fortran-comment)
132 145
133;; This used to match preprocessor lines too, but that messes up 146;; This used to match preprocessor lines too, but that messes up
134;; filling and doesn't seem to be necessary. 147;; filling and doesn't seem to be necessary.
@@ -136,8 +149,8 @@ You might want to change this to \"*\", for instance."
136 "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*" 149 "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*"
137 "*Regexp to match the start of a full-line comment." 150 "*Regexp to match the start of a full-line comment."
138 :version "21.1" 151 :version "21.1"
139 :type 'regexp 152 :type 'regexp
140 :group 'fortran-comment) 153 :group 'fortran-comment)
141 154
142(defcustom fortran-directive-re 155(defcustom fortran-directive-re
143 "^[ \t]*#.*" 156 "^[ \t]*#.*"
@@ -145,17 +158,17 @@ You might want to change this to \"*\", for instance."
145The matching text will be fontified with `font-lock-keyword-face'. 158The matching text will be fontified with `font-lock-keyword-face'.
146The matching line will be given zero indentation." 159The matching line will be given zero indentation."
147 :version "21.4" 160 :version "21.4"
148 :type 'regexp 161 :type 'regexp
149 :group 'fortran-indent) 162 :group 'fortran-indent)
150 163
151(defcustom fortran-minimum-statement-indent-fixed 6 164(defcustom fortran-minimum-statement-indent-fixed 6
152 "*Minimum statement indentation for fixed format continuation style." 165 "*Minimum statement indentation for fixed format continuation style."
153 :type 'integer 166 :type 'integer
154 :group 'fortran-indent) 167 :group 'fortran-indent)
155 168
156(defcustom fortran-minimum-statement-indent-tab (max tab-width 6) 169(defcustom fortran-minimum-statement-indent-tab (max tab-width 6)
157 "*Minimum statement indentation for TAB format continuation style." 170 "*Minimum statement indentation for TAB format continuation style."
158 :type 'integer 171 :type 'integer
159 :group 'fortran-indent) 172 :group 'fortran-indent)
160 173
161;; Note that this is documented in the v18 manuals as being a string 174;; Note that this is documented in the v18 manuals as being a string
@@ -164,229 +177,208 @@ The matching line will be given zero indentation."
164(defcustom fortran-comment-indent-char " " 177(defcustom fortran-comment-indent-char " "
165 "*Single-character string inserted for Fortran comment indentation. 178 "*Single-character string inserted for Fortran comment indentation.
166Normally a space." 179Normally a space."
167 :type 'string 180 :type 'string
168 :group 'fortran-comment) 181 :group 'fortran-comment)
169 182
170(defcustom fortran-line-number-indent 1 183(defcustom fortran-line-number-indent 1
171 "*Maximum indentation for Fortran line numbers. 184 "*Maximum indentation for Fortran line numbers.
1725 means right-justify them within their five-column field." 1855 means right-justify them within their five-column field."
173 :type 'integer 186 :type 'integer
174 :group 'fortran-indent) 187 :group 'fortran-indent)
175 188
176(defcustom fortran-check-all-num-for-matching-do nil 189(defcustom fortran-check-all-num-for-matching-do nil
177 "*Non-nil causes all numbered lines to be treated as possible DO loop ends." 190 "*Non-nil causes all numbered lines to be treated as possible DO loop ends."
178 :type 'boolean 191 :type 'boolean
179 :group 'fortran) 192 :group 'fortran)
180 193
181(defcustom fortran-blink-matching-if nil 194(defcustom fortran-blink-matching-if nil
182 "*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF. 195 "*Non-nil causes \\[fortran-indent-line] on ENDIF to blink on matching IF.
183Also, from an ENDDO statement blink on matching DO [WHILE] statement." 196Also, from an ENDDO statement blink on matching DO [WHILE] statement."
184 :type 'boolean 197 :type 'boolean
185 :group 'fortran) 198 :group 'fortran)
186 199
187(defcustom fortran-continuation-string "$" 200(defcustom fortran-continuation-string "$"
188 "*Single-character string used for Fortran continuation lines. 201 "*Single-character string used for Fortran continuation lines.
189In fixed format continuation style, this character is inserted in 202In fixed format continuation style, this character is inserted in
190column 6 by \\[fortran-split-line] to begin a continuation line. 203column 6 by \\[fortran-split-line] to begin a continuation line.
191Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will 204Also, if \\[fortran-indent-line] finds this at the beginning of a
192convert the line into a continuation line of the appropriate style. 205line, it will convert the line into a continuation line of the
193Normally $." 206appropriate style. Normally $."
194 :type 'string 207 :type 'string
195 :group 'fortran) 208 :group 'fortran)
196 209
197(defcustom fortran-comment-region "c$$$" 210(defcustom fortran-comment-region "c$$$"
198 "*String inserted by \\[fortran-comment-region] at start of each \ 211 "*String inserted by \\[fortran-comment-region] at start of each \
199line in region." 212line in region."
200 :type 'string 213 :type 'string
201 :group 'fortran-comment) 214 :group 'fortran-comment)
202 215
203(defcustom fortran-electric-line-number t 216(defcustom fortran-electric-line-number t
204 "*Non-nil causes line number digits to be moved to the correct \ 217 "*Non-nil causes line numbers to be moved to the correct column as typed."
205column as typed." 218 :type 'boolean
206 :type 'boolean
207 :group 'fortran) 219 :group 'fortran)
208 220
209(defvar fortran-column-ruler-fixed 221(defcustom fortran-column-ruler-fixed
210 "0 4 6 10 20 30 40 5\ 222 "0 4 6 10 20 30 40 5\
2110 60 70\n\ 2230 60 70\n\
212\[ ]|{ | | | | | | | | \ 224\[ ]|{ | | | | | | | | \
213\| | | | |}\n" 225\| | | | |}\n"
214 "String displayed above current line by \\[fortran-column-ruler]. 226 "String displayed above current line by \\[fortran-column-ruler].
215This variable used in fixed format mode.") 227This variable is used in fixed format mode.
228See the variable `fortran-column-ruler-tab' for TAB format mode."
229 :type 'string
230 :group 'fortran)
216 231
217(defvar fortran-column-ruler-tab 232(defcustom fortran-column-ruler-tab
218 "0 810 20 30 40 5\ 233 "0 810 20 30 40 5\
2190 60 70\n\ 2340 60 70\n\
220\[ ]| { | | | | | | | | \ 235\[ ]| { | | | | | | | | \
221\| | | | |}\n" 236\| | | | |}\n"
222 "String displayed above current line by \\[fortran-column-ruler]. 237 "String displayed above current line by \\[fortran-column-ruler].
223This variable used in TAB format mode.") 238This variable is used in TAB format mode.
239See the variable `fortran-column-ruler-fixed' for fixed format mode."
240 :type 'string
241 :group 'fortran)
224 242
225(defvar fortran-analyze-depth 100 243(defcustom fortran-analyze-depth 100
226 "Number of lines to scan to determine whether to use fixed or TAB \ 244 "Number of lines to scan to identify fixed or TAB format style."
227format style.") 245 :type 'integer
246 :group 'fortran)
228 247
229(defcustom fortran-break-before-delimiters t 248(defcustom fortran-break-before-delimiters t
230 "*Non-nil causes filling to break lines before delimiters." 249 "*Non-nil causes filling to break lines before delimiters.
231 :type 'boolean 250Delimiters are whitespace, commas, quotes, and operators."
251 :type 'boolean
232 :group 'fortran) 252 :group 'fortran)
233 253
234(defvar fortran-mode-syntax-table 254(defcustom fortran-mode-hook nil
235 (let ((table (make-syntax-table))) 255 "Hook run when entering Fortran mode."
236 ;; We might like `;' to be punctuation (g77 multi-statement 256 :type 'hook
237 ;; lines), but that screws abbrevs. 257 :group 'fortran)
238 (modify-syntax-entry ?\; "w" table)
239 (modify-syntax-entry ?\r " " table)
240 (modify-syntax-entry ?+ "." table)
241 (modify-syntax-entry ?- "." table)
242 (modify-syntax-entry ?= "." table)
243 (modify-syntax-entry ?* "." table)
244 (modify-syntax-entry ?/ "." table)
245 (modify-syntax-entry ?\' "\"" table)
246 (modify-syntax-entry ?\" "\"" table)
247 ;; Consistent with GNU Fortran -- see the manual.
248 (modify-syntax-entry ?\\ "\\" table)
249 ;; This might be better as punctuation, as for C, but this way you
250 ;; can treat floating-point numbers as symbols.
251 (modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b'
252 (modify-syntax-entry ?_ "_" table)
253 (modify-syntax-entry ?$ "_" table) ; esp. VMSisms
254 (modify-syntax-entry ?\! "<" table)
255 (modify-syntax-entry ?\n ">" table)
256 table)
257 "Syntax table in use in Fortran mode buffers.")
258 258
259;; Comments are real pain in Fortran because there is no way to 259
260;; represent the standard comment syntax in an Emacs syntax table. 260(defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*("
261;; (We can do so for F90-style). Therefore an unmatched quote in a 261 "Regexp matching the start of an IF statement.")
262;; standard comment will throw fontification off on the wrong track. 262
263;; So we do syntactic fontification with regexps. 263(defvar fortran-end-prog-re1
264 "end\
265\\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\
266\\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?"
267 "Regexp possibly matching the end of a subprogram.")
264 268
265(defvar fortran-font-lock-keywords-1 nil 269(defvar fortran-end-prog-re
270 (concat "^[ \t0-9]*" fortran-end-prog-re1)
271 "Regexp possibly matching the end of a subprogram, from the line start.
272See also `fortran-end-prog-re1'.")
273
274(defconst fortran-type-types
275 (concat "\\<"
276 (mapconcat 'identity ; " " -> "[ \t]*"
277 (split-string
278 (regexp-opt
279 (let ((simple-types
280 '("character" "byte" "integer" "logical"
281 "none" "real" "complex"
282 "double precision" "double complex"))
283 (structured-types '("structure" "union" "map"))
284 (other-types '("record" "dimension"
285 "parameter" "common" "save"
286 "external" "intrinsic" "data"
287 "equivalence")))
288 (append
289 (mapcar (lambda (x) (concat "implicit " x))
290 simple-types)
291 simple-types
292 (mapcar (lambda (x) (concat "end " x))
293 structured-types)
294 structured-types
295 other-types)) 'paren))
296 "[ \t]*") "\\>")
297 "Regexp matching Fortran types.")
298
299(defvar fortran-font-lock-keywords-1
300 ;; Program, subroutine and function declarations, plus calls.
301 '(("\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|\
302program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?"
303 (1 font-lock-keyword-face)
304 (2 font-lock-function-name-face nil t)))
266 "Subdued level highlighting for Fortran mode.") 305 "Subdued level highlighting for Fortran mode.")
267 306
268(defvar fortran-font-lock-keywords-2 nil 307(defvar fortran-font-lock-keywords-2
308 (append fortran-font-lock-keywords-1
309 (list
310 ;; Fontify all type specifiers (must be first - see below).
311 (cons fortran-type-types 'font-lock-type-face)
312 ;; Builtin keywords (except logical, do and goto - see below).
313 (concat "\\<" (regexp-opt
314 '("continue" "format" "end" "enddo"
315 "if" "then" "else" "endif" "elseif"
316 "while" "inquire" "stop" "return"
317 "include" "open" "close" "read"
318 "write" "format" "print" "select" "case"
319 "cycle" "exit" "rewind" "backspace")
320 'paren) "\\>")
321 ;; Builtin operators.
322 (concat "\\." (regexp-opt
323 '("and" "or" "not" "lt" "le" "eq" "ge"
324 "gt" "ne" "true" "false")
325 'paren) "\\.")
326 ;; do/goto keywords and targets, and goto tags.
327 '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
328 (1 font-lock-keyword-face)
329 (2 font-lock-constant-face nil t))
330 '("^ *\\([0-9]+\\)" . font-lock-constant-face)))
269 "Medium level highlighting for Fortran mode.") 331 "Medium level highlighting for Fortran mode.")
270 332
271(defvar fortran-font-lock-keywords-3 nil 333(defvar fortran-font-lock-keywords-3
334 (append
335 fortran-font-lock-keywords-1
336 ;; All type specifiers plus their declared items.
337 (list
338 (list (concat fortran-type-types "[ \t(/]*\\(*\\)?")
339 ;; Type specifier.
340 '(1 font-lock-type-face)
341 ;; Declaration item (or just /.../ block name).
342 `(font-lock-match-c-style-declaration-item-and-skip-to-next
343 ;; Start after any *(...) expression.
344 (condition-case nil
345 (and (match-beginning ,(1+ (regexp-opt-depth
346 fortran-type-types)))
347 (forward-sexp)
348 (forward-sexp))
349 (error nil))
350 ;; No need to clean up.
351 nil
352 ;; Fontify as a variable name, functions fontified elsewhere.
353 (1 font-lock-variable-name-face nil t))))
354 ;; Things extra to `fortran-font-lock-keywords-3' (must be done first).
355 (list
356 ;; Goto-like `err=label'/`end=label' in read/write statements.
357 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
358 (1 font-lock-keyword-face) (4 font-lock-constant-face nil t))
359 ;; Standard continuation character and in a TAB-formatted line.
360 '("^ \\{5\\}\\([^ 0\n]\\)" 1 font-lock-string-face)
361 '("^\t\\([1-9]\\)" 1 font-lock-string-face))
362 `((,fortran-directive-re (0 font-lock-keyword-face t)))
363 ;; `fortran-font-lock-keywords-2' without types (see above).
364 (cdr (nthcdr (length fortran-font-lock-keywords-1)
365 fortran-font-lock-keywords-2)))
272 "Gaudy level highlighting for Fortran mode.") 366 "Gaudy level highlighting for Fortran mode.")
273 367
274(defvar fortran-font-lock-syntactic-keywords nil 368;; Comments are real pain in Fortran because there is no way to
369;; represent the standard comment syntax in an Emacs syntax table.
370;; (We can do so for F90-style). Therefore an unmatched quote in a
371;; standard comment will throw fontification off on the wrong track.
372;; So we do syntactic fontification with regexps.
373(defvar fortran-font-lock-syntactic-keywords
374 '(("^[cd\\*]" 0 (11))
375 ("^[^cd\\*\t\n].\\{71\\}\\([^\n]+\\)" 1 (11)))
275 "`font-lock-syntactic-keywords' for Fortran. 376 "`font-lock-syntactic-keywords' for Fortran.
276These get fixed-format comments fontified.") 377These get fixed-format comments fontified.")
277 378
278(let ((comment-chars "cd\\*") ; `d' for `debugging' comments
279 (fortran-type-types
280 (eval-when-compile
281 (let ((re (regexp-opt
282 (let ((simple-types
283 '("character" "byte" "integer" "logical"
284 "none" "real" "complex"
285 "double precision" "double complex"))
286 (structured-types '("structure" "union" "map"))
287 (other-types '("record" "dimension"
288 "parameter" "common" "save"
289 "external" "intrinsic" "data"
290 "equivalence")))
291 (append
292 (mapcar (lambda (x) (concat "implicit " x))
293 simple-types)
294 simple-types
295 (mapcar (lambda (x) (concat "end " x))
296 structured-types)
297 structured-types
298 other-types)))))
299 ;; In the optimized regexp above, replace spaces by a
300 ;; regexp for optional whitespace; regexp-opt would have
301 ;; escaped that.
302 (mapconcat #'identity (split-string re) "[ \t]*"))))
303 (fortran-keywords
304 (eval-when-compile
305 (regexp-opt '("continue" "format" "end" "enddo" "if" "then"
306 "else" "endif" "elseif" "while" "inquire" "stop"
307 "return" "include" "open" "close" "read" "write"
308 "format" "print" "select" "case" "cycle" "exit"
309 "rewind" "backspace"))))
310 (fortran-logicals
311 (eval-when-compile
312 (regexp-opt '("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne"
313 "true" "false")))))
314 (setq fortran-font-lock-syntactic-keywords
315 ;; Fixed format comments. (!-style handled normally.)
316 (list
317 (list (concat "^[" comment-chars "]") 0 '(11))
318 (list (concat "^[^" comment-chars "\t\n]" ".\\{71\\}"
319 "\\([^\n]+\\)")
320 1 '(11))))
321 (setq fortran-font-lock-keywords-1
322 (list
323 ;; Program, subroutine and function declarations, plus calls.
324 (list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|"
325 "program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?")
326 '(1 font-lock-keyword-face)
327 '(2 font-lock-function-name-face nil t))))
328 (setq fortran-font-lock-keywords-2
329 (append fortran-font-lock-keywords-1
330 (list
331 ;; Fontify all type specifiers (must be first; see below).
332 (cons (concat "\\<\\(" fortran-type-types "\\)\\>")
333 'font-lock-type-face)
334 ;; Fontify all builtin keywords (except logical, do
335 ;; and goto; see below).
336 (concat "\\<\\(" fortran-keywords "\\)\\>")
337 ;; Fontify all builtin operators.
338 (concat "\\.\\(" fortran-logicals "\\)\\.")
339 ;; Fontify do/goto keywords and targets, and goto tags.
340 (list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?"
341 '(1 font-lock-keyword-face)
342 '(2 font-lock-constant-face nil t))
343 (cons "^ *\\([0-9]+\\)" 'font-lock-constant-face))))
344 (setq fortran-font-lock-keywords-3
345 (append
346 ;; The list `fortran-font-lock-keywords-1'.
347 fortran-font-lock-keywords-1
348 ;; Fontify all type specifiers plus their declared items.
349 (list
350 (list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?")
351 ;; Fontify the type specifier.
352 '(1 font-lock-type-face)
353 ;; Fontify each declaration item (or just the /.../ block name).
354 `(font-lock-match-c-style-declaration-item-and-skip-to-next
355 ;; Start after any *(...) expression.
356 (condition-case nil
357 (and (and (match-beginning ,(+ 2 (regexp-opt-depth
358 fortran-type-types)))
359 (forward-sexp))
360 (forward-sexp))
361 (error nil))
362 ;; No need to clean up.
363 nil
364 ;; Fontify as a variable name, functions are
365 ;; fontified elsewhere.
366 (1 font-lock-variable-name-face nil t))))
367 ;; Things extra to `fortran-font-lock-keywords-3'
368 ;; (must be done first).
369 (list
370 ;; Fontify goto-like `err=label'/`end=label' in read/write
371 ;; statements.
372 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
373 (1 font-lock-keyword-face) (4 font-lock-constant-face nil t))
374 ;; Highlight standard continuation character and in a
375 ;; TAB-formatted line.
376 '("^ \\([^ 0]\\)" 1 font-lock-string-face)
377 '("^\t\\([1-9]\\)" 1 font-lock-string-face))
378 (list
379 ;; cpp stuff (ugh)
380;;; '("^# *[a-z]+" . font-lock-keyword-face))
381 `(,fortran-directive-re (0 font-lock-keyword-face t)))
382 ;; The list `fortran-font-lock-keywords-2' less that for types
383 ;; (see above).
384 (cdr (nthcdr (length fortran-font-lock-keywords-1)
385 fortran-font-lock-keywords-2)))))
386
387(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1 379(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
388 "Default expressions to highlight in Fortran mode.") 380 "Default expressions to highlight in Fortran mode.")
389 381
390(defvar fortran-imenu-generic-expression 382(defvar fortran-imenu-generic-expression
391 ;; These patterns could be confused by sequence nos. in cols 72+ and 383 ;; These patterns could be confused by sequence nos. in cols 72+ and
392 ;; don't allow continuations everywhere. 384 ;; don't allow continuations everywhere.
@@ -407,23 +399,49 @@ These get fixed-format comments fontified.")
407 ;; Variable to index: 399 ;; Variable to index:
408 "\\(\\sw+\\)") 400 "\\(\\sw+\\)")
409 3) 401 3)
410 ;; Un-named block data 402 ;; Un-named block data.
411 (list nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1)) 403 '(nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1))
412 "Imenu generic expression for `imenu-default-create-index-function'.") 404 "Value for `imenu-generic-expression' in Fortran mode.")
405
406
407(defvar fortran-mode-syntax-table
408 (let ((table (make-syntax-table)))
409 ;; We might like `;' to be punctuation (g77 multi-statement
410 ;; lines), but that screws abbrevs.
411 (modify-syntax-entry ?\; "w" table)
412 (modify-syntax-entry ?\r " " table)
413 (modify-syntax-entry ?+ "." table)
414 (modify-syntax-entry ?- "." table)
415 (modify-syntax-entry ?= "." table)
416 (modify-syntax-entry ?* "." table)
417 (modify-syntax-entry ?/ "." table)
418 (modify-syntax-entry ?\' "\"" table)
419 (modify-syntax-entry ?\" "\"" table)
420 ;; Consistent with GNU Fortran -- see the manual.
421 (modify-syntax-entry ?\\ "\\" table)
422 ;; This might be better as punctuation, as for C, but this way you
423 ;; can treat floating-point numbers as symbols.
424 (modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b'
425 (modify-syntax-entry ?_ "_" table)
426 (modify-syntax-entry ?$ "_" table) ; esp. VMSisms
427 (modify-syntax-entry ?\! "<" table)
428 (modify-syntax-entry ?\n ">" table)
429 table)
430 "Syntax table used in Fortran mode.")
413 431
414(defvar fortran-mode-map 432(defvar fortran-mode-map
415 (let ((map (make-sparse-keymap))) 433 (let ((map (make-sparse-keymap)))
416 (define-key map ";" 'fortran-abbrev-start) 434 (define-key map ";" 'fortran-abbrev-start)
417 (define-key map "\C-c;" 'fortran-comment-region) 435 (define-key map "\C-c;" 'fortran-comment-region)
418 (define-key map "\M-;" 'fortran-indent-comment) 436 (define-key map "\M-;" 'fortran-indent-comment)
419 (define-key map "\M-\n" 'fortran-split-line) 437 (define-key map "\M-\n" 'fortran-split-line)
420 (define-key map "\M-\C-q" 'fortran-indent-subprogram) 438 (define-key map "\M-\C-q" 'fortran-indent-subprogram)
421 (define-key map "\C-c\C-w" 'fortran-window-create-momentarily) 439 (define-key map "\C-c\C-w" 'fortran-window-create-momentarily)
422 (define-key map "\C-c\C-r" 'fortran-column-ruler) 440 (define-key map "\C-c\C-r" 'fortran-column-ruler)
423 (define-key map "\C-c\C-p" 'fortran-previous-statement) 441 (define-key map "\C-c\C-p" 'fortran-previous-statement)
424 (define-key map "\C-c\C-n" 'fortran-next-statement) 442 (define-key map "\C-c\C-n" 'fortran-next-statement)
425 (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90 443 (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90
426 (define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation 444 (define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation
427 (define-key map "0" 'fortran-electric-line-number) 445 (define-key map "0" 'fortran-electric-line-number)
428 (define-key map "1" 'fortran-electric-line-number) 446 (define-key map "1" 'fortran-electric-line-number)
429 (define-key map "2" 'fortran-electric-line-number) 447 (define-key map "2" 'fortran-electric-line-number)
@@ -435,55 +453,56 @@ These get fixed-format comments fontified.")
435 (define-key map "8" 'fortran-electric-line-number) 453 (define-key map "8" 'fortran-electric-line-number)
436 (define-key map "9" 'fortran-electric-line-number) 454 (define-key map "9" 'fortran-electric-line-number)
437 455
438 ;; Menu 456 (easy-menu-define fortran-menu map "Menu for Fortran mode."
439 (easy-menu-define 457 `("Fortran"
440 fortran-mode-menu map "" 458 ["Manual" (info "(emacs)Fortran")]
441 `("Fortran" 459 ("Customization"
442 ["Manual" (info "(emacs)Fortran")] 460 ,(custom-menu-create 'fortran)
443 ("Customization" 461 ["Set" Custom-set t]
444 ,(custom-menu-create 'fortran) 462 ["Save" Custom-save t]
445 ["Set" Custom-set t] 463 ["Reset to Current" Custom-reset-current t]
446 ["Save" Custom-save t] 464 ["Reset to Saved" Custom-reset-saved t]
447 ["Reset to Current" Custom-reset-current t] 465 ["Reset to Standard Settings" Custom-reset-standard t]
448 ["Reset to Saved" Custom-reset-saved t] 466 )
449 ["Reset to Standard Settings" Custom-reset-standard t]) 467 "--"
450 "----" 468 ["Comment Region" fortran-comment-region mark-active]
451 ["Toggle Auto-fill" auto-fill-mode :style toggle 469 ["Uncomment Region"
452 :selected auto-fill-function] 470 (fortran-comment-region (region-beginning) (region-end) 1)
453 ["Toggle abbrev-mode" abbrev-mode :style toggle :selected abbrev-mode] 471 mark-active]
454 "----" 472 ["Indent Region" indent-region mark-active]
455 ["Comment-out Region" fortran-comment-region mark-active] 473 ["Indent Subprogram" fortran-indent-subprogram t]
456 ["Uncomment-out region" 474 "--"
457 (fortran-comment-region (region-beginning) (region-end) 1) 475 ["Beginning of Subprogram" fortran-beginning-of-subprogram t]
458 mark-active] 476 ["End of Subprogram" fortran-end-of-subprogram t]
459 ["Indent Region" indent-region mark-active] 477 ("Mark"
460 ["Indent Subprogram" fortran-indent-subprogram t] 478 ["Subprogram" mark-defun t]
461 "----" 479 ["IF Block" fortran-mark-if t]
462 ["Beginning of Subprogram" fortran-beginning-of-subprogram t] 480 ["DO Block" fortran-mark-do t]
463 ["End of Subprogram" fortran-end-of-subprogram t] 481 )
464 ("Mark" 482 ["Narrow to Subprogram" narrow-to-defun t]
465 ["Subprogram" mark-defun t] 483 ["Widen" widen t]
466 ["IF Block" fortran-mark-if t] 484 "--"
467 ["DO Block" fortran-mark-do t]) 485 ["Temporary column ruler" fortran-column-ruler t]
468 ["Narrow to Subprogram" narrow-to-defun t] 486 ["72-column window" fortran-window-create t]
469 ["Widen" widen t] 487 ["Full Width Window"
470 "----" 488 (enlarge-window-horizontally (- (frame-width) (window-width)))
471 ["Temporary column ruler" fortran-column-ruler t] 489 (< (window-width) (frame-width))]
472 ["72-column window" fortran-window-create t] 490 ["Momentary 72-column window" fortran-window-create-momentarily t]
473 ["Full Width Window" 491 "--"
474 (enlarge-window-horizontally (- (frame-width) (window-width))) 492 ["Break Line at Point" fortran-split-line t]
475 (< (window-width) (frame-width))] 493 ["Join Line" fortran-join-line t]
476 ["Momentary 72-column window" fortran-window-create-momentarily t] 494 ["Fill Statement/Comment" fill-paragraph t]
477 "----" 495 "--"
478 ["Break Line at Point" fortran-split-line t] 496 ["Toggle auto-fill" auto-fill-mode :selected auto-fill-function
479 ["Join Line" fortran-join-line t] 497 :style toggle]
480 ["Fill Statement/Comment" fill-paragraph t] 498 ["Toggle abbrev-mode" abbrev-mode :selected abbrev-mode
481 "----" 499 :style toggle]
482 ["Add imenu menu" 500 ["Add imenu Menu" imenu-add-menubar-index
483 imenu-add-menubar-index (not (and (boundp 'imenu--index-alist) 501 :active (not (lookup-key (current-local-map) [menu-bar index]))
484 imenu--index-alist))])) 502 :included (fboundp 'imenu-add-to-menubar)]))
485 map) 503 map)
486 "Keymap used in Fortran mode.") 504 "Keymap used in Fortran mode.")
505
487 506
488(defvar fortran-mode-abbrev-table 507(defvar fortran-mode-abbrev-table
489 (let (abbrevs-changed) 508 (let (abbrevs-changed)
@@ -557,145 +576,124 @@ These get fixed-format comments fontified.")
557 (";w" "write" ) 576 (";w" "write" )
558 (";wh" "where" ))) 577 (";wh" "where" )))
559 fortran-mode-abbrev-table)) 578 fortran-mode-abbrev-table))
560
561(eval-when-compile ; silence compiler
562 (defvar imenu-case-fold-search)
563 (defvar imenu-syntax-alist))
564 579
565(defcustom fortran-mode-hook nil 580
566 "Hook run by Fortran mode."
567 :type 'hook
568 :group 'fortran)
569 581
570;;;###autoload 582;;;###autoload
571(defun fortran-mode () 583(defun fortran-mode ()
572 "Major mode for editing Fortran code. 584 "Major mode for editing Fortran code in fixed format.
585For free format code, use `f90-mode'.
586
573\\[fortran-indent-line] indents the current Fortran line correctly. 587\\[fortran-indent-line] indents the current Fortran line correctly.
574DO statements must not share a common CONTINUE. 588Note that DO statements must not share a common CONTINUE.
575 589
576Type ;? or ;\\[help-command] to display a list of built-in abbrevs for 590Type ;? or ;\\[help-command] to display a list of built-in abbrevs for\
577Fortran keywords. 591 Fortran keywords.
578 592
579Key definitions: 593Key definitions:
580\\{fortran-mode-map} 594\\{fortran-mode-map}
581 595
582Variables controlling indentation style and extra features: 596Variables controlling indentation style and extra features:
583 597
584 `comment-start' 598`comment-start'
585 If you want to use comments starting with `!', 599 To use comments starting with `!', set this to the string \"!\".
586 set this to the string \"!\". 600`fortran-do-indent'
587 `fortran-do-indent' 601 Extra indentation within DO blocks (default 3).
588 Extra indentation within do blocks. (default 3) 602`fortran-if-indent'
589 `fortran-if-indent' 603 Extra indentation within IF blocks (default 3).
590 Extra indentation within if blocks. (default 3) 604`fortran-structure-indent'
591 `fortran-structure-indent' 605 Extra indentation within STRUCTURE, UNION, MAP and INTERFACE blocks.
592 Extra indentation within structure, union, map and interface blocks. 606 (default 3)
593 (default 3) 607`fortran-continuation-indent'
594 `fortran-continuation-indent' 608 Extra indentation applied to continuation statements (default 5).
595 Extra indentation applied to continuation statements. (default 5) 609`fortran-comment-line-extra-indent'
596 `fortran-comment-line-extra-indent' 610 Amount of extra indentation for text in full-line comments (default 0).
597 Amount of extra indentation for text within full-line comments. (default 0) 611`fortran-comment-indent-style'
598 `fortran-comment-indent-style' 612 How to indent the text in full-line comments. Allowed values are:
599 nil means don't change indentation of text in full-line comments, 613 nil don't change the indentation
600 fixed means indent that text at `fortran-comment-line-extra-indent' beyond 614 fixed indent to `fortran-comment-line-extra-indent' beyond the
601 the value of `fortran-minimum-statement-indent-fixed' (for fixed 615 value of either
602 format continuation style) or `fortran-minimum-statement-indent-tab' 616 `fortran-minimum-statement-indent-fixed' (fixed format) or
603 (for TAB format continuation style). 617 `fortran-minimum-statement-indent-tab' (TAB format),
604 relative means indent at `fortran-comment-line-extra-indent' beyond the 618 depending on the continuation format in use.
619 relative indent to `fortran-comment-line-extra-indent' beyond the
605 indentation for a line of code. 620 indentation for a line of code.
606 (default 'fixed) 621 (default 'fixed)
607 `fortran-comment-indent-char' 622`fortran-comment-indent-char'
608 Single-character string to be inserted instead of space for 623 Single-character string to be inserted instead of space for
609 full-line comment indentation. (default \" \") 624 full-line comment indentation (default \" \").
610 `fortran-minimum-statement-indent-fixed' 625`fortran-minimum-statement-indent-fixed'
611 Minimum indentation for Fortran statements in fixed format mode. (def.6) 626 Minimum indentation for statements in fixed format mode (default 6).
612 `fortran-minimum-statement-indent-tab' 627`fortran-minimum-statement-indent-tab'
613 Minimum indentation for Fortran statements in TAB format mode. (default 9) 628 Minimum indentation for statements in TAB format mode (default 9).
614 `fortran-line-number-indent' 629`fortran-line-number-indent'
615 Maximum indentation for line numbers. A line number will get 630 Maximum indentation for line numbers (default 1). A line number will
616 less than this much indentation if necessary to avoid reaching 631 get less than this much indentation if necessary to avoid reaching
617 column 5. (default 1) 632 column 5.
618 `fortran-check-all-num-for-matching-do' 633`fortran-check-all-num-for-matching-do'
619 Non-nil causes all numbered lines to be treated as possible \"continue\" 634 Non-nil causes all numbered lines to be treated as possible \"continue\"
620 statements. (default nil) 635 statements (default nil).
621 `fortran-blink-matching-if' 636`fortran-blink-matching-if'
622 Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on 637 Non-nil causes \\[fortran-indent-line] on an ENDIF (or ENDDO) statement
623 matching IF. Also, from an ENDDO statement, blink on matching DO [WHILE] 638 to blink on the matching IF (or DO [WHILE]). (default nil)
624 statement. (default nil) 639`fortran-continuation-string'
625 `fortran-continuation-string' 640 Single-character string to be inserted in column 5 of a continuation
626 Single-character string to be inserted in column 5 of a continuation 641 line (default \"$\").
627 line. (default \"$\") 642`fortran-comment-region'
628 `fortran-comment-region' 643 String inserted by \\[fortran-comment-region] at start of each line in
629 String inserted by \\[fortran-comment-region] at start of each line in 644 the region (default \"c$$$\").
630 region. (default \"c$$$\") 645`fortran-electric-line-number'
631 `fortran-electric-line-number' 646 Non-nil causes line number digits to be moved to the correct column
632 Non-nil causes line number digits to be moved to the correct column 647 as typed (default t).
633 as typed. (default t) 648`fortran-break-before-delimiters'
634 `fortran-break-before-delimiters' 649 Non-nil causes lines to be broken before delimiters (default t).
635 Non-nil causes lines to be broken before delimiters.
636 (default t)
637 650
638Turning on Fortran mode calls the value of the variable `fortran-mode-hook' 651Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
639with no args, if that value is non-nil." 652with no args, if that value is non-nil."
640 (interactive) 653 (interactive)
641 (kill-all-local-variables) 654 (kill-all-local-variables)
642 (setq local-abbrev-table fortran-mode-abbrev-table) 655 (setq major-mode 'fortran-mode
656 mode-name "Fortran"
657 local-abbrev-table fortran-mode-abbrev-table)
643 (set-syntax-table fortran-mode-syntax-table) 658 (set-syntax-table fortran-mode-syntax-table)
644 ;; Font Lock mode support. 659 (use-local-map fortran-mode-map)
645 (make-local-variable 'font-lock-defaults) 660 (set (make-local-variable 'indent-line-function) 'fortran-indent-line)
646 (setq font-lock-defaults '((fortran-font-lock-keywords 661 (set (make-local-variable 'indent-region-function)
647 fortran-font-lock-keywords-1 662 (lambda (start end)
648 fortran-font-lock-keywords-2 663 (let (fortran-blink-matching-if ; avoid blinking delay
649 fortran-font-lock-keywords-3) 664 indent-region-function)
650 nil t ((?/ . "$/") ("_$" . "w")) 665 (indent-region start end nil))))
651 fortran-beginning-of-subprogram)) 666 (set (make-local-variable 'require-final-newline) t)
652 (set (make-local-variable 'font-lock-syntactic-keywords) 667 ;; The syntax tables don't understand the column-0 comment-markers.
653 fortran-font-lock-syntactic-keywords) 668 (set (make-local-variable 'comment-use-syntax) nil)
654 (make-local-variable 'fortran-break-before-delimiters) 669 (set (make-local-variable 'comment-padding) "$$$")
655 (setq fortran-break-before-delimiters t) 670 (set (make-local-variable 'comment-start) fortran-comment-line-start)
656 (make-local-variable 'indent-line-function)
657 (setq indent-line-function 'fortran-indent-line)
658 (make-local-variable 'comment-indent-function)
659 (setq comment-indent-function 'fortran-comment-indent)
660 (set (make-local-variable 'comment-start-skip) 671 (set (make-local-variable 'comment-start-skip)
661 ;; We can't reuse `fortran-comment-line-start-skip' directly because 672 ;; We can't reuse `fortran-comment-line-start-skip' directly because
662 ;; it contains backrefs whereas we need submatch-1 to end at the 673 ;; it contains backrefs whereas we need submatch-1 to end at the
663 ;; beginning of the comment delimiter. 674 ;; beginning of the comment delimiter.
664 ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)") 675 ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)")
665 "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*") 676 "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*")
666 (set (make-local-variable 'comment-padding) "$$$") 677 (set (make-local-variable 'comment-indent-function) 'fortran-comment-indent)
667 (set (make-local-variable 'comment-start) fortran-comment-line-start) 678 (set (make-local-variable 'abbrev-all-caps) t)
668 ;; The syntax tables don't understand the column-0 comment-markers. 679 (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill)
669 (set (make-local-variable 'comment-use-syntax) nil) 680 (setq fortran-tab-mode-minor-mode-string fortran-tab-mode-string)
670 (make-local-variable 'require-final-newline) 681 (set (make-local-variable 'indent-tabs-mode) (fortran-analyze-file-format))
671 (setq require-final-newline t)
672 (make-local-variable 'abbrev-all-caps)
673 (setq abbrev-all-caps t)
674 (make-local-variable 'indent-tabs-mode)
675 (setq indent-tabs-mode nil)
676;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead??
677 (set (make-local-variable 'fill-column) 72) 682 (set (make-local-variable 'fill-column) 72)
678 (use-local-map fortran-mode-map)
679 (setq mode-name "Fortran")
680 (setq major-mode 'fortran-mode)
681 (make-local-variable 'fortran-comment-line-extra-indent)
682 (make-local-variable 'fortran-minimum-statement-indent-fixed)
683 (make-local-variable 'fortran-minimum-statement-indent-tab)
684 (make-local-variable 'fortran-column-ruler-fixed)
685 (make-local-variable 'fortran-column-ruler-tab)
686 (setq fortran-tab-mode-string " TAB-format")
687 (setq indent-tabs-mode (fortran-analyze-file-format))
688 (setq imenu-case-fold-search t)
689 (setq imenu-generic-expression fortran-imenu-generic-expression)
690 (setq imenu-syntax-alist '(("_$" . "w")))
691 (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph) 683 (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph)
692 (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill) 684 (set (make-local-variable 'font-lock-defaults)
693 (set (make-local-variable 'indent-line-function) 'fortran-indent-line) 685 '((fortran-font-lock-keywords
694 (set (make-local-variable 'indent-region-function) 686 fortran-font-lock-keywords-1
695 (lambda (start end) 687 fortran-font-lock-keywords-2
696 (let (fortran-blink-matching-if ; avoid blinking delay 688 fortran-font-lock-keywords-3)
697 indent-region-function) 689 nil t ((?/ . "$/") ("_$" . "w"))
698 (indent-region start end nil)))) 690 fortran-beginning-of-subprogram))
691 (set (make-local-variable 'font-lock-syntactic-keywords)
692 fortran-font-lock-syntactic-keywords)
693 (set (make-local-variable 'imenu-case-fold-search) t)
694 (set (make-local-variable 'imenu-generic-expression)
695 fortran-imenu-generic-expression)
696 (set (make-local-variable 'imenu-syntax-alist) '(("_$" . "w")))
699 (set (make-local-variable 'beginning-of-defun-function) 697 (set (make-local-variable 'beginning-of-defun-function)
700 #'fortran-beginning-of-subprogram) 698 #'fortran-beginning-of-subprogram)
701 (set (make-local-variable 'end-of-defun-function) 699 (set (make-local-variable 'end-of-defun-function)
@@ -704,32 +702,35 @@ with no args, if that value is non-nil."
704 #'fortran-current-defun) 702 #'fortran-current-defun)
705 (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search) 703 (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search)
706 (run-hooks 'fortran-mode-hook)) 704 (run-hooks 'fortran-mode-hook))
705
707 706
708(defsubst fortran-comment-indent () 707(defsubst fortran-comment-indent ()
709 (save-excursion 708 "Return the indentation appropriate for the current comment line.
710 (if (looking-at fortran-comment-line-start-skip) 0 709This is 0 for a line matching `fortran-comment-line-start-skip', else
710the value of `comment-column' (leaving at least one space after code)."
711 (if (looking-at fortran-comment-line-start-skip) 0
712 (save-excursion
711 (skip-chars-backward " \t") 713 (skip-chars-backward " \t")
712 (max (+ 1 (current-column)) 714 (max (1+ (current-column))
713 comment-column)))) 715 comment-column))))
714 716
715(defun fortran-indent-comment () 717(defun fortran-indent-comment ()
716 "Align or create comment on current line. 718 "Align or create comment on current line.
717Existing comments of all types are recognized and aligned. 719Existing comments of all types are recognized and aligned.
718If the line has no comment, a side-by-side comment is inserted and aligned 720If the line has no comment, a side-by-side comment is inserted and aligned,
719if the value of `comment-start' is not nil and allows such comments. 721if the value of `comment-start' is not nil and allows such comments.
720Otherwise, a separate-line comment is inserted, on this line 722Otherwise, a separate-line comment is inserted, on this line
721or on a new line inserted before this line if this line is not blank." 723or on a new line inserted before this line if this line is not blank."
722 (interactive) 724 (interactive "*")
723 (beginning-of-line) 725 (beginning-of-line)
724 ;; Recognize existing comments of either kind. 726 ;; Recognize existing comments of either kind.
725 (cond ((fortran-find-comment-start-skip 'all) 727 (cond ((fortran-find-comment-start-skip 'all)
726 (goto-char (match-beginning 0)) 728 (goto-char (match-beginning 0))
727 (if (bolp) 729 (if (bolp)
728 (fortran-indent-line) 730 (fortran-indent-line)
729 (if (not (= (current-column) 731 (unless (= (current-column) (fortran-comment-indent))
730 (fortran-comment-indent))) 732 (delete-horizontal-space)
731 (progn (delete-horizontal-space) 733 (indent-to (fortran-comment-indent)))))
732 (indent-to (fortran-comment-indent))))))
733 ;; No existing comment. 734 ;; No existing comment.
734 ;; If side-by-side comments are defined, insert one, 735 ;; If side-by-side comments are defined, insert one,
735 ;; unless line is now blank. 736 ;; unless line is now blank.
@@ -753,35 +754,37 @@ or on a new line inserted before this line if this line is not blank."
753 (- (fortran-calculate-indent) (current-column)))))) 754 (- (fortran-calculate-indent) (current-column))))))
754 755
755(defun fortran-comment-region (beg-region end-region arg) 756(defun fortran-comment-region (beg-region end-region arg)
756 "Comments every line in the region. 757 "Comment every line in the region.
757Puts `fortran-comment-region' at the beginning of every line in the region. 758Inserts the string variable `fortran-comment-region' at the beginning of
758BEG-REGION and END-REGION are args which specify the region boundaries. 759every line in the region.
760BEG-REGION and END-REGION specify the region boundaries.
759With non-nil ARG, uncomments the region." 761With non-nil ARG, uncomments the region."
760 (interactive "*r\nP") 762 (interactive "*r\nP")
761 (let ((end-region-mark (copy-marker end-region)) 763 (let ((end-region-mark (copy-marker end-region))
762 (save-point (point-marker))) 764 (save-point (point-marker)))
763 (goto-char beg-region) 765 (goto-char beg-region)
764 (beginning-of-line) 766 (beginning-of-line)
765 (if (not arg) ;comment the region 767 (if arg
766 (progn (insert fortran-comment-region) 768 (let ((com (regexp-quote fortran-comment-region))) ;uncomment region
767 (while (and (= (forward-line 1) 0) 769 (if (looking-at com)
768 (< (point) end-region-mark)) 770 (delete-region (point) (match-end 0)))
769 (insert fortran-comment-region))) 771 (while (and (zerop (forward-line 1))
770 (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region 772 (< (point) end-region-mark))
771 (if (looking-at com) 773 (if (looking-at com)
772 (delete-region (point) (match-end 0))) 774 (delete-region (point) (match-end 0)))))
773 (while (and (= (forward-line 1) 0) 775 (insert fortran-comment-region) ;comment the region
774 (< (point) end-region-mark)) 776 (while (and (zerop (forward-line 1))
775 (if (looking-at com) 777 (< (point) end-region-mark))
776 (delete-region (point) (match-end 0)))))) 778 (insert fortran-comment-region)))
777 (goto-char save-point) 779 (goto-char save-point)
778 (set-marker end-region-mark nil) 780 (set-marker end-region-mark nil)
779 (set-marker save-point nil))) 781 (set-marker save-point nil)))
782
780 783
781(defun fortran-abbrev-start () 784(defun fortran-abbrev-start ()
782 "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. 785 "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs.
783Any other key combination is executed normally." 786Any other key combination is executed normally."
784 (interactive) 787 (interactive "*")
785 (let (c) 788 (let (c)
786 (insert last-command-char) 789 (insert last-command-char)
787 (if (and abbrev-mode 790 (if (and abbrev-mode
@@ -798,6 +801,7 @@ Any other key combination is executed normally."
798 (message "Listing abbrev table...done")) 801 (message "Listing abbrev table...done"))
799 802
800(defun fortran-prepare-abbrev-list-buffer () 803(defun fortran-prepare-abbrev-list-buffer ()
804 "Create a buffer listing the Fortran mode abbreviations."
801 (save-excursion 805 (save-excursion
802 (set-buffer (get-buffer-create "*Abbrevs*")) 806 (set-buffer (get-buffer-create "*Abbrevs*"))
803 (erase-buffer) 807 (erase-buffer)
@@ -862,7 +866,7 @@ See also `fortran-window-create'."
862 866
863(defun fortran-split-line () 867(defun fortran-split-line ()
864 "Break line at point and insert continuation marker and alignment." 868 "Break line at point and insert continuation marker and alignment."
865 (interactive) 869 (interactive "*")
866 (delete-horizontal-space) 870 (delete-horizontal-space)
867 (if (save-excursion 871 (if (save-excursion
868 (let ((pos (point))) 872 (let ((pos (point)))
@@ -876,10 +880,12 @@ See also `fortran-window-create'."
876 (fortran-indent-line)) ; when the cont string is C, c or *. 880 (fortran-indent-line)) ; when the cont string is C, c or *.
877 881
878(defun fortran-remove-continuation () 882(defun fortran-remove-continuation ()
879 (if (looking-at "\\( [^ 0\n]\\|\t[1-9]\\|&\\)") 883 "Delete any Fortran continuation characters at point.
880 (progn (replace-match "") 884Returns t if anything actually deleted."
881 (delete-indentation) 885 (when (looking-at "\\( \\{5\\}[^ 0\n]\\|\t[1-9]\\|&\\)")
882 t))) 886 (replace-match "")
887 (delete-indentation)
888 t))
883 889
884(defun fortran-join-line (arg) 890(defun fortran-join-line (arg)
885 "Join current line to the previous one and re-indent. 891 "Join current line to the previous one and re-indent.
@@ -900,19 +906,19 @@ Continuation lines are correctly handled."
900 906
901(defun fortran-numerical-continuation-char () 907(defun fortran-numerical-continuation-char ()
902 "Return a digit for tab-digit style of continuation lines. 908 "Return a digit for tab-digit style of continuation lines.
903If, previous line is a tab-digit continuation line, returns that digit 909If previous line is a tab-digit continuation line, return that digit
904plus one. Otherwise return 1. Zero not allowed." 910plus one, otherwise return 1. Zero not allowed."
905 (save-excursion 911 (save-excursion
906 (forward-line -1) 912 (forward-line -1)
907 (if (looking-at "\t[1-9]") 913 (if (looking-at "\t[1-9]")
908 (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9)) 914 (+ ?1 (% (- (char-after (1+ (point))) ?0) 9))
909 ?1))) 915 ?1)))
910 916
911(put 'fortran-electric-line-number 'delete-selection t) 917(put 'fortran-electric-line-number 'delete-selection t)
912(defun fortran-electric-line-number (arg) 918(defun fortran-electric-line-number (arg)
913 "Self insert, but if part of a Fortran line number indent it automatically. 919 "Self insert, but if part of a Fortran line number indent it automatically.
914Auto-indent does not happen if a numeric ARG is used." 920Auto-indent does not happen if a numeric ARG is used."
915 (interactive "P") 921 (interactive "*P")
916 (if (or arg (not fortran-electric-line-number)) 922 (if (or arg (not fortran-electric-line-number))
917 (if arg 923 (if arg
918 (self-insert-command (prefix-numeric-value arg)) 924 (self-insert-command (prefix-numeric-value arg))
@@ -920,32 +926,27 @@ Auto-indent does not happen if a numeric ARG is used."
920 (if (or (and (= 5 (current-column)) 926 (if (or (and (= 5 (current-column))
921 (save-excursion 927 (save-excursion
922 (beginning-of-line) 928 (beginning-of-line)
923 (looking-at " \\{5\\}"))) ;In col 5 with only spaces to left. 929 ;; In col 5 with only spaces to the left.
930 (looking-at " \\{5\\}")))
924 (and (= (if indent-tabs-mode 931 (and (= (if indent-tabs-mode
925 fortran-minimum-statement-indent-tab 932 fortran-minimum-statement-indent-tab
926 fortran-minimum-statement-indent-fixed) (current-column)) 933 fortran-minimum-statement-indent-fixed) (current-column))
927 (eq ?\t (char-after (line-beginning-position))) ;In col 8 934 ;; In col 8 with a single tab to the left.
928 ; with a single tab to the left. 935 (eq ?\t (char-after (line-beginning-position)))
929 (not (or (eq last-command 'fortran-indent-line) 936 (not (or (eq last-command 'fortran-indent-line)
930 (eq last-command 937 (eq last-command
931 'fortran-indent-new-line)))) 938 'fortran-indent-new-line))))
932 (save-excursion 939 (save-excursion
933 (re-search-backward "[^ \t0-9]" 940 (re-search-backward "[^ \t0-9]"
934 (line-beginning-position) 941 (line-beginning-position)
935 t)) ;not a line number 942 t)) ; not a line number
936 (looking-at "[0-9]")) ;within a line number 943 (looking-at "[0-9]")) ; within a line number
937 (self-insert-command (prefix-numeric-value arg)) 944 (self-insert-command (prefix-numeric-value arg))
938 (skip-chars-backward " \t") 945 (skip-chars-backward " \t")
939 (insert last-command-char) 946 (insert last-command-char)
940 (fortran-indent-line)))) 947 (fortran-indent-line))))
948
941 949
942(defvar fortran-end-prog-re1
943 "end\
944\\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\
945\\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?")
946(defvar fortran-end-prog-re
947 (concat "^[ \t0-9]*" fortran-end-prog-re1)
948 "Regexp possibly marking subprogram end.")
949 950
950(defun fortran-check-end-prog-re () 951(defun fortran-check-end-prog-re ()
951 "Check a preliminary match against `fortran-end-prog-re'." 952 "Check a preliminary match against `fortran-end-prog-re'."
@@ -1005,7 +1006,7 @@ Directive lines are treated as comments."
1005 (concat "[ \t]*" 1006 (concat "[ \t]*"
1006 (regexp-quote fortran-continuation-string))) 1007 (regexp-quote fortran-continuation-string)))
1007 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")))) 1008 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]"))))
1008 (while (and (setq not-first-statement (= (forward-line -1) 0)) 1009 (while (and (setq not-first-statement (zerop (forward-line -1)))
1009 (or (looking-at fortran-comment-line-start-skip) 1010 (or (looking-at fortran-comment-line-start-skip)
1010 (looking-at fortran-directive-re) 1011 (looking-at fortran-directive-re)
1011 (looking-at 1012 (looking-at
@@ -1030,7 +1031,7 @@ Directive lines are treated as comments."
1030 (let (not-last-statement) 1031 (let (not-last-statement)
1031 (beginning-of-line) 1032 (beginning-of-line)
1032 (while (and (setq not-last-statement 1033 (while (and (setq not-last-statement
1033 (and (= (forward-line 1) 0) 1034 (and (zerop (forward-line 1))
1034 (not (eobp)))) 1035 (not (eobp))))
1035 (or (looking-at fortran-comment-line-start-skip) 1036 (or (looking-at fortran-comment-line-start-skip)
1036 (looking-at fortran-directive-re) 1037 (looking-at fortran-directive-re)
@@ -1038,6 +1039,7 @@ Directive lines are treated as comments."
1038 (looking-at (concat "[ \t]*" comment-start-skip))))) 1039 (looking-at (concat "[ \t]*" comment-start-skip)))))
1039 (if (not not-last-statement) 1040 (if (not not-last-statement)
1040 'last-statement))) 1041 'last-statement)))
1042
1041 1043
1042(defun fortran-blink-match (regex keyword find-begin) 1044(defun fortran-blink-match (regex keyword find-begin)
1043 "From a line matching REGEX, blink matching KEYWORD statement line. 1045 "From a line matching REGEX, blink matching KEYWORD statement line.
@@ -1047,26 +1049,25 @@ Use function FIND-BEGIN to match it."
1047 (case-fold-search t) 1049 (case-fold-search t)
1048 matching 1050 matching
1049 message) 1051 message)
1050 (if (save-excursion 1052 (when (save-excursion
1051 (beginning-of-line) 1053 (beginning-of-line)
1052 (skip-chars-forward " \t0-9") 1054 (skip-chars-forward " \t0-9")
1053 (looking-at regex)) 1055 (looking-at regex))
1054 (progn 1056 (if (not (setq matching (funcall find-begin)))
1055 (if (not (setq matching (funcall find-begin))) 1057 (setq message (concat "No matching " keyword "."))
1056 (setq message (concat "No matching " keyword ".")) 1058 (if (< matching top-of-window)
1057 (if (< matching top-of-window) 1059 (save-excursion
1058 (save-excursion 1060 (goto-char matching)
1059 (goto-char matching) 1061 (beginning-of-line)
1060 (beginning-of-line) 1062 (setq message
1061 (setq message 1063 (concat "Matches "
1062 (concat "Matches " 1064 (buffer-substring (point)
1063 (buffer-substring (point) 1065 (line-end-position)))))))
1064 (line-end-position))))))) 1066 (if message
1065 (if message 1067 (message "%s" message)
1066 (message "%s" message) 1068 (goto-char matching)
1067 (goto-char matching) 1069 (sit-for 1)
1068 (sit-for 1) 1070 (goto-char end-point)))))
1069 (goto-char end-point))))))
1070 1071
1071(defun fortran-blink-matching-if () 1072(defun fortran-blink-matching-if ()
1072 "From an ENDIF or ELSE statement, blink the matching IF statement." 1073 "From an ENDIF or ELSE statement, blink the matching IF statement."
@@ -1101,7 +1102,7 @@ Return point or nil."
1101 ;; Search for one. 1102 ;; Search for one.
1102 (save-excursion 1103 (save-excursion
1103 (let ((count 1)) 1104 (let ((count 1))
1104 (while (and (not (= count 0)) 1105 (while (and (not (zerop count))
1105 (not (eq (fortran-next-statement) 'last-statement)) 1106 (not (eq (fortran-next-statement) 'last-statement))
1106 ;; Keep local to subprogram 1107 ;; Keep local to subprogram
1107 (not (and (looking-at fortran-end-prog-re) 1108 (not (and (looking-at fortran-end-prog-re)
@@ -1111,8 +1112,8 @@ Return point or nil."
1111 (setq count (1- count))) 1112 (setq count (1- count)))
1112 ((looking-at 1113 ((looking-at
1113 "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]") 1114 "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]")
1114 (setq count (+ count 1))))) 1115 (setq count (1+ count)))))
1115 (and (= count 0) 1116 (and (zerop count)
1116 ;; All pairs accounted for. 1117 ;; All pairs accounted for.
1117 (point))))))) 1118 (point)))))))
1118 1119
@@ -1130,7 +1131,7 @@ Return point or nil. Ignores labelled DO loops (ie DO 10 ... 10 CONTINUE)."
1130 ;; Search for one. 1131 ;; Search for one.
1131 (save-excursion 1132 (save-excursion
1132 (let ((count 1)) 1133 (let ((count 1))
1133 (while (and (not (= count 0)) 1134 (while (and (not (zerop count))
1134 (not (eq (fortran-previous-statement) 'first-statement)) 1135 (not (eq (fortran-previous-statement) 'first-statement))
1135 ;; Keep local to subprogram 1136 ;; Keep local to subprogram
1136 (not (and (looking-at fortran-end-prog-re) 1137 (not (and (looking-at fortran-end-prog-re)
@@ -1141,7 +1142,7 @@ Return point or nil. Ignores labelled DO loops (ie DO 10 ... 10 CONTINUE)."
1141 ;; Note labelled loop ends not considered. 1142 ;; Note labelled loop ends not considered.
1142 ((looking-at "end[ \t]*do\\b") 1143 ((looking-at "end[ \t]*do\\b")
1143 (setq count (1+ count))))) 1144 (setq count (1+ count)))))
1144 (and (= count 0) 1145 (and (zerop count)
1145 ;; All pairs accounted for. 1146 ;; All pairs accounted for.
1146 (point))))))) 1147 (point)))))))
1147 1148
@@ -1158,8 +1159,6 @@ The marks are pushed."
1158 (push-mark) 1159 (push-mark)
1159 (goto-char if-point))))) 1160 (goto-char if-point)))))
1160 1161
1161(defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")
1162
1163(defun fortran-end-if () 1162(defun fortran-end-if ()
1164 "Search forwards for first unmatched ENDIF. 1163 "Search forwards for first unmatched ENDIF.
1165Return point or nil." 1164Return point or nil."
@@ -1173,14 +1172,14 @@ Return point or nil."
1173 ;; letter on line but this should not cause troubles. 1172 ;; letter on line but this should not cause troubles.
1174 (save-excursion 1173 (save-excursion
1175 (let ((count 1)) 1174 (let ((count 1))
1176 (while (and (not (= count 0)) 1175 (while (and (not (zerop count))
1177 (not (eq (fortran-next-statement) 'last-statement)) 1176 (not (eq (fortran-next-statement) 'last-statement))
1178 ;; Keep local to subprogram. 1177 ;; Keep local to subprogram.
1179 (not (and (looking-at fortran-end-prog-re) 1178 (not (and (looking-at fortran-end-prog-re)
1180 (fortran-check-end-prog-re)))) 1179 (fortran-check-end-prog-re))))
1181 (skip-chars-forward " \t0-9") 1180 (skip-chars-forward " \t0-9")
1182 (cond ((looking-at "end[ \t]*if\\b") 1181 (cond ((looking-at "end[ \t]*if\\b")
1183 (setq count (- count 1))) 1182 (setq count (1- count)))
1184 ((looking-at fortran-if-start-re) 1183 ((looking-at fortran-if-start-re)
1185 (save-excursion 1184 (save-excursion
1186 (if (or 1185 (if (or
@@ -1188,7 +1187,7 @@ Return point or nil."
1188 (let (then-test) ; Multi-line if-then. 1187 (let (then-test) ; Multi-line if-then.
1189 (while 1188 (while
1190 (and 1189 (and
1191 (= (forward-line 1) 0) 1190 (zerop (forward-line 1))
1192 ;; Search forward for then. 1191 ;; Search forward for then.
1193 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") 1192 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1194 (not 1193 (not
@@ -1196,8 +1195,8 @@ Return point or nil."
1196 (looking-at 1195 (looking-at
1197 ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) 1196 ".*then\\b[ \t]*[^ \t(=a-z0-9]")))))
1198 then-test)) 1197 then-test))
1199 (setq count (+ count 1))))))) 1198 (setq count (1+ count)))))))
1200 (and (= count 0) 1199 (and (zerop count)
1201 ;; All pairs accounted for. 1200 ;; All pairs accounted for.
1202 (point))))))) 1201 (point)))))))
1203 1202
@@ -1221,7 +1220,7 @@ Return point or nil."
1221 ;; Multi-line if-then. 1220 ;; Multi-line if-then.
1222 (let (then-test) 1221 (let (then-test)
1223 (while 1222 (while
1224 (and (= (forward-line 1) 0) 1223 (and (zerop (forward-line 1))
1225 ;; Search forward for then. 1224 ;; Search forward for then.
1226 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") 1225 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1227 (not 1226 (not
@@ -1234,7 +1233,7 @@ Return point or nil."
1234 ;; Search for one. 1233 ;; Search for one.
1235 (save-excursion 1234 (save-excursion
1236 (let ((count 1)) 1235 (let ((count 1))
1237 (while (and (not (= count 0)) 1236 (while (and (not (zerop count))
1238 (not (eq (fortran-previous-statement) 'first-statement)) 1237 (not (eq (fortran-previous-statement) 'first-statement))
1239 ;; Keep local to subprogram. 1238 ;; Keep local to subprogram.
1240 (not (and (looking-at fortran-end-prog-re) 1239 (not (and (looking-at fortran-end-prog-re)
@@ -1247,7 +1246,7 @@ Return point or nil."
1247 (let (then-test) ; Multi-line if-then. 1246 (let (then-test) ; Multi-line if-then.
1248 (while 1247 (while
1249 (and 1248 (and
1250 (= (forward-line 1) 0) 1249 (zerop (forward-line 1))
1251 ;; Search forward for then. 1250 ;; Search forward for then.
1252 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") 1251 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1253 (not 1252 (not
@@ -1256,16 +1255,17 @@ Return point or nil."
1256 (concat ".*then\\b[ \t]*" 1255 (concat ".*then\\b[ \t]*"
1257 "[^ \t(=a-z0-9]")))))) 1256 "[^ \t(=a-z0-9]"))))))
1258 then-test)) 1257 then-test))
1259 (setq count (- count 1))))) 1258 (setq count (1- count)))))
1260 ((looking-at "end[ \t]*if\\b") 1259 ((looking-at "end[ \t]*if\\b")
1261 (setq count (+ count 1))))) 1260 (setq count (1+ count)))))
1262 (and (= count 0) 1261 (and (zerop count)
1263 ;; All pairs accounted for. 1262 ;; All pairs accounted for.
1264 (point))))))) 1263 (point)))))))
1264
1265 1265
1266(defun fortran-indent-line () 1266(defun fortran-indent-line ()
1267 "Indent current Fortran line based on its contents and on previous lines." 1267 "Indent current Fortran line based on its contents and on previous lines."
1268 (interactive) 1268 (interactive "*")
1269 (let ((cfi (fortran-calculate-indent))) 1269 (let ((cfi (fortran-calculate-indent)))
1270 (save-excursion 1270 (save-excursion
1271 (beginning-of-line) 1271 (beginning-of-line)
@@ -1279,18 +1279,18 @@ Return point or nil."
1279 ;; Never leave point in left margin. 1279 ;; Never leave point in left margin.
1280 (if (< (current-column) cfi) 1280 (if (< (current-column) cfi)
1281 (move-to-column cfi)) 1281 (move-to-column cfi))
1282 (if (and auto-fill-function 1282 (and auto-fill-function
1283 (> (save-excursion (end-of-line) (current-column)) 1283 (> (save-excursion (end-of-line) (current-column))
1284 fill-column)) 1284 fill-column)
1285 (save-excursion 1285 (save-excursion
1286 (end-of-line) 1286 (end-of-line)
1287 (fortran-fill))) 1287 (fortran-fill)))
1288 (if fortran-blink-matching-if 1288 (when fortran-blink-matching-if
1289 (progn 1289 (fortran-blink-matching-if)
1290 (fortran-blink-matching-if) 1290 (fortran-blink-matching-do))))
1291 (fortran-blink-matching-do)))))
1292 1291
1293(defun fortran-auto-fill () 1292(defun fortran-auto-fill ()
1293 "Function to use for `normal-auto-fill-function' in Fortran mode."
1294 (if (> (current-column) (current-fill-column)) 1294 (if (> (current-column) (current-fill-column))
1295 (let ((cfi (fortran-calculate-indent))) 1295 (let ((cfi (fortran-calculate-indent)))
1296 (save-excursion 1296 (save-excursion
@@ -1313,8 +1313,8 @@ Return point or nil."
1313(defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent) 1313(defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent)
1314 1314
1315(defun fortran-indent-subprogram () 1315(defun fortran-indent-subprogram ()
1316 "Properly indent the Fortran subprogram which contains point." 1316 "Properly indent the Fortran subprogram containing point."
1317 (interactive) 1317 (interactive "*")
1318 (save-excursion 1318 (save-excursion
1319 (mark-defun) 1319 (mark-defun)
1320 (message "Indenting subprogram...") 1320 (message "Indenting subprogram...")
@@ -1339,7 +1339,7 @@ Return point or nil."
1339 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") 1339 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(")
1340 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") 1340 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]")
1341 (let (then-test) ;multi-line if-then 1341 (let (then-test) ;multi-line if-then
1342 (while (and (= (forward-line 1) 0) 1342 (while (and (zerop (forward-line 1))
1343 ;;search forward for then 1343 ;;search forward for then
1344 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") 1344 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")
1345 (not (setq then-test 1345 (not (setq then-test
@@ -1422,6 +1422,7 @@ Return point or nil."
1422 (message "Warning: `end' not in column %d. Probably\ 1422 (message "Warning: `end' not in column %d. Probably\
1423 an unclosed block." fortran-minimum-statement-indent)))))) 1423 an unclosed block." fortran-minimum-statement-indent))))))
1424 (max fortran-minimum-statement-indent icol))) 1424 (max fortran-minimum-statement-indent icol)))
1425
1425 1426
1426(defun fortran-current-line-indentation () 1427(defun fortran-current-line-indentation ()
1427 "Indentation of current line, ignoring Fortran line number or continuation. 1428 "Indentation of current line, ignoring Fortran line number or continuation.
@@ -1447,7 +1448,7 @@ non-indentation text within the comment."
1447 (current-column))) 1448 (current-column)))
1448 1449
1449(defun fortran-indent-to-column (col) 1450(defun fortran-indent-to-column (col)
1450 "Indent current line with spaces to column COL. 1451 "Indent current line to column COL.
1451notes: 1) A non-zero/non-blank character in column 5 indicates a continuation 1452notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
1452 line, and this continuation character is retained on indentation; 1453 line, and this continuation character is retained on indentation;
1453 2) If `fortran-continuation-string' is the first non-whitespace 1454 2) If `fortran-continuation-string' is the first non-whitespace
@@ -1505,11 +1506,11 @@ notes: 1) A non-zero/non-blank character in column 5 indicates a continuation
1505 (delete-horizontal-space) 1506 (delete-horizontal-space)
1506 (indent-to col) 1507 (indent-to col)
1507 ;; Indent any comment following code on the same line. 1508 ;; Indent any comment following code on the same line.
1508 (if (fortran-find-comment-start-skip) 1509 (when (fortran-find-comment-start-skip)
1509 (progn (goto-char (match-beginning 0)) 1510 (goto-char (match-beginning 0))
1510 (if (not (= (current-column) (fortran-comment-indent))) 1511 (unless (= (current-column) (fortran-comment-indent))
1511 (progn (delete-horizontal-space) 1512 (delete-horizontal-space)
1512 (indent-to (fortran-comment-indent))))))))) 1513 (indent-to (fortran-comment-indent)))))))
1513 1514
1514(defun fortran-line-number-indented-correctly-p () 1515(defun fortran-line-number-indented-correctly-p ()
1515 "Return t if current line's line number is correctly indented. 1516 "Return t if current line's line number is correctly indented.
@@ -1529,33 +1530,31 @@ Otherwise return nil."
1529 charnum) 1530 charnum)
1530 (save-excursion 1531 (save-excursion
1531 (beginning-of-line) 1532 (beginning-of-line)
1532 (if (looking-at "[ \t]*[0-9]+") 1533 (when (looking-at "[ \t]*[0-9]+")
1533 (progn 1534 (skip-chars-forward " \t")
1534 (skip-chars-forward " \t") 1535 (skip-chars-forward "0") ;skip past leading zeros
1535 (skip-chars-forward "0") ;skip past leading zeros 1536 (setq charnum
1536 (setq charnum 1537 (buffer-substring (point) (progn
1537 (buffer-substring (point) (progn 1538 (skip-chars-forward "0-9")
1538 (skip-chars-forward "0-9") 1539 (point))))
1539 (point)))) 1540 (beginning-of-line)
1540 (beginning-of-line) 1541 (save-restriction
1541 (save-restriction 1542 (save-excursion
1542 (save-excursion 1543 (narrow-to-defun)
1543 (narrow-to-defun) 1544 (and (re-search-backward
1544 (and (re-search-backward 1545 (concat
1545 (concat 1546 "\\(^[ \t0-9]*do[ \t]*0*"
1546 "\\(^[ \t0-9]*do[ \t]*0*" 1547 charnum "\\b\\)\\|" "\\(^[ \t]*0*"
1547 charnum "\\b\\)\\|" "\\(^[ \t]*0*" 1548 charnum "\\b\\)")
1548 charnum "\\b\\)") 1549 nil t)
1549 nil t) 1550 (looking-at
1550 (looking-at 1551 (concat "^[ \t0-9]*do[ \t]*0*"
1551 (concat "^[ \t0-9]*do[ \t]*0*" 1552 charnum)))))))))
1552 charnum))))))))))
1553 1553
1554(defun fortran-find-comment-start-skip (&optional all) 1554(defun fortran-find-comment-start-skip (&optional all)
1555 "Move to past `comment-start-skip' found on current line. 1555 "Move to past `comment-start-skip' found on current line.
1556Return non-nil if `comment-start-skip' found, nil if not. 1556Return non-nil if `comment-start-skip' found, nil if not.
1557If ALL is nil, only match comments that start in column > 0." 1557If ALL is nil, only match comments that start in column > 0."
1558 (interactive)
1559 ;; Hopefully at some point we can just use the line below! -stef 1558 ;; Hopefully at some point we can just use the line below! -stef
1560 ;; (comment-search-forward (line-end-position) t)) 1559 ;; (comment-search-forward (line-end-position) t))
1561 (when (or all comment-start-skip) 1560 (when (or all comment-start-skip)
@@ -1574,7 +1573,7 @@ If ALL is nil, only match comments that start in column > 0."
1574 (goto-char pos) 1573 (goto-char pos)
1575 nil))))) 1574 nil)))))
1576 1575
1577;;From: ralf@up3aud1.gwdg.de (Ralf Fassel) 1576;; From: ralf@up3aud1.gwdg.de (Ralf Fassel)
1578;; Test if TAB format continuation lines work. 1577;; Test if TAB format continuation lines work.
1579(defun fortran-is-in-string-p (where) 1578(defun fortran-is-in-string-p (where)
1580 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string." 1579 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string."
@@ -1638,6 +1637,7 @@ If ALL is nil, only match comments that start in column > 0."
1638(defalias 'fortran-auto-fill-mode 'auto-fill-mode) 1637(defalias 'fortran-auto-fill-mode 'auto-fill-mode)
1639 1638
1640(defun fortran-fill () 1639(defun fortran-fill ()
1640 "Fill the current line at an appropriate point(s)."
1641 (let* ((auto-fill-function #'fortran-auto-fill) 1641 (let* ((auto-fill-function #'fortran-auto-fill)
1642 (opoint (point)) 1642 (opoint (point))
1643 (bol (line-beginning-position)) 1643 (bol (line-beginning-position))
@@ -1665,7 +1665,7 @@ If ALL is nil, only match comments that start in column > 0."
1665 (- fill-column 6 fortran-continuation-indent)) 1665 (- fill-column 6 fortran-continuation-indent))
1666 fcpoint 1666 fcpoint
1667 start)))))) 1667 start))))))
1668 ;; decide where to split the line. If a position for a quoted 1668 ;; Decide where to split the line. If a position for a quoted
1669 ;; string was found above then use that, else break the line 1669 ;; string was found above then use that, else break the line
1670 ;; before the last delimiter. 1670 ;; before the last delimiter.
1671 ;; Delimiters are whitespace, commas, and operators. 1671 ;; Delimiters are whitespace, commas, and operators.
@@ -1674,6 +1674,7 @@ If ALL is nil, only match comments that start in column > 0."
1674 (or quote 1674 (or quote
1675 (save-excursion 1675 (save-excursion
1676 (move-to-column (1+ fill-column)) 1676 (move-to-column (1+ fill-column))
1677 ;; GM Make this a defcustom as in f90-mode? Add ", (?
1677 (skip-chars-backward "^ \t\n,'+-/*=)" 1678 (skip-chars-backward "^ \t\n,'+-/*=)"
1678;;; (if fortran-break-before-delimiters 1679;;; (if fortran-break-before-delimiters
1679;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)") 1680;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)")
@@ -1718,6 +1719,7 @@ If ALL is nil, only match comments that start in column > 0."
1718 (end-of-line)))) 1719 (end-of-line))))
1719 1720
1720(defun fortran-break-line () 1721(defun fortran-break-line ()
1722 "Call `fortran-split-line'. Joins continuation lines first, then refills."
1721 (let ((opoint (point)) 1723 (let ((opoint (point))
1722 (bol (line-beginning-position)) 1724 (bol (line-beginning-position))
1723 (comment-string 1725 (comment-string
@@ -1744,12 +1746,11 @@ If ALL is nil, only match comments that start in column > 0."
1744 1746
1745(defun fortran-analyze-file-format () 1747(defun fortran-analyze-file-format ()
1746 "Return nil if fixed format is used, t if TAB formatting is used. 1748 "Return nil if fixed format is used, t if TAB formatting is used.
1747Use `fortran-tab-mode-default' if no non-comment statements are found in the 1749Use `fortran-tab-mode-default' if no non-comment statements are found
1748file before the end or the first `fortran-analyze-depth' lines." 1750before the end or in the first `fortran-analyze-depth' lines."
1749 (let ((i 0)) 1751 (let ((i 0))
1750 (save-excursion 1752 (save-excursion
1751 (goto-char (point-min)) 1753 (goto-char (point-min))
1752 (setq i 0)
1753 (while (not (or 1754 (while (not (or
1754 (eobp) 1755 (eobp)
1755 (eq (char-after) ?\t) 1756 (eq (char-after) ?\t)
@@ -1763,49 +1764,46 @@ file before the end or the first `fortran-analyze-depth' lines."
1763 (fortran-tab-mode-default t) 1764 (fortran-tab-mode-default t)
1764 (t nil))))) 1765 (t nil)))))
1765 1766
1766(or (assq 'fortran-tab-mode-string minor-mode-alist)
1767 (setq minor-mode-alist (cons
1768 '(fortran-tab-mode-string
1769 (indent-tabs-mode fortran-tab-mode-string))
1770 minor-mode-alist)))
1771
1772(defun fortran-fill-paragraph (&optional justify) 1767(defun fortran-fill-paragraph (&optional justify)
1773 "Fill surrounding comment block as paragraphs, else fill statement. 1768 "Fill surrounding comment block as paragraphs, else fill statement.
1774Intended as the value of `fill-paragraph-function'." 1769Intended as the value of `fill-paragraph-function'.
1775 (interactive "P") 1770A comment block is filled by calling `fill-comment-paragraph' with
1771argument JUSTIFY, otherwise `fortran-fill-statement' is called.
1772Always returns non-nil (to prevent `fill-paragraph' being called)."
1773 (interactive "*P")
1776 (or (fill-comment-paragraph justify) 1774 (or (fill-comment-paragraph justify)
1777 (fortran-fill-statement) 1775 (fortran-fill-statement)
1778 t)) 1776 t))
1779 1777
1780(defun fortran-fill-statement () 1778(defun fortran-fill-statement ()
1781 "Fill a fortran statement up to `fill-column'." 1779 "Fill a Fortran statement up to `fill-column'."
1782 (interactive) 1780 (interactive "*")
1783 (let ((auto-fill-function #'fortran-auto-fill)) 1781 (let ((auto-fill-function #'fortran-auto-fill))
1784 (if (not (save-excursion 1782 (unless (save-excursion
1785 (beginning-of-line) 1783 (beginning-of-line)
1786 (or (looking-at "[ \t]*$") 1784 (or (looking-at "[ \t]*$")
1787 (looking-at fortran-comment-line-start-skip) 1785 (looking-at fortran-comment-line-start-skip)
1788 (and comment-start-skip 1786 (and comment-start-skip
1789 (looking-at (concat "[ \t]*" comment-start-skip)))))) 1787 (looking-at (concat "[ \t]*" comment-start-skip)))))
1790 (save-excursion 1788 (save-excursion
1791 ;; Find beginning of statement. 1789 ;; Find beginning of statement.
1792 (fortran-next-statement) 1790 (fortran-next-statement)
1793 (fortran-previous-statement) 1791 (fortran-previous-statement)
1794 ;; Re-indent initially. 1792 ;; Re-indent initially.
1795 (fortran-indent-line) 1793 (fortran-indent-line)
1796 ;; Replace newline plus continuation field plus indentation with 1794 ;; Replace newline plus continuation field plus indentation with
1797 ;; single space. 1795 ;; single space.
1798 (while (progn 1796 (while (progn
1799 (forward-line) 1797 (forward-line)
1800 (fortran-remove-continuation))) 1798 (fortran-remove-continuation)))
1801 (fortran-previous-statement))) 1799 (fortran-previous-statement)))
1802 (fortran-indent-line))) 1800 (fortran-indent-line)))
1803 1801
1804(defun fortran-strip-sequence-nos (&optional do-space) 1802(defun fortran-strip-sequence-nos (&optional do-space)
1805 "Delete all text in column 72 and up (assumed to be sequence numbers). 1803 "Delete all text in column 72 and up (assumed to be sequence numbers).
1806Normally also deletes trailing whitespace after stripping such text. 1804Normally also deletes trailing whitespace after stripping such text.
1807Supplying prefix arg DO-SPACE prevents stripping the whitespace." 1805Supplying prefix arg DO-SPACE prevents stripping the whitespace."
1808 (interactive "p") 1806 (interactive "*p")
1809 (save-excursion 1807 (save-excursion
1810 (goto-char (point-min)) 1808 (goto-char (point-min))
1811 (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t) 1809 (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t)