home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / modes / eiffel3.el < prev    next >
Encoding:
Text File  |  1995-05-20  |  79.3 KB  |  2,242 lines

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