1 |
;;; fortran.el --- Fortran mode for GNU Emacs |
;;; fortran.el --- Fortran mode for GNU Emacs |
2 |
|
|
3 |
;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 2001 |
;; Copyright (c) 1986, 93, 94, 95, 97, 98, 99, 2000, 01, 2003 |
4 |
;; Free Software Foundation, Inc. |
;; Free Software Foundation, Inc. |
5 |
|
|
6 |
;; Author: Michael D. Prange <prange@erl.mit.edu> |
;; Author: Michael D. Prange <prange@erl.mit.edu> |
7 |
;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> |
;; Maintainer: Glenn Morris <gmorris@ast.cam.ac.uk> |
8 |
;; Keywords: languages |
;; Keywords: fortran, languages |
9 |
|
|
10 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
11 |
|
|
53 |
;; second in column 6. |
;; second in column 6. |
54 |
;; * Support any other extensions to f77 grokked by GNU Fortran I've missed. |
;; * Support any other extensions to f77 grokked by GNU Fortran I've missed. |
55 |
|
|
56 |
|
(eval-when-compile ; silence compiler |
57 |
|
(defvar dabbrev-case-fold-search) |
58 |
|
(defvar imenu-case-fold-search) |
59 |
|
(defvar imenu-syntax-alist)) |
60 |
|
|
61 |
|
|
62 |
(defgroup fortran nil |
(defgroup fortran nil |
63 |
"Fortran mode for Emacs" |
"Major mode for editing fixed format Fortran code." |
64 |
:link '(custom-manual "(emacs)Fortran") |
:link '(custom-manual "(emacs)Fortran") |
65 |
:group 'languages) |
:group 'languages) |
66 |
|
|
67 |
(defgroup fortran-indent nil |
(defgroup fortran-indent nil |
68 |
"Indentation variables in Fortran mode" |
"Indentation variables in Fortran mode." |
69 |
:prefix "fortran-" |
:prefix "fortran-" |
70 |
:group 'fortran) |
:group 'fortran) |
71 |
|
|
72 |
(defgroup fortran-comment nil |
(defgroup fortran-comment nil |
73 |
"Comment-handling variables in Fortran mode" |
"Comment-handling variables in Fortran mode." |
74 |
:prefix "fortran-" |
:prefix "fortran-" |
75 |
:group 'fortran) |
:group 'fortran) |
76 |
|
|
77 |
|
|
78 |
;;;###autoload |
;;;###autoload |
79 |
(defcustom fortran-tab-mode-default nil |
(defcustom fortran-tab-mode-default nil |
80 |
"*Default tabbing/carriage control style for empty files in Fortran mode. |
"*Default tabbing/carriage control style for empty files in Fortran mode. |
81 |
A value of t specifies tab-digit style of continuation control. |
A non-nil value specifies tab-digit style of continuation control. |
82 |
A value of nil specifies that continuation lines are marked |
A value of nil specifies that continuation lines are marked |
83 |
with a character in column 6." |
with a character in column 6." |
84 |
:type 'boolean |
:type 'boolean |
85 |
:group 'fortran-indent) |
:group 'fortran-indent) |
86 |
|
|
87 |
;; Buffer local, used to display mode line. |
(defcustom fortran-tab-mode-string "/t" |
88 |
(defcustom fortran-tab-mode-string nil |
"*String to appear in mode line in TAB format buffers." |
89 |
"String to appear in mode line when TAB format mode is on." |
:type 'string |
|
:type '(choice (const nil) string) |
|
90 |
:group 'fortran-indent) |
:group 'fortran-indent) |
|
(make-variable-buffer-local 'fortran-tab-mode-string) |
|
91 |
|
|
92 |
(defcustom fortran-do-indent 3 |
(defcustom fortran-do-indent 3 |
93 |
"*Extra indentation applied to DO blocks." |
"*Extra indentation applied to DO blocks." |
94 |
:type 'integer |
:type 'integer |
95 |
:group 'fortran-indent) |
:group 'fortran-indent) |
96 |
|
|
97 |
(defcustom fortran-if-indent 3 |
(defcustom fortran-if-indent 3 |
98 |
"*Extra indentation applied to IF blocks." |
"*Extra indentation applied to IF blocks." |
99 |
:type 'integer |
:type 'integer |
100 |
:group 'fortran-indent) |
:group 'fortran-indent) |
101 |
|
|
102 |
(defcustom fortran-structure-indent 3 |
(defcustom fortran-structure-indent 3 |
103 |
"*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks." |
"*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks." |
104 |
:type 'integer |
:type 'integer |
105 |
:group 'fortran-indent) |
:group 'fortran-indent) |
106 |
|
|
107 |
(defcustom fortran-continuation-indent 5 |
(defcustom fortran-continuation-indent 5 |
108 |
"*Extra indentation applied to Fortran continuation lines." |
"*Extra indentation applied to continuation lines." |
109 |
:type 'integer |
:type 'integer |
110 |
:group 'fortran-indent) |
:group 'fortran-indent) |
111 |
|
|
112 |
(defcustom fortran-comment-indent-style 'fixed |
(defcustom fortran-comment-indent-style 'fixed |
113 |
"*How to indent comments. |
"*How to indent comments. |
114 |
nil forces comment lines not to be touched, |
nil forces comment lines not to be touched; |
115 |
`fixed' makes fixed comment indentation to `fortran-comment-line-extra-indent' |
`fixed' indents to `fortran-comment-line-extra-indent' columns beyond |
116 |
columns beyond `fortran-minimum-statement-indent-fixed' (for |
`fortran-minimum-statement-indent-fixed' (if `indent-tabs-mode' nil), or |
117 |
`indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for |
`fortran-minimum-statement-indent-tab' (if `indent-tabs-mode' non-nil); |
|
`indent-tabs-mode' of t), and |
|
118 |
`relative' indents to current Fortran indentation plus |
`relative' indents to current Fortran indentation plus |
119 |
`fortran-comment-line-extra-indent'." |
`fortran-comment-line-extra-indent'." |
120 |
:type '(radio (const :tag "Untouched" nil) (const fixed) (const relative)) |
:type '(radio (const :tag "Untouched" nil) (const fixed) (const relative)) |
121 |
:group 'fortran-indent) |
:group 'fortran-indent) |
122 |
|
|
123 |
(defcustom fortran-comment-line-extra-indent 0 |
(defcustom fortran-comment-line-extra-indent 0 |
124 |
"*Amount of extra indentation for text within full-line comments." |
"*Amount of extra indentation for text within full-line comments." |
125 |
:type 'integer |
:type 'integer |
126 |
:group 'fortran-indent |
:group 'fortran-indent |
127 |
:group 'fortran-comment) |
:group 'fortran-comment) |
128 |
|
|
130 |
"*Delimiter inserted to start new full-line comment. |
"*Delimiter inserted to start new full-line comment. |
131 |
You might want to change this to \"*\", for instance." |
You might want to change this to \"*\", for instance." |
132 |
:version "21.1" |
:version "21.1" |
133 |
:type 'string |
:type 'string |
134 |
:group 'fortran-comment) |
:group 'fortran-comment) |
135 |
|
|
136 |
;; This used to match preprocessor lines too, but that messes up |
;; This used to match preprocessor lines too, but that messes up |
137 |
;; filling and doesn't seem to be necessary. |
;; filling and doesn't seem to be necessary. |
139 |
"^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*" |
"^[CcDd*!]\\(\\([^ \t\n]\\)\\2+\\)?[ \t]*" |
140 |
"*Regexp to match the start of a full-line comment." |
"*Regexp to match the start of a full-line comment." |
141 |
:version "21.1" |
:version "21.1" |
142 |
:type 'regexp |
:type 'regexp |
143 |
:group 'fortran-comment) |
:group 'fortran-comment) |
144 |
|
|
145 |
(defcustom fortran-directive-re |
(defcustom fortran-directive-re |
146 |
"^[ \t]*#.*" |
"^[ \t]*#.*" |
148 |
The matching text will be fontified with `font-lock-keyword-face'. |
The matching text will be fontified with `font-lock-keyword-face'. |
149 |
The matching line will be given zero indentation." |
The matching line will be given zero indentation." |
150 |
:version "21.4" |
:version "21.4" |
151 |
:type 'regexp |
:type 'regexp |
152 |
:group 'fortran-indent) |
:group 'fortran-indent) |
153 |
|
|
154 |
(defcustom fortran-minimum-statement-indent-fixed 6 |
(defcustom fortran-minimum-statement-indent-fixed 6 |
155 |
"*Minimum statement indentation for fixed format continuation style." |
"*Minimum statement indentation for fixed format continuation style." |
156 |
:type 'integer |
:type 'integer |
157 |
:group 'fortran-indent) |
:group 'fortran-indent) |
158 |
|
|
159 |
(defcustom fortran-minimum-statement-indent-tab (max tab-width 6) |
(defcustom fortran-minimum-statement-indent-tab (max tab-width 6) |
160 |
"*Minimum statement indentation for TAB format continuation style." |
"*Minimum statement indentation for TAB format continuation style." |
161 |
:type 'integer |
:type 'integer |
162 |
:group 'fortran-indent) |
:group 'fortran-indent) |
163 |
|
|
164 |
;; Note that this is documented in the v18 manuals as being a string |
;; Note that this is documented in the v18 manuals as being a string |
167 |
(defcustom fortran-comment-indent-char " " |
(defcustom fortran-comment-indent-char " " |
168 |
"*Single-character string inserted for Fortran comment indentation. |
"*Single-character string inserted for Fortran comment indentation. |
169 |
Normally a space." |
Normally a space." |
170 |
:type 'string |
:type 'string |
171 |
:group 'fortran-comment) |
:group 'fortran-comment) |
172 |
|
|
173 |
(defcustom fortran-line-number-indent 1 |
(defcustom fortran-line-number-indent 1 |
174 |
"*Maximum indentation for Fortran line numbers. |
"*Maximum indentation for Fortran line numbers. |
175 |
5 means right-justify them within their five-column field." |
5 means right-justify them within their five-column field." |
176 |
:type 'integer |
:type 'integer |
177 |
:group 'fortran-indent) |
:group 'fortran-indent) |
178 |
|
|
179 |
(defcustom fortran-check-all-num-for-matching-do nil |
(defcustom fortran-check-all-num-for-matching-do nil |
180 |
"*Non-nil causes all numbered lines to be treated as possible DO loop ends." |
"*Non-nil causes all numbered lines to be treated as possible DO loop ends." |
181 |
:type 'boolean |
:type 'boolean |
182 |
:group 'fortran) |
:group 'fortran) |
183 |
|
|
184 |
(defcustom fortran-blink-matching-if nil |
(defcustom fortran-blink-matching-if nil |
185 |
"*Non-nil causes \\[fortran-indent-line] on ENDIF statement to blink on matching IF. |
"*Non-nil causes \\[fortran-indent-line] on ENDIF to blink on matching IF. |
186 |
Also, from an ENDDO statement blink on matching DO [WHILE] statement." |
Also, from an ENDDO statement blink on matching DO [WHILE] statement." |
187 |
:type 'boolean |
:type 'boolean |
188 |
:group 'fortran) |
:group 'fortran) |
189 |
|
|
190 |
(defcustom fortran-continuation-string "$" |
(defcustom fortran-continuation-string "$" |
191 |
"*Single-character string used for Fortran continuation lines. |
"*Single-character string used for Fortran continuation lines. |
192 |
In fixed format continuation style, this character is inserted in |
In fixed format continuation style, this character is inserted in |
193 |
column 6 by \\[fortran-split-line] to begin a continuation line. |
column 6 by \\[fortran-split-line] to begin a continuation line. |
194 |
Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will |
Also, if \\[fortran-indent-line] finds this at the beginning of a |
195 |
convert the line into a continuation line of the appropriate style. |
line, it will convert the line into a continuation line of the |
196 |
Normally $." |
appropriate style. Normally $." |
197 |
:type 'string |
:type 'string |
198 |
:group 'fortran) |
:group 'fortran) |
199 |
|
|
200 |
(defcustom fortran-comment-region "c$$$" |
(defcustom fortran-comment-region "c$$$" |
201 |
"*String inserted by \\[fortran-comment-region] at start of each \ |
"*String inserted by \\[fortran-comment-region] at start of each \ |
202 |
line in region." |
line in region." |
203 |
:type 'string |
:type 'string |
204 |
:group 'fortran-comment) |
:group 'fortran-comment) |
205 |
|
|
206 |
(defcustom fortran-electric-line-number t |
(defcustom fortran-electric-line-number t |
207 |
"*Non-nil causes line number digits to be moved to the correct \ |
"*Non-nil causes line numbers to be moved to the correct column as typed." |
208 |
column as typed." |
:type 'boolean |
|
:type 'boolean |
|
209 |
:group 'fortran) |
:group 'fortran) |
210 |
|
|
211 |
(defvar fortran-column-ruler-fixed |
(defcustom fortran-column-ruler-fixed |
212 |
"0 4 6 10 20 30 40 5\ |
"0 4 6 10 20 30 40 5\ |
213 |
0 60 70\n\ |
0 60 70\n\ |
214 |
\[ ]|{ | | | | | | | | \ |
\[ ]|{ | | | | | | | | \ |
215 |
\| | | | |}\n" |
\| | | | |}\n" |
216 |
"String displayed above current line by \\[fortran-column-ruler]. |
"String displayed above current line by \\[fortran-column-ruler]. |
217 |
This variable used in fixed format mode.") |
This variable is used in fixed format mode. |
218 |
|
See the variable `fortran-column-ruler-tab' for TAB format mode." |
219 |
|
:type 'string |
220 |
|
:group 'fortran) |
221 |
|
|
222 |
(defvar fortran-column-ruler-tab |
(defcustom fortran-column-ruler-tab |
223 |
"0 810 20 30 40 5\ |
"0 810 20 30 40 5\ |
224 |
0 60 70\n\ |
0 60 70\n\ |
225 |
\[ ]| { | | | | | | | | \ |
\[ ]| { | | | | | | | | \ |
226 |
\| | | | |}\n" |
\| | | | |}\n" |
227 |
"String displayed above current line by \\[fortran-column-ruler]. |
"String displayed above current line by \\[fortran-column-ruler]. |
228 |
This variable used in TAB format mode.") |
This variable is used in TAB format mode. |
229 |
|
See the variable `fortran-column-ruler-fixed' for fixed format mode." |
230 |
|
:type 'string |
231 |
|
:group 'fortran) |
232 |
|
|
233 |
(defvar fortran-analyze-depth 100 |
(defcustom fortran-analyze-depth 100 |
234 |
"Number of lines to scan to determine whether to use fixed or TAB \ |
"Number of lines to scan to identify fixed or TAB format style." |
235 |
format style.") |
:type 'integer |
236 |
|
:group 'fortran) |
237 |
|
|
238 |
(defcustom fortran-break-before-delimiters t |
(defcustom fortran-break-before-delimiters t |
239 |
"*Non-nil causes filling to break lines before delimiters." |
"*Non-nil causes filling to break lines before delimiters. |
240 |
:type 'boolean |
Delimiters are whitespace, commas, quotes, and operators." |
241 |
|
:type 'boolean |
242 |
:group 'fortran) |
:group 'fortran) |
243 |
|
|
244 |
(defvar fortran-mode-syntax-table |
(defcustom fortran-mode-hook nil |
245 |
(let ((table (make-syntax-table))) |
"Hook run when entering Fortran mode." |
246 |
;; We might like `;' to be punctuation (g77 multi-statement |
:type 'hook |
247 |
;; lines), but that screws abbrevs. |
:group 'fortran) |
|
(modify-syntax-entry ?\; "w" table) |
|
|
(modify-syntax-entry ?\r " " table) |
|
|
(modify-syntax-entry ?+ "." table) |
|
|
(modify-syntax-entry ?- "." table) |
|
|
(modify-syntax-entry ?= "." table) |
|
|
(modify-syntax-entry ?* "." table) |
|
|
(modify-syntax-entry ?/ "." table) |
|
|
(modify-syntax-entry ?\' "\"" table) |
|
|
(modify-syntax-entry ?\" "\"" table) |
|
|
;; Consistent with GNU Fortran -- see the manual. |
|
|
(modify-syntax-entry ?\\ "\\" table) |
|
|
;; This might be better as punctuation, as for C, but this way you |
|
|
;; can treat floating-point numbers as symbols. |
|
|
(modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b' |
|
|
(modify-syntax-entry ?_ "_" table) |
|
|
(modify-syntax-entry ?$ "_" table) ; esp. VMSisms |
|
|
(modify-syntax-entry ?\! "<" table) |
|
|
(modify-syntax-entry ?\n ">" table) |
|
|
table) |
|
|
"Syntax table in use in Fortran mode buffers.") |
|
248 |
|
|
249 |
;; Comments are real pain in Fortran because there is no way to |
|
250 |
;; represent the standard comment syntax in an Emacs syntax table. |
(defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(" |
251 |
;; (We can do so for F90-style). Therefore an unmatched quote in a |
"Regexp matching the start of an IF statement.") |
252 |
;; standard comment will throw fontification off on the wrong track. |
|
253 |
;; So we do syntactic fontification with regexps. |
(defvar fortran-end-prog-re1 |
254 |
|
"end\ |
255 |
|
\\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\ |
256 |
|
\\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?" |
257 |
|
"Regexp possibly matching the end of a subprogram.") |
258 |
|
|
259 |
|
(defvar fortran-end-prog-re |
260 |
|
(concat "^[ \t0-9]*" fortran-end-prog-re1) |
261 |
|
"Regexp possibly matching the end of a subprogram, from the line start. |
262 |
|
See also `fortran-end-prog-re1'.") |
263 |
|
|
264 |
(defvar fortran-font-lock-keywords-1 nil |
(defconst fortran-type-types |
265 |
|
(concat "\\<" |
266 |
|
(mapconcat 'identity ; " " -> "[ \t]*" |
267 |
|
(split-string |
268 |
|
(regexp-opt |
269 |
|
(let ((simple-types |
270 |
|
'("character" "byte" "integer" "logical" |
271 |
|
"none" "real" "complex" |
272 |
|
"double precision" "double complex")) |
273 |
|
(structured-types '("structure" "union" "map")) |
274 |
|
(other-types '("record" "dimension" |
275 |
|
"parameter" "common" "save" |
276 |
|
"external" "intrinsic" "data" |
277 |
|
"equivalence"))) |
278 |
|
(append |
279 |
|
(mapcar (lambda (x) (concat "implicit " x)) |
280 |
|
simple-types) |
281 |
|
simple-types |
282 |
|
(mapcar (lambda (x) (concat "end " x)) |
283 |
|
structured-types) |
284 |
|
structured-types |
285 |
|
other-types)) 'paren)) |
286 |
|
"[ \t]*") "\\>") |
287 |
|
"Regexp matching Fortran types.") |
288 |
|
|
289 |
|
(defvar fortran-font-lock-keywords-1 |
290 |
|
;; Program, subroutine and function declarations, plus calls. |
291 |
|
'(("\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|\ |
292 |
|
program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?" |
293 |
|
(1 font-lock-keyword-face) |
294 |
|
(2 font-lock-function-name-face nil t))) |
295 |
"Subdued level highlighting for Fortran mode.") |
"Subdued level highlighting for Fortran mode.") |
296 |
|
|
297 |
(defvar fortran-font-lock-keywords-2 nil |
(defvar fortran-font-lock-keywords-2 |
298 |
|
(append fortran-font-lock-keywords-1 |
299 |
|
(list |
300 |
|
;; Fontify all type specifiers (must be first - see below). |
301 |
|
(cons fortran-type-types 'font-lock-type-face) |
302 |
|
;; Builtin keywords (except logical, do and goto - see below). |
303 |
|
(concat "\\<" (regexp-opt |
304 |
|
'("continue" "format" "end" "enddo" |
305 |
|
"if" "then" "else" "endif" "elseif" |
306 |
|
"while" "inquire" "stop" "return" |
307 |
|
"include" "open" "close" "read" |
308 |
|
"write" "format" "print" "select" "case" |
309 |
|
"cycle" "exit" "rewind" "backspace") |
310 |
|
'paren) "\\>") |
311 |
|
;; Builtin operators. |
312 |
|
(concat "\\." (regexp-opt |
313 |
|
'("and" "or" "not" "lt" "le" "eq" "ge" |
314 |
|
"gt" "ne" "true" "false") |
315 |
|
'paren) "\\.") |
316 |
|
;; do/goto keywords and targets, and goto tags. |
317 |
|
'("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?" |
318 |
|
(1 font-lock-keyword-face) |
319 |
|
(2 font-lock-constant-face nil t)) |
320 |
|
'("^ *\\([0-9]+\\)" . font-lock-constant-face))) |
321 |
"Medium level highlighting for Fortran mode.") |
"Medium level highlighting for Fortran mode.") |
322 |
|
|
323 |
(defvar fortran-font-lock-keywords-3 nil |
(defvar fortran-font-lock-keywords-3 |
324 |
|
(append |
325 |
|
fortran-font-lock-keywords-1 |
326 |
|
;; All type specifiers plus their declared items. |
327 |
|
(list |
328 |
|
(list (concat fortran-type-types "[ \t(/]*\\(*\\)?") |
329 |
|
;; Type specifier. |
330 |
|
'(1 font-lock-type-face) |
331 |
|
;; Declaration item (or just /.../ block name). |
332 |
|
`(font-lock-match-c-style-declaration-item-and-skip-to-next |
333 |
|
;; Start after any *(...) expression. |
334 |
|
(condition-case nil |
335 |
|
(and (match-beginning ,(1+ (regexp-opt-depth |
336 |
|
fortran-type-types))) |
337 |
|
(forward-sexp) |
338 |
|
(forward-sexp)) |
339 |
|
(error nil)) |
340 |
|
;; No need to clean up. |
341 |
|
nil |
342 |
|
;; Fontify as a variable name, functions fontified elsewhere. |
343 |
|
(1 font-lock-variable-name-face nil t)))) |
344 |
|
;; Things extra to `fortran-font-lock-keywords-3' (must be done first). |
345 |
|
(list |
346 |
|
;; Goto-like `err=label'/`end=label' in read/write statements. |
347 |
|
'(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?" |
348 |
|
(1 font-lock-keyword-face) (4 font-lock-constant-face nil t)) |
349 |
|
;; Standard continuation character and in a TAB-formatted line. |
350 |
|
'("^ \\{5\\}\\([^ 0\n]\\)" 1 font-lock-string-face) |
351 |
|
'("^\t\\([1-9]\\)" 1 font-lock-string-face)) |
352 |
|
`((,fortran-directive-re (0 font-lock-keyword-face t))) |
353 |
|
;; `fortran-font-lock-keywords-2' without types (see above). |
354 |
|
(cdr (nthcdr (length fortran-font-lock-keywords-1) |
355 |
|
fortran-font-lock-keywords-2))) |
356 |
"Gaudy level highlighting for Fortran mode.") |
"Gaudy level highlighting for Fortran mode.") |
357 |
|
|
358 |
(defvar fortran-font-lock-syntactic-keywords nil |
;; Comments are real pain in Fortran because there is no way to |
359 |
|
;; represent the standard comment syntax in an Emacs syntax table. |
360 |
|
;; (We can do so for F90-style). Therefore an unmatched quote in a |
361 |
|
;; standard comment will throw fontification off on the wrong track. |
362 |
|
;; So we do syntactic fontification with regexps. |
363 |
|
(defvar fortran-font-lock-syntactic-keywords |
364 |
|
'(("^[cd\\*]" 0 (11)) |
365 |
|
("^[^cd\\*\t\n].\\{71\\}\\([^\n]+\\)" 1 (11))) |
366 |
"`font-lock-syntactic-keywords' for Fortran. |
"`font-lock-syntactic-keywords' for Fortran. |
367 |
These get fixed-format comments fontified.") |
These get fixed-format comments fontified.") |
368 |
|
|
|
(let ((comment-chars "cd\\*") ; `d' for `debugging' comments |
|
|
(fortran-type-types |
|
|
(eval-when-compile |
|
|
(let ((re (regexp-opt |
|
|
(let ((simple-types |
|
|
'("character" "byte" "integer" "logical" |
|
|
"none" "real" "complex" |
|
|
"double precision" "double complex")) |
|
|
(structured-types '("structure" "union" "map")) |
|
|
(other-types '("record" "dimension" |
|
|
"parameter" "common" "save" |
|
|
"external" "intrinsic" "data" |
|
|
"equivalence"))) |
|
|
(append |
|
|
(mapcar (lambda (x) (concat "implicit " x)) |
|
|
simple-types) |
|
|
simple-types |
|
|
(mapcar (lambda (x) (concat "end " x)) |
|
|
structured-types) |
|
|
structured-types |
|
|
other-types))))) |
|
|
;; In the optimized regexp above, replace spaces by a |
|
|
;; regexp for optional whitespace; regexp-opt would have |
|
|
;; escaped that. |
|
|
(mapconcat #'identity (split-string re) "[ \t]*")))) |
|
|
(fortran-keywords |
|
|
(eval-when-compile |
|
|
(regexp-opt '("continue" "format" "end" "enddo" "if" "then" |
|
|
"else" "endif" "elseif" "while" "inquire" "stop" |
|
|
"return" "include" "open" "close" "read" "write" |
|
|
"format" "print" "select" "case" "cycle" "exit" |
|
|
"rewind" "backspace")))) |
|
|
(fortran-logicals |
|
|
(eval-when-compile |
|
|
(regexp-opt '("and" "or" "not" "lt" "le" "eq" "ge" "gt" "ne" |
|
|
"true" "false"))))) |
|
|
(setq fortran-font-lock-syntactic-keywords |
|
|
;; Fixed format comments. (!-style handled normally.) |
|
|
(list |
|
|
(list (concat "^[" comment-chars "]") 0 '(11)) |
|
|
(list (concat "^[^" comment-chars "\t\n]" ".\\{71\\}" |
|
|
"\\([^\n]+\\)") |
|
|
1 '(11)))) |
|
|
(setq fortran-font-lock-keywords-1 |
|
|
(list |
|
|
;; Program, subroutine and function declarations, plus calls. |
|
|
(list (concat "\\<\\(block[ \t]*data\\|call\\|entry\\|function\\|" |
|
|
"program\\|subroutine\\)\\>[ \t]*\\(\\sw+\\)?") |
|
|
'(1 font-lock-keyword-face) |
|
|
'(2 font-lock-function-name-face nil t)))) |
|
|
(setq fortran-font-lock-keywords-2 |
|
|
(append fortran-font-lock-keywords-1 |
|
|
(list |
|
|
;; Fontify all type specifiers (must be first; see below). |
|
|
(cons (concat "\\<\\(" fortran-type-types "\\)\\>") |
|
|
'font-lock-type-face) |
|
|
;; Fontify all builtin keywords (except logical, do |
|
|
;; and goto; see below). |
|
|
(concat "\\<\\(" fortran-keywords "\\)\\>") |
|
|
;; Fontify all builtin operators. |
|
|
(concat "\\.\\(" fortran-logicals "\\)\\.") |
|
|
;; Fontify do/goto keywords and targets, and goto tags. |
|
|
(list "\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)?" |
|
|
'(1 font-lock-keyword-face) |
|
|
'(2 font-lock-constant-face nil t)) |
|
|
(cons "^ *\\([0-9]+\\)" 'font-lock-constant-face)))) |
|
|
(setq fortran-font-lock-keywords-3 |
|
|
(append |
|
|
;; The list `fortran-font-lock-keywords-1'. |
|
|
fortran-font-lock-keywords-1 |
|
|
;; Fontify all type specifiers plus their declared items. |
|
|
(list |
|
|
(list (concat "\\<\\(" fortran-type-types "\\)\\>[ \t(/]*\\(*\\)?") |
|
|
;; Fontify the type specifier. |
|
|
'(1 font-lock-type-face) |
|
|
;; Fontify each declaration item (or just the /.../ block name). |
|
|
`(font-lock-match-c-style-declaration-item-and-skip-to-next |
|
|
;; Start after any *(...) expression. |
|
|
(condition-case nil |
|
|
(and (and (match-beginning ,(+ 2 (regexp-opt-depth |
|
|
fortran-type-types))) |
|
|
(forward-sexp)) |
|
|
(forward-sexp)) |
|
|
(error nil)) |
|
|
;; No need to clean up. |
|
|
nil |
|
|
;; Fontify as a variable name, functions are |
|
|
;; fontified elsewhere. |
|
|
(1 font-lock-variable-name-face nil t)))) |
|
|
;; Things extra to `fortran-font-lock-keywords-3' |
|
|
;; (must be done first). |
|
|
(list |
|
|
;; Fontify goto-like `err=label'/`end=label' in read/write |
|
|
;; statements. |
|
|
'(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?" |
|
|
(1 font-lock-keyword-face) (4 font-lock-constant-face nil t)) |
|
|
;; Highlight standard continuation character and in a |
|
|
;; TAB-formatted line. |
|
|
'("^ \\([^ 0]\\)" 1 font-lock-string-face) |
|
|
'("^\t\\([1-9]\\)" 1 font-lock-string-face)) |
|
|
(list |
|
|
;; cpp stuff (ugh) |
|
|
;;; '("^# *[a-z]+" . font-lock-keyword-face)) |
|
|
`(,fortran-directive-re (0 font-lock-keyword-face t))) |
|
|
;; The list `fortran-font-lock-keywords-2' less that for types |
|
|
;; (see above). |
|
|
(cdr (nthcdr (length fortran-font-lock-keywords-1) |
|
|
fortran-font-lock-keywords-2))))) |
|
|
|
|
369 |
(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1 |
(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1 |
370 |
"Default expressions to highlight in Fortran mode.") |
"Default expressions to highlight in Fortran mode.") |
371 |
|
|
372 |
(defvar fortran-imenu-generic-expression |
(defvar fortran-imenu-generic-expression |
373 |
;; These patterns could be confused by sequence nos. in cols 72+ and |
;; These patterns could be confused by sequence nos. in cols 72+ and |
374 |
;; don't allow continuations everywhere. |
;; don't allow continuations everywhere. |
389 |
;; Variable to index: |
;; Variable to index: |
390 |
"\\(\\sw+\\)") |
"\\(\\sw+\\)") |
391 |
3) |
3) |
392 |
;; Un-named block data |
;; Un-named block data. |
393 |
(list nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1)) |
'(nil "^\\s-+\\(block\\s-*data\\)\\s-*$" 1)) |
394 |
"Imenu generic expression for `imenu-default-create-index-function'.") |
"Value for `imenu-generic-expression' in Fortran mode.") |
395 |
|
|
396 |
|
|
397 |
|
(defvar fortran-mode-syntax-table |
398 |
|
(let ((table (make-syntax-table))) |
399 |
|
;; We might like `;' to be punctuation (g77 multi-statement |
400 |
|
;; lines), but that screws abbrevs. |
401 |
|
(modify-syntax-entry ?\; "w" table) |
402 |
|
(modify-syntax-entry ?\r " " table) |
403 |
|
(modify-syntax-entry ?+ "." table) |
404 |
|
(modify-syntax-entry ?- "." table) |
405 |
|
(modify-syntax-entry ?= "." table) |
406 |
|
(modify-syntax-entry ?* "." table) |
407 |
|
(modify-syntax-entry ?/ "." table) |
408 |
|
(modify-syntax-entry ?\' "\"" table) |
409 |
|
(modify-syntax-entry ?\" "\"" table) |
410 |
|
;; Consistent with GNU Fortran -- see the manual. |
411 |
|
(modify-syntax-entry ?\\ "\\" table) |
412 |
|
;; This might be better as punctuation, as for C, but this way you |
413 |
|
;; can treat floating-point numbers as symbols. |
414 |
|
(modify-syntax-entry ?. "_" table) ; e.g. `a.ne.b' |
415 |
|
(modify-syntax-entry ?_ "_" table) |
416 |
|
(modify-syntax-entry ?$ "_" table) ; esp. VMSisms |
417 |
|
(modify-syntax-entry ?\! "<" table) |
418 |
|
(modify-syntax-entry ?\n ">" table) |
419 |
|
table) |
420 |
|
"Syntax table used in Fortran mode.") |
421 |
|
|
422 |
|
(defvar fortran-gud-syntax-table |
423 |
|
(let ((st (make-syntax-table fortran-mode-syntax-table))) |
424 |
|
(modify-syntax-entry ?\n "." st) |
425 |
|
st) |
426 |
|
"Syntax table used to parse Fortran expressions for printing in GUD.") |
427 |
|
|
428 |
(defvar fortran-mode-map |
(defvar fortran-mode-map |
429 |
(let ((map (make-sparse-keymap))) |
(let ((map (make-sparse-keymap))) |
430 |
(define-key map ";" 'fortran-abbrev-start) |
(define-key map ";" 'fortran-abbrev-start) |
431 |
(define-key map "\C-c;" 'fortran-comment-region) |
(define-key map "\C-c;" 'fortran-comment-region) |
432 |
(define-key map "\M-;" 'fortran-indent-comment) |
(define-key map "\M-;" 'fortran-indent-comment) |
433 |
(define-key map "\M-\n" 'fortran-split-line) |
(define-key map "\M-\n" 'fortran-split-line) |
434 |
(define-key map "\M-\C-q" 'fortran-indent-subprogram) |
(define-key map "\M-\C-q" 'fortran-indent-subprogram) |
435 |
(define-key map "\C-c\C-w" 'fortran-window-create-momentarily) |
(define-key map "\C-c\C-w" 'fortran-window-create-momentarily) |
436 |
(define-key map "\C-c\C-r" 'fortran-column-ruler) |
(define-key map "\C-c\C-r" 'fortran-column-ruler) |
437 |
(define-key map "\C-c\C-p" 'fortran-previous-statement) |
(define-key map "\C-c\C-p" 'fortran-previous-statement) |
438 |
(define-key map "\C-c\C-n" 'fortran-next-statement) |
(define-key map "\C-c\C-n" 'fortran-next-statement) |
439 |
(define-key map "\C-c\C-d" 'fortran-join-line) ; like f90 |
(define-key map "\C-c\C-d" 'fortran-join-line) ; like f90 |
440 |
(define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation |
(define-key map "\M-^" 'fortran-join-line) ; subvert delete-indentation |
441 |
(define-key map "0" 'fortran-electric-line-number) |
(define-key map "0" 'fortran-electric-line-number) |
442 |
(define-key map "1" 'fortran-electric-line-number) |
(define-key map "1" 'fortran-electric-line-number) |
443 |
(define-key map "2" 'fortran-electric-line-number) |
(define-key map "2" 'fortran-electric-line-number) |
449 |
(define-key map "8" 'fortran-electric-line-number) |
(define-key map "8" 'fortran-electric-line-number) |
450 |
(define-key map "9" 'fortran-electric-line-number) |
(define-key map "9" 'fortran-electric-line-number) |
451 |
|
|
452 |
;; Menu |
(easy-menu-define fortran-menu map "Menu for Fortran mode." |
453 |
(easy-menu-define |
`("Fortran" |
454 |
fortran-mode-menu map "" |
["Manual" (info "(emacs)Fortran")] |
455 |
`("Fortran" |
("Customization" |
456 |
["Manual" (info "(emacs)Fortran")] |
,(custom-menu-create 'fortran) |
457 |
("Customization" |
["Set" Custom-set t] |
458 |
,(custom-menu-create 'fortran) |
["Save" Custom-save t] |
459 |
["Set" Custom-set t] |
["Reset to Current" Custom-reset-current t] |
460 |
["Save" Custom-save t] |
["Reset to Saved" Custom-reset-saved t] |
461 |
["Reset to Current" Custom-reset-current t] |
["Reset to Standard Settings" Custom-reset-standard t] |
462 |
["Reset to Saved" Custom-reset-saved t] |
) |
463 |
["Reset to Standard Settings" Custom-reset-standard t]) |
"--" |
464 |
"----" |
["Comment Region" fortran-comment-region mark-active] |
465 |
["Toggle Auto-fill" auto-fill-mode :style toggle |
["Uncomment Region" |
466 |
:selected auto-fill-function] |
(fortran-comment-region (region-beginning) (region-end) 1) |
467 |
["Toggle abbrev-mode" abbrev-mode :style toggle :selected abbrev-mode] |
mark-active] |
468 |
"----" |
["Indent Region" indent-region mark-active] |
469 |
["Comment-out Region" fortran-comment-region mark-active] |
["Indent Subprogram" fortran-indent-subprogram t] |
470 |
["Uncomment-out region" |
"--" |
471 |
(fortran-comment-region (region-beginning) (region-end) 1) |
["Beginning of Subprogram" fortran-beginning-of-subprogram t] |
472 |
mark-active] |
["End of Subprogram" fortran-end-of-subprogram t] |
473 |
["Indent Region" indent-region mark-active] |
("Mark" |
474 |
["Indent Subprogram" fortran-indent-subprogram t] |
["Subprogram" mark-defun t] |
475 |
"----" |
["IF Block" fortran-mark-if t] |
476 |
["Beginning of Subprogram" fortran-beginning-of-subprogram t] |
["DO Block" fortran-mark-do t] |
477 |
["End of Subprogram" fortran-end-of-subprogram t] |
) |
478 |
("Mark" |
["Narrow to Subprogram" narrow-to-defun t] |
479 |
["Subprogram" mark-defun t] |
["Widen" widen t] |
480 |
["IF Block" fortran-mark-if t] |
"--" |
481 |
["DO Block" fortran-mark-do t]) |
["Temporary column ruler" fortran-column-ruler t] |
482 |
["Narrow to Subprogram" narrow-to-defun t] |
["72-column window" fortran-window-create t] |
483 |
["Widen" widen t] |
["Full Width Window" |
484 |
"----" |
(enlarge-window-horizontally (- (frame-width) (window-width))) |
485 |
["Temporary column ruler" fortran-column-ruler t] |
(< (window-width) (frame-width))] |
486 |
["72-column window" fortran-window-create t] |
["Momentary 72-column window" fortran-window-create-momentarily t] |
487 |
["Full Width Window" |
"--" |
488 |
(enlarge-window-horizontally (- (frame-width) (window-width))) |
["Break Line at Point" fortran-split-line t] |
489 |
(< (window-width) (frame-width))] |
["Join Line" fortran-join-line t] |
490 |
["Momentary 72-column window" fortran-window-create-momentarily t] |
["Fill Statement/Comment" fill-paragraph t] |
491 |
"----" |
"--" |
492 |
["Break Line at Point" fortran-split-line t] |
["Toggle auto-fill" auto-fill-mode :selected auto-fill-function |
493 |
["Join Line" fortran-join-line t] |
:style toggle] |
494 |
["Fill Statement/Comment" fill-paragraph t] |
["Toggle abbrev-mode" abbrev-mode :selected abbrev-mode |
495 |
"----" |
:style toggle] |
496 |
["Add imenu menu" |
["Add imenu Menu" imenu-add-menubar-index |
497 |
imenu-add-menubar-index (not (and (boundp 'imenu--index-alist) |
:active (not (lookup-key (current-local-map) [menu-bar index])) |
498 |
imenu--index-alist))])) |
:included (fboundp 'imenu-add-to-menubar)])) |
499 |
map) |
map) |
500 |
"Keymap used in Fortran mode.") |
"Keymap used in Fortran mode.") |
501 |
|
|
502 |
|
|
503 |
(defvar fortran-mode-abbrev-table |
(defvar fortran-mode-abbrev-table |
504 |
(let (abbrevs-changed) |
(let (abbrevs-changed) |
572 |
(";w" "write" ) |
(";w" "write" ) |
573 |
(";wh" "where" ))) |
(";wh" "where" ))) |
574 |
fortran-mode-abbrev-table)) |
fortran-mode-abbrev-table)) |
|
|
|
|
(eval-when-compile ; silence compiler |
|
|
(defvar imenu-case-fold-search) |
|
|
(defvar imenu-syntax-alist)) |
|
575 |
|
|
576 |
(defcustom fortran-mode-hook nil |
|
|
"Hook run by Fortran mode." |
|
|
:type 'hook |
|
|
:group 'fortran) |
|
577 |
|
|
578 |
;;;###autoload |
;;;###autoload |
579 |
(defun fortran-mode () |
(defun fortran-mode () |
580 |
"Major mode for editing Fortran code. |
"Major mode for editing Fortran code in fixed format. |
581 |
|
For free format code, use `f90-mode'. |
582 |
|
|
583 |
\\[fortran-indent-line] indents the current Fortran line correctly. |
\\[fortran-indent-line] indents the current Fortran line correctly. |
584 |
DO statements must not share a common CONTINUE. |
Note that DO statements must not share a common CONTINUE. |
585 |
|
|
586 |
Type ;? or ;\\[help-command] to display a list of built-in abbrevs for |
Type ;? or ;\\[help-command] to display a list of built-in abbrevs for\ |
587 |
Fortran keywords. |
Fortran keywords. |
588 |
|
|
589 |
Key definitions: |
Key definitions: |
590 |
\\{fortran-mode-map} |
\\{fortran-mode-map} |
591 |
|
|
592 |
Variables controlling indentation style and extra features: |
Variables controlling indentation style and extra features: |
593 |
|
|
594 |
`comment-start' |
`comment-start' |
595 |
If you want to use comments starting with `!', |
To use comments starting with `!', set this to the string \"!\". |
596 |
set this to the string \"!\". |
`fortran-do-indent' |
597 |
`fortran-do-indent' |
Extra indentation within DO blocks (default 3). |
598 |
Extra indentation within do blocks. (default 3) |
`fortran-if-indent' |
599 |
`fortran-if-indent' |
Extra indentation within IF blocks (default 3). |
600 |
Extra indentation within if blocks. (default 3) |
`fortran-structure-indent' |
601 |
`fortran-structure-indent' |
Extra indentation within STRUCTURE, UNION, MAP and INTERFACE blocks. |
602 |
Extra indentation within structure, union, map and interface blocks. |
(default 3) |
603 |
(default 3) |
`fortran-continuation-indent' |
604 |
`fortran-continuation-indent' |
Extra indentation applied to continuation statements (default 5). |
605 |
Extra indentation applied to continuation statements. (default 5) |
`fortran-comment-line-extra-indent' |
606 |
`fortran-comment-line-extra-indent' |
Amount of extra indentation for text in full-line comments (default 0). |
607 |
Amount of extra indentation for text within full-line comments. (default 0) |
`fortran-comment-indent-style' |
608 |
`fortran-comment-indent-style' |
How to indent the text in full-line comments. Allowed values are: |
609 |
nil means don't change indentation of text in full-line comments, |
nil don't change the indentation |
610 |
fixed means indent that text at `fortran-comment-line-extra-indent' beyond |
fixed indent to `fortran-comment-line-extra-indent' beyond the |
611 |
the value of `fortran-minimum-statement-indent-fixed' (for fixed |
value of either |
612 |
format continuation style) or `fortran-minimum-statement-indent-tab' |
`fortran-minimum-statement-indent-fixed' (fixed format) or |
613 |
(for TAB format continuation style). |
`fortran-minimum-statement-indent-tab' (TAB format), |
614 |
relative means indent at `fortran-comment-line-extra-indent' beyond the |
depending on the continuation format in use. |
615 |
|
relative indent to `fortran-comment-line-extra-indent' beyond the |
616 |
indentation for a line of code. |
indentation for a line of code. |
617 |
(default 'fixed) |
(default 'fixed) |
618 |
`fortran-comment-indent-char' |
`fortran-comment-indent-char' |
619 |
Single-character string to be inserted instead of space for |
Single-character string to be inserted instead of space for |
620 |
full-line comment indentation. (default \" \") |
full-line comment indentation (default \" \"). |
621 |
`fortran-minimum-statement-indent-fixed' |
`fortran-minimum-statement-indent-fixed' |
622 |
Minimum indentation for Fortran statements in fixed format mode. (def.6) |
Minimum indentation for statements in fixed format mode (default 6). |
623 |
`fortran-minimum-statement-indent-tab' |
`fortran-minimum-statement-indent-tab' |
624 |
Minimum indentation for Fortran statements in TAB format mode. (default 9) |
Minimum indentation for statements in TAB format mode (default 9). |
625 |
`fortran-line-number-indent' |
`fortran-line-number-indent' |
626 |
Maximum indentation for line numbers. A line number will get |
Maximum indentation for line numbers (default 1). A line number will |
627 |
less than this much indentation if necessary to avoid reaching |
get less than this much indentation if necessary to avoid reaching |
628 |
column 5. (default 1) |
column 5. |
629 |
`fortran-check-all-num-for-matching-do' |
`fortran-check-all-num-for-matching-do' |
630 |
Non-nil causes all numbered lines to be treated as possible \"continue\" |
Non-nil causes all numbered lines to be treated as possible \"continue\" |
631 |
statements. (default nil) |
statements (default nil). |
632 |
`fortran-blink-matching-if' |
`fortran-blink-matching-if' |
633 |
Non-nil causes \\[fortran-indent-line] on an ENDIF statement to blink on |
Non-nil causes \\[fortran-indent-line] on an ENDIF (or ENDDO) statement |
634 |
matching IF. Also, from an ENDDO statement, blink on matching DO [WHILE] |
to blink on the matching IF (or DO [WHILE]). (default nil) |
635 |
statement. (default nil) |
`fortran-continuation-string' |
636 |
`fortran-continuation-string' |
Single-character string to be inserted in column 5 of a continuation |
637 |
Single-character string to be inserted in column 5 of a continuation |
line (default \"$\"). |
638 |
line. (default \"$\") |
`fortran-comment-region' |
639 |
`fortran-comment-region' |
String inserted by \\[fortran-comment-region] at start of each line in |
640 |
String inserted by \\[fortran-comment-region] at start of each line in |
the region (default \"c$$$\"). |
641 |
region. (default \"c$$$\") |
`fortran-electric-line-number' |
642 |
`fortran-electric-line-number' |
Non-nil causes line number digits to be moved to the correct column |
643 |
Non-nil causes line number digits to be moved to the correct column |
as typed (default t). |
644 |
as typed. (default t) |
`fortran-break-before-delimiters' |
645 |
`fortran-break-before-delimiters' |
Non-nil causes lines to be broken before delimiters (default t). |
|
Non-nil causes lines to be broken before delimiters. |
|
|
(default t) |
|
646 |
|
|
647 |
Turning on Fortran mode calls the value of the variable `fortran-mode-hook' |
Turning on Fortran mode calls the value of the variable `fortran-mode-hook' |
648 |
with no args, if that value is non-nil." |
with no args, if that value is non-nil." |
649 |
(interactive) |
(interactive) |
650 |
(kill-all-local-variables) |
(kill-all-local-variables) |
651 |
(setq local-abbrev-table fortran-mode-abbrev-table) |
(setq major-mode 'fortran-mode |
652 |
|
mode-name "Fortran" |
653 |
|
local-abbrev-table fortran-mode-abbrev-table) |
654 |
(set-syntax-table fortran-mode-syntax-table) |
(set-syntax-table fortran-mode-syntax-table) |
655 |
;; Font Lock mode support. |
(use-local-map fortran-mode-map) |
656 |
(make-local-variable 'font-lock-defaults) |
(set (make-local-variable 'indent-line-function) 'fortran-indent-line) |
657 |
(setq font-lock-defaults '((fortran-font-lock-keywords |
(set (make-local-variable 'indent-region-function) |
658 |
fortran-font-lock-keywords-1 |
(lambda (start end) |
659 |
fortran-font-lock-keywords-2 |
(let (fortran-blink-matching-if ; avoid blinking delay |
660 |
fortran-font-lock-keywords-3) |
indent-region-function) |
661 |
nil t ((?/ . "$/") ("_$" . "w")) |
(indent-region start end nil)))) |
662 |
fortran-beginning-of-subprogram)) |
(set (make-local-variable 'require-final-newline) t) |
663 |
(set (make-local-variable 'font-lock-syntactic-keywords) |
;; The syntax tables don't understand the column-0 comment-markers. |
664 |
fortran-font-lock-syntactic-keywords) |
(set (make-local-variable 'comment-use-syntax) nil) |
665 |
(make-local-variable 'fortran-break-before-delimiters) |
(set (make-local-variable 'comment-padding) "$$$") |
666 |
(setq fortran-break-before-delimiters t) |
(set (make-local-variable 'comment-start) fortran-comment-line-start) |
|
(make-local-variable 'indent-line-function) |
|
|
(setq indent-line-function 'fortran-indent-line) |
|
|
(make-local-variable 'comment-indent-function) |
|
|
(setq comment-indent-function 'fortran-comment-indent) |
|
667 |
(set (make-local-variable 'comment-start-skip) |
(set (make-local-variable 'comment-start-skip) |
668 |
;; We can't reuse `fortran-comment-line-start-skip' directly because |
;; We can't reuse `fortran-comment-line-start-skip' directly because |
669 |
;; it contains backrefs whereas we need submatch-1 to end at the |
;; it contains backrefs whereas we need submatch-1 to end at the |
670 |
;; beginning of the comment delimiter. |
;; beginning of the comment delimiter. |
671 |
;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)") |
;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)") |
672 |
"\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*") |
"\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*") |
673 |
(set (make-local-variable 'comment-padding) "$$$") |
(set (make-local-variable 'comment-indent-function) 'fortran-comment-indent) |
674 |
(set (make-local-variable 'comment-start) fortran-comment-line-start) |
(set (make-local-variable 'abbrev-all-caps) t) |
675 |
;; The syntax tables don't understand the column-0 comment-markers. |
(set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill) |
676 |
(set (make-local-variable 'comment-use-syntax) nil) |
(set (make-local-variable 'indent-tabs-mode) (fortran-analyze-file-format)) |
677 |
(make-local-variable 'require-final-newline) |
(setq mode-line-process '(indent-tabs-mode fortran-tab-mode-string)) |
|
(setq require-final-newline t) |
|
|
(make-local-variable 'abbrev-all-caps) |
|
|
(setq abbrev-all-caps t) |
|
|
(make-local-variable 'indent-tabs-mode) |
|
|
(setq indent-tabs-mode nil) |
|
|
;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead?? |
|
678 |
(set (make-local-variable 'fill-column) 72) |
(set (make-local-variable 'fill-column) 72) |
|
(use-local-map fortran-mode-map) |
|
|
(setq mode-name "Fortran") |
|
|
(setq major-mode 'fortran-mode) |
|
|
(make-local-variable 'fortran-comment-line-extra-indent) |
|
|
(make-local-variable 'fortran-minimum-statement-indent-fixed) |
|
|
(make-local-variable 'fortran-minimum-statement-indent-tab) |
|
|
(make-local-variable 'fortran-column-ruler-fixed) |
|
|
(make-local-variable 'fortran-column-ruler-tab) |
|
|
(setq fortran-tab-mode-string " TAB-format") |
|
|
(setq indent-tabs-mode (fortran-analyze-file-format)) |
|
|
(setq imenu-case-fold-search t) |
|
|
(setq imenu-generic-expression fortran-imenu-generic-expression) |
|
|
(setq imenu-syntax-alist '(("_$" . "w"))) |
|
679 |
(set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph) |
(set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph) |
680 |
(set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill) |
(set (make-local-variable 'font-lock-defaults) |
681 |
(set (make-local-variable 'indent-line-function) 'fortran-indent-line) |
'((fortran-font-lock-keywords |
682 |
(set (make-local-variable 'indent-region-function) |
fortran-font-lock-keywords-1 |
683 |
(lambda (start end) |
fortran-font-lock-keywords-2 |
684 |
(let (fortran-blink-matching-if ; avoid blinking delay |
fortran-font-lock-keywords-3) |
685 |
indent-region-function) |
nil t ((?/ . "$/") ("_$" . "w")) |
686 |
(indent-region start end nil)))) |
fortran-beginning-of-subprogram)) |
687 |
|
(set (make-local-variable 'font-lock-syntactic-keywords) |
688 |
|
fortran-font-lock-syntactic-keywords) |
689 |
|
(set (make-local-variable 'imenu-case-fold-search) t) |
690 |
|
(set (make-local-variable 'imenu-generic-expression) |
691 |
|
fortran-imenu-generic-expression) |
692 |
|
(set (make-local-variable 'imenu-syntax-alist) '(("_$" . "w"))) |
693 |
(set (make-local-variable 'beginning-of-defun-function) |
(set (make-local-variable 'beginning-of-defun-function) |
694 |
#'fortran-beginning-of-subprogram) |
#'fortran-beginning-of-subprogram) |
695 |
(set (make-local-variable 'end-of-defun-function) |
(set (make-local-variable 'end-of-defun-function) |
697 |
(set (make-local-variable 'add-log-current-defun-function) |
(set (make-local-variable 'add-log-current-defun-function) |
698 |
#'fortran-current-defun) |
#'fortran-current-defun) |
699 |
(set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search) |
(set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search) |
700 |
|
(set (make-local-variable 'gud-find-expr-function) 'fortran-gud-find-expr) |
701 |
(run-hooks 'fortran-mode-hook)) |
(run-hooks 'fortran-mode-hook)) |
702 |
|
|
703 |
|
|
704 |
|
(defun fortran-gud-find-expr () |
705 |
|
;; Consider \n as punctuation (end of expression). |
706 |
|
(with-syntax-table fortran-gud-syntax-table |
707 |
|
(gud-find-c-expr))) |
708 |
|
|
709 |
(defsubst fortran-comment-indent () |
(defsubst fortran-comment-indent () |
710 |
(save-excursion |
"Return the indentation appropriate for the current comment line. |
711 |
(if (looking-at fortran-comment-line-start-skip) 0 |
This is 0 for a line matching `fortran-comment-line-start-skip', else |
712 |
|
the value of `comment-column' (leaving at least one space after code)." |
713 |
|
(if (looking-at fortran-comment-line-start-skip) 0 |
714 |
|
(save-excursion |
715 |
(skip-chars-backward " \t") |
(skip-chars-backward " \t") |
716 |
(max (+ 1 (current-column)) |
(max (1+ (current-column)) comment-column)))) |
|
comment-column)))) |
|
717 |
|
|
718 |
(defun fortran-indent-comment () |
(defun fortran-indent-comment () |
719 |
"Align or create comment on current line. |
"Align or create comment on current line. |
720 |
Existing comments of all types are recognized and aligned. |
Existing comments of all types are recognized and aligned. |
721 |
If the line has no comment, a side-by-side comment is inserted and aligned |
If the line has no comment, a side-by-side comment is inserted and aligned, |
722 |
if the value of `comment-start' is not nil and allows such comments. |
if the value of `comment-start' is not nil and allows such comments. |
723 |
Otherwise, a separate-line comment is inserted, on this line |
Otherwise, a separate-line comment is inserted, on this line |
724 |
or on a new line inserted before this line if this line is not blank." |
or on a new line inserted before this line if this line is not blank." |
725 |
(interactive) |
(interactive "*") |
726 |
(beginning-of-line) |
(beginning-of-line) |
727 |
;; Recognize existing comments of either kind. |
;; Recognize existing comments of either kind. |
728 |
(cond ((fortran-find-comment-start-skip 'all) |
(cond ((fortran-find-comment-start-skip 'all) |
729 |
(goto-char (match-beginning 0)) |
(goto-char (match-beginning 0)) |
730 |
(if (bolp) |
(if (bolp) |
731 |
(fortran-indent-line) |
(fortran-indent-line) |
732 |
(if (not (= (current-column) |
(unless (= (current-column) (fortran-comment-indent)) |
733 |
(fortran-comment-indent))) |
(delete-horizontal-space) |
734 |
(progn (delete-horizontal-space) |
(indent-to (fortran-comment-indent))))) |
|
(indent-to (fortran-comment-indent)))))) |
|
735 |
;; No existing comment. |
;; No existing comment. |
736 |
;; If side-by-side comments are defined, insert one, |
;; If side-by-side comments are defined, insert one, |
737 |
;; unless line is now blank. |
;; unless line is now blank. |
755 |
(- (fortran-calculate-indent) (current-column)))))) |
(- (fortran-calculate-indent) (current-column)))))) |
756 |
|
|
757 |
(defun fortran-comment-region (beg-region end-region arg) |
(defun fortran-comment-region (beg-region end-region arg) |
758 |
"Comments every line in the region. |
"Comment every line in the region. |
759 |
Puts `fortran-comment-region' at the beginning of every line in the region. |
Inserts the string variable `fortran-comment-region' at the beginning of |
760 |
BEG-REGION and END-REGION are args which specify the region boundaries. |
every line in the region. |
761 |
|
BEG-REGION and END-REGION specify the region boundaries. |
762 |
With non-nil ARG, uncomments the region." |
With non-nil ARG, uncomments the region." |
763 |
(interactive "*r\nP") |
(interactive "*r\nP") |
764 |
(let ((end-region-mark (copy-marker end-region)) |
(let ((end-region-mark (copy-marker end-region)) |
765 |
(save-point (point-marker))) |
(save-point (point-marker))) |
766 |
(goto-char beg-region) |
(goto-char beg-region) |
767 |
(beginning-of-line) |
(beginning-of-line) |
768 |
(if (not arg) ;comment the region |
(if arg |
769 |
(progn (insert fortran-comment-region) |
(let ((com (regexp-quote fortran-comment-region))) ; uncomment |
770 |
(while (and (= (forward-line 1) 0) |
(if (looking-at com) |
771 |
(< (point) end-region-mark)) |
(delete-region (point) (match-end 0))) |
772 |
(insert fortran-comment-region))) |
(while (and (zerop (forward-line 1)) |
773 |
(let ((com (regexp-quote fortran-comment-region))) ;uncomment the region |
(< (point) end-region-mark)) |
774 |
(if (looking-at com) |
(if (looking-at com) |
775 |
(delete-region (point) (match-end 0))) |
(delete-region (point) (match-end 0))))) |
776 |
(while (and (= (forward-line 1) 0) |
(insert fortran-comment-region) ; comment |
777 |
(< (point) end-region-mark)) |
(while (and (zerop (forward-line 1)) |
778 |
(if (looking-at com) |
(< (point) end-region-mark)) |
779 |
(delete-region (point) (match-end 0)))))) |
(insert fortran-comment-region))) |
780 |
(goto-char save-point) |
(goto-char save-point) |
781 |
(set-marker end-region-mark nil) |
(set-marker end-region-mark nil) |
782 |
(set-marker save-point nil))) |
(set-marker save-point nil))) |
783 |
|
|
784 |
|
|
785 |
(defun fortran-abbrev-start () |
(defun fortran-abbrev-start () |
786 |
"Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. |
"Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. |
787 |
Any other key combination is executed normally." |
Any other key combination is executed normally." |
788 |
(interactive) |
(interactive "*") |
789 |
(let (c) |
(insert last-command-char) |
790 |
(insert last-command-char) |
(let (char event) |
791 |
(if (or (eq (setq c (read-event)) ??) ;insert char if not equal to `?' |
(if (fboundp 'next-command-event) ; XEmacs |
792 |
(eq c help-char)) |
(setq event (next-command-event) |
793 |
|
char (event-to-character event)) |
794 |
|
(setq event (read-event) |
795 |
|
char event)) |
796 |
|
;; Insert char if not equal to `?', or if abbrev-mode is off. |
797 |
|
(if (and abbrev-mode (or (eq char ??) (eq char help-char))) |
798 |
(fortran-abbrev-help) |
(fortran-abbrev-help) |
799 |
(setq unread-command-events (list c))))) |
(setq unread-command-events (list event))))) |
800 |
|
|
801 |
(defun fortran-abbrev-help () |
(defun fortran-abbrev-help () |
802 |
"List the currently defined abbrevs in Fortran mode." |
"List the currently defined abbrevs in Fortran mode." |
806 |
(message "Listing abbrev table...done")) |
(message "Listing abbrev table...done")) |
807 |
|
|
808 |
(defun fortran-prepare-abbrev-list-buffer () |
(defun fortran-prepare-abbrev-list-buffer () |
809 |
|
"Create a buffer listing the Fortran mode abbreviations." |
810 |
(save-excursion |
(save-excursion |
811 |
(set-buffer (get-buffer-create "*Abbrevs*")) |
(set-buffer (get-buffer-create "*Abbrevs*")) |
812 |
(erase-buffer) |
(erase-buffer) |
818 |
|
|
819 |
(defun fortran-column-ruler () |
(defun fortran-column-ruler () |
820 |
"Insert a column ruler momentarily above current line, till next keystroke. |
"Insert a column ruler momentarily above current line, till next keystroke. |
821 |
The ruler is defined by the value of `fortran-column-ruler-fixed' when in fixed |
The ruler is defined by the value of `fortran-column-ruler-fixed' in fixed |
822 |
format mode, and `fortran-column-ruler-tab' when in TAB format mode. |
format mode, and `fortran-column-ruler-tab' in TAB format mode. |
823 |
The key typed is executed unless it is SPC." |
The next key typed is executed unless it is SPC." |
824 |
(interactive) |
(interactive) |
825 |
(momentary-string-display |
(momentary-string-display |
826 |
(if indent-tabs-mode |
(if indent-tabs-mode |
871 |
|
|
872 |
(defun fortran-split-line () |
(defun fortran-split-line () |
873 |
"Break line at point and insert continuation marker and alignment." |
"Break line at point and insert continuation marker and alignment." |
874 |
(interactive) |
(interactive "*") |
875 |
(delete-horizontal-space) |
(delete-horizontal-space) |
876 |
(if (save-excursion |
(if (save-excursion |
877 |
(let ((pos (point))) |
(let ((pos (point))) |
881 |
(insert ?\n (match-string 0)) |
(insert ?\n (match-string 0)) |
882 |
(if indent-tabs-mode |
(if indent-tabs-mode |
883 |
(insert ?\n ?\t (fortran-numerical-continuation-char)) |
(insert ?\n ?\t (fortran-numerical-continuation-char)) |
884 |
(insert "\n " fortran-continuation-string))) ; Space after \n important |
(insert "\n " fortran-continuation-string))) ; space after \n important |
885 |
(fortran-indent-line)) ; when the cont string is C, c or *. |
(fortran-indent-line)) ; when cont string is C, c or * |
886 |
|
|
887 |
(defun fortran-remove-continuation () |
(defun fortran-remove-continuation () |
888 |
(if (looking-at "\\( [^ 0\n]\\|\t[1-9]\\|&\\)") |
"Delete any Fortran continuation characters at point. |
889 |
(progn (replace-match "") |
Returns t if anything actually deleted." |
890 |
(delete-indentation) |
(when (looking-at "\\( \\{5\\}[^ 0\n]\\|\t[1-9]\\|&\\)") |
891 |
t))) |
(replace-match "") |
892 |
|
(delete-indentation) |
893 |
|
t)) |
894 |
|
|
895 |
(defun fortran-join-line (arg) |
(defun fortran-join-line (arg) |
896 |
"Join current line to the previous one and re-indent. |
"Join current line to the previous one and re-indent. |
911 |
|
|
912 |
(defun fortran-numerical-continuation-char () |
(defun fortran-numerical-continuation-char () |
913 |
"Return a digit for tab-digit style of continuation lines. |
"Return a digit for tab-digit style of continuation lines. |
914 |
If, previous line is a tab-digit continuation line, returns that digit |
If previous line is a tab-digit continuation line, return that digit |
915 |
plus one. Otherwise return 1. Zero not allowed." |
plus one, otherwise return 1. Zero not allowed." |
916 |
(save-excursion |
(save-excursion |
917 |
(forward-line -1) |
(forward-line -1) |
918 |
(if (looking-at "\t[1-9]") |
(if (looking-at "\t[1-9]") |
919 |
(+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9)) |
(+ ?1 (% (- (char-after (1+ (point))) ?0) 9)) |
920 |
?1))) |
?1))) |
921 |
|
|
922 |
(put 'fortran-electric-line-number 'delete-selection t) |
(put 'fortran-electric-line-number 'delete-selection t) |
923 |
(defun fortran-electric-line-number (arg) |
(defun fortran-electric-line-number (arg) |
924 |
"Self insert, but if part of a Fortran line number indent it automatically. |
"Self insert, but if part of a Fortran line number indent it automatically. |
925 |
Auto-indent does not happen if a numeric ARG is used." |
Auto-indent does not happen if a numeric ARG is used." |
926 |
(interactive "P") |
(interactive "*P") |
927 |
(if (or arg (not fortran-electric-line-number)) |
(if (or arg (not fortran-electric-line-number)) |
928 |
(if arg |
(if arg |
929 |
(self-insert-command (prefix-numeric-value arg)) |
(self-insert-command (prefix-numeric-value arg)) |
931 |
(if (or (and (= 5 (current-column)) |
(if (or (and (= 5 (current-column)) |
932 |
(save-excursion |
(save-excursion |
933 |
(beginning-of-line) |
(beginning-of-line) |
934 |
(looking-at " \\{5\\}"))) ;In col 5 with only spaces to left. |
;; In col 5 with only spaces to the left. |
935 |
|
(looking-at " \\{5\\}"))) |
936 |
(and (= (if indent-tabs-mode |
(and (= (if indent-tabs-mode |
937 |
fortran-minimum-statement-indent-tab |
fortran-minimum-statement-indent-tab |
938 |
fortran-minimum-statement-indent-fixed) (current-column)) |
fortran-minimum-statement-indent-fixed) (current-column)) |
939 |
(eq ?\t (char-after (line-beginning-position))) ;In col 8 |
;; In col 8 with a single tab to the left. |
940 |
; with a single tab to the left. |
(eq ?\t (char-after (line-beginning-position))) |
941 |
(not (or (eq last-command 'fortran-indent-line) |
(not (or (eq last-command 'fortran-indent-line) |
942 |
(eq last-command |
(eq last-command |
943 |
'fortran-indent-new-line)))) |
'fortran-indent-new-line)))) |
944 |
(save-excursion |
(save-excursion |
945 |
(re-search-backward "[^ \t0-9]" |
(re-search-backward "[^ \t0-9]" |
946 |
(line-beginning-position) |
(line-beginning-position) |
947 |
t)) ;not a line number |
t)) ; not a line number |
948 |
(looking-at "[0-9]")) ;within a line number |
(looking-at "[0-9]")) ; within a line number |
949 |
(self-insert-command (prefix-numeric-value arg)) |
(self-insert-command (prefix-numeric-value arg)) |
950 |
(skip-chars-backward " \t") |
(skip-chars-backward " \t") |
951 |
(insert last-command-char) |
(insert last-command-char) |
952 |
(fortran-indent-line)))) |
(fortran-indent-line)))) |
|
|
|
|
(defvar fortran-end-prog-re1 |
|
|
"end\ |
|
|
\\([ \t]*\\(program\\|subroutine\\|function\\|block[ \t]*data\\)\\>\ |
|
|
\\([ \t]*\\(\\sw\\|\\s_\\)+\\)?\\)?") |
|
|
(defvar fortran-end-prog-re |
|
|
(concat "^[ \t0-9]*" fortran-end-prog-re1) |
|
|
"Regexp possibly marking subprogram end.") |
|
953 |
|
|
954 |
|
|
955 |
(defun fortran-check-end-prog-re () |
(defun fortran-check-end-prog-re () |
956 |
"Check a preliminary match against `fortran-end-prog-re'." |
"Check a preliminary match against `fortran-end-prog-re'." |
957 |
;; Having got a possible match for the subprogram end, we need a |
;; Having got a possible match for the subprogram end, we need a |
1010 |
(concat "[ \t]*" |
(concat "[ \t]*" |
1011 |
(regexp-quote fortran-continuation-string))) |
(regexp-quote fortran-continuation-string))) |
1012 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")))) |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")))) |
1013 |
(while (and (setq not-first-statement (= (forward-line -1) 0)) |
(while (and (setq not-first-statement (zerop (forward-line -1))) |
1014 |
(or (looking-at fortran-comment-line-start-skip) |
(or (looking-at fortran-comment-line-start-skip) |
1015 |
(looking-at fortran-directive-re) |
(looking-at fortran-directive-re) |
1016 |
|
(looking-at |
1017 |
|
(concat "[ \t]*" |
1018 |
|
(regexp-quote fortran-continuation-string))) |
1019 |
(looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]") |
(looking-at "[ \t]*$\\| \\{5\\}[^ 0\n]\\|\t[1-9]") |
1020 |
(looking-at (concat "[ \t]*" comment-start-skip))))) |
(looking-at (concat "[ \t]*" comment-start-skip))))) |
1021 |
(cond ((and continue-test |
(cond ((and continue-test |
1035 |
(let (not-last-statement) |
(let (not-last-statement) |
1036 |
(beginning-of-line) |
(beginning-of-line) |
1037 |
(while (and (setq not-last-statement |
(while (and (setq not-last-statement |
1038 |
(and (= (forward-line 1) 0) |
(and (zerop (forward-line 1)) |
1039 |
(not (eobp)))) |
(not (eobp)))) |
1040 |
(or (looking-at fortran-comment-line-start-skip) |
(or (looking-at fortran-comment-line-start-skip) |
1041 |
(looking-at fortran-directive-re) |
(looking-at fortran-directive-re) |
1043 |
(looking-at (concat "[ \t]*" comment-start-skip))))) |
(looking-at (concat "[ \t]*" comment-start-skip))))) |
1044 |
(if (not not-last-statement) |
(if (not not-last-statement) |
1045 |
'last-statement))) |
'last-statement))) |
1046 |
|
|
1047 |
|
|
1048 |
(defun fortran-blink-match (regex keyword find-begin) |
(defun fortran-blink-match (regex keyword find-begin) |
1049 |
"From a line matching REGEX, blink matching KEYWORD statement line. |
"From a line matching REGEX, blink matching KEYWORD statement line. |
1053 |
(case-fold-search t) |
(case-fold-search t) |
1054 |
matching |
matching |
1055 |
message) |
message) |
1056 |
(if (save-excursion |
(when (save-excursion |
1057 |
(beginning-of-line) |
(beginning-of-line) |
1058 |
(skip-chars-forward " \t0-9") |
(skip-chars-forward " \t0-9") |
1059 |
(looking-at regex)) |
(looking-at regex)) |
1060 |
(progn |
(if (not (setq matching (funcall find-begin))) |
1061 |
(if (not (setq matching (funcall find-begin))) |
(setq message (concat "No matching " keyword ".")) |
1062 |
(setq message (concat "No matching " keyword ".")) |
(if (< matching top-of-window) |
1063 |
(if (< matching top-of-window) |
(save-excursion |
1064 |
(save-excursion |
(goto-char matching) |
1065 |
(goto-char matching) |
(beginning-of-line) |
1066 |
(beginning-of-line) |
(setq message |
1067 |
(setq message |
(concat "Matches " |
1068 |
(concat "Matches " |
(buffer-substring (point) |
1069 |
(buffer-substring (point) |
(line-end-position))))))) |
1070 |
(line-end-position))))))) |
(if message |
1071 |
(if message |
(message "%s" message) |
1072 |
(message "%s" message) |
(goto-char matching) |
1073 |
(goto-char matching) |
(sit-for 1) |
1074 |
(sit-for 1) |
(goto-char end-point))))) |
|
(goto-char end-point)))))) |
|
1075 |
|
|
1076 |
(defun fortran-blink-matching-if () |
(defun fortran-blink-matching-if () |
1077 |
"From an ENDIF or ELSE statement, blink the matching IF statement." |
"From an ENDIF or ELSE statement, blink the matching IF statement." |
1106 |
;; Search for one. |
;; Search for one. |
1107 |
(save-excursion |
(save-excursion |
1108 |
(let ((count 1)) |
(let ((count 1)) |
1109 |
(while (and (not (= count 0)) |
(while (and (not (zerop count)) |
1110 |
(not (eq (fortran-next-statement) 'last-statement)) |
(not (eq (fortran-next-statement) 'last-statement)) |
1111 |
;; Keep local to subprogram |
;; Keep local to subprogram. |
1112 |
(not (and (looking-at fortran-end-prog-re) |
(not (and (looking-at fortran-end-prog-re) |
1113 |
(fortran-check-end-prog-re)))) |
(fortran-check-end-prog-re)))) |
1114 |
(skip-chars-forward " \t0-9") |
(skip-chars-forward " \t0-9") |
1116 |
(setq count (1- count))) |
(setq count (1- count))) |
1117 |
((looking-at |
((looking-at |
1118 |
"\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]") |
"\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?do[ \t]+[^0-9]") |
1119 |
(setq count (+ count 1))))) |
(setq count (1+ count))))) |
1120 |
(and (= count 0) |
(and (zerop count) |
1121 |
;; All pairs accounted for. |
;; All pairs accounted for. |
1122 |
(point))))))) |
(point))))))) |
1123 |
|
|
1135 |
;; Search for one. |
;; Search for one. |
1136 |
(save-excursion |
(save-excursion |
1137 |
(let ((count 1)) |
(let ((count 1)) |
1138 |
(while (and (not (= count 0)) |
(while (and (not (zerop count)) |
1139 |
(not (eq (fortran-previous-statement) 'first-statement)) |
(not (eq (fortran-previous-statement) 'first-statement)) |
1140 |
;; Keep local to subprogram |
;; Keep local to subprogram. |
1141 |
(not (and (looking-at fortran-end-prog-re) |
(not (and (looking-at fortran-end-prog-re) |
1142 |
(fortran-check-end-prog-re)))) |
(fortran-check-end-prog-re)))) |
1143 |
(skip-chars-forward " \t0-9") |
(skip-chars-forward " \t0-9") |
1146 |
;; Note labelled loop ends not considered. |
;; Note labelled loop ends not considered. |
1147 |
((looking-at "end[ \t]*do\\b") |
((looking-at "end[ \t]*do\\b") |
1148 |
(setq count (1+ count))))) |
(setq count (1+ count))))) |
1149 |
(and (= count 0) |
(and (zerop count) |
1150 |
;; All pairs accounted for. |
;; All pairs accounted for. |
1151 |
(point))))))) |
(point))))))) |
1152 |
|
|
1163 |
(push-mark) |
(push-mark) |
1164 |
(goto-char if-point))))) |
(goto-char if-point))))) |
1165 |
|
|
|
(defvar fortran-if-start-re "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") |
|
|
|
|
1166 |
(defun fortran-end-if () |
(defun fortran-end-if () |
1167 |
"Search forwards for first unmatched ENDIF. |
"Search forwards for first unmatched ENDIF. |
1168 |
Return point or nil." |
Return point or nil." |
1176 |
;; letter on line but this should not cause troubles. |
;; letter on line but this should not cause troubles. |
1177 |
(save-excursion |
(save-excursion |
1178 |
(let ((count 1)) |
(let ((count 1)) |
1179 |
(while (and (not (= count 0)) |
(while (and (not (zerop count)) |
1180 |
(not (eq (fortran-next-statement) 'last-statement)) |
(not (eq (fortran-next-statement) 'last-statement)) |
1181 |
;; Keep local to subprogram. |
;; Keep local to subprogram. |
1182 |
(not (and (looking-at fortran-end-prog-re) |
(not (and (looking-at fortran-end-prog-re) |
1183 |
(fortran-check-end-prog-re)))) |
(fortran-check-end-prog-re)))) |
1184 |
(skip-chars-forward " \t0-9") |
(skip-chars-forward " \t0-9") |
1185 |
(cond ((looking-at "end[ \t]*if\\b") |
(cond ((looking-at "end[ \t]*if\\b") |
1186 |
(setq count (- count 1))) |
(setq count (1- count))) |
1187 |
((looking-at fortran-if-start-re) |
((looking-at fortran-if-start-re) |
1188 |
(save-excursion |
(save-excursion |
1189 |
(if (or |
(if (or |
1190 |
(looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
(looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
1191 |
(let (then-test) ; Multi-line if-then. |
(let (then-test) ; multi-line if-then |
1192 |
(while |
(while |
1193 |
(and |
(and |
1194 |
(= (forward-line 1) 0) |
(zerop (forward-line 1)) |
1195 |
;; Search forward for then. |
;; Search forward for then. |
1196 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1197 |
(not |
(not |
1199 |
(looking-at |
(looking-at |
1200 |
".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) |
".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) |
1201 |
then-test)) |
then-test)) |
1202 |
(setq count (+ count 1))))))) |
(setq count (1+ count))))))) |
1203 |
(and (= count 0) |
(and (zerop count) |
1204 |
;; All pairs accounted for. |
;; All pairs accounted for. |
1205 |
(point))))))) |
(point))))))) |
1206 |
|
|
1224 |
;; Multi-line if-then. |
;; Multi-line if-then. |
1225 |
(let (then-test) |
(let (then-test) |
1226 |
(while |
(while |
1227 |
(and (= (forward-line 1) 0) |
(and (zerop (forward-line 1)) |
1228 |
;; Search forward for then. |
;; Search forward for then. |
1229 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1230 |
(not |
(not |
1237 |
;; Search for one. |
;; Search for one. |
1238 |
(save-excursion |
(save-excursion |
1239 |
(let ((count 1)) |
(let ((count 1)) |
1240 |
(while (and (not (= count 0)) |
(while (and (not (zerop count)) |
1241 |
(not (eq (fortran-previous-statement) 'first-statement)) |
(not (eq (fortran-previous-statement) 'first-statement)) |
1242 |
;; Keep local to subprogram. |
;; Keep local to subprogram. |
1243 |
(not (and (looking-at fortran-end-prog-re) |
(not (and (looking-at fortran-end-prog-re) |
1247 |
(save-excursion |
(save-excursion |
1248 |
(if (or |
(if (or |
1249 |
(looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
(looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") |
1250 |
(let (then-test) ; Multi-line if-then. |
(let (then-test) ; multi-line if-then |
1251 |
(while |
(while |
1252 |
(and |
(and |
1253 |
(= (forward-line 1) 0) |
(zerop (forward-line 1)) |
1254 |
;; Search forward for then. |
;; Search forward for then. |
1255 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1256 |
(not |
(not |
1259 |
(concat ".*then\\b[ \t]*" |
(concat ".*then\\b[ \t]*" |
1260 |
"[^ \t(=a-z0-9]")))))) |
"[^ \t(=a-z0-9]")))))) |
1261 |
then-test)) |
then-test)) |
1262 |
(setq count (- count 1))))) |
(setq count (1- count))))) |
1263 |
((looking-at "end[ \t]*if\\b") |
((looking-at "end[ \t]*if\\b") |
1264 |
(setq count (+ count 1))))) |
(setq count (1+ count))))) |
1265 |
(and (= count 0) |
(and (zerop count) |
1266 |
;; All pairs accounted for. |
;; All pairs accounted for. |
1267 |
(point))))))) |
(point))))))) |
1268 |
|
|
1269 |
|
|
1270 |
(defun fortran-indent-line () |
(defun fortran-indent-line () |
1271 |
"Indent current Fortran line based on its contents and on previous lines." |
"Indent current Fortran line based on its contents and on previous lines." |
1272 |
(interactive) |
(interactive "*") |
1273 |
(let ((cfi (fortran-calculate-indent))) |
(let ((cfi (fortran-calculate-indent))) |
1274 |
(save-excursion |
(save-excursion |
1275 |
(beginning-of-line) |
(beginning-of-line) |
1283 |
;; Never leave point in left margin. |
;; Never leave point in left margin. |
1284 |
(if (< (current-column) cfi) |
(if (< (current-column) cfi) |
1285 |
(move-to-column cfi)) |
(move-to-column cfi)) |
1286 |
(if (and auto-fill-function |
(and auto-fill-function |
1287 |
(> (save-excursion (end-of-line) (current-column)) |
(> (save-excursion (end-of-line) (current-column)) |
1288 |
fill-column)) |
fill-column) |
1289 |
(save-excursion |
(save-excursion |
1290 |
(end-of-line) |
(end-of-line) |
1291 |
(fortran-fill))) |
(fortran-fill))) |
1292 |
(if fortran-blink-matching-if |
(when fortran-blink-matching-if |
1293 |
(progn |
(fortran-blink-matching-if) |
1294 |
(fortran-blink-matching-if) |
(fortran-blink-matching-do)))) |
|
(fortran-blink-matching-do))))) |
|
1295 |
|
|
1296 |
(defun fortran-auto-fill () |
(defun fortran-auto-fill () |
1297 |
|
"Function to use for `normal-auto-fill-function' in Fortran mode." |
1298 |
(if (> (current-column) (current-fill-column)) |
(if (> (current-column) (current-fill-column)) |
1299 |
(let ((cfi (fortran-calculate-indent))) |
(let ((cfi (fortran-calculate-indent))) |
1300 |
(save-excursion |
(save-excursion |
1317 |
(defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent) |
(defalias 'fortran-indent-new-line 'reindent-then-newline-and-indent) |
1318 |
|
|
1319 |
(defun fortran-indent-subprogram () |
(defun fortran-indent-subprogram () |
1320 |
"Properly indent the Fortran subprogram which contains point." |
"Properly indent the Fortran subprogram containing point." |
1321 |
(interactive) |
(interactive "*") |
1322 |
(save-excursion |
(save-excursion |
1323 |
(mark-defun) |
(mark-defun) |
1324 |
(message "Indenting subprogram...") |
(message "Indenting subprogram...") |
1336 |
(setq first-statement (fortran-previous-statement)) |
(setq first-statement (fortran-previous-statement)) |
1337 |
(if first-statement |
(if first-statement |
1338 |
(setq icol fortran-minimum-statement-indent) |
(setq icol fortran-minimum-statement-indent) |
1339 |
(progn |
(if (= (point) (point-min)) |
1340 |
(if (= (point) (point-min)) |
(setq icol fortran-minimum-statement-indent) |
1341 |
(setq icol fortran-minimum-statement-indent) |
(setq icol (fortran-current-line-indentation))) |
1342 |
(setq icol (fortran-current-line-indentation))) |
(skip-chars-forward " \t0-9") |
1343 |
(skip-chars-forward " \t0-9") |
(cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") |
1344 |
(cond ((looking-at "\\(\\(\\sw\\|\\s_\\)+:[ \t]*\\)?if[ \t]*(") |
(if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") |
1345 |
(if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") |
(let (then-test) ; multi-line if-then |
1346 |
(let (then-test) ;multi-line if-then |
(while (and (zerop (forward-line 1)) |
1347 |
(while (and (= (forward-line 1) 0) |
;; Search forward for then. |
1348 |
;;search forward for then |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
1349 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]") |
(not (setq then-test |
1350 |
(not (setq then-test |
(looking-at |
1351 |
(looking-at |
".*then\\b[ \t]\ |
|
".*then\\b[ \t]\ |
|
1352 |
*[^ \t_$(=a-z0-9]"))))) |
*[^ \t_$(=a-z0-9]"))))) |
1353 |
then-test)) |
then-test)) |
1354 |
(setq icol (+ icol fortran-if-indent)))) |
(setq icol (+ icol fortran-if-indent)))) |
1355 |
((looking-at "else\\(if\\)?\\b") |
((looking-at "else\\(if\\)?\\b") |
1356 |
(setq icol (+ icol fortran-if-indent))) |
(setq icol (+ icol fortran-if-indent))) |
1357 |
((looking-at "select[ \t]*case[ \t](.*)") |
((looking-at "select[ \t]*case[ \t](.*)") |
1358 |
(setq icol (+ icol fortran-if-indent))) |
(setq icol (+ icol fortran-if-indent))) |
1359 |
((looking-at "case[ \t]*(.*)") |
((looking-at "case[ \t]*(.*)") |
1360 |
(setq icol (+ icol fortran-if-indent))) |
(setq icol (+ icol fortran-if-indent))) |
1361 |
((looking-at "case[ \t]*default\\b") |
((looking-at "case[ \t]*default\\b") |
1362 |
(setq icol (+ icol fortran-if-indent))) |
(setq icol (+ icol fortran-if-indent))) |
1363 |
((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") |
((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") |
1364 |
(setq icol (+ icol fortran-if-indent))) |
(setq icol (+ icol fortran-if-indent))) |
1365 |
((looking-at "where[ \t]*(.*)[ \t]*\n") |
((looking-at "where[ \t]*(.*)[ \t]*\n") |
1366 |
(setq icol (+ icol fortran-if-indent))) |
(setq icol (+ icol fortran-if-indent))) |
1367 |
((looking-at "do\\b") |
((looking-at "do\\b") |
1368 |
(setq icol (+ icol fortran-do-indent))) |
(setq icol (+ icol fortran-do-indent))) |
1369 |
((looking-at |
((looking-at |
1370 |
"\\(structure\\|union\\|map\\|interface\\)\ |
"\\(structure\\|union\\|map\\|interface\\)\ |
1371 |
\\b[ \t]*[^ \t=(a-z]") |
\\b[ \t]*[^ \t=(a-z]") |
1372 |
(setq icol (+ icol fortran-structure-indent))) |
(setq icol (+ icol fortran-structure-indent))) |
1373 |
((and (looking-at fortran-end-prog-re1) |
((and (looking-at fortran-end-prog-re1) |
1374 |
(fortran-check-end-prog-re)) |
(fortran-check-end-prog-re)) |
1375 |
;; Previous END resets indent to minimum |
;; Previous END resets indent to minimum. |
1376 |
(setq icol fortran-minimum-statement-indent)))))) |
(setq icol fortran-minimum-statement-indent))))) |
1377 |
(save-excursion |
(save-excursion |
1378 |
(beginning-of-line) |
(beginning-of-line) |
1379 |
(cond ((looking-at "[ \t]*$")) |
(cond ((looking-at "[ \t]*$")) |
1387 |
(setq icol (+ fortran-minimum-statement-indent |
(setq icol (+ fortran-minimum-statement-indent |
1388 |
fortran-comment-line-extra-indent)))) |
fortran-comment-line-extra-indent)))) |
1389 |
(setq fortran-minimum-statement-indent 0)) |
(setq fortran-minimum-statement-indent 0)) |
1390 |
((or (looking-at (concat "[ \t]*" |
((or (looking-at (concat "[ \t]*" |
1391 |
(regexp-quote |
(regexp-quote |
1392 |
fortran-continuation-string))) |
fortran-continuation-string))) |
1393 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) |
1394 |
(setq icol (+ icol fortran-continuation-indent))) |
(skip-chars-forward " \t") |
1395 |
|
;; Do not introduce extra whitespace into a broken string. |
1396 |
|
(setq icol |
1397 |
|
(if (fortran-is-in-string-p (point)) |
1398 |
|
6 |
1399 |
|
(+ icol fortran-continuation-indent)))) |
1400 |
(first-statement) |
(first-statement) |
1401 |
((and fortran-check-all-num-for-matching-do |
((and fortran-check-all-num-for-matching-do |
1402 |
(looking-at "[ \t]*[0-9]+") |
(looking-at "[ \t]*[0-9]+") |
1426 |
(message "Warning: `end' not in column %d. Probably\ |
(message "Warning: `end' not in column %d. Probably\ |
1427 |
an unclosed block." fortran-minimum-statement-indent)))))) |
an unclosed block." fortran-minimum-statement-indent)))))) |
1428 |
(max fortran-minimum-statement-indent icol))) |
(max fortran-minimum-statement-indent icol))) |
1429 |
|
|
1430 |
|
|
1431 |
(defun fortran-current-line-indentation () |
(defun fortran-current-line-indentation () |
1432 |
"Indentation of current line, ignoring Fortran line number or continuation. |
"Indentation of current line, ignoring Fortran line number or continuation. |
1452 |
(current-column))) |
(current-column))) |
1453 |
|
|
1454 |
(defun fortran-indent-to-column (col) |
(defun fortran-indent-to-column (col) |
1455 |
"Indent current line with spaces to column COL. |
"Indent current line to column COL. |
1456 |
notes: 1) A non-zero/non-blank character in column 5 indicates a continuation |
notes: 1) A non-zero/non-blank character in column 5 indicates a continuation |
1457 |
line, and this continuation character is retained on indentation; |
line, and this continuation character is retained on indentation; |
1458 |
2) If `fortran-continuation-string' is the first non-whitespace |
2) If `fortran-continuation-string' is the first non-whitespace |
1485 |
(insert ?\t (fortran-numerical-continuation-char) 1)) |
(insert ?\t (fortran-numerical-continuation-char) 1)) |
1486 |
(forward-char 6)) |
(forward-char 6)) |
1487 |
(delete-horizontal-space) |
(delete-horizontal-space) |
1488 |
;; Put line number in columns 0-4 |
;; Put line number in columns 0-4, or |
1489 |
;; or put continuation character in column 5. |
;; continuation character in column 5. |
1490 |
(cond ((eobp)) |
(cond ((eobp)) |
1491 |
((looking-at (regexp-quote fortran-continuation-string)) |
((looking-at (regexp-quote fortran-continuation-string)) |
1492 |
(if indent-tabs-mode |
(if indent-tabs-mode |
1510 |
(delete-horizontal-space) |
(delete-horizontal-space) |
1511 |
(indent-to col) |
(indent-to col) |
1512 |
;; Indent any comment following code on the same line. |
;; Indent any comment following code on the same line. |
1513 |
(if (fortran-find-comment-start-skip) |
(when (fortran-find-comment-start-skip) |
1514 |
(progn (goto-char (match-beginning 0)) |
(goto-char (match-beginning 0)) |
1515 |
(if (not (= (current-column) (fortran-comment-indent))) |
(unless (= (current-column) (fortran-comment-indent)) |
1516 |
(progn (delete-horizontal-space) |
(delete-horizontal-space) |
1517 |
(indent-to (fortran-comment-indent))))))))) |
(indent-to (fortran-comment-indent))))))) |
1518 |
|
|
1519 |
(defun fortran-line-number-indented-correctly-p () |
(defun fortran-line-number-indented-correctly-p () |
1520 |
"Return t if current line's line number is correctly indented. |
"Return t if current line's line number is correctly indented. |
1534 |
charnum) |
charnum) |
1535 |
(save-excursion |
(save-excursion |
1536 |
(beginning-of-line) |
(beginning-of-line) |
1537 |
(if (looking-at "[ \t]*[0-9]+") |
(when (looking-at "[ \t]*[0-9]+") |
1538 |
(progn |
(skip-chars-forward " \t") |
1539 |
(skip-chars-forward " \t") |
(skip-chars-forward "0") ; skip past leading zeros |
1540 |
(skip-chars-forward "0") ;skip past leading zeros |
(setq charnum |
1541 |
(setq charnum |
(buffer-substring (point) (progn |
1542 |
(buffer-substring (point) (progn |
(skip-chars-forward "0-9") |
1543 |
(skip-chars-forward "0-9") |
(point)))) |
1544 |
(point)))) |
(beginning-of-line) |
1545 |
(beginning-of-line) |
(save-restriction |
1546 |
(save-restriction |
(save-excursion |
1547 |
(save-excursion |
(narrow-to-defun) |
1548 |
(narrow-to-defun) |
(and (re-search-backward |
1549 |
(and (re-search-backward |
(concat |
1550 |
(concat |
"\\(^[ \t0-9]*do[ \t]*0*" |
1551 |
"\\(^[ \t0-9]*do[ \t]*0*" |
charnum "\\b\\)\\|" "\\(^[ \t]*0*" |
1552 |
charnum "\\b\\)\\|" "\\(^[ \t]*0*" |
charnum "\\b\\)") |
1553 |
charnum "\\b\\)") |
nil t) |
1554 |
nil t) |
(looking-at |
1555 |
(looking-at |
(concat "^[ \t0-9]*do[ \t]*0*" |
1556 |
(concat "^[ \t0-9]*do[ \t]*0*" |
charnum))))))))) |
|
charnum)))))))))) |
|
1557 |
|
|
1558 |
(defun fortran-find-comment-start-skip (&optional all) |
(defun fortran-find-comment-start-skip (&optional all) |
1559 |
"Move to past `comment-start-skip' found on current line. |
"Move to past `comment-start-skip' found on current line. |
1560 |
Return non-nil if `comment-start-skip' found, nil if not. |
Return non-nil if `comment-start-skip' found, nil if not. |
1561 |
If ALL is nil, only match comments that start in column > 0." |
If ALL is nil, only match comments that start in column > 0." |
|
(interactive) |
|
1562 |
;; Hopefully at some point we can just use the line below! -stef |
;; Hopefully at some point we can just use the line below! -stef |
1563 |
;; (comment-search-forward (line-end-position) t)) |
;; (comment-search-forward (line-end-position) t)) |
1564 |
(when (or all comment-start-skip) |
(when (or all comment-start-skip) |
1577 |
(goto-char pos) |
(goto-char pos) |
1578 |
nil))))) |
nil))))) |
1579 |
|
|
1580 |
;;From: ralf@up3aud1.gwdg.de (Ralf Fassel) |
;; From: ralf@up3aud1.gwdg.de (Ralf Fassel) |
1581 |
;; Test if TAB format continuation lines work. |
;; Test if TAB format continuation lines work. |
1582 |
(defun fortran-is-in-string-p (where) |
(defun fortran-is-in-string-p (where) |
1583 |
"Return non-nil iff WHERE (a buffer position) is inside a Fortran string." |
"Return non-nil iff WHERE (a buffer position) is inside a Fortran string." |
1588 |
((save-excursion ; comment lines too |
((save-excursion ; comment lines too |
1589 |
(beginning-of-line) |
(beginning-of-line) |
1590 |
(looking-at fortran-comment-line-start-skip)) nil) |
(looking-at fortran-comment-line-start-skip)) nil) |
1591 |
(t (let (;; ok, serious now. Init some local vars: |
(t (let ((parse-state '(0 nil nil nil nil nil 0)) |
|
(parse-state '(0 nil nil nil nil nil 0)) |
|
1592 |
(quoted-comment-start (if comment-start |
(quoted-comment-start (if comment-start |
1593 |
(regexp-quote comment-start))) |
(regexp-quote comment-start))) |
1594 |
(not-done t) |
(not-done t) |
1595 |
parse-limit end-of-line) |
parse-limit end-of-line) |
1596 |
;; move to start of current statement |
;; Move to start of current statement. |
1597 |
(fortran-next-statement) |
(fortran-next-statement) |
1598 |
(fortran-previous-statement) |
(fortran-previous-statement) |
1599 |
;; now parse up to WHERE |
;; Now parse up to WHERE. |
1600 |
(while not-done |
(while not-done |
1601 |
(if (or ;; skip to next line if: |
(if (or ;; Skip to next line if: |
1602 |
;; - comment line? |
;; - comment line? |
1603 |
(looking-at fortran-comment-line-start-skip) |
(looking-at fortran-comment-line-start-skip) |
1604 |
;; - at end of line? |
;; - at end of line? |
1611 |
(if (> (forward-line) 0) |
(if (> (forward-line) 0) |
1612 |
(setq not-done nil)) |
(setq not-done nil)) |
1613 |
;; else: |
;; else: |
1614 |
;; if we are at beginning of code line, skip any |
;; If we are at beginning of code line, skip any |
1615 |
;; whitespace, labels and tab continuation markers. |
;; whitespace, labels and tab continuation markers. |
1616 |
(if (bolp) (skip-chars-forward " \t0-9")) |
(if (bolp) (skip-chars-forward " \t0-9")) |
1617 |
;; if we are in column <= 5 now, check for continuation char |
;; If we are in column <= 5 now, check for continuation char. |
1618 |
(cond ((= 5 (current-column)) (forward-char 1)) |
(cond ((= 5 (current-column)) (forward-char 1)) |
1619 |
((and (< (current-column) 5) |
((and (< (current-column) 5) |
1620 |
(equal fortran-continuation-string |
(equal fortran-continuation-string |
1621 |
(char-to-string (following-char))) |
(char-to-string (following-char))) |
1622 |
(forward-char 1)))) |
(forward-char 1)))) |
1623 |
;; find out parse-limit from here |
;; Find out parse-limit from here. |
1624 |
(setq end-of-line (line-end-position)) |
(setq end-of-line (line-end-position)) |
1625 |
(setq parse-limit (min where end-of-line)) |
(setq parse-limit (min where end-of-line)) |
1626 |
;; parse max up to comment-start, if non-nil and in current line |
;; Parse max up to comment-start, if non-nil and in current line. |
1627 |
(if comment-start |
(if comment-start |
1628 |
(save-excursion |
(save-excursion |
1629 |
(if (re-search-forward quoted-comment-start end-of-line t) |
(if (re-search-forward quoted-comment-start end-of-line t) |
1630 |
(setq parse-limit (min (point) parse-limit))))) |
(setq parse-limit (min (point) parse-limit))))) |
1631 |
;; now parse if still in limits |
;; Now parse if still in limits. |
1632 |
(if (< (point) where) |
(if (< (point) where) |
1633 |
(setq parse-state (parse-partial-sexp |
(setq parse-state (parse-partial-sexp |
1634 |
(point) parse-limit nil nil parse-state)) |
(point) parse-limit nil nil parse-state)) |
1635 |
(setq not-done nil)))) |
(setq not-done nil)))) |
1636 |
;; result is |
;; Result. |
1637 |
(nth 3 parse-state)))))) |
(nth 3 parse-state)))))) |
1638 |
|
|
1639 |
;; From old version. |
;; From old version. |
1640 |
(defalias 'fortran-auto-fill-mode 'auto-fill-mode) |
(defalias 'fortran-auto-fill-mode 'auto-fill-mode) |
1641 |
|
|
1642 |
(defun fortran-fill () |
(defun fortran-fill () |
1643 |
|
"Fill the current line at an appropriate point(s)." |
1644 |
(let* ((auto-fill-function #'fortran-auto-fill) |
(let* ((auto-fill-function #'fortran-auto-fill) |
1645 |
(opoint (point)) |
(opoint (point)) |
1646 |
(bol (line-beginning-position)) |
(bol (line-beginning-position)) |
1649 |
(quote |
(quote |
1650 |
(save-excursion |
(save-excursion |
1651 |
(goto-char bol) |
(goto-char bol) |
1652 |
(if (looking-at fortran-comment-line-start-skip) |
;; OK to break quotes on comment lines. |
1653 |
nil ; OK to break quotes on comment lines. |
(unless (looking-at fortran-comment-line-start-skip) |
1654 |
|
(let (fcpoint start) |
1655 |
(move-to-column fill-column) |
(move-to-column fill-column) |
1656 |
(if (fortran-is-in-string-p (point)) |
(when (fortran-is-in-string-p (setq fcpoint (point))) |
1657 |
(save-excursion (re-search-backward "\\S\"\\s\"\\S\"" bol t) |
(save-excursion |
1658 |
(if fortran-break-before-delimiters |
(re-search-backward "\\S\"\\s\"\\S\"" bol t) |
1659 |
(point) |
(setq start |
1660 |
(1+ (point)))))))) |
(if fortran-break-before-delimiters |
1661 |
;; decide where to split the line. If a position for a quoted |
(point) |
1662 |
|
(1+ (point))))) |
1663 |
|
(if (re-search-forward "\\S\"\\s\"\\S\"" eol t) |
1664 |
|
(backward-char 2)) |
1665 |
|
;; If the current string is longer than 72 - 6 chars, |
1666 |
|
;; break it at the fill column (else infinite loop). |
1667 |
|
(if (> (- (point) start) |
1668 |
|
(- fill-column 6 fortran-continuation-indent)) |
1669 |
|
fcpoint |
1670 |
|
start)))))) |
1671 |
|
;; Decide where to split the line. If a position for a quoted |
1672 |
;; string was found above then use that, else break the line |
;; string was found above then use that, else break the line |
1673 |
;; before the last delimiter. |
;; before the last delimiter. |
1674 |
;; Delimiters are whitespace, commas, and operators. |
;; Delimiters are whitespace, commas, and operators. |
1677 |
(or quote |
(or quote |
1678 |
(save-excursion |
(save-excursion |
1679 |
(move-to-column (1+ fill-column)) |
(move-to-column (1+ fill-column)) |
1680 |
|
;; GM Make this a defcustom as in f90-mode? Add ", (? |
1681 |
(skip-chars-backward "^ \t\n,'+-/*=)" |
(skip-chars-backward "^ \t\n,'+-/*=)" |
1682 |
;;; (if fortran-break-before-delimiters |
;;; (if fortran-break-before-delimiters |
1683 |
;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)") |
;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)") |
1684 |
) |
) |
1685 |
(if (<= (point) (1+ bos)) |
(when (<= (point) (1+ bos)) |
1686 |
(progn |
(move-to-column (1+ fill-column)) |
1687 |
(move-to-column (1+ fill-column)) |
;; What is this doing??? |
1688 |
;;what is this doing??? |
(or (re-search-forward "[\t\n,'+-/*)=]" eol t) |
1689 |
(if (not (re-search-forward "[\t\n,'+-/*)=]" eol t)) |
(goto-char bol))) |
|
(goto-char bol)))) |
|
1690 |
(if (bolp) |
(if (bolp) |
1691 |
(re-search-forward "[ \t]" opoint t) |
(re-search-forward "[ \t]" opoint t) |
1692 |
(backward-char) |
(backward-char) |
1696 |
(if fortran-break-before-delimiters |
(if fortran-break-before-delimiters |
1697 |
(point) |
(point) |
1698 |
(1+ (point))))))) |
(1+ (point))))))) |
1699 |
;; if we are in an in-line comment, don't break unless the |
;; If we are in an in-line comment, don't break unless the |
1700 |
;; line of code is longer than it should be. Otherwise |
;; line of code is longer than it should be. Otherwise |
1701 |
;; break the line at the column computed above. |
;; break the line at the column computed above. |
1702 |
;; |
;; |
1703 |
;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s |
;; Need to use fortran-find-comment-start-skip to make sure that |
1704 |
;; don't prevent a break. |
;; quoted !'s don't prevent a break. |
1705 |
(when (and (save-excursion |
(when (and (save-excursion |
1706 |
(beginning-of-line) |
(beginning-of-line) |
1707 |
(if (not (fortran-find-comment-start-skip)) |
(if (not (fortran-find-comment-start-skip)) |
1722 |
(end-of-line)))) |
(end-of-line)))) |
1723 |
|
|
1724 |
(defun fortran-break-line () |
(defun fortran-break-line () |
1725 |
|
"Call `fortran-split-line'. Joins continuation lines first, then refills." |
1726 |
(let ((opoint (point)) |
(let ((opoint (point)) |
1727 |
(bol (line-beginning-position)) |
(bol (line-beginning-position)) |
1728 |
(comment-string |
(comment-string |
1730 |
(if (fortran-find-comment-start-skip) |
(if (fortran-find-comment-start-skip) |
1731 |
(delete-and-extract-region |
(delete-and-extract-region |
1732 |
(match-beginning 0) (line-end-position)))))) |
(match-beginning 0) (line-end-position)))))) |
1733 |
;; Forward line 1 really needs to go to next non white line |
;; Forward line 1 really needs to go to next non white line. |
1734 |
(if (save-excursion (forward-line) |
(if (save-excursion (forward-line) |
1735 |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) |
(looking-at " \\{5\\}[^ 0\n]\\|\t[1-9]")) |
1736 |
(progn |
(progn |
1749 |
|
|
1750 |
(defun fortran-analyze-file-format () |
(defun fortran-analyze-file-format () |
1751 |
"Return nil if fixed format is used, t if TAB formatting is used. |
"Return nil if fixed format is used, t if TAB formatting is used. |
1752 |
Use `fortran-tab-mode-default' if no non-comment statements are found in the |
Use `fortran-tab-mode-default' if no non-comment statements are found |
1753 |
file before the end or the first `fortran-analyze-depth' lines." |
before the end or in the first `fortran-analyze-depth' lines." |
1754 |
(let ((i 0)) |
(let ((i 0)) |
1755 |
(save-excursion |
(save-excursion |
1756 |
(goto-char (point-min)) |
(goto-char (point-min)) |
|
(setq i 0) |
|
1757 |
(while (not (or |
(while (not (or |
1758 |
(eobp) |
(eobp) |
1759 |
(eq (char-after) ?\t) |
(eq (char-after) ?\t) |
1764 |
(cond |
(cond |
1765 |
((eq (char-after) ?\t) t) |
((eq (char-after) ?\t) t) |
1766 |
((looking-at " \\{6\\}") nil) |
((looking-at " \\{6\\}") nil) |
1767 |
(fortran-tab-mode-default t) |
(t fortran-tab-mode-default))))) |
|
(t nil))))) |
|
|
|
|
|
(or (assq 'fortran-tab-mode-string minor-mode-alist) |
|
|
(setq minor-mode-alist (cons |
|
|
'(fortran-tab-mode-string |
|
|
(indent-tabs-mode fortran-tab-mode-string)) |
|
|
minor-mode-alist))) |
|
1768 |
|
|
1769 |
(defun fortran-fill-paragraph (&optional justify) |
(defun fortran-fill-paragraph (&optional justify) |
1770 |
"Fill surrounding comment block as paragraphs, else fill statement. |
"Fill surrounding comment block as paragraphs, else fill statement. |
1771 |
Intended as the value of `fill-paragraph-function'." |
Intended as the value of `fill-paragraph-function'. |
1772 |
(interactive "P") |
A comment block is filled by calling `fill-comment-paragraph' with |
1773 |
|
argument JUSTIFY, otherwise `fortran-fill-statement' is called. |
1774 |
|
Always returns non-nil (to prevent `fill-paragraph' being called)." |
1775 |
|
(interactive "*P") |
1776 |
(or (fill-comment-paragraph justify) |
(or (fill-comment-paragraph justify) |
1777 |
(fortran-fill-statement) |
(fortran-fill-statement) |
1778 |
t)) |
t)) |
1779 |
|
|
1780 |
(defun fortran-fill-statement () |
(defun fortran-fill-statement () |
1781 |
"Fill a fortran statement up to `fill-column'." |
"Fill a Fortran statement up to `fill-column'." |
1782 |
(interactive) |
(interactive "*") |
1783 |
(let ((auto-fill-function #'fortran-auto-fill)) |
(let ((auto-fill-function #'fortran-auto-fill)) |
1784 |
(if (not (save-excursion |
(unless (save-excursion |
1785 |
(beginning-of-line) |
(beginning-of-line) |
1786 |
(or (looking-at "[ \t]*$") |
(or (looking-at "[ \t]*$") |
1787 |
(looking-at fortran-comment-line-start-skip) |
(looking-at fortran-comment-line-start-skip) |
1788 |
(and comment-start-skip |
(and comment-start-skip |
1789 |
(looking-at (concat "[ \t]*" comment-start-skip)))))) |
(looking-at (concat "[ \t]*" comment-start-skip))))) |
1790 |
(save-excursion |
(save-excursion |
1791 |
;; Find beginning of statement. |
;; Find beginning of statement. |
1792 |
(fortran-next-statement) |
(fortran-next-statement) |
1793 |
(fortran-previous-statement) |
(fortran-previous-statement) |
1794 |
;; Re-indent initially. |
;; Re-indent initially. |
1795 |
(fortran-indent-line) |
(fortran-indent-line) |
1796 |
;; Replace newline plus continuation field plus indentation with |
;; Replace newline plus continuation field plus indentation with |
1797 |
;; single space. |
;; single space. |
1798 |
(while (progn |
(while (progn |
1799 |
(forward-line) |
(forward-line) |
1800 |
(fortran-remove-continuation))) |
(fortran-remove-continuation))) |
1801 |
(fortran-previous-statement))) |
(fortran-previous-statement))) |
1802 |
(fortran-indent-line))) |
(fortran-indent-line))) |
1803 |
|
|
1804 |
(defun fortran-strip-sequence-nos (&optional do-space) |
(defun fortran-strip-sequence-nos (&optional do-space) |
1805 |
"Delete all text in column 72 and up (assumed to be sequence numbers). |
"Delete all text in column 72 and up (assumed to be sequence numbers). |
1806 |
Normally also deletes trailing whitespace after stripping such text. |
Normally also deletes trailing whitespace after stripping such text. |
1807 |
Supplying prefix arg DO-SPACE prevents stripping the whitespace." |
Supplying prefix arg DO-SPACE prevents stripping the whitespace." |
1808 |
(interactive "p") |
(interactive "*p") |
1809 |
(save-excursion |
(save-excursion |
1810 |
(goto-char (point-min)) |
(goto-char (point-min)) |
1811 |
(while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t) |
(while (re-search-forward "^.\\{72\\}\\(.*\\)" nil t) |
1820 |
;; We must be inside function body for this to work. |
;; We must be inside function body for this to work. |
1821 |
(fortran-beginning-of-subprogram) |
(fortran-beginning-of-subprogram) |
1822 |
(let ((case-fold-search t)) ; case-insensitive |
(let ((case-fold-search t)) ; case-insensitive |
1823 |
;; search for fortran subprogram start |
;; Search for fortran subprogram start. |
1824 |
(if (re-search-forward |
(if (re-search-forward |
1825 |
(concat "^[ \t]*\\(program\\|subroutine\\|function" |
(concat "^[ \t]*\\(program\\|subroutine\\|function" |
1826 |
"\\|[ \ta-z0-9*()]*[ \t]+function\\|" |
"\\|[ \ta-z0-9*()]*[ \t]+function\\|" |
1830 |
t) |
t) |
1831 |
(or (match-string-no-properties 2) |
(or (match-string-no-properties 2) |
1832 |
(progn |
(progn |
1833 |
;; move to EOL or before first left paren |
;; Move to EOL or before first left paren. |
1834 |
(if (re-search-forward "[(\n]" nil t) |
(if (re-search-forward "[(\n]" nil t) |
1835 |
(progn (backward-char) |
(progn (backward-char) |
1836 |
(skip-chars-backward " \t")) |
(skip-chars-backward " \t")) |
1842 |
|
|
1843 |
(provide 'fortran) |
(provide 'fortran) |
1844 |
|
|
1845 |
|
;;; arch-tag: 74935096-21c4-4cab-8ee5-6ef16090dc04 |
1846 |
;;; fortran.el ends here |
;;; fortran.el ends here |