comparison lisp/progmodes/ada-mode.el @ 30411:41f228350eca

Got rid of all byte-compiler warnings on Emacs Load ada-xref.el before ada-prj.el, so that the Project menu is created when ada-prj tries to add to it. (ada-activate-keys-for-case): Suppress the characters that are not part of the Ada syntax. Better compatibility with else-mode (ada-adjust-case-interactive): When auto-casing is not active, correctly insert newlines (used to insert only ^M). Prevent the syntax table from being changed in case of an error (or '_' becomes part of a word and some commands are confused). Do nothing if ada-auto-case is nil. (ada-after-keyword-p): Ignore keywords that are also attributes (ada-batch-reformat): Update usage comment (ada-call-from-contextual-menu): New function (ada-case-read-exceptions): Reinitialize the casing exception list first to nil first, so that the casing exception file can be shared. (ada-check-defun-name): Handles "configure" keyword for gnatdist files. (ada-compile-goto-error): Fix regexp used to detect a file:line anywhere in the error message (ada-contextual-menu-last-point): New variable (ada-create-keymap): If the variable delete-key-deletes-forward is t on XEmacs, it means that DEL should delete one character forward. (ada-create-menu): Use :included instead of :visible for XEmacs. New submenu "Options". (ada-end-stmt-re): Correctly indent "select ... then abort" statements. (ada-fill-comment-paragraph): Correctly delete all leading '--' even if they don't match ada-fill-comment-prefix Fix handling of paragraphs on the first or last line of a file. (ada-format-paramlist): Fix handling of default parameter values. (ada-get-body-name): New function. (ada-get-current-indent): Optimized by searchling directly for an existing generic part or a statement outside of it. Handle ada-indent-align-comments when indenting comments Replaced some regexps by testing directly the next character. This results in a huge speedup on some files. New indentation scheme for renames statements. Stop looking for the 'while' or 'for' associated with a 'loop' at the first semicolon encountered. A "return" can also match an anonymous access subprogram declaration. (ada-get-indent-noindent): Ignore strings and comments when looking for the keywords "record" and "private". (ada-goto-matching-decl-start): When matching "if", make sure we are not in fact seeing "end if". Ignore "when" statements except when initial keyword was "begin". Fix handling of nested procedures. Add a recursive call to this function to skip over other 'end' statmts. Fix indentation for "when .. => begin" (ada-in-open-paren-p): Fix indentation for complex boolean expressions, where 'and then', 'or else' and parenthesis statements are mixed up. (ada-in-paramlist-p): Skip comments while searching for the beginning Fix handling of operator declarations. (ada-indent-align-comments): New variable (ada-indent-current): Change the syntax table only in the protected section, so that we are sure it is restored correctly. (ada-indent-on-previous-lines): Use ada-use-indent and ada-with-indent Correctly indent "select ... then" (ada-indent-region): Slight speedup. (ada-indent-renames): New variable. (ada-last-which-function-subprog, ada-last-which-function-line): New variables (ada-looking-at-semi-private): Correctly indent the 'private' keyword when it is the first word in a package declaration. (ada-loose-case-word): Stop searching if at the end of the buffer. (ada-loose-case-word, ada-capitalize-word): Recase the whole word even if point is not initially at the end of the word. (ada-matching-decl-start-re): Add "when". (ada-mode): Add support for abbrev-mode, outline-mode and which-func-mode Override the old find-file.el entry in ff-special-constructs since it is using the obsolete ada-spec-suffix variable (ada-no-auto-case): New function (ada-scan-paramlist): When parsing the argument type, accept spaces (as in "X 'Class", generated by Rational Rose). (ada-other-file-name): No longer loads the other file. (ada-popup-menu): Save and restore the current buffer and cursor position before and after displaying the menu. (ada-search-ignore-complex-boolean): New function. (ada-uncomment-region): Emacs21 already knows how to delete comments not starting in the first column. (ada-use-indent): New variable (ada-which-function): New function. (ada-with-indent): New variable (ada-xemacs): evaluate it at compile time too, so that ada-mode.el can be batch-compiled from the command line.
author Gerd Moellmann <gerd@gnu.org>
date Mon, 24 Jul 2000 11:14:26 +0000
parents 93c16141d107
children 5acb191f2a15
comparison
equal deleted inserted replaced
30410:01ac16657214 30411:41f228350eca
1 ;; @(#) ada-mode.el --- major-mode for editing Ada sources. 1 ;; @(#) ada-mode.el --- major-mode for editing Ada source.
2 2
3 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. 3 ;; Copyright (C) 1994, 1995, 1997-1999, 2000 Free Software Foundation, Inc.
4 4
5 ;; Author: Rolf Ebert <ebert@inf.enst.fr> 5 ;; Author: Rolf Ebert <ebert@inf.enst.fr>
6 ;; Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de> 6 ;; Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de>
7 ;; Emmanuel Briot <briot@gnat.com> 7 ;; Emmanuel Briot <briot@gnat.com>
8 ;; Maintainer: Emmanuel Briot <briot@gnat.com> 8 ;; Maintainer: Emmanuel Briot <briot@gnat.com>
9 ;; Ada Core Technologies's version: $Revision: 1.31 $ 9 ;; Ada Core Technologies's version: $Revision: 1.117 $
10 ;; Keywords: languages ada 10 ;; Keywords: languages ada
11 11
12 ;; This file is not part of GNU Emacs 12 ;; This file is not part of GNU Emacs
13 13
14 ;; This program is free software; you can redistribute it and/or modify 14 ;; This program is free software; you can redistribute it and/or modify
25 ;; along with GNU Emacs; see the file COPYING. If not, write to 25 ;; along with GNU Emacs; see the file COPYING. If not, write to
26 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 26 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 27
28 ;;; Commentary: 28 ;;; Commentary:
29 ;;; This mode is a major mode for editing Ada83 and Ada95 source code. 29 ;;; This mode is a major mode for editing Ada83 and Ada95 source code.
30 ;;; This is a major rewrite of the file packaged with Emacs-20.2. The 30 ;;; This is a major rewrite of the file packaged with Emacs-20. The
31 ;;; ada-mode is composed of four lisp file, ada-mode.el, ada-xref.el, 31 ;;; ada-mode is composed of four lisp file, ada-mode.el, ada-xref.el,
32 ;;; ada-prj.el and ada-stmt.el. Only this file (ada-mode.el) is 32 ;;; ada-prj.el and ada-stmt.el. Only this file (ada-mode.el) is
33 ;;; completely independent from the GNU Ada compiler Gnat, distributed 33 ;;; completely independent from the GNU Ada compiler Gnat, distributed
34 ;;; by Ada Core Technologies. All the other files rely heavily on 34 ;;; by Ada Core Technologies. All the other files rely heavily on
35 ;;; features provides only by Gnat. 35 ;;; features provides only by Gnat.
93 ;;; comar@gnat.com (Cyrille Comar) 93 ;;; comar@gnat.com (Cyrille Comar)
94 ;;; stephen.leake@gsfc.nasa.gov (Stephen Leake) 94 ;;; stephen.leake@gsfc.nasa.gov (Stephen Leake)
95 ;;; and others for their valuable hints. 95 ;;; and others for their valuable hints.
96 96
97 ;;; Code: 97 ;;; Code:
98 ;;; Note: Every function is this package is compiler-independent. 98 ;;; Note: Every function in this package is compiler-independent.
99 ;;; The names start with ada- 99 ;;; The names start with ada-
100 ;;; The variables that the user can edit can all be modified through 100 ;;; The variables that the user can edit can all be modified through
101 ;;; the customize mode. They are sorted in alphabetical order in this 101 ;;; the customize mode. They are sorted in alphabetical order in this
102 ;;; file. 102 ;;; file.
103 103
106 (eval-and-compile 106 (eval-and-compile
107 (defun ada-check-emacs-version (major minor &optional is-xemacs) 107 (defun ada-check-emacs-version (major minor &optional is-xemacs)
108 "Returns t if Emacs's version is greater or equal to MAJOR.MINOR. 108 "Returns t if Emacs's version is greater or equal to MAJOR.MINOR.
109 If IS-XEMACS is non-nil, check for XEmacs instead of Emacs." 109 If IS-XEMACS is non-nil, check for XEmacs instead of Emacs."
110 (let ((xemacs-running (or (string-match "Lucid" emacs-version) 110 (let ((xemacs-running (or (string-match "Lucid" emacs-version)
111 (string-match "XEmacs" emacs-version)))) 111 (string-match "XEmacs" emacs-version))))
112 (and (or (and is-xemacs xemacs-running) 112 (and (or (and is-xemacs xemacs-running)
113 (not (or is-xemacs xemacs-running))) 113 (not (or is-xemacs xemacs-running)))
114 (or (> emacs-major-version major) 114 (or (> emacs-major-version major)
115 (and (= emacs-major-version major) 115 (and (= emacs-major-version major)
116 (>= emacs-minor-version minor))))))) 116 (>= emacs-minor-version minor)))))))
117 117
118 118
119 ;; We create a constant for that, for efficiency only 119 ;; We create a constant for that, for efficiency only
120 ;; This should not be evaluated at compile time, only a runtime 120 ;; This should be evaluated both at compile time, only a runtime
121 (defconst ada-xemacs (boundp 'running-xemacs) 121 (eval-and-compile
122 "Return t if we are using XEmacs.") 122 (defconst ada-xemacs (and (boundp 'running-xemacs)
123 (symbol-value 'running-xemacs))
124 "Return t if we are using XEmacs."))
123 125
124 (unless ada-xemacs 126 (unless ada-xemacs
125 (require 'outline)) 127 (require 'outline))
126 128
127 (eval-and-compile 129 (eval-and-compile
164 >>>>>>>>>Value); -- from ada-broken-indent" 166 >>>>>>>>>Value); -- from ada-broken-indent"
165 :type 'integer :group 'ada) 167 :type 'integer :group 'ada)
166 168
167 (defcustom ada-case-attribute 'ada-capitalize-word 169 (defcustom ada-case-attribute 'ada-capitalize-word
168 "*Function to call to adjust the case of Ada attributes. 170 "*Function to call to adjust the case of Ada attributes.
169 It may be `downcase-word', `upcase-word', `ada-loose-case-word' or 171 It may be `downcase-word', `upcase-word', `ada-loose-case-word',
170 `ada-capitalize-word'." 172 `ada-capitalize-word' or `ada-no-auto-case'."
171 :type '(choice (const downcase-word) 173 :type '(choice (const downcase-word)
172 (const upcase-word) 174 (const upcase-word)
173 (const ada-capitalize-word) 175 (const ada-capitalize-word)
174 (const ada-loose-case-word)) 176 (const ada-loose-case-word)
177 (const ada-no-auto-case))
175 :group 'ada) 178 :group 'ada)
176 179
177 (defcustom ada-case-exception-file "~/.emacs_case_exceptions" 180 (defcustom ada-case-exception-file '("~/.emacs_case_exceptions")
178 "*File name for the dictionary of special casing exceptions for identifiers. 181 "*List of special casing exceptions dictionaries for identifiers.
179 This file should contain one word per line, that gives the casing 182 The first file is the one where new exceptions will be saved by Emacs
180 to be used for that words in Ada files." 183 when you call `ada-create-case-exception'.
181 :type 'file :group 'ada) 184
185 These files should contain one word per line, that gives the casing
186 to be used for that word in Ada files. Each line can be terminated by
187 a comment."
188 :type '(repeat (file))
189 :group 'ada)
182 190
183 (defcustom ada-case-keyword 'downcase-word 191 (defcustom ada-case-keyword 'downcase-word
184 "*Function to call to adjust the case of an Ada keywords. 192 "*Function to call to adjust the case of an Ada keywords.
185 It may be `downcase-word', `upcase-word', `ada-loose-case-word' or 193 It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
186 `ada-capitalize-word'." 194 `ada-capitalize-word'."
187 :type '(choice (const downcase-word) 195 :type '(choice (const downcase-word)
188 (const upcase-word) 196 (const upcase-word)
189 (const ada-capitalize-word) 197 (const ada-capitalize-word)
190 (const ada-loose-case-word)) 198 (const ada-loose-case-word)
199 (const ada-no-auto-case))
191 :group 'ada) 200 :group 'ada)
192 201
193 (defcustom ada-case-identifier 'ada-loose-case-word 202 (defcustom ada-case-identifier 'ada-loose-case-word
194 "*Function to call to adjust the case of an Ada identifier. 203 "*Function to call to adjust the case of an Ada identifier.
195 It may be `downcase-word', `upcase-word', `ada-loose-case-word' or 204 It may be `downcase-word', `upcase-word', `ada-loose-case-word' or
196 `ada-capitalize-word'." 205 `ada-capitalize-word'."
197 :type '(choice (const downcase-word) 206 :type '(choice (const downcase-word)
198 (const upcase-word) 207 (const upcase-word)
199 (const ada-capitalize-word) 208 (const ada-capitalize-word)
200 (const ada-loose-case-word)) 209 (const ada-loose-case-word)
210 (const ada-no-auto-case))
201 :group 'ada) 211 :group 'ada)
202 212
203 (defcustom ada-clean-buffer-before-saving t 213 (defcustom ada-clean-buffer-before-saving t
204 "*Non-nil means remove trailing spaces and untabify the buffer before saving." 214 "*Non-nil means remove trailing spaces and untabify the buffer before saving."
205 :type 'boolean :group 'ada) 215 :type 'boolean :group 'ada)
215 225
216 (defcustom ada-indent-after-return t 226 (defcustom ada-indent-after-return t
217 "*Non-nil means automatically indent after RET or LFD." 227 "*Non-nil means automatically indent after RET or LFD."
218 :type 'boolean :group 'ada) 228 :type 'boolean :group 'ada)
219 229
230 (defcustom ada-indent-align-comments t
231 "*Non-nil means align comments on previous line comments, if any.
232 If nil, indentation is calculated as usual.
233 Note that indentation is calculated only if `ada-indent-comment-as-code' is t.
234
235 For instance:
236 A := 1; -- A multi-line comment
237 -- aligned if ada-indent-align-comments is t"
238 :type 'boolean :group 'ada)
239
220 (defcustom ada-indent-comment-as-code t 240 (defcustom ada-indent-comment-as-code t
221 "*Non-nil means indent comment lines as code." 241 "*Non-nil means indent comment lines as code.
242 Nil means do not auto-indent comments."
222 :type 'boolean :group 'ada) 243 :type 'boolean :group 'ada)
223 244
224 (defcustom ada-indent-is-separate t 245 (defcustom ada-indent-is-separate t
225 "*Non-nil means indent 'is separate' or 'is abstract' if on a single line." 246 "*Non-nil means indent 'is separate' or 'is abstract' if on a single line."
226 :type 'boolean :group 'ada) 247 :type 'boolean :group 'ada)
229 "*Indentation for 'record' relative to 'type' or 'use'. 250 "*Indentation for 'record' relative to 'type' or 'use'.
230 251
231 An example is: 252 An example is:
232 type A is 253 type A is
233 >>>>>>>>>>>record -- from ada-indent-record-rel-type" 254 >>>>>>>>>>>record -- from ada-indent-record-rel-type"
255 :type 'integer :group 'ada)
256
257 (defcustom ada-indent-renames ada-broken-indent
258 "*Indentation for renames relative to the matching function statement.
259 If ada-indent-return is null or negative, the indentation is done relative to
260 the open parenthesis (if there is no parenthesis, ada-broken-indent is used).
261
262 An example is:
263 function A (B : Integer)
264 return C; -- from ada-indent-return
265 >>>renames Foo; -- from ada-indent-renames"
234 :type 'integer :group 'ada) 266 :type 'integer :group 'ada)
235 267
236 (defcustom ada-indent-return 0 268 (defcustom ada-indent-return 0
237 "*Indentation for 'return' relative to the matching 'function' statement. 269 "*Indentation for 'return' relative to the matching 'function' statement.
238 If ada-indent-return is null or negative, the indentation is done relative to 270 If ada-indent-return is null or negative, the indentation is done relative to
276 not to 'begin'." 308 not to 'begin'."
277 :type 'boolean :group 'ada) 309 :type 'boolean :group 'ada)
278 310
279 (defcustom ada-popup-key '[down-mouse-3] 311 (defcustom ada-popup-key '[down-mouse-3]
280 "*Key used for binding the contextual menu. 312 "*Key used for binding the contextual menu.
281 If nil, no contextual menu is available.") 313 If nil, no contextual menu is available."
314 :type 'string :group 'ada)
282 315
283 (defcustom ada-search-directories 316 (defcustom ada-search-directories
284 '("." "$ADA_INCLUDE_PATH" "/usr/adainclude" "/usr/local/adainclude" 317 '("." "$ADA_INCLUDE_PATH" "/usr/adainclude" "/usr/local/adainclude"
285 "/opt/gnu/adainclude") 318 "/opt/gnu/adainclude")
286 "*List of directories to search for Ada files. 319 "*List of directories to search for Ada files.
310 :type '(choice (const indent-auto) 343 :type '(choice (const indent-auto)
311 (const indent-rigidly) 344 (const indent-rigidly)
312 (const always-tab)) 345 (const always-tab))
313 :group 'ada) 346 :group 'ada)
314 347
348 (defcustom ada-use-indent ada-broken-indent
349 "*Indentation for the lines in a 'use' statement.
350
351 An example is:
352 use Ada.Text_IO,
353 >>>>>Ada.Numerics; -- from ada-use-indent"
354 :type 'integer :group 'ada)
355
315 (defcustom ada-when-indent 3 356 (defcustom ada-when-indent 3
316 "*Indentation for 'when' relative to 'exception' or 'case'. 357 "*Indentation for 'when' relative to 'exception' or 'case'.
317 358
318 An example is: 359 An example is:
319 case A is 360 case A is
320 >>>>>>>>when B => -- from ada-when-indent" 361 >>>>>>>>when B => -- from ada-when-indent"
362 :type 'integer :group 'ada)
363
364 (defcustom ada-with-indent ada-broken-indent
365 "*Indentation for the lines in a 'with' statement.
366
367 An example is:
368 with Ada.Text_IO,
369 >>>>>Ada.Numerics; -- from ada-with-indent"
321 :type 'integer :group 'ada) 370 :type 'integer :group 'ada)
322 371
323 (defcustom ada-which-compiler 'gnat 372 (defcustom ada-which-compiler 'gnat
324 "*Name of the compiler to use. 373 "*Name of the compiler to use.
325 This will determine what features are made available through the ada-mode. 374 This will determine what features are made available through the ada-mode.
346 (defvar ada-mode-menu (make-sparse-keymap) 395 (defvar ada-mode-menu (make-sparse-keymap)
347 "Menu for ada-mode.") 396 "Menu for ada-mode.")
348 397
349 (defvar ada-mode-map (make-sparse-keymap) 398 (defvar ada-mode-map (make-sparse-keymap)
350 "Local keymap used for Ada mode.") 399 "Local keymap used for Ada mode.")
400
401 (defvar ada-mode-abbrev-table nil
402 "Local abbrev table for Ada mode.")
351 403
352 (defvar ada-mode-syntax-table nil 404 (defvar ada-mode-syntax-table nil
353 "Syntax table to be used for editing Ada source code.") 405 "Syntax table to be used for editing Ada source code.")
354 406
355 (defvar ada-mode-symbol-syntax-table nil 407 (defvar ada-mode-symbol-syntax-table nil
427 (eval-when-compile 479 (eval-when-compile
428 (concat "\\(" 480 (concat "\\("
429 ";" "\\|" 481 ";" "\\|"
430 "=>[ \t]*$" "\\|" 482 "=>[ \t]*$" "\\|"
431 "^[ \t]*separate[ \t]*(\\(\\sw\\|[_.]\\)+)" "\\|" 483 "^[ \t]*separate[ \t]*(\\(\\sw\\|[_.]\\)+)" "\\|"
432 "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic" "loop" 484 "\\<" (regexp-opt '("begin" "declare" "is" "do" "else" "generic"
433 "private" "record" "select" "then") t) "\\>" "\\|" 485 "loop" "private" "record" "select"
486 "then abort" "then") t) "\\>" "\\|"
434 "^[ \t]*" (regexp-opt '("function" "package" "procedure") 487 "^[ \t]*" (regexp-opt '("function" "package" "procedure")
435 t) "\\>\\(\\sw\\|[ \t_.]\\)+\\<is\\>" "\\|" 488 t) "\\>\\(\\sw\\|[ \t_.]\\)+\\<is\\>" "\\|"
436 "^[ \t]*exception\\>" 489 "^[ \t]*exception\\>"
437 "\\)") ) 490 "\\)") )
438 "Regexp of possible ends for a non-broken statement. 491 "Regexp of possible ends for a non-broken statement.
449 502
450 (defvar ada-matching-decl-start-re 503 (defvar ada-matching-decl-start-re
451 (eval-when-compile 504 (eval-when-compile
452 (concat "\\<" 505 (concat "\\<"
453 (regexp-opt 506 (regexp-opt
454 '("is" "separate" "end" "declare" "if" "new" "begin" "generic") t) 507 '("is" "separate" "end" "declare" "if" "new" "begin" "generic" "when") t)
455 "\\>")) 508 "\\>"))
456 "Regexp used in ada-goto-matching-decl-start.") 509 "Regexp used in ada-goto-matching-decl-start.")
457
458 510
459 (defvar ada-loop-start-re 511 (defvar ada-loop-start-re
460 "\\<\\(for\\|while\\|loop\\)\\>" 512 "\\<\\(for\\|while\\|loop\\)\\>"
461 "Regexp for the start of a loop.") 513 "Regexp for the start of a loop.")
462 514
471 "Regexp of the name of a block or loop.") 523 "Regexp of the name of a block or loop.")
472 524
473 (defvar ada-contextual-menu-on-identifier nil 525 (defvar ada-contextual-menu-on-identifier nil
474 "Set to true when the right mouse button was clicked on an identifier.") 526 "Set to true when the right mouse button was clicked on an identifier.")
475 527
528 (defvar ada-contextual-menu-last-point nil
529 "Position of point just before displaying the menu.
530 This is a list (point buffer).
531 Since `ada-popup-menu' moves the point where the user clicked, the region
532 is modified. Therefore no command from the menu knows what the user selected
533 before displaying the contextual menu.
534 To get the original region, restore the point to this position before
535 calling `region-end' and `region-beginning'.
536 Modify this variable if you want to restore the point to another position.")
537
476 (defvar ada-contextual-menu 538 (defvar ada-contextual-menu
539 (if ada-xemacs
540 '("Ada"
541 ["Goto Declaration/Body"
542 (ada-call-from-contextual-menu 'ada-point-and-xref)
543 :included (and (functionp 'ada-point-and-xref)
544 ada-contextual-menu-on-identifier)]
545 ["Goto Previous Reference"
546 (ada-call-from-contextual-menu 'ada-xref-goto-previous-reference)
547 :included (functionp 'ada-xref-goto-previous-reference)]
548 ["List References" ada-find-references
549 :included ada-contextual-menu-on-identifier]
550 ["-" nil nil]
551 ["Other File" ff-find-other-file]
552 ["Goto Parent Unit" ada-goto-parent]
553 )
554
555 (let ((map (make-sparse-keymap "Ada")))
556 ;; The identifier part
557 (if (equal ada-which-compiler 'gnat)
558 (progn
559 (define-key-after map [Ref]
560 '(menu-item "Goto Declaration/Body"
561 (lambda()(interactive)
562 (ada-call-from-contextual-menu
563 'ada-point-and-xref))
564 :visible
565 (and (functionp 'ada-point-and-xref)
566 ada-contextual-menu-on-identifier))
567 t)
568 (define-key-after map [Prev]
569 '(menu-item "Goto Previous Reference"
570 (lambda()(interactive)
571 (ada-call-from-contextual-menu
572 'ada-xref-goto-previous-reference))
573 :visible
574 (functionp 'ada-xref-goto-previous-reference))
575 t)
576 (define-key-after map [List]
577 '(menu-item "List References"
578 ada-find-references
579 :visible ada-contextual-menu-on-identifier) t)
580 (define-key-after map [-] '("-" nil) t)
581 ))
582 (define-key-after map [Other] '("Other file" . ff-find-other-file) t)
583 (define-key-after map [Parent] '("Goto Parent Unit" . ada-goto-parent)t)
584 map))
477 "Defines the menu to use when the user presses the right mouse button. 585 "Defines the menu to use when the user presses the right mouse button.
478 The variable `ada-contextual-menu-on-identifier' will be set to t before 586 The variable `ada-contextual-menu-on-identifier' will be set to t before
479 displaying the menu if point was on an identifier." 587 displaying the menu if point was on an identifier."
480 (if ada-xemacs 588 )
481 '("Ada"
482 ["Goto Declaration/Body" ada-goto-declaration
483 :included ada-contextual-menu-on-identifier]
484 ["Goto Previous Reference" ada-xref-goto-previous-reference]
485 ["List References" ada-find-references
486 :included ada-contextual-menu-on-identifier]
487 ["-" nil nil]
488 ["Other File" ff-find-other-file]
489 ["Goto Parent Unit" ada-goto-parent]
490 )
491
492 (let ((map (make-sparse-keymap "Ada")))
493 ;; The identifier part
494 (if (equal ada-which-compiler 'gnat)
495 (progn
496 (define-key-after map [Ref]
497 '(menu-item "Goto Declaration/Body"
498 ada-point-and-xref
499 :visible ada-contextual-menu-on-identifier
500 ) t)
501 (define-key-after map [Prev]
502 '("Goto Previous Reference" .ada-xref-goto-previous-reference) t)
503 (define-key-after map [List]
504 '(menu-item "List References"
505 ada-find-references
506 :visible ada-contextual-menu-on-identifier) t)
507 (define-key-after map [-] '("-" nil) t)
508 ))
509 (define-key-after map [Other] '("Other file" . ff-find-other-file) t)
510 (define-key-after map [Parent] '("Goto Parent Unit" . ada-goto-parent)t)
511 map)))
512
513 589
514 590
515 ;;------------------------------------------------------------------ 591 ;;------------------------------------------------------------------
516 ;; Support for imenu (see imenu.el) 592 ;; Support for imenu (see imenu.el)
517 ;;------------------------------------------------------------------ 593 ;;------------------------------------------------------------------
518 594
595 (defconst ada-imenu-subprogram-menu-re
596 "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)[ \t\n]*\\([ \t\n]\\|([^)]+)\\)[ \t\n]*\\(return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?is[ \t\n]")
597
519 (defvar ada-imenu-generic-expression 598 (defvar ada-imenu-generic-expression
520 (list 599 (list
521 '(nil "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)[ \t\n]*\\([ \t\n]\\|([^)]+)\\)[ \t\n]*\\(return[ \t\n]+\\(\\sw\\|[_.]\\)+[ \t\n]*\\)?is[ \t\n]" 2) 600 (list nil ada-imenu-subprogram-menu-re 2)
522 (list "*Specs*" 601 (list "*Specs*"
523 (concat 602 (concat
524 "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)" 603 "^[ \t]*\\(procedure\\|function\\)[ \t\n]+\\(\\(\\sw\\|_\\)+\\)"
525 "\\(" 604 "\\("
526 "\\([ \t\n]+\\|[ \t\n]*([^)]+)\\)";; parameter list or simple space 605 "\\([ \t\n]+\\|[ \t\n]*([^)]+)\\)";; parameter list or simple space
532 "Imenu generic expression for Ada mode. 611 "Imenu generic expression for Ada mode.
533 See `imenu-generic-expression'. This variable will create two submenus, one 612 See `imenu-generic-expression'. This variable will create two submenus, one
534 for type and subtype definitions, the other for subprograms declarations. 613 for type and subtype definitions, the other for subprograms declarations.
535 The main menu will reference the bodies of the subprograms.") 614 The main menu will reference the bodies of the subprograms.")
536 615
616
537 617
538 ;;------------------------------------------------------------ 618 ;;------------------------------------------------------------
539 ;; Support for compile.el 619 ;; Support for compile.el
540 ;;------------------------------------------------------------ 620 ;;------------------------------------------------------------
541 621
542 (defun ada-compile-mouse-goto-error () 622 (defun ada-compile-mouse-goto-error ()
543 "Mouse interface for `ada-compile-goto-error'." 623 "Mouse interface for ada-compile-goto-error."
544 (interactive) 624 (interactive)
545 (mouse-set-point last-input-event) 625 (mouse-set-point last-input-event)
546 (ada-compile-goto-error (point)) 626 (ada-compile-goto-error (point))
547 ) 627 )
548 628
558 638
559 (skip-chars-backward "-a-zA-Z0-9_:./\\") 639 (skip-chars-backward "-a-zA-Z0-9_:./\\")
560 (cond 640 (cond
561 ;; special case: looking at a filename:line not at the beginning of a line 641 ;; special case: looking at a filename:line not at the beginning of a line
562 ((and (not (bolp)) 642 ((and (not (bolp))
563 (looking-at 643 (looking-at
564 "\\(\\(\\sw\\|[_-.]\\)+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?")) 644 "\\([-_.a-zA-Z0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"))
565 (let ((line (match-string 3)) 645 (let ((line (match-string 2))
566 (error-pos (point-marker)) 646 (error-pos (point-marker))
567 source) 647 source)
568 (save-excursion 648 (save-excursion
569 (save-restriction 649 (save-restriction
570 (widen) 650 (widen)
571 (set-buffer (compilation-find-file (point-marker) (match-string 1) 651 ;; Use funcall so as to prevent byte-compiler warnings
572 "./")) 652 (set-buffer (funcall (symbol-function 'compilation-find-file)
653 (point-marker) (match-string 1)
654 "./"))
573 (if (stringp line) 655 (if (stringp line)
574 (goto-line (string-to-number line))) 656 (goto-line (string-to-number line)))
575 (set 'source (point-marker)))) 657 (set 'source (point-marker))))
576 (compilation-goto-locus (cons source error-pos)) 658 (funcall (symbol-function 'compilation-goto-locus)
659 (cons source error-pos))
577 )) 660 ))
578 661
579 ;; otherwise, default behavior 662 ;; otherwise, default behavior
580 (t 663 (t
581 (compile-goto-error)) 664 (funcall (symbol-function 'compile-goto-error)))
582 ) 665 )
583 (recenter)) 666 (recenter))
584 667
668
585 ;;------------------------------------------------------------------------- 669 ;;-------------------------------------------------------------------------
586 ;; Grammar related function 670 ;; Grammar related function
587 ;; The functions below work with the syntax class of the characters in an Ada 671 ;; The functions below work with the syntax class of the characters in an Ada
588 ;; buffer. Two syntax tables are created, depending on whether we want '_' 672 ;; buffer. Two syntax tables are created, depending on whether we want '_'
589 ;; to be considered as part of a word or not. 673 ;; to be considered as part of a word or not.
691 (while (re-search-forward "\\(#[0-9a-fA-F]*#\\)" to t) 775 (while (re-search-forward "\\(#[0-9a-fA-F]*#\\)" to t)
692 (set 'change (cons (list (match-beginning 1) 776 (set 'change (cons (list (match-beginning 1)
693 (length (match-string 1)) 777 (length (match-string 1))
694 (match-string 1)) 778 (match-string 1))
695 change)) 779 change))
696 (replace-match (make-string (length (match-string 1)) ?@)))) 780 (replace-match (make-string (length (match-string 1)) ?@))))
697 ad-do-it 781 ad-do-it
698 (save-excursion 782 (save-excursion
699 (while change 783 (while change
700 (goto-char (caar change)) 784 (goto-char (caar change))
701 (delete-char (cadar change)) 785 (delete-char (cadar change))
747 (if (looking-at "^[ \t]*#") 831 (if (looking-at "^[ \t]*#")
748 (add-text-properties (match-beginning 0) (match-end 0) 832 (add-text-properties (match-beginning 0) (match-end 0)
749 '(syntax-table (11 . 10)))) 833 '(syntax-table (11 . 10))))
750 )))) 834 ))))
751 835
836 ;;------------------------------------------------------------------
837 ;; Testing the grammatical context
838 ;;------------------------------------------------------------------
839
840 (defsubst ada-in-comment-p (&optional parse-result)
841 "Returns t if inside a comment."
842 (nth 4 (or parse-result
843 (parse-partial-sexp
844 (save-excursion (beginning-of-line) (point)) (point)))))
845
846 (defsubst ada-in-string-p (&optional parse-result)
847 "Returns t if point is inside a string.
848 If parse-result is non-nil, use is instead of calling parse-partial-sexp."
849 (nth 3 (or parse-result
850 (parse-partial-sexp
851 (save-excursion (beginning-of-line) (point)) (point)))))
852
853 (defsubst ada-in-string-or-comment-p (&optional parse-result)
854 "Returns t if inside a comment or string."
855 (set 'parse-result (or parse-result
856 (parse-partial-sexp
857 (save-excursion (beginning-of-line) (point)) (point))))
858 (or (ada-in-string-p parse-result) (ada-in-comment-p parse-result)))
859
752 860
753 ;;------------------------------------------------------------------ 861 ;;------------------------------------------------------------------
754 ;; Contextual menus 862 ;; Contextual menus
755 ;; The Ada-mode comes with fully contextual menus, bound by default 863 ;; The Ada-mode comes with contextual menus, bound by default to the right
756 ;; on the right mouse button. 864 ;; mouse button.
757 ;; Add items to this menu by modifying `ada-contextual-menu'. Note that the 865 ;; Add items to this menu by modifying `ada-contextual-menu'. Note that the
758 ;; variable `ada-contextual-menu-on-identifier' is set automatically to t 866 ;; variable `ada-contextual-menu-on-identifier' is set automatically to t
759 ;; if the mouse button was pressed on an identifier. 867 ;; if the mouse button was pressed on an identifier.
760 ;;------------------------------------------------------------------ 868 ;;------------------------------------------------------------------
761 869
870 (defun ada-call-from-contextual-menu (function)
871 "Execute FUNCTION when called from the contextual menu.
872 It forces Emacs to change the cursor position."
873 (interactive)
874 (funcall function)
875 (setq ada-contextual-menu-last-point
876 (list (point) (current-buffer))))
877
762 (defun ada-popup-menu (position) 878 (defun ada-popup-menu (position)
763 "Pops up a contextual menu, depending on where the user clicked. 879 "Pops up a contextual menu, depending on where the user clicked.
764 POSITION is the location the mouse was clicked on." 880 POSITION is the location the mouse was clicked on.
881 Sets `ada-contextual-menu-last-point' to the current position before
882 displaying the menu. When a function from the menu is called, the point is
883 where the mouse button was clicked."
765 (interactive "e") 884 (interactive "e")
766 (save-excursion 885
886 ;; declare this as a local variable, so that the function called
887 ;; in the contextual menu does not hide the region in
888 ;; transient-mark-mode.
889 (let ((deactivate-mark nil))
890 (set 'ada-contextual-menu-last-point
891 (list (point) (current-buffer)))
767 (mouse-set-point last-input-event) 892 (mouse-set-point last-input-event)
768 893
769 (setq ada-contextual-menu-on-identifier 894 (setq ada-contextual-menu-on-identifier
770 (and (char-after) 895 (and (char-after)
771 (or (= (char-syntax (char-after)) ?w) 896 (or (= (char-syntax (char-after)) ?w)
772 (= (char-after) ?_)) 897 (= (char-after) ?_))
773 (not (ada-in-string-or-comment-p)) 898 (not (ada-in-string-or-comment-p))
774 (save-excursion (skip-syntax-forward "w") 899 (save-excursion (skip-syntax-forward "w")
775 (not (ada-after-keyword-p))) 900 (not (ada-after-keyword-p)))
776 )) 901 ))
777 (let (choice) 902 (let (choice)
778 (if ada-xemacs 903 (if ada-xemacs
779 (set 'choice (popup-menu ada-contextual-menu)) 904 (set 'choice (funcall (symbol-function 'popup-menu)
780 (set 'choice (x-popup-menu position ada-contextual-menu))) 905 ada-contextual-menu))
906 (set 'choice (x-popup-menu position ada-contextual-menu)))
781 (if choice 907 (if choice
782 (funcall (lookup-key ada-contextual-menu (vector (car choice)))))))) 908 (funcall (lookup-key ada-contextual-menu (vector (car choice))))))
909 (set-buffer (cadr ada-contextual-menu-last-point))
910 (goto-char (car ada-contextual-menu-last-point))
911 ))
912
783 913
784 ;;------------------------------------------------------------------ 914 ;;------------------------------------------------------------------
785 ;; Misc functions 915 ;; Misc functions
786 ;;------------------------------------------------------------------ 916 ;;------------------------------------------------------------------
787 917
791 Going from body to spec with `ff-find-other-file' used these 921 Going from body to spec with `ff-find-other-file' used these
792 extensions. 922 extensions.
793 SPEC and BODY are two regular expressions that must match against the file 923 SPEC and BODY are two regular expressions that must match against the file
794 name" 924 name"
795 (let* ((reg (concat (regexp-quote body) "$")) 925 (let* ((reg (concat (regexp-quote body) "$"))
796 (tmp (assoc reg ada-other-file-alist))) 926 (tmp (assoc reg ada-other-file-alist)))
797 (if tmp 927 (if tmp
798 (setcdr tmp (list (cons spec (cadr tmp)))) 928 (setcdr tmp (list (cons spec (cadr tmp))))
799 (add-to-list 'ada-other-file-alist (list reg (list spec))))) 929 (add-to-list 'ada-other-file-alist (list reg (list spec)))))
800 930
801 (let* ((reg (concat (regexp-quote spec) "$")) 931 (let* ((reg (concat (regexp-quote spec) "$"))
802 (tmp (assoc reg ada-other-file-alist))) 932 (tmp (assoc reg ada-other-file-alist)))
803 (if tmp 933 (if tmp
804 (setcdr tmp (list (cons body (cadr tmp)))) 934 (setcdr tmp (list (cons body (cadr tmp))))
805 (add-to-list 'ada-other-file-alist (list reg (list body))))) 935 (add-to-list 'ada-other-file-alist (list reg (list body)))))
806 936
807 (add-to-list 'auto-mode-alist (cons spec 'ada-mode)) 937 (add-to-list 'auto-mode-alist (cons spec 'ada-mode))
808 (add-to-list 'auto-mode-alist (cons body 'ada-mode)) 938 (add-to-list 'auto-mode-alist (cons body 'ada-mode))
809 939
813 ;; Support for speedbar (Specifies that we want to see these files in 943 ;; Support for speedbar (Specifies that we want to see these files in
814 ;; speedbar) 944 ;; speedbar)
815 (condition-case nil 945 (condition-case nil
816 (progn 946 (progn
817 (require 'speedbar) 947 (require 'speedbar)
818 (speedbar-add-supported-extension spec) 948 (funcall (symbol-function 'speedbar-add-supported-extension)
819 (speedbar-add-supported-extension body))) 949 spec)
950 (funcall (symbol-function 'speedbar-add-supported-extension)
951 body)))
820 ) 952 )
821
822 953
823 954
824 ;;;###autoload 955 ;;;###autoload
825 (defun ada-mode () 956 (defun ada-mode ()
826 "Ada mode is the major mode for editing Ada code. 957 "Ada mode is the major mode for editing Ada code.
861 If you use this function in a spec and no body is available, it gets created with body stubs. 992 If you use this function in a spec and no body is available, it gets created with body stubs.
862 993
863 If you use ada-xref.el: 994 If you use ada-xref.el:
864 Goto declaration: '\\[ada-point-and-xref]' on the identifier 995 Goto declaration: '\\[ada-point-and-xref]' on the identifier
865 or '\\[ada-goto-declaration]' with point on the identifier 996 or '\\[ada-goto-declaration]' with point on the identifier
866 Complete identifier: '\\[ada-complete-identifier]'" 997 Complete identifier: '\\[ada-complete-identifier]'."
867 998
868 (interactive) 999 (interactive)
869 (kill-all-local-variables) 1000 (kill-all-local-variables)
870 1001
871 (set (make-local-variable 'require-final-newline) t) 1002 (set (make-local-variable 'require-final-newline) t)
892 ;; correctly with the definition of paragraph-start above when the comment 1023 ;; correctly with the definition of paragraph-start above when the comment
893 ;; is right after a multi-line subprogram declaration (the comments are 1024 ;; is right after a multi-line subprogram declaration (the comments are
894 ;; aligned under the latest parameter, not under the declaration start). 1025 ;; aligned under the latest parameter, not under the declaration start).
895 (set (make-local-variable 'comment-line-break-function) 1026 (set (make-local-variable 'comment-line-break-function)
896 (lambda (&optional soft) (let ((fill-prefix nil)) 1027 (lambda (&optional soft) (let ((fill-prefix nil))
897 (indent-new-comment-line soft)))) 1028 (indent-new-comment-line soft))))
898 1029
899 (set (make-local-variable 'indent-line-function) 1030 (set (make-local-variable 'indent-line-function)
900 'ada-indent-current-function) 1031 'ada-indent-current-function)
901 1032
902 (set (make-local-variable 'comment-column) 40) 1033 (set (make-local-variable 'comment-column) 40)
903 1034
925 1056
926 ;; Support for compile.el 1057 ;; Support for compile.el
927 ;; We just substitute our own functions to go to the error. 1058 ;; We just substitute our own functions to go to the error.
928 (add-hook 'compilation-mode-hook 1059 (add-hook 'compilation-mode-hook
929 (lambda() 1060 (lambda()
930 (set 'compile-auto-highlight 40) 1061 (set 'compile-auto-highlight 40)
931 (define-key compilation-minor-mode-map [mouse-2] 1062 (define-key compilation-minor-mode-map [mouse-2]
932 'ada-compile-mouse-goto-error) 1063 'ada-compile-mouse-goto-error)
933 (define-key compilation-minor-mode-map "\C-c\C-c" 1064 (define-key compilation-minor-mode-map "\C-c\C-c"
934 'ada-compile-goto-error) 1065 'ada-compile-goto-error)
935 (define-key compilation-minor-mode-map "\C-m" 1066 (define-key compilation-minor-mode-map "\C-m"
936 'ada-compile-goto-error) 1067 'ada-compile-goto-error)
937 )) 1068 ))
938 1069
939 ;; font-lock support : 1070 ;; font-lock support :
940 ;; We need to set some properties for XEmacs, and define some variables 1071 ;; We need to set some properties for XEmacs, and define some variables
941 ;; for Emacs 1072 ;; for Emacs
942 1073
951 nil t 1082 nil t
952 ((?\_ . "w") (?# . ".")) 1083 ((?\_ . "w") (?# . "."))
953 beginning-of-line 1084 beginning-of-line
954 (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords))) 1085 (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords)))
955 ) 1086 )
956 1087
957 ;; Set up support for find-file.el. 1088 ;; Set up support for find-file.el.
958 (set (make-variable-buffer-local 'ff-other-file-alist) 1089 (set (make-variable-buffer-local 'ff-other-file-alist)
959 'ada-other-file-alist) 1090 'ada-other-file-alist)
960 (set (make-variable-buffer-local 'ff-search-directories) 1091 (set (make-variable-buffer-local 'ff-search-directories)
961 'ada-search-directories) 1092 'ada-search-directories)
962 (setq ff-post-load-hooks 'ada-set-point-accordingly 1093 (setq ff-post-load-hooks 'ada-set-point-accordingly
963 ff-file-created-hooks 'ada-make-body) 1094 ff-file-created-hooks 'ada-make-body)
964 (add-hook 'ff-pre-load-hooks 'ada-which-function-are-we-in) 1095 (add-hook 'ff-pre-load-hooks 'ada-which-function-are-we-in)
965 1096
966 ;; Some special constructs for find-file.el 1097 ;; Some special constructs for find-file.el
967 ;; We do not need to add the construction for 'with', which is in the 1098 ;; We do not need to add the construction for 'with', which is in the
968 ;; standard find-file.el 1099 ;; standard find-file.el
1100 (make-local-variable 'ff-special-constructs)
1101
969 ;; Go to the parent package : 1102 ;; Go to the parent package :
970 (make-local-variable 'ff-special-constructs)
971 (add-to-list 'ff-special-constructs 1103 (add-to-list 'ff-special-constructs
972 (cons (eval-when-compile 1104 (cons (eval-when-compile
973 (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+" 1105 (concat "^\\(private[ \t]\\)?[ \t]*package[ \t]+"
974 "\\(body[ \t]+\\)?" 1106 "\\(body[ \t]+\\)?"
975 "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is")) 1107 "\\(\\(\\sw\\|[_.]\\)+\\)\\.\\(\\sw\\|_\\)+[ \t\n]+is"))
976 (lambda () 1108 (lambda ()
977 (set 'fname (ff-get-file 1109 (set 'fname (ff-get-file
978 ff-search-directories 1110 ada-search-directories
979 (ada-make-filename-from-adaname 1111 (ada-make-filename-from-adaname
980 (match-string 3)) 1112 (match-string 3))
981 ada-spec-suffixes))))) 1113 ada-spec-suffixes)))))
982 ;; Another special construct for find-file.el : when in a separate clause, 1114 ;; Another special construct for find-file.el : when in a separate clause,
983 ;; go to the correct package. 1115 ;; go to the correct package.
984 (add-to-list 'ff-special-constructs 1116 (add-to-list 'ff-special-constructs
985 (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))" 1117 (cons "^separate[ \t\n]*(\\(\\(\\sw\\|[_.]\\)+\\))"
986 (lambda () 1118 (lambda ()
987 (set 'fname (ff-get-file 1119 (set 'fname (ff-get-file
988 ff-search-directories 1120 ada-search-directories
989 (ada-make-filename-from-adaname 1121 (ada-make-filename-from-adaname
990 (match-string 1)) 1122 (match-string 1))
991 ada-spec-suffixes))))) 1123 ada-spec-suffixes)))))
992 ;; Another special construct, that redefines the one in find-file.el. The 1124 ;; Another special construct, that redefines the one in find-file.el. The
993 ;; old one can handle only one possible type of extension for Ada files 1125 ;; old one can handle only one possible type of extension for Ada files
994 (add-to-list 'ff-special-constructs 1126 ;; remove from the list the standard "with..." that is put by find-file.el,
995 (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" 1127 ;; since it uses the old ada-spec-suffix variable
996 (lambda () 1128 ;; This one needs to replace the standard one defined in find-file.el (with
997 (set 'fname (ff-get-file 1129 ;; Emacs <= 20.4), since that one uses the old variable ada-spec-suffix
998 ff-search-directories 1130 (let ((old-construct
999 (ada-make-filename-from-adaname 1131 (assoc "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)" ff-special-constructs))
1000 (match-string 1)) 1132 (new-cdr
1001 ada-spec-suffixes))))) 1133 (lambda ()
1002 1134 (set 'fname (ff-get-file
1135 ada-search-directories
1136 (ada-make-filename-from-adaname
1137 (match-string 1))
1138 ada-spec-suffixes)))))
1139 (if old-construct
1140 (setcdr old-construct new-cdr)
1141 (add-to-list 'ff-special-constructs
1142 (cons "^with[ \t]+\\([a-zA-Z0-9_\\.]+\\)"
1143 new-cdr))))
1144
1003 ;; Support for outline-minor-mode 1145 ;; Support for outline-minor-mode
1004 (set (make-local-variable 'outline-regexp) 1146 (set (make-local-variable 'outline-regexp)
1005 "\\([ \t]*\\(procedure\\|function\\|package\\|with\\|use\\)\\|--\\|end\\)") 1147 "\\([ \t]*\\(procedure\\|function\\|package\\|if\\|while\\|for\\|declare\\|case\\|end\\|begin\\|loop\\)\\|--\\)")
1006 (set (make-local-variable 'outline-level) 'ada-outline-level) 1148 (set (make-local-variable 'outline-level) 'ada-outline-level)
1007 1149
1008 ;; Support for imenu : We want a sorted index 1150 ;; Support for imenu : We want a sorted index
1009 (set 'imenu-sort-function 'imenu--sort-by-name) 1151 (set 'imenu-sort-function 'imenu--sort-by-name)
1152
1153 ;; Support for which-function-mode is provided in ada-support (support
1154 ;; for nested subprograms)
1010 1155
1011 ;; Set up the contextual menu 1156 ;; Set up the contextual menu
1012 (if ada-popup-key 1157 (if ada-popup-key
1013 (define-key ada-mode-map ada-popup-key 'ada-popup-menu)) 1158 (define-key ada-mode-map ada-popup-key 'ada-popup-menu))
1014 1159
1160 ;; Support for Abbreviations (the user still need to "M-x abbrev-mode"
1161 (define-abbrev-table 'ada-mode-abbrev-table ())
1162 (set 'local-abbrev-table ada-mode-abbrev-table)
1163
1015 ;; Support for indent-new-comment-line (Especially for XEmacs) 1164 ;; Support for indent-new-comment-line (Especially for XEmacs)
1016 (set 'comment-multi-line nil) 1165 (set 'comment-multi-line nil)
1017 (defconst comment-indent-function (lambda () comment-column)) 1166 (defconst comment-indent-function (lambda () comment-column))
1018 1167
1019 (set 'major-mode 'ada-mode) 1168 (set 'major-mode 'ada-mode)
1020 (set 'mode-name "Ada") 1169 (set 'mode-name "Ada")
1021 1170
1022 (use-local-map ada-mode-map) 1171 (use-local-map ada-mode-map)
1023 1172
1024 (if ada-xemacs 1173 (if ada-xemacs
1025 (easy-menu-add ada-mode-menu ada-mode-map)) 1174 (funcall (symbol-function 'easy-menu-add)
1026 1175 ada-mode-menu ada-mode-map))
1176
1027 (set-syntax-table ada-mode-syntax-table) 1177 (set-syntax-table ada-mode-syntax-table)
1028 1178
1029 (if ada-clean-buffer-before-saving 1179 (if ada-clean-buffer-before-saving
1030 (progn 1180 (progn
1031 ;; remove all spaces at the end of lines in the whole buffer. 1181 ;; remove all spaces at the end of lines in the whole buffer.
1046 (add-hook 'font-lock-mode-hook 'ada-deactivate-properties nil t))) 1196 (add-hook 'font-lock-mode-hook 'ada-deactivate-properties nil t)))
1047 1197
1048 ;; the following has to be done after running the ada-mode-hook 1198 ;; the following has to be done after running the ada-mode-hook
1049 ;; because users might want to set the values of these variable 1199 ;; because users might want to set the values of these variable
1050 ;; inside the hook (MH) 1200 ;; inside the hook (MH)
1051 ;; Note that we add the new elements at the end of ada-other-file-alist
1052 ;; since some user might want to give priority to some other extensions
1053 ;; first (for instance, a .adb file could be associated with a .ads
1054 ;; or a .ads.gp (gnatprep)).
1055 ;; This is why we can't use add-to-list here.
1056 1201
1057 (cond ((eq ada-language-version 'ada83) 1202 (cond ((eq ada-language-version 'ada83)
1058 (set 'ada-keywords ada-83-keywords)) 1203 (set 'ada-keywords ada-83-keywords))
1059 ((eq ada-language-version 'ada95) 1204 ((eq ada-language-version 'ada95)
1060 (set 'ada-keywords ada-95-keywords))) 1205 (set 'ada-keywords ada-95-keywords)))
1072 ;; are references to the functions that will do the actual casing. 1217 ;; are references to the functions that will do the actual casing.
1073 ;; 1218 ;;
1074 ;; However, in most cases, the user will want to define some exceptions to 1219 ;; However, in most cases, the user will want to define some exceptions to
1075 ;; these casing rules. This is done through a list of files, that contain 1220 ;; these casing rules. This is done through a list of files, that contain
1076 ;; one word per line. These files are stored in `ada-case-exception-file'. 1221 ;; one word per line. These files are stored in `ada-case-exception-file'.
1222 ;; For backward compatibility, this variable can also be a string.
1077 ;;----------------------------------------------------------------- 1223 ;;-----------------------------------------------------------------
1078 1224
1079 (defun ada-create-case-exception (&optional word) 1225 (defun ada-create-case-exception (&optional word)
1080 "Defines WORD as an exception for the casing system. 1226 "Defines WORD as an exception for the casing system.
1081 If WORD is not given, then the current word in the buffer is used instead. 1227 If WORD is not given, then the current word in the buffer is used instead.
1082 The new words is added to the first file in `ada-case-exception-file'. 1228 The new words is added to the first file in `ada-case-exception-file'.
1083 The standard casing rules will no longer apply to this word." 1229 The standard casing rules will no longer apply to this word."
1084 (interactive) 1230 (interactive)
1085 (let ((previous-syntax-table (syntax-table)) 1231 (let ((previous-syntax-table (syntax-table))
1086 (exception-list '())) 1232 (exception-list '())
1233 file-name
1234 )
1235
1236 (cond ((stringp ada-case-exception-file)
1237 (set 'file-name ada-case-exception-file))
1238 ((listp ada-case-exception-file)
1239 (set 'file-name (car ada-case-exception-file)))
1240 (t
1241 (error "No exception file specified")))
1242
1087 (set-syntax-table ada-mode-symbol-syntax-table) 1243 (set-syntax-table ada-mode-symbol-syntax-table)
1088 (unless word 1244 (unless word
1089 (save-excursion 1245 (save-excursion
1090 (skip-syntax-backward "w") 1246 (skip-syntax-backward "w")
1091 (set 'word (buffer-substring-no-properties 1247 (set 'word (buffer-substring-no-properties
1092 (point) (save-excursion (forward-word 1) (point)))))) 1248 (point) (save-excursion (forward-word 1) (point))))))
1093 1249
1094 ;; Reread the exceptions file, in case it was modified by some other, 1250 ;; Reread the exceptions file, in case it was modified by some other,
1095 ;; and to keep the end-of-line comments that may exist in it. 1251 ;; and to keep the end-of-line comments that may exist in it.
1096 (if (file-readable-p (expand-file-name ada-case-exception-file)) 1252 (if (file-readable-p (expand-file-name file-name))
1097 (let ((buffer (current-buffer))) 1253 (let ((buffer (current-buffer)))
1098 (find-file (expand-file-name ada-case-exception-file)) 1254 (find-file (expand-file-name file-name))
1099 (set-syntax-table ada-mode-symbol-syntax-table) 1255 (set-syntax-table ada-mode-symbol-syntax-table)
1100 (widen) 1256 (widen)
1101 (goto-char (point-min)) 1257 (goto-char (point-min))
1102 (while (not (eobp)) 1258 (while (not (eobp))
1103 (add-to-list 'exception-list 1259 (add-to-list 'exception-list
1104 (list 1260 (list
1105 (buffer-substring-no-properties 1261 (buffer-substring-no-properties
1106 (point) (save-excursion (forward-word 1) (point))) 1262 (point) (save-excursion (forward-word 1) (point)))
1107 (buffer-substring-no-properties 1263 (buffer-substring-no-properties
1108 (save-excursion (forward-word 1) (point)) 1264 (save-excursion (forward-word 1) (point))
1109 (save-excursion (end-of-line) (point))) 1265 (save-excursion (end-of-line) (point)))
1110 t)) 1266 t))
1111 (forward-line 1)) 1267 (forward-line 1))
1112 (kill-buffer nil) 1268 (kill-buffer nil)
1113 (set-buffer buffer))) 1269 (set-buffer buffer)))
1114 1270
1115 ;; If the word is already in the list, even with a different casing 1271 ;; If the word is already in the list, even with a different casing
1116 ;; we simply want to replace it. 1272 ;; we simply want to replace it.
1117 (if (and (not (equal exception-list '())) 1273 (if (and (not (equal exception-list '()))
1118 (assoc-ignore-case word exception-list)) 1274 (assoc-ignore-case word exception-list))
1119 (setcar (assoc-ignore-case word exception-list) 1275 (setcar (assoc-ignore-case word exception-list)
1120 word) 1276 word)
1121 (add-to-list 'exception-list (list word "" t)) 1277 (add-to-list 'exception-list (list word "" t))
1122 ) 1278 )
1123 1279
1124 (if (and (not (equal ada-case-exception '())) 1280 (if (and (not (equal ada-case-exception '()))
1125 (assoc-ignore-case word ada-case-exception)) 1281 (assoc-ignore-case word ada-case-exception))
1126 (setcar (assoc-ignore-case word ada-case-exception) 1282 (setcar (assoc-ignore-case word ada-case-exception)
1127 word) 1283 word)
1128 (add-to-list 'ada-case-exception (cons word t)) 1284 (add-to-list 'ada-case-exception (cons word t))
1129 ) 1285 )
1130 1286
1131 ;; Save the list in the file 1287 ;; Save the list in the file
1132 (find-file (expand-file-name ada-case-exception-file)) 1288 (find-file (expand-file-name file-name))
1133 (erase-buffer) 1289 (erase-buffer)
1134 (mapcar (lambda (x) (insert (car x) (nth 1 x) "\n")) 1290 (mapcar (lambda (x) (insert (car x) (nth 1 x) "\n"))
1135 (sort exception-list 1291 (sort exception-list
1136 (lambda(a b) (string< (car a) (car b))))) 1292 (lambda(a b) (string< (car a) (car b)))))
1137 (save-buffer) 1293 (save-buffer)
1138 (kill-buffer nil) 1294 (kill-buffer nil)
1139 (set-syntax-table previous-syntax-table) 1295 (set-syntax-table previous-syntax-table)
1140 )) 1296 ))
1141 1297
1142 (defun ada-case-read-exceptions () 1298 (defun ada-case-read-exceptions-from-file (file-name)
1143 "Parse `ada-case-exception-file' for the dictionary of casing exceptions." 1299 "Read the content of the casing exception file FILE-NAME."
1144 (interactive) 1300 (if (file-readable-p (expand-file-name file-name))
1145 (set 'ada-case-exception '())
1146 (if (file-readable-p (expand-file-name ada-case-exception-file))
1147 (let ((buffer (current-buffer))) 1301 (let ((buffer (current-buffer)))
1148 (find-file (expand-file-name ada-case-exception-file)) 1302 (find-file (expand-file-name file-name))
1149 (set-syntax-table ada-mode-symbol-syntax-table) 1303 (set-syntax-table ada-mode-symbol-syntax-table)
1150 (widen) 1304 (widen)
1151 (goto-char (point-min)) 1305 (goto-char (point-min))
1152 (while (not (eobp)) 1306 (while (not (eobp))
1153 (add-to-list 'ada-case-exception 1307
1154 (cons 1308 ;; If the item is already in the list, even with an other casing,
1155 (buffer-substring-no-properties 1309 ;; do not add it again. This way, the user can easily decide which
1156 (point) (save-excursion (forward-word 1) (point))) 1310 ;; priority should be applied to each casing exception
1157 t)) 1311 (let ((word (buffer-substring-no-properties
1312 (point) (save-excursion (forward-word 1) (point)))))
1313 (unless (assoc-ignore-case word ada-case-exception)
1314 (add-to-list 'ada-case-exception (cons word t))))
1315
1158 (forward-line 1)) 1316 (forward-line 1))
1159 (kill-buffer nil) 1317 (kill-buffer nil)
1160 (set-buffer buffer) 1318 (set-buffer buffer)))
1161 ))) 1319 )
1320
1321 (defun ada-case-read-exceptions ()
1322 "Read all the casing exception files from `ada-case-exception-file'."
1323 (interactive)
1324
1325 ;; Reinitialize the casing exception list
1326 (set 'ada-case-exception '())
1327
1328 (cond ((stringp ada-case-exception-file)
1329 (ada-case-read-exceptions-from-file ada-case-exception-file))
1330
1331 ((listp ada-case-exception-file)
1332 (mapcar 'ada-case-read-exceptions-from-file
1333 ada-case-exception-file))))
1162 1334
1163 (defun ada-adjust-case-identifier () 1335 (defun ada-adjust-case-identifier ()
1164 "Adjust case of the previous identifier. 1336 "Adjust case of the previous identifier.
1165 The auto-casing is done according to the value of `ada-case-identifier' and 1337 The auto-casing is done according to the value of `ada-case-identifier' and
1166 the exceptions defined in `ada-case-exception-file'." 1338 the exceptions defined in `ada-case-exception-file'."
1339 (interactive)
1167 (if (or (equal ada-case-exception '()) 1340 (if (or (equal ada-case-exception '())
1168 (equal (char-after) ?_)) 1341 (equal (char-after) ?_))
1169 (funcall ada-case-identifier -1) 1342 (funcall ada-case-identifier -1)
1170 1343
1171 (progn 1344 (progn
1172 (let ((end (point)) 1345 (let ((end (point))
1173 (start (save-excursion (skip-syntax-backward "w") 1346 (start (save-excursion (skip-syntax-backward "w")
1174 (point))) 1347 (point)))
1175 match) 1348 match)
1176 ;; If we have an exception, replace the word by the correct casing 1349 ;; If we have an exception, replace the word by the correct casing
1177 (if (set 'match (assoc-ignore-case (buffer-substring start end) 1350 (if (set 'match (assoc-ignore-case (buffer-substring start end)
1178 ada-case-exception)) 1351 ada-case-exception))
1179 1352
1183 1356
1184 ;; Else simply re-case the word 1357 ;; Else simply re-case the word
1185 (funcall ada-case-identifier -1)))))) 1358 (funcall ada-case-identifier -1))))))
1186 1359
1187 (defun ada-after-keyword-p () 1360 (defun ada-after-keyword-p ()
1188 "Returns t if cursor is after a keyword." 1361 "Returns t if cursor is after a keyword that is not an attribute."
1189 (save-excursion 1362 (save-excursion
1190 (forward-word -1) 1363 (forward-word -1)
1191 (and (not (and (char-before) (= (char-before) ?_)));; unless we have a _ 1364 (and (not (and (char-before)
1365 (or (= (char-before) ?_)
1366 (= (char-before) ?'))));; unless we have a _ or '
1192 (looking-at (concat ada-keywords "[^_]"))))) 1367 (looking-at (concat ada-keywords "[^_]")))))
1193 1368
1194 (defun ada-adjust-case (&optional force-identifier) 1369 (defun ada-adjust-case (&optional force-identifier)
1195 "Adjust the case of the word before the just typed character. 1370 "Adjust the case of the word before the just typed character.
1196 If FORCE-IDENTIFIER is non-nil then also adjust keyword as identifier." 1371 If FORCE-IDENTIFIER is non-nil then also adjust keyword as identifier."
1197 (let ((previous-syntax-table (syntax-table))) 1372 (forward-char -1)
1198 (set-syntax-table ada-mode-symbol-syntax-table) 1373 (if (and (> (point) 1)
1199 1374 ;; or if at the end of a character constant
1200 (forward-char -1) 1375 (not (and (eq (char-after) ?')
1201 1376 (eq (char-before (1- (point))) ?')))
1202 ;; Do nothing in some cases 1377 ;; or if the previous character was not part of a word
1203 (if (and (> (point) 1) 1378 (eq (char-syntax (char-before)) ?w)
1204 1379 ;; if in a string or a comment
1205 ;; or if at the end of a character constant 1380 (not (ada-in-string-or-comment-p))
1206 (not (and (eq (char-after) ?') 1381 )
1207 (eq (char-before (1- (point))) ?'))) 1382 (if (save-excursion
1208 1383 (forward-word -1)
1209 ;; or if the previous character was not part of a word 1384 (or (= (point) (point-min))
1210 (eq (char-syntax (char-before)) ?w) 1385 (backward-char 1))
1211 1386 (= (char-after) ?'))
1212 ;; if in a string or a comment 1387 (funcall ada-case-attribute -1)
1213 (not (ada-in-string-or-comment-p)) 1388 (if (and
1214 ) 1389 (not force-identifier) ; (MH)
1215 1390 (ada-after-keyword-p))
1216 (if (save-excursion 1391 (funcall ada-case-keyword -1)
1217 (forward-word -1) 1392 (ada-adjust-case-identifier))))
1218 (or (= (point) (point-min)) 1393 (forward-char 1)
1219 (backward-char 1))
1220 (= (char-after) ?'))
1221 (funcall ada-case-attribute -1)
1222 (if (and
1223 (not force-identifier) ; (MH)
1224 (ada-after-keyword-p))
1225 (funcall ada-case-keyword -1)
1226 (ada-adjust-case-identifier))))
1227 (forward-char 1)
1228 (set-syntax-table previous-syntax-table)
1229 )
1230 ) 1394 )
1231 1395
1232 (defun ada-adjust-case-interactive (arg) 1396 (defun ada-adjust-case-interactive (arg)
1233 "Adjust the case of the previous word, and process the character just typed. 1397 "Adjust the case of the previous word, and process the character just typed.
1234 ARG is the prefix the user entered with \C-u." 1398 ARG is the prefix the user entered with \C-u."
1235 (interactive "P") 1399 (interactive "P")
1236 (let ((lastk last-command-char)) 1400
1237 (cond ((or (eq lastk ?\n) 1401 (if ada-auto-case
1238 (eq lastk ?\r)) 1402 (let ((lastk last-command-char)
1239 ;; horrible kludge 1403 (previous-syntax-table (syntax-table)))
1240 (insert " ") 1404
1241 (ada-adjust-case) 1405 (unwind-protect
1242 ;; horrible De-kludge 1406 (progn
1243 (delete-backward-char 1) 1407 (set-syntax-table ada-mode-symbol-syntax-table)
1244 ;; some special keys and their bindings 1408 (cond ((or (eq lastk ?\n)
1245 (cond 1409 (eq lastk ?\r))
1246 ((eq lastk ?\n) 1410 ;; horrible kludge
1247 (funcall ada-lfd-binding)) 1411 (insert " ")
1248 ((eq lastk ?\r) 1412 (ada-adjust-case)
1249 (funcall ada-ret-binding)))) 1413 ;; horrible dekludge
1250 ((eq lastk ?\C-i) (ada-tab)) 1414 (delete-backward-char 1)
1251 ((self-insert-command (prefix-numeric-value arg)))) 1415 ;; some special keys and their bindings
1252 ;; if there is a keyword in front of the underscore 1416 (cond
1253 ;; then it should be part of an identifier (MH) 1417 ((eq lastk ?\n)
1254 (if (eq lastk ?_) 1418 (funcall ada-lfd-binding))
1255 (ada-adjust-case t) 1419 ((eq lastk ?\r)
1256 (ada-adjust-case)))) 1420 (funcall ada-ret-binding))))
1257 1421 ((eq lastk ?\C-i) (ada-tab))
1422 ;; Else just insert the character
1423 ((self-insert-command (prefix-numeric-value arg))))
1424 ;; if there is a keyword in front of the underscore
1425 ;; then it should be part of an identifier (MH)
1426 (if (eq lastk ?_)
1427 (ada-adjust-case t)
1428 (ada-adjust-case))
1429 )
1430 ;; Restore the syntax table
1431 (set-syntax-table previous-syntax-table))
1432 )
1433
1434 ;; Else, no auto-casing
1435 (cond
1436 ((eq last-command-char ?\n)
1437 (funcall ada-lfd-binding))
1438 ((eq last-command-char ?\r)
1439 (funcall ada-ret-binding))
1440 (t
1441 (self-insert-command (prefix-numeric-value arg))))
1442 ))
1258 1443
1259 (defun ada-activate-keys-for-case () 1444 (defun ada-activate-keys-for-case ()
1260 "Modifies the key bindings for all the keys that should readjust the casing." 1445 "Modifies the key bindings for all the keys that should readjust the casing."
1261 (interactive) 1446 (interactive)
1262 ;; save original key bindings to allow swapping ret/lfd 1447 ;; Save original key-bindings to allow swapping ret/lfd
1263 ;; when casing is activated 1448 ;; when casing is activated.
1264 ;; the 'or ...' is there to be sure that the value will not 1449 ;; The 'or ...' is there to be sure that the value will not
1265 ;; be changed again when Ada mode is called more than once (MH) 1450 ;; be changed again when Ada mode is called more than once
1266 (or ada-ret-binding 1451 (or ada-ret-binding (set 'ada-ret-binding (key-binding "\C-M")))
1267 (set 'ada-ret-binding (key-binding "\C-M"))) 1452 (or ada-lfd-binding (set 'ada-lfd-binding (key-binding "\C-j")))
1268 (or ada-lfd-binding 1453
1269 (set 'ada-lfd-binding (key-binding "\C-j"))) 1454 ;; Call case modifying function after certain keys.
1270 ;; call case modifying function after certain keys.
1271 (mapcar (function (lambda(key) (define-key 1455 (mapcar (function (lambda(key) (define-key
1272 ada-mode-map 1456 ada-mode-map
1273 (char-to-string key) 1457 (char-to-string key)
1274 'ada-adjust-case-interactive))) 1458 'ada-adjust-case-interactive)))
1275 '( ?` ?~ ?! ?_ ?@ ?# ?$ ?% ?^ ?& ?* ?( ?) ?- ?= ?+ ?[ ?{ ?] ?} 1459 '( ?` ?_ ?# ?% ?& ?* ?( ?) ?- ?= ?+
1276 ?\\ ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?? ?/ ?\n 32 ?\r ))) 1460 ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?/ ?\n 32 ?\r )))
1277 1461
1278 (defun ada-loose-case-word (&optional arg) 1462 (defun ada-loose-case-word (&optional arg)
1279 "Upcase first letter and letters following `_' in the following word. 1463 "Upcase first letter and letters following `_' in the following word.
1280 No other letter is modified. 1464 No other letter is modified.
1281 ARG is ignored, and is there for compatibility with `capitalize-word' only." 1465 ARG is ignored, and is there for compatibility with `capitalize-word' only."
1282 (interactive) 1466 (interactive)
1283 (let ((pos (point)) 1467 (save-excursion
1284 (first t)) 1468 (let ((end (save-excursion (skip-syntax-forward "w") (point)))
1285 (skip-syntax-backward "w") 1469 (first t))
1286 (while (or first 1470 (skip-syntax-backward "w")
1287 (search-forward "_" pos t)) 1471 (while (and (or first (search-forward "_" end t))
1288 (and first 1472 (< (point) end))
1289 (set 'first nil)) 1473 (and first
1290 (insert-char (upcase (following-char)) 1) 1474 (set 'first nil))
1291 (delete-char 1)) 1475 (insert-char (upcase (following-char)) 1)
1292 (goto-char pos))) 1476 (delete-char 1)))))
1477
1478 (defun ada-no-auto-case (&optional arg)
1479 "Does nothing.
1480 This function can be used for the auto-casing variables in the ada-mode, to
1481 adapt to unusal auto-casing schemes. Since it does nothing, you can for
1482 instance use it for `ada-case-identifier' if you don't want any special
1483 auto-casing for identifiers, whereas keywords have to be lower-cased.
1484 See also `ada-auto-case' to disable auto casing altogether."
1485 )
1293 1486
1294 (defun ada-capitalize-word (&optional arg) 1487 (defun ada-capitalize-word (&optional arg)
1295 "Upcase first letter and letters following '_', lower case other letters. 1488 "Upcase first letter and letters following '_', lower case other letters.
1296 ARG is ignored, and is there for compatibility with `capitalize-word' only." 1489 ARG is ignored, and is there for compatibility with `capitalize-word' only."
1297 (interactive) 1490 (interactive)
1298 (let ((pos (point))) 1491 (let ((end (save-excursion (skip-syntax-forward "w") (point)))
1299 (skip-syntax-backward "w") 1492 (begin (save-excursion (skip-syntax-backward "w") (point))))
1300 (modify-syntax-entry ?_ "_") 1493 (modify-syntax-entry ?_ "_")
1301 (capitalize-region (point) pos) 1494 (capitalize-region begin end)
1302 (goto-char pos)
1303 (modify-syntax-entry ?_ "w"))) 1495 (modify-syntax-entry ?_ "w")))
1304 1496
1305 (defun ada-adjust-case-region (from to) 1497 (defun ada-adjust-case-region (from to)
1306 "Adjusts the case of all words in the region between FROM and TO. 1498 "Adjusts the case of all words in the region between FROM and TO.
1307 Attention: This function might take very long for big regions !" 1499 Attention: This function might take very long for big regions !"
1363 ;; format: 1555 ;; format:
1364 ;; ( (<Param_Name> in? out? access? <Type_Name> <Default_Expression>) 1556 ;; ( (<Param_Name> in? out? access? <Type_Name> <Default_Expression>)
1365 ;; ... ) 1557 ;; ... )
1366 ;; This is done in `ada-scan-paramlist'. 1558 ;; This is done in `ada-scan-paramlist'.
1367 ;; - Delete and recreate the parameter list in function 1559 ;; - Delete and recreate the parameter list in function
1368 ;; `ada-format-paramlist'. 1560 ;; `ada-insert-paramlist'.
1561 ;; Both steps are called from `ada-format-paramlist'.
1369 ;; Note: Comments inside the parameter list are lost. 1562 ;; Note: Comments inside the parameter list are lost.
1370 ;; The syntax has to be correct, or the reformating will fail. 1563 ;; The syntax has to be correct, or the reformating will fail.
1371 ;;-------------------------------------------------------------- 1564 ;;--------------------------------------------------------------
1372 1565
1373 (defun ada-format-paramlist () 1566 (defun ada-format-paramlist ()
1395 1588
1396 ;; find end of parameter-list 1589 ;; find end of parameter-list
1397 (forward-sexp 1) 1590 (forward-sexp 1)
1398 (set 'delend (point)) 1591 (set 'delend (point))
1399 (delete-char -1) 1592 (delete-char -1)
1593 (insert "\n")
1400 1594
1401 ;; find end of last parameter-declaration 1595 ;; find end of last parameter-declaration
1402 (forward-comment -1000) 1596 (forward-comment -1000)
1403 (set 'end (point)) 1597 (set 'end (point))
1404 1598
1405 ;; build a list of all elements of the parameter-list 1599 ;; build a list of all elements of the parameter-list
1406 (set 'paramlist (ada-scan-paramlist (1+ begin) end)) 1600 (set 'paramlist (ada-scan-paramlist (1+ begin) end))
1407 1601
1408 ;; delete the original parameter-list 1602 ;; delete the original parameter-list
1409 (delete-region begin (1- delend)) 1603 (delete-region begin delend)
1410 1604
1411 ;; insert the new parameter-list 1605 ;; insert the new parameter-list
1412 (goto-char begin) 1606 (goto-char begin)
1413 (ada-insert-paramlist paramlist)) 1607 (ada-insert-paramlist paramlist))
1414 1608
1484 (while (looking-at "\\<\\(in\\|out\\|access\\)\\>") 1678 (while (looking-at "\\<\\(in\\|out\\|access\\)\\>")
1485 (forward-word 1) 1679 (forward-word 1)
1486 (ada-goto-next-non-ws)) 1680 (ada-goto-next-non-ws))
1487 1681
1488 ;; read type of parameter 1682 ;; read type of parameter
1489 (looking-at "\\<\\(\\sw\\|[_.']\\)+\\>") 1683 ;; We accept spaces in the name, since some software like Rose
1684 ;; generates something like: "A : B 'Class"
1685 (looking-at "\\<\\(\\sw\\|[_.' \t]\\)+\\>")
1490 (set 'param 1686 (set 'param
1491 (append param 1687 (append param
1492 (list (match-string 0)))) 1688 (list (match-string 0))))
1493 1689
1494 ;; read default-expression, if there is one 1690 ;; read default-expression, if there is one
1515 (defun ada-insert-paramlist (paramlist) 1711 (defun ada-insert-paramlist (paramlist)
1516 "Inserts a formatted PARAMLIST in the buffer." 1712 "Inserts a formatted PARAMLIST in the buffer."
1517 (let ((i (length paramlist)) 1713 (let ((i (length paramlist))
1518 (parlen 0) 1714 (parlen 0)
1519 (typlen 0) 1715 (typlen 0)
1520 (temp 0)
1521 (inp nil) 1716 (inp nil)
1522 (outp nil) 1717 (outp nil)
1523 (accessp nil) 1718 (accessp nil)
1524 (column nil) 1719 (column nil)
1525 (firstcol nil)) 1720 (firstcol nil))
1626 ;; put it in a new line and indent it 1821 ;; put it in a new line and indent it
1627 (unless (looking-at "[ \t]*\\(;\\|\n\\|is\\|return\\)") 1822 (unless (looking-at "[ \t]*\\(;\\|\n\\|is\\|return\\)")
1628 (ada-indent-newline-indent)) 1823 (ada-indent-newline-indent))
1629 )) 1824 ))
1630 1825
1631
1632 ;;;----------------------------;;;
1633 ;;; Move To Matching Start/End ;;;
1634 ;;;----------------------------;;;
1635 (defun ada-move-to-start ()
1636 "Moves point to the matching start of the current Ada structure."
1637 (interactive)
1638 (let ((pos (point))
1639 (previous-syntax-table (syntax-table)))
1640 (unwind-protect
1641 (progn
1642 (set-syntax-table ada-mode-symbol-syntax-table)
1643
1644 (message "searching for block start ...")
1645 (save-excursion
1646 ;;
1647 ;; do nothing if in string or comment or not on 'end ...;'
1648 ;; or if an error occurs during processing
1649 ;;
1650 (or
1651 (ada-in-string-or-comment-p)
1652 (and (progn
1653 (or (looking-at "[ \t]*\\<end\\>")
1654 (backward-word 1))
1655 (or (looking-at "[ \t]*\\<end\\>")
1656 (backward-word 1))
1657 (or (looking-at "[ \t]*\\<end\\>")
1658 (error "not on end ...;")))
1659 (ada-goto-matching-start 1)
1660 (set 'pos (point))
1661
1662 ;;
1663 ;; on 'begin' => go on, according to user option
1664 ;;
1665 ada-move-to-declaration
1666 (looking-at "\\<begin\\>")
1667 (ada-goto-matching-decl-start)
1668 (set 'pos (point))))
1669
1670 ) ; end of save-excursion
1671
1672 ;; now really move to the found position
1673 (goto-char pos)
1674 (message "searching for block start ... done"))
1675
1676 ;;
1677 ;; restore syntax-table
1678 ;;
1679 (set-syntax-table previous-syntax-table))))
1680
1681 (defun ada-move-to-end ()
1682 "Moves point to the matching end of the current block around point.
1683 Moves to 'begin' if in a declarative part."
1684 (interactive)
1685 (let ((pos (point))
1686 (previous-syntax-table (syntax-table)))
1687 (unwind-protect
1688 (progn
1689 (set-syntax-table ada-mode-symbol-syntax-table)
1690
1691 (message "searching for block end ...")
1692 (save-excursion
1693
1694 (forward-char 1)
1695 (cond
1696 ;; directly on 'begin'
1697 ((save-excursion
1698 (ada-goto-previous-word)
1699 (looking-at "\\<begin\\>"))
1700 (ada-goto-matching-end 1))
1701 ;; on first line of defun declaration
1702 ((save-excursion
1703 (and (ada-goto-stmt-start)
1704 (looking-at "\\<function\\>\\|\\<procedure\\>" )))
1705 (ada-search-ignore-string-comment "begin" nil nil nil
1706 'word-search-forward))
1707 ;; on first line of task declaration
1708 ((save-excursion
1709 (and (ada-goto-stmt-start)
1710 (looking-at "\\<task\\>" )
1711 (forward-word 1)
1712 (ada-goto-next-non-ws)
1713 (looking-at "\\<body\\>")))
1714 (ada-search-ignore-string-comment "begin" nil nil nil
1715 'word-search-forward))
1716 ;; accept block start
1717 ((save-excursion
1718 (and (ada-goto-stmt-start)
1719 (looking-at "\\<accept\\>" )))
1720 (ada-goto-matching-end 0))
1721 ;; package start
1722 ((save-excursion
1723 (and (ada-goto-matching-decl-start t)
1724 (looking-at "\\<package\\>")))
1725 (ada-goto-matching-end 1))
1726 ;; inside a 'begin' ... 'end' block
1727 ((save-excursion
1728 (ada-goto-matching-decl-start t))
1729 (ada-search-ignore-string-comment "begin" nil nil nil
1730 'word-search-forward))
1731 ;; (hopefully ;-) everything else
1732 (t
1733 (ada-goto-matching-end 1)))
1734 (set 'pos (point))
1735 )
1736
1737 ;; now really move to the found position
1738 (goto-char pos)
1739 (message "searching for block end ... done"))
1740
1741 ;; restore syntax-table
1742 (set-syntax-table previous-syntax-table))))
1743 1826
1744 1827
1745 ;;;---------------------------------------------------------------- 1828 ;;;----------------------------------------------------------------
1746 ;; Indentation Engine 1829 ;; Indentation Engine
1747 ;; All indentations are indicated as a two-element string: 1830 ;; All indentations are indicated as a two-element string:
1764 ;; calculation that were done 1847 ;; calculation that were done
1765 ;; - `ada-indent-current': Re-indent the current line 1848 ;; - `ada-indent-current': Re-indent the current line
1766 ;; - `ada-get-current-indent': Calculate the indentation for the current line, 1849 ;; - `ada-get-current-indent': Calculate the indentation for the current line,
1767 ;; based on the context (see above). 1850 ;; based on the context (see above).
1768 ;; - `ada-get-indent-*': Calculate the indentation in a specific context. 1851 ;; - `ada-get-indent-*': Calculate the indentation in a specific context.
1769 ;; For efficiency, these functions do not check the correct context. 1852 ;; For efficiency, these functions do not check they are in the correct
1853 ;; context.
1770 ;;;---------------------------------------------------------------- 1854 ;;;----------------------------------------------------------------
1771 1855
1772 (defun ada-indent-region (beg end) 1856 (defun ada-indent-region (beg end)
1773 "Indent the region between BEG and END." 1857 "Indent the region between BEG end END."
1774 (interactive "*r") 1858 (interactive "*r")
1775 (goto-char beg) 1859 (goto-char beg)
1776 (let ((block-done 0) 1860 (let ((block-done 0)
1777 (lines-remaining (count-lines beg end)) 1861 (lines-remaining (count-lines beg end))
1778 (msg (format "indenting %4d lines %%4d lines remaining ..." 1862 (msg (format "%%4d out of %4d lines remaining ..."
1779 (count-lines beg end))) 1863 (count-lines beg end)))
1780 (endmark (copy-marker end))) 1864 (endmark (copy-marker end)))
1781 ;; catch errors while indenting 1865 ;; catch errors while indenting
1782 (while (< (point) endmark) 1866 (while (< (point) endmark)
1783 (if (> block-done 39) 1867 (if (> block-done 39)
1784 (progn (message msg lines-remaining) 1868 (progn
1785 (set 'block-done 0))) 1869 (setq lines-remaining (- lines-remaining block-done)
1786 (if (looking-at "^$") nil 1870 block-done 0)
1871 (message msg lines-remaining)))
1872 (if (= (char-after) ?\n) nil
1787 (ada-indent-current)) 1873 (ada-indent-current))
1788 (forward-line 1) 1874 (forward-line 1)
1789 (set 'block-done (1+ block-done)) 1875 (setq block-done (1+ block-done)))
1790 (set 'lines-remaining (1- lines-remaining)))
1791 (message "indenting ... done"))) 1876 (message "indenting ... done")))
1792 1877
1793 (defun ada-indent-newline-indent () 1878 (defun ada-indent-newline-indent ()
1794 "Indents the current line, inserts a newline and then indents the new line." 1879 "Indents the current line, inserts a newline and then indents the new line."
1795 (interactive "*") 1880 (interactive "*")
1812 1897
1813 (let ((cur-indent (ada-indent-current))) 1898 (let ((cur-indent (ada-indent-current)))
1814 1899
1815 (message nil) 1900 (message nil)
1816 (if (equal (cdr cur-indent) '(0)) 1901 (if (equal (cdr cur-indent) '(0))
1817 (message "same indentation") 1902 (message "same indentation")
1818 (message (mapconcat (lambda(x) 1903 (message (mapconcat (lambda(x)
1819 (cond 1904 (cond
1820 ((symbolp x) 1905 ((symbolp x)
1821 (symbol-name x)) 1906 (symbol-name x))
1822 ((numberp x) 1907 ((numberp x)
1823 (number-to-string x)) 1908 (number-to-string x))
1824 ((listp x) 1909 ((listp x)
1825 (concat "- " (symbol-name (cadr x)))) 1910 (concat "- " (symbol-name (cadr x))))
1826 )) 1911 ))
1827 (cdr cur-indent) 1912 (cdr cur-indent)
1828 " + "))) 1913 " + ")))
1829 (save-excursion 1914 (save-excursion
1830 (goto-char (car cur-indent)) 1915 (goto-char (car cur-indent))
1831 (sit-for 1)))) 1916 (sit-for 1))))
1917
1918 (defun ada-batch-reformat ()
1919 "Re-indent and re-case all the files found on the command line.
1920 This function should be used from the Unix/Windows command line, with a
1921 command like:
1922 emacs -batch -l ada-mode -f ada-batch-reformat file1 file2 ..."
1923
1924 (while command-line-args-left
1925 (let ((source (car command-line-args-left)))
1926 (message (concat "formating " source))
1927 (find-file source)
1928 (ada-indent-region (point-min) (point-max))
1929 (ada-adjust-case-buffer)
1930 (write-file source))
1931 (set 'command-line-args-left (cdr command-line-args-left)))
1932 (message "Done")
1933 (kill-emacs 0))
1934
1935 (defsubst ada-goto-previous-word ()
1936 "Moves point to the beginning of the previous word of Ada code.
1937 Returns the new position of point or nil if not found."
1938 (ada-goto-next-word t))
1832 1939
1833 (defun ada-indent-current () 1940 (defun ada-indent-current ()
1834 "Indent current line as Ada code. 1941 "Indent current line as Ada code.
1835 Returns the calculation that was done, including the reference point and the 1942 Returns the calculation that was done, including the reference point and the
1836 offset." 1943 offset."
1837 (interactive) 1944 (interactive)
1838 (let ((previous-syntax-table (syntax-table)) 1945 (let ((previous-syntax-table (syntax-table))
1839 (orgpoint (point-marker)) 1946 (orgpoint (point-marker))
1840 cur-indent tmp-indent 1947 cur-indent tmp-indent
1841 prev-indent) 1948 prev-indent)
1842
1843 (set-syntax-table ada-mode-symbol-syntax-table)
1844
1845 ;; This need to be done here so that the advice is not always activated
1846 ;; (this might interact badly with other modes)
1847 (if ada-xemacs
1848 (ad-activate 'parse-partial-sexp t))
1849 1949
1850 (unwind-protect 1950 (unwind-protect
1851 (progn 1951 (progn
1852 1952 (set-syntax-table ada-mode-symbol-syntax-table)
1853 (save-excursion 1953
1854 (set 'cur-indent 1954 ;; This need to be done here so that the advice is not always
1855 ;; Not First line in the buffer ? 1955 ;; activated (this might interact badly with other modes)
1856 1956 (if ada-xemacs
1857 (if (save-excursion (zerop (forward-line -1))) 1957 (ad-activate 'parse-partial-sexp t))
1858 (progn 1958
1859 (back-to-indentation) 1959 (save-excursion
1860 (ada-get-current-indent)) 1960 (set 'cur-indent
1861 1961
1862 ;; first line in the buffer 1962 ;; Not First line in the buffer ?
1863 (list (point-min) 0)))) 1963 (if (save-excursion (zerop (forward-line -1)))
1964 (progn
1965 (back-to-indentation)
1966 (ada-get-current-indent))
1967
1968 ;; first line in the buffer
1969 (list (point-min) 0))))
1970
1971 ;; Evaluate the list to get the column to indent to
1972 ;; prev-indent contains the column to indent to
1973 (if cur-indent
1974 (setq prev-indent (save-excursion (goto-char (car cur-indent))
1975 (current-column))
1976 tmp-indent (cdr cur-indent))
1977 (setq prev-indent 0 tmp-indent '()))
1864 1978
1865 ;; Evaluate the list to get the column to indent to 1979 (while (not (null tmp-indent))
1866 ;; prev-indent contains the column to indent to 1980 (cond
1867 (set 'prev-indent (save-excursion (goto-char (car cur-indent)) 1981 ((numberp (car tmp-indent))
1868 (current-column))) 1982 (set 'prev-indent (+ prev-indent (car tmp-indent))))
1869 (set 'tmp-indent (cdr cur-indent)) 1983 (t
1870 (while (not (null tmp-indent)) 1984 (set 'prev-indent (+ prev-indent (eval (car tmp-indent)))))
1871 (cond 1985 )
1872 ((numberp (car tmp-indent)) 1986 (set 'tmp-indent (cdr tmp-indent)))
1873 (set 'prev-indent (+ prev-indent (car tmp-indent)))) 1987
1874 (t 1988 ;; only re-indent if indentation is different then the current
1875 (set 'prev-indent (+ prev-indent (eval (car tmp-indent))))) 1989 (if (= (save-excursion (back-to-indentation) (current-column)) prev-indent)
1876 ) 1990 nil
1877 (set 'tmp-indent (cdr tmp-indent))) 1991 (beginning-of-line)
1878 1992 (delete-horizontal-space)
1879 ;; only re-indent if indentation is different then the current 1993 (indent-to prev-indent))
1880 (if (= (save-excursion (back-to-indentation) (current-column)) prev-indent) 1994 ;;
1881 nil 1995 ;; restore position of point
1882 (beginning-of-line) 1996 ;;
1883 (delete-horizontal-space) 1997 (goto-char orgpoint)
1884 (indent-to prev-indent)) 1998 (if (< (current-column) (current-indentation))
1885 ;; 1999 (back-to-indentation)))
1886 ;; restore position of point 2000
1887 ;; 2001 ;; restore syntax-table
1888 (goto-char orgpoint) 2002 (set-syntax-table previous-syntax-table)
1889 (if (< (current-column) (current-indentation)) 2003 (if ada-xemacs
1890 (back-to-indentation)))) 2004 (ad-deactivate 'parse-partial-sexp))
1891 2005 )
1892 ;; restore syntax-table 2006
1893 (if ada-xemacs
1894 (ad-deactivate 'parse-partial-sexp))
1895 (set-syntax-table previous-syntax-table)
1896 cur-indent 2007 cur-indent
1897 )) 2008 ))
1898 2009
1899 (defun ada-get-current-indent () 2010 (defun ada-get-current-indent ()
1900 "Returns the indentation to use for the current line." 2011 "Return the indentation to use for the current line."
1901 (let (column 2012 (let (column
1902 pos 2013 pos
1903 match-cons 2014 match-cons
1904 (orgpoint (save-excursion 2015 result
1905 (beginning-of-line) 2016 (orgpoint (save-excursion
1906 (forward-comment -10000) 2017 (beginning-of-line)
1907 (forward-line 1) 2018 (forward-comment -10000)
1908 (point)))) 2019 (forward-line 1)
2020 (point))))
2021
2022 (set 'result
1909 (cond 2023 (cond
1910 ;; 2024
1911 ;; preprocessor line (gnatprep) 2025 ;;-----------------------------
1912 ;;
1913 ((and (equal ada-which-compiler 'gnat)
1914 (looking-at "#[ \t]*\\(if\\|else\\|elsif\\|end[ \t]*if\\)"))
1915 (list (save-excursion (beginning-of-line) (point)) 0))
1916
1917 ;;
1918 ;; in open parenthesis, but not in parameter-list 2026 ;; in open parenthesis, but not in parameter-list
1919 ;; 2027 ;;-----------------------------
1920 ((and 2028
1921 ada-indent-to-open-paren 2029 ((and ada-indent-to-open-paren
1922 (not (ada-in-paramlist-p)) 2030 (not (ada-in-paramlist-p))
1923 (set 'column (ada-in-open-paren-p))) 2031 (set 'column (ada-in-open-paren-p)))
2032
1924 ;; check if we have something like this (Table_Component_Type => 2033 ;; check if we have something like this (Table_Component_Type =>
1925 ;; Source_File_Record) 2034 ;; Source_File_Record)
1926 (save-excursion 2035 (save-excursion
1927 (if (and (skip-chars-backward " \t") 2036 (if (and (skip-chars-backward " \t")
1928 (= (char-before) ?\n) 2037 (= (char-before) ?\n)
1929 (not (forward-comment -10000)) 2038 (not (forward-comment -10000))
1930 (= (char-before) ?>)) 2039 (= (char-before) ?>))
1931 (list column 'ada-broken-indent);; ??? Could use a different variable 2040 ;; ??? Could use a different variable
1932 (list column 0)))) 2041 (list column 'ada-broken-indent)
1933 2042 (list column 0))))
1934 ;; 2043
1935 ;; end 2044 ;;---------------------------
1936 ;; 2045 ;; at end of buffer
1937 ((looking-at "\\<end\\>") 2046 ;;---------------------------
1938 (let ((label 0)) 2047
1939 (save-excursion 2048 ((not (char-after))
1940 (ada-goto-matching-start 1) 2049 (ada-indent-on-previous-lines nil orgpoint orgpoint))
1941 2050
1942 ;; 2051 ;;---------------------------
1943 ;; found 'loop' => skip back to 'while' or 'for' 2052 ;; starting with e
1944 ;; if 'loop' is not on a separate line 2053 ;;---------------------------
1945 ;; 2054
1946 (if (save-excursion 2055 ((= (char-after) ?e)
1947 (beginning-of-line) 2056 (cond
1948 (looking-at ".+\\<loop\\>")) 2057
1949 (if (save-excursion 2058 ;; ------- end ------
1950 (and 2059
1951 (set 'match-cons 2060 ((looking-at "end\\>")
1952 (ada-search-ignore-string-comment ada-loop-start-re t)) 2061 (let ((label 0)
1953 (not (looking-at "\\<loop\\>")))) 2062 limit)
1954 (progn 2063 (save-excursion
1955 (goto-char (car match-cons)) 2064 (ada-goto-matching-start 1)
1956 (save-excursion 2065
1957 (beginning-of-line) 2066 ;;
1958 (if (looking-at ada-named-block-re) 2067 ;; found 'loop' => skip back to 'while' or 'for'
1959 (set 'label (- ada-label-indent))))))) 2068 ;; if 'loop' is not on a separate line
1960 2069 ;; Stop the search for 'while' and 'for' when a ';' is encountered.
1961 (list (+ (save-excursion (back-to-indentation) (point)) label) 0)))) 2070 ;;
1962 ;; 2071 (if (save-excursion
1963 ;; exception 2072 (beginning-of-line)
1964 ;; 2073 (looking-at ".+\\<loop\\>"))
1965 ((looking-at "\\<exception\\>") 2074 (progn
2075 (save-excursion
2076 (set 'limit (car (ada-search-ignore-string-comment ";" t))))
2077 (if (save-excursion
2078 (and
2079 (set 'match-cons
2080 (ada-search-ignore-string-comment ada-loop-start-re t limit))
2081 (not (looking-at "\\<loop\\>"))))
2082 (progn
2083 (goto-char (car match-cons))
2084 (save-excursion
2085 (beginning-of-line)
2086 (if (looking-at ada-named-block-re)
2087 (set 'label (- ada-label-indent))))))))
2088
2089 (list (+ (save-excursion (back-to-indentation) (point)) label) 0))))
2090
2091 ;; ------ exception ----
2092
2093 ((looking-at "exception\\>")
2094 (save-excursion
2095 (ada-goto-matching-start 1)
2096 (list (save-excursion (back-to-indentation) (point)) 0)))
2097
2098 ;; else
2099
2100 ((looking-at "else\\>")
2101 (if (save-excursion (ada-goto-previous-word)
2102 (looking-at "\\<or\\>"))
2103 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2104 (save-excursion
2105 (ada-goto-matching-start 1 nil t)
2106 (list (progn (back-to-indentation) (point)) 0))))
2107
2108 ;; elsif
2109
2110 ((looking-at "elsif\\>")
2111 (save-excursion
2112 (ada-goto-matching-start 1 nil t)
2113 (list (progn (back-to-indentation) (point)) 0)))
2114
2115 ))
2116
2117 ;;---------------------------
2118 ;; starting with w (when)
2119 ;;---------------------------
2120
2121 ((and (= (char-after) ?w)
2122 (looking-at "when\\>"))
1966 (save-excursion 2123 (save-excursion
1967 (ada-goto-matching-start 1) 2124 (ada-goto-matching-start 1)
1968 (list (save-excursion (back-to-indentation) (point)) 0))) 2125 (list (save-excursion (back-to-indentation) (point))
1969 ;; 2126 'ada-when-indent)))
1970 ;; when 2127
1971 ;; 2128 ;;---------------------------
1972 ((looking-at "\\<when\\>") 2129 ;; starting with t (then)
1973 (save-excursion 2130 ;;---------------------------
1974 (ada-goto-matching-start 1) 2131
1975 (list (save-excursion (back-to-indentation) (point)) 'ada-when-indent))) 2132 ((and (= (char-after) ?t)
1976 ;; 2133 (looking-at "then\\>"))
1977 ;; else 2134 (if (save-excursion (ada-goto-previous-word)
1978 ;; 2135 (looking-at "and\\>"))
1979 ((looking-at "\\<else\\>")
1980 (if (save-excursion (ada-goto-previous-word)
1981 (looking-at "\\<or\\>"))
1982 (ada-indent-on-previous-lines nil orgpoint orgpoint) 2136 (ada-indent-on-previous-lines nil orgpoint orgpoint)
1983 (save-excursion 2137 (save-excursion
1984 (ada-goto-matching-start 1 nil t) 2138 ;; Select has been added for the statement: "select ... then abort"
1985 (list (progn (back-to-indentation) (point)) 0)))) 2139 (ada-search-ignore-string-comment
1986 ;; 2140 "\\<\\(elsif\\|if\\|select\\)\\>" t nil)
1987 ;; elsif 2141 (list (progn (back-to-indentation) (point))
1988 ;; 2142 'ada-stmt-end-indent))))
1989 ((looking-at "\\<elsif\\>") 2143
1990 (save-excursion 2144 ;;---------------------------
1991 (ada-goto-matching-start 1 nil t) 2145 ;; starting with l (loop)
1992 (list (progn (back-to-indentation) (point)) 0))) 2146 ;;---------------------------
1993 ;; 2147
1994 ;; then 2148 ((and (= (char-after) ?l)
1995 ;; 2149 (looking-at "loop\\>"))
1996 ((looking-at "\\<then\\>")
1997 (if (save-excursion (ada-goto-previous-word)
1998 (looking-at "\\<and\\>"))
1999 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2000 (save-excursion
2001 ;; Select has been added for the statement: "select ... then abort"
2002 (ada-search-ignore-string-comment "\\<\\(elsif\\|if\\|select\\)\\>" t nil)
2003 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))
2004 ;;
2005 ;; loop
2006 ;;
2007 ((looking-at "\\<loop\\>")
2008 (set 'pos (point)) 2150 (set 'pos (point))
2009 (save-excursion 2151 (save-excursion
2010 (goto-char (match-end 0)) 2152 (goto-char (match-end 0))
2011 (ada-goto-stmt-start) 2153 (ada-goto-stmt-start)
2012 (if (looking-at "\\<\\(loop\\|if\\)\\>") 2154 (if (looking-at "\\<\\(loop\\|if\\)\\>")
2013 (ada-indent-on-previous-lines nil orgpoint orgpoint) 2155 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2014 (unless (looking-at ada-loop-start-re) 2156 (unless (looking-at ada-loop-start-re)
2015 (ada-search-ignore-string-comment ada-loop-start-re 2157 (ada-search-ignore-string-comment ada-loop-start-re
2016 nil pos)) 2158 nil pos))
2017 (if (looking-at "\\<loop\\>") 2159 (if (looking-at "\\<loop\\>")
2018 (ada-indent-on-previous-lines nil orgpoint orgpoint) 2160 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2019 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))) 2161 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))))
2020 ;; 2162
2021 ;; begin 2163 ;;---------------------------
2022 ;; 2164 ;; starting with b (begin)
2023 ((looking-at "\\<begin\\>") 2165 ;;---------------------------
2166
2167 ((and (= (char-after) ?b)
2168 (looking-at "begin\\>"))
2024 (save-excursion 2169 (save-excursion
2025 (if (ada-goto-matching-decl-start t) 2170 (if (ada-goto-matching-decl-start t)
2026 (list (progn (back-to-indentation) (point)) 0) 2171 (list (progn (back-to-indentation) (point)) 0)
2027 (ada-indent-on-previous-lines nil orgpoint orgpoint)))) 2172 (ada-indent-on-previous-lines nil orgpoint orgpoint))))
2028 ;; 2173
2029 ;; is 2174 ;;---------------------------
2030 ;; 2175 ;; starting with i (is)
2031 ((looking-at "\\<is\\>") 2176 ;;---------------------------
2177
2178 ((and (= (char-after) ?i)
2179 (looking-at "is\\>"))
2180
2032 (if (and ada-indent-is-separate 2181 (if (and ada-indent-is-separate
2033 (save-excursion 2182 (save-excursion
2034 (goto-char (match-end 0)) 2183 (goto-char (match-end 0))
2035 (ada-goto-next-non-ws (save-excursion (end-of-line) 2184 (ada-goto-next-non-ws (save-excursion (end-of-line)
2036 (point))) 2185 (point)))
2037 (looking-at "\\<abstract\\>\\|\\<separate\\>"))) 2186 (looking-at "\\<abstract\\>\\|\\<separate\\>")))
2038 (save-excursion 2187 (save-excursion
2039 (ada-goto-stmt-start) 2188 (ada-goto-stmt-start)
2040 (list (progn (back-to-indentation) (point)) 'ada-indent)) 2189 (list (progn (back-to-indentation) (point)) 'ada-indent))
2041 (save-excursion 2190 (save-excursion
2042 (ada-goto-stmt-start) 2191 (ada-goto-stmt-start)
2043 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))) 2192 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))))
2044 ;; 2193
2045 ;; record 2194 ;;---------------------------
2046 ;; 2195 ;; starting with r (record, return, renames)
2047 ((looking-at "\\<record\\>") 2196 ;;---------------------------
2048 (save-excursion 2197
2049 (ada-search-ignore-string-comment 2198 ((= (char-after) ?r)
2050 "\\<\\(type\\|use\\)\\>" t nil) 2199
2051 (if (looking-at "\\<use\\>") 2200 (cond
2052 (ada-search-ignore-string-comment "for" t nil nil 'word-search-backward)) 2201
2053 (list (progn (back-to-indentation) (point)) 'ada-indent-record-rel-type))) 2202 ;; ----- record ------
2054 ;; 2203
2055 ;; 'or' as statement-start 2204 ((looking-at "record\\>")
2056 ;; 'private' as statement-start 2205 (save-excursion
2057 ;; 2206 (ada-search-ignore-string-comment
2058 ((or (ada-looking-at-semi-or) 2207 "\\<\\(type\\|use\\)\\>" t nil)
2059 (ada-looking-at-semi-private)) 2208 (if (looking-at "\\<use\\>")
2209 (ada-search-ignore-string-comment "for" t nil nil 'word-search-backward))
2210 (list (progn (back-to-indentation) (point)) 'ada-indent-record-rel-type)))
2211
2212 ;; ----- return or renames ------
2213
2214 ((looking-at "re\\(turn\\|names\\)\\>")
2215 (save-excursion
2216 (let ((var 'ada-indent-return))
2217 ;; If looking at a renames, skip the 'return' statement too
2218 (if (looking-at "renames")
2219 (let (pos)
2220 (save-excursion
2221 (set 'pos (ada-search-ignore-string-comment ";\\|return\\>" t)))
2222 (if (and pos
2223 (= (char-after (car pos)) ?r))
2224 (goto-char (car pos)))
2225 (set 'var 'ada-indent-renames)))
2226
2227 (forward-comment -1000)
2228 (if (= (char-before) ?\))
2229 (forward-sexp -1)
2230 (forward-word -1))
2231
2232 ;; If there is a parameter list, and we have a function declaration
2233 ;; or a access to subprogram declaration
2234 (let ((num-back 1))
2235 (if (and (= (char-after) ?\()
2236 (save-excursion
2237 (or (progn
2238 (backward-word 1)
2239 (looking-at "function\\>"))
2240 (progn
2241 (backward-word 1)
2242 (set 'num-back 2)
2243 (looking-at "function\\>")))))
2244
2245 ;; The indentation depends of the value of ada-indent-return
2246 (if (<= (eval var) 0)
2247 (list (point) (list '- var))
2248 (list (progn (backward-word num-back) (point))
2249 var))
2250
2251 ;; Else there is no parameter list, but we have a function
2252 ;; Only do something special if the user want to indent
2253 ;; relative to the "function" keyword
2254 (if (and (> (eval var) 0)
2255 (save-excursion (forward-word -1)
2256 (looking-at "function\\>")))
2257 (list (progn (forward-word -1) (point)) var)
2258
2259 ;; Else...
2260 (ada-indent-on-previous-lines nil orgpoint orgpoint)))))))
2261 ))
2262
2263 ;;--------------------------------
2264 ;; starting with 'o' or 'p'
2265 ;; 'or' as statement-start
2266 ;; 'private' as statement-start
2267 ;;--------------------------------
2268
2269 ((and (or (= (char-after) ?o)
2270 (= (char-after) ?p))
2271 (or (ada-looking-at-semi-or)
2272 (ada-looking-at-semi-private)))
2060 (save-excursion 2273 (save-excursion
2061 (ada-goto-matching-start 1) 2274 (ada-goto-matching-start 1)
2062 (list (progn (back-to-indentation) (point)) 0))) 2275 (list (progn (back-to-indentation) (point)) 0)))
2063 ;; 2276
2064 ;; new/abstract/separate 2277 ;;--------------------------------
2065 ;; 2278 ;; starting with 'd' (do)
2066 ((looking-at "\\<\\(new\\|abstract\\|separate\\)\\>") 2279 ;;--------------------------------
2067 (ada-indent-on-previous-lines nil orgpoint orgpoint)) 2280
2068 ;; 2281 ((and (= (char-after) ?d)
2069 ;; return 2282 (looking-at "do\\>"))
2070 ;;
2071 ((looking-at "\\<return\\>")
2072 (save-excursion
2073 (forward-comment -1000)
2074 (if (= (char-before) ?\))
2075 (forward-sexp -1)
2076 (forward-word -1))
2077
2078 ;; If there is a parameter list, and we have a function declaration
2079 (if (and (= (char-after) ?\()
2080 (save-excursion
2081 (backward-sexp 2)
2082 (looking-at "\\<function\\>")))
2083
2084 ;; The indentation depends of the value of ada-indent-return
2085 (if (<= ada-indent-return 0)
2086 (list (point) (- ada-indent-return))
2087 (list (progn (backward-sexp 2) (point)) ada-indent-return))
2088
2089 ;; Else there is no parameter list, but we have a function
2090 ;; Only do something special if the user want to indent relative
2091 ;; to the "function" keyword
2092 (if (and (> ada-indent-return 0)
2093 (save-excursion (forward-word -1)
2094 (looking-at "\\<function\\>")))
2095 (list (progn (forward-word -1) (point)) ada-indent-return)
2096
2097 ;; Else...
2098 (ada-indent-on-previous-lines nil orgpoint orgpoint)))))
2099 ;;
2100 ;; do
2101 ;;
2102 ((looking-at "\\<do\\>")
2103 (save-excursion 2283 (save-excursion
2104 (ada-goto-stmt-start) 2284 (ada-goto-stmt-start)
2105 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent))) 2285 (list (progn (back-to-indentation) (point)) 'ada-stmt-end-indent)))
2106 ;; 2286
2107 ;; package/function/procedure 2287 ;;--------------------------------
2108 ;; 2288 ;; starting with '-' (comment)
2109 ((and (looking-at "\\<\\(package\\|function\\|procedure\\)\\>") 2289 ;;--------------------------------
2110 (save-excursion 2290
2111 (forward-char 1) 2291 ((= (char-after) ?-)
2112 (ada-goto-stmt-start) 2292 (if ada-indent-comment-as-code
2113 (looking-at "\\<\\(package\\|function\\|procedure\\)\\>"))) 2293
2114 (save-excursion 2294 ;; Indent comments on previous line comments if required
2115 ;; look for 'generic' 2295 ;; We must use a search-forward (even if the code is more complex),
2116 (if (and (ada-goto-matching-decl-start t) 2296 ;; since we want to find the beginning of the comment.
2117 (looking-at "generic")) 2297 (let (pos)
2118 (list (progn (back-to-indentation) (point)) 0) 2298
2119 (ada-indent-on-previous-lines nil orgpoint orgpoint)))) 2299 (if (and ada-indent-align-comments
2120 ;; 2300 (save-excursion
2121 ;; label 2301 (forward-line -1)
2122 ;; 2302 (beginning-of-line)
2123 ((looking-at "\\<\\(\\sw\\|_\\)+[ \t\n]*:[^=]") 2303 (while (and (not pos)
2124 (if (ada-in-decl-p) 2304 (search-forward "--"
2125 (ada-indent-on-previous-lines nil orgpoint orgpoint) 2305 (save-excursion
2126 (set 'pos (ada-indent-on-previous-lines nil orgpoint orgpoint)) 2306 (end-of-line) (point))
2127 (list (car pos) 2307 t))
2128 (cadr pos) 2308 (unless (ada-in-string-p)
2129 'ada-label-indent))) 2309 (set 'pos (point))))
2130 ;; 2310 pos))
2131 ;; identifier and other noindent-statements 2311 (list (- pos 2) 0)
2132 ;; 2312
2133 ((looking-at "\\<\\(\\sw\\|_\\)+[ \t\n]*") 2313 ;; Else always on previous line
2134 (ada-indent-on-previous-lines nil orgpoint orgpoint)) 2314 (ada-indent-on-previous-lines nil orgpoint orgpoint)))
2135 ;; 2315
2136 ;; beginning of a parameter list 2316 ;; Else same indentation as the previous line
2137 ;; 2317 (list (save-excursion (back-to-indentation) (point)) 0)))
2138 ((and (not (eobp)) (= (char-after) ?\()) 2318
2139 (ada-indent-on-previous-lines nil orgpoint orgpoint)) 2319 ;;--------------------------------
2140 ;; 2320 ;; starting with '#' (preprocessor line)
2141 ;; end of a parameter list 2321 ;;--------------------------------
2142 ;; 2322
2323 ((and (= (char-after) ?#)
2324 (equal ada-which-compiler 'gnat)
2325 (looking-at "#[ \t]*\\(if\\|els\\(e\\|if\\)\\|end[ \t]*if\\)"))
2326 (list (save-excursion (beginning-of-line) (point)) 0))
2327
2328 ;;--------------------------------
2329 ;; starting with ')' (end of a parameter list)
2330 ;;--------------------------------
2331
2143 ((and (not (eobp)) (= (char-after) ?\))) 2332 ((and (not (eobp)) (= (char-after) ?\)))
2144 (save-excursion 2333 (save-excursion
2145 (forward-char 1) 2334 (forward-char 1)
2146 (backward-sexp 1) 2335 (backward-sexp 1)
2147 (list (point) 0))) 2336 (list (point) 0)))
2148 ;; 2337
2149 ;; comment 2338 ;;---------------------------------
2150 ;; 2339 ;; new/abstract/separate
2151 ((looking-at "--") 2340 ;;---------------------------------
2152 (if ada-indent-comment-as-code 2341
2153 ;; If previous line is a comment, indent likewise 2342 ((looking-at "\\(new\\|abstract\\|separate\\)\\>")
2154 (save-excursion 2343 (ada-indent-on-previous-lines nil orgpoint orgpoint))
2155 (forward-line -1) 2344
2156 (beginning-of-line) 2345 ;;---------------------------------
2157 (if (looking-at "[ \t]*--") 2346 ;; package/function/procedure
2158 (list (progn (back-to-indentation) (point)) 0) 2347 ;;---------------------------------
2159 (ada-indent-on-previous-lines nil orgpoint orgpoint))) 2348
2160 (list (save-excursion (back-to-indentation) (point)) 0))) 2349 ((and (or (= (char-after) ?p) (= (char-after) ?f))
2161 ;; 2350 (looking-at "\\<\\(package\\|function\\|procedure\\)\\>"))
2162 ;; unknown syntax 2351 (save-excursion
2163 ;; 2352 ;; Go up until we find either a generic section, or the end of the
2164 (t 2353 ;; previous subprogram/package
2165 (ada-indent-on-previous-lines nil orgpoint orgpoint))))) 2354 (let (found)
2355 (while (and (not found)
2356 (ada-search-ignore-string-comment
2357 "\\<\\(generic\\|end\\|begin\\|package\\|procedure\\|function\\)\\>" t))
2358
2359 ;; avoid "with procedure"... in generic parts
2360 (save-excursion
2361 (forward-word -1)
2362 (set 'found (not (looking-at "with"))))))
2363
2364 (if (looking-at "generic")
2365 (list (progn (back-to-indentation) (point)) 0)
2366 (ada-indent-on-previous-lines nil orgpoint orgpoint))))
2367
2368 ;;---------------------------------
2369 ;; label
2370 ;;---------------------------------
2371
2372 ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
2373 (if (ada-in-decl-p)
2374 (ada-indent-on-previous-lines nil orgpoint orgpoint)
2375 (append (ada-indent-on-previous-lines nil orgpoint orgpoint)
2376 '(ada-label-indent))))
2377
2378 ))
2379
2380 ;;---------------------------------
2381 ;; Other syntaxes
2382 ;;---------------------------------
2383 (or result (ada-indent-on-previous-lines nil orgpoint orgpoint))))
2166 2384
2167 (defun ada-indent-on-previous-lines (&optional nomove orgpoint initial-pos) 2385 (defun ada-indent-on-previous-lines (&optional nomove orgpoint initial-pos)
2168 "Calculate the indentation for the new line after ORGPOINT. 2386 "Calculate the indentation for the new line after ORGPOINT.
2169 The result list is based on the previous lines in the buffer. 2387 The result list is based on the previous lines in the buffer.
2170 If NOMOVE is nil, moves point to the beginning of the current statement. 2388 If NOMOVE is nil, moves point to the beginning of the current statement.
2171 if INITIAL-POS is non-nil, moves point to INITIAL-POS before calculation." 2389 if INITIAL-POS is non-nil, moves point to INITIAL-POS before calculation."
2172 (if initial-pos 2390 (if initial-pos
2173 (goto-char initial-pos)) 2391 (goto-char initial-pos))
2174 (let ((oldpoint (point)) 2392 (let ((oldpoint (point)))
2175 result) 2393
2176 ;;
2177 ;; Is inside a parameter-list ? 2394 ;; Is inside a parameter-list ?
2178 ;;
2179 (if (ada-in-paramlist-p) 2395 (if (ada-in-paramlist-p)
2180 (set 'result (ada-get-indent-paramlist)) 2396 (ada-get-indent-paramlist)
2181 2397
2182 ;;
2183 ;; move to beginning of current statement 2398 ;; move to beginning of current statement
2184 ;;
2185 (unless nomove 2399 (unless nomove
2186 (ada-goto-stmt-start)) 2400 (ada-goto-stmt-start))
2187 2401
2188 (unless result 2402 ;; no beginning found => don't change indentation
2189 (progn 2403 (if (and (eq oldpoint (point))
2190 ;; 2404 (not nomove))
2191 ;; no beginning found => don't change indentation 2405 (ada-get-indent-nochange)
2192 ;; 2406
2193 (if (and (eq oldpoint (point)) 2407 (cond
2194 (not nomove)) 2408 ;;
2195 (set 'result (ada-get-indent-nochange)) 2409 ((and
2196 2410 ada-indent-to-open-paren
2197 (cond 2411 (ada-in-open-paren-p))
2198 ;; 2412 (ada-get-indent-open-paren))
2199 ((and 2413 ;;
2200 ada-indent-to-open-paren 2414 ((looking-at "end\\>")
2201 (ada-in-open-paren-p)) 2415 (ada-get-indent-end orgpoint))
2202 (set 'result (ada-get-indent-open-paren))) 2416 ;;
2203 ;; 2417 ((looking-at ada-loop-start-re)
2204 ((looking-at "end\\>") 2418 (ada-get-indent-loop orgpoint))
2205 (set 'result (ada-get-indent-end orgpoint))) 2419 ;;
2206 ;; 2420 ((looking-at ada-subprog-start-re)
2207 ((looking-at ada-loop-start-re) 2421 (ada-get-indent-subprog orgpoint))
2208 (set 'result (ada-get-indent-loop orgpoint))) 2422 ;;
2209 ;; 2423 ((looking-at ada-block-start-re)
2210 ((looking-at ada-subprog-start-re) 2424 (ada-get-indent-block-start orgpoint))
2211 (set 'result (ada-get-indent-subprog orgpoint))) 2425 ;;
2212 ;; 2426 ((looking-at "\\(sub\\)?type\\>")
2213 ((looking-at ada-block-start-re) 2427 (ada-get-indent-type orgpoint))
2214 (set 'result (ada-get-indent-block-start orgpoint))) 2428 ;;
2215 ;; 2429 ;; "then" has to be included in the case of "select...then abort"
2216 ((looking-at "\\(sub\\)?type\\>") 2430 ;; statements, since (goto-stmt-start) at the beginning of
2217 (set 'result (ada-get-indent-type orgpoint))) 2431 ;; the current function would leave the cursor on that position
2218 ;; 2432 ((looking-at "\\(\\(els\\)?if\\>\\)\\|then abort\\\>")
2219 ((looking-at "\\(els\\)?if\\>") 2433 (ada-get-indent-if orgpoint))
2220 (set 'result (ada-get-indent-if orgpoint))) 2434 ;;
2221 ;; 2435 ((looking-at "case\\>")
2222 ((looking-at "case\\>") 2436 (ada-get-indent-case orgpoint))
2223 (set 'result (ada-get-indent-case orgpoint))) 2437 ;;
2224 ;; 2438 ((looking-at "when\\>")
2225 ((looking-at "when\\>") 2439 (ada-get-indent-when orgpoint))
2226 (set 'result (ada-get-indent-when orgpoint))) 2440 ;;
2227 ;; 2441 ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]")
2228 ((looking-at "\\(\\sw\\|_\\)+[ \t\n]*:[^=]") 2442 (ada-get-indent-label orgpoint))
2229 (set 'result (ada-get-indent-label orgpoint))) 2443 ;;
2230 ;; 2444 ((looking-at "separate\\>")
2231 ((looking-at "separate\\>") 2445 (ada-get-indent-nochange))
2232 (set 'result (ada-get-indent-nochange))) 2446 ;;
2233 (t 2447 ((looking-at "with\\>\\|use\\>")
2234 (set 'result (ada-get-indent-noindent orgpoint)))))))) 2448 ;; Are we still in that statement, or are we in fact looking at
2235 2449 ;; the previous one ?
2236 result)) 2450 (if (save-excursion (search-forward ";" oldpoint t))
2451 (list (progn (back-to-indentation) (point)) 0)
2452 (list (point) (if (looking-at "with")
2453 'ada-with-indent
2454 'ada-use-indent))))
2455 ;;
2456 (t
2457 (ada-get-indent-noindent orgpoint)))))
2458 ))
2237 2459
2238 (defun ada-get-indent-open-paren () 2460 (defun ada-get-indent-open-paren ()
2239 "Calculates the indentation when point is behind an unclosed parenthesis." 2461 "Calculates the indentation when point is behind an unclosed parenthesis."
2240 (list (ada-in-open-paren-p) 0)) 2462 (list (ada-in-open-paren-p) 0))
2241 2463
2270 2492
2271 (defun ada-get-indent-end (orgpoint) 2493 (defun ada-get-indent-end (orgpoint)
2272 "Calculates the indentation when point is just before an end_statement. 2494 "Calculates the indentation when point is just before an end_statement.
2273 ORGPOINT is the limit position used in the calculation." 2495 ORGPOINT is the limit position used in the calculation."
2274 (let ((defun-name nil) 2496 (let ((defun-name nil)
2275 (label 0)
2276 (indent nil)) 2497 (indent nil))
2277 ;; 2498
2278 ;; is the line already terminated by ';' ? 2499 ;; is the line already terminated by ';' ?
2279 ;;
2280 (if (save-excursion 2500 (if (save-excursion
2281 (ada-search-ignore-string-comment ";" nil orgpoint nil 2501 (ada-search-ignore-string-comment ";" nil orgpoint nil
2282 'search-forward)) 2502 'search-forward))
2283 ;; 2503
2284 ;; yes, look what's following 'end' 2504 ;; yes, look what's following 'end'
2285 ;;
2286 (progn 2505 (progn
2287 (forward-word 1) 2506 (forward-word 1)
2288 (ada-goto-next-non-ws) 2507 (ada-goto-next-non-ws)
2289 (cond 2508 (cond
2290 ((looking-at "\\<\\(loop\\|select\\|if\\|case\\)\\>") 2509 ((looking-at "\\<\\(loop\\|select\\|if\\|case\\)\\>")
2291 (save-excursion (ada-check-matching-start (match-string 0))) 2510 (save-excursion (ada-check-matching-start (match-string 0)))
2292 (list (save-excursion (back-to-indentation) (point)) 0)) 2511 (list (save-excursion (back-to-indentation) (point)) 0))
2293 2512
2294 ;; 2513 ;;
2295 ;; loop/select/if/case/record/select 2514 ;; loop/select/if/case/record/select
2296 ;; 2515 ;;
2297 ((looking-at "\\<record\\>") 2516 ((looking-at "\\<record\\>")
2298 (save-excursion 2517 (save-excursion
2299 (ada-check-matching-start (match-string 0)) 2518 (ada-check-matching-start (match-string 0))
2300 ;; we are now looking at the matching "record" statement 2519 ;; we are now looking at the matching "record" statement
2301 (forward-word 1) 2520 (forward-word 1)
2302 (ada-goto-stmt-start) 2521 (ada-goto-stmt-start)
2303 ;; now on the matching type declaration, or use clause 2522 ;; now on the matching type declaration, or use clause
2304 (unless (looking-at "\\(for\\|type\\)\\>") 2523 (unless (looking-at "\\(for\\|type\\)\\>")
2305 (ada-search-ignore-string-comment "\\<type\\>" t)) 2524 (ada-search-ignore-string-comment "\\<type\\>" t))
2306 (list (progn (back-to-indentation) (point)) 0))) 2525 (list (progn (back-to-indentation) (point)) 0)))
2307 ;; 2526 ;;
2308 ;; a named block end 2527 ;; a named block end
2309 ;; 2528 ;;
2310 ((looking-at ada-ident-re) 2529 ((looking-at ada-ident-re)
2311 (set 'defun-name (match-string 0)) 2530 (set 'defun-name (match-string 0))
2312 (save-excursion 2531 (save-excursion
2313 (ada-goto-matching-start 0) 2532 (ada-goto-matching-start 0)
2314 (ada-check-defun-name defun-name)) 2533 (ada-check-defun-name defun-name))
2315 (list (progn (back-to-indentation) (point)) 0)) 2534 (list (progn (back-to-indentation) (point)) 0))
2316 ;; 2535 ;;
2317 ;; a block-end without name 2536 ;; a block-end without name
2318 ;; 2537 ;;
2319 ((= (char-after) ?\;) 2538 ((= (char-after) ?\;)
2320 (save-excursion 2539 (save-excursion
2321 (ada-goto-matching-start 0) 2540 (ada-goto-matching-start 0)
2322 (if (looking-at "\\<begin\\>") 2541 (if (looking-at "\\<begin\\>")
2323 (progn 2542 (progn
2324 (set 'indent (list (point) 0)) 2543 (set 'indent (list (point) 0))
2325 (if (ada-goto-matching-decl-start t) 2544 (if (ada-goto-matching-decl-start t)
2326 (list (progn (back-to-indentation) (point)) 0) 2545 (list (progn (back-to-indentation) (point)) 0)
2327 indent))))) 2546 indent)))))
2328 ;; 2547 ;;
2329 ;; anything else - should maybe signal an error ? 2548 ;; anything else - should maybe signal an error ?
2330 ;; 2549 ;;
2331 (t 2550 (t
2332 (list (save-excursion (back-to-indentation) (point)) 2551 (list (save-excursion (back-to-indentation) (point))
2333 'ada-broken-indent)))) 2552 'ada-broken-indent))))
2334 2553
2335 (list (save-excursion (back-to-indentation) (point)) 2554 (list (save-excursion (back-to-indentation) (point))
2336 'ada-broken-indent)))) 2555 'ada-broken-indent))))
2337 2556
2338 (defun ada-get-indent-case (orgpoint) 2557 (defun ada-get-indent-case (orgpoint)
2339 "Calculates the indentation when point is just before a case statement. 2558 "Calculates the indentation when point is just before a case statement.
2340 ORGPOINT is the limit position used in the calculation." 2559 ORGPOINT is the limit position used in the calculation."
2341 (let ((match-cons nil) 2560 (let ((match-cons nil)
2353 "[ \t\n]+=>" nil orgpoint)))) 2572 "[ \t\n]+=>" nil orgpoint))))
2354 (save-excursion 2573 (save-excursion
2355 (goto-char (car match-cons)) 2574 (goto-char (car match-cons))
2356 (unless (ada-search-ignore-string-comment "when" t opos) 2575 (unless (ada-search-ignore-string-comment "when" t opos)
2357 (error "missing 'when' between 'case' and '=>'")) 2576 (error "missing 'when' between 'case' and '=>'"))
2358 (list (save-excursion (back-to-indentation) (point)) 'ada-indent))) 2577 (list (save-excursion (back-to-indentation) (point)) 'ada-indent)))
2359 ;; 2578 ;;
2360 ;; case..is..when 2579 ;; case..is..when
2361 ;; 2580 ;;
2362 ((save-excursion 2581 ((save-excursion
2363 (set 'match-cons (ada-search-ignore-string-comment 2582 (set 'match-cons (ada-search-ignore-string-comment
2374 ;; 2593 ;;
2375 ;; incomplete case 2594 ;; incomplete case
2376 ;; 2595 ;;
2377 (t 2596 (t
2378 (list (save-excursion (back-to-indentation) (point)) 2597 (list (save-excursion (back-to-indentation) (point))
2379 'ada-broken-indent))))) 2598 'ada-broken-indent)))))
2380 2599
2381 (defun ada-get-indent-when (orgpoint) 2600 (defun ada-get-indent-when (orgpoint)
2382 "Calcules the indentation when point is just before a when statement. 2601 "Calculates the indentation when point is just before a when statement.
2383 ORGPOINT is the limit position used in the calculation." 2602 ORGPOINT is the limit position used in the calculation."
2384 (let ((cur-indent (save-excursion (back-to-indentation) (point)))) 2603 (let ((cur-indent (save-excursion (back-to-indentation) (point))))
2385 (if (ada-search-ignore-string-comment "[ \t\n]*=>" nil orgpoint) 2604 (if (ada-search-ignore-string-comment "[ \t\n]*=>" nil orgpoint)
2386 (list cur-indent 'ada-indent) 2605 (list cur-indent 'ada-indent)
2387 (list cur-indent 'ada-broken-indent)))) 2606 (list cur-indent 'ada-broken-indent))))
2388 2607
2389 (defun ada-get-indent-if (orgpoint) 2608 (defun ada-get-indent-if (orgpoint)
2390 "Calculates the indentation when point is just before an if statement. 2609 "Calculates the indentation when point is just before an if statement.
2391 ORGPOINT is the limit position used in the calculation." 2610 ORGPOINT is the limit position used in the calculation."
2402 (if match-cons 2621 (if match-cons
2403 (progn 2622 (progn
2404 ;; 2623 ;;
2405 ;; 'then' first in separate line ? 2624 ;; 'then' first in separate line ?
2406 ;; => indent according to 'then', 2625 ;; => indent according to 'then',
2407 ;; => else indent according to 'if' 2626 ;; => else indent according to 'if'
2408 ;; 2627 ;;
2409 (if (save-excursion 2628 (if (save-excursion
2410 (back-to-indentation) 2629 (back-to-indentation)
2411 (looking-at "\\<then\\>")) 2630 (looking-at "\\<then\\>"))
2412 (set 'cur-indent (save-excursion (back-to-indentation) (point)))) 2631 (set 'cur-indent (save-excursion (back-to-indentation) (point))))
2413 ;; skip 'then' 2632 ;; skip 'then'
2414 (forward-word 1) 2633 (forward-word 1)
2415 (list cur-indent 'ada-indent)) 2634 (list cur-indent 'ada-indent))
2416 2635
2417 (list cur-indent 'ada-broken-indent)))) 2636 (list cur-indent 'ada-broken-indent))))
2418 2637
2419 (defun ada-get-indent-block-start (orgpoint) 2638 (defun ada-get-indent-block-start (orgpoint)
2420 "Calculates the indentation when point is at the start of a block. 2639 "Calculates the indentation when point is at the start of a block.
2491 (ada-indent-on-previous-lines t orgpoint))) 2710 (ada-indent-on-previous-lines t orgpoint)))
2492 ;; 2711 ;;
2493 ;; no 'is' but ';' 2712 ;; no 'is' but ';'
2494 ;; 2713 ;;
2495 ((save-excursion 2714 ((save-excursion
2496 (ada-search-ignore-string-comment ";" nil orgpoint nil 2715 (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward))
2497 'search-forward))
2498 (list cur-indent 0)) 2716 (list cur-indent 0))
2499 ;; 2717 ;;
2500 ;; no 'is' or ';' 2718 ;; no 'is' or ';'
2501 ;; 2719 ;;
2502 (t 2720 (t
2509 (save-excursion 2727 (save-excursion
2510 (beginning-of-line) 2728 (beginning-of-line)
2511 2729
2512 (cond 2730 (cond
2513 2731
2514 ;; This one is called when indenting a line preceded by a multiline 2732 ;; This one is called when indenting a line preceded by a multi-line
2515 ;; subprogram declaration (in that case, we are at this point inside 2733 ;; subprogram declaration (in that case, we are at this point inside
2516 ;; the parameter declaration list) 2734 ;; the parameter declaration list)
2517 ((ada-in-paramlist-p) 2735 ((ada-in-paramlist-p)
2518 (ada-previous-procedure) 2736 (ada-previous-procedure)
2519 (list (save-excursion (back-to-indentation) (point)) 0)) 2737 (list (save-excursion (back-to-indentation) (point)) 0))
2520 2738
2521 ;; This one is called when indenting the second line of a multi-line 2739 ;; This one is called when indenting the second line of a multi-line
2522 ;; declaration section, in a declare block or a record declaration 2740 ;; declaration section, in a declare block or a record declaration
2523 ((looking-at "[ \t]*\\(\\sw\\|_\\)*[ \t]*,[ \t]*$") 2741 ((looking-at "[ \t]*\\(\\sw\\|_\\)*[ \t]*,[ \t]*$")
2524 (list (save-excursion (back-to-indentation) (point)) 2742 (list (save-excursion (back-to-indentation) (point))
2525 'ada-broken-decl-indent)) 2743 'ada-broken-decl-indent))
2526 2744
2527 ;; This one is called in every over case when indenting a line at the 2745 ;; This one is called in every over case when indenting a line at the
2528 ;; top level 2746 ;; top level
2529 (t 2747 (t
2530 (if (looking-at ada-named-block-re) 2748 (if (looking-at ada-named-block-re)
2531 (set 'label (- ada-label-indent)) 2749 (set 'label (- ada-label-indent))
2532 2750
2533 ;; "with private" or "null record" cases 2751 (let (p)
2534 (if (or (and (re-search-forward "\\<private\\>" orgpoint t) 2752
2535 (save-excursion (forward-char -7);; skip back "private" 2753 ;; "with private" or "null record" cases
2536 (ada-goto-previous-word) 2754 (if (or (save-excursion
2537 (looking-at "with"))) 2755 (and (ada-search-ignore-string-comment "\\<private\\>" nil orgpoint)
2538 (and (re-search-forward "\\<record\\>" orgpoint t) 2756 (set 'p (point))
2539 (save-excursion (forward-char -6);; skip back "record" 2757 (save-excursion (forward-char -7);; skip back "private"
2540 (ada-goto-previous-word) 2758 (ada-goto-previous-word)
2541 (looking-at "null")))) 2759 (looking-at "with"))))
2542 (progn 2760 (save-excursion
2543 (re-search-backward "\\<\\(type\\|subtype\\)\\>" nil t) 2761 (and (ada-search-ignore-string-comment "\\<record\\>" nil orgpoint)
2544 (list (save-excursion (back-to-indentation) (point)) 0)))) 2762 (set 'p (point))
2763 (save-excursion (forward-char -6);; skip back "record"
2764 (ada-goto-previous-word)
2765 (looking-at "null")))))
2766 (progn
2767 (goto-char p)
2768 (re-search-backward "\\<\\(type\\|subtype\\)\\>" nil t)
2769 (list (save-excursion (back-to-indentation) (point)) 0)))))
2545 (if (save-excursion 2770 (if (save-excursion
2546 (ada-search-ignore-string-comment ";" nil orgpoint nil 'search-forward)) 2771 (ada-search-ignore-string-comment ";" nil orgpoint nil
2547 (list (+ (save-excursion (back-to-indentation) (point)) label) 0) 2772 'search-forward))
2548 (list (+ (save-excursion (back-to-indentation) (point)) label) 2773 (list (+ (save-excursion (back-to-indentation) (point)) label) 0)
2549 'ada-broken-indent))))))) 2774 (list (+ (save-excursion (back-to-indentation) (point)) label)
2775 'ada-broken-indent)))))))
2550 2776
2551 (defun ada-get-indent-label (orgpoint) 2777 (defun ada-get-indent-label (orgpoint)
2552 "Calculates the indentation when before a label or variable declaration. 2778 "Calculates the indentation when before a label or variable declaration.
2553 ORGPOINT is the limit position used in the calculation." 2779 ORGPOINT is the limit position used in the calculation."
2554 (let ((match-cons nil) 2780 (let ((match-cons nil)
2556 (ada-search-ignore-string-comment ":" nil) 2782 (ada-search-ignore-string-comment ":" nil)
2557 (cond 2783 (cond
2558 ;; loop label 2784 ;; loop label
2559 ((save-excursion 2785 ((save-excursion
2560 (set 'match-cons (ada-search-ignore-string-comment 2786 (set 'match-cons (ada-search-ignore-string-comment
2561 ada-loop-start-re nil orgpoint))) 2787 ada-loop-start-re nil orgpoint)))
2562 (goto-char (car match-cons)) 2788 (goto-char (car match-cons))
2563 (ada-get-indent-loop orgpoint)) 2789 (ada-get-indent-loop orgpoint))
2564 2790
2565 ;; declare label 2791 ;; declare label
2566 ((save-excursion 2792 ((save-excursion
2567 (set 'match-cons (ada-search-ignore-string-comment 2793 (set 'match-cons (ada-search-ignore-string-comment
2568 "\\<declare\\|begin\\>" nil orgpoint))) 2794 "\\<declare\\|begin\\>" nil orgpoint)))
2569 (goto-char (car match-cons)) 2795 (goto-char (car match-cons))
2570 (list (save-excursion (back-to-indentation) (point)) 'ada-indent)) 2796 (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
2571 2797
2572 ;; variable declaration 2798 ;; variable declaration
2573 ((ada-in-decl-p) 2799 ((ada-in-decl-p)
2574 (if (save-excursion 2800 (if (save-excursion
2575 (ada-search-ignore-string-comment ";" nil orgpoint)) 2801 (ada-search-ignore-string-comment ";" nil orgpoint))
2576 (list cur-indent 0) 2802 (list cur-indent 0)
2577 (list cur-indent 'ada-broken-indent))) 2803 (list cur-indent 'ada-broken-indent)))
2578 2804
2579 ;; nothing follows colon 2805 ;; nothing follows colon
2580 (t 2806 (t
2581 (list cur-indent '(- ada-label-indent)))))) 2807 (list cur-indent '(- ada-label-indent))))))
2582 2808
2584 "Calculates the indentation when just before a loop or a for ... use. 2810 "Calculates the indentation when just before a loop or a for ... use.
2585 ORGPOINT is the limit position used in the calculation." 2811 ORGPOINT is the limit position used in the calculation."
2586 (let ((match-cons nil) 2812 (let ((match-cons nil)
2587 (pos (point)) 2813 (pos (point))
2588 2814
2589 ;; If looking at a named block, skip the label 2815 ;; If looking at a named block, skip the label
2590 (label (save-excursion 2816 (label (save-excursion
2591 (beginning-of-line) 2817 (beginning-of-line)
2592 (if (looking-at ada-named-block-re) 2818 (if (looking-at ada-named-block-re)
2593 (- ada-label-indent) 2819 (- ada-label-indent)
2594 0)))) 2820 0))))
2598 ;; 2824 ;;
2599 ;; statement complete 2825 ;; statement complete
2600 ;; 2826 ;;
2601 ((save-excursion 2827 ((save-excursion
2602 (ada-search-ignore-string-comment ";" nil orgpoint nil 2828 (ada-search-ignore-string-comment ";" nil orgpoint nil
2603 'search-forward)) 2829 'search-forward))
2604 (list (+ (save-excursion (back-to-indentation) (point)) label) 0)) 2830 (list (+ (save-excursion (back-to-indentation) (point)) label) 0))
2605 ;; 2831 ;;
2606 ;; simple loop 2832 ;; simple loop
2607 ;; 2833 ;;
2608 ((looking-at "loop\\>") 2834 ((looking-at "loop\\>")
2609 (set 'pos (ada-get-indent-block-start orgpoint)) 2835 (set 'pos (ada-get-indent-block-start orgpoint))
2610 (if (equal label 0) 2836 (if (equal label 0)
2611 pos 2837 pos
2612 (list (+ (car pos) label) (cdr pos)))) 2838 (list (+ (car pos) label) (cdr pos))))
2613 2839
2614 ;; 2840 ;;
2615 ;; 'for'- loop (or also a for ... use statement) 2841 ;; 'for'- loop (or also a for ... use statement)
2616 ;; 2842 ;;
2617 ((looking-at "for\\>") 2843 ((looking-at "for\\>")
2634 (set 'match-cons (ada-search-ignore-string-comment 2860 (set 'match-cons (ada-search-ignore-string-comment
2635 "record" nil orgpoint nil 'word-search-forward)) 2861 "record" nil orgpoint nil 'word-search-forward))
2636 t))) 2862 t)))
2637 (if match-cons 2863 (if match-cons
2638 (goto-char (car match-cons))) 2864 (goto-char (car match-cons)))
2639 (list (save-excursion (back-to-indentation) (point)) 'ada-indent)) 2865 (list (save-excursion (back-to-indentation) (point)) 'ada-indent))
2640 ;; 2866 ;;
2641 ;; for..loop 2867 ;; for..loop
2642 ;; 2868 ;;
2643 ((save-excursion 2869 ((save-excursion
2644 (set 'match-cons (ada-search-ignore-string-comment 2870 (set 'match-cons (ada-search-ignore-string-comment
2650 ;; 2876 ;;
2651 (unless (save-excursion 2877 (unless (save-excursion
2652 (back-to-indentation) 2878 (back-to-indentation)
2653 (looking-at "\\<loop\\>")) 2879 (looking-at "\\<loop\\>"))
2654 (goto-char pos)) 2880 (goto-char pos))
2655 (list (+ (save-excursion (back-to-indentation) (point)) label) 2881 (list (+ (save-excursion (back-to-indentation) (point)) label)
2656 'ada-indent)) 2882 'ada-indent))
2657 ;; 2883 ;;
2658 ;; for-statement is broken 2884 ;; for-statement is broken
2659 ;; 2885 ;;
2660 (t 2886 (t
2661 (list (+ (save-excursion (back-to-indentation) (point)) label) 2887 (list (+ (save-excursion (back-to-indentation) (point)) label)
2662 'ada-broken-indent)))) 2888 'ada-broken-indent))))
2663 2889
2664 ;; 2890 ;;
2665 ;; 'while'-loop 2891 ;; 'while'-loop
2666 ;; 2892 ;;
2667 ((looking-at "while\\>") 2893 ((looking-at "while\\>")
2680 ;; 2906 ;;
2681 (unless (save-excursion 2907 (unless (save-excursion
2682 (back-to-indentation) 2908 (back-to-indentation)
2683 (looking-at "\\<loop\\>")) 2909 (looking-at "\\<loop\\>"))
2684 (goto-char pos)) 2910 (goto-char pos))
2685 (list (+ (save-excursion (back-to-indentation) (point)) label) 2911 (list (+ (save-excursion (back-to-indentation) (point)) label)
2686 'ada-indent)) 2912 'ada-indent))
2687 2913
2688 (list (+ (save-excursion (back-to-indentation) (point)) label) 2914 (list (+ (save-excursion (back-to-indentation) (point)) label)
2689 'ada-broken-indent)))))) 2915 'ada-broken-indent))))))
2690
2691 2916
2692 (defun ada-get-indent-type (orgpoint) 2917 (defun ada-get-indent-type (orgpoint)
2693 "Calculates the indentation when before a type statement. 2918 "Calculates the indentation when before a type statement.
2694 ORGPOINT is the limit position used in the calculation." 2919 ORGPOINT is the limit position used in the calculation."
2695 (let ((match-dat nil)) 2920 (let ((match-dat nil))
2719 ;; 2944 ;;
2720 ;; complete type declaration 2945 ;; complete type declaration
2721 ;; 2946 ;;
2722 ((save-excursion 2947 ((save-excursion
2723 (ada-search-ignore-string-comment ";" nil orgpoint nil 2948 (ada-search-ignore-string-comment ";" nil orgpoint nil
2724 'search-forward)) 2949 'search-forward))
2725 (list (save-excursion (back-to-indentation) (point)) 0)) 2950 (list (save-excursion (back-to-indentation) (point)) 0))
2726 ;; 2951 ;;
2727 ;; "type ... is", but not "type ... is ...", which is broken 2952 ;; "type ... is", but not "type ... is ...", which is broken
2728 ;; 2953 ;;
2729 ((save-excursion 2954 ((save-excursion
2730 (and 2955 (and
2731 (ada-search-ignore-string-comment "is" nil orgpoint nil 2956 (ada-search-ignore-string-comment "is" nil orgpoint nil
2732 'word-search-forward) 2957 'word-search-forward)
2733 (not (ada-goto-next-non-ws orgpoint)))) 2958 (not (ada-goto-next-non-ws orgpoint))))
2734 (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent)) 2959 (list (save-excursion (back-to-indentation) (point)) 'ada-broken-indent))
2735 ;; 2960 ;;
2736 ;; broken statement 2961 ;; broken statement
2737 ;; 2962 ;;
2738 (t 2963 (t
2739 (list (save-excursion (back-to-indentation) (point)) 2964 (list (save-excursion (back-to-indentation) (point))
2740 'ada-broken-indent))))) 2965 'ada-broken-indent)))))
2741 2966
2742 2967
2743 ;; ----------------------------------------------------------- 2968 ;; -----------------------------------------------------------
2744 ;; -- searching and matching 2969 ;; -- searching and matching
2745 ;; ----------------------------------------------------------- 2970 ;; -----------------------------------------------------------
2752 (let ((match-dat nil) 2977 (let ((match-dat nil)
2753 (orgpoint (point))) 2978 (orgpoint (point)))
2754 2979
2755 (set 'match-dat (ada-search-prev-end-stmt)) 2980 (set 'match-dat (ada-search-prev-end-stmt))
2756 (if match-dat 2981 (if match-dat
2757 2982
2758 ;; 2983 ;;
2759 ;; found a previous end-statement => check if anything follows 2984 ;; found a previous end-statement => check if anything follows
2760 ;; 2985 ;;
2761 (unless (looking-at "declare") 2986 (unless (looking-at "declare")
2762 (progn 2987 (progn
2763 (unless (save-excursion 2988 (unless (save-excursion
2764 (goto-char (cdr match-dat)) 2989 (goto-char (cdr match-dat))
2765 (ada-goto-next-non-ws orgpoint)) 2990 (ada-goto-next-non-ws orgpoint))
2766 ;; 2991 ;;
2767 ;; nothing follows => it's the end-statement directly in 2992 ;; nothing follows => it's the end-statement directly in
2768 ;; front of point => search again 2993 ;; front of point => search again
2769 ;; 2994 ;;
2770 (set 'match-dat (ada-search-prev-end-stmt))) 2995 (set 'match-dat (ada-search-prev-end-stmt)))
2771 ;; 2996 ;;
2772 ;; if found the correct end-statement => goto next non-ws 2997 ;; if found the correct end-statement => goto next non-ws
2773 ;; 2998 ;;
2774 (if match-dat 2999 (if match-dat
2775 (goto-char (cdr match-dat))) 3000 (goto-char (cdr match-dat)))
2776 (ada-goto-next-non-ws) 3001 (ada-goto-next-non-ws)
2777 )) 3002 ))
2778 3003
2779 ;; 3004 ;;
2780 ;; no previous end-statement => we are at the beginning of the 3005 ;; no previous end-statement => we are at the beginning of the
2781 ;; accessible part of the buffer 3006 ;; accessible part of the buffer
2782 ;; 3007 ;;
2783 (progn 3008 (progn
2784 (goto-char (point-min)) 3009 (goto-char (point-min))
2785 ;; 3010 ;;
2786 ;; skip to the very first statement, if there is one 3011 ;; skip to the very first statement, if there is one
2787 ;; 3012 ;;
2788 (unless (ada-goto-next-non-ws orgpoint) 3013 (unless (ada-goto-next-non-ws orgpoint)
2789 (goto-char orgpoint)))) 3014 (goto-char orgpoint))))
2790
2791 (point))) 3015 (point)))
2792 3016
2793 3017
2794 (defun ada-search-prev-end-stmt () 3018 (defun ada-search-prev-end-stmt ()
2795 "Moves point to previous end-statement. 3019 "Moves point to previous end-statement.
2796 Returns a cons cell whose car is the beginning and whose cdr the end of the 3020 Returns a cons cell whose car is the beginning and whose cdr the end of the
2797 match." 3021 match."
2798 (let ((match-dat nil) 3022 (let ((match-dat nil)
2799 (found nil) 3023 (found nil))
2800 parse) 3024
2801
2802 ;;
2803 ;; search until found or beginning-of-buffer 3025 ;; search until found or beginning-of-buffer
2804 ;;
2805 (while 3026 (while
2806 (and 3027 (and
2807 (not found) 3028 (not found)
2808 (set 'match-dat (ada-search-ignore-string-comment 3029 (set 'match-dat (ada-search-ignore-string-comment
2809 ada-end-stmt-re t))) 3030 ada-end-stmt-re t)))
2824 ;; words that can go after an 'is' 3045 ;; words that can go after an 'is'
2825 (unless (looking-at 3046 (unless (looking-at
2826 (eval-when-compile 3047 (eval-when-compile
2827 (concat "\\<" 3048 (concat "\\<"
2828 (regexp-opt '("separate" "access" "array" 3049 (regexp-opt '("separate" "access" "array"
2829 "abstract" "new") t) 3050 "abstract" "new") t)
2830 "\\>\\|("))) 3051 "\\>\\|(")))
2831 (set 'found t)))) 3052 (set 'found t))))
2832 )) 3053 ))
2833 3054
2834 (if found 3055 (if found
2870 (let ((match-cons nil) 3091 (let ((match-cons nil)
2871 (orgpoint (point)) 3092 (orgpoint (point))
2872 (old-syntax (char-to-string (char-syntax ?_)))) 3093 (old-syntax (char-to-string (char-syntax ?_))))
2873 (modify-syntax-entry ?_ "w") 3094 (modify-syntax-entry ?_ "w")
2874 (unless backward 3095 (unless backward
2875 (skip-syntax-forward "w"));; ??? Used to have . too 3096 (skip-syntax-forward "w"))
2876 (if (set 'match-cons 3097 (if (set 'match-cons
2877 (if backward 3098 (if backward
2878 (ada-search-ignore-string-comment "\\w" t nil t) 3099 (ada-search-ignore-string-comment "\\w" t nil t)
2879 (ada-search-ignore-string-comment "\\w" nil nil t))) 3100 (ada-search-ignore-string-comment "\\w" nil nil t)))
2880 ;; 3101 ;;
2891 'nil) 3112 'nil)
2892 (modify-syntax-entry ?_ old-syntax)) 3113 (modify-syntax-entry ?_ old-syntax))
2893 ) 3114 )
2894 3115
2895 3116
2896 (defsubst ada-goto-previous-word ()
2897 "Moves point to the beginning of the previous word of Ada code.
2898 Returns the new position of point or nil if not found."
2899 (ada-goto-next-word t))
2900
2901
2902 (defun ada-check-matching-start (keyword) 3117 (defun ada-check-matching-start (keyword)
2903 "Signals an error if matching block start is not KEYWORD. 3118 "Signals an error if matching block start is not KEYWORD.
2904 Moves point to the matching block start." 3119 Moves point to the matching block start."
2905 (ada-goto-matching-start 0) 3120 (ada-goto-matching-start 0)
2906 (unless (looking-at (concat "\\<" keyword "\\>")) 3121 (unless (looking-at (concat "\\<" keyword "\\>"))
2918 (looking-at (concat "\\<" defun-name "\\> *:"))) 3133 (looking-at (concat "\\<" defun-name "\\> *:")))
2919 t ; do nothing 3134 t ; do nothing
2920 ;; 3135 ;;
2921 ;; 'accept' or 'package' ? 3136 ;; 'accept' or 'package' ?
2922 ;; 3137 ;;
2923 (unless (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>") 3138 (unless (looking-at ada-subprog-start-re)
2924 (ada-goto-matching-decl-start)) 3139 (ada-goto-matching-decl-start))
2925 ;; 3140 ;;
2926 ;; 'begin' of 'procedure'/'function'/'task' or 'declare' 3141 ;; 'begin' of 'procedure'/'function'/'task' or 'declare'
2927 ;; 3142 ;;
2928 (save-excursion 3143 (save-excursion
2950 (unless (looking-at (concat "\\<" defun-name "\\>")) 3165 (unless (looking-at (concat "\\<" defun-name "\\>"))
2951 (error "matching defun has different name: %s" 3166 (error "matching defun has different name: %s"
2952 (buffer-substring (point) 3167 (buffer-substring (point)
2953 (progn (forward-sexp 1) (point)))))))) 3168 (progn (forward-sexp 1) (point))))))))
2954 3169
2955 (defun ada-goto-matching-decl-start (&optional noerror) 3170 (defun ada-goto-matching-decl-start (&optional noerror recursive)
2956 "Moves point to the matching declaration start of the current 'begin'. 3171 "Moves point to the matching declaration start of the current 'begin'.
2957 If NOERROR is non-nil, it only returns nil if no match was found." 3172 If NOERROR is non-nil, it only returns nil if no match was found."
2958 (let ((nest-count 1) 3173 (let ((nest-count 1)
2959 (first t) 3174 (first (not recursive))
2960 (flag nil)
2961 (count-generic nil) 3175 (count-generic nil)
3176 (stop-at-when nil)
2962 ) 3177 )
3178
3179 ;; Ignore "when" most of the time, except if we are looking at the
3180 ;; beginning of a block (structure: case .. is
3181 ;; when ... =>
3182 ;; begin ...
3183 ;; exception ... )
3184 (if (looking-at "begin")
3185 (set 'stop-at-when t))
2963 3186
2964 (if (or 3187 (if (or
2965 (looking-at "\\<\\(package\\|procedure\\|function\\)\\>") 3188 (looking-at "\\<\\(package\\|procedure\\|function\\)\\>")
2966 (save-excursion 3189 (save-excursion
2967 (ada-search-ignore-string-comment 3190 (ada-search-ignore-string-comment
2968 "\\<\\(package\\|procedure\\|function\\|generic\\)\\>" t) 3191 "\\<\\(package\\|procedure\\|function\\|generic\\)\\>" t)
2969 (looking-at "generic"))) 3192 (looking-at "generic")))
2970 (set 'count-generic t)) 3193 (set 'count-generic t))
2971 3194
2972 ;; search backward for interesting keywords 3195 ;; search backward for interesting keywords
2973 (while (and 3196 (while (and
2979 (cond 3202 (cond
2980 ;; 3203 ;;
2981 ((looking-at "end") 3204 ((looking-at "end")
2982 (ada-goto-matching-start 1 noerror) 3205 (ada-goto-matching-start 1 noerror)
2983 3206
2984 ;; In some case, two begin..end block can follow each other closely, 3207 ;; In some case, two begin..end block can follow each other closely,
2985 ;; which we have to detect, as in 3208 ;; which we have to detect, as in
2986 ;; procedure P is 3209 ;; procedure P is
2987 ;; procedure Q is 3210 ;; procedure Q is
2988 ;; begin 3211 ;; begin
2989 ;; end; 3212 ;; end;
2990 ;; begin -- here we should go to procedure, not begin 3213 ;; begin -- here we should go to procedure, not begin
2991 ;; end 3214 ;; end
2992 3215
2993 (let ((loop-again 0)) 3216 (if (looking-at "begin")
2994 (if (looking-at "begin") 3217 (let ((loop-again t))
2995 (set 'loop-again 1)) 3218 (save-excursion
2996 3219 (while loop-again
2997 (save-excursion 3220 ;; If begin was just there as the beginning of a block
2998 (while (not (= loop-again 0)) 3221 ;; (with no declare) then do nothing, otherwise just
2999 3222 ;; register that we have to find the statement that
3000 ;; If begin was just there as the beginning of a block (with no 3223 ;; required the begin
3001 ;; declare) then do nothing, otherwise just register that we 3224
3002 ;; have to find the statement that required the begin 3225 (ada-search-ignore-string-comment
3003 3226 "\\<\\(declare\\|begin\\|end\\|procedure\\|function\\|task\\|package\\)\\>"
3004 (ada-search-ignore-string-comment 3227 t)
3005 "declare\\|begin\\|end\\|procedure\\|function\\|task\\|package" 3228
3006 t) 3229 (if (looking-at "end")
3007 3230 (ada-goto-matching-decl-start noerror t)
3008 (if (looking-at "end") 3231
3009 (set 'loop-again (1+ loop-again)) 3232 (set 'loop-again nil)
3010 3233 (unless (looking-at "begin")
3011 (set 'loop-again (1- loop-again)) 3234 (set 'nest-count (1+ nest-count))))
3012 (unless (looking-at "begin") 3235 ))
3013 (set 'nest-count (1+ nest-count)))) 3236 )))
3014 ))
3015 ))
3016 ;; 3237 ;;
3017 ((looking-at "generic") 3238 ((looking-at "generic")
3018 (if count-generic 3239 (if count-generic
3019 (progn 3240 (progn
3020 (set 'first nil) 3241 (set 'first nil)
3021 (set 'nest-count (1- nest-count))))) 3242 (set 'nest-count (1- nest-count)))))
3022 ;; 3243 ;;
3023 ((looking-at "declare\\|generic\\|if") 3244 ((looking-at "if")
3245 (save-excursion
3246 (forward-word -1)
3247 (unless (looking-at "\\<end[ \t\n]*if\\>")
3248 (progn
3249 (set 'nest-count (1- nest-count))
3250 (set 'first nil)))))
3251
3252 ;;
3253 ((looking-at "declare\\|generic")
3024 (set 'nest-count (1- nest-count)) 3254 (set 'nest-count (1- nest-count))
3025 (set 'first nil)) 3255 (set 'first nil))
3026 ;; 3256 ;;
3027 ((looking-at "is") 3257 ((looking-at "is")
3028 ;; check if it is only a type definition, but not a protected 3258 ;; check if it is only a type definition, but not a protected
3061 (looking-at "is")) 3291 (looking-at "is"))
3062 (goto-char (match-beginning 0)))) 3292 (goto-char (match-beginning 0))))
3063 ;; 3293 ;;
3064 ((and first 3294 ((and first
3065 (looking-at "begin")) 3295 (looking-at "begin"))
3066 (set 'nest-count 0) 3296 (set 'nest-count 0))
3067 (set 'flag t)) 3297 ;;
3298 ((looking-at "when")
3299 (if stop-at-when
3300 (set 'nest-count (1- nest-count)))
3301 (set 'first nil))
3068 ;; 3302 ;;
3069 (t 3303 (t
3070 (set 'nest-count (1+ nest-count)) 3304 (set 'nest-count (1+ nest-count))
3071 (set 'first nil))) 3305 (set 'first nil)))
3072 3306
3073 );; end of loop 3307 );; end of loop
3074 3308
3075 ;; check if declaration-start is really found 3309 ;; check if declaration-start is really found
3076 (if (and 3310 (if (and
3077 (zerop nest-count) 3311 (zerop nest-count)
3078 (not flag)
3079 (if (looking-at "is") 3312 (if (looking-at "is")
3080 (ada-search-ignore-string-comment ada-subprog-start-re t) 3313 (ada-search-ignore-string-comment ada-subprog-start-re t)
3081 (looking-at "declare\\|generic"))) 3314 (looking-at "declare\\|generic")))
3082 t 3315 t
3083 (if noerror nil 3316 (if noerror nil
3140 "\\<\\(is\\|renames\\|;\\)\\>" nil))) 3373 "\\<\\(is\\|renames\\|;\\)\\>" nil)))
3141 (if pos 3374 (if pos
3142 (goto-char (car pos)) 3375 (goto-char (car pos))
3143 (error (concat 3376 (error (concat
3144 "No matching 'is' or 'renames' for 'package' at" 3377 "No matching 'is' or 'renames' for 'package' at"
3145 " line " 3378 " line "
3146 (number-to-string (count-lines (point-min) 3379 (number-to-string (count-lines (point-min)
3147 (1+ current))))))) 3380 (1+ current)))))))
3148 (unless (looking-at "renames") 3381 (unless (looking-at "renames")
3149 (progn 3382 (progn
3150 (forward-word 1) 3383 (forward-word 1)
3151 (ada-goto-next-non-ws) 3384 (ada-goto-next-non-ws)
3152 ;; ignore it if it is only a declaration with 'new' 3385 ;; ignore it if it is only a declaration with 'new'
3162 ((looking-at "\\<type\\>") 3395 ((looking-at "\\<type\\>")
3163 ;; In that case, do nothing if there is a "is" 3396 ;; In that case, do nothing if there is a "is"
3164 (forward-word 2);; skip "type" 3397 (forward-word 2);; skip "type"
3165 (ada-goto-next-non-ws);; skip type name 3398 (ada-goto-next-non-ws);; skip type name
3166 3399
3167 ;; Do nothing if we are simply looking at a simple 3400 ;; Do nothing if we are simply looking at a simple
3168 ;; "task type name;" statement with no block 3401 ;; "task type name;" statement with no block
3169 (unless (looking-at ";") 3402 (unless (looking-at ";")
3170 (progn 3403 (progn
3171 ;; Skip the parameters 3404 ;; Skip the parameters
3172 (if (looking-at "(") 3405 (if (looking-at "(")
3173 (ada-search-ignore-string-comment ")" nil)) 3406 (ada-search-ignore-string-comment ")" nil))
3174 (let ((tmp (ada-search-ignore-string-comment 3407 (let ((tmp (ada-search-ignore-string-comment
3175 "\\<\\(is\\|;\\)\\>" nil))) 3408 "\\<\\(is\\|;\\)\\>" nil)))
3176 (if tmp 3409 (if tmp
3177 (progn 3410 (progn
3178 (goto-char (car tmp)) 3411 (goto-char (car tmp))
3179 (if (looking-at "is") 3412 (if (looking-at "is")
3180 (set 'nest-count (1- nest-count))))))))) 3413 (set 'nest-count (1- nest-count)))))))))
3181 (t 3414 (t
3182 ;; Check if that task declaration had a block attached to 3415 ;; Check if that task declaration had a block attached to
3183 ;; it (i.e do nothing if we have just "task name;") 3416 ;; it (i.e do nothing if we have just "task name;")
3184 (unless (progn (forward-word 1) 3417 (unless (progn (forward-word 1)
3185 (looking-at "[ \t]*;")) 3418 (looking-at "[ \t]*;"))
3186 (set 'nest-count (1- nest-count))))))) 3419 (set 'nest-count (1- nest-count)))))))
3187 ;; all the other block starts 3420 ;; all the other block starts
3188 (t 3421 (t
3189 (set 'nest-count (1- nest-count)))) ; end of 'cond' 3422 (set 'nest-count (1- nest-count)))) ; end of 'cond'
3190 3423
3191 ;; match is found, if nest-depth is zero 3424 ;; match is found, if nest-depth is zero
3205 ((and 3438 ((and
3206 gotothen 3439 gotothen
3207 (looking-at "if") 3440 (looking-at "if")
3208 (save-excursion 3441 (save-excursion
3209 (ada-search-ignore-string-comment "then" nil nil nil 3442 (ada-search-ignore-string-comment "then" nil nil nil
3210 'word-search-forward) 3443 'word-search-forward)
3211 (back-to-indentation) 3444 (back-to-indentation)
3212 (looking-at "\\<then\\>"))) 3445 (looking-at "\\<then\\>")))
3213 (goto-char (match-beginning 0))) 3446 (goto-char (match-beginning 0)))
3214 ;; 3447 ;;
3215 ;; found 'do' => skip back to 'accept' 3448 ;; found 'do' => skip back to 'accept'
3216 ;; 3449 ;;
3217 ((looking-at "do") 3450 ((looking-at "do")
3218 (unless (ada-search-ignore-string-comment "accept" t nil nil 3451 (unless (ada-search-ignore-string-comment "accept" t nil nil
3219 'word-search-backward) 3452 'word-search-backward)
3220 (error "missing 'accept' in front of 'do'")))) 3453 (error "missing 'accept' in front of 'do'"))))
3221 (point)) 3454 (point))
3222 3455
3223 (if noerror 3456 (if noerror
3224 nil 3457 nil
3259 (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>")) 3492 (looking-at "\\<\\(loop\\|select\\|record\\|case\\|if\\)\\>"))
3260 (forward-word 1))) 3493 (forward-word 1)))
3261 ;; found package start => check if it really starts a block 3494 ;; found package start => check if it really starts a block
3262 ((looking-at "\\<package\\>") 3495 ((looking-at "\\<package\\>")
3263 (ada-search-ignore-string-comment "is" nil nil nil 3496 (ada-search-ignore-string-comment "is" nil nil nil
3264 'word-search-forward) 3497 'word-search-forward)
3265 (ada-goto-next-non-ws) 3498 (ada-goto-next-non-ws)
3266 ;; ignore and skip it if it is only a 'new' package 3499 ;; ignore and skip it if it is only a 'new' package
3267 (if (looking-at "\\<new\\>") 3500 (if (looking-at "\\<new\\>")
3268 (goto-char (match-end 0)) 3501 (goto-char (match-end 0))
3269 (set 'nest-count (1+ nest-count)))) 3502 (set 'nest-count (1+ nest-count))))
3283 (error "no matching end"))) 3516 (error "no matching end")))
3284 )) 3517 ))
3285 3518
3286 3519
3287 (defun ada-search-ignore-string-comment 3520 (defun ada-search-ignore-string-comment
3288 (search-re &optional backward limit paramlists search-func ) 3521 (search-re &optional backward limit paramlists search-func)
3289 "Regexp-search for SEARCH-RE, ignoring comments, strings. 3522 "Regexp-search for SEARCH-RE, ignoring comments, strings.
3290 If PARAMLISTS is nil, ignore parameter lists. Returns a cons cell of 3523 If PARAMLISTS is nil, ignore parameter lists. Returns a cons cell of
3291 begin and end of match data or nil, if not found. 3524 begin and end of match data or nil, if not found.
3292 The search is done using SEARCH-FUNC, which should search backward if 3525 The search is done using SEARCH-FUNC, which should search backward if
3293 BACKWARD is non-nil, forward otherwise. SEARCH-FUNC can be optimized in case 3526 BACKWARD is non-nil, forward otherwise. SEARCH-FUNC can be optimized in case
3333 ;; If inside a comment, skip it (and the following comments) 3566 ;; If inside a comment, skip it (and the following comments)
3334 ;; There is a special code for comments at the end of the file 3567 ;; There is a special code for comments at the end of the file
3335 ;; 3568 ;;
3336 ((ada-in-comment-p parse-result) 3569 ((ada-in-comment-p parse-result)
3337 (if ada-xemacs 3570 (if ada-xemacs
3338 (progn 3571 (progn
3339 (forward-line 1) 3572 (forward-line 1)
3340 (beginning-of-line) 3573 (beginning-of-line)
3341 (forward-comment -1)) 3574 (forward-comment -1))
3342 (goto-char (nth 8 parse-result))) 3575 (goto-char (nth 8 parse-result)))
3343 (unless backward 3576 (unless backward
3344 ;; at the end of the file, it is not possible to skip a comment 3577 ;; at the end of the file, it is not possible to skip a comment
3345 ;; so we just go at the end of the line 3578 ;; so we just go at the end of the line
3346 (if (forward-comment 1) 3579 (if (forward-comment 1)
3380 (defun ada-in-decl-p () 3613 (defun ada-in-decl-p ()
3381 "Returns t if point is inside a declarative part. 3614 "Returns t if point is inside a declarative part.
3382 Assumes point to be at the end of a statement." 3615 Assumes point to be at the end of a statement."
3383 (or (ada-in-paramlist-p) 3616 (or (ada-in-paramlist-p)
3384 (save-excursion 3617 (save-excursion
3385 (ada-goto-matching-decl-start t)))) 3618 (ada-goto-matching-decl-start t))))
3386 3619
3387 3620
3388 (defun ada-looking-at-semi-or () 3621 (defun ada-looking-at-semi-or ()
3389 "Returns t if looking-at an 'or' following a semicolon." 3622 "Returns t if looking-at an 'or' following a semicolon."
3390 (save-excursion 3623 (save-excursion
3394 (ada-goto-stmt-start) 3627 (ada-goto-stmt-start)
3395 (looking-at "\\<or\\>"))))) 3628 (looking-at "\\<or\\>")))))
3396 3629
3397 3630
3398 (defun ada-looking-at-semi-private () 3631 (defun ada-looking-at-semi-private ()
3399 "Returns t if looking-at an 'private' following a semicolon. 3632 "Returns t if looking at the start of a private section in a package.
3400 Returns nil if the private is part of the package name, as in 3633 Returns nil if the private is part of the package name, as in
3401 'private package A is...' (this can only happen at top level)." 3634 'private package A is...' (this can only happen at top level)."
3402 (save-excursion 3635 (save-excursion
3403 (and (looking-at "\\<private\\>") 3636 (and (looking-at "\\<private\\>")
3404 (not (looking-at "\\<private[ \t]*\\(package\\|generic\\)")) 3637 (not (looking-at "\\<private[ \t]*\\(package\\|generic\\)"))
3405 (progn (forward-comment -1000) 3638
3406 (= (char-before) ?\;))))) 3639 ;; Make sure this is the start of a private section (ie after
3407 3640 ;; a semicolon or just after the package declaration, but not
3408 (defsubst ada-in-comment-p (&optional parse-result) 3641 ;; after a 'type ... is private' or 'is new ... with private'
3409 "Returns t if inside a comment." 3642 (progn (forward-comment -1000)
3410 (nth 4 (or parse-result 3643 (or (= (char-before) ?\;)
3411 (parse-partial-sexp 3644 (and (forward-word -3)
3412 (save-excursion (beginning-of-line) (point)) (point))))) 3645 (looking-at "\\<package\\>")))))))
3413 3646
3414 (defsubst ada-in-string-p (&optional parse-result)
3415 "Returns t if point is inside a string.
3416 If parse-result is non-nil, use is instead of calling parse-partial-sexp."
3417 (nth 3 (or parse-result
3418 (parse-partial-sexp
3419 (save-excursion (beginning-of-line) (point)) (point)))))
3420
3421 (defsubst ada-in-string-or-comment-p (&optional parse-result)
3422 "Returns t if inside a comment or string."
3423 (set 'parse-result (or parse-result
3424 (parse-partial-sexp
3425 (save-excursion (beginning-of-line) (point)) (point))))
3426 (or (ada-in-string-p parse-result) (ada-in-comment-p parse-result)))
3427 3647
3428 (defun ada-in-paramlist-p () 3648 (defun ada-in-paramlist-p ()
3429 "Returns t if point is inside a parameter-list." 3649 "Returns t if point is inside a parameter-list."
3430 (save-excursion 3650 (save-excursion
3431 (and 3651 (and
3432 (re-search-backward "(\\|)" nil t) 3652 (ada-search-ignore-string-comment "(\\|)" t nil t)
3433 ;; inside parentheses ? 3653 ;; inside parentheses ?
3434 (= (char-after) ?\() 3654 (= (char-after) ?\()
3435 (backward-word 2) 3655
3436 3656 ;; We could be looking at two things here:
3657 ;; operator definition: function "." (
3658 ;; subprogram definition: procedure .... (
3659 ;; Let's skip back over the first one
3660 (progn
3661 (skip-syntax-backward " ")
3662 (if (= (char-before) ?\")
3663 (backward-char 3)
3664 (backward-word 1))
3665 t)
3666
3667 ;; and now over the second one
3668 (backward-word 1)
3669
3437 ;; We should ignore the case when the reserved keyword is in a 3670 ;; We should ignore the case when the reserved keyword is in a
3438 ;; comment (for instance, when we have: 3671 ;; comment (for instance, when we have:
3439 ;; -- .... package 3672 ;; -- .... package
3440 ;; Test (A) 3673 ;; Test (A)
3441 ;; we should return nil 3674 ;; we should return nil
3442 3675
3443 (not (ada-in-string-or-comment-p)) 3676 (not (ada-in-string-or-comment-p))
3444 3677
3445 ;; right keyword two words before parenthesis ? 3678 ;; right keyword two words before parenthesis ?
3446 ;; Type is in this list because of discriminants 3679 ;; Type is in this list because of discriminants
3447 (looking-at (eval-when-compile 3680 (looking-at (eval-when-compile
3448 (concat "\\<\\(" 3681 (concat "\\<\\("
3449 "procedure\\|function\\|body\\|" 3682 "procedure\\|function\\|body\\|"
3450 "task\\|entry\\|accept\\|" 3683 "task\\|entry\\|accept\\|"
3451 "access[ \t]+procedure\\|" 3684 "access[ \t]+procedure\\|"
3452 "access[ \t]+function\\|" 3685 "access[ \t]+function\\|"
3453 "pragma\\|" 3686 "pragma\\|"
3454 "type\\)\\>")))))) 3687 "type\\)\\>"))))))
3688
3689 (defun ada-search-ignore-complex-boolean (regexp backwardp)
3690 "Like `ada-search-ignore-string-comment', except that it also ignores
3691 boolean expressions 'and then' and 'or else'."
3692 (let (result)
3693 (while (and (set 'result (ada-search-ignore-string-comment regexp backwardp))
3694 (save-excursion (forward-word -1)
3695 (looking-at "and then\\|or else"))))
3696 result))
3455 3697
3456 (defun ada-in-open-paren-p () 3698 (defun ada-in-open-paren-p ()
3457 "Returns the position of the first non-ws behind the last unclosed 3699 "Returns the position of the first non-ws behind the last unclosed
3458 parenthesis, or nil." 3700 parenthesis, or nil."
3459 (save-excursion 3701 (save-excursion
3460 (let ((parse (parse-partial-sexp 3702 (let ((parse (parse-partial-sexp
3461 (point) 3703 (point)
3462 (or (car (ada-search-ignore-string-comment 3704 (or (car (ada-search-ignore-complex-boolean
3463 "\\<\\(;\\|is\\|then\\|loop\\|begin\\|else\\)\\>" 3705 "\\<\\(;\\|is\\|then\\|loop\\|begin\\|else\\)\\>"
3464 t)) 3706 t))
3465 (point-min))))) 3707 (point-min)))))
3466 3708
3467 (if (nth 1 parse) 3709 (if (nth 1 parse)
3468 (progn 3710 (progn
3469 (goto-char (1+ (nth 1 parse))) 3711 (goto-char (1+ (nth 1 parse)))
3470 (skip-chars-forward " \t") 3712 (skip-chars-forward " \t")
3471 (point)))))) 3713 (point))))))
3472 3714
3473 3715
3474 ;;;----------------------------------------------------------- 3716 ;; -----------------------------------------------------------
3475 ;;; Behavior Of TAB Key 3717 ;; -- Behavior Of TAB Key
3476 ;;;----------------------------------------------------------- 3718 ;; -----------------------------------------------------------
3477 3719
3478 (defun ada-tab () 3720 (defun ada-tab ()
3479 "Do indenting or tabbing according to `ada-tab-policy'. 3721 "Do indenting or tabbing according to `ada-tab-policy'.
3480 In Transient Mark mode, if the mark is active, operate on the contents 3722 In Transient Mark mode, if the mark is active, operate on the contents
3481 of the region. Otherwise, operates only on the current line." 3723 of the region. Otherwise, operates only on the current line."
3482 (interactive) 3724 (interactive)
3483 (cond ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard)) 3725 (cond ((eq ada-tab-policy 'indent-rigidly) (ada-tab-hard))
3484 ((eq ada-tab-policy 'indent-auto) 3726 ((eq ada-tab-policy 'indent-auto)
3485 ;; transient-mark-mode and mark-active are not defined in XEmacs 3727 ;; transient-mark-mode and mark-active are not defined in XEmacs
3486 (if (or (and ada-xemacs (region-active-p)) 3728 (if (or (and ada-xemacs (funcall (symbol-function 'region-active-p)))
3487 (and (not ada-xemacs) 3729 (and (not ada-xemacs)
3488 transient-mark-mode 3730 (symbol-value 'transient-mark-mode)
3489 mark-active)) 3731 (symbol-value 'mark-active)))
3490 (ada-indent-region (region-beginning) (region-end)) 3732 (ada-indent-region (region-beginning) (region-end))
3491 (ada-indent-current))) 3733 (ada-indent-current)))
3492 ((eq ada-tab-policy 'always-tab) (error "not implemented")) 3734 ((eq ada-tab-policy 'always-tab) (error "not implemented"))
3493 )) 3735 ))
3494 3736
3542 (widen) 3784 (widen)
3543 (goto-char (point-min)) 3785 (goto-char (point-min))
3544 (while (re-search-forward "[ \t]+$" (point-max) t) 3786 (while (re-search-forward "[ \t]+$" (point-max) t)
3545 (replace-match "" nil nil)))))) 3787 (replace-match "" nil nil))))))
3546 3788
3547 (defun ada-ff-other-window ()
3548 "Find other file in other window using `ff-find-other-file'."
3549 (interactive)
3550 (and (fboundp 'ff-find-other-file)
3551 (ff-find-other-file t)))
3552
3553 (defun ada-gnat-style () 3789 (defun ada-gnat-style ()
3554 "Clean up comments, `(' and `,' for GNAT style checking switch." 3790 "Clean up comments, `(' and `,' for GNAT style checking switch."
3555 (interactive) 3791 (interactive)
3556 (save-excursion 3792 (save-excursion
3557 (goto-char (point-min)) 3793 (goto-char (point-min))
3558 (while (re-search-forward "-- ?\\([^ -]\\)" nil t) 3794 (while (re-search-forward "--[ \t]*\\([^-]\\)" nil t)
3559 (replace-match "-- \\1")) 3795 (replace-match "-- \\1"))
3560 (goto-char (point-min)) 3796 (goto-char (point-min))
3561 (while (re-search-forward "\\>(" nil t) 3797 (while (re-search-forward "\\>(" nil t)
3562 (replace-match " (")) 3798 (replace-match " ("))
3563 (goto-char (point-min)) 3799 (goto-char (point-min))
3800 (while (re-search-forward "([ \t]+" nil t)
3801 (replace-match "("))
3802 (goto-char (point-min))
3803 (while (re-search-forward ")[ \t]+)" nil t)
3804 (replace-match "))"))
3805 (goto-char (point-min))
3806 (while (re-search-forward "\\>:" nil t)
3807 (replace-match " :"))
3808 (goto-char (point-min))
3564 (while (re-search-forward ",\\<" nil t) 3809 (while (re-search-forward ",\\<" nil t)
3565 (replace-match ", ")) 3810 (replace-match ", "))
3811 (goto-char (point-min))
3812 (while (re-search-forward "[ \t]*\\.\\.[ \t]*" nil t)
3813 (replace-match " .. "))
3814 (goto-char (point-min))
3815 (while (re-search-forward "[ \t]*\\([-:+*/]\\)[ \t]*" nil t)
3816 (if (not (ada-in-string-or-comment-p))
3817 (progn
3818 (forward-char -1)
3819 (cond
3820 ((looking-at "/=")
3821 (replace-match " /= "))
3822 ((looking-at ":=")
3823 (replace-match ":= "))
3824 ((not (looking-at "--"))
3825 (replace-match " \\1 ")))
3826 (forward-char 2))))
3566 )) 3827 ))
3567 3828
3568 3829
3569 3830
3570 ;; ------------------------------------------------------------- 3831 ;; -------------------------------------------------------------
3571 ;; -- Moving To Procedures/Packages 3832 ;; -- Moving To Procedures/Packages/Statements
3572 ;; ------------------------------------------------------------- 3833 ;; -------------------------------------------------------------
3834
3835 (defun ada-move-to-start ()
3836 "Moves point to the matching start of the current Ada structure."
3837 (interactive)
3838 (let ((pos (point))
3839 (previous-syntax-table (syntax-table)))
3840 (unwind-protect
3841 (progn
3842 (set-syntax-table ada-mode-symbol-syntax-table)
3843
3844 (message "searching for block start ...")
3845 (save-excursion
3846 ;;
3847 ;; do nothing if in string or comment or not on 'end ...;'
3848 ;; or if an error occurs during processing
3849 ;;
3850 (or
3851 (ada-in-string-or-comment-p)
3852 (and (progn
3853 (or (looking-at "[ \t]*\\<end\\>")
3854 (backward-word 1))
3855 (or (looking-at "[ \t]*\\<end\\>")
3856 (backward-word 1))
3857 (or (looking-at "[ \t]*\\<end\\>")
3858 (error "not on end ...;")))
3859 (ada-goto-matching-start 1)
3860 (set 'pos (point))
3861
3862 ;;
3863 ;; on 'begin' => go on, according to user option
3864 ;;
3865 ada-move-to-declaration
3866 (looking-at "\\<begin\\>")
3867 (ada-goto-matching-decl-start)
3868 (set 'pos (point))))
3869
3870 ) ; end of save-excursion
3871
3872 ;; now really move to the found position
3873 (goto-char pos)
3874 (message "searching for block start ... done"))
3875
3876 ;; restore syntax-table
3877 (set-syntax-table previous-syntax-table))))
3878
3879 (defun ada-move-to-end ()
3880 "Moves point to the matching end of the block around point.
3881 Moves to 'begin' if in a declarative part."
3882 (interactive)
3883 (let ((pos (point))
3884 (previous-syntax-table (syntax-table)))
3885 (unwind-protect
3886 (progn
3887 (set-syntax-table ada-mode-symbol-syntax-table)
3888
3889 (message "searching for block end ...")
3890 (save-excursion
3891
3892 (forward-char 1)
3893 (cond
3894 ;; directly on 'begin'
3895 ((save-excursion
3896 (ada-goto-previous-word)
3897 (looking-at "\\<begin\\>"))
3898 (ada-goto-matching-end 1))
3899 ;; on first line of defun declaration
3900 ((save-excursion
3901 (and (ada-goto-stmt-start)
3902 (looking-at "\\<function\\>\\|\\<procedure\\>" )))
3903 (ada-search-ignore-string-comment "begin" nil nil nil
3904 'word-search-forward))
3905 ;; on first line of task declaration
3906 ((save-excursion
3907 (and (ada-goto-stmt-start)
3908 (looking-at "\\<task\\>" )
3909 (forward-word 1)
3910 (ada-goto-next-non-ws)
3911 (looking-at "\\<body\\>")))
3912 (ada-search-ignore-string-comment "begin" nil nil nil
3913 'word-search-forward))
3914 ;; accept block start
3915 ((save-excursion
3916 (and (ada-goto-stmt-start)
3917 (looking-at "\\<accept\\>" )))
3918 (ada-goto-matching-end 0))
3919 ;; package start
3920 ((save-excursion
3921 (and (ada-goto-matching-decl-start t)
3922 (looking-at "\\<package\\>")))
3923 (ada-goto-matching-end 1))
3924 ;; inside a 'begin' ... 'end' block
3925 ((save-excursion
3926 (ada-goto-matching-decl-start t))
3927 (ada-search-ignore-string-comment "begin" nil nil nil
3928 'word-search-forward))
3929 ;; (hopefully ;-) everything else
3930 (t
3931 (ada-goto-matching-end 1)))
3932 (set 'pos (point))
3933 )
3934
3935 ;; now really move to the position found
3936 (goto-char pos)
3937 (message "searching for block end ... done"))
3938
3939 ;; restore syntax-table
3940 (set-syntax-table previous-syntax-table))))
3573 3941
3574 (defun ada-next-procedure () 3942 (defun ada-next-procedure ()
3575 "Moves point to next procedure." 3943 "Moves point to next procedure."
3576 (interactive) 3944 (interactive)
3577 (end-of-line) 3945 (end-of-line)
3636 ;; Casing 4004 ;; Casing
3637 (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer) 4005 (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer)
3638 (define-key ada-mode-map "\C-c\C-t" 'ada-case-read-exceptions) 4006 (define-key ada-mode-map "\C-c\C-t" 'ada-case-read-exceptions)
3639 (define-key ada-mode-map "\C-c\C-y" 'ada-create-case-exception) 4007 (define-key ada-mode-map "\C-c\C-y" 'ada-create-case-exception)
3640 4008
3641 (define-key ada-mode-map "\177" 'backward-delete-char-untabify) 4009 ;; On XEmacs, you can easily specify whether DEL should deletes
4010 ;; one character forward or one character backward. Take this into
4011 ;; account
4012 (if (boundp 'delete-key-deletes-forward)
4013 (define-key ada-mode-map [backspace] 'backward-delete-char-untabify)
4014 (define-key ada-mode-map "\177" 'backward-delete-char-untabify))
3642 4015
3643 ;; Make body 4016 ;; Make body
3644 (define-key ada-mode-map "\C-c\C-n" 'ada-make-subprogram-body) 4017 (define-key ada-mode-map "\C-c\C-n" 'ada-make-subprogram-body)
3645 4018
3646 ;; Use predefined function of Emacs19 for comments (RE) 4019 ;; Use predefined function of Emacs19 for comments (RE)
3651 4024
3652 (defun ada-create-menu () 4025 (defun ada-create-menu ()
3653 "Create the ada menu as shown in the menu bar. 4026 "Create the ada menu as shown in the menu bar.
3654 This function is designed to be extensible, so that each compiler-specific file 4027 This function is designed to be extensible, so that each compiler-specific file
3655 can add its own items." 4028 can add its own items."
3656
3657 ;; Note that the separators must have different length in the submenus 4029 ;; Note that the separators must have different length in the submenus
3658 (autoload 'easy-menu-define "easymenu") 4030 (autoload 'easy-menu-define "easymenu")
3659 (autoload 'imenu "imenu") 4031
3660 (easy-menu-define 4032 (let ((m '("Ada"
3661 ada-mode-menu ada-mode-map "Menu keymap for Ada mode" 4033 ("Help" ["Ada Mode" (info "ada-mode") t])))
3662 '("Ada" 4034 (option '(["Auto Casing" (setq ada-auto-case (not ada-auto-case))
3663 ("Help" 4035 :style toggle :selected ada-auto-case]
3664 ["Ada Mode" (info "ada-mode") t]) 4036 ["Auto Indent After Return"
3665 ["Customize" (customize-group 'ada) (>= emacs-major-version 20)] 4037 (setq ada-indent-after-return (not ada-indent-after-return))
3666 ("Goto" 4038 :style toggle :selected ada-indent-after-return]))
3667 ["Next compilation error" next-error t] 4039 (goto '(["Next compilation error" next-error t]
3668 ["Previous Package" ada-previous-package t] 4040 ["Previous Package" ada-previous-package t]
3669 ["Next Package" ada-next-package t] 4041 ["Next Package" ada-next-package t]
3670 ["Previous Procedure" ada-previous-procedure t] 4042 ["Previous Procedure" ada-previous-procedure t]
3671 ["Next Procedure" ada-next-procedure t] 4043 ["Next Procedure" ada-next-procedure t]
3672 ["Goto Start Of Statement" ada-move-to-start t] 4044 ["Goto Start Of Statement" ada-move-to-start t]
3673 ["Goto End Of Statement" ada-move-to-end t] 4045 ["Goto End Of Statement" ada-move-to-end t]
3674 ["-" nil nil] 4046 ["-" nil nil]
3675 ["Other File" ff-find-other-file t] 4047 ["Other File" ff-find-other-file t]
3676 ["Other File Other Window" ada-ff-other-window t]) 4048 ["Other File Other Window" ada-ff-other-window t]))
3677 ("Edit" 4049 (edit '(["Indent Line" ada-indent-current-function t]
3678 ["Indent Line" ada-indent-current-function t] 4050 ["Justify Current Indentation" ada-justified-indent-current t]
3679 ["Justify Current Indentation" ada-justified-indent-current t] 4051 ["Indent Lines in Selection" ada-indent-region t]
3680 ["Indent Lines in Selection" ada-indent-region t] 4052 ["Indent Lines in File" (ada-indent-region (point-min) (point-max)) t]
3681 ["Indent Lines in File" (ada-indent-region (point-min) (point-max)) t] 4053 ["Format Parameter List" ada-format-paramlist t]
3682 ["Format Parameter List" ada-format-paramlist t] 4054 ["-" nil nil]
3683 ["-" nil nil] 4055 ["Comment Selection" comment-region t]
3684 ["Comment Selection" comment-region t] 4056 ["Uncomment Selection" ada-uncomment-region t]
3685 ["Uncomment Selection" ada-uncomment-region t] 4057 ["--" nil nil]
3686 ["--" nil nil] 4058 ["Fill Comment Paragraph" fill-paragraph t]
3687 ["Fill Comment Paragraph" fill-paragraph t] 4059 ["Fill Comment Paragraph Justify" ada-fill-comment-paragraph-justify t]
3688 ["Fill Comment Paragraph Justify" ada-fill-comment-paragraph-justify t] 4060 ["Fill Comment Paragraph Postfix" ada-fill-comment-paragraph-postfix t]
3689 ["Fill Comment Paragraph Postfix" ada-fill-comment-paragraph-postfix t] 4061 ["---" nil nil]
3690 ["---" nil nil] 4062 ["Adjust Case Selection" ada-adjust-case-region t]
3691 ["Adjust Case Selection" ada-adjust-case-region t] 4063 ["Adjust Case Buffer" ada-adjust-case-buffer t]
3692 ["Adjust Case Buffer" ada-adjust-case-buffer t] 4064 ["Create Case Exception" ada-create-case-exception t]
3693 ["Create Case Exception" ada-create-case-exception t] 4065 ["Reload Case Exceptions" ada-case-read-exceptions t]
3694 ["Reload Case Exceptions" ada-case-read-exceptions t] 4066 ["----" nil nil]
3695 ["----" nil nil] 4067 ["Make body for subprogram" ada-make-subprogram-body t]))
3696 ["Make body for subprogram" ada-make-subprogram-body t] 4068
4069 )
4070
4071 ;; Option menu present only if in Ada mode
4072 (set 'm (append m (list (append (list "Options"
4073 (if ada-xemacs :included :visible)
4074 '(string= mode-name "Ada"))
4075 option))))
4076
4077 ;; Customize menu always present
4078 (set 'm (append m '(["Customize" (customize-group 'ada)
4079 (>= emacs-major-version 20)])))
4080
4081 ;; Goto and Edit menus present only if in Ada mode
4082 (set 'm (append m (list (append (list "Goto"
4083 (if ada-xemacs :included :visible)
4084 '(string= mode-name "Ada"))
4085 goto)
4086 (append (list "Edit"
4087 (if ada-xemacs :included :visible)
4088 '(string= mode-name "Ada"))
4089 edit))))
4090
4091 (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode" m)
4092 (if ada-xemacs
4093 (progn
4094 (easy-menu-add ada-mode-menu ada-mode-map)
4095 (define-key ada-mode-map [menu-bar] ada-mode-menu)
4096 (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu)))
3697 ) 4097 )
3698 ["Index" imenu t] 4098 ))
3699 ))
3700
3701 (if ada-xemacs
3702 (progn
3703 (easy-menu-add ada-mode-menu ada-mode-map)
3704 (define-key ada-mode-map [menu-bar] ada-mode-menu)
3705 (set 'mode-popup-menu (cons "Ada mode" ada-mode-menu))
3706 )
3707 )
3708 )
3709 4099
3710 4100
3711 ;; ------------------------------------------------------- 4101 ;; -------------------------------------------------------
3712 ;; Commenting/Uncommenting code 4102 ;; Commenting/Uncommenting code
3713 ;; The two following calls are provided to enhance the standard 4103 ;; The following two calls are provided to enhance the standard
3714 ;; comment-region function, which only allows uncommenting if the 4104 ;; comment-region function, which only allows uncommenting if the
3715 ;; comment is at the beginning of a line. If the line have been re-indented, 4105 ;; comment is at the beginning of a line. If the line have been re-indented,
3716 ;; we are unable to use comment-region, which makes no sense. 4106 ;; we are unable to use comment-region, which makes no sense.
3717 ;; 4107 ;;
3718 ;; In addition, we provide an interface to the standard comment handling 4108 ;; In addition, we provide an interface to the standard comment handling
3731 )))) 4121 ))))
3732 4122
3733 (defun ada-uncomment-region (beg end &optional arg) 4123 (defun ada-uncomment-region (beg end &optional arg)
3734 "Delete `comment-start' at the beginning of a line in the region." 4124 "Delete `comment-start' at the beginning of a line in the region."
3735 (interactive "r\nP") 4125 (interactive "r\nP")
3736 (ad-activate 'comment-region) 4126
3737 (comment-region beg end (- (or arg 1))) 4127 ;; This advice is not needed anymore with Emacs21. However, for older
3738 (ad-deactivate 'comment-region)) 4128 ;; versions, as well as for XEmacs, we still need to enable it.
4129 (if (or (<= emacs-major-version 20) (boundp 'running-xemacs))
4130 (progn
4131 (ad-activate 'comment-region)
4132 (comment-region beg end (- (or arg 1)))
4133 (ad-deactivate 'comment-region))
4134 (comment-region beg end (list (- (or arg 1))))))
3739 4135
3740 (defun ada-fill-comment-paragraph-justify () 4136 (defun ada-fill-comment-paragraph-justify ()
3741 "Fills current comment paragraph and justifies each line as well." 4137 "Fills current comment paragraph and justifies each line as well."
3742 (interactive) 4138 (interactive)
3743 (ada-fill-comment-paragraph 'full)) 4139 (ada-fill-comment-paragraph 'full))
3764 (let* ((indent) 4160 (let* ((indent)
3765 (from) 4161 (from)
3766 (to) 4162 (to)
3767 (opos (point-marker)) 4163 (opos (point-marker))
3768 4164
3769 ;; Sets this variable to nil, otherwise it prevents 4165 ;; Sets this variable to nil, otherwise it prevents
3770 ;; fill-region-as-paragraph to work on Emacs <= 20.2 4166 ;; fill-region-as-paragraph to work on Emacs <= 20.2
3771 (parse-sexp-lookup-properties nil) 4167 (parse-sexp-lookup-properties nil)
3772 4168
3773 fill-prefix 4169 fill-prefix
3774 (fill-column (current-fill-column))) 4170 (fill-column (current-fill-column)))
3775 4171
3776 ;; Find end of paragraph 4172 ;; Find end of paragraph
3777 (back-to-indentation) 4173 (back-to-indentation)
3778 (while (and (not (eobp)) (looking-at "--[ \t]*[^ \t\n]")) 4174 (while (and (not (eobp)) (looking-at "--[ \t]*[^ \t\n]"))
3779 (forward-line 1) 4175 (forward-line 1)
3780 (back-to-indentation)) 4176
4177 ;; If we were at the last line in the buffer, create a dummy empty
4178 ;; line at the end of the buffer.
4179 (if (eolp)
4180 (insert "\n")
4181 (back-to-indentation)))
3781 (beginning-of-line) 4182 (beginning-of-line)
3782 (set 'to (point-marker)) 4183 (set 'to (point-marker))
3783 (goto-char opos) 4184 (goto-char opos)
3784 4185
3785 ;; Find beginning of paragraph 4186 ;; Find beginning of paragraph
3786 (back-to-indentation) 4187 (back-to-indentation)
3787 (while (and (not (bobp)) (looking-at "--[ \t]*[^ \t\n]")) 4188 (while (and (not (bobp)) (looking-at "--[ \t]*[^ \t\n]"))
3788 (forward-line -1) 4189 (forward-line -1)
3789 (back-to-indentation)) 4190 (back-to-indentation))
3790 (forward-line 1) 4191
4192 ;; We want one line to above the first one, unless we are at the beginning
4193 ;; of the buffer
4194 (unless (bobp)
4195 (forward-line 1))
3791 (beginning-of-line) 4196 (beginning-of-line)
3792 (set 'from (point-marker)) 4197 (set 'from (point-marker))
3793 4198
3794 ;; Calculate the indentation we will need for the paragraph 4199 ;; Calculate the indentation we will need for the paragraph
3795 (back-to-indentation) 4200 (back-to-indentation)
3797 ;; unindent the first line of the paragraph 4202 ;; unindent the first line of the paragraph
3798 (delete-region from (point)) 4203 (delete-region from (point))
3799 4204
3800 ;; Remove the old postfixes 4205 ;; Remove the old postfixes
3801 (goto-char from) 4206 (goto-char from)
3802 (while (re-search-forward (concat ada-fill-comment-postfix "\n") to t) 4207 (while (re-search-forward "--\n" to t)
3803 (replace-match "\n")) 4208 (replace-match "\n"))
3804 4209
4210 ;; Remove the old prefixes (so that the number of spaces after -- is not
4211 ;; relevant), except on the first one since `fill-region-as-paragraph'
4212 ;; would not put it back on the first line.
4213 (goto-char (+ from 2))
4214 (while (re-search-forward "^-- *" to t)
4215 (replace-match " "))
4216
3805 (goto-char (1- to)) 4217 (goto-char (1- to))
3806 (set 'to (point-marker)) 4218 (set 'to (point-marker))
3807 4219
3808 ;; Indent and justify the paragraph 4220 ;; Indent and justify the paragraph
3809 (set 'fill-prefix ada-fill-comment-prefix) 4221 (set 'fill-prefix ada-fill-comment-prefix)
3835 (goto-char to) 4247 (goto-char to)
3836 (end-of-line) 4248 (end-of-line)
3837 (delete-char 1))) 4249 (delete-char 1)))
3838 4250
3839 (goto-char opos))) 4251 (goto-char opos)))
4252
3840 4253
3841 ;; --------------------------------------------------- 4254 ;; ---------------------------------------------------
3842 ;; support for find-file.el 4255 ;; support for find-file.el
3843 ;; These functions are used by find-file to guess the file names from 4256 ;; These functions are used by find-file to guess the file names from
3844 ;; unit names, and to find the other file (spec or body) from the current 4257 ;; unit names, and to find the other file (spec or body) from the current
3855 (defun ada-make-filename-from-adaname (adaname) 4268 (defun ada-make-filename-from-adaname (adaname)
3856 "Determine the filename in which ADANAME is found. 4269 "Determine the filename in which ADANAME is found.
3857 This is a generic function, independent from any compiler." 4270 This is a generic function, independent from any compiler."
3858 (while (string-match "\\." adaname) 4271 (while (string-match "\\." adaname)
3859 (set 'adaname (replace-match "-" t t adaname))) 4272 (set 'adaname (replace-match "-" t t adaname)))
3860 adaname 4273 (downcase adaname)
3861 ) 4274 )
3862 4275
3863 (defun ada-other-file-name () 4276 (defun ada-other-file-name ()
3864 "Return the name of the other file (the body if current-buffer is the spec, 4277 "Return the name of the other file.
3865 or the spec otherwise." 4278 The name returned is the body if current-buffer is the spec, or the spec
3866 (let ((ff-always-try-to-create nil) 4279 otherwise."
3867 (buffer (current-buffer)) 4280
3868 name) 4281 (let ((is-spec nil)
3869 (ff-find-other-file nil t) ;; same window, ignore 'with' lines 4282 (is-body nil)
3870 4283 (suffixes ada-spec-suffixes)
3871 ;; If the other file was not found, return an empty string 4284 (name (buffer-file-name)))
3872 (if (equal buffer (current-buffer)) 4285
3873 "" 4286 ;; Guess whether we have a spec or a body, and get the basename of the
3874 (set 'name (buffer-file-name)) 4287 ;; file. Since the extension may not start with '.', we can not use
3875 (switch-to-buffer buffer) 4288 ;; file-name-extension
3876 name))) 4289 (while (and (not is-spec)
4290 suffixes)
4291 (if (string-match (concat "\\(.*\\)" (car suffixes) "$") name)
4292 (setq is-spec t
4293 name (match-string 1 name)))
4294 (set 'suffixes (cdr suffixes)))
4295
4296 (if (not is-spec)
4297 (progn
4298 (set 'suffixes ada-body-suffixes)
4299 (while (and (not is-body)
4300 suffixes)
4301 (if (string-match (concat "\\(.*\\)" (car suffixes) "$") name)
4302 (setq is-body t
4303 name (match-string 1 name)))
4304 (set 'suffixes (cdr suffixes)))))
4305
4306 ;; If this wasn't in either list, return name itself
4307 (if (not (or is-spec is-body))
4308 name
4309
4310 ;; Else find the other possible names
4311 (if is-spec
4312 (set 'suffixes ada-body-suffixes)
4313 (set 'suffixes ada-spec-suffixes))
4314 (set 'is-spec name)
4315
4316 (while suffixes
4317 (if (file-exists-p (concat name (car suffixes)))
4318 (set 'is-spec (concat name (car suffixes))))
4319 (set 'suffixes (cdr suffixes)))
4320
4321 is-spec)))
3877 4322
3878 (defun ada-which-function-are-we-in () 4323 (defun ada-which-function-are-we-in ()
3879 "Return the name of the function whose definition/declaration point is in. 4324 "Return the name of the function whose definition/declaration point is in.
3880 Redefines the function `ff-which-function-are-we-in'." 4325 Redefines the function `ff-which-function-are-we-in'."
3881 (set 'ff-function-name nil) 4326 (set 'ff-function-name nil)
3882 (save-excursion 4327 (save-excursion
3883 (end-of-line) ;; make sure we get the complete name 4328 (end-of-line);; make sure we get the complete name
3884 (if (or (re-search-backward ada-procedure-start-regexp nil t) 4329 (if (or (re-search-backward ada-procedure-start-regexp nil t)
3885 (re-search-backward ada-package-start-regexp nil t)) 4330 (re-search-backward ada-package-start-regexp nil t))
3886 (set 'ff-function-name (match-string 0))) 4331 (set 'ff-function-name (match-string 0)))
3887 )) 4332 ))
4333
4334
4335 (defvar ada-last-which-function-line -1
4336 "Last on which ada-which-function was called")
4337 (defvar ada-last-which-function-subprog 0
4338 "Last subprogram name returned by ada-which-function")
4339 (make-variable-buffer-local 'ada-last-which-function-subprog)
4340 (make-variable-buffer-local 'ada-last-which-function-line)
4341
4342
4343 (defun ada-which-function ()
4344 "Returns the name of the function whose body the point is in.
4345 This function works even in the case of nested subprograms, whereas the
4346 standard Emacs function which-function does not.
4347 Note that this function expects subprogram bodies to be terminated by
4348 'end <name>;', not 'end;'.
4349 Since the search can be long, the results are cached."
4350
4351 (let ((line (count-lines (point-min) (point)))
4352 (pos (point))
4353 end-pos
4354 func-name
4355 found)
4356
4357 ;; If this is the same line as before, simply return the same result
4358 (if (= line ada-last-which-function-line)
4359 ada-last-which-function-subprog
4360
4361 (save-excursion
4362 ;; In case the current line is also the beginning of the body
4363 (end-of-line)
4364 (while (and (ada-in-paramlist-p)
4365 (= (forward-line 1) 0))
4366 (end-of-line))
4367
4368 ;; Can't simply do forward-word, in case the "is" is not on the
4369 ;; same line as the closing parenthesis
4370 (skip-chars-forward "is \t\n")
4371
4372 ;; No look for the closest subprogram body that has not ended yet.
4373 ;; Not that we expect all the bodies to be finished by "end <name",
4374 ;; not simply "end"
4375
4376 (while (and (not found)
4377 (re-search-backward ada-imenu-subprogram-menu-re nil t))
4378 (set 'func-name (match-string 2))
4379 (if (and (not (ada-in-comment-p))
4380 (not (save-excursion
4381 (goto-char (match-end 0))
4382 (looking-at "[ \t\n]*new"))))
4383 (save-excursion
4384 (if (ada-search-ignore-string-comment
4385 (concat "end[ \t]+" func-name "[ \t]*;"))
4386 (set 'end-pos (point))
4387 (set 'end-pos (point-max)))
4388 (if (>= end-pos pos)
4389 (set 'found func-name))))
4390 )
4391 (setq ada-last-which-function-line line
4392 ada-last-which-function-subprog found)
4393 found))))
4394
4395 (defun ada-ff-other-window ()
4396 "Find other file in other window using `ff-find-other-file'."
4397 (interactive)
4398 (and (fboundp 'ff-find-other-file)
4399 (ff-find-other-file t)))
3888 4400
3889 (defun ada-set-point-accordingly () 4401 (defun ada-set-point-accordingly ()
3890 "Move to the function declaration that was set by 4402 "Move to the function declaration that was set by
3891 `ff-which-function-are-we-in'." 4403 `ff-which-function-are-we-in'."
3892 (if ff-function-name 4404 (if ff-function-name
3893 (progn 4405 (progn
3894 (goto-char (point-min)) 4406 (goto-char (point-min))
3895 (unless (ada-search-ignore-string-comment 4407 (unless (ada-search-ignore-string-comment
3896 (concat ff-function-name "\\b") nil) 4408 (concat ff-function-name "\\b") nil)
3897 (goto-char (point-min)))))) 4409 (goto-char (point-min))))))
4410
4411 (defun ada-get-body-name (&optional spec-name)
4412 "Returns the file name for the body of SPEC-NAME.
4413 If SPEC-NAME is nil, returns the body for the current package.
4414 Returns nil if no body was found."
4415 (interactive)
4416
4417 (unless spec-name (set 'spec-name (buffer-file-name)))
4418
4419 ;; If find-file.el was available, use its functions
4420 (if (functionp 'ff-get-file)
4421 (ff-get-file-name ada-search-directories
4422 (ada-make-filename-from-adaname
4423 (file-name-nondirectory
4424 (file-name-sans-extension spec-name)))
4425 ada-body-suffixes)
4426 ;; Else emulate it very simply
4427 (concat (ada-make-filename-from-adaname
4428 (file-name-nondirectory
4429 (file-name-sans-extension spec-name)))
4430 ".adb")))
3898 4431
3899 4432
3900 ;; --------------------------------------------------- 4433 ;; ---------------------------------------------------
3901 ;; support for font-lock.el 4434 ;; support for font-lock.el
3902 ;; Strings are a real pain in Ada because a single quote character is 4435 ;; Strings are a real pain in Ada because a single quote character is
3993 ;; 4526 ;;
3994 ;; Goto tags. 4527 ;; Goto tags.
3995 '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face) 4528 '("<<\\(\\sw+\\)>>" 1 font-lock-reference-face)
3996 )) 4529 ))
3997 "Default expressions to highlight in Ada mode.") 4530 "Default expressions to highlight in Ada mode.")
4531
3998 4532
3999 ;; --------------------------------------------------------- 4533 ;; ---------------------------------------------------------
4000 ;; Support for outline.el 4534 ;; Support for outline.el
4001 ;; --------------------------------------------------------- 4535 ;; ---------------------------------------------------------
4002 4536
4119 (if (looking-at ada-package-start-regexp) 4653 (if (looking-at ada-package-start-regexp)
4120 (progn (goto-char (cdr found)) 4654 (progn (goto-char (cdr found))
4121 (insert " body")) 4655 (insert " body"))
4122 (ada-gen-treat-proc found)))))) 4656 (ada-gen-treat-proc found))))))
4123 4657
4658
4124 (defun ada-make-subprogram-body () 4659 (defun ada-make-subprogram-body ()
4125 "Make one dummy subprogram body from spec surrounding point." 4660 "Make one dummy subprogram body from spec surrounding point."
4126 (interactive) 4661 (interactive)
4127 (let* ((found (re-search-backward ada-procedure-start-regexp nil t)) 4662 (let* ((found (re-search-backward ada-procedure-start-regexp nil t))
4128 (spec (match-beginning 0))) 4663 (spec (match-beginning 0))
4664 body-file)
4129 (if found 4665 (if found
4130 (progn 4666 (progn
4131 (goto-char spec) 4667 (goto-char spec)
4132 (if (and (re-search-forward "(\\|;" nil t) 4668 (if (and (re-search-forward "(\\|;" nil t)
4133 (= (char-before) ?\()) 4669 (= (char-before) ?\())
4134 (progn 4670 (progn
4135 (ada-search-ignore-string-comment ")" nil) 4671 (ada-search-ignore-string-comment ")" nil)
4136 (ada-search-ignore-string-comment ";" nil))) 4672 (ada-search-ignore-string-comment ";" nil)))
4137 (set 'spec (buffer-substring spec (point))) 4673 (set 'spec (buffer-substring spec (point)))
4138 4674
4139 ;; If find-file.el was available, use its functions 4675 ;; If find-file.el was available, use its functions
4140 (if (functionp 'ff-get-file) 4676 (set 'body-file (ada-get-body-name))
4141 (find-file (ff-get-file 4677 (if body-file
4142 ff-search-directories 4678 (find-file body-file)
4143 (ada-make-filename-from-adaname 4679 (error "No body found for the package. Create it first."))
4144 (file-name-nondirectory 4680
4145 (file-name-sans-extension (buffer-name))))
4146 ada-body-suffixes))
4147 ;; Else emulate it very simply
4148 (find-file (concat (ada-make-filename-from-adaname
4149 (file-name-nondirectory
4150 (file-name-sans-extension (buffer-name))))
4151 ".adb")))
4152
4153 (save-restriction 4681 (save-restriction
4154 (widen) 4682 (widen)
4155 (goto-char (point-max)) 4683 (goto-char (point-max))
4156 (forward-comment -10000) 4684 (forward-comment -10000)
4157 (re-search-backward "\\<end\\>" nil t) 4685 (re-search-backward "\\<end\\>" nil t)
4186 4714
4187 ;; Read the special cases for exceptions 4715 ;; Read the special cases for exceptions
4188 (ada-case-read-exceptions) 4716 (ada-case-read-exceptions)
4189 4717
4190 ;; include the other ada-mode files 4718 ;; include the other ada-mode files
4191
4192 (if (equal ada-which-compiler 'gnat) 4719 (if (equal ada-which-compiler 'gnat)
4193 (progn 4720 (progn
4194 ;; The order here is important: ada-xref defines the Project 4721 ;; The order here is important: ada-xref defines the Project
4195 ;; submenu, and ada-prj adds to it. 4722 ;; submenu, and ada-prj adds to it.
4723 (require 'ada-xref)
4196 (condition-case nil (require 'ada-prj) (error nil)) 4724 (condition-case nil (require 'ada-prj) (error nil))
4197 (require 'ada-xref)
4198 )) 4725 ))
4199 (condition-case nil (require 'ada-stmt) (error nil)) 4726 (condition-case nil (require 'ada-stmt) (error nil))
4200 4727
4201 ;;; provide ourselves 4728 ;;; provide ourselves
4202 (provide 'ada-mode) 4729 (provide 'ada-mode)