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