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)