Mercurial > hg > xemacs-beta
comparison lisp/modes/eiffel3.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; $Id: eiffel3.el,v 1.1.1.1 1996/12/18 03:30:45 steve Exp $ | |
2 ;;;-------------------------------------------------------------------------- | |
3 ;;; TowerEiffel -- Copyright (c) 1993,1994 Tower Technology Corporation. | |
4 ;;; All Rights Reserved. | |
5 ;;; | |
6 ;;; Use, duplication, or disclosure is subject to restrictions as set forth | |
7 ;;; in subdivision (c)(1)(ii) of the Rights in Technical Data and Computer | |
8 ;;; Software clause at DFARS 252.227-7013. | |
9 ;;; | |
10 ;;; This file is made available for use and distribution under the same terms | |
11 ;;; as GNU Emacs. Such availability of this elisp file should not be construed | |
12 ;;; as granting such availability to the rest of TowerEiffel. | |
13 ;;;-------------------------------------------------------------------------- | |
14 ;;; Portions of the file, as indicated below, were derived from "eiffel.el" | |
15 ;;; and "eif-mult-fmt.el | |
16 ;;; Copyright (C) 1989, 1990 Free Software Foundation, Inc. and Bob Weiner | |
17 ;;; Available for use and distribution under the same terms as GNU Emacs. | |
18 | |
19 ;;; Synched up with: Not in FSF. | |
20 | |
21 ;;;-------------------------------------------------------------------------- | |
22 ;;; Adapted the file for the XEmacs 19.12 distribution. -- jasa (1995/03/11) | |
23 ;;;-------------------------------------------------------------------------- | |
24 ;;; | |
25 ;;; EIFFEL3 : GNU Emacs mode for Eiffel Version 3 | |
26 ;;; | |
27 ;;; INSTALLATION | |
28 ;;; To install, simply copy this file into a directory in your | |
29 ;;; load-path and add the following two commands in your .emacs file: | |
30 ;;; | |
31 ;;; (setq auto-mode-alist (cons '("\\.e$" . eiffel-mode) | |
32 ;;; auto-mode-alist)) | |
33 ;;; (autoload 'eiffel-mode "eiffel3" "Mode for Eiffel programs" t) | |
34 ;;; | |
35 ;;; TowerEiffel users should do the following instead: See the file | |
36 ;;; dot-emacs that comes with the TowerEiffel distribution for a sample | |
37 ;;; ".emacs" file. If all Tower elisp files are already in your | |
38 ;;; load-path, then simply add the following line to your .emacs file: | |
39 ;;; | |
40 ;;; (load "tinstall") | |
41 ;;; | |
42 ;;; TOWER EIFFEL | |
43 ;;; TowerEiffel provides additional Emacs support for Eiffel | |
44 ;;; programming that integrates Emacs with Tower's Eiffel compiler, | |
45 ;;; documentation, and browsing tools. For more information on | |
46 ;;; these tools and their Emacs interface contact: | |
47 ;;; | |
48 ;;; Tower Technology Corporation | |
49 ;;; 1501 Koenig Dr. | |
50 ;;; Austin TX, 78756 | |
51 ;;; | |
52 ;;; tower@twr.com (to reach a human being) | |
53 ;;; info@twr.com (automated file server) | |
54 ;;; (512)452-1721 (FAX) | |
55 ;;; (512)452-9455 (phone) | |
56 ;;; | |
57 ;;; SUPPORT | |
58 ;;; Please send bug reports, fixes or enhancements to: | |
59 ;;; elisp@atlanta.twr.com | |
60 ;;; | |
61 ;;; COMPATIBILITY: | |
62 ;;; This file has been tested with XEmacs 19.11. Syntax highlighting is | |
63 ;;; primarily supported with font-lock.el. | |
64 ;;; | |
65 ;;; COMMANDS | |
66 ;;; eif-backward-sexp | |
67 ;;; eif-feature-quote | |
68 ;;; eif-forward-sexp | |
69 ;;; eif-goto-matching-line | |
70 ;;; eif-indent-region | |
71 ;;; eif-indent-construct | |
72 ;;; eif-indent-line | |
73 ;;; eif-newline | |
74 ;;; eiffel-mode | |
75 ;;; | |
76 ;;; PUBLIC VARIABLES | |
77 ;;; eif-body-comment-indent | |
78 ;;; eif-check-keyword-indent | |
79 ;;; eif-class-level-comment-indent | |
80 ;;; eif-class-level-kw-indent | |
81 ;;; eif-extra-body-comment-indent | |
82 ;;; eif-extra-check-keyword-indent | |
83 ;;; eif-extra-class-level-comment-indent | |
84 ;;; eif-extra-class-level-kw-indent | |
85 ;;; eif-extra-feature-level-comment-indent | |
86 ;;; eif-extra-feature-level-indent | |
87 ;;; eif-extra-feature-level-kw-indent | |
88 ;;; eif-extra-inherit-level-kw-indent | |
89 ;;; eif-extra-then-indent | |
90 ;;; eif-feature-level-comment-indent | |
91 ;;; eif-feature-level-indent | |
92 ;;; eif-feature-level-kw-indent | |
93 ;;; eif-indent-increment | |
94 ;;; eif-inherit-level-kw-indent | |
95 ;;; eif-rescue-keyword-indent | |
96 ;;; eif-then-indent | |
97 ;;; eiffel-mode-abbrev-table | |
98 ;;; eiffel-mode-hook | |
99 ;;; eiffel-mode-map | |
100 ;;; eiffel-mode-syntax-table | |
101 ;;; | |
102 ;;; PUBLIC FUNCTIONS | |
103 ;;; None. | |
104 ;;; | |
105 ;;; HISTORY | |
106 ;;; Fred Hart - Jul 31, 1992: Created. | |
107 | |
108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
109 ;;; Indentation Amount Variables. ;;; | |
110 ;;; ;;; | |
111 ;;; The default values correspond to style used in ``Eiffel: The ;;; | |
112 ;;; Language''. Note: for TowerEiffel users the values below ;;; | |
113 ;;; will be superceded by the values in either tcustom.el or ;;; | |
114 ;;; ~/.tcustom.el if it is present. ;;; | |
115 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
116 | |
117 (defvar eif-indent-increment 3 | |
118 "Default indentation interval (in spaces)") | |
119 | |
120 (defvar eif-class-level-kw-indent 0 | |
121 "Indentation amount for Class level keywords (in number of | |
122 eif-indent-increments) (see eif-class-level-keywords variable).") | |
123 (defvar eif-extra-class-level-kw-indent 0 | |
124 "Number of SPACES to add to eif-class-level-kw-indent to get the | |
125 actual indentation of a class level keyword. Can be negative.") | |
126 | |
127 (defvar eif-class-level-comment-indent 0 | |
128 "Indentation of comments at the beginning of the class (in number of | |
129 eif-indent-increments)") | |
130 (defvar eif-extra-class-level-comment-indent 0 | |
131 "Number of SPACES to add to eif-class-level-comment-indent to get the | |
132 actual indentation of a class level comment. Can be negative.") | |
133 | |
134 (defvar eif-inherit-level-kw-indent 2 | |
135 "Indentation of keywords falling under the Inherit clause (in number of | |
136 eif-indent-increments) (see eif-inherit-level-keywords variable.") | |
137 (defvar eif-extra-inherit-level-kw-indent 0 | |
138 "Number of SPACES to add to eif-inherit-level-kw-indent to get the | |
139 actual indentation of an inherit level keyword. Can be negative.") | |
140 | |
141 (defvar eif-feature-level-indent 1 | |
142 "Indentation amount of features. (in number of eif-indent-increments)") | |
143 (defvar eif-extra-feature-level-indent 0 | |
144 "Number of SPACES to add to eif-feature-level-indent to get the | |
145 actual indentation of a feature. Can be negative.") | |
146 | |
147 (defvar eif-feature-level-kw-indent 2 | |
148 "Indentation of keywords belonging to individual features. (in number of | |
149 eif-indent-increments) (see eif-feature-level-keywords variable)") | |
150 (defvar eif-extra-feature-level-kw-indent 0 | |
151 "Number of SPACES to add to eif-feature-level-kw-indent to get the | |
152 actual indentation of a feature level keyword. Can be negative.") | |
153 | |
154 (defvar eif-feature-level-comment-indent 3 | |
155 "Indentation of comments at the beginning of a feature. (in number of | |
156 eif-indent-increments)") | |
157 (defvar eif-extra-feature-level-comment-indent 0 | |
158 "Number of SPACES to add to eif-feature-level-comment-indent to get the | |
159 actual indentation of a feature level comment. Can be negative.") | |
160 | |
161 (defvar eif-body-comment-indent 0 | |
162 "Indentation of comments in the body of a routine. (in number of | |
163 eif-indent-increments)") | |
164 (defvar eif-extra-body-comment-indent 0 | |
165 "Number of SPACES to add to eif-body-comment-indent to get the | |
166 actual indentation of a routine body comment. Can be negative.") | |
167 | |
168 (defvar eif-check-keyword-indent 0 | |
169 "Extra indentation for the check clause as described in ETL. (in number of | |
170 eif-indent-increments). Default is 0, which is different than in ETL's 1.") | |
171 (defvar eif-extra-check-keyword-indent 0 | |
172 "Number of SPACES to add to eif-check-keyword-indent to get the | |
173 actual indentation of a check keyword. Can be negative.") | |
174 | |
175 (defvar eif-rescue-keyword-indent -1 | |
176 "Extra indentation for the rescue clause as described in ETL. (in number of | |
177 eif-indent-increments). Default is -1.") | |
178 (defvar eif-extra-rescue-keyword-indent 0 | |
179 "Number of SPACES to add to eif-rescue-keyword-indent to get the | |
180 actual indentation of a rescue keyword. Can be negative.") | |
181 | |
182 (defvar eif-then-indent 0 | |
183 "Indentation for a `then' appearing on a line by itself rather | |
184 than on the same line as an `if'. (in number of eif-indent-increments)") | |
185 (defvar eif-extra-then-indent 1 | |
186 "Number of SPACES to add to eif-then-indent to get the | |
187 actual indentation of a `then' appearing on a line by itself. Can be | |
188 negative.") | |
189 | |
190 (defvar eif-continuation-indent 1 | |
191 "Extra indentation for a continued statement line. (in number of eif-indent-increments)") | |
192 (defvar eif-extra-continuation-indent 0 | |
193 "Number of SPACES to add to eif-continuation-indent to get the | |
194 actual indentation of a continued statement line. Can be | |
195 negative.") | |
196 | |
197 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
198 ;;; font-lock, lhilit, and hilit19 support ;;; | |
199 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
200 | |
201 ;; The value for a font variable must either be a string | |
202 ;; specifying a valid font, the symbol 'default meaning the | |
203 ;; default font, or the symbol 'context meaning the font of the | |
204 ;; surrounding text. | |
205 ;; | |
206 ;; Simlarly, the value for a color variable must either be a string | |
207 ;; specifying a valid color, the symbol 'default meaning the | |
208 ;; default foreground color, or the symbol 'context meaning the | |
209 ;; foregound color of the surrounding text. | |
210 | |
211 (if (or (featurep 'font-lock) (featurep 'lhilit) (featurep 'hilit19)) (progn | |
212 | |
213 (cond ((eq window-system 'pm) | |
214 (defvar eif-comment-font 'default | |
215 "The font in which to display comments in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
216 (defvar eif-comment-color "firebrick" | |
217 "Color of comments in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
218 | |
219 (defvar eif-hidden-comment-font 'default | |
220 "The font in which to display hidden comments in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
221 (defvar eif-hidden-comment-color "os2darkgreen" | |
222 "Color of hidden comments in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
223 | |
224 (defvar eif-major-keyword-font 'default | |
225 "The font in which to display major keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
226 (defvar eif-major-keyword-color 'default | |
227 "Color of major keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
228 | |
229 (defvar eif-assertion-keyword-font 'default | |
230 "The font in which to display assertion keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
231 (defvar eif-assertion-keyword-color "os2darkblue" | |
232 "Color of assertion keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
233 | |
234 (defvar eif-minor-keyword-font 'default | |
235 "The font in which to display minor keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
236 (defvar eif-minor-keyword-color 'default | |
237 "Color of minor-keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
238 | |
239 (defvar eif-string-font 'default | |
240 "The font in which to display literal strings in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
241 (defvar eif-string-color "os2darkcyan" | |
242 "Color of literal strings in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
243 | |
244 (defvar eif-quoted-feature-font 'default | |
245 "The font in which to display features names enclosed in `'s in Eiffel and Ace file comments (either a font name string or 'default or 'context)") | |
246 (defvar eif-quoted-feature-color 'context | |
247 "Color of features names enclosed in `'s in Eiffel and Ace file comments (either a color name string or 'default or 'context)") | |
248 ) | |
249 | |
250 ((eq window-system 'ns) | |
251 (defvar eif-comment-font 'default | |
252 "The font in which to display comments in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
253 (defvar eif-comment-color "red3" | |
254 "Color of comments in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
255 | |
256 (defvar eif-hidden-comment-font 'default | |
257 "The font in which to display hidden comments in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
258 (defvar eif-hidden-comment-color "ForestGreen" | |
259 "Color of hidden comments in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
260 | |
261 (defvar eif-major-keyword-font "Courier-Bold" | |
262 "The font in which to display major keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
263 (defvar eif-major-keyword-color 'default | |
264 "Color of major keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
265 | |
266 (defvar eif-assertion-keyword-font "Courier-Bold" | |
267 "The font in which to display assertion keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
268 (defvar eif-assertion-keyword-color "slate blue" | |
269 "Color of assertion keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
270 | |
271 (defvar eif-minor-keyword-font "Courier-Bold" | |
272 "The font in which to display minor keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
273 (defvar eif-minor-keyword-color 'default | |
274 "Color of minor-keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
275 | |
276 (defvar eif-string-font 'default | |
277 "The font in which to display literal strings in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
278 (defvar eif-string-color "sienna" | |
279 "Color of literal strings in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
280 | |
281 (defvar eif-quoted-feature-font 'default | |
282 "The font in which to display features names enclosed in `'s in Eiffel and Ace file comments (either a font name string or 'default or 'context)") | |
283 (defvar eif-quoted-feature-color 'context | |
284 "Color of features names enclosed in `'s in Eiffel and Ace file comments (either a color name string or 'default or 'context)") | |
285 ) | |
286 | |
287 ((eq window-system 'x) | |
288 (defvar eif-comment-font 'default | |
289 "The font in which to display comments in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
290 (defvar eif-comment-color "red3" | |
291 "Color of comments in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
292 | |
293 (defvar eif-hidden-comment-font 'default | |
294 "The font in which to display hidden comments in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
295 (defvar eif-hidden-comment-color "ForestGreen" | |
296 "Color of hidden comments in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
297 | |
298 (defvar eif-major-keyword-font "-*-fixed-bold-*-*-*-*-100-*-*-*-*-*-*" | |
299 "The font in which to display major keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
300 (defvar eif-major-keyword-color 'default | |
301 "Color of major keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
302 | |
303 (defvar eif-assertion-keyword-font "-*-fixed-bold-*-*-*-*-100-*-*-*-*-*-*" | |
304 "The font in which to display assertion keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
305 (defvar eif-assertion-keyword-color "slate blue" | |
306 "Color of assertion keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
307 | |
308 (defvar eif-minor-keyword-font "-*-fixed-bold-*-*-*-*-100-*-*-*-*-*-*" | |
309 "The font in which to display minor keywords in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
310 (defvar eif-minor-keyword-color 'default | |
311 "Color of minor-keywords in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
312 | |
313 (defvar eif-string-font 'default | |
314 "The font in which to display literal strings in Eiffel and Ace files (either a font name string or 'default or 'context)") | |
315 (defvar eif-string-color "sienna" | |
316 "Color of literal strings in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
317 | |
318 (defvar eif-quoted-feature-font "-*-times-medium-i-*-*-*-120-*-*-*-*-*-*" | |
319 "The font in which to display features names enclosed in `'s in Eiffel and Ace file comments (either a font name string or 'default or 'context)") | |
320 (defvar eif-quoted-feature-color 'context | |
321 "Color of features names enclosed in `'s in Eiffel and Ace file comments (either a color name string or 'default or 'context)") | |
322 ) | |
323 ) | |
324 | |
325 (defvar default-foreground-color 'default | |
326 "Default text color in Eiffel and Ace files (either a color name string or 'default or 'context)") | |
327 | |
328 (defvar disable-color nil "Should hilighting not use colors") | |
329 | |
330 | |
331 (defun eif-set-foreground (face color) | |
332 "Set the FACE's foreground color to COLOR if COLOR is a string, to the default foreground color if COLOR is 'default, or to the color of the surrounding text if COLOR is 'context" | |
333 (cond ((stringp color) | |
334 ;; If the specified color is not useable, use 'default: | |
335 (condition-case error | |
336 (set-face-foreground face color) | |
337 (error | |
338 (progn | |
339 (message "eif-set-foreground failed for face %s and color %s. Setting to 'default" face color) | |
340 (eif-set-foreground face 'default))) | |
341 ) | |
342 ) | |
343 ((eq color 'context) | |
344 (remove-face-property face 'foreground) | |
345 ) | |
346 ((eq color 'default) | |
347 (set-face-foreground face (face-foreground 'default)) | |
348 ) | |
349 ) | |
350 ) | |
351 | |
352 (defun eif-set-font (face font) | |
353 "Set the FACE's font to FONT if FONT is a string, to the default font if FONT is 'default, or to the font of the surrounding text if FONT is 'context" | |
354 (cond ((stringp font) | |
355 ;; If the specified font is not useable, use 'default: | |
356 (condition-case error | |
357 (set-face-font face font) | |
358 (error | |
359 (progn | |
360 (message "eif-set-font failed for face %s and font %s. Setting to 'default" face font) | |
361 (eif-set-font face 'default))) | |
362 ) | |
363 ) | |
364 ((eq font 'context) | |
365 (set-face-font face nil) | |
366 ) | |
367 ((eq font 'default) | |
368 (set-face-font face (face-font 'default)) | |
369 ) | |
370 ) | |
371 ) | |
372 | |
373 (defun eif-supports-color-p () | |
374 (and (not disable-color) | |
375 (or (and (fboundp 'display-color-p) | |
376 (display-color-p)) | |
377 (and (fboundp 'x-display-color-p) | |
378 (x-display-color-p)) | |
379 (and (fboundp 'x-color-display-p) | |
380 (x-color-display-p)) | |
381 ) | |
382 ) | |
383 ) | |
384 | |
385 (defun eif-init-color () | |
386 "Reset the Eiffel fonts and faces from the values of their repective variables" | |
387 (make-face 'eif-comment) | |
388 (make-face 'eif-hidden-comment) | |
389 (make-face 'eif-major-keyword) | |
390 (make-face 'eif-minor-keyword) | |
391 (make-face 'eif-quoted-feature) | |
392 (make-face 'eif-assertion) | |
393 (make-face 'eif-string) | |
394 | |
395 (if (eif-supports-color-p) | |
396 (progn | |
397 (eif-set-foreground 'eif-comment eif-comment-color) | |
398 (eif-set-font 'eif-comment eif-comment-font) | |
399 (eif-set-foreground 'eif-hidden-comment eif-hidden-comment-color) | |
400 (eif-set-font 'eif-hidden-comment eif-hidden-comment-font) | |
401 (eif-set-foreground 'eif-quoted-feature eif-quoted-feature-color) | |
402 (eif-set-font 'eif-quoted-feature eif-quoted-feature-font) | |
403 (eif-set-foreground 'eif-major-keyword eif-major-keyword-color) | |
404 (eif-set-font 'eif-major-keyword eif-major-keyword-font) | |
405 (eif-set-foreground 'eif-minor-keyword eif-minor-keyword-color) | |
406 (eif-set-font 'eif-minor-keyword eif-minor-keyword-font) | |
407 (eif-set-foreground 'eif-assertion eif-assertion-keyword-color) | |
408 (eif-set-font 'eif-assertion eif-assertion-keyword-font) | |
409 (eif-set-foreground 'eif-string eif-string-color) | |
410 (eif-set-font 'eif-string eif-string-font) | |
411 ) | |
412 (eif-set-foreground 'eif-comment default-foreground-color) | |
413 (eif-set-font 'eif-comment eif-comment-font) | |
414 (eif-set-foreground 'eif-hidden-comment default-foreground-color) | |
415 (eif-set-font 'eif-hidden-comment eif-hidden-comment-font) | |
416 (eif-set-foreground 'eif-quoted-feature default-foreground-color) | |
417 (eif-set-font 'eif-quoted-feature eif-quoted-feature-font) | |
418 (eif-set-foreground 'eif-major-keyword default-foreground-color) | |
419 (eif-set-font 'eif-major-keyword eif-major-keyword-font) | |
420 (eif-set-foreground 'eif-minor-keyword default-foreground-color) | |
421 (eif-set-font 'eif-minor-keyword eif-minor-keyword-font) | |
422 (eif-set-foreground 'eif-assertion default-foreground-color) | |
423 (eif-set-font 'eif-assertion eif-assertion-keyword-font) | |
424 (eif-set-foreground 'eif-string default-foreground-color) | |
425 (eif-set-font 'eif-string eif-string-font) | |
426 ) | |
427 | |
428 (cond ((featurep 'font-lock) | |
429 (copy-face 'eif-comment 'font-lock-comment-face) | |
430 (copy-face 'eif-string 'font-lock-string-face) | |
431 ) | |
432 ((and (featurep 'hilit19) | |
433 (not (eq 'eif-comment (car hilit-predefined-face-list))) | |
434 ) | |
435 (setq hilit-predefined-face-list | |
436 (append '(eif-comment | |
437 eif-hidden-comment | |
438 eif-major-keyword | |
439 eif-minor-keyword | |
440 eif-quoted-feature | |
441 eif-assertion | |
442 eif-string | |
443 ) | |
444 hilit-predefined-face-list | |
445 ) | |
446 ) | |
447 ) | |
448 ) | |
449 ) | |
450 | |
451 (eif-init-color) | |
452 | |
453 )) ;; matches "(if () (progn" above that checks for a highlighting package | |
454 | |
455 (cond ((featurep 'font-lock) | |
456 (copy-face 'eif-comment 'font-lock-comment-face) | |
457 (copy-face 'eif-string 'font-lock-string-face) | |
458 (defconst eiffel-font-lock-keywords | |
459 (purecopy | |
460 '(;; major keywords | |
461 ("\\(^[ \t]*\\|[ \t]+\\)creation\\|^deferred[ \t]+class\\|^expanded[ \t]+class\\|^class\\|^feature\\|^indexing\\|\\(^[ \t]*\\|[ \t]+\\)inherit\\|^obsolete" 0 eif-major-keyword nil) | |
462 ;; assertions | |
463 ("\\(^\\|[^_\n]\\<\\)\\(check\\|ensure then\\|ensure\\|invariant\\|require else\\|require\\|variant\\)\\($\\|\\>[^_\n]\\)" 2 eif-assertion nil) | |
464 ;; minor keywords | |
465 ("\\(^\\|[^_\n]\\<\\)\\(alias\\|all\\|and not\\|and then\\|and\\|as\\|debug\\|deferred\\|do\\|else\\|elseif\\|end\\|export\\|external\\|from\\|frozen\\|if not\\|if\\|implies not\\|implies\\|infix\\|inspect\\|is deferred\\|is unique\\|is\\|like\\|local\\|loop\\|not\\|obsolete\\|old\\|once\\|or else\\|or not\\|or\\|prefix\\|redefine\\|rename\\|rescue\\|retry\\|select\\|strip\\|then\\|undefine\\|unique\\|until\\|when\\|xor\\)\\($\\|\\>[^_\n]\\)" 2 eif-minor-keyword nil) | |
466 ;; hidden comments | |
467 ("--|.*" 0 eif-hidden-comment t) | |
468 ;; quoted expr's in comments | |
469 ("`[^`'\n]*'" 0 eif-quoted-feature t) | |
470 ) | |
471 ) | |
472 "Regular expressions to use with font-lock mode.") | |
473 (defconst ace-font-lock-keywords | |
474 (purecopy | |
475 '(;; major keywords | |
476 ("^system\\|^default\\|^root\\|^cluster\\|^external\\|[ \t\n]end\\($\\|\\>[^_\n]\\)" 0 eif-major-keyword nil) | |
477 ;; hidden comments | |
478 ("--|.*" 0 eif-hidden-comment t) | |
479 ;; quoted expr's in comments | |
480 ("`[^`'\n]*'" 0 eif-quoted-feature t) | |
481 ) | |
482 ) | |
483 "Ace regular expressions to use with font-lock mode.") | |
484 ) | |
485 ((featurep 'lhilit) | |
486 | |
487 ;; ---- Eiffel mode ----- | |
488 ;; NOTE: The order of keywords below is generally alphabetical except | |
489 ;; when one keyword is the prefix of another (e.g. "and" & "and then") | |
490 ;; In such cases, the prefix keyword MUST be the last one. | |
491 (defvar eiffel-mode-hilit | |
492 '( | |
493 ("--|.*" nil eif-hidden-comment 4);; hidden comments | |
494 ("--[^\n|].*\\|--$" nil eif-comment 3);; comments | |
495 ("`[^`'\n]*'" nil eif-quoted-feature 5);; quoted expr's in comments | |
496 ("^creation\\|^deferred[ \t]*class\\|^expanded[ \t]*class\\|^class\\|^feature\\|^indexing\\|^inherit\\|^obsolete" nil eif-major-keyword 1);; major keywords | |
497 ("\\(^\\|[^_\n]\\<\\)\\(alias\\|all\\|and not\\|and then\\|and\\|as\\|debug\\|deferred\\|do\\|else\\|elseif\\|end\\|export\\|external\\|from\\|frozen\\|if not\\|if\\|implies not\\|implies\\|infix\\|inspect\\|is deferred\\|is unique\\|is\\|like\\|local\\|loop\\|not\\|obsolete\\|old\\|once\\|or else\\|or not\\|or\\|prefix\\|redefine\\|rename\\|rescue\\|retry\\|select\\|strip\\|then\\|undefine\\|unique\\|until\\|when\\|xor\\)\\($\\|\\>[^_\n]\\)" nil eif-minor-keyword 0 2) ;; minor keywords | |
498 ("\\(^\\|[^_\n]\\<\\)\\(check\\|ensure then\\|ensure\\|invariant\\|require else\\|require\\|variant\\)\\($\\|\\>[^_\n]\\)" nil eif-assertion 2 2) ;; assertions | |
499 ("\\(\"\"\\)\\|\\(\"\\([^\"%]\\|%.\\|%\n\\)+\"\\)" nil eif-string 2);; strings | |
500 )) | |
501 (hilit::mode-list-update "Eiffel" eiffel-mode-hilit) | |
502 ;; ---- Ace mode ----- | |
503 (defvar ace-mode-hilit | |
504 '( | |
505 ("--|.*" nil eif-hidden-comment 2);; hidden comments | |
506 ("--[^\n|].*\\|--$" nil eif-comment 1);; comments | |
507 ("`[^`'\n]*'" nil eif-quoted-feature 3);; quoted expr's in comments | |
508 ("^system\\|^default\\|^root\\|^cluster\\|^external\\|[ \t\n]end\\($\\|\\>[^_\n]\\)" nil eif-major-keyword);; major keywords | |
509 | |
510 )) | |
511 (hilit::mode-list-update "Ace" ace-mode-hilit) | |
512 ) | |
513 ;; | |
514 ;; NOTE: The hilit19 colors and fonts are _not_ set via the eif-* | |
515 ;; faces, fonts, and foreground variables defined above. They | |
516 ;; use their own face names which describe the colors and fonts | |
517 ;; to use. See hilit19.el for more info. | |
518 ((featurep 'hilit19) | |
519 | |
520 ;; ---- Eiffel mode ----- | |
521 ;; NOTE: The order of keywords below is generally alphabetical except | |
522 ;; when one keyword is the prefix of another (e.g. "and" & "and then") | |
523 ;; In such cases, the prefix keyword MUST be the last one. | |
524 (hilit-set-mode-patterns | |
525 'eiffel-mode | |
526 '( | |
527 ("--|.*" nil eif-hidden-comment 4);; hidden comments | |
528 ("--[^\n|].*\\|--$" nil eif-comment 3);; comments | |
529 ("`[^`'\n]*'" nil eif-quoted-feature 5);; quoted expr's in comments | |
530 ("^creation\\|^deferred[ \t]*class\\|^expanded[ \t]*class\\|^class\\|^feature\\|^indexing\\|^inherit\\|^obsolete" nil eif-major-keyword 1);; major keywords | |
531 ("\\(^\\|[^_\n]\\<\\)\\(alias\\|all\\|and not\\|and then\\|and\\|as\\|debug\\|deferred\\|do\\|else\\|elseif\\|end\\|export\\|external\\|from\\|frozen\\|if not\\|if\\|implies not\\|implies\\|infix\\|inspect\\|is deferred\\|is unique\\|is\\|like\\|local\\|loop\\|not\\|obsolete\\|old\\|once\\|or else\\|or not\\|or\\|prefix\\|redefine\\|rename\\|rescue\\|retry\\|select\\|strip\\|then\\|undefine\\|unique\\|until\\|when\\|xor\\)\\($\\|\\>[^_\n]\\)" 2 eif-minor-keyword 0) ;; minor keywords | |
532 ("\\(^\\|[^_\n]\\<\\)\\(check\\|ensure then\\|ensure\\|invariant\\|require else\\|require\\|variant\\)\\($\\|\\>[^_\n]\\)" 2 eif-assertion 2) ;; assertions | |
533 ("\\(\"\"\\)\\|\\(\"\\([^\"%]\\|%.\\|%\n\\)+\"\\)" nil eif-string 2);; strings | |
534 ) | |
535 ) | |
536 ;; ---- Ace mode ----- | |
537 (hilit-set-mode-patterns | |
538 'ace-mode | |
539 '( | |
540 ("--|.*" nil eif-hidden-comment 2);; hidden comments | |
541 ("--[^\n|].*\\|--$" nil eif-comment 1);; comments | |
542 ("`[^`'\n]*'" nil eif-quoted-feature 3);; quoted expr's in comments | |
543 ("^system\\|^default\\|^root\\|^cluster\\|^external\\|[ \t\n]end\\($\\|\\>[^_\n]\\)" nil eif-major-keyword);; major keywords | |
544 | |
545 ) | |
546 ) | |
547 ) | |
548 ) | |
549 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
550 ;;; No user-customizable definitions below this point. ;;; | |
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
552 | |
553 (defmacro eif-class-level-kw-indent-m () | |
554 "Indentation amount for Class level keywords (in number of spaces)." | |
555 '(+ (* eif-class-level-kw-indent eif-indent-increment) | |
556 eif-extra-class-level-kw-indent) | |
557 ) | |
558 | |
559 (defmacro eif-class-level-comment-indent-m () | |
560 "Indentation amount for Class level comments (in number of spaces)." | |
561 '(+ (* eif-class-level-comment-indent eif-indent-increment) | |
562 eif-extra-class-level-comment-indent) | |
563 ) | |
564 | |
565 (defmacro eif-inherit-level-kw-indent-m () | |
566 "Indentation amount for Inherit level keywords (in number of spaces)." | |
567 '(+ (* eif-inherit-level-kw-indent eif-indent-increment) | |
568 eif-extra-inherit-level-kw-indent) | |
569 ) | |
570 | |
571 (defmacro eif-feature-level-indent-m () | |
572 "Indentation amount for features (in number of spaces)." | |
573 '(+ (* eif-feature-level-indent eif-indent-increment) | |
574 eif-extra-feature-level-indent) | |
575 ) | |
576 | |
577 (defmacro eif-feature-level-kw-indent-m () | |
578 "Indentation amount for Feature level keywords (in number of spaces)." | |
579 '(+ (* eif-feature-level-kw-indent eif-indent-increment) | |
580 eif-extra-feature-level-kw-indent) | |
581 ) | |
582 | |
583 (defmacro eif-body-comment-indent-m () | |
584 "Indentation amount for comments in routine bodies (in number of spaces)." | |
585 '(+ (* eif-body-comment-indent eif-indent-increment) | |
586 eif-extra-body-comment-indent) | |
587 ) | |
588 | |
589 (defmacro eif-feature-level-comment-indent-m () | |
590 "Indentation amount for Feature level comments (in number of spaces)." | |
591 '(+ (* eif-feature-level-comment-indent eif-indent-increment) | |
592 eif-extra-feature-level-comment-indent) | |
593 ) | |
594 | |
595 (defmacro eif-check-keyword-indent-m () | |
596 "Indentation amount for Check keyword (in number of spaces)." | |
597 '(+ (* eif-check-keyword-indent eif-indent-increment) | |
598 eif-extra-check-keyword-indent) | |
599 ) | |
600 | |
601 (defmacro eif-rescue-keyword-indent-m () | |
602 "Indentation amount for Rescue keyword (in number of spaces)." | |
603 '(+ (* eif-rescue-keyword-indent eif-indent-increment) | |
604 eif-extra-rescue-keyword-indent) | |
605 ) | |
606 | |
607 (defmacro eif-then-indent-m () | |
608 "Indentation amount for `then' appearing on a line by itself (in number of spaces)." | |
609 '(+ (* eif-then-indent eif-indent-increment) | |
610 eif-extra-then-indent) | |
611 ) | |
612 | |
613 (defmacro eif-continuation-indent-m () | |
614 "Indentation amount for a statement continuation line (in number of spaces)." | |
615 '(+ (* eif-continuation-indent eif-indent-increment) | |
616 eif-extra-continuation-indent) | |
617 ) | |
618 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
619 ;;; Keyword Regular Expression Variables. ;;; | |
620 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
621 | |
622 (defvar eif-all-keywords-regexp | |
623 "\\(indexing\\|class\\|inherit\\|creation\\|feature\\|invariant\\|rename\ | |
624 \\|redefine\\|undefine\\|select\\|export\\|require\\|local\\|deferred\ | |
625 \\|do\\|once\\|ensure\\|alias\\|external\\|check\\|rescue\\|debug\\|if\ | |
626 \\|inspect\\|from\\|else\\|elseif\\|when\\|until\\|variant\\|loop\\|then\ | |
627 \\|obsolete\\|end\\)[^a-z0-9_]" | |
628 "Regular Expression to identify the presence of any eiffel keyword in a line. | |
629 Does not include `is'." | |
630 ) | |
631 | |
632 ;; Note invariant is handled as a special case since it is both a | |
633 ;; class-level and a from-level keyword | |
634 ;; Note obsolete is handled as a special case since it is both a | |
635 ;; class-level and a feature-level keyword | |
636 (defvar eif-class-level-keywords | |
637 "\\(indexing\\|class\\|deferred[ \t]*class\\|expanded[ \t]*class\\|inherit\\|creation\\|feature\\)[^a-z0-9_]" | |
638 "Those keywords introducing class-level clauses. Note that `invariant' | |
639 and `obsolete' are not included here since can function as more than one type of keyword. " | |
640 ) | |
641 | |
642 (defvar eif-inherit-level-keywords | |
643 "\\(rename\\|redefine\\|undefine\\|select\\|export\\)" | |
644 "Those keywords which introduce subclauses of the inherit clause." | |
645 ) | |
646 | |
647 (defvar eif-feature-level-keywords | |
648 "\\(require\\|local\\|deferred\\|do\\|once\\|ensure\\|alias\\|external\\)[^a-z0-9_]" | |
649 "Those keywords which are internal to features (in particular, routines)." | |
650 ) | |
651 | |
652 (defvar eif-end-keyword "end" "The `end' keyword.") | |
653 | |
654 (defvar eif-end-on-current-line ".*[ \t]end[ \t]*;?[ \t]*\\(--.*\\)?$" | |
655 "Regular expression to identify lines ending with the `end' keyword") | |
656 | |
657 (defvar eif-non-id-char-regexp "[^a-z0-9_]" | |
658 "The characters that are not part of identifiers.") | |
659 | |
660 (defvar eif-end-keyword-regexp "[^a-z0-9_]end[^a-z0-9_]" | |
661 "The `end' keyword with context.") | |
662 | |
663 (defvar eif-end-matching-keywords | |
664 "\\(check\\|class\\|feature\\|rename\\|redefine\\|undefine\\|select\\|export\\|do\\|once\\|deferred\\|external\\|alias\\|if\\|inspect\\|from\\|debug\\)[^a-z0-9_]" | |
665 "Those keywords whose clause is terminated by an `end' keyword." | |
666 ) | |
667 | |
668 (defvar eif-control-flow-keywords | |
669 "\\(if\\|inspect\\|from\\|debug\\)" | |
670 "Keywords which introduce control-flow constructs." | |
671 ) | |
672 | |
673 (defvar eif-control-flow-matching-keywords | |
674 "\\(deferred\\|do\\|once\\|if\\|inspect\\|from\\|debug\\)[^a-z0-9_]" | |
675 "Keywords whose occurrence prior to a control-flow-keyword causes the | |
676 indentation of the control-flow-keyword. Note that technically, | |
677 `end' is part of this list but it is handled separately in the | |
678 functions: eif-matching-indent and eif-matching-kw." | |
679 ) | |
680 | |
681 (defvar eif-check-keyword "check" "The `check' keyword.") | |
682 | |
683 (defvar eif-check-keywords "\\(check\\)[^a-z0-9_]" | |
684 "The `check' keyword (with trailing context).") | |
685 | |
686 (defvar eif-check-matching-keywords | |
687 "\\(deferred\\|do\\|once\\|if\\|inspect\\|from\\|debug\\)[^a-z0-9_]" | |
688 "Keywords whose occurrence prior to a check-keyword causes the | |
689 indentation of the check-keyword. Note that technically, `end' is | |
690 part of this list but it is handled separately in the functions: | |
691 eif-matching-indent and eif-matching-kw. (see also | |
692 eif-control-flow-matching-keywords)" | |
693 ) | |
694 | |
695 (defvar eif-rescue-keyword "rescue" "The `rescue' keyword.") | |
696 | |
697 (defvar eif-obsolete-keyword "obsolete" "The `obsolete' keyword.") | |
698 | |
699 (defvar eif-rescue-keywords "\\(rescue\\)[^a-z0-9_]" | |
700 "The `rescue' keyword (with trailing context).") | |
701 | |
702 (defvar eif-rescue-matching-keywords | |
703 "\\(deferred\\|do\\|once\\)[^a-z0-9_]" | |
704 "Keywords whose occurrence prior to a rescue-keyword causes the | |
705 indentation of the rescue-keyword. Note that technically, `end' is | |
706 part of this list but it is handled separately in the functions: | |
707 eif-matching-indent and eif-matching-kw. (see also | |
708 eif-control-flow-matching-keywords)" | |
709 ) | |
710 | |
711 (defvar eif-from-level-keywords | |
712 "\\(until\\|variant\\|loop\\)[^a-z0-9_]" | |
713 "Keywords occuring inside of a from clause." | |
714 ) | |
715 | |
716 (defvar eif-from-keyword "from" "The keyword `from'.") | |
717 | |
718 (defvar eif-if-or-inspect-level-keywords "\\(elseif\\|else\\|when\\)[^a-z0-9_]" | |
719 "Keywords occuring inside of an if or inspect clause." | |
720 ) | |
721 | |
722 (defvar eif-if-or-inspect-keyword "\\(if\\|inspect\\)[^a-z0-9_]" | |
723 "The `if' or `inspect' keywords." | |
724 ) | |
725 | |
726 (defvar eif-then-keyword ".*[ \t)]then[ \t]*$" | |
727 "The keyword `then' with possible leading text.") | |
728 | |
729 (defvar eif-solitary-then-keyword "then" "The keyword `then'.") | |
730 | |
731 (defvar eif-then-matching-keywords "\\(if\\|elseif\\|when\\)" | |
732 "Keywords whose occurrence prior to a then-keyword sets the | |
733 indentation of the then-keyword. Note that technically, `end' is | |
734 part of this list but it is handled separately in the functions: | |
735 eif-matching-indent and eif-matching-kw. (see also | |
736 eif-control-flow-matching-keywords)" | |
737 ) | |
738 | |
739 (defvar eif-invariant-keyword "invariant" "The `invariant' keyword.") | |
740 | |
741 (defvar eif-invariant-matching-keywords | |
742 "\\(from\\|feature\\)" | |
743 "Keywords whose occurrence prior to an invariant-keyword causes the | |
744 indentation of the invariant-keyword. Note that technically, `end' | |
745 is part of this list but it is handled separately in the functions: | |
746 eif-matching-indent and eif-matching-kw. (see also | |
747 eif-control-flow-matching-keywords)" | |
748 ) | |
749 | |
750 (defvar eif-obsolete-matching-keywords | |
751 "\\(is\\|class\\)" | |
752 "Keywords whose occurrence prior to an obsolete-keyword causes the | |
753 indentation of the obsolete-keyword." | |
754 ) | |
755 | |
756 (defvar eif-white-space-regexp "[ ]*" | |
757 "RE to locate whitespace.") | |
758 | |
759 (defvar eif-comment-line-regexp "[ ]*\\(--.*\\)$" | |
760 "RE to match a line with a comment on it.") | |
761 | |
762 (defvar eif-non-source-line "[ ]*\\(--.*\\)?$" | |
763 "RE to match a line with a only a comment or whitespace.") | |
764 | |
765 (defvar eif-variable-or-const-regexp "[^()\n]*:[^=].*" | |
766 "RE to match a variable or constant declaration.") | |
767 | |
768 (defvar eif-indentation-keywords-regexp | |
769 "\\(indexing\\|class\\|check\\|rescue\\|inherit\\|creation\\|feature\\|invariant\\|rename\\|redefine\\|undefine\\|select\\|export\\|require\\|local\\|deferred\\|do\\|once\\|ensure\\|alias\\|external\\|if\\|inspect\\|from\\|debug\\|else\\|elseif\\|when\\|until\\|variant\\|invariant\\|loop\\|obsolete\\)[^a-z0-9_]" | |
770 "RE to identify the presence of any eiffel keyword triggering indentation" | |
771 ) | |
772 | |
773 (defvar eif-feature-indentation-keywords-regexp | |
774 "\\(creation\\|feature\\)[^a-z0-9_]" | |
775 "Keywords which denote the presence of features following them." | |
776 ) | |
777 | |
778 (defvar eif-is-keyword-regexp "\\(.*[ )]\\)?is[ ]*\\(--.*\\)?$" | |
779 "The `is' keyword (with some context)." | |
780 ) | |
781 | |
782 (defvar eif-multiline-routine-is-keyword-regexp | |
783 ".*([^)]*)\\([ \t\n]*\\|[ \t\n]*:[][ \t\nA-Za-x0-9_,]*\\)is[ ]*\\(--.*\\)?$" | |
784 "The `is' keyword (with some context)." | |
785 ) | |
786 | |
787 (defvar eif-operator-regexp | |
788 "[ ]*\\([@*/+]\\|-[^-]\\|\\<and[ (]\\|\\<or[ (]\\)" | |
789 "Eiffel operators - used to identify continuation lines" | |
790 ) | |
791 | |
792 (defvar eif-operator-eol-regexp | |
793 ".*\\([@*/+-]\\|\\<and\\|\\<or\\|:=\\)[ ]*$" | |
794 "Eiffel operators - used to identify continuation lines" | |
795 ) | |
796 | |
797 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
798 | |
799 (defvar eif-matching-indent -1 | |
800 "The indentation of the keyword found on the last call to eif-matching-kw. | |
801 -1 if no match was found." | |
802 ) | |
803 | |
804 (defvar eif-matching-kw-for-end nil) | |
805 | |
806 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
807 ;;; Indentation Functions. ;;; | |
808 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
809 | |
810 (defun eif-calc-indent () | |
811 "Calculate the indentation of the current line of eiffel code. This | |
812 function generally assumes that the preceding line of code is | |
813 indented properly, although lines containing certain class-level | |
814 constructs do not require correct indentation of the preceding line." | |
815 (let ((indent 0) | |
816 (line-end 0) | |
817 (originally-looking-at-comment nil) | |
818 (kw-match nil) | |
819 (continuation) | |
820 (id-colon) | |
821 ) | |
822 | |
823 (save-excursion | |
824 | |
825 ;; Save location of line-end and skip past leading white space. | |
826 (end-of-line) | |
827 (setq line-end (point)) | |
828 (beginning-of-line) | |
829 (re-search-forward eif-white-space-regexp line-end t) | |
830 | |
831 ;; Is the line we are trying to indent a comment line? | |
832 (setq originally-looking-at-comment (looking-at eif-comment-line-regexp)) | |
833 | |
834 ;; Look for a keyword on the current line | |
835 (if (looking-at eif-all-keywords-regexp) | |
836 | |
837 ;; Then we are looking at a keyword | |
838 (cond ((looking-at eif-class-level-keywords) | |
839 ;; File level keywords (indent defaults to 0) | |
840 (setq indent (eif-class-level-kw-indent-m)) | |
841 ) | |
842 ((looking-at eif-inherit-level-keywords) | |
843 ;; Inherit level keywords (indent defaults to | |
844 ;; 2*eif-indent-increment) | |
845 (setq indent (eif-inherit-level-kw-indent-m)) | |
846 ) | |
847 ((looking-at eif-feature-level-keywords) | |
848 ;; Feature level keywords (indent defaults to | |
849 ;; (eif-feature-level-indent-m) + eif-indent-increment) | |
850 (setq indent (eif-feature-level-kw-indent-m)) | |
851 ) | |
852 ((looking-at eif-end-keyword) | |
853 ;; End keyword (indent to level of matching keyword) | |
854 (if (string-match "end" | |
855 (eif-matching-kw eif-end-matching-keywords)) | |
856 ;; Then | |
857 (if (= eif-matching-indent | |
858 (eif-feature-level-kw-indent-m)) | |
859 ;; Then | |
860 (setq indent (eif-class-level-kw-indent-m)) | |
861 ;; Else | |
862 (setq indent | |
863 (- eif-matching-indent eif-indent-increment)) | |
864 ) | |
865 ;; Else | |
866 (setq indent eif-matching-indent) | |
867 ) | |
868 (if (<= indent (eif-feature-level-indent-m)) | |
869 (save-excursion | |
870 (end-of-line) | |
871 (while (and (< (point) (point-max)) | |
872 (or (forward-char 1) t) | |
873 (looking-at eif-non-source-line) | |
874 ) | |
875 (end-of-line) | |
876 ) | |
877 (if (not (looking-at eif-non-source-line)) | |
878 (setq indent (eif-inherit-level-kw-indent-m)) | |
879 (setq indent (eif-class-level-kw-indent-m)) | |
880 ) | |
881 ) | |
882 ) | |
883 ) | |
884 ((looking-at eif-control-flow-keywords) | |
885 ;; Control flow keywords | |
886 ;; Indent to same level as a preceding "end" or | |
887 ;; if no preceding "end" is found, indent to the level | |
888 ;; of the preceding "do" plus the value of | |
889 ;; eif-indent-increment | |
890 (setq kw-match | |
891 (eif-matching-kw eif-control-flow-matching-keywords)) | |
892 (cond ((string-match "end" kw-match) | |
893 (setq indent eif-matching-indent) | |
894 ) | |
895 (t | |
896 (setq indent | |
897 (+ eif-matching-indent eif-indent-increment) | |
898 ) | |
899 ) | |
900 ) | |
901 ) | |
902 ((looking-at eif-check-keywords) | |
903 ;; Check keyword | |
904 ;; Indent to level of preceding "end"+eif-indent-increment or | |
905 ;; if no preceding "end" is found, indent to the level | |
906 ;; of the preceding eif-check-matching-keywords plus the | |
907 ;; value (eif-indent-increment + eif-check-keyword-indent). | |
908 (setq kw-match (eif-matching-kw eif-check-matching-keywords)) | |
909 (cond ((string-match "end" kw-match) | |
910 (setq indent (+ eif-matching-indent | |
911 (eif-check-keyword-indent-m) | |
912 ) | |
913 ) | |
914 ) | |
915 (t | |
916 (setq indent | |
917 (+ eif-matching-indent | |
918 (+ eif-indent-increment | |
919 (eif-check-keyword-indent-m) | |
920 ) | |
921 ) | |
922 ) | |
923 ) | |
924 ) | |
925 ) | |
926 ((looking-at eif-rescue-keywords) | |
927 ;; Rescue keyword | |
928 ;; Indent to level of preceding "end"+eif-indent-increment or | |
929 ;; if no preceding "end" is found, indent to the level | |
930 ;; of the preceding eif-rescue-matching-keywords plus the | |
931 ;; value (eif-indent-increment + eif-rescue-keyword-indent). | |
932 (setq kw-match (eif-matching-kw eif-rescue-matching-keywords)) | |
933 (cond ((string-match "end" kw-match) | |
934 (setq indent (+ eif-matching-indent | |
935 (eif-rescue-keyword-indent-m) | |
936 ) | |
937 ) | |
938 ) | |
939 (t | |
940 (setq indent eif-matching-indent) | |
941 ) | |
942 ) | |
943 ) | |
944 ((looking-at eif-from-level-keywords) | |
945 ;; From level keywords (indent to level of matching "From") | |
946 (if (string-match "end" (eif-matching-kw eif-from-keyword)) | |
947 ;; Closest matching KW is `end'. | |
948 (setq indent (- eif-matching-indent eif-indent-increment)) | |
949 ;; Closest matching KW is one of `eif-from-keyword'. | |
950 (setq indent eif-matching-indent) | |
951 ) | |
952 ) | |
953 ((looking-at eif-if-or-inspect-level-keywords) | |
954 ;; If level keywords (indent to level of matching | |
955 ;; "If" or "Inspect") | |
956 (if (string-match "end" | |
957 (eif-matching-kw eif-if-or-inspect-keyword) | |
958 ) | |
959 ;; Closest matching KW is `end'. | |
960 (setq indent (- eif-matching-indent eif-indent-increment)) | |
961 ;; Closest matching KW is one of `eif-if-or-inspect-keyword'. | |
962 (setq indent eif-matching-indent) | |
963 ) | |
964 ) | |
965 ((looking-at eif-solitary-then-keyword) | |
966 ;; Handles case where "then" appears on a line by itself | |
967 ;; (Indented to the level of the matching if, elseif or when) | |
968 (setq indent (+ (eif-matching-indent eif-then-matching-keywords) | |
969 (eif-then-indent-m) | |
970 ) | |
971 ) | |
972 ) | |
973 ((looking-at eif-invariant-keyword) | |
974 ;; Invariant keyword | |
975 ;; (Indented to the level of the matching from or feature) | |
976 (if (string-match "from" | |
977 (eif-matching-kw eif-invariant-matching-keywords) | |
978 ) | |
979 ;; Then - loop invariant | |
980 (setq indent eif-matching-indent) | |
981 ;; Else - class invariant | |
982 (setq indent (eif-class-level-kw-indent-m)) | |
983 ) | |
984 ) | |
985 ((looking-at eif-obsolete-keyword) | |
986 ;; Obsolete keyword | |
987 ;; (Indented to the level of the matching from or feature) | |
988 (if (string-match "is" | |
989 (eif-matching-kw eif-obsolete-matching-keywords) | |
990 ) | |
991 ;; Then - feature obsolete | |
992 (setq indent (eif-feature-level-kw-indent-m)) | |
993 ;; Else - class obsolete | |
994 (setq indent (eif-class-level-kw-indent-m)) | |
995 ) | |
996 ) ;; end of cond | |
997 ) | |
998 | |
999 ;; Else no keyword on current line, | |
1000 ;; are we in a multi-line parenthesis expression | |
1001 | |
1002 (if (or (and (> (eif-in-paren-expression) 0) | |
1003 (> (setq indent (eif-indent-multi-line)) -1) | |
1004 ) | |
1005 (setq indent (eif-manifest-array-indent)) | |
1006 ) | |
1007 | |
1008 ;; multi-line parenthesis expression | |
1009 ;; Move string continuation lines one column to the left | |
1010 (if (looking-at "%") | |
1011 (setq indent (1- indent)) | |
1012 ) | |
1013 | |
1014 ;; Else Find the first preceding line with non-comment source on it | |
1015 ;; that is not a continuation line of a multi-line parnethesized | |
1016 ;; expression. | |
1017 | |
1018 ;; Record whether this line begins with an operator. We assume | |
1019 ;; that the line is a continuation line if it begins with an operator | |
1020 (beginning-of-line) | |
1021 (if (looking-at eif-operator-regexp) | |
1022 (setq continuation t) | |
1023 (setq continuation nil) | |
1024 ) | |
1025 ;; Record whether the line being indented begins with an "<id> :" | |
1026 ;; This is used in indenting assertion tag expressions. | |
1027 (if (looking-at "[ ]*[a-zA-Z0-9_]+[ ]*:") | |
1028 (setq id-colon t) | |
1029 (setq id-colon nil) | |
1030 ) | |
1031 | |
1032 (forward-line -1) | |
1033 (beginning-of-line) | |
1034 (while (and (looking-at eif-non-source-line) (not (= (point) 1))) | |
1035 (previous-line 1) | |
1036 (beginning-of-line) | |
1037 ) | |
1038 (if (eif-line-contains-close-paren) | |
1039 (backward-sexp) | |
1040 ) | |
1041 (end-of-line) | |
1042 (setq line-end (point)) | |
1043 (beginning-of-line) | |
1044 (re-search-forward eif-white-space-regexp line-end t) | |
1045 | |
1046 (cond ((and (= (point) 1) | |
1047 originally-looking-at-comment | |
1048 (setq indent (eif-class-level-comment-indent-m)) | |
1049 ) | |
1050 ) | |
1051 ;; 'eif-is-keyword-regexp' case must precede | |
1052 ;; '(not eif-all-keywords-regexp)' case since "is" is not | |
1053 ;; part of 'eif-all-keywords-regexp' | |
1054 ((or (looking-at eif-is-keyword-regexp) | |
1055 (looking-at eif-multiline-routine-is-keyword-regexp) | |
1056 (looking-at eif-obsolete-keyword) | |
1057 ) | |
1058 (if originally-looking-at-comment | |
1059 ;; Then the line we are trying to indent is a comment | |
1060 (setq indent (eif-feature-level-comment-indent-m)) | |
1061 ;; Else the line being indented is not a comment | |
1062 (setq indent (eif-feature-level-kw-indent-m)) | |
1063 ) | |
1064 ) | |
1065 ((looking-at eif-feature-indentation-keywords-regexp) | |
1066 (setq indent (eif-feature-level-indent-m)) | |
1067 ) | |
1068 ((looking-at eif-indentation-keywords-regexp) | |
1069 (if (looking-at eif-end-on-current-line) | |
1070 (setq indent (eif-current-line-indent)) | |
1071 (setq indent | |
1072 (+ (eif-current-line-indent) eif-indent-increment)) | |
1073 ) | |
1074 ) | |
1075 ((looking-at eif-solitary-then-keyword) | |
1076 (setq indent (- (+ (eif-current-line-indent) eif-indent-increment) | |
1077 (eif-then-indent-m) | |
1078 ) | |
1079 ) | |
1080 ) | |
1081 ((looking-at eif-then-keyword) | |
1082 (setq indent (eif-current-line-indent)) | |
1083 ) | |
1084 ((looking-at (concat eif-end-keyword eif-non-id-char-regexp)) | |
1085 (if (= (setq indent (eif-current-line-indent)) | |
1086 (eif-feature-level-kw-indent-m) | |
1087 ) | |
1088 (setq indent (eif-feature-level-indent-m)) | |
1089 (eif-matching-line) | |
1090 (if (string-match eif-check-keyword eif-matching-kw-for-end) | |
1091 (setq indent (- indent (eif-check-keyword-indent-m))) | |
1092 ) | |
1093 ) | |
1094 ) | |
1095 ((looking-at eif-variable-or-const-regexp) | |
1096 ;;Either a variable declaration or a pre or post condition tag | |
1097 (if originally-looking-at-comment | |
1098 ;; Then the line we are trying to indent is a comment | |
1099 (if (= (setq indent (eif-current-line-indent)) | |
1100 (eif-feature-level-indent-m) | |
1101 ) | |
1102 ;; Then - a feature level comment | |
1103 (setq indent (eif-feature-level-comment-indent-m)) | |
1104 ;; Else - some other kind of comment | |
1105 (setq indent (+ indent (eif-body-comment-indent-m))) | |
1106 ) | |
1107 ;; Else the line being indented is not a comment | |
1108 (if (setq indent (eif-indent-assertion-continuation id-colon)) | |
1109 indent | |
1110 (setq indent (eif-current-line-indent)) | |
1111 ) | |
1112 ) | |
1113 ) | |
1114 ((setq indent (eif-manifest-array-start)) | |
1115 indent | |
1116 ) | |
1117 ((not (looking-at eif-all-keywords-regexp)) | |
1118 (if originally-looking-at-comment | |
1119 ;; Then the line we are trying to indent is a comment | |
1120 (cond ((eif-continuation-line) | |
1121 (setq indent | |
1122 (+ (- (eif-current-line-indent) | |
1123 eif-indent-increment | |
1124 ) | |
1125 (eif-body-comment-indent-m) | |
1126 ) | |
1127 ) | |
1128 ) | |
1129 ;; preceding line is at eif-feature-level-indent - | |
1130 ;; assume that the preceding line is a parent | |
1131 ;; class in an inherit clause | |
1132 ((= (eif-current-line-indent) | |
1133 (eif-feature-level-indent-m) | |
1134 ) | |
1135 (setq indent | |
1136 (+ (eif-inherit-level-kw-indent-m) | |
1137 (eif-body-comment-indent-m) | |
1138 ) | |
1139 ) | |
1140 ) | |
1141 (t | |
1142 (setq indent | |
1143 (+ (eif-current-line-indent) | |
1144 (eif-body-comment-indent-m) | |
1145 ) | |
1146 ) | |
1147 ) | |
1148 ) | |
1149 ;; Else line being indented is not a comment | |
1150 | |
1151 ;; The line the point is on is the one above the line being | |
1152 ;; indented | |
1153 (beginning-of-line) | |
1154 (if (or continuation (looking-at eif-operator-eol-regexp)) | |
1155 ;; Then the line being indented is a continuation line | |
1156 (if (eif-continuation-line) | |
1157 ;; The line preceding the line being indented is | |
1158 ;; also a continuation line. Indent to the current | |
1159 ;; line indentation. | |
1160 (setq indent (eif-current-line-indent)) | |
1161 ;; Else The line preceding the line being indented is | |
1162 ;; not a continuation line. Indent an extra | |
1163 ;; eif-continuation-indent | |
1164 (setq indent (+ (eif-current-line-indent) | |
1165 (eif-continuation-indent-m))) | |
1166 ) | |
1167 ;; Else the line being indented is not a continuation line. | |
1168 (if (eif-continuation-line) | |
1169 (if id-colon | |
1170 ;; Then the line preceding the one being indented | |
1171 ;; is an assertion continuation. Indent the current | |
1172 ;; line to the same level as the preceding assertion | |
1173 ;; tag. | |
1174 (setq indent (eif-indent-assertion-tag)) | |
1175 ;; Then the line preceding the one being indented is | |
1176 ;; a continuation line. Un-indent by an | |
1177 ;; eif-continuation-indent. | |
1178 (setq indent (- (eif-current-line-indent) | |
1179 eif-indent-increment | |
1180 ) | |
1181 ) | |
1182 ) | |
1183 ;; Else the line preceding the line being indented is | |
1184 ;; also not a continuation line. Use the current indent. | |
1185 (setq indent (eif-current-line-indent)) | |
1186 ) | |
1187 ) | |
1188 ) | |
1189 ) | |
1190 ) ;; cond | |
1191 ) ;; if | |
1192 ) ;; if | |
1193 ) ;; save-excursion | |
1194 indent | |
1195 ) ;; let | |
1196 ) | |
1197 | |
1198 (defun eif-continuation-line () | |
1199 (or (looking-at eif-operator-regexp) | |
1200 (save-excursion | |
1201 (forward-line -1) | |
1202 (beginning-of-line) | |
1203 (looking-at eif-operator-eol-regexp) | |
1204 ) | |
1205 ) | |
1206 ) | |
1207 | |
1208 (defun eif-indent-assertion-continuation (id-colon) | |
1209 "Are we inside a pre or a post condition clause on a line that is a | |
1210 continuation of a multi-line assertion beginning with a tag? If so, return | |
1211 the indentation of the continuation line." | |
1212 (let ((limit (point))) | |
1213 (if (save-excursion | |
1214 (if (re-search-backward (concat eif-feature-level-keywords "\\|" | |
1215 eif-end-keyword-regexp) nil t) | |
1216 (if (looking-at "ensure\\|require") | |
1217 (setq limit (point)) | |
1218 nil | |
1219 ) | |
1220 nil | |
1221 ) | |
1222 ) | |
1223 (save-excursion | |
1224 (end-of-line) | |
1225 (if (and (not id-colon) (re-search-backward ": *" limit t)) | |
1226 (progn | |
1227 (goto-char (match-end 0)) | |
1228 (current-column) | |
1229 ) | |
1230 nil | |
1231 ) | |
1232 ) | |
1233 nil | |
1234 ) | |
1235 ) | |
1236 ) | |
1237 | |
1238 (defun eif-indent-assertion-tag () | |
1239 "Are we inside a pre or a post condition clause on a line that is a | |
1240 continuation of a multi-line assertion beginning with a tag? If so, return | |
1241 the indentation of the continuation line." | |
1242 (let (indent) | |
1243 (save-excursion | |
1244 (if (re-search-backward "ensure\\|require\\|variant\\|invariant" nil t) | |
1245 (setq indent (+ (eif-current-line-indent) eif-indent-increment)) | |
1246 ;; This option should not occur | |
1247 (error "Could not find assertion tag.") | |
1248 ) | |
1249 ) | |
1250 ) | |
1251 ) | |
1252 | |
1253 (defun eif-matching-indent (matching-keyword-regexp) | |
1254 "Search backward from the point looking for one of the keywords | |
1255 in the MATCHING-KEYWORD-REGEXP. Return the indentation of the | |
1256 keyword found. If an `end' keyword occurs prior to finding one of | |
1257 the keywords in MATCHING-KEYWORD-REGEXP and it terminates a check | |
1258 clause, return the indentation of the `end' minus the value of | |
1259 eif-check-keyword-indent." | |
1260 (let ((search-regexp (concat "[^a-z0-9A-Z_]" | |
1261 eif-end-keyword | |
1262 "[^a-z0-9A-Z_]\\|[^a-z0-9A-Z_]" | |
1263 matching-keyword-regexp | |
1264 ) | |
1265 ) | |
1266 (indent 0) | |
1267 (continue t) | |
1268 ) | |
1269 (save-excursion | |
1270 (while (and (re-search-backward search-regexp 1 t) | |
1271 (or (eif-in-quoted-string-p) | |
1272 (eif-in-comment-p) | |
1273 ) | |
1274 ) | |
1275 ) | |
1276 (if (looking-at search-regexp) | |
1277 ;; Then | |
1278 (if (and (looking-at eif-end-keyword-regexp) | |
1279 (eif-matching-line) | |
1280 (string-match eif-check-keyword eif-matching-kw-for-end) | |
1281 ) | |
1282 ;; The keyword "end" was found that terminated a "check" clause | |
1283 (setq indent (- (eif-current-line-indent) (eif-check-keyword-indent-m))) | |
1284 ;; Else a keyword in "matching-keyword-regexp" or a normal | |
1285 ;; "end"was found | |
1286 (setq indent (eif-current-line-indent)) | |
1287 ) | |
1288 ;; Else | |
1289 (message "No matching indent keyword was found") | |
1290 ) | |
1291 indent | |
1292 | |
1293 ) | |
1294 ) | |
1295 ) | |
1296 | |
1297 (defun eif-matching-kw (matching-keyword-regexp) | |
1298 "Search backward from the point looking for one of the keywords in | |
1299 the MATCHING-KEYWORD-REGEXP. Return the keyword found. Also set the | |
1300 value of eif-matching-indent to the indentation of the keyword | |
1301 found. If an `end' keyword occurs prior to finding one of the | |
1302 keywords in MATCHING-KEYWORD-REGEXP and it terminates a check | |
1303 clause, set the value of eif-matching-indent to the indentation of | |
1304 the `end' minus the value of eif-check-keyword-indent." | |
1305 (let ((search-regexp (concat "[^a-z0-9A-Z_.]" | |
1306 eif-end-keyword | |
1307 "[^a-z0-9A-Z_.]\\|[^a-z0-9A-Z_.]" | |
1308 matching-keyword-regexp | |
1309 ) | |
1310 ) | |
1311 (keyword "") | |
1312 ) | |
1313 (save-excursion | |
1314 ;; Search backward for a matching keyword. | |
1315 (while (and (re-search-backward search-regexp 1 t) | |
1316 (or (eif-in-quoted-string-p) | |
1317 (eif-in-comment-p) | |
1318 ) | |
1319 ) | |
1320 ) | |
1321 (if (looking-at search-regexp) | |
1322 ;; Then - a keyword was found | |
1323 (progn | |
1324 (setq keyword | |
1325 (buffer-substring (match-beginning 0) (match-end 0)) | |
1326 ) | |
1327 (if (and (looking-at eif-end-keyword-regexp) | |
1328 (eif-matching-line) | |
1329 (string-match eif-check-keyword eif-matching-kw-for-end) | |
1330 ) | |
1331 ;; Then | |
1332 (setq eif-matching-indent | |
1333 (- (eif-current-line-indent) (eif-check-keyword-indent-m)) | |
1334 ) | |
1335 ;; Else | |
1336 (setq eif-matching-indent (eif-current-line-indent)) | |
1337 ) | |
1338 ) | |
1339 ;; Else no keyword was found. I think this is an error | |
1340 (setq eif-matching-indent 0) | |
1341 (message "No matching indent keyword was found") | |
1342 ) | |
1343 keyword | |
1344 ) | |
1345 ) | |
1346 ) | |
1347 | |
1348 (defun eif-current-line-indent () | |
1349 "Return the indentation of the line containing the point." | |
1350 (save-excursion | |
1351 (let ((line-end 0) | |
1352 (indent 0) | |
1353 ) | |
1354 (end-of-line) | |
1355 (setq line-end (point)) | |
1356 (beginning-of-line) | |
1357 (re-search-forward eif-white-space-regexp line-end t) | |
1358 (setq indent (current-column)) | |
1359 ) | |
1360 ) | |
1361 ) | |
1362 | |
1363 (defun eif-line-contains-close-paren () | |
1364 "This function returns t if the current line contains a close paren and | |
1365 nil otherwise. If a close paren is found, the point is placed immediately | |
1366 after the last close paren on the line. If no paren is found, the point is | |
1367 placed at the beginning of the line." | |
1368 (let ((search-min 0)) | |
1369 (beginning-of-line) | |
1370 (setq search-min (point)) | |
1371 (end-of-line) | |
1372 (if (search-backward ")" search-min t) | |
1373 ;; Then | |
1374 (progn | |
1375 (forward-char 1) | |
1376 t | |
1377 ) | |
1378 ;; Else | |
1379 (beginning-of-line) | |
1380 nil | |
1381 ) | |
1382 ) | |
1383 ) | |
1384 | |
1385 ;;;; Not Currently Used | |
1386 ;;;(defun eif-quoted-string-on-line-p () | |
1387 ;;; "t if an Eiffel quoted string begins, ends, or is continued | |
1388 ;;; on current line." | |
1389 ;;; (save-excursion | |
1390 ;;; (beginning-of-line) | |
1391 ;;; ;; Line must either start with optional whitespace immediately followed | |
1392 ;;; ;; by a '%' or include a '\"'. It must either end with a '%' character | |
1393 ;;; ;; or must include a second '\"' character. | |
1394 ;;; (looking-at "^\\([ \t]*%\\|[^\"\n]*\"\\)[^\"\n]*\\(%$\\|\"\\)") | |
1395 ;;; ) | |
1396 ;;;) | |
1397 | |
1398 (defun eif-in-quoted-string-p (&optional non-strict-p) | |
1399 "t if point is in a quoted string. Optional argument NON-STRICT-P if true | |
1400 causes the function to return true even if the point is located in leading | |
1401 white space on a continuation line. Normally leading white space is not | |
1402 considered part of the string." | |
1403 (let ((initial-regexp "^[ \t]*%\\|[^%]\"\\|%[ \t]*$") | |
1404 (search-limit (point)) | |
1405 (count 0) | |
1406 ) | |
1407 (save-excursion | |
1408 ;; Line must either start with optional whitespace immediately followed | |
1409 ;; by a '%' or include a '\"' before the search-limit. | |
1410 (beginning-of-line) | |
1411 (while (re-search-forward initial-regexp search-limit t) | |
1412 (setq count (1+ count)) | |
1413 (if (= count 1) (setq search-limit (1+ search-limit))) | |
1414 ) | |
1415 ;; If the number of quotes (including continuation line markers) is odd, | |
1416 ;; then we are inside of a string. Also if non-strict-p and we are in | |
1417 ;; the leading white space of a continuation line, then we are in a quote. | |
1418 (if (= (% count 2) 1) | |
1419 t | |
1420 (beginning-of-line) | |
1421 (if non-strict-p | |
1422 (if (looking-at "^[ \t]*%") | |
1423 t | |
1424 nil | |
1425 ) | |
1426 nil | |
1427 );; if | |
1428 );; if | |
1429 );; save-excursion | |
1430 );; let | |
1431 );; e-in-quoted-string | |
1432 | |
1433 (defvar eif-opening-regexp | |
1434 "\\<\\(external\\|check\\|deferred\\|do\\|once\\|from\\|if\\|inspect\\)\\>" | |
1435 "Keywords that open eiffel nesting constructs." | |
1436 ) | |
1437 (defvar eif-closing-regexp "\\<end\\>" | |
1438 "Keywords that close eiffel nesting constructs." | |
1439 ) | |
1440 (defvar eif-do-regexp "\\<do\\|once\\|external\\>" | |
1441 "Keyword that opens eiffel routine body." | |
1442 ) | |
1443 (defvar eif-opening-or-closing-regexp | |
1444 (concat "\\(" eif-opening-regexp "\\|" eif-closing-regexp "\\)") | |
1445 "Keywords that open or close eiffel nesting constructs." | |
1446 ) | |
1447 | |
1448 ;;; | |
1449 ;;; Code to allow indenting whole eiffel blocks | |
1450 ;;; | |
1451 | |
1452 (defun eif-matching-line (&optional return-line-break direction) | |
1453 "Return the character position of the keyword matching the eiffel | |
1454 keyword on the current line. (e.g. a line containing the keyword | |
1455 'do' is matched by a line containing the keyword 'end' and a line | |
1456 containing 'end' may be matched by a number of opening keywords. | |
1457 If the optional parameter 'return-line-break' is not nil, the | |
1458 character position returned is the beginning (or end) of the line | |
1459 containing the matching keyword instead of the position of the | |
1460 keyword itself. If the second optional parameter, direction, is | |
1461 non-null, the current line is not searched for a keyword. Instead, | |
1462 if the value of direction is 'forward, the function acts as if | |
1463 an eif-opening-regexp is on the current line. If the value of direction | |
1464 is 'backward, the function acts as if a eif-closing-regexp is on the | |
1465 current line. The effect of using the direction parameter is to | |
1466 locate either the opening or closing keyword of the syntactic | |
1467 construct containing the point." | |
1468 (let ((nesting-level 0) | |
1469 (matching-point nil) | |
1470 (search-end 0) | |
1471 (opening-keyword nil) | |
1472 (match-start nil) | |
1473 (match-end nil) | |
1474 (success nil) | |
1475 (start-point nil) | |
1476 ) | |
1477 (unwind-protect | |
1478 (save-excursion | |
1479 (modify-syntax-entry ?_ "w ") | |
1480 (setq eif-matching-kw-for-end "");; public variable set by this function | |
1481 (setq start-point (point)) | |
1482 (end-of-line) | |
1483 (setq search-end (point)) | |
1484 (beginning-of-line) | |
1485 ;; Set starting state: If direction was specified use it. | |
1486 ;; If direction is nil, search for a keyword on the current line | |
1487 ;; If the keyword in in eif-opening-regexp, set the search | |
1488 ;; direction to 'forward, if the keyword on the current line is `end' | |
1489 ;; set the search direction to 'backward. | |
1490 (cond ((eq direction 'forward) | |
1491 (end-of-line);; So we wont see any keywords on the current line | |
1492 (setq nesting-level 1) | |
1493 ) | |
1494 ((eq direction 'backward) | |
1495 (beginning-of-line);; So we wont see any keywords on the current line | |
1496 (setq nesting-level -1) | |
1497 ) | |
1498 ((and (re-search-forward eif-opening-regexp search-end t) | |
1499 (not (or (eif-in-quoted-string-p) | |
1500 (eif-in-comment-p) | |
1501 ) | |
1502 ) | |
1503 ) | |
1504 (setq match-start (match-beginning 0)) | |
1505 (goto-char match-start) | |
1506 (if (not (or (eif-in-quoted-string-p) (eif-in-comment-p))) | |
1507 (setq nesting-level 1) | |
1508 ) | |
1509 (setq opening-keyword | |
1510 (cons (buffer-substring match-start (match-end 0)) | |
1511 opening-keyword | |
1512 ) | |
1513 ) | |
1514 (goto-char (match-end 0)) | |
1515 ) | |
1516 ((and (progn (beginning-of-line) t) | |
1517 (re-search-forward eif-closing-regexp search-end t) | |
1518 (not (or (eif-in-quoted-string-p) | |
1519 (eif-in-comment-p) | |
1520 ) | |
1521 ) | |
1522 ) | |
1523 (goto-char (match-beginning 0)) | |
1524 (if (not (or (eif-in-quoted-string-p) (eif-in-comment-p))) | |
1525 (setq nesting-level -1) | |
1526 ) | |
1527 ) | |
1528 ) | |
1529 ;; Perform the search | |
1530 (while (not (= nesting-level 0)) | |
1531 (if (> nesting-level 0) | |
1532 ;; Then search forward for the next keyword not in a comment | |
1533 (while (and (re-search-forward eif-opening-or-closing-regexp nil 1) | |
1534 (goto-char (setq match-start (match-beginning 0))) | |
1535 (setq match-end (match-end 0)) | |
1536 (setq success t) | |
1537 (or (eif-in-quoted-string-p) (eif-in-comment-p)) | |
1538 ) | |
1539 (goto-char match-end) | |
1540 (setq success nil) | |
1541 ) | |
1542 ;; Else search backward for the next keyword not in a comment | |
1543 (while (and (re-search-backward eif-opening-or-closing-regexp nil 1) | |
1544 (goto-char (setq match-start (match-beginning 0))) | |
1545 (setq success t) | |
1546 (or (eif-in-quoted-string-p) (eif-in-comment-p)) | |
1547 ) | |
1548 (setq success nil) | |
1549 ) | |
1550 ) | |
1551 (cond ((and (looking-at eif-opening-regexp) success) | |
1552 ;; Found an opening keyword | |
1553 (if (> nesting-level 0) | |
1554 ;; Then | |
1555 (if (looking-at eif-do-regexp) | |
1556 ;; Then | |
1557 (setq nesting-level -1) | |
1558 ;; Else | |
1559 (setq opening-keyword | |
1560 (cons (buffer-substring match-start (match-end 0)) | |
1561 opening-keyword | |
1562 ) | |
1563 ) | |
1564 (goto-char (match-end 0)) | |
1565 ) | |
1566 ;; Else | |
1567 (if (= nesting-level -1) | |
1568 ;; Then | |
1569 (progn | |
1570 (setq eif-matching-kw-for-end | |
1571 (buffer-substring match-start (match-end 0)) | |
1572 ) | |
1573 (if (looking-at "[ \t\n]+") (goto-char (match-end 0))) | |
1574 ) | |
1575 ;; Else | |
1576 (if (looking-at eif-do-regexp) | |
1577 ;; Then | |
1578 (progn | |
1579 (goto-char (eif-matching-line nil 'forward)) | |
1580 (setq nesting-level -1) | |
1581 ) | |
1582 ) | |
1583 ) | |
1584 (setq opening-keyword (cdr opening-keyword)) | |
1585 (if return-line-break | |
1586 (beginning-of-line) | |
1587 ) | |
1588 ) | |
1589 (setq nesting-level (1+ nesting-level)) | |
1590 ) | |
1591 ((and (looking-at eif-closing-regexp) success) | |
1592 ;; Found an opening keyword | |
1593 (if (> nesting-level 0) | |
1594 ;; Then | |
1595 (progn | |
1596 (setq opening-keyword (cdr opening-keyword)) | |
1597 (if return-line-break | |
1598 (end-of-line) | |
1599 ) | |
1600 (goto-char (match-end 0)) | |
1601 ) | |
1602 ;; Else | |
1603 (setq opening-keyword | |
1604 (cons (buffer-substring (match-beginning 0) | |
1605 (match-end 0) | |
1606 ) | |
1607 opening-keyword | |
1608 ) | |
1609 ) | |
1610 ) | |
1611 (setq nesting-level (1- nesting-level)) | |
1612 ) | |
1613 (t (message (concat "Could not find match" | |
1614 (if (car opening-keyword) | |
1615 (concat " for: " (car opening-keyword)) | |
1616 ) | |
1617 ) | |
1618 ) | |
1619 (goto-char start-point) | |
1620 (setq nesting-level 0) | |
1621 ) | |
1622 );; cond | |
1623 );; while | |
1624 (setq matching-point (point)) | |
1625 );; save-excursion | |
1626 (modify-syntax-entry ?_ "_ ") | |
1627 );; unwind-protect | |
1628 (set-mark matching-point) | |
1629 );; let | |
1630 );; eif-matching-line | |
1631 | |
1632 ;;; ENHANCEME: Make this function correctly indent more than just routine | |
1633 ;;; bodies and their sub-constructs. At the least it should | |
1634 ;;; handle whole routines also. | |
1635 (defun eif-indent-construct () | |
1636 "Indents an entire eiffel syntactic construct. It is assumed that | |
1637 the point is within a nesting construct ('do', `once', 'check', 'if', | |
1638 'from', or 'inspect'). The whole construct is indented up to the | |
1639 matching end. If the point is not within such a construct, then | |
1640 only that line is indented" | |
1641 (interactive) | |
1642 (let ((end-point 0)) | |
1643 (save-excursion | |
1644 (end-of-line) | |
1645 (if (not (= (point) (point-max))) (forward-char 1)) | |
1646 (goto-char (eif-matching-line t 'backward)) | |
1647 (setq end-point (eif-matching-line t 'forward)) | |
1648 (while (< (point) end-point) | |
1649 (eif-indent-line) | |
1650 (next-line 1) | |
1651 (beginning-of-line) | |
1652 ) | |
1653 ) | |
1654 ) | |
1655 ) | |
1656 | |
1657 (defun eif-indent-region (&optional start end) | |
1658 "Indents the lines in the current region" | |
1659 (interactive) | |
1660 (let ((start-point (or start (region-beginning))) | |
1661 (end-point (copy-marker (or end (region-end)))) | |
1662 ) | |
1663 (save-excursion | |
1664 (goto-char start-point) | |
1665 (cond ((eq major-mode 'ace-mode) | |
1666 (while (< (point) end-point) | |
1667 (if (not (looking-at "[ ]*$")) | |
1668 (ace-indent-line) | |
1669 ) | |
1670 (next-line 1) | |
1671 (beginning-of-line) | |
1672 ) | |
1673 ) | |
1674 ((eq major-mode 'eiffel-mode) | |
1675 (while (< (point) end-point) | |
1676 (if (not (looking-at "[ ]*$")) | |
1677 (eif-indent-line) | |
1678 ) | |
1679 (next-line 1) | |
1680 (beginning-of-line) | |
1681 ) | |
1682 ) | |
1683 (t (error "Buffer must be in eiffel or ace mode.")) | |
1684 ) | |
1685 ) | |
1686 ) | |
1687 ) | |
1688 | |
1689 ;;(defun eif-goto-matching-line (&optional direction) | |
1690 ;; "Place the cursor on the line which closes(opens) the current | |
1691 ;;opening(closing) syntactic construct. For example if the point | |
1692 ;;is on `from', executing goto-matching-line places the point | |
1693 ;;on the matching `end' and vice-versa." | |
1694 ;; (interactive) | |
1695 ;; (if (not direction) | |
1696 ;; (progn | |
1697 ;; (cond ((save-excursion (beginning-of-line) (looking-at "[ ]*end.*$")) | |
1698 ;; (goto-char (eif-matching-line nil 'backward)) | |
1699 ;; ) | |
1700 ;; ((looking-at "(") | |
1701 ;; (forward-sexp) | |
1702 ;; ) | |
1703 ;; ((save-excursion (backward-char 1) (looking-at ")")) | |
1704 ;; (backward-sexp) | |
1705 ;; ) | |
1706 ;; (t | |
1707 ;; (goto-char (eif-matching-line nil 'forward)) | |
1708 ;; ) | |
1709 ;; ) | |
1710 ;; ) | |
1711 ;; ) | |
1712 ;; ) | |
1713 | |
1714 (defun eif-forward-sexp () | |
1715 "Place the cursor on the line which closes the current opening syntactic construct. For example if the point is on `from', executing eif-forward-sexp places the point on the matching `end'. This also does matching of parens ala forward-sexp." | |
1716 (interactive) | |
1717 (cond ((looking-at "[[(]") | |
1718 (forward-sexp) | |
1719 ) | |
1720 (t | |
1721 (goto-char (eif-matching-line nil 'forward)) | |
1722 ) | |
1723 ) | |
1724 ) | |
1725 | |
1726 (defun eif-backward-sexp () | |
1727 "Place the cursor on the line which opens the current closing syntactic construct. For example if the point is on the terminating `end' of an `if' statement, executing eif-backward-sexp places the point on the opening `if'. This also does matching of parens ala backward-sexp." | |
1728 (interactive) | |
1729 (cond ((save-excursion (backward-char 1) (looking-at "[])]")) | |
1730 (backward-sexp) | |
1731 ) | |
1732 (t | |
1733 (goto-char (eif-matching-line nil 'backward)) | |
1734 ) | |
1735 ) | |
1736 ) | |
1737 | |
1738 (defun eif-local-indent (amount) | |
1739 "Set the value of eif-indent-increment to amount and make the change local to this buffer." | |
1740 (interactive "NNumber of spaces for eif-indent-increment: ") | |
1741 (make-local-variable 'eif-indent-increment) | |
1742 (setq eif-indent-increment amount) | |
1743 ) | |
1744 | |
1745 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1746 ;;; Utility Functions. ;;; | |
1747 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1748 | |
1749 (defun eif-feature-quote () | |
1750 "Put a `' around the current feature name" | |
1751 (interactive) | |
1752 (save-excursion | |
1753 (backward-sexp) | |
1754 (insert "`") | |
1755 (forward-sexp) | |
1756 (insert "'") | |
1757 ) | |
1758 (if (looking-at "'") | |
1759 (forward-char 1)) | |
1760 ) | |
1761 | |
1762 (defvar eiffel-mode-abbrev-table nil) | |
1763 (define-abbrev-table 'eiffel-mode-abbrev-table ()) | |
1764 | |
1765 ;;; ---------------------------------------------------------------------- | |
1766 ;;; This next portion of the file is derived from "eiffel.el" | |
1767 ;;; Copyright (C) 1989, 1990 Free Software Foundation, Inc. and Bob Weiner | |
1768 ;;; Available for use and distribution under the same terms as GNU Emacs. | |
1769 ;;; ---------------------------------------------------------------------- | |
1770 | |
1771 (defvar eiffel-mode-map nil | |
1772 "Keymap for Eiffel mode.") | |
1773 | |
1774 (defvar eiffel-mode-syntax-table nil | |
1775 "Syntax table in use in Eiffel-mode buffers.") | |
1776 | |
1777 (if eiffel-mode-syntax-table | |
1778 nil | |
1779 (let ((table (make-syntax-table)) | |
1780 (i 0)) | |
1781 (while (< i ?0) | |
1782 (modify-syntax-entry i "_ " table) | |
1783 (setq i (1+ i))) | |
1784 (setq i (1+ ?9)) | |
1785 (while (< i ?A) | |
1786 (modify-syntax-entry i "_ " table) | |
1787 (setq i (1+ i))) | |
1788 (setq i (1+ ?Z)) | |
1789 (while (< i ?a) | |
1790 (modify-syntax-entry i "_ " table) | |
1791 (setq i (1+ i))) | |
1792 (setq i (1+ ?z)) | |
1793 (while (< i 128) | |
1794 (modify-syntax-entry i "_ " table) | |
1795 (setq i (1+ i))) | |
1796 (modify-syntax-entry ? " " table) | |
1797 (modify-syntax-entry ?- ". 12" table) | |
1798 (modify-syntax-entry ?_ "_ " table) | |
1799 (modify-syntax-entry ?\t " " table) | |
1800 (modify-syntax-entry ?\n "> " table) | |
1801 (modify-syntax-entry ?\f "> " table) | |
1802 (modify-syntax-entry ?\" "\" " table) | |
1803 (modify-syntax-entry ?\\ "." table) | |
1804 (modify-syntax-entry ?\( "() " table) | |
1805 (modify-syntax-entry ?\) ")( " table) | |
1806 (modify-syntax-entry ?\[ "(] " table) | |
1807 (modify-syntax-entry ?\] ")[ " table) | |
1808 (modify-syntax-entry ?\{ "(} " table) | |
1809 (modify-syntax-entry ?\} "){ " table) | |
1810 (modify-syntax-entry ?' "\"" table) | |
1811 (modify-syntax-entry ?` "." table) | |
1812 (modify-syntax-entry ?/ "." table) | |
1813 (modify-syntax-entry ?* "." table) | |
1814 (modify-syntax-entry ?+ "." table) | |
1815 (modify-syntax-entry ?= "." table) | |
1816 (modify-syntax-entry ?% "\\" table) | |
1817 (modify-syntax-entry ?< "." table) | |
1818 (modify-syntax-entry ?> "." table) | |
1819 (modify-syntax-entry ?& "." table) | |
1820 (modify-syntax-entry ?| "." table) | |
1821 (modify-syntax-entry ?; "." table) | |
1822 (modify-syntax-entry ?: "." table) | |
1823 (modify-syntax-entry ?! "." table) | |
1824 (modify-syntax-entry ?. "." table) | |
1825 (setq eiffel-mode-syntax-table table)) | |
1826 ) | |
1827 | |
1828 (if eiffel-mode-map | |
1829 nil | |
1830 (setq eiffel-mode-map (make-sparse-keymap)) | |
1831 (define-key eiffel-mode-map "\t" 'eif-indent-line) | |
1832 (define-key eiffel-mode-map "\C-j" 'eif-newline) | |
1833 (define-key eiffel-mode-map "\177" 'backward-delete-char-untabify) | |
1834 (define-key eiffel-mode-map "\M-\C-q" 'eif-indent-construct) | |
1835 (define-key eiffel-mode-map "\M-'" 'eif-feature-quote) | |
1836 (define-key eiffel-mode-map "\M-q" 'eif-fill-paragraph) | |
1837 ) | |
1838 | |
1839 ;;;###autoload | |
1840 (defun eiffel-mode () | |
1841 "Major mode for editing Eiffel programs." | |
1842 (interactive) | |
1843 (setq major-mode 'eiffel-mode) | |
1844 (setq mode-name "Eiffel") | |
1845 (use-local-map eiffel-mode-map) | |
1846 (set-syntax-table eiffel-mode-syntax-table) | |
1847 | |
1848 ;; Make local variables. | |
1849 (make-local-variable 'paragraph-start) | |
1850 (make-local-variable 'paragraph-separate) | |
1851 (make-local-variable 'paragraph-ignore-fill-prefix) | |
1852 (make-local-variable 'require-final-newline) | |
1853 (make-local-variable 'parse-sexp-ignore-comments) | |
1854 (make-local-variable 'indent-line-function) | |
1855 (make-local-variable 'indent-region-function) | |
1856 (make-local-variable 'comment-start) | |
1857 (make-local-variable 'comment-end) | |
1858 (make-local-variable 'comment-column) | |
1859 (make-local-variable 'comment-start-skip) | |
1860 ;; Now set their values. | |
1861 (setq paragraph-start (concat "^$\\|" page-delimiter) | |
1862 paragraph-separate paragraph-start | |
1863 paragraph-ignore-fill-prefix t | |
1864 require-final-newline 'ask | |
1865 parse-sexp-ignore-comments t | |
1866 indent-line-function 'eif-indent-line | |
1867 indent-region-function 'eif-indent-region | |
1868 comment-start "-- " | |
1869 comment-end "" | |
1870 comment-column 32 | |
1871 comment-start-skip "--+ *") | |
1872 | |
1873 (run-hooks 'eiffel-mode-hook) | |
1874 (setq local-abbrev-table eiffel-mode-abbrev-table) | |
1875 (setq auto-fill-function 'eif-auto-fill) | |
1876 ) | |
1877 | |
1878 (defun eif-in-comment-p () | |
1879 "t if point is in a comment." | |
1880 (save-excursion | |
1881 (and (/= (point) (point-max)) (forward-char 1)) | |
1882 (search-backward "--" (save-excursion (beginning-of-line) (point)) t))) | |
1883 | |
1884 | |
1885 (defun eif-comment-prefix () | |
1886 "Prefix that starts a comment that begins a line. | |
1887 Comments that are not the only thing on a line return nil as their prefix." | |
1888 (save-excursion | |
1889 (end-of-line) | |
1890 (let ((limit (point)) len | |
1891 (in-string (eif-in-quoted-string-p)) | |
1892 ) | |
1893 (beginning-of-line) | |
1894 (cond ((re-search-forward "^[ \t]*--|?[ \t]*" limit t) | |
1895 (buffer-substring (match-beginning 0) (match-end 0)) | |
1896 ) | |
1897 ;; Handle string-literal continuation lines | |
1898 (in-string | |
1899 (end-of-line) | |
1900 (re-search-backward "^[ \t]*%\\|[^%]\"" nil t) | |
1901 (re-search-forward "%\\|\"" nil t) | |
1902 (setq len (1- (current-column))) | |
1903 (concat (make-string len ? ) "%") | |
1904 ) | |
1905 (t nil) | |
1906 ) | |
1907 ) | |
1908 ) | |
1909 ) | |
1910 | |
1911 | |
1912 (defun eif-auto-fill () | |
1913 (if (> (current-column) fill-column) | |
1914 (let ((fill-prefix (eif-comment-prefix)) (pm (point-marker))) | |
1915 (if fill-prefix | |
1916 (if (string-match "^[ \t]*%" fill-prefix) | |
1917 (progn | |
1918 (backward-char 1) | |
1919 (re-search-backward "[^][a-zA-Z0-9]" nil t) | |
1920 (forward-char 1) | |
1921 (insert "%\n") | |
1922 (insert fill-prefix) | |
1923 (goto-char pm) | |
1924 ) | |
1925 ;; (do-auto-fill) | |
1926 (backward-char 1) | |
1927 (re-search-backward "\\s-" nil t) | |
1928 (forward-char 1) | |
1929 (insert "\n") | |
1930 (insert fill-prefix) | |
1931 (goto-char pm) | |
1932 ) | |
1933 ) | |
1934 ) | |
1935 ) | |
1936 ) | |
1937 | |
1938 (defun eif-fill-paragraph () | |
1939 "Textually fills Eiffel comments ala fill-paragraph" | |
1940 (interactive) | |
1941 (save-excursion | |
1942 (let ((current-point (point)) | |
1943 (last-point nil) | |
1944 (para-begin nil) | |
1945 (para-end nil) | |
1946 (fill-prefix (eif-comment-prefix)) | |
1947 ) | |
1948 (if fill-prefix | |
1949 (progn | |
1950 (setq last-point (point)) | |
1951 (forward-line -1) | |
1952 (end-of-line) | |
1953 (while (and (not (= (point) last-point)) | |
1954 (eif-comment-prefix) | |
1955 ) | |
1956 (setq last-point (point)) | |
1957 (forward-line -1) | |
1958 (end-of-line) | |
1959 ) | |
1960 (if (= (point) last-point) | |
1961 (setq para-begin (save-excursion (beginning-of-line) (point))) | |
1962 (setq para-begin (1+ (point))) | |
1963 ) | |
1964 (goto-char current-point) | |
1965 (setq last-point (point)) | |
1966 (next-line 1) | |
1967 (end-of-line) | |
1968 (while (and (not (= (point) last-point)) | |
1969 (eif-comment-prefix) | |
1970 ) | |
1971 (setq last-point (point)) | |
1972 (next-line 1) | |
1973 (end-of-line) | |
1974 ) | |
1975 (if (= (point) last-point) | |
1976 (setq para-end (point)) | |
1977 (beginning-of-line) | |
1978 (setq para-end (point)) | |
1979 ) | |
1980 (fill-region para-begin para-end) | |
1981 ) | |
1982 ) | |
1983 ) | |
1984 ) | |
1985 ) | |
1986 | |
1987 (defun eif-newline () | |
1988 "Insert a newline and indent the new line." | |
1989 (interactive) | |
1990 (insert "\n") | |
1991 (eif-indent-line) | |
1992 ) | |
1993 | |
1994 (defun eif-indent-line (&optional whole-exp) | |
1995 "Indent the current line as Eiffel code. | |
1996 With argument, indent any additional lines of the same clause | |
1997 rigidly along with this one (not implemented yet)." | |
1998 (interactive "p") | |
1999 (save-excursion | |
2000 (beginning-of-line) | |
2001 (skip-chars-forward " \t") | |
2002 (let ((indent (eif-calc-indent))) | |
2003 (if (not (= indent (current-column))) | |
2004 (progn | |
2005 (delete-horizontal-space) | |
2006 (indent-to indent) | |
2007 ) | |
2008 ) | |
2009 ) | |
2010 ) | |
2011 (skip-chars-forward " \t")) | |
2012 | |
2013 ;; ENHANCEME: Currently eif-beginning-of-feature only works for routines. | |
2014 ;; It should be made more general. | |
2015 ;; | |
2016 | |
2017 (defun eif-beginning-of-feature (&optional arg) | |
2018 "Move backward to next feature beginning. With argument, do this that many | |
2019 times. Returns t unless search stops due to beginning of buffer." | |
2020 (interactive "p") | |
2021 (and arg (< arg 0) (forward-char 1)) | |
2022 (if (or (re-search-backward eif-multiline-routine-is-keyword-regexp | |
2023 nil t (or arg 1)) | |
2024 (re-search-backward eif-is-keyword-regexp | |
2025 nil 'move (or arg 1)) | |
2026 ) | |
2027 (progn | |
2028 (backward-sexp 1) | |
2029 (if (looking-at "(") | |
2030 (backward-word 1) | |
2031 ) | |
2032 (beginning-of-line) | |
2033 ) | |
2034 nil | |
2035 ) | |
2036 ) | |
2037 | |
2038 (defun eif-move-to-prev-non-blank () | |
2039 "Moves point to previous line excluding blank lines. | |
2040 Returns t if successful, nil if not." | |
2041 (beginning-of-line) | |
2042 (re-search-backward "^[ \t]*[^ \t\n]" nil t)) | |
2043 | |
2044 (defvar eif-last-feature-level-indent -1) | |
2045 (defvar eif-feature-level-indent-regexp nil) | |
2046 (defun eif-in-paren-expression () | |
2047 "Determine if we are inside of a parenthesized expression" | |
2048 (interactive) | |
2049 (let ((paren-count 0) (limit 0)) | |
2050 (save-excursion | |
2051 (if (= eif-last-feature-level-indent (eif-feature-level-indent-m)) | |
2052 (setq limit | |
2053 (re-search-backward eif-feature-level-indent-regexp nil t)) | |
2054 (setq eif-last-feature-level-indent (eif-feature-level-indent-m)) | |
2055 (setq eif-feature-level-indent-regexp | |
2056 (concat "^" (make-string eif-last-feature-level-indent ? ) | |
2057 "[^ \t\n]") | |
2058 ) | |
2059 (setq limit | |
2060 (or (re-search-backward eif-feature-level-indent-regexp nil t) | |
2061 0) | |
2062 ) | |
2063 ) | |
2064 ) | |
2065 (save-excursion | |
2066 (while (re-search-backward "[][()]" limit t) | |
2067 (if (looking-at "[[(]") | |
2068 (setq paren-count (1+ paren-count)) | |
2069 (setq paren-count (1- paren-count)) | |
2070 ) | |
2071 ) | |
2072 ) | |
2073 paren-count | |
2074 ) | |
2075 ) | |
2076 | |
2077 (defun eif-manifest-array-indent () | |
2078 "Determine if we are inside of a manifest array" | |
2079 (interactive) | |
2080 (let ((paren-count 0) (indent nil) | |
2081 (limit 0)) | |
2082 (save-excursion | |
2083 (if (= eif-last-feature-level-indent (eif-feature-level-indent-m)) | |
2084 (setq limit | |
2085 (re-search-backward eif-feature-level-indent-regexp nil t)) | |
2086 (setq eif-last-feature-level-indent (eif-feature-level-indent-m)) | |
2087 (setq eif-feature-level-indent-regexp | |
2088 (concat "^" (make-string eif-last-feature-level-indent ? ) | |
2089 "[^ \t\n]") | |
2090 ) | |
2091 (setq limit | |
2092 (or (re-search-backward eif-feature-level-indent-regexp nil t) | |
2093 0) | |
2094 ) | |
2095 ) | |
2096 ) | |
2097 (save-excursion | |
2098 (while (and (<= paren-count 0) (re-search-backward "<<\\|>>" nil t)) | |
2099 (if (looking-at "<<") | |
2100 (setq paren-count (1+ paren-count)) | |
2101 (setq paren-count (1- paren-count)) | |
2102 ) | |
2103 ) | |
2104 (if (> paren-count 0) | |
2105 (let ((eol (save-excursion (end-of-line) (point)))) | |
2106 (setq indent | |
2107 (or (and (re-search-forward "[^< \t]" eol t) | |
2108 (1- (current-column))) | |
2109 (+ (current-column) 2) | |
2110 ) | |
2111 ) | |
2112 ) | |
2113 ) | |
2114 ) | |
2115 indent | |
2116 ) | |
2117 ) | |
2118 | |
2119 (defun eif-manifest-array-start () | |
2120 "Determine the indentation of the statement containing a manifest array" | |
2121 (interactive) | |
2122 (let ((paren-count 0) (indent nil) | |
2123 (limit 0)) | |
2124 (save-excursion | |
2125 (if (= eif-last-feature-level-indent (eif-feature-level-indent-m)) | |
2126 (setq limit | |
2127 (re-search-backward eif-feature-level-indent-regexp nil t)) | |
2128 (setq eif-last-feature-level-indent (eif-feature-level-indent-m)) | |
2129 (setq eif-feature-level-indent-regexp | |
2130 (concat "^" (make-string eif-last-feature-level-indent ? ) | |
2131 "[^ \t\n]") | |
2132 ) | |
2133 (setq limit | |
2134 (or (re-search-backward eif-feature-level-indent-regexp nil t) | |
2135 0) | |
2136 ) | |
2137 ) | |
2138 ) | |
2139 (save-excursion | |
2140 (while (and (<= paren-count 0) (re-search-backward "<<\\|>>" nil t)) | |
2141 (if (looking-at "<<") | |
2142 (setq paren-count (1+ paren-count)) | |
2143 (setq paren-count (1- paren-count)) | |
2144 ) | |
2145 ) | |
2146 (if (> paren-count 0) | |
2147 (let ((limit (progn (end-of-line) (point)))) | |
2148 (beginning-of-line) | |
2149 (if (re-search-forward "^[ \t]*<<" limit t) | |
2150 (setq indent (- (current-column) 2 eif-indent-increment)) | |
2151 (re-search-forward "^[ \t]*" limit t) | |
2152 (setq indent (current-column)) | |
2153 ) | |
2154 ) | |
2155 ) | |
2156 ) | |
2157 indent | |
2158 ) | |
2159 ) | |
2160 | |
2161 ;;; ---------------------------------------------------------------------- | |
2162 ;;; The portion of the file below this point is derived from "eif-mult-fmt.el" | |
2163 ;;; Copyright (C) 1985 Free Software Foundation, Inc. | |
2164 ;;; Copyright (C) 1990 Bob Weiner, Motorola Inc. | |
2165 ;;; Available for use and distribution under the same terms as GNU Emacs. | |
2166 ;;; ---------------------------------------------------------------------- | |
2167 | |
2168 (defun eif-indent-multi-line (&optional parse-start) | |
2169 "Return integer giving appropriate indentation for current Eiffel code | |
2170 line between parentheses or double quotes, otherwise -1. Optional | |
2171 PARSE-START is buffer position at which to begin parsing, default is to begin | |
2172 at the feature enclosing or preceding point." | |
2173 (let ((eif-opoint (point)) | |
2174 (indent-point (progn (beginning-of-line) (point))) | |
2175 (eif-ind-val -1) | |
2176 (eif-in-str nil) | |
2177 (eif-paren-depth 0) | |
2178 (retry t) | |
2179 state | |
2180 ;; setting this to a number inhibits calling hook | |
2181 last-sexp containing-sexp) | |
2182 (if parse-start | |
2183 (goto-char parse-start) | |
2184 (eif-beginning-of-feature)) | |
2185 ;; Find outermost containing sexp | |
2186 (while (< (point) indent-point) | |
2187 (setq state (parse-partial-sexp (point) indent-point 0))) | |
2188 ;; Find innermost containing sexp | |
2189 (while (and retry | |
2190 state | |
2191 (> (setq eif-paren-depth (elt state 0)) 0)) | |
2192 (setq retry nil) | |
2193 (setq last-sexp (elt state 2)) | |
2194 (setq containing-sexp (elt state 1)) | |
2195 ;; Position following last unclosed open. | |
2196 (goto-char (1+ containing-sexp)) | |
2197 ;; Is there a complete sexp since then? | |
2198 (if (and last-sexp (> last-sexp (point))) | |
2199 ;; Yes, but is there a containing sexp after that? | |
2200 (let ((peek (parse-partial-sexp last-sexp indent-point 0))) | |
2201 (if (setq retry (car (cdr peek))) (setq state peek))))) | |
2202 (if retry | |
2203 nil | |
2204 ;; Innermost containing sexp found | |
2205 (goto-char (1+ containing-sexp)) | |
2206 (if (not last-sexp) | |
2207 ;; indent-point immediately follows open paren. | |
2208 nil | |
2209 ;; Find the start of first element of containing sexp. | |
2210 (parse-partial-sexp (point) last-sexp 0 t) | |
2211 (cond ((looking-at "\\s(") | |
2212 ;; First element of containing sexp is a list. | |
2213 ;; Indent under that list. | |
2214 ) | |
2215 ((> (save-excursion (forward-line 1) (point)) | |
2216 last-sexp) | |
2217 ;; This is the first line to start within the containing sexp. | |
2218 (backward-prefix-chars)) | |
2219 (t | |
2220 ;; Indent beneath first sexp on same line as last-sexp. | |
2221 ;; Again, it's almost certainly a routine call. | |
2222 (goto-char last-sexp) | |
2223 (beginning-of-line) | |
2224 (parse-partial-sexp (point) last-sexp 0 t) | |
2225 (backward-prefix-chars)))) | |
2226 (setq eif-ind-val (current-column)) | |
2227 ) | |
2228 ;; Point is at the point to indent under unless we are inside a string. | |
2229 (setq eif-in-str (elt state 3)) | |
2230 (goto-char eif-opoint) | |
2231 (if (not eif-in-str) | |
2232 nil | |
2233 ;; Inside a string, indent 1 past string start | |
2234 (setq eif-paren-depth 1);; To account for being inside string | |
2235 (save-excursion | |
2236 (if (re-search-backward "\"" nil t) | |
2237 (setq eif-ind-val (1+ (current-column))) | |
2238 (goto-char indent-point) | |
2239 (if (looking-at "^[ \t]*[^ \t\n]") | |
2240 (eif-move-to-prev-non-blank)) | |
2241 (skip-chars-forward " \t") | |
2242 (setq eif-ind-val (current-column))))) | |
2243 (if (> eif-paren-depth 0) eif-ind-val -1) | |
2244 )) | |
2245 | |
2246 (provide 'eiffel3) |