Mercurial > emacs
comparison lisp/progmodes/fortran.el @ 88155:d7ddb3e565de
sync with trunk
author | Henrik Enberg <henrik.enberg@telia.com> |
---|---|
date | Mon, 16 Jan 2006 00:03:54 +0000 |
parents | fb628fd7f726 |
children |
comparison
equal
deleted
inserted
replaced
88154:8ce476d3ba36 | 88155:d7ddb3e565de |
---|---|
1 ;;; fortran.el --- Fortran mode for GNU Emacs | 1 ;;; fortran.el --- Fortran mode for GNU Emacs |
2 | 2 |
3 ;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 2001 | 3 ;; Copyright (C) 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, |
4 ;; Free Software Foundation, Inc. | 4 ;; 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
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 <rgm@gnu.org> |
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 |
12 ;; GNU Emacs is free software; you can redistribute it and/or modify | 12 ;; GNU Emacs is free software; you can redistribute it and/or modify |
13 ;; it under the terms of the GNU General Public License as published by | 13 ;; it under the terms of the GNU General Public License as published by |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 ;; GNU General Public License for more details. | 20 ;; GNU General Public License for more details. |
21 | 21 |
22 ;; You should have received a copy of the GNU General Public License | 22 ;; You should have received a copy of the GNU General Public License |
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the | 23 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
25 ;; Boston, MA 02111-1307, USA. | 25 ;; Boston, MA 02110-1301, USA. |
26 | 26 |
27 ;;; Commentary: | 27 ;;; Commentary: |
28 | 28 |
29 ;; This mode is documented in the Emacs manual. | 29 ;; This mode is documented in the Emacs manual. |
30 ;; | 30 ;; |
51 ;; * Implement insertion and removal of statement continuations in | 51 ;; * Implement insertion and removal of statement continuations in |
52 ;; mixed f77/f90 style, with the first `&' past column 72 and the | 52 ;; mixed f77/f90 style, with the first `&' past column 72 and the |
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 dabbrev-case-fold-search) | |
58 (defvar font-lock-syntactic-keywords) | |
59 (defvar gud-find-expr-function) | |
60 (defvar imenu-case-fold-search) | |
61 (defvar imenu-syntax-alist)) | |
62 | |
63 | |
56 (defgroup fortran nil | 64 (defgroup fortran nil |
57 "Fortran mode for Emacs" | 65 "Major mode for editing fixed format Fortran code." |
66 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces) | |
58 :link '(custom-manual "(emacs)Fortran") | 67 :link '(custom-manual "(emacs)Fortran") |
59 :group 'languages) | 68 :group 'languages) |
60 | 69 |
61 (defgroup fortran-indent nil | 70 (defgroup fortran-indent nil |
62 "Indentation variables in Fortran mode" | 71 "Indentation variables in Fortran mode." |
63 :prefix "fortran-" | 72 :prefix "fortran-" |
64 :group 'fortran) | 73 :group 'fortran) |
65 | 74 |
66 (defgroup fortran-comment nil | 75 (defgroup fortran-comment nil |
67 "Comment-handling variables in Fortran mode" | 76 "Comment-handling variables in Fortran mode." |
68 :prefix "fortran-" | 77 :prefix "fortran-" |
69 :group 'fortran) | 78 :group 'fortran) |
70 | 79 |
71 | 80 |
72 ;;;###autoload | 81 ;;;###autoload |
73 (defcustom fortran-tab-mode-default nil | 82 (defcustom fortran-tab-mode-default nil |
74 "*Default tabbing/carriage control style for empty files in Fortran mode. | 83 "*Default tabbing/carriage control style for empty files in Fortran mode. |
75 A value of t specifies tab-digit style of continuation control. | 84 A non-nil value specifies tab-digit style of continuation control. |
76 A value of nil specifies that continuation lines are marked | 85 A value of nil specifies that continuation lines are marked |
77 with a character in column 6." | 86 with a character in column 6." |
78 :type 'boolean | 87 :type 'boolean |
79 :group 'fortran-indent) | 88 :group 'fortran-indent) |
80 | 89 |
81 ;; Buffer local, used to display mode line. | 90 (defcustom fortran-tab-mode-string "/t" |
82 (defcustom fortran-tab-mode-string nil | 91 "*String to appear in mode line in TAB format buffers." |
83 "String to appear in mode line when TAB format mode is on." | 92 :type 'string |
84 :type '(choice (const nil) string) | |
85 :group 'fortran-indent) | 93 :group 'fortran-indent) |
86 (make-variable-buffer-local 'fortran-tab-mode-string) | |
87 | 94 |
88 (defcustom fortran-do-indent 3 | 95 (defcustom fortran-do-indent 3 |
89 "*Extra indentation applied to DO blocks." | 96 "*Extra indentation applied to DO blocks." |
90 :type 'integer | 97 :type 'integer |
91 :group 'fortran-indent) | 98 :group 'fortran-indent) |
92 | 99 |
93 (defcustom fortran-if-indent 3 | 100 (defcustom fortran-if-indent 3 |
94 "*Extra indentation applied to IF blocks." | 101 "*Extra indentation applied to IF, SELECT CASE and WHERE blocks." |
95 :type 'integer | 102 :type 'integer |
96 :group 'fortran-indent) | 103 :group 'fortran-indent) |
97 | 104 |
98 (defcustom fortran-structure-indent 3 | 105 (defcustom fortran-structure-indent 3 |
99 "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks." | 106 "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks." |
100 :type 'integer | 107 :type 'integer |
101 :group 'fortran-indent) | 108 :group 'fortran-indent) |
102 | 109 |
103 (defcustom fortran-continuation-indent 5 | 110 (defcustom fortran-continuation-indent 5 |
104 "*Extra indentation applied to Fortran continuation lines." | 111 "*Extra indentation applied to continuation lines." |
105 :type 'integer | 112 :type 'integer |
106 :group 'fortran-indent) | 113 :group 'fortran-indent) |
107 | 114 |
108 (defcustom fortran-comment-indent-style 'fixed | 115 (defcustom fortran-comment-indent-style 'fixed |
109 "*How to indent comments. | 116 "*How to indent comments. |
110 nil forces comment lines not to be touched, | 117 nil forces comment lines not to be touched; |
111 `fixed' makes fixed comment indentation to `fortran-comment-line-extra-indent' | 118 `fixed' indents to `fortran-comment-line-extra-indent' columns beyond |
112 columns beyond `fortran-minimum-statement-indent-fixed' (for | 119 `fortran-minimum-statement-indent-fixed' (if `indent-tabs-mode' nil), or |
113 `indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for | 120 `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 | 121 `relative' indents to current Fortran indentation plus |
116 `fortran-comment-line-extra-indent'." | 122 `fortran-comment-line-extra-indent'." |
117 :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative)) | 123 :type '(radio (const :tag "Untouched" nil) (const fixed) (const relative)) |
118 :group 'fortran-indent) | 124 :group 'fortran-indent) |
119 | 125 |
120 (defcustom fortran-comment-line-extra-indent 0 | 126 (defcustom fortran-comment-line-extra-indent 0 |
121 "*Amount of extra indentation for text within full-line comments." | 127 "*Amount of extra indentation for text within full-line comments." |
122 :type 'integer | 128 :type 'integer |
123 :group 'fortran-indent | 129 :group 'fortran-indent |
124 :group 'fortran-comment) | 130 :group 'fortran-comment) |
125 | 131 |
126 (defcustom fortran-comment-line-start "C" | 132 (defcustom fortran-comment-line-start "C" |
127 "*Delimiter inserted to start new full-line comment. | 133 "*Delimiter inserted to start new full-line comment. |
128 You might want to change this to \"*\", for instance." | 134 You might want to change this to \"*\", for instance." |
129 :version "21.1" | 135 :version "21.1" |
130 :type 'string | 136 :type 'string |
131 :group 'fortran-comment) | 137 :group 'fortran-comment) |
132 | 138 |
133 ;; This used to match preprocessor lines too, but that messes up | 139 ;; This used to match preprocessor lines too, but that messes up |
134 ;; filling and doesn't seem to be necessary. | 140 ;; filling and doesn't seem to be necessary. |
135 (defcustom fortran-comment-line-start-skip | 141 (defcustom fortran-comment-line-start-skip |
136 "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*" | 142 "^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*" |
137 "*Regexp to match the start of a full-line comment." | 143 "*Regexp to match the start of a full-line comment." |
138 :version "21.1" | 144 :version "21.1" |
139 :type 'regexp | 145 :type 'regexp |
140 :group 'fortran-comment) | 146 :group 'fortran-comment) |
141 | 147 |
142 (defcustom fortran-directive-re | 148 (defcustom fortran-directive-re |
143 "^[ \t]*#.*" | 149 "^[ \t]*#.*" |
144 "*Regexp to match a directive line. | 150 "*Regexp to match a directive line. |
145 The matching text will be fontified with `font-lock-keyword-face'. | 151 The matching text will be fontified with `font-lock-keyword-face'. |
146 The matching line will be given zero indentation." | 152 The matching line will be given zero indentation." |
147 :version "21.4" | 153 :version "22.1" |
148 :type 'regexp | 154 :type 'regexp |
149 :group 'fortran-indent) | 155 :group 'fortran-indent) |
150 | 156 |
151 (defcustom fortran-minimum-statement-indent-fixed 6 | 157 (defcustom fortran-minimum-statement-indent-fixed 6 |
152 "*Minimum statement indentation for fixed format continuation style." | 158 "*Minimum statement indentation for fixed format continuation style." |
153 :type 'integer | 159 :type 'integer |
154 :group 'fortran-indent) | 160 :group 'fortran-indent) |
155 | 161 |
156 (defcustom fortran-minimum-statement-indent-tab (max tab-width 6) | 162 (defcustom fortran-minimum-statement-indent-tab (max tab-width 6) |
157 "*Minimum statement indentation for TAB format continuation style." | 163 "*Minimum statement indentation for TAB format continuation style." |
158 :type 'integer | 164 :type 'integer |
159 :group 'fortran-indent) | 165 :group 'fortran-indent) |
160 | 166 |
161 ;; Note that this is documented in the v18 manuals as being a string | 167 ;; Note that this is documented in the v18 manuals as being a string |
162 ;; of length one rather than a single character. | 168 ;; of length one rather than a single character. |
163 ;; The code in this file accepts either format for compatibility. | 169 ;; The code in this file accepts either format for compatibility. |
164 (defcustom fortran-comment-indent-char " " | 170 (defcustom fortran-comment-indent-char " " |
165 "*Single-character string inserted for Fortran comment indentation. | 171 "*Single-character string inserted for Fortran comment indentation. |
166 Normally a space." | 172 Normally a space." |
167 :type 'string | 173 :type 'string |
168 :group 'fortran-comment) | 174 :group 'fortran-comment) |
169 | 175 |
170 (defcustom fortran-line-number-indent 1 | 176 (defcustom fortran-line-number-indent 1 |
171 "*Maximum indentation for Fortran line numbers. | 177 "*Maximum indentation for Fortran line numbers. |
172 5 means right-justify them within their five-column field." | 178 5 means right-justify them within their five-column field." |
173 :type 'integer | 179 :type 'integer |
174 :group 'fortran-indent) | 180 :group 'fortran-indent) |
175 | 181 |
176 (defcustom fortran-check-all-num-for-matching-do nil | 182 (defcustom fortran-check-all-num-for-matching-do nil |
177 "*Non-nil causes all numbered lines to be treated as possible DO loop ends." | 183 "*Non-nil causes all numbered lines to be treated as possible DO loop ends." |
178 :type 'boolean | 184 :type 'boolean |
179 :group 'fortran) | 185 :group 'fortran) |
180 | 186 |
181 (defcustom fortran-blink-matching-if nil | 187 (defcustom fortran-blink-matching-if nil |
182 "*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF. | 188 "*Non-nil causes \\[fortran-indent-line] on ENDIF to blink on matching IF. |
183 Also, from an ENDDO statement blink on matching DO [WHILE] statement." | 189 Also, from an ENDDO statement blink on matching DO [WHILE] statement." |
184 :type 'boolean | 190 :type 'boolean |
185 :group 'fortran) | 191 :group 'fortran) |
186 | 192 |
187 (defcustom fortran-continuation-string "$" | 193 (defcustom fortran-continuation-string "$" |
188 "*Single-character string used for Fortran continuation lines. | 194 "*Single-character string used for Fortran continuation lines. |
189 In fixed format continuation style, this character is inserted in | 195 In fixed format continuation style, this character is inserted in |
190 column 6 by \\[fortran-split-line] to begin a continuation line. | 196 column 6 by \\[fortran-split-line] to begin a continuation line. |
191 Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will | 197 Also, if \\[fortran-indent-line] finds this at the beginning of a |
192 convert the line into a continuation line of the appropriate style. | 198 line, it will convert the line into a continuation line of the |
193 Normally $." | 199 appropriate style. Normally $." |
194 :type 'string | 200 :type 'string |
195 :group 'fortran) | 201 :group 'fortran) |
196 | 202 |
197 (defcustom fortran-comment-region "c$$$" | 203 (defcustom fortran-comment-region "c$$$" |
198 "*String inserted by \\[fortran-comment-region] at start of each \ | 204 "*String inserted by \\[fortran-comment-region] at start of each \ |
199 line in region." | 205 line in region." |
200 :type 'string | 206 :type 'string |
201 :group 'fortran-comment) | 207 :group 'fortran-comment) |
202 | 208 |
203 (defcustom fortran-electric-line-number t | 209 (defcustom fortran-electric-line-number t |
204 "*Non-nil causes line number digits to be moved to the correct \ | 210 "*Non-nil causes line numbers to be moved to the correct column as typed." |
205 column as typed." | 211 :type 'boolean |
206 :type 'boolean | |
207 :group 'fortran) | 212 :group 'fortran) |
208 | 213 |
209 (defvar fortran-column-ruler-fixed | 214 (defcustom fortran-column-ruler-fixed |
210 "0 4 6 10 20 30 40 5\ | 215 "0 4 6 10 20 30 40 5\ |
211 0 60 70\n\ | 216 0 60 70\n\ |
212 \[ ]|{ | | | | | | | | \ | 217 \[ ]|{ | | | | | | | | \ |
213 \| | | | |}\n" | 218 \| | | | |}\n" |
214 "String displayed above current line by \\[fortran-column-ruler]. | 219 "String displayed above current line by \\[fortran-column-ruler]. |
215 This variable used in fixed format mode.") | 220 This variable is used in fixed format mode. |
216 | 221 See the variable `fortran-column-ruler-tab' for TAB format mode." |
217 (defvar fortran-column-ruler-tab | 222 :type 'string |
223 :group 'fortran) | |
224 | |
225 (defcustom fortran-column-ruler-tab | |
218 "0 810 20 30 40 5\ | 226 "0 810 20 30 40 5\ |
219 0 60 70\n\ | 227 0 60 70\n\ |
220 \[ ]| { | | | | | | | | \ | 228 \[ ]| { | | | | | | | | \ |
221 \| | | | |}\n" | 229 \| | | | |}\n" |
222 "String displayed above current line by \\[fortran-column-ruler]. | 230 "String displayed above current line by \\[fortran-column-ruler]. |
223 This variable used in TAB format mode.") | 231 This variable is used in TAB format mode. |
224 | 232 See the variable `fortran-column-ruler-fixed' for fixed format mode." |
225 (defvar fortran-analyze-depth 100 | 233 :type 'string |
226 "Number of lines to scan to determine whether to use fixed or TAB \ | 234 :group 'fortran) |
227 format style.") | 235 |
236 (defcustom fortran-analyze-depth 100 | |
237 "Number of lines to scan to identify fixed or TAB format style." | |
238 :type 'integer | |
239 :group 'fortran) | |
228 | 240 |
229 (defcustom fortran-break-before-delimiters t | 241 (defcustom fortran-break-before-delimiters t |
230 "*Non-nil causes filling to break lines before delimiters." | 242 "*Non-nil causes filling to break lines before delimiters. |
231 :type 'boolean | 243 Delimiters are characters matching the regexp `fortran-break-delimiters-re'." |
244 :type 'boolean | |
232 :group 'fortran) | 245 :group 'fortran) |
233 | 246 |
234 (defvar fortran-mode-syntax-table | 247 (defconst fortran-break-delimiters-re "[-+*/><=, \t]" |
235 (let ((table (make-syntax-table))) | 248 "Regexp matching delimiter characters at which lines may be broken. |
236 ;; We might like `;' to be punctuation (g77 multi-statement | 249 There are certain tokens comprised entirely of characters |
237 ;; lines), but that screws abbrevs. | 250 matching this regexp that should not be split, and these are |
238 (modify-syntax-entry ?\; "w" table) | 251 specified by the constant `fortran-no-break-re'.") |
239 (modify-syntax-entry ?\r " " table) | 252 |
240 (modify-syntax-entry ?+ "." table) | 253 ;; The ">=", etc F77 extensions are supported by g77. |
241 (modify-syntax-entry ?- "." table) | 254 (defconst fortran-no-break-re |
242 (modify-syntax-entry ?= "." table) | 255 (regexp-opt '("**" "//" "=>" ">=" "<=" "==" "/=") 'paren) |
243 (modify-syntax-entry ?* "." table) | 256 "Regexp specifying where not to break lines when filling. |
244 (modify-syntax-entry ?/ "." table) | 257 This regexp matches certain tokens comprised entirely of |
245 (modify-syntax-entry ?\' "\"" table) | 258 characters matching the regexp `fortran-break-delimiters-re' that should |
246 (modify-syntax-entry ?\" "\"" table) | 259 not be split by filling. Each element is assumed to be two |
247 ;; Consistent with GNU Fortran -- see the manual. | 260 characters long.") |
248 (modify-syntax-entry ?\\ "\\" table) | 261 |
249 ;; This might be better as punctuation, as for C, but this way you | 262 (defcustom fortran-mode-hook nil |
250 ;; can treat floating-point numbers as symbols. | 263 "Hook run when entering Fortran mode." |
251 (modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b' | 264 :type 'hook |
252 (modify-syntax-entry ?_ "_" table) | 265 :group 'fortran) |
253 (modify-syntax-entry ?$ "_" table) ; esp. VMSisms | 266 |
254 (modify-syntax-entry ?\! "<" table) | 267 |
255 (modify-syntax-entry ?\n ">" table) | 268 (defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(" |
256 table) | 269 "Regexp matching the start of an IF statement.") |
257 "Syntax table in use in Fortran mode buffers.") | 270 |
271 (defvar fortran-end-prog-re1 | |
272 "end\ | |
273 \\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\ | |
274 \\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?" | |
275 "Regexp possibly matching the end of a subprogram.") | |
276 | |
277 (defvar fortran-end-prog-re | |
278 (concat "^[ \t0-9]*" fortran-end-prog-re1) | |
279 "Regexp possibly matching the end of a subprogram, from the line start. | |
280 See also `fortran-end-prog-re1'.") | |
281 | |
282 (defconst fortran-type-types | |
283 (concat "\\<" | |
284 (mapconcat 'identity ; " " -> "[ \t]*" | |
285 (split-string | |
286 (regexp-opt | |
287 (let ((simple-types | |
288 '("character" "byte" "integer" "logical" | |
289 "none" "real" "complex" | |
290 "double precision" "double complex")) | |
291 (structured-types '("structure" "union" "map")) | |
292 (other-types '("record" "dimension" | |
293 "parameter" "common" "save" | |
294 "external" "intrinsic" "data" | |
295 "equivalence"))) | |
296 (append | |
297 (mapcar (lambda (x) (concat "implicit " x)) | |
298 simple-types) | |
299 simple-types | |
300 (mapcar (lambda (x) (concat "end " x)) | |
301 structured-types) | |
302 structured-types | |
303 other-types)) 'paren)) | |
304 "[ \t]*") "\\>") | |
305 "Regexp matching Fortran types.") | |
306 | |
307 (defvar fortran-font-lock-keywords-1 | |
308 ;; Program, subroutine and function declarations, plus calls. | |
309 '(("\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|\ | |
310 program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?" | |
311 (1 font-lock-keyword-face) | |
312 (2 font-lock-function-name-face nil t))) | |
313 "Subdued level highlighting for Fortran mode.") | |
314 | |
315 (defvar fortran-font-lock-keywords-2 | |
316 (append fortran-font-lock-keywords-1 | |
317 (list | |
318 ;; Fontify all type specifiers (must be first - see below). | |
319 (cons fortran-type-types 'font-lock-type-face) | |
320 ;; Builtin keywords (except logical, do and goto - see below). | |
321 (concat "\\<" (regexp-opt | |
322 '("continue" "format" "end" "enddo" | |
323 "if" "then" "else" "endif" "elseif" | |
324 "while" "inquire" "stop" "return" | |
325 "include" "open" "close" "read" | |
326 "write" "format" "print" "select" "case" | |
327 "cycle" "exit" "rewind" "backspace" | |
328 "where" "elsewhere") | |
329 'paren) "\\>") | |
330 ;; Builtin operators. | |
331 (concat "\\." (regexp-opt | |
332 '("and" "or" "not" "lt" "le" "eq" "ge" | |
333 "gt" "ne" "true" "false") | |
334 'paren) "\\.") | |
335 ;; do/goto keywords and targets, and goto tags. | |
336 '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?" | |
337 (1 font-lock-keyword-face) | |
338 (2 font-lock-constant-face nil t)) | |
339 '("^ *\\([0-9]+\\)" . font-lock-constant-face))) | |
340 "Medium level highlighting for Fortran mode.") | |
341 | |
342 (defvar fortran-font-lock-keywords-3 | |
343 (append | |
344 fortran-font-lock-keywords-1 | |
345 ;; All type specifiers plus their declared items. | |
346 (list | |
347 (list (concat fortran-type-types "[ \t(/]*\\(*\\)?") | |
348 ;; Type specifier. | |
349 '(1 font-lock-type-face) | |
350 ;; Declaration item (or just /.../ block name). | |
351 `(font-lock-match-c-style-declaration-item-and-skip-to-next | |
352 ;; Start after any *(...) expression. | |
353 (condition-case nil | |
354 (and (match-beginning ,(1+ (regexp-opt-depth | |
355 fortran-type-types))) | |
356 (forward-sexp) | |
357 (forward-sexp)) | |
358 (error nil)) | |
359 ;; No need to clean up. | |
360 nil | |
361 ;; Fontify as a variable name, functions fontified elsewhere. | |
362 (1 font-lock-variable-name-face nil t)))) | |
363 ;; Things extra to `fortran-font-lock-keywords-3' (must be done first). | |
364 (list | |
365 ;; Goto-like `err=label'/`end=label' in read/write statements. | |
366 '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?" | |
367 (1 font-lock-keyword-face) (4 font-lock-constant-face nil t)) | |
368 ;; Standard continuation character and in a TAB-formatted line. | |
369 '("^ \\{5\\}\\([^ 0\n]\\)" 1 font-lock-string-face) | |
370 '("^\t\\([1-9]\\)" 1 font-lock-string-face)) | |
371 `((,fortran-directive-re (0 font-lock-keyword-face t))) | |
372 ;; `fortran-font-lock-keywords-2' without types (see above). | |
373 (cdr (nthcdr (length fortran-font-lock-keywords-1) | |
374 fortran-font-lock-keywords-2))) | |
375 "Gaudy level highlighting for Fortran mode.") | |
376 | |
377 (defvar fortran-font-lock-keywords-4 | |
378 (append fortran-font-lock-keywords-3 | |
379 (list (list | |
380 (concat "\\<" | |
381 (regexp-opt | |
382 '("int" "ifix" "idint" "real" "float" "sngl" | |
383 "dble" "cmplx" "ichar" "char" "aint" "dint" | |
384 "anint" "dnint" "nint" "idnint" "iabs" "abs" | |
385 "dabs" "cabs" "mod" "amod" "dmod" "isign" | |
386 "sign" "dsign" "idim" "dim" "ddim" "dprod" | |
387 "max" "max0" "amax1" "dmax1" "amax0" "max1" | |
388 "min0" "amin1" "dmin1" "amin0" "min1" "len" | |
389 "index" "lge" "lgt" "lle" "llt" "aimag" | |
390 "conjg" "sqrt" "dsqrt" "csqrt" "exp" "dexp" | |
391 "cexp" "log" "alog" "dlog" "clog" "log10" | |
392 "alog10" "dlog10" "sin" "dsin" "csin" "cos" | |
393 "dcos" "ccos" "tan" "dtan" "asin" "dasin" | |
394 "acos" "dacos" "atan" "datan" "atan2" "datan2" | |
395 "sinh" "dsinh" "cosh" "dcosh" "tanh" "dtanh") | |
396 'paren) "[ \t]*(") '(1 font-lock-builtin-face)))) | |
397 "Maximum highlighting for Fortran mode. | |
398 Consists of level 3 plus all other intrinsics not already highlighted.") | |
258 | 399 |
259 ;; Comments are real pain in Fortran because there is no way to | 400 ;; Comments are real pain in Fortran because there is no way to |
260 ;; represent the standard comment syntax in an Emacs syntax table. | 401 ;; represent the standard comment syntax in an Emacs syntax table. |
261 ;; (We can do so for F90-style). Therefore an unmatched quote in a | 402 ;; (We can do so for F90-style). Therefore an unmatched quote in a |
262 ;; standard comment will throw fontification off on the wrong track. | 403 ;; standard comment will throw fontification off on the wrong track. |
263 ;; So we do syntactic fontification with regexps. | 404 ;; So we do syntactic fontification with regexps. |
264 | 405 (defvar fortran-font-lock-syntactic-keywords |
265 (defvar fortran-font-lock-keywords-1 nil | 406 '(("^[cd\\*]" 0 (11)) |
266 "Subdued level highlighting for Fortran mode.") | 407 ("^[^cd\\*\t\n].\\{71\\}\\([^\n]+\\)" 1 (11))) |
267 | |
268 (defvar fortran-font-lock-keywords-2 nil | |
269 "Medium level highlighting for Fortran mode.") | |
270 | |
271 (defvar fortran-font-lock-keywords-3 nil | |
272 "Gaudy level highlighting for Fortran mode.") | |
273 | |
274 (defvar fortran-font-lock-syntactic-keywords nil | |
275 "`font-lock-syntactic-keywords' for Fortran. | 408 "`font-lock-syntactic-keywords' for Fortran. |
276 These get fixed-format comments fontified.") | 409 These get fixed-format comments fontified.") |
277 | 410 |
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 | 411 (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1 |
388 "Default expressions to highlight in Fortran mode.") | 412 "Default expressions to highlight in Fortran mode.") |
389 | 413 |
390 (defvar fortran-imenu-generic-expression | 414 (defvar fortran-imenu-generic-expression |
391 ;; These patterns could be confused by sequence nos. in cols 72+ and | 415 ;; These patterns could be confused by sequence nos. in cols 72+ and |
392 ;; don't allow continuations everywhere. | 416 ;; don't allow continuations everywhere. |
393 (list | 417 (list |
394 (list | 418 (list |
405 ;; Possible statement continuation: | 429 ;; Possible statement continuation: |
406 "[ \t" fortran-continuation-string "]+" | 430 "[ \t" fortran-continuation-string "]+" |
407 ;; Variable to index: | 431 ;; Variable to index: |
408 "\\(\\sw+\\)") | 432 "\\(\\sw+\\)") |
409 3) | 433 3) |
410 ;; Un-named block data | 434 ;; Un-named block data. |
411 (list nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1)) | 435 '(nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1)) |
412 "Imenu generic expression for `imenu-default-create-index-function'.") | 436 "Value for `imenu-generic-expression' in Fortran mode.") |
437 | |
438 | |
439 ;; Hideshow support. | |
440 (defconst fortran-blocks-re | |
441 (concat "block[ \t]*data\\|select[ \t]*case\\|" | |
442 (regexp-opt '("do" "if" "interface" "function" "map" "program" | |
443 "structure" "subroutine" "union" "where"))) | |
444 "Regexp potentially indicating the start or end of a Fortran \"block\". | |
445 Omits naked END statements, and DO-loops closed by anything other | |
446 than ENDDO.") | |
447 | |
448 (defconst fortran-end-block-re | |
449 ;; Do-loops terminated by things other than ENDDO cannot be handled | |
450 ;; with a regexp. This omission does not seem to matter to hideshow... | |
451 (concat "^[ \t0-9]*\\<end[ \t]*\\(" | |
452 fortran-blocks-re | |
453 ;; Naked END statement. | |
454 "\\|!\\|$\\)") | |
455 "Regexp matching the end of a Fortran \"block\", from the line start. | |
456 Note that only ENDDO is handled for the end of a DO-loop. Used | |
457 in the Fortran entry in `hs-special-modes-alist'.") | |
458 | |
459 (defconst fortran-start-block-re | |
460 (concat | |
461 "^[ \t0-9]*\\(" ; statement number | |
462 ;; Structure label for DO, IF, SELECT, WHERE. | |
463 "\\(\\(\\sw+[ \t]*:[ \t]*\\)?" | |
464 ;; IF blocks are a nuisance: | |
465 ;; IF ( ... ) foo is not a block, but a single statement. | |
466 ;; IF ( ... ) THEN can be split over multiple lines. | |
467 ;; [So can, eg, a DO WHILE (... ), but that is less common, I hope.] | |
468 ;; The regexp below allows for it to be split over at most 2 lines. | |
469 ;; That leads to the problem of not matching two consecutive IF | |
470 ;; statements as one, eg: | |
471 ;; IF ( ... ) foo | |
472 ;; IF ( ... ) THEN | |
473 ;; It simply is not possible to do this in a 100% correct fashion | |
474 ;; using a regexp - see the functions fortran-end-if, | |
475 ;; fortran-beginning-if for the hoops we have to go through. | |
476 ;; An alternative is to match on THEN at a line end, eg: | |
477 ;; ".*)[ \t]*then[ \t]*\\($\\|!\\)" | |
478 ;; This would also match ELSE branches, though. This does not seem | |
479 ;; right to me, because then one has neighbouring blocks that are | |
480 ;; not nested in each other. | |
481 "\\(if[ \t]*(\\(.*\\|" | |
482 ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|" | |
483 "do\\|select[ \t]*case\\|where\\)\\)\\|" | |
484 (regexp-opt '("interface" "function" "map" "program" | |
485 "structure" "subroutine" "union")) | |
486 "\\|block[ \t]*data\\)[ \t]*") | |
487 "Regexp matching the start of a Fortran \"block\", from the line start. | |
488 A simple regexp cannot do this in fully correct fashion, so this | |
489 tries to strike a compromise between complexity and flexibility. | |
490 Used in the Fortran entry in `hs-special-modes-alist'.") | |
491 | |
492 (add-to-list 'hs-special-modes-alist | |
493 `(fortran-mode ,fortran-start-block-re ,fortran-end-block-re | |
494 "^[cC*!]" fortran-end-of-block nil)) | |
495 | |
496 | |
497 (defvar fortran-mode-syntax-table | |
498 (let ((table (make-syntax-table))) | |
499 ;; We might like `;' to be punctuation (g77 multi-statement | |
500 ;; lines), but that screws abbrevs. | |
501 (modify-syntax-entry ?\; "w" table) | |
502 (modify-syntax-entry ?\r " " table) | |
503 (modify-syntax-entry ?+ "." table) | |
504 (modify-syntax-entry ?- "." table) | |
505 (modify-syntax-entry ?= "." table) | |
506 (modify-syntax-entry ?* "." table) | |
507 (modify-syntax-entry ?/ "." table) | |
508 (modify-syntax-entry ?\' "\"" table) | |
509 (modify-syntax-entry ?\" "\"" table) | |
510 ;; Consistent with GNU Fortran's default -- see the manual. | |
511 ;; The F77 standard imposes no rule on this issue. | |
512 (modify-syntax-entry ?\\ "\\" table) | |
513 ;; This might be better as punctuation, as for C, but this way you | |
514 ;; can treat floating-point numbers as symbols. | |
515 (modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b' | |
516 (modify-syntax-entry ?_ "_" table) | |
517 (modify-syntax-entry ?$ "_" table) ; esp. VMSisms | |
518 (modify-syntax-entry ?\! "<" table) | |
519 (modify-syntax-entry ?\n ">" table) | |
520 table) | |
521 "Syntax table used in Fortran mode.") | |
522 | |
523 (defvar fortran-gud-syntax-table | |
524 (let ((st (make-syntax-table fortran-mode-syntax-table))) | |
525 (modify-syntax-entry ?\n "." st) | |
526 st) | |
527 "Syntax table used to parse Fortran expressions for printing in GUD.") | |
413 | 528 |
414 (defvar fortran-mode-map | 529 (defvar fortran-mode-map |
415 (let ((map (make-sparse-keymap))) | 530 (let ((map (make-sparse-keymap))) |
416 (define-key map ";" 'fortran-abbrev-start) | 531 (define-key map ";" 'fortran-abbrev-start) |
417 (define-key map "\C-c;" 'fortran-comment-region) | 532 (define-key map "\C-c;" 'fortran-comment-region) |
418 (define-key map "\M-;" 'fortran-indent-comment) | 533 (define-key map "\M-;" 'fortran-indent-comment) |
419 (define-key map "\M-\n" 'fortran-split-line) | 534 (define-key map "\M-\n" 'fortran-split-line) |
420 (define-key map "\M-\C-q" 'fortran-indent-subprogram) | 535 (define-key map "\M-\C-n" 'fortran-end-of-block) |
536 (define-key map "\M-\C-p" 'fortran-beginning-of-block) | |
537 (define-key map "\M-\C-q" 'fortran-indent-subprogram) | |
421 (define-key map "\C-c\C-w" 'fortran-window-create-momentarily) | 538 (define-key map "\C-c\C-w" 'fortran-window-create-momentarily) |
422 (define-key map "\C-c\C-r" 'fortran-column-ruler) | 539 (define-key map "\C-c\C-r" 'fortran-column-ruler) |
423 (define-key map "\C-c\C-p" 'fortran-previous-statement) | 540 (define-key map "\C-c\C-p" 'fortran-previous-statement) |
424 (define-key map "\C-c\C-n" 'fortran-next-statement) | 541 (define-key map "\C-c\C-n" 'fortran-next-statement) |
425 (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90 | 542 (define-key map "\C-c\C-d" 'fortran-join-line) ; like f90 |
426 (define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation | 543 (define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation |
427 (define-key map "0" 'fortran-electric-line-number) | 544 (define-key map "0" 'fortran-electric-line-number) |
428 (define-key map "1" 'fortran-electric-line-number) | 545 (define-key map "1" 'fortran-electric-line-number) |
429 (define-key map "2" 'fortran-electric-line-number) | 546 (define-key map "2" 'fortran-electric-line-number) |
430 (define-key map "3" 'fortran-electric-line-number) | 547 (define-key map "3" 'fortran-electric-line-number) |
431 (define-key map "4" 'fortran-electric-line-number) | 548 (define-key map "4" 'fortran-electric-line-number) |
433 (define-key map "6" 'fortran-electric-line-number) | 550 (define-key map "6" 'fortran-electric-line-number) |
434 (define-key map "7" 'fortran-electric-line-number) | 551 (define-key map "7" 'fortran-electric-line-number) |
435 (define-key map "8" 'fortran-electric-line-number) | 552 (define-key map "8" 'fortran-electric-line-number) |
436 (define-key map "9" 'fortran-electric-line-number) | 553 (define-key map "9" 'fortran-electric-line-number) |
437 | 554 |
438 ;; Menu | 555 (easy-menu-define fortran-menu map "Menu for Fortran mode." |
439 (easy-menu-define | 556 `("Fortran" |
440 fortran-mode-menu map "" | 557 ["Manual" (info "(emacs)Fortran")] |
441 `("Fortran" | 558 ("Customization" |
442 ["Manual" (info "(emacs)Fortran")] | 559 ,(custom-menu-create 'fortran) |
443 ("Customization" | 560 ["Set" Custom-set t] |
444 ,(custom-menu-create 'fortran) | 561 ["Save" Custom-save t] |
445 ["Set" Custom-set t] | 562 ["Reset to Current" Custom-reset-current t] |
446 ["Save" Custom-save t] | 563 ["Reset to Saved" Custom-reset-saved t] |
447 ["Reset to Current" Custom-reset-current t] | 564 ["Reset to Standard Settings" Custom-reset-standard t] |
448 ["Reset to Saved" Custom-reset-saved t] | 565 ) |
449 ["Reset to Standard Settings" Custom-reset-standard t]) | 566 "--" |
450 "----" | 567 ["Comment Region" fortran-comment-region mark-active] |
451 ["Toggle Auto-fill" auto-fill-mode :style toggle | 568 ["Uncomment Region" |
452 :selected auto-fill-function] | 569 (fortran-comment-region (region-beginning) (region-end) 1) |
453 ["Toggle abbrev-mode" abbrev-mode :style toggle :selected abbrev-mode] | 570 mark-active] |
454 "----" | 571 ["Indent Region" indent-region mark-active] |
455 ["Comment-out Region" fortran-comment-region mark-active] | 572 ["Indent Subprogram" fortran-indent-subprogram t] |
456 ["Uncomment-out region" | 573 "--" |
457 (fortran-comment-region (region-beginning) (region-end) 1) | 574 ["Beginning of Subprogram" fortran-beginning-of-subprogram t] |
458 mark-active] | 575 ["End of Subprogram" fortran-end-of-subprogram t] |
459 ["Indent Region" indent-region mark-active] | 576 ("Mark" |
460 ["Indent Subprogram" fortran-indent-subprogram t] | 577 ["Subprogram" mark-defun t] |
461 "----" | 578 ["IF Block" fortran-mark-if t] |
462 ["Beginning of Subprogram" fortran-beginning-of-subprogram t] | 579 ["DO Block" fortran-mark-do t] |
463 ["End of Subprogram" fortran-end-of-subprogram t] | 580 ) |
464 ("Mark" | 581 ["Narrow to Subprogram" narrow-to-defun t] |
465 ["Subprogram" mark-defun t] | 582 ["Widen" widen t] |
466 ["IF Block" fortran-mark-if t] | 583 "--" |
467 ["DO Block" fortran-mark-do t]) | 584 ["Temporary column ruler" fortran-column-ruler t] |
468 ["Narrow to Subprogram" narrow-to-defun t] | 585 ["72-column window" fortran-window-create t] |
469 ["Widen" widen t] | 586 ["Full Width Window" |
470 "----" | 587 (enlarge-window-horizontally (- (frame-width) (window-width))) |
471 ["Temporary column ruler" fortran-column-ruler t] | 588 (< (window-width) (frame-width))] |
472 ["72-column window" fortran-window-create t] | 589 ["Momentary 72-column window" fortran-window-create-momentarily t] |
473 ["Full Width Window" | 590 "--" |
474 (enlarge-window-horizontally (- (frame-width) (window-width))) | 591 ["Break Line at Point" fortran-split-line t] |
475 (< (window-width) (frame-width))] | 592 ["Join Line" fortran-join-line t] |
476 ["Momentary 72-column window" fortran-window-create-momentarily t] | 593 ["Fill Statement/Comment" fill-paragraph t] |
477 "----" | 594 "--" |
478 ["Break Line at Point" fortran-split-line t] | 595 ["Toggle auto-fill" auto-fill-mode :selected auto-fill-function |
479 ["Join Line" fortran-join-line t] | 596 :style toggle] |
480 ["Fill Statement/Comment" fill-paragraph t] | 597 ["Toggle abbrev-mode" abbrev-mode :selected abbrev-mode |
481 "----" | 598 :style toggle] |
482 ["Add imenu menu" | 599 ["Add imenu Menu" imenu-add-menubar-index |
483 imenu-add-menubar-index (not (and (boundp 'imenu--index-alist) | 600 :active (not (lookup-key (current-local-map) [menu-bar index])) |
484 imenu--index-alist))])) | 601 :included (fboundp 'imenu-add-to-menubar)])) |
485 map) | 602 map) |
486 "Keymap used in Fortran mode.") | 603 "Keymap used in Fortran mode.") |
604 | |
487 | 605 |
488 (defvar fortran-mode-abbrev-table | 606 (defvar fortran-mode-abbrev-table |
489 (let (abbrevs-changed) | 607 (let (abbrevs-changed) |
490 (define-abbrev-table 'fortran-mode-abbrev-table nil) | 608 (define-abbrev-table 'fortran-mode-abbrev-table nil) |
491 ;; Use the 6th arg (SYSTEM-FLAG) of define-abbrev if possible. | 609 ;; Use the 6th arg (SYSTEM-FLAG) of define-abbrev if possible. |
555 (";ty" "type" ) | 673 (";ty" "type" ) |
556 (";vo" "volatile" ) | 674 (";vo" "volatile" ) |
557 (";w" "write" ) | 675 (";w" "write" ) |
558 (";wh" "where" ))) | 676 (";wh" "where" ))) |
559 fortran-mode-abbrev-table)) | 677 fortran-mode-abbrev-table)) |
678 | |
560 | 679 |
561 (eval-when-compile ; silence compiler | |
562 (defvar imenu-case-fold-search) | |
563 (defvar imenu-syntax-alist)) | |
564 | |
565 (defcustom fortran-mode-hook nil | |
566 "Hook run by Fortran mode." | |
567 :type 'hook | |
568 :group 'fortran) | |
569 | 680 |
570 ;;;###autoload | 681 ;;;###autoload |
571 (defun fortran-mode () | 682 (defun fortran-mode () |
572 "Major mode for editing Fortran code. | 683 "Major mode for editing Fortran code in fixed format. |
684 For free format code, use `f90-mode'. | |
685 | |
573 \\[fortran-indent-line] indents the current Fortran line correctly. | 686 \\[fortran-indent-line] indents the current Fortran line correctly. |
574 DO statements must not share a common CONTINUE. | 687 Note that DO statements must not share a common CONTINUE. |
575 | 688 |
576 Type ;? or ;\\[help-command] to display a list of built-in abbrevs for | 689 Type ;? or ;\\[help-command] to display a list of built-in abbrevs for\ |
577 Fortran keywords. | 690 Fortran keywords. |
578 | 691 |
579 Key definitions: | 692 Key definitions: |
580 \\{fortran-mode-map} | 693 \\{fortran-mode-map} |
581 | 694 |
582 Variables controlling indentation style and extra features: | 695 Variables controlling indentation style and extra features: |
583 | 696 |
584 `comment-start' | 697 `fortran-comment-line-start' |
585 If you want to use comments starting with `!', | 698 To use comments starting with `!', set this to the string \"!\". |
586 set this to the string \"!\". | 699 `fortran-do-indent' |
587 `fortran-do-indent' | 700 Extra indentation within DO blocks (default 3). |
588 Extra indentation within do blocks. (default 3) | 701 `fortran-if-indent' |
589 `fortran-if-indent' | 702 Extra indentation within IF blocks (default 3). |
590 Extra indentation within if blocks. (default 3) | 703 `fortran-structure-indent' |
591 `fortran-structure-indent' | 704 Extra indentation within STRUCTURE, UNION, MAP and INTERFACE blocks. |
592 Extra indentation within structure, union, map and interface blocks. | 705 (default 3) |
593 (default 3) | 706 `fortran-continuation-indent' |
594 `fortran-continuation-indent' | 707 Extra indentation applied to continuation statements (default 5). |
595 Extra indentation applied to continuation statements. (default 5) | 708 `fortran-comment-line-extra-indent' |
596 `fortran-comment-line-extra-indent' | 709 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) | 710 `fortran-comment-indent-style' |
598 `fortran-comment-indent-style' | 711 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, | 712 nil don't change the indentation |
600 fixed means indent that text at `fortran-comment-line-extra-indent' beyond | 713 fixed indent to `fortran-comment-line-extra-indent' beyond the |
601 the value of `fortran-minimum-statement-indent-fixed' (for fixed | 714 value of either |
602 format continuation style) or `fortran-minimum-statement-indent-tab' | 715 `fortran-minimum-statement-indent-fixed' (fixed format) or |
603 (for TAB format continuation style). | 716 `fortran-minimum-statement-indent-tab' (TAB format), |
604 relative means indent at `fortran-comment-line-extra-indent' beyond the | 717 depending on the continuation format in use. |
718 relative indent to `fortran-comment-line-extra-indent' beyond the | |
605 indentation for a line of code. | 719 indentation for a line of code. |
606 (default 'fixed) | 720 (default 'fixed) |
607 `fortran-comment-indent-char' | 721 `fortran-comment-indent-char' |
608 Single-character string to be inserted instead of space for | 722 Single-character string to be inserted instead of space for |
609 full-line comment indentation. (default \" \") | 723 full-line comment indentation (default \" \"). |
610 `fortran-minimum-statement-indent-fixed' | 724 `fortran-minimum-statement-indent-fixed' |
611 Minimum indentation for Fortran statements in fixed format mode. (def.6) | 725 Minimum indentation for statements in fixed format mode (default 6). |
612 `fortran-minimum-statement-indent-tab' | 726 `fortran-minimum-statement-indent-tab' |
613 Minimum indentation for Fortran statements in TAB format mode. (default 9) | 727 Minimum indentation for statements in TAB format mode (default 9). |
614 `fortran-line-number-indent' | 728 `fortran-line-number-indent' |
615 Maximum indentation for line numbers. A line number will get | 729 Maximum indentation for line numbers (default 1). A line number will |
616 less than this much indentation if necessary to avoid reaching | 730 get less than this much indentation if necessary to avoid reaching |
617 column 5. (default 1) | 731 column 5. |
618 `fortran-check-all-num-for-matching-do' | 732 `fortran-check-all-num-for-matching-do' |
619 Non-nil causes all numbered lines to be treated as possible \"continue\" | 733 Non-nil causes all numbered lines to be treated as possible \"continue\" |
620 statements. (default nil) | 734 statements (default nil). |
621 `fortran-blink-matching-if' | 735 `fortran-blink-matching-if' |
622 Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on | 736 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] | 737 to blink on the matching IF (or DO [WHILE]). (default nil) |
624 statement. (default nil) | 738 `fortran-continuation-string' |
625 `fortran-continuation-string' | 739 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 | 740 line (default \"$\"). |
627 line. (default \"$\") | 741 `fortran-comment-region' |
628 `fortran-comment-region' | 742 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 | 743 the region (default \"c$$$\"). |
630 region. (default \"c$$$\") | 744 `fortran-electric-line-number' |
631 `fortran-electric-line-number' | 745 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 | 746 as typed (default t). |
633 as typed. (default t) | 747 `fortran-break-before-delimiters' |
634 `fortran-break-before-delimiters' | 748 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 | 749 |
638 Turning on Fortran mode calls the value of the variable `fortran-mode-hook' | 750 Turning on Fortran mode calls the value of the variable `fortran-mode-hook' |
639 with no args, if that value is non-nil." | 751 with no args, if that value is non-nil." |
640 (interactive) | 752 (interactive) |
641 (kill-all-local-variables) | 753 (kill-all-local-variables) |
642 (setq local-abbrev-table fortran-mode-abbrev-table) | 754 (setq major-mode 'fortran-mode |
755 mode-name "Fortran" | |
756 local-abbrev-table fortran-mode-abbrev-table) | |
643 (set-syntax-table fortran-mode-syntax-table) | 757 (set-syntax-table fortran-mode-syntax-table) |
644 ;; Font Lock mode support. | 758 (use-local-map fortran-mode-map) |
645 (make-local-variable 'font-lock-defaults) | 759 (set (make-local-variable 'indent-line-function) 'fortran-indent-line) |
646 (setq font-lock-defaults '((fortran-font-lock-keywords | 760 (set (make-local-variable 'indent-region-function) |
647 fortran-font-lock-keywords-1 | 761 (lambda (start end) |
648 fortran-font-lock-keywords-2 | 762 (let (fortran-blink-matching-if ; avoid blinking delay |
649 fortran-font-lock-keywords-3) | 763 indent-region-function) |
650 nil t ((?/ . "$/") ("_$" . "w")) | 764 (indent-region start end nil)))) |
651 fortran-beginning-of-subprogram)) | 765 (set (make-local-variable 'require-final-newline) mode-require-final-newline) |
652 (set (make-local-variable 'font-lock-syntactic-keywords) | 766 ;; The syntax tables don't understand the column-0 comment-markers. |
653 fortran-font-lock-syntactic-keywords) | 767 (set (make-local-variable 'comment-use-syntax) nil) |
654 (make-local-variable 'fortran-break-before-delimiters) | 768 (set (make-local-variable 'comment-padding) "$$$") |
655 (setq fortran-break-before-delimiters t) | 769 (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) | 770 (set (make-local-variable 'comment-start-skip) |
661 ;; We can't reuse `fortran-comment-line-start-skip' directly because | 771 ;; We can't reuse `fortran-comment-line-start-skip' directly because |
662 ;; it contains backrefs whereas we need submatch-1 to end at the | 772 ;; it contains backrefs whereas we need submatch-1 to end at the |
663 ;; beginning of the comment delimiter. | 773 ;; beginning of the comment delimiter. |
664 ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)") | 774 ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)") |
665 "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*") | 775 "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*") |
666 (set (make-local-variable 'comment-padding) "$$$") | 776 (set (make-local-variable 'comment-indent-function) 'fortran-comment-indent) |
667 (set (make-local-variable 'comment-start) fortran-comment-line-start) | 777 (set (make-local-variable 'abbrev-all-caps) t) |
668 ;; The syntax tables don't understand the column-0 comment-markers. | 778 (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill) |
669 (set (make-local-variable 'comment-use-syntax) nil) | 779 (set (make-local-variable 'indent-tabs-mode) (fortran-analyze-file-format)) |
670 (make-local-variable 'require-final-newline) | 780 (setq mode-line-process '(indent-tabs-mode fortran-tab-mode-string)) |
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) | 781 (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) | 782 (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph) |
692 (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill) | 783 (set (make-local-variable 'font-lock-defaults) |
693 (set (make-local-variable 'indent-line-function) 'fortran-indent-line) | 784 '((fortran-font-lock-keywords |
694 (set (make-local-variable 'indent-region-function) | 785 fortran-font-lock-keywords-1 |
695 (lambda (start end) | 786 fortran-font-lock-keywords-2 |
696 (let (fortran-blink-matching-if ; avoid blinking delay | 787 fortran-font-lock-keywords-3 |
697 indent-region-function) | 788 fortran-font-lock-keywords-4) |
698 (indent-region start end nil)))) | 789 nil t ((?/ . "$/") ("_$" . "w")) |
790 fortran-beginning-of-subprogram)) | |
791 (set (make-local-variable 'font-lock-syntactic-keywords) | |
792 fortran-font-lock-syntactic-keywords) | |
793 (set (make-local-variable 'imenu-case-fold-search) t) | |
794 (set (make-local-variable 'imenu-generic-expression) | |
795 fortran-imenu-generic-expression) | |
796 (set (make-local-variable 'imenu-syntax-alist) '(("_$" . "w"))) | |
699 (set (make-local-variable 'beginning-of-defun-function) | 797 (set (make-local-variable 'beginning-of-defun-function) |
700 #'fortran-beginning-of-subprogram) | 798 #'fortran-beginning-of-subprogram) |
701 (set (make-local-variable 'end-of-defun-function) | 799 (set (make-local-variable 'end-of-defun-function) |
702 #'fortran-end-of-subprogram) | 800 #'fortran-end-of-subprogram) |
703 (set (make-local-variable 'add-log-current-defun-function) | 801 (set (make-local-variable 'add-log-current-defun-function) |
704 #'fortran-current-defun) | 802 #'fortran-current-defun) |
705 (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search) | 803 (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search) |
706 (run-hooks 'fortran-mode-hook)) | 804 (set (make-local-variable 'gud-find-expr-function) 'fortran-gud-find-expr) |
805 (run-mode-hooks 'fortran-mode-hook)) | |
806 | |
707 | 807 |
808 (defun fortran-gud-find-expr () | |
809 ;; Consider \n as punctuation (end of expression). | |
810 (with-syntax-table fortran-gud-syntax-table | |
811 (gud-find-c-expr))) | |
812 | |
708 (defsubst fortran-comment-indent () | 813 (defsubst fortran-comment-indent () |
709 (save-excursion | 814 "Return the indentation appropriate for the current comment line. |
710 (if (looking-at fortran-comment-line-start-skip) 0 | 815 This is 0 for a line matching `fortran-comment-line-start-skip', else |
816 the value of `comment-column' (leaving at least one space after code)." | |
817 (if (looking-at fortran-comment-line-start-skip) 0 | |
818 (save-excursion | |
711 (skip-chars-backward " \t") | 819 (skip-chars-backward " \t") |
712 (max (+ 1 (current-column)) | 820 (max (1+ (current-column)) comment-column)))) |
713 comment-column)))) | |
714 | 821 |
715 (defun fortran-indent-comment () | 822 (defun fortran-indent-comment () |
716 "Align or create comment on current line. | 823 "Align or create comment on current line. |
717 Existing comments of all types are recognized and aligned. | 824 Existing comments of all types are recognized and aligned. |
718 If the line has no comment, a side-by-side comment is inserted and aligned | 825 If the line has no comment, a side-by-side comment is inserted and aligned, |
719 if the value of `comment-start' is not nil and allows such comments. | 826 if the value of `comment-start' is not nil and allows such comments. |
720 Otherwise, a separate-line comment is inserted, on this line | 827 Otherwise, a separate-line comment is inserted, on this line |
721 or on a new line inserted before this line if this line is not blank." | 828 or on a new line inserted before this line if this line is not blank." |
722 (interactive) | 829 (interactive "*") |
723 (beginning-of-line) | 830 (beginning-of-line) |
724 ;; Recognize existing comments of either kind. | 831 ;; Recognize existing comments of either kind. |
725 (cond ((fortran-find-comment-start-skip 'all) | 832 (cond ((fortran-find-comment-start-skip 'all) |
726 (goto-char (match-beginning 0)) | 833 (goto-char (match-beginning 0)) |
727 (if (bolp) | 834 (if (bolp) |
728 (fortran-indent-line) | 835 (fortran-indent-line) |
729 (if (not (= (current-column) | 836 (unless (= (current-column) (fortran-comment-indent)) |
730 (fortran-comment-indent))) | 837 (delete-horizontal-space) |
731 (progn (delete-horizontal-space) | 838 (indent-to (fortran-comment-indent))))) |
732 (indent-to (fortran-comment-indent)))))) | |
733 ;; No existing comment. | 839 ;; No existing comment. |
734 ;; If side-by-side comments are defined, insert one, | 840 ;; If side-by-side comments are defined, insert one, |
735 ;; unless line is now blank. | 841 ;; unless line is now blank. |
736 ((and comment-start (not (looking-at "[ \t]*$")) | 842 ((and comment-start (not (looking-at "[ \t]*$")) |
737 (string-match comment-start-skip (concat " " comment-start))) | 843 (string-match comment-start-skip (concat " " comment-start))) |
751 (aref fortran-comment-indent-char 0) | 857 (aref fortran-comment-indent-char 0) |
752 fortran-comment-indent-char) | 858 fortran-comment-indent-char) |
753 (- (fortran-calculate-indent) (current-column)))))) | 859 (- (fortran-calculate-indent) (current-column)))))) |
754 | 860 |
755 (defun fortran-comment-region (beg-region end-region arg) | 861 (defun fortran-comment-region (beg-region end-region arg) |
756 "Comments every line in the region. | 862 "Comment every line in the region. |
757 Puts `fortran-comment-region' at the beginning of every line in the region. | 863 Inserts the string variable `fortran-comment-region' at the beginning of |
758 BEG-REGION and END-REGION are args which specify the region boundaries. | 864 every line in the region. |
865 BEG-REGION and END-REGION specify the region boundaries. | |
759 With non-nil ARG, uncomments the region." | 866 With non-nil ARG, uncomments the region." |
760 (interactive "*r\nP") | 867 (interactive "*r\nP") |
761 (let ((end-region-mark (copy-marker end-region)) | 868 (let ((end-region-mark (copy-marker end-region)) |
762 (save-point (point-marker))) | 869 (save-point (point-marker))) |
763 (goto-char beg-region) | 870 (goto-char beg-region) |
764 (beginning-of-line) | 871 (beginning-of-line) |
765 (if (not arg) ;comment the region | 872 (if arg |
766 (progn (insert fortran-comment-region) | 873 (let ((com (regexp-quote fortran-comment-region))) ; uncomment |
767 (while (and (= (forward-line 1) 0) | 874 (if (looking-at com) |
768 (< (point) end-region-mark)) | 875 (delete-region (point) (match-end 0))) |
769 (insert fortran-comment-region))) | 876 (while (and (zerop (forward-line 1)) |
770 (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region | 877 (< (point) end-region-mark)) |
771 (if (looking-at com) | 878 (if (looking-at com) |
772 (delete-region (point) (match-end 0))) | 879 (delete-region (point) (match-end 0))))) |
773 (while (and (= (forward-line 1) 0) | 880 (insert fortran-comment-region) ; comment |
774 (< (point) end-region-mark)) | 881 (while (and (zerop (forward-line 1)) |
775 (if (looking-at com) | 882 (< (point) end-region-mark)) |
776 (delete-region (point) (match-end 0)))))) | 883 (insert fortran-comment-region))) |
777 (goto-char save-point) | 884 (goto-char save-point) |
778 (set-marker end-region-mark nil) | 885 (set-marker end-region-mark nil) |
779 (set-marker save-point nil))) | 886 (set-marker save-point nil))) |
887 | |
780 | 888 |
781 (defun fortran-abbrev-start () | 889 (defun fortran-abbrev-start () |
782 "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. | 890 "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. |
783 Any other key combination is executed normally." | 891 Any other key combination is executed normally." |
784 (interactive) | 892 (interactive "*") |
785 (let (c) | 893 (insert last-command-char) |
786 (insert last-command-char) | 894 (let (char event) |
787 (if (or (eq (setq c (read-event)) ??) ;insert char if not equal to `?' | 895 (if (fboundp 'next-command-event) ; XEmacs |
788 (eq c help-char)) | 896 (setq event (next-command-event) |
897 char (event-to-character event)) | |
898 (setq event (read-event) | |
899 char event)) | |
900 ;; Insert char if not equal to `?', or if abbrev-mode is off. | |
901 (if (and abbrev-mode (or (eq char ??) (eq char help-char))) | |
789 (fortran-abbrev-help) | 902 (fortran-abbrev-help) |
790 (setq unread-command-events (list c))))) | 903 (setq unread-command-events (list event))))) |
791 | 904 |
792 (defun fortran-abbrev-help () | 905 (defun fortran-abbrev-help () |
793 "List the currently defined abbrevs in Fortran mode." | 906 "List the currently defined abbrevs in Fortran mode." |
794 (interactive) | 907 (interactive) |
795 (message "Listing abbrev table...") | 908 (message "Listing abbrev table...") |
796 (display-buffer (fortran-prepare-abbrev-list-buffer)) | 909 (display-buffer (fortran-prepare-abbrev-list-buffer)) |
797 (message "Listing abbrev table...done")) | 910 (message "Listing abbrev table...done")) |
798 | 911 |
799 (defun fortran-prepare-abbrev-list-buffer () | 912 (defun fortran-prepare-abbrev-list-buffer () |
913 "Create a buffer listing the Fortran mode abbreviations." | |
800 (save-excursion | 914 (save-excursion |
801 (set-buffer (get-buffer-create "*Abbrevs*")) | 915 (set-buffer (get-buffer-create "*Abbrevs*")) |
802 (erase-buffer) | 916 (erase-buffer) |
803 (insert-abbrev-table-description 'fortran-mode-abbrev-table t) | 917 (insert-abbrev-table-description 'fortran-mode-abbrev-table t) |
804 (goto-char (point-min)) | 918 (goto-char (point-min)) |
806 (edit-abbrevs-mode)) | 920 (edit-abbrevs-mode)) |
807 (get-buffer-create "*Abbrevs*")) | 921 (get-buffer-create "*Abbrevs*")) |
808 | 922 |
809 (defun fortran-column-ruler () | 923 (defun fortran-column-ruler () |
810 "Insert a column ruler momentarily above current line, till next keystroke. | 924 "Insert a column ruler momentarily above current line, till next keystroke. |
811 The ruler is defined by the value of `fortran-column-ruler-fixed' when in fixed | 925 The ruler is defined by the value of `fortran-column-ruler-fixed' in fixed |
812 format mode, and `fortran-column-ruler-tab' when in TAB format mode. | 926 format mode, and `fortran-column-ruler-tab' in TAB format mode. |
813 The key typed is executed unless it is SPC." | 927 The next key typed is executed unless it is SPC." |
814 (interactive) | 928 (interactive) |
815 (momentary-string-display | 929 (momentary-string-display |
816 (if indent-tabs-mode | 930 (if indent-tabs-mode |
817 fortran-column-ruler-tab | 931 fortran-column-ruler-tab |
818 fortran-column-ruler-fixed) | 932 fortran-column-ruler-fixed) |
859 (setq unread-command-events (list char)))))) | 973 (setq unread-command-events (list char)))))) |
860 (fortran-window-create))) | 974 (fortran-window-create))) |
861 | 975 |
862 (defun fortran-split-line () | 976 (defun fortran-split-line () |
863 "Break line at point and insert continuation marker and alignment." | 977 "Break line at point and insert continuation marker and alignment." |
864 (interactive) | 978 (interactive "*") |
865 (delete-horizontal-space) | 979 (delete-horizontal-space) |
866 (if (save-excursion | 980 (if (save-excursion |
867 (let ((pos (point))) | 981 (let ((pos (point))) |
868 (beginning-of-line) | 982 (beginning-of-line) |
869 (and (fortran-find-comment-start-skip 'all) | 983 (and (fortran-find-comment-start-skip 'all) |
870 (< (match-beginning 0) pos)))) | 984 (< (match-beginning 0) pos)))) |
871 (insert ?\n (match-string 0)) | 985 (insert ?\n (match-string 0)) |
872 (if indent-tabs-mode | 986 (if indent-tabs-mode |
873 (insert ?\n ?\t (fortran-numerical-continuation-char)) | 987 (insert ?\n ?\t (fortran-numerical-continuation-char)) |
874 (insert "\n " fortran-continuation-string))) ; Space after \n important | 988 (insert "\n " fortran-continuation-string))) ; space after \n important |
875 (fortran-indent-line)) ; when the cont string is C, c or *. | 989 (fortran-indent-line)) ; when cont string is C, c or * |
876 | 990 |
877 (defun fortran-remove-continuation () | 991 (defun fortran-remove-continuation () |
878 (if (looking-at "\\( [^ 0\n]\\|\t[1-9]\\|&\\)") | 992 "Delete any Fortran continuation characters at point. |
879 (progn (replace-match "") | 993 Returns t if anything actually deleted." |
880 (delete-indentation) | 994 (when (looking-at "\\( \\{5\\}[^ 0\n]\\|\t[1-9]\\|&\\)") |
881 t))) | 995 (replace-match "") |
996 (delete-indentation) | |
997 t)) | |
882 | 998 |
883 (defun fortran-join-line (arg) | 999 (defun fortran-join-line (arg) |
884 "Join current line to the previous one and re-indent. | 1000 "Join current line to the previous one and re-indent. |
885 With a prefix argument, repeat this operation that many times. | 1001 With a prefix argument, repeat this operation that many times. |
886 If the prefix argument ARG is negative, join the next -ARG lines. | 1002 If the prefix argument ARG is negative, join the next -ARG lines. |
897 (setq arg (1- arg))) | 1013 (setq arg (1- arg))) |
898 (fortran-indent-line))) | 1014 (fortran-indent-line))) |
899 | 1015 |
900 (defun fortran-numerical-continuation-char () | 1016 (defun fortran-numerical-continuation-char () |
901 "Return a digit for tab-digit style of continuation lines. | 1017 "Return a digit for tab-digit style of continuation lines. |
902 If, previous line is a tab-digit continuation line, returns that digit | 1018 If previous line is a tab-digit continuation line, return that digit |
903 plus one. Otherwise return 1. Zero not allowed." | 1019 plus one, otherwise return 1. Zero not allowed." |
904 (save-excursion | 1020 (save-excursion |
905 (forward-line -1) | 1021 (forward-line -1) |
906 (if (looking-at "\t[1-9]") | 1022 (if (looking-at "\t[1-9]") |
907 (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9)) | 1023 (+ ?1 (% (- (char-after (1+ (point))) ?0) 9)) |
908 ?1))) | 1024 ?1))) |
909 | 1025 |
910 (put 'fortran-electric-line-number 'delete-selection t) | 1026 (put 'fortran-electric-line-number 'delete-selection t) |
911 (defun fortran-electric-line-number (arg) | 1027 (defun fortran-electric-line-number (arg) |
912 "Self insert, but if part of a Fortran line number indent it automatically. | 1028 "Self insert, but if part of a Fortran line number indent it automatically. |
913 Auto-indent does not happen if a numeric ARG is used." | 1029 Auto-indent does not happen if a numeric ARG is used." |
914 (interactive "P") | 1030 (interactive "*P") |
915 (if (or arg (not fortran-electric-line-number)) | 1031 (if (or arg (not fortran-electric-line-number)) |
916 (if arg | 1032 (if arg |
917 (self-insert-command (prefix-numeric-value arg)) | 1033 (self-insert-command (prefix-numeric-value arg)) |
918 (self-insert-command 1)) | 1034 (self-insert-command 1)) |
919 (if (or (and (= 5 (current-column)) | 1035 (if (or (and (= 5 (current-column)) |
920 (save-excursion | 1036 (save-excursion |
921 (beginning-of-line) | 1037 (beginning-of-line) |
922 (looking-at " \\{5\\}"))) ;In col 5 with only spaces to left. | 1038 ;; In col 5 with only spaces to the left. |
1039 (looking-at " \\{5\\}"))) | |
923 (and (= (if indent-tabs-mode | 1040 (and (= (if indent-tabs-mode |
924 fortran-minimum-statement-indent-tab | 1041 fortran-minimum-statement-indent-tab |
925 fortran-minimum-statement-indent-fixed) (current-column)) | 1042 fortran-minimum-statement-indent-fixed) (current-column)) |
926 (eq ?\t (char-after (line-beginning-position))) ;In col 8 | 1043 ;; In col 8 with a single tab to the left. |
927 ; with a single tab to the left. | 1044 (eq ?\t (char-after (line-beginning-position))) |
928 (not (or (eq last-command 'fortran-indent-line) | 1045 (not (or (eq last-command 'fortran-indent-line) |
929 (eq last-command | 1046 (eq last-command |
930 'fortran-indent-new-line)))) | 1047 'fortran-indent-new-line)))) |
931 (save-excursion | 1048 (save-excursion |
932 (re-search-backward "[^ \t0-9]" | 1049 (re-search-backward "[^ \t0-9]" |
933 (line-beginning-position) | 1050 (line-beginning-position) |
934 t)) ;not a line number | 1051 t)) ; not a line number |
935 (looking-at "[0-9]")) ;within a line number | 1052 (looking-at "[0-9]")) ; within a line number |
936 (self-insert-command (prefix-numeric-value arg)) | 1053 (self-insert-command (prefix-numeric-value arg)) |
937 (skip-chars-backward " \t") | 1054 (skip-chars-backward " \t") |
938 (insert last-command-char) | 1055 (insert last-command-char) |
939 (fortran-indent-line)))) | 1056 (fortran-indent-line)))) |
1057 | |
940 | 1058 |
941 (defvar fortran-end-prog-re1 | |
942 "end\ | |
943 \\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\ | |
944 \\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?") | |
945 (defvar fortran-end-prog-re | |
946 (concat "^[ \t0-9]*" fortran-end-prog-re1) | |
947 "Regexp possibly marking subprogram end.") | |
948 | |
949 (defun fortran-check-end-prog-re () | 1059 (defun fortran-check-end-prog-re () |
950 "Check a preliminary match against `fortran-end-prog-re'." | 1060 "Check a preliminary match against `fortran-end-prog-re'." |
951 ;; Having got a possible match for the subprogram end, we need a | 1061 ;; Having got a possible match for the subprogram end, we need a |
952 ;; match of whitespace, avoiding possible column 73+ stuff. | 1062 ;; match of whitespace, avoiding possible column 73+ stuff. |
953 (save-match-data | 1063 (save-match-data |
1002 (not (looking-at fortran-directive-re)) | 1112 (not (looking-at fortran-directive-re)) |
1003 (or (looking-at | 1113 (or (looking-at |
1004 (concat "[ \t]*" | 1114 (concat "[ \t]*" |
1005 (regexp-quote fortran-continuation-string))) | 1115 (regexp-quote fortran-continuation-string))) |
1006 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")))) | 1116 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")))) |
1007 (while (and (setq not-first-statement (= (forward-line -1) 0)) | 1117 (while (and (setq not-first-statement (zerop (forward-line -1))) |
1008 (or (looking-at fortran-comment-line-start-skip) | 1118 (or (looking-at fortran-comment-line-start-skip) |
1009 (looking-at fortran-directive-re) | 1119 (looking-at fortran-directive-re) |
1120 (looking-at | |
1121 (concat "[ \t]*" | |
1122 (regexp-quote fortran-continuation-string))) | |
1010 (looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]") | 1123 (looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]") |
1011 (looking-at (concat "[ \t]*" comment-start-skip))))) | 1124 (looking-at (concat "[ \t]*" comment-start-skip))))) |
1012 (cond ((and continue-test | 1125 (cond ((and continue-test |
1013 (not not-first-statement)) | 1126 (not not-first-statement)) |
1014 (message "Incomplete continuation statement.")) | 1127 (message "Incomplete continuation statement.")) |
1024 Directive lines are treated as comments." | 1137 Directive lines are treated as comments." |
1025 (interactive) | 1138 (interactive) |
1026 (let (not-last-statement) | 1139 (let (not-last-statement) |
1027 (beginning-of-line) | 1140 (beginning-of-line) |
1028 (while (and (setq not-last-statement | 1141 (while (and (setq not-last-statement |
1029 (and (= (forward-line 1) 0) | 1142 (and (zerop (forward-line 1)) |
1030 (not (eobp)))) | 1143 (not (eobp)))) |
1031 (or (looking-at fortran-comment-line-start-skip) | 1144 (or (looking-at fortran-comment-line-start-skip) |
1032 (looking-at fortran-directive-re) | 1145 (looking-at fortran-directive-re) |
1033 (looking-at "[ \t]*$\\| [^ 0\n]\\|\t[1-9]") | 1146 (looking-at "[ \t]*$\\| [^ 0\n]\\|\t[1-9]") |
1034 (looking-at (concat "[ \t]*" comment-start-skip))))) | 1147 (looking-at (concat "[ \t]*" comment-start-skip))))) |
1035 (if (not not-last-statement) | 1148 (if (not not-last-statement) |
1036 'last-statement))) | 1149 'last-statement))) |
1150 | |
1151 (defun fortran-looking-at-if-then () | |
1152 "Return non-nil if at the start of a line with an IF ... THEN statement." | |
1153 ;; cf f90-looking-at-if-then. | |
1154 (let ((p (point)) | |
1155 (i (fortran-beginning-if))) | |
1156 (if i | |
1157 (save-excursion | |
1158 (goto-char i) | |
1159 (beginning-of-line) | |
1160 (= (point) p))))) | |
1161 | |
1162 ;; Used in hs-special-modes-alist. | |
1163 (defun fortran-end-of-block (&optional num) | |
1164 "Move point forward to the end of the current code block. | |
1165 With optional argument NUM, go forward that many balanced blocks. | |
1166 If NUM is negative, go backward to the start of a block. Does | |
1167 not check for consistency of block types. Interactively, pushes | |
1168 mark before moving point." | |
1169 (interactive "p") | |
1170 (if (interactive-p) (push-mark (point) t)) | |
1171 (and num (< num 0) (fortran-beginning-of-block (- num))) | |
1172 (let ((case-fold-search t) | |
1173 (count (or num 1))) | |
1174 (end-of-line) | |
1175 (while (and (> count 0) | |
1176 (re-search-forward | |
1177 (concat "\\(" fortran-blocks-re | |
1178 (if fortran-check-all-num-for-matching-do | |
1179 "\\|^[ \t]*[0-9]+" "") | |
1180 "\\|continue\\|end\\)\\>") | |
1181 nil 'move)) | |
1182 (beginning-of-line) | |
1183 (if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re)) | |
1184 (fortran-looking-at-if-then) | |
1185 (looking-at fortran-start-block-re)) | |
1186 (setq count (1+ count)) | |
1187 (if (or (looking-at fortran-end-block-re) | |
1188 (and (or (looking-at "^[0-9 \t]*continue") | |
1189 (and fortran-check-all-num-for-matching-do | |
1190 (looking-at "[ \t]*[0-9]+"))) | |
1191 (fortran-check-for-matching-do))) | |
1192 (setq count (1- count)))) | |
1193 (end-of-line)) | |
1194 (if (> count 0) (error "Missing block end")))) | |
1195 | |
1196 (defun fortran-beginning-of-block (&optional num) | |
1197 "Move point backwards to the start of the current code block. | |
1198 With optional argument NUM, go backward that many balanced | |
1199 blocks. If NUM is negative, go forward to the end of a block. | |
1200 Does not check for consistency of block types. Interactively, | |
1201 pushes mark before moving point." | |
1202 (interactive "p") | |
1203 (if (interactive-p) (push-mark (point) t)) | |
1204 (and num (< num 0) (fortran-end-of-block (- num))) | |
1205 (let ((case-fold-search t) | |
1206 (count (or num 1))) | |
1207 (beginning-of-line) | |
1208 (while (and (> count 0) | |
1209 (re-search-backward | |
1210 (concat "\\(" fortran-blocks-re | |
1211 (if fortran-check-all-num-for-matching-do | |
1212 "\\|^[ \t]*[0-9]+" "") | |
1213 "\\|continue\\|end\\)\\>") | |
1214 nil 'move)) | |
1215 (beginning-of-line) | |
1216 (if (if (looking-at (concat "^[0-9 \t]*" fortran-if-start-re)) | |
1217 (fortran-looking-at-if-then) | |
1218 (looking-at fortran-start-block-re)) | |
1219 (setq count (1- count)) | |
1220 (if (or (looking-at fortran-end-block-re) | |
1221 (and (or (looking-at "^[0-9 \t]*continue") | |
1222 (and fortran-check-all-num-for-matching-do | |
1223 (looking-at "[ \t]*[0-9]+"))) | |
1224 (fortran-check-for-matching-do))) | |
1225 (setq count (1+ count))))) | |
1226 ;; Includes an un-named main program block. | |
1227 (if (> count 0) (error "Missing block start")))) | |
1228 | |
1037 | 1229 |
1038 (defun fortran-blink-match (regex keyword find-begin) | 1230 (defun fortran-blink-match (regex keyword find-begin) |
1039 "From a line matching REGEX, blink matching KEYWORD statement line. | 1231 "From a line matching REGEX, blink matching KEYWORD statement line. |
1040 Use function FIND-BEGIN to match it." | 1232 Use function FIND-BEGIN to match it." |
1041 (let ((top-of-window (window-start)) | 1233 (let ((top-of-window (window-start)) |
1042 (end-point (point)) | 1234 (end-point (point)) |
1043 (case-fold-search t) | 1235 (case-fold-search t) |
1044 matching | 1236 matching |
1045 message) | 1237 message) |
1046 (if (save-excursion | 1238 (when (save-excursion |
1047 (beginning-of-line) | 1239 (beginning-of-line) |
1048 (skip-chars-forward " \t0-9") | 1240 (skip-chars-forward " \t0-9") |
1049 (looking-at regex)) | 1241 (looking-at regex)) |
1050 (progn | 1242 (if (not (setq matching (funcall find-begin))) |
1051 (if (not (setq matching (funcall find-begin))) | 1243 (setq message (concat "No matching " keyword ".")) |
1052 (setq message (concat "No matching " keyword ".")) | 1244 (if (< matching top-of-window) |
1053 (if (< matching top-of-window) | 1245 (save-excursion |
1054 (save-excursion | 1246 (goto-char matching) |
1055 (goto-char matching) | 1247 (beginning-of-line) |
1056 (beginning-of-line) | 1248 (setq message |
1057 (setq message | 1249 (concat "Matches " |
1058 (concat "Matches " | 1250 (buffer-substring (point) |
1059 (buffer-substring (point) | 1251 (line-end-position))))))) |
1060 (line-end-position))))))) | 1252 (if message |
1061 (if message | 1253 (message "%s" message) |
1062 (message "%s" message) | 1254 (goto-char matching) |
1063 (goto-char matching) | 1255 (sit-for blink-matching-delay) |
1064 (sit-for 1) | 1256 (goto-char end-point))))) |
1065 (goto-char end-point)))))) | |
1066 | 1257 |
1067 (defun fortran-blink-matching-if () | 1258 (defun fortran-blink-matching-if () |
1068 "From an ENDIF or ELSE statement, blink the matching IF statement." | 1259 "From an ENDIF or ELSE statement, blink the matching IF statement." |
1069 (fortran-blink-match "e\\(nd[ \t]*if\\|lse\\([ \t]*if\\)?\\)\\b" | 1260 (fortran-blink-match "e\\(nd[ \t]*if\\|lse\\([ \t]*if\\)?\\)\\b" |
1070 "if" #'fortran-beginning-if)) | 1261 "if" #'fortran-beginning-if)) |
1095 ;; Sitting on one. | 1286 ;; Sitting on one. |
1096 (match-beginning 0) | 1287 (match-beginning 0) |
1097 ;; Search for one. | 1288 ;; Search for one. |
1098 (save-excursion | 1289 (save-excursion |
1099 (let ((count 1)) | 1290 (let ((count 1)) |
1100 (while (and (not (= count 0)) | 1291 (while (and (not (zerop count)) |
1101 (not (eq (fortran-next-statement) 'last-statement)) | 1292 (not (eq (fortran-next-statement) 'last-statement)) |
1102 ;; Keep local to subprogram | 1293 ;; Keep local to subprogram. |
1103 (not (and (looking-at fortran-end-prog-re) | 1294 (not (and (looking-at fortran-end-prog-re) |
1104 (fortran-check-end-prog-re)))) | 1295 (fortran-check-end-prog-re)))) |
1105 (skip-chars-forward " \t0-9") | 1296 (skip-chars-forward " \t0-9") |
1106 (cond ((looking-at "end[ \t]*do\\b") | 1297 (cond ((looking-at "end[ \t]*do\\b") |
1107 (setq count (1- count))) | 1298 (setq count (1- count))) |
1108 ((looking-at | 1299 ((looking-at |
1109 "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]") | 1300 "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]") |
1110 (setq count (+ count 1))))) | 1301 (setq count (1+ count))))) |
1111 (and (= count 0) | 1302 (and (zerop count) |
1112 ;; All pairs accounted for. | 1303 ;; All pairs accounted for. |
1113 (point))))))) | 1304 (point))))))) |
1114 | 1305 |
1115 (defun fortran-beginning-do () | 1306 (defun fortran-beginning-do () |
1116 "Search backwards for first unmatched DO [WHILE]. | 1307 "Search backwards for first unmatched DO [WHILE]. |
1124 ;; Sitting on one. | 1315 ;; Sitting on one. |
1125 (match-beginning 0) | 1316 (match-beginning 0) |
1126 ;; Search for one. | 1317 ;; Search for one. |
1127 (save-excursion | 1318 (save-excursion |
1128 (let ((count 1)) | 1319 (let ((count 1)) |
1129 (while (and (not (= count 0)) | 1320 (while (and (not (zerop count)) |
1130 (not (eq (fortran-previous-statement) 'first-statement)) | 1321 (not (eq (fortran-previous-statement) 'first-statement)) |
1131 ;; Keep local to subprogram | 1322 ;; Keep local to subprogram. |
1132 (not (and (looking-at fortran-end-prog-re) | 1323 (not (and (looking-at fortran-end-prog-re) |
1133 (fortran-check-end-prog-re)))) | 1324 (fortran-check-end-prog-re)))) |
1134 (skip-chars-forward " \t0-9") | 1325 (skip-chars-forward " \t0-9") |
1135 (cond ((looking-at dostart-re) | 1326 (cond ((looking-at dostart-re) |
1136 (setq count (1- count))) | 1327 (setq count (1- count))) |
1137 ;; Note labelled loop ends not considered. | 1328 ;; Note labelled loop ends not considered. |
1138 ((looking-at "end[ \t]*do\\b") | 1329 ((looking-at "end[ \t]*do\\b") |
1139 (setq count (1+ count))))) | 1330 (setq count (1+ count))))) |
1140 (and (= count 0) | 1331 (and (zerop count) |
1141 ;; All pairs accounted for. | 1332 ;; All pairs accounted for. |
1142 (point))))))) | 1333 (point))))))) |
1143 | 1334 |
1144 (defun fortran-mark-if () | 1335 (defun fortran-mark-if () |
1145 "Put mark at end of Fortran IF-ENDIF construct, point at beginning. | 1336 "Put mark at end of Fortran IF-ENDIF construct, point at beginning. |
1151 (message "No matching if.") | 1342 (message "No matching if.") |
1152 ;; Set mark, move point. | 1343 ;; Set mark, move point. |
1153 (goto-char endif-point) | 1344 (goto-char endif-point) |
1154 (push-mark) | 1345 (push-mark) |
1155 (goto-char if-point))))) | 1346 (goto-char if-point))))) |
1156 | |
1157 (defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") | |
1158 | 1347 |
1159 (defun fortran-end-if () | 1348 (defun fortran-end-if () |
1160 "Search forwards for first unmatched ENDIF. | 1349 "Search forwards for first unmatched ENDIF. |
1161 Return point or nil." | 1350 Return point or nil." |
1162 (let ((case-fold-search t)) | 1351 (let ((case-fold-search t)) |
1167 (match-beginning 0) | 1356 (match-beginning 0) |
1168 ;; Search for one. The point has been already been moved to first | 1357 ;; Search for one. The point has been already been moved to first |
1169 ;; letter on line but this should not cause troubles. | 1358 ;; letter on line but this should not cause troubles. |
1170 (save-excursion | 1359 (save-excursion |
1171 (let ((count 1)) | 1360 (let ((count 1)) |
1172 (while (and (not (= count 0)) | 1361 (while (and (not (zerop count)) |
1173 (not (eq (fortran-next-statement) 'last-statement)) | 1362 (not (eq (fortran-next-statement) 'last-statement)) |
1174 ;; Keep local to subprogram. | 1363 ;; Keep local to subprogram. |
1175 (not (and (looking-at fortran-end-prog-re) | 1364 (not (and (looking-at fortran-end-prog-re) |
1176 (fortran-check-end-prog-re)))) | 1365 (fortran-check-end-prog-re)))) |
1177 (skip-chars-forward " \t0-9") | 1366 (skip-chars-forward " \t0-9") |
1178 (cond ((looking-at "end[ \t]*if\\b") | 1367 (cond ((looking-at "end[ \t]*if\\b") |
1179 (setq count (- count 1))) | 1368 (setq count (1- count))) |
1180 ((looking-at fortran-if-start-re) | 1369 ((looking-at fortran-if-start-re) |
1181 (save-excursion | 1370 (save-excursion |
1182 (if (or | 1371 (if (or |
1183 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") | 1372 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
1184 (let (then-test) ; Multi-line if-then. | 1373 (let (then-test) ; multi-line if-then |
1185 (while | 1374 (while |
1186 (and | 1375 (and |
1187 (= (forward-line 1) 0) | 1376 (zerop (forward-line 1)) |
1188 ;; Search forward for then. | 1377 ;; Search forward for then. |
1189 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") | 1378 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1190 (not | 1379 (not |
1191 (setq then-test | 1380 (setq then-test |
1192 (looking-at | 1381 (looking-at |
1193 ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) | 1382 ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) |
1194 then-test)) | 1383 then-test)) |
1195 (setq count (+ count 1))))))) | 1384 (setq count (1+ count))))))) |
1196 (and (= count 0) | 1385 (and (zerop count) |
1197 ;; All pairs accounted for. | 1386 ;; All pairs accounted for. |
1198 (point))))))) | 1387 (point))))))) |
1199 | 1388 |
1200 (defun fortran-beginning-if () | 1389 (defun fortran-beginning-if () |
1201 "Search backwards for first unmatched IF-THEN. | 1390 "Search backwards for first unmatched IF-THEN. |
1215 (save-match-data | 1404 (save-match-data |
1216 (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") | 1405 (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
1217 ;; Multi-line if-then. | 1406 ;; Multi-line if-then. |
1218 (let (then-test) | 1407 (let (then-test) |
1219 (while | 1408 (while |
1220 (and (= (forward-line 1) 0) | 1409 (and (zerop (forward-line 1)) |
1221 ;; Search forward for then. | 1410 ;; Search forward for then. |
1222 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") | 1411 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1223 (not | 1412 (not |
1224 (setq then-test | 1413 (setq then-test |
1225 (looking-at | 1414 (looking-at |
1228 ;; Sitting on one. | 1417 ;; Sitting on one. |
1229 (match-beginning 0) | 1418 (match-beginning 0) |
1230 ;; Search for one. | 1419 ;; Search for one. |
1231 (save-excursion | 1420 (save-excursion |
1232 (let ((count 1)) | 1421 (let ((count 1)) |
1233 (while (and (not (= count 0)) | 1422 (while (and (not (zerop count)) |
1234 (not (eq (fortran-previous-statement) 'first-statement)) | 1423 (not (eq (fortran-previous-statement) 'first-statement)) |
1235 ;; Keep local to subprogram. | 1424 ;; Keep local to subprogram. |
1236 (not (and (looking-at fortran-end-prog-re) | 1425 (not (and (looking-at fortran-end-prog-re) |
1237 (fortran-check-end-prog-re)))) | 1426 (fortran-check-end-prog-re)))) |
1238 (skip-chars-forward " \t0-9") | 1427 (skip-chars-forward " \t0-9") |
1239 (cond ((looking-at fortran-if-start-re) | 1428 (cond ((looking-at fortran-if-start-re) |
1240 (save-excursion | 1429 (save-excursion |
1241 (if (or | 1430 (if (or |
1242 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") | 1431 (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
1243 (let (then-test) ; Multi-line if-then. | 1432 (let (then-test) ; multi-line if-then |
1244 (while | 1433 (while |
1245 (and | 1434 (and |
1246 (= (forward-line 1) 0) | 1435 (zerop (forward-line 1)) |
1247 ;; Search forward for then. | 1436 ;; Search forward for then. |
1248 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") | 1437 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1249 (not | 1438 (not |
1250 (setq then-test | 1439 (setq then-test |
1251 (looking-at | 1440 (looking-at |
1252 (concat ".*then\\b[ \t]*" | 1441 (concat ".*then\\b[ \t]*" |
1253 "[^ \t(=a-z0-9]")))))) | 1442 "[^ \t(=a-z0-9]")))))) |
1254 then-test)) | 1443 then-test)) |
1255 (setq count (- count 1))))) | 1444 (setq count (1- count))))) |
1256 ((looking-at "end[ \t]*if\\b") | 1445 ((looking-at "end[ \t]*if\\b") |
1257 (setq count (+ count 1))))) | 1446 (setq count (1+ count))))) |
1258 (and (= count 0) | 1447 (and (zerop count) |
1259 ;; All pairs accounted for. | 1448 ;; All pairs accounted for. |
1260 (point))))))) | 1449 (point))))))) |
1450 | |
1261 | 1451 |
1262 (defun fortran-indent-line () | 1452 (defun fortran-indent-line () |
1263 "Indent current Fortran line based on its contents and on previous lines." | 1453 "Indent current Fortran line based on its contents and on previous lines." |
1264 (interactive) | 1454 (interactive "*") |
1265 (let ((cfi (fortran-calculate-indent))) | 1455 (let ((cfi (fortran-calculate-indent))) |
1266 (save-excursion | 1456 (save-excursion |
1267 (beginning-of-line) | 1457 (beginning-of-line) |
1268 (if (or (not (= cfi (fortran-current-line-indentation))) | 1458 (if (or (not (= cfi (fortran-current-line-indentation))) |
1269 (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t) | 1459 (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t) |
1273 (if (fortran-find-comment-start-skip) | 1463 (if (fortran-find-comment-start-skip) |
1274 (fortran-indent-comment)))) | 1464 (fortran-indent-comment)))) |
1275 ;; Never leave point in left margin. | 1465 ;; Never leave point in left margin. |
1276 (if (< (current-column) cfi) | 1466 (if (< (current-column) cfi) |
1277 (move-to-column cfi)) | 1467 (move-to-column cfi)) |
1278 (if (and auto-fill-function | 1468 (and auto-fill-function |
1279 (> (save-excursion (end-of-line) (current-column)) | 1469 (> (save-excursion (end-of-line) (current-column)) |
1280 fill-column)) | 1470 fill-column) |
1281 (save-excursion | 1471 (save-excursion |
1282 (end-of-line) | 1472 (end-of-line) |
1283 (fortran-fill))) | 1473 (fortran-fill))) |
1284 (if fortran-blink-matching-if | 1474 (when fortran-blink-matching-if |
1285 (progn | 1475 (fortran-blink-matching-if) |
1286 (fortran-blink-matching-if) | 1476 (fortran-blink-matching-do)))) |
1287 (fortran-blink-matching-do))))) | |
1288 | 1477 |
1289 (defun fortran-auto-fill () | 1478 (defun fortran-auto-fill () |
1479 "Function to use for `normal-auto-fill-function' in Fortran mode." | |
1290 (if (> (current-column) (current-fill-column)) | 1480 (if (> (current-column) (current-fill-column)) |
1291 (let ((cfi (fortran-calculate-indent))) | 1481 (let ((cfi (fortran-calculate-indent))) |
1292 (save-excursion | 1482 (save-excursion |
1293 (beginning-of-line) | 1483 (beginning-of-line) |
1294 (if (or (not (= cfi (fortran-current-line-indentation))) | 1484 (if (or (not (= cfi (fortran-current-line-indentation))) |
1307 ;; Historically this was a separate function which advertised itself | 1497 ;; Historically this was a separate function which advertised itself |
1308 ;; as reindenting but only did so where `most likely to be necessary'. | 1498 ;; as reindenting but only did so where `most likely to be necessary'. |
1309 (defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent) | 1499 (defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent) |
1310 | 1500 |
1311 (defun fortran-indent-subprogram () | 1501 (defun fortran-indent-subprogram () |
1312 "Properly indent the Fortran subprogram which contains point." | 1502 "Properly indent the Fortran subprogram containing point." |
1313 (interactive) | 1503 (interactive "*") |
1314 (save-excursion | 1504 (save-excursion |
1315 (mark-defun) | 1505 (mark-defun) |
1316 (message "Indenting subprogram...") | 1506 (message "Indenting subprogram...") |
1317 (indent-region (point) (mark) nil)) | 1507 (indent-region (point) (mark) nil)) |
1318 (message "Indenting subprogram...done.")) | 1508 (message "Indenting subprogram...done.")) |
1326 fortran-minimum-statement-indent-fixed))) | 1516 fortran-minimum-statement-indent-fixed))) |
1327 (save-excursion | 1517 (save-excursion |
1328 (setq first-statement (fortran-previous-statement)) | 1518 (setq first-statement (fortran-previous-statement)) |
1329 (if first-statement | 1519 (if first-statement |
1330 (setq icol fortran-minimum-statement-indent) | 1520 (setq icol fortran-minimum-statement-indent) |
1331 (progn | 1521 (if (= (point) (point-min)) |
1332 (if (= (point) (point-min)) | 1522 (setq icol fortran-minimum-statement-indent) |
1333 (setq icol fortran-minimum-statement-indent) | 1523 (setq icol (fortran-current-line-indentation))) |
1334 (setq icol (fortran-current-line-indentation))) | 1524 (skip-chars-forward " \t0-9") |
1335 (skip-chars-forward " \t0-9") | 1525 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") |
1336 (cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") | 1526 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") |
1337 (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") | 1527 (let (then-test) ; multi-line if-then |
1338 (let (then-test) ;multi-line if-then | 1528 (while (and (zerop (forward-line 1)) |
1339 (while (and (= (forward-line 1) 0) | 1529 ;; Search forward for then. |
1340 ;;search forward for then | 1530 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1341 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") | 1531 (not (setq then-test |
1342 (not (setq then-test | 1532 (looking-at |
1343 (looking-at | 1533 ".*then\\b[ \t]\ |
1344 ".*then\\b[ \t]\ | |
1345 *[^ \t_$(=a-z0-9]"))))) | 1534 *[^ \t_$(=a-z0-9]"))))) |
1346 then-test)) | 1535 then-test)) |
1347 (setq icol (+ icol fortran-if-indent)))) | 1536 (setq icol (+ icol fortran-if-indent)))) |
1348 ((looking-at "else\\(if\\)?\\b") | 1537 ((looking-at "else\\(if\\)?\\b") |
1349 (setq icol (+ icol fortran-if-indent))) | 1538 (setq icol (+ icol fortran-if-indent))) |
1350 ((looking-at "select[ \t]*case[ \t](.*)") | 1539 ((looking-at "select[ \t]*case[ \t](.*)") |
1351 (setq icol (+ icol fortran-if-indent))) | 1540 (setq icol (+ icol fortran-if-indent))) |
1352 ((looking-at "case[ \t]*(.*)") | 1541 ((looking-at "case[ \t]*(.*)") |
1353 (setq icol (+ icol fortran-if-indent))) | 1542 (setq icol (+ icol fortran-if-indent))) |
1354 ((looking-at "case[ \t]*default\\b") | 1543 ((looking-at "case[ \t]*default\\b") |
1355 (setq icol (+ icol fortran-if-indent))) | 1544 (setq icol (+ icol fortran-if-indent))) |
1356 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") | 1545 ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") |
1357 (setq icol (+ icol fortran-if-indent))) | 1546 (setq icol (+ icol fortran-if-indent))) |
1358 ((looking-at "where[ \t]*(.*)[ \t]*\n") | 1547 ((looking-at "where[ \t]*(.*)[ \t]*\n") |
1359 (setq icol (+ icol fortran-if-indent))) | 1548 (setq icol (+ icol fortran-if-indent))) |
1360 ((looking-at "do\\b") | 1549 ((looking-at "do\\b") |
1361 (setq icol (+ icol fortran-do-indent))) | 1550 (setq icol (+ icol fortran-do-indent))) |
1362 ((looking-at | 1551 ((looking-at |
1363 "\\(structure\\|union\\|map\\|interface\\)\ | 1552 "\\(structure\\|union\\|map\\|interface\\)\ |
1364 \\b[ \t]*[^ \t=(a-z]") | 1553 \\b[ \t]*[^ \t=(a-z]") |
1365 (setq icol (+ icol fortran-structure-indent))) | 1554 (setq icol (+ icol fortran-structure-indent))) |
1366 ((and (looking-at fortran-end-prog-re1) | 1555 ((and (looking-at fortran-end-prog-re1) |
1367 (fortran-check-end-prog-re)) | 1556 (fortran-check-end-prog-re)) |
1368 ;; Previous END resets indent to minimum | 1557 ;; Previous END resets indent to minimum. |
1369 (setq icol fortran-minimum-statement-indent)))))) | 1558 (setq icol fortran-minimum-statement-indent))))) |
1370 (save-excursion | 1559 (save-excursion |
1371 (beginning-of-line) | 1560 (beginning-of-line) |
1372 (cond ((looking-at "[ \t]*$")) | 1561 (cond ((looking-at "[ \t]*$")) |
1373 ;; Check for directive before comment, so as not to indent. | 1562 ;; Check for directive before comment, so as not to indent. |
1374 ((looking-at fortran-directive-re) | 1563 ((looking-at fortran-directive-re) |
1378 (setq icol (+ icol fortran-comment-line-extra-indent))) | 1567 (setq icol (+ icol fortran-comment-line-extra-indent))) |
1379 ((eq fortran-comment-indent-style 'fixed) | 1568 ((eq fortran-comment-indent-style 'fixed) |
1380 (setq icol (+ fortran-minimum-statement-indent | 1569 (setq icol (+ fortran-minimum-statement-indent |
1381 fortran-comment-line-extra-indent)))) | 1570 fortran-comment-line-extra-indent)))) |
1382 (setq fortran-minimum-statement-indent 0)) | 1571 (setq fortran-minimum-statement-indent 0)) |
1383 ((or (looking-at (concat "[ \t]*" | 1572 ((or (looking-at (concat "[ \t]*" |
1384 (regexp-quote | 1573 (regexp-quote |
1385 fortran-continuation-string))) | 1574 fortran-continuation-string))) |
1386 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) | 1575 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) |
1387 (setq icol (+ icol fortran-continuation-indent))) | 1576 (skip-chars-forward " \t") |
1577 ;; Do not introduce extra whitespace into a broken string. | |
1578 (setq icol | |
1579 (if (fortran-is-in-string-p (point)) | |
1580 6 | |
1581 (+ icol fortran-continuation-indent)))) | |
1388 (first-statement) | 1582 (first-statement) |
1389 ((and fortran-check-all-num-for-matching-do | 1583 ((and fortran-check-all-num-for-matching-do |
1390 (looking-at "[ \t]*[0-9]+") | 1584 (looking-at "[ \t]*[0-9]+") |
1391 (fortran-check-for-matching-do)) | 1585 (fortran-check-for-matching-do)) |
1392 (setq icol (- icol fortran-do-indent))) | 1586 (setq icol (- icol fortran-do-indent))) |
1412 (fortran-check-end-prog-re) | 1606 (fortran-check-end-prog-re) |
1413 (not (= icol fortran-minimum-statement-indent))) | 1607 (not (= icol fortran-minimum-statement-indent))) |
1414 (message "Warning: `end' not in column %d. Probably\ | 1608 (message "Warning: `end' not in column %d. Probably\ |
1415 an unclosed block." fortran-minimum-statement-indent)))))) | 1609 an unclosed block." fortran-minimum-statement-indent)))))) |
1416 (max fortran-minimum-statement-indent icol))) | 1610 (max fortran-minimum-statement-indent icol))) |
1611 | |
1417 | 1612 |
1418 (defun fortran-current-line-indentation () | 1613 (defun fortran-current-line-indentation () |
1419 "Indentation of current line, ignoring Fortran line number or continuation. | 1614 "Indentation of current line, ignoring Fortran line number or continuation. |
1420 This is the column position of the first non-whitespace character | 1615 This is the column position of the first non-whitespace character |
1421 aside from the line number and/or column 5/8 line-continuation character. | 1616 aside from the line number and/or column 5/8 line-continuation character. |
1437 ;; Move past whitespace. | 1632 ;; Move past whitespace. |
1438 (skip-chars-forward " \t") | 1633 (skip-chars-forward " \t") |
1439 (current-column))) | 1634 (current-column))) |
1440 | 1635 |
1441 (defun fortran-indent-to-column (col) | 1636 (defun fortran-indent-to-column (col) |
1442 "Indent current line with spaces to column COL. | 1637 "Indent current line to column COL. |
1443 notes: 1) A non-zero/non-blank character in column 5 indicates a continuation | 1638 notes: 1) A non-zero/non-blank character in column 5 indicates a continuation |
1444 line, and this continuation character is retained on indentation; | 1639 line, and this continuation character is retained on indentation; |
1445 2) If `fortran-continuation-string' is the first non-whitespace | 1640 2) If `fortran-continuation-string' is the first non-whitespace |
1446 character, this is a continuation line; | 1641 character, this is a continuation line; |
1447 3) A non-continuation line which has a number as the first | 1642 3) A non-continuation line which has a number as the first |
1452 (if (looking-at fortran-comment-line-start-skip) | 1647 (if (looking-at fortran-comment-line-start-skip) |
1453 (if fortran-comment-indent-style | 1648 (if fortran-comment-indent-style |
1454 (let* ((char (if (stringp fortran-comment-indent-char) | 1649 (let* ((char (if (stringp fortran-comment-indent-char) |
1455 (aref fortran-comment-indent-char 0) | 1650 (aref fortran-comment-indent-char 0) |
1456 fortran-comment-indent-char)) | 1651 fortran-comment-indent-char)) |
1457 (chars (string ? ?\t char))) | 1652 (chars (string ?\s ?\t char))) |
1458 (goto-char (match-end 0)) | 1653 (goto-char (match-end 0)) |
1459 (skip-chars-backward chars) | 1654 (skip-chars-backward chars) |
1460 (delete-region (point) (progn (skip-chars-forward chars) | 1655 (delete-region (point) (progn (skip-chars-forward chars) |
1461 (point))) | 1656 (point))) |
1462 (insert-char char (- col (current-column))))) | 1657 (insert-char char (- col (current-column))))) |
1463 (if (looking-at "\t[1-9]") | 1658 (if (looking-at "\t[1-9]") |
1464 (if indent-tabs-mode | 1659 (if indent-tabs-mode |
1465 (goto-char (match-end 0)) | 1660 (goto-char (match-end 0)) |
1466 (delete-char 2) | 1661 (delete-char 2) |
1467 (insert-char ? 5) | 1662 (insert-char ?\s 5) |
1468 (insert fortran-continuation-string)) | 1663 (insert fortran-continuation-string)) |
1469 (if (looking-at " \\{5\\}[^ 0\n]") | 1664 (if (looking-at " \\{5\\}[^ 0\n]") |
1470 (if indent-tabs-mode | 1665 (if indent-tabs-mode |
1471 (progn (delete-char 6) | 1666 (progn (delete-char 6) |
1472 (insert ?\t (fortran-numerical-continuation-char) 1)) | 1667 (insert ?\t (fortran-numerical-continuation-char) 1)) |
1473 (forward-char 6)) | 1668 (forward-char 6)) |
1474 (delete-horizontal-space) | 1669 (delete-horizontal-space) |
1475 ;; Put line number in columns 0-4 | 1670 ;; Put line number in columns 0-4, or |
1476 ;; or put continuation character in column 5. | 1671 ;; continuation character in column 5. |
1477 (cond ((eobp)) | 1672 (cond ((eobp)) |
1478 ((looking-at (regexp-quote fortran-continuation-string)) | 1673 ((looking-at (regexp-quote fortran-continuation-string)) |
1479 (if indent-tabs-mode | 1674 (if indent-tabs-mode |
1480 (progn | 1675 (progn |
1481 (indent-to | 1676 (indent-to |
1495 ;; Point is now after any continuation character or line number. | 1690 ;; Point is now after any continuation character or line number. |
1496 ;; Put body of statement where specified. | 1691 ;; Put body of statement where specified. |
1497 (delete-horizontal-space) | 1692 (delete-horizontal-space) |
1498 (indent-to col) | 1693 (indent-to col) |
1499 ;; Indent any comment following code on the same line. | 1694 ;; Indent any comment following code on the same line. |
1500 (if (fortran-find-comment-start-skip) | 1695 (when (fortran-find-comment-start-skip) |
1501 (progn (goto-char (match-beginning 0)) | 1696 (goto-char (match-beginning 0)) |
1502 (if (not (= (current-column) (fortran-comment-indent))) | 1697 (unless (= (current-column) (fortran-comment-indent)) |
1503 (progn (delete-horizontal-space) | 1698 (delete-horizontal-space) |
1504 (indent-to (fortran-comment-indent))))))))) | 1699 (indent-to (fortran-comment-indent))))))) |
1505 | 1700 |
1506 (defun fortran-line-number-indented-correctly-p () | 1701 (defun fortran-line-number-indented-correctly-p () |
1507 "Return t if current line's line number is correctly indented. | 1702 "Return t if current line's line number is correctly indented. |
1508 Do not call if there is no line number." | 1703 Do not call if there is no line number." |
1509 (save-excursion | 1704 (save-excursion |
1519 Otherwise return nil." | 1714 Otherwise return nil." |
1520 (let ((case-fold-search t) | 1715 (let ((case-fold-search t) |
1521 charnum) | 1716 charnum) |
1522 (save-excursion | 1717 (save-excursion |
1523 (beginning-of-line) | 1718 (beginning-of-line) |
1524 (if (looking-at "[ \t]*[0-9]+") | 1719 (when (looking-at "[ \t]*[0-9]+") |
1525 (progn | 1720 (skip-chars-forward " \t") |
1526 (skip-chars-forward " \t") | 1721 (skip-chars-forward "0") ; skip past leading zeros |
1527 (skip-chars-forward "0") ;skip past leading zeros | 1722 (setq charnum |
1528 (setq charnum | 1723 (buffer-substring (point) (progn |
1529 (buffer-substring (point) (progn | 1724 (skip-chars-forward "0-9") |
1530 (skip-chars-forward "0-9") | 1725 (point)))) |
1531 (point)))) | 1726 (beginning-of-line) |
1532 (beginning-of-line) | 1727 (save-restriction |
1533 (save-restriction | 1728 (save-excursion |
1534 (save-excursion | 1729 (narrow-to-defun) |
1535 (narrow-to-defun) | 1730 (and (re-search-backward |
1536 (and (re-search-backward | 1731 (concat |
1537 (concat | 1732 "\\(^[ \t0-9]*do[ \t]*0*" |
1538 "\\(^[ \t0-9]*do[ \t]*0*" | 1733 charnum "\\b\\)\\|" "\\(^[ \t]*0*" |
1539 charnum "\\b\\)\\|" "\\(^[ \t]*0*" | 1734 charnum "\\b\\)") |
1540 charnum "\\b\\)") | 1735 nil t) |
1541 nil t) | 1736 (looking-at |
1542 (looking-at | 1737 (concat "^[ \t0-9]*do[ \t]*0*" |
1543 (concat "^[ \t0-9]*do[ \t]*0*" | 1738 charnum))))))))) |
1544 charnum)))))))))) | |
1545 | 1739 |
1546 (defun fortran-find-comment-start-skip (&optional all) | 1740 (defun fortran-find-comment-start-skip (&optional all) |
1547 "Move to past `comment-start-skip' found on current line. | 1741 "Move to past `comment-start-skip' found on current line. |
1548 Return non-nil if `comment-start-skip' found, nil if not. | 1742 Return non-nil if `comment-start-skip' found, nil if not. |
1549 If ALL is nil, only match comments that start in column > 0." | 1743 If ALL is nil, only match comments that start in column > 0." |
1550 (interactive) | |
1551 ;; Hopefully at some point we can just use the line below! -stef | 1744 ;; Hopefully at some point we can just use the line below! -stef |
1552 ;; (comment-search-forward (line-end-position) t)) | 1745 ;; (comment-search-forward (line-end-position) t)) |
1553 (when (or all comment-start-skip) | 1746 (when (or all comment-start-skip) |
1554 (let ((pos (point)) | 1747 (let ((pos (point)) |
1555 (css (if comment-start-skip | 1748 (css (if comment-start-skip |
1564 (fortran-find-comment-start-skip all))) | 1757 (fortran-find-comment-start-skip all))) |
1565 (point) | 1758 (point) |
1566 (goto-char pos) | 1759 (goto-char pos) |
1567 nil))))) | 1760 nil))))) |
1568 | 1761 |
1569 ;;From: ralf@up3aud1.gwdg.de (Ralf Fassel) | 1762 ;; From: ralf@up3aud1.gwdg.de (Ralf Fassel) |
1570 ;; Test if TAB format continuation lines work. | 1763 ;; Test if TAB format continuation lines work. |
1571 (defun fortran-is-in-string-p (where) | 1764 (defun fortran-is-in-string-p (where) |
1572 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string." | 1765 "Return non-nil iff WHERE (a buffer position) is inside a Fortran string." |
1573 (save-excursion | 1766 (save-excursion |
1574 (goto-char where) | 1767 (goto-char where) |
1575 (cond | 1768 (cond |
1576 ((bolp) nil) ; bol is never inside a string | 1769 ((bolp) nil) ; bol is never inside a string |
1577 ((save-excursion ; comment lines too | 1770 ((save-excursion ; comment lines too |
1578 (beginning-of-line) | 1771 (beginning-of-line) |
1579 (looking-at fortran-comment-line-start-skip)) nil) | 1772 (looking-at fortran-comment-line-start-skip)) nil) |
1580 (t (let (;; ok, serious now. Init some local vars: | 1773 (t (let ((parse-state '(0 nil nil nil nil nil 0)) |
1581 (parse-state '(0 nil nil nil nil nil 0)) | |
1582 (quoted-comment-start (if comment-start | 1774 (quoted-comment-start (if comment-start |
1583 (regexp-quote comment-start))) | 1775 (regexp-quote comment-start))) |
1584 (not-done t) | 1776 (not-done t) |
1585 parse-limit end-of-line) | 1777 parse-limit end-of-line) |
1586 ;; move to start of current statement | 1778 ;; Move to start of current statement. |
1587 (fortran-next-statement) | 1779 (fortran-next-statement) |
1588 (fortran-previous-statement) | 1780 (fortran-previous-statement) |
1589 ;; now parse up to WHERE | 1781 ;; Now parse up to WHERE. |
1590 (while not-done | 1782 (while not-done |
1591 (if (or ;; skip to next line if: | 1783 (if (or ;; Skip to next line if: |
1592 ;; - comment line? | 1784 ;; - comment line? |
1593 (looking-at fortran-comment-line-start-skip) | 1785 (looking-at fortran-comment-line-start-skip) |
1594 ;; - at end of line? | 1786 ;; - at end of line? |
1595 (eolp) | 1787 (eolp) |
1596 ;; - not in a string and after comment-start? | 1788 ;; - not in a string and after comment-start? |
1599 (equal comment-start | 1791 (equal comment-start |
1600 (char-to-string (preceding-char))))) | 1792 (char-to-string (preceding-char))))) |
1601 (if (> (forward-line) 0) | 1793 (if (> (forward-line) 0) |
1602 (setq not-done nil)) | 1794 (setq not-done nil)) |
1603 ;; else: | 1795 ;; else: |
1604 ;; if we are at beginning of code line, skip any | 1796 ;; If we are at beginning of code line, skip any |
1605 ;; whitespace, labels and tab continuation markers. | 1797 ;; whitespace, labels and tab continuation markers. |
1606 (if (bolp) (skip-chars-forward " \t0-9")) | 1798 (if (bolp) (skip-chars-forward " \t0-9")) |
1607 ;; if we are in column <= 5 now, check for continuation char | 1799 ;; If we are in column <= 5 now, check for continuation char. |
1608 (cond ((= 5 (current-column)) (forward-char 1)) | 1800 (cond ((= 5 (current-column)) (forward-char 1)) |
1609 ((and (< (current-column) 5) | 1801 ((and (< (current-column) 5) |
1610 (equal fortran-continuation-string | 1802 (equal fortran-continuation-string |
1611 (char-to-string (following-char))) | 1803 (char-to-string (following-char))) |
1612 (forward-char 1)))) | 1804 (forward-char 1)))) |
1613 ;; find out parse-limit from here | 1805 ;; Find out parse-limit from here. |
1614 (setq end-of-line (line-end-position)) | 1806 (setq end-of-line (line-end-position)) |
1615 (setq parse-limit (min where end-of-line)) | 1807 (setq parse-limit (min where end-of-line)) |
1616 ;; parse max up to comment-start, if non-nil and in current line | 1808 ;; Parse max up to comment-start, if non-nil and in current line. |
1617 (if comment-start | 1809 (if comment-start |
1618 (save-excursion | 1810 (save-excursion |
1619 (if (re-search-forward quoted-comment-start end-of-line t) | 1811 (if (re-search-forward quoted-comment-start end-of-line t) |
1620 (setq parse-limit (min (point) parse-limit))))) | 1812 (setq parse-limit (min (point) parse-limit))))) |
1621 ;; now parse if still in limits | 1813 ;; Now parse if still in limits. |
1622 (if (< (point) where) | 1814 (if (< (point) where) |
1623 (setq parse-state (parse-partial-sexp | 1815 (setq parse-state (parse-partial-sexp |
1624 (point) parse-limit nil nil parse-state)) | 1816 (point) parse-limit nil nil parse-state)) |
1625 (setq not-done nil)))) | 1817 (setq not-done nil)))) |
1626 ;; result is | 1818 ;; Result. |
1627 (nth 3 parse-state)))))) | 1819 (nth 3 parse-state)))))) |
1628 | 1820 |
1629 ;; From old version. | 1821 ;; From old version. |
1630 (defalias 'fortran-auto-fill-mode 'auto-fill-mode) | 1822 (defalias 'fortran-auto-fill-mode 'auto-fill-mode) |
1631 | 1823 |
1632 (defun fortran-fill () | 1824 (defun fortran-fill () |
1825 "Fill the current line at an appropriate point(s)." | |
1633 (let* ((auto-fill-function #'fortran-auto-fill) | 1826 (let* ((auto-fill-function #'fortran-auto-fill) |
1634 (opoint (point)) | 1827 (opoint (point)) |
1635 (bol (line-beginning-position)) | 1828 (bol (line-beginning-position)) |
1636 (eol (line-end-position)) | 1829 (eol (line-end-position)) |
1637 (bos (min eol (+ bol (fortran-current-line-indentation)))) | 1830 (bos (min eol (+ bol (fortran-current-line-indentation)))) |
1831 ;; If in a string at fill-column, break it either before the | |
1832 ;; initial quote, or at fill-col (if string is too long). | |
1638 (quote | 1833 (quote |
1639 (save-excursion | 1834 (save-excursion |
1640 (goto-char bol) | 1835 (goto-char bol) |
1641 (if (looking-at fortran-comment-line-start-skip) | 1836 ;; OK to break quotes on comment lines. |
1642 nil ; OK to break quotes on comment lines. | 1837 (unless (looking-at fortran-comment-line-start-skip) |
1643 (move-to-column fill-column) | 1838 (let (fcpoint start) |
1644 (if (fortran-is-in-string-p (point)) | 1839 (move-to-column fill-column) |
1645 (save-excursion (re-search-backward "\\S\"\\s\"\\S\"" bol t) | 1840 (when (fortran-is-in-string-p (setq fcpoint (point))) |
1646 (if fortran-break-before-delimiters | 1841 (save-excursion |
1647 (point) | 1842 (re-search-backward "\\S\"\\s\"\\S\"?" bol t) |
1648 (1+ (point)))))))) | 1843 (setq start |
1649 ;; decide where to split the line. If a position for a quoted | 1844 (if fortran-break-before-delimiters |
1845 (point) | |
1846 (1+ (point))))) | |
1847 (if (re-search-forward "\\S\"\\s\"\\S\"" eol t) | |
1848 (backward-char 2)) | |
1849 ;; If the current string is longer than (fill-column | |
1850 ;; - 6) chars, break it at the fill column (else | |
1851 ;; infinite loop). | |
1852 (if (> (- (point) start) | |
1853 (- fill-column 6 fortran-continuation-indent)) | |
1854 fcpoint | |
1855 start)))))) | |
1856 ;; Decide where to split the line. If a position for a quoted | |
1650 ;; string was found above then use that, else break the line | 1857 ;; string was found above then use that, else break the line |
1651 ;; before the last delimiter. | 1858 ;; before/after the last delimiter. |
1652 ;; Delimiters are whitespace, commas, and operators. | |
1653 ;; Will break before a pair of *'s. | |
1654 (fill-point | 1859 (fill-point |
1655 (or quote | 1860 (or quote |
1656 (save-excursion | 1861 (save-excursion |
1657 (move-to-column (1+ fill-column)) | 1862 ;; If f-b-b-d is t, have an extra column to play with, |
1658 (skip-chars-backward "^ \t\n,'+-/*=)" | 1863 ;; since delimiter gets shifted to new line. |
1659 ;;; (if fortran-break-before-delimiters | 1864 (move-to-column (if fortran-break-before-delimiters |
1660 ;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)") | 1865 (1+ fill-column) |
1661 ) | 1866 fill-column)) |
1662 (if (<= (point) (1+ bos)) | 1867 (let ((repeat t)) |
1663 (progn | 1868 (while repeat |
1664 (move-to-column (1+ fill-column)) | 1869 (setq repeat nil) |
1665 ;;what is this doing??? | 1870 ;; Adapted from f90-find-breakpoint. |
1666 (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t)) | 1871 (re-search-backward fortran-break-delimiters-re bol) |
1667 (goto-char bol)))) | 1872 (if (not fortran-break-before-delimiters) |
1873 (if (looking-at fortran-no-break-re) | |
1874 ;; Deal with cases such as "**" split over | |
1875 ;; fill-col. Simpler alternative would be | |
1876 ;; to start from (1- fill-column) above. | |
1877 (if (> (+ 2 (current-column)) fill-column) | |
1878 (setq repeat t) | |
1879 (forward-char 2)) | |
1880 (forward-char 1)) | |
1881 (backward-char) | |
1882 (or (looking-at fortran-no-break-re) | |
1883 (forward-char))))) | |
1884 ;; Line indented beyond fill-column? | |
1885 (when (<= (point) bos) | |
1886 (move-to-column (1+ fill-column)) | |
1887 ;; What is this doing??? | |
1888 (or (re-search-forward "[\t\n,'+-/*)=]" eol t) | |
1889 (goto-char bol))) | |
1668 (if (bolp) | 1890 (if (bolp) |
1669 (re-search-forward "[ \t]" opoint t) | 1891 (re-search-forward "[ \t]" opoint t)) |
1670 (backward-char) | 1892 (point))))) |
1671 (if (looking-at "\\s\"") | 1893 ;; If we are in an in-line comment, don't break unless the |
1672 (forward-char) | |
1673 (skip-chars-backward " \t\*"))) | |
1674 (if fortran-break-before-delimiters | |
1675 (point) | |
1676 (1+ (point))))))) | |
1677 ;; if we are in an in-line comment, don't break unless the | |
1678 ;; line of code is longer than it should be. Otherwise | 1894 ;; line of code is longer than it should be. Otherwise |
1679 ;; break the line at the column computed above. | 1895 ;; break the line at the column computed above. |
1680 ;; | 1896 ;; |
1681 ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s | 1897 ;; Need to use fortran-find-comment-start-skip to make sure that |
1682 ;; don't prevent a break. | 1898 ;; quoted !'s don't prevent a break. |
1683 (when (and (save-excursion | 1899 (when (and (save-excursion |
1684 (beginning-of-line) | 1900 (beginning-of-line) |
1685 (if (not (fortran-find-comment-start-skip)) | 1901 (if (not (fortran-find-comment-start-skip)) |
1686 t | 1902 t |
1687 (goto-char (match-beginning 0)) | 1903 (goto-char (match-beginning 0)) |
1698 (goto-char fill-point) | 1914 (goto-char fill-point) |
1699 (fortran-break-line) | 1915 (fortran-break-line) |
1700 (end-of-line)))) | 1916 (end-of-line)))) |
1701 | 1917 |
1702 (defun fortran-break-line () | 1918 (defun fortran-break-line () |
1919 "Call `fortran-split-line'. Joins continuation lines first, then refills." | |
1703 (let ((opoint (point)) | 1920 (let ((opoint (point)) |
1704 (bol (line-beginning-position)) | 1921 (bol (line-beginning-position)) |
1705 (comment-string | 1922 (comment-string |
1706 (save-excursion | 1923 (save-excursion |
1707 (if (fortran-find-comment-start-skip) | 1924 (if (fortran-find-comment-start-skip) |
1708 (delete-and-extract-region | 1925 (delete-and-extract-region |
1709 (match-beginning 0) (line-end-position)))))) | 1926 (match-beginning 0) (line-end-position)))))) |
1710 ;; Forward line 1 really needs to go to next non white line | 1927 ;; Forward line 1 really needs to go to next non white line. |
1711 (if (save-excursion (forward-line) | 1928 (if (save-excursion (forward-line) |
1712 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) | 1929 (looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) |
1713 (progn | 1930 (progn |
1714 (end-of-line) | 1931 (end-of-line) |
1715 (delete-region (point) (match-end 0)) | 1932 (delete-region (point) (match-end 0)) |
1724 (indent-to (fortran-comment-indent)) | 1941 (indent-to (fortran-comment-indent)) |
1725 (insert comment-string))))) | 1942 (insert comment-string))))) |
1726 | 1943 |
1727 (defun fortran-analyze-file-format () | 1944 (defun fortran-analyze-file-format () |
1728 "Return nil if fixed format is used, t if TAB formatting is used. | 1945 "Return nil if fixed format is used, t if TAB formatting is used. |
1729 Use `fortran-tab-mode-default' if no non-comment statements are found in the | 1946 Use `fortran-tab-mode-default' if no non-comment statements are found |
1730 file before the end or the first `fortran-analyze-depth' lines." | 1947 before the end or in the first `fortran-analyze-depth' lines." |
1731 (let ((i 0)) | 1948 (let ((i 0)) |
1732 (save-excursion | 1949 (save-excursion |
1733 (goto-char (point-min)) | 1950 (goto-char (point-min)) |
1734 (setq i 0) | |
1735 (while (not (or | 1951 (while (not (or |
1736 (eobp) | 1952 (eobp) |
1737 (eq (char-after) ?\t) | 1953 (eq (char-after) ?\t) |
1738 (looking-at " \\{6\\}") | 1954 (looking-at " \\{6\\}") |
1739 (> i fortran-analyze-depth))) | 1955 (> i fortran-analyze-depth))) |
1740 (forward-line) | 1956 (forward-line) |
1741 (setq i (1+ i))) | 1957 (setq i (1+ i))) |
1742 (cond | 1958 (cond |
1743 ((eq (char-after) ?\t) t) | 1959 ((eq (char-after) ?\t) t) |
1744 ((looking-at " \\{6\\}") nil) | 1960 ((looking-at " \\{6\\}") nil) |
1745 (fortran-tab-mode-default t) | 1961 (t fortran-tab-mode-default))))) |
1746 (t nil))))) | |
1747 | |
1748 (or (assq 'fortran-tab-mode-string minor-mode-alist) | |
1749 (setq minor-mode-alist (cons | |
1750 '(fortran-tab-mode-string | |
1751 (indent-tabs-mode fortran-tab-mode-string)) | |
1752 minor-mode-alist))) | |
1753 | 1962 |
1754 (defun fortran-fill-paragraph (&optional justify) | 1963 (defun fortran-fill-paragraph (&optional justify) |
1755 "Fill surrounding comment block as paragraphs, else fill statement. | 1964 "Fill surrounding comment block as paragraphs, else fill statement. |
1756 Intended as the value of `fill-paragraph-function'." | 1965 Intended as the value of `fill-paragraph-function'. |
1757 (interactive "P") | 1966 A comment block is filled by calling `fill-comment-paragraph' with |
1967 argument JUSTIFY, otherwise `fortran-fill-statement' is called. | |
1968 Always returns non-nil (to prevent `fill-paragraph' being called)." | |
1969 (interactive "*P") | |
1758 (or (fill-comment-paragraph justify) | 1970 (or (fill-comment-paragraph justify) |
1759 (fortran-fill-statement) | 1971 (fortran-fill-statement) |
1760 t)) | 1972 t)) |
1761 | 1973 |
1762 (defun fortran-fill-statement () | 1974 (defun fortran-fill-statement () |
1763 "Fill a fortran statement up to `fill-column'." | 1975 "Fill a Fortran statement up to `fill-column'." |
1764 (interactive) | 1976 (interactive "*") |
1765 (let ((auto-fill-function #'fortran-auto-fill)) | 1977 (let ((auto-fill-function #'fortran-auto-fill)) |
1766 (if (not (save-excursion | 1978 (unless (save-excursion |
1767 (beginning-of-line) | 1979 (beginning-of-line) |
1768 (or (looking-at "[ \t]*$") | 1980 (or (looking-at "[ \t]*$") |
1769 (looking-at fortran-comment-line-start-skip) | 1981 (looking-at fortran-comment-line-start-skip) |
1770 (and comment-start-skip | 1982 (and comment-start-skip |
1771 (looking-at (concat "[ \t]*" comment-start-skip)))))) | 1983 (looking-at (concat "[ \t]*" comment-start-skip))))) |
1772 (save-excursion | 1984 (save-excursion |
1773 ;; Find beginning of statement. | 1985 ;; Find beginning of statement. |
1774 (fortran-next-statement) | 1986 (fortran-next-statement) |
1775 (fortran-previous-statement) | 1987 (fortran-previous-statement) |
1776 ;; Re-indent initially. | 1988 ;; Re-indent initially. |
1777 (fortran-indent-line) | 1989 (fortran-indent-line) |
1778 ;; Replace newline plus continuation field plus indentation with | 1990 ;; Replace newline plus continuation field plus indentation with |
1779 ;; single space. | 1991 ;; single space. |
1780 (while (progn | 1992 (while (progn |
1781 (forward-line) | 1993 (forward-line) |
1782 (fortran-remove-continuation))) | 1994 (fortran-remove-continuation))) |
1783 (fortran-previous-statement))) | 1995 (fortran-previous-statement))) |
1784 (fortran-indent-line))) | 1996 (fortran-indent-line))) |
1785 | 1997 |
1786 (defun fortran-strip-sequence-nos (&optional do-space) | 1998 (defun fortran-strip-sequence-nos (&optional do-space) |
1787 "Delete all text in column 72 and up (assumed to be sequence numbers). | 1999 "Delete all text in column 72 and up (assumed to be sequence numbers). |
1788 Normally also deletes trailing whitespace after stripping such text. | 2000 Normally also deletes trailing whitespace after stripping such text. |
1789 Supplying prefix arg DO-SPACE prevents stripping the whitespace." | 2001 Supplying prefix arg DO-SPACE prevents stripping the whitespace." |
1790 (interactive "p") | 2002 (interactive "*p") |
1791 (save-excursion | 2003 (save-excursion |
1792 (goto-char (point-min)) | 2004 (goto-char (point-min)) |
1793 (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t) | 2005 (while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t) |
1794 (replace-match "" nil nil nil 1) | 2006 (replace-match "" nil nil nil 1) |
1795 (unless do-space (delete-horizontal-space))))) | 2007 (unless do-space (delete-horizontal-space))))) |
1800 "Function to use for `add-log-current-defun-function' in Fortran mode." | 2012 "Function to use for `add-log-current-defun-function' in Fortran mode." |
1801 (save-excursion | 2013 (save-excursion |
1802 ;; We must be inside function body for this to work. | 2014 ;; We must be inside function body for this to work. |
1803 (fortran-beginning-of-subprogram) | 2015 (fortran-beginning-of-subprogram) |
1804 (let ((case-fold-search t)) ; case-insensitive | 2016 (let ((case-fold-search t)) ; case-insensitive |
1805 ;; search for fortran subprogram start | 2017 ;; Search for fortran subprogram start. |
1806 (if (re-search-forward | 2018 (if (re-search-forward |
1807 (concat "^[ \t]*\\(program\\|subroutine\\|function" | 2019 (concat "^[ \t]*\\(program\\|subroutine\\|function" |
1808 "\\|[ \ta-z0-9*()]*[ \t]+function\\|" | 2020 "\\|[ \ta-z0-9*()]*[ \t]+function\\|" |
1809 "\\(block[ \t]*data\\)\\)") | 2021 "\\(block[ \t]*data\\)\\)") |
1810 (save-excursion (fortran-end-of-subprogram) | 2022 (save-excursion (fortran-end-of-subprogram) |
1811 (point)) | 2023 (point)) |
1812 t) | 2024 t) |
1813 (or (match-string-no-properties 2) | 2025 (or (match-string-no-properties 2) |
1814 (progn | 2026 (progn |
1815 ;; move to EOL or before first left paren | 2027 ;; Move to EOL or before first left paren. |
1816 (if (re-search-forward "[(\n]" nil t) | 2028 (if (re-search-forward "[(\n]" nil t) |
1817 (progn (backward-char) | 2029 (progn (backward-char) |
1818 (skip-chars-backward " \t")) | 2030 (skip-chars-backward " \t")) |
1819 (end-of-line)) | 2031 (end-of-line)) |
1820 ;; Use the name preceding that. | 2032 ;; Use the name preceding that. |
1822 (point))))) | 2034 (point))))) |
1823 "main")))) | 2035 "main")))) |
1824 | 2036 |
1825 (provide 'fortran) | 2037 (provide 'fortran) |
1826 | 2038 |
2039 ;;; arch-tag: 74935096-21c4-4cab-8ee5-6ef16090dc04 | |
1827 ;;; fortran.el ends here | 2040 ;;; fortran.el ends here |