Mercurial > hg > xemacs-beta
diff lisp/modes/ada-mode.el @ 189:489f57a838ef r20-3b21
Import from CVS: tag r20-3b21
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:57:07 +0200 |
parents | 28f395d8dc7a |
children |
line wrap: on
line diff
--- a/lisp/modes/ada-mode.el Mon Aug 13 09:56:30 2007 +0200 +++ b/lisp/modes/ada-mode.el Mon Aug 13 09:57:07 2007 +0200 @@ -1,35 +1,38 @@ ;;; ada-mode.el --- An Emacs major-mode for editing Ada source. -;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc. - -;;; Authors: Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de> -;;; Rolf Ebert <ebert@inf.enst.fr> - -;;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by + +;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. + +;; Authors: Rolf Ebert <ebert@inf.enst.fr> +;; Markus Heritsch <Markus.Heritsch@studbox.uni-stuttgart.de> +;; Keywords: languages oop ada +;; Rolf Ebert's version: 2.27 + +;; This file is part of XEmacs + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. -;; XEmacs is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. +;; XEmacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. +;; along with XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;;; This mode is a complete rewrite of a major mode for editing Ada 83 ;;; and Ada 95 source code under Emacs-19. It contains completely new ;;; indenting code and support for code browsing (see ada-xref). -;;; Synched up with: FSF 19.34. +;;; Synched up with: FSF 20.1 ;;; USAGE ;;; ===== -;;; Emacs should enter ada-mode when you load an ada source (*.ad[abs]). +;;; Emacs should enter Ada mode when you load an Ada source (*.ad[abs]). ;;; ;;; When you have entered ada-mode, you may get more info by pressing ;;; C-h m. You may also get online help describing various functions by: @@ -53,7 +56,7 @@ ;;; electric-ada.el. ;;; ;;; The current Ada mode is a complete rewrite by M. Heritsch and -;;; R. Ebert. Some ideas from the ada-mode mailing list have been +;;; R. Ebert. Some ideas from the Ada mode mailing list have been ;;; added. Some of the functionality of L. Slater's mode has not ;;; (yet) been recoded in this new mode. Perhaps you prefer sticking ;;; to his version. @@ -65,15 +68,18 @@ ;;; In the presence of comments and/or incorrect syntax ;;; ada-format-paramlist produces weird results. ;;; ------------------- -;;; Indenting of some tasking constructs is still buggy. +;;; Character constants with otherwise syntactic relevant characters +;;; like `(' or `"' throw indentation off the track. Fontification +;;; should work now in Emacs-19.35 +;;; C : constant Character := Character'('"'); ;;; ------------------- -;;; package Test is -;;; -- If I hit return on the "type" line it will indent the next line -;;; -- in another 3 space instead of heading out to the "(". If I hit -;;; -- tab or return it reindents the line correctly but does not initially. -;;; type Wait_Return is (Read_Success, Read_Timeout, Wait_Timeout, -;;; Nothing_To_Wait_For_In_Wait_List); -;;; ------------------- + + +;;; TODO +;;; ==== +;;; +;;; o bodify-single-subprogram +;;; o make a function "separate" and put it in the corresponding file. @@ -92,43 +98,70 @@ ;;; USER OPTIONS ;;;-------------------- + +;; ---- customize support + +(defgroup ada nil + "Major mode for editing Ada source in Emacs" + :group 'languages) + ;; ---- configure indentation -(defvar ada-indent 3 - "*Defines the size of Ada indentation.") - -(defvar ada-broken-indent 2 - "*# of columns to indent the continuation of a broken line.") - -(defvar ada-label-indent -4 - "*# of columns to indent a label.") - -(defvar ada-stmt-end-indent 0 +(defcustom ada-indent 3 + "*Defines the size of Ada indentation." + :type 'integer + :group 'ada) + +(defcustom ada-broken-indent 2 + "*# of columns to indent the continuation of a broken line." + :type 'integer + :group 'ada) + +(defcustom ada-label-indent -4 + "*# of columns to indent a label." + :type 'integer + :group 'ada) + +(defcustom ada-stmt-end-indent 0 "*# of columns to indent a statement end keyword in a separate line. -Examples are 'is', 'loop', 'record', ...") - -(defvar ada-when-indent 3 - "*Defines the indentation for 'when' relative to 'exception' or 'case'.") - -(defvar ada-indent-record-rel-type 3 - "*Defines the indentation for 'record' relative to 'type' or 'use'.") - -(defvar ada-indent-comment-as-code t - "*If non-nil, comment-lines get indented as Ada code.") - -(defvar ada-indent-is-separate t - "*If non-nil, 'is separate' or 'is abstract' on a single line are indented.") - -(defvar ada-indent-to-open-paren t - "*If non-nil, indent according to the innermost open parenthesis.") - -(defvar ada-search-paren-char-count-limit 3000 - "*Search that many characters for an open parenthesis.") +Examples are 'is', 'loop', 'record', ..." + :type 'integer + :group 'ada) + +(defcustom ada-when-indent 3 + "*Defines the indentation for 'when' relative to 'exception' or 'case'." + :type 'integer + :group 'ada) + +(defcustom ada-indent-record-rel-type 3 + "*Defines the indentation for 'record' relative to 'type' or 'use'." + :type 'integer + :group 'ada) + +(defcustom ada-indent-comment-as-code t + "*If non-nil, comment-lines get indented as Ada code." + :type 'boolean + :group 'ada) + +(defcustom ada-indent-is-separate t + "*If non-nil, 'is separate' or 'is abstract' on a single line are indented." + :type 'boolean + :group 'ada) + +(defcustom ada-indent-to-open-paren t + "*If non-nil, indent according to the innermost open parenthesis." + :type 'boolean + :group 'ada) + +(defcustom ada-search-paren-char-count-limit 3000 + "*Search that many characters for an open parenthesis." + :type 'integer + :group 'ada) ;; ---- other user options -(defvar ada-tab-policy 'indent-auto +(defcustom ada-tab-policy 'indent-auto "*Control behaviour of the TAB key. Must be one of `indent-rigidly', `indent-auto', `gei', `indent-af' or `always-tab'. @@ -137,74 +170,173 @@ `indent-auto' : use indentation functions in this file. `gei' : use David Kågedal's Generic Indentation Engine. `indent-af' : use Gary E. Barnes' ada-format.el -`always-tab' : do indent-relative.") - -(defvar ada-move-to-declaration nil +`always-tab' : do indent-relative." + :type '(choice (const indent-auto) + (const indent-rigidly) + (const gei) + (const indent-af) + (const always-tab)) + :group 'ada) + +(defcustom ada-move-to-declaration nil "*If non-nil, `ada-move-to-start' moves point to the subprog declaration, -not to 'begin'.") - -(defvar ada-spec-suffix ".ads" - "*Suffix of Ada specification files.") - -(defvar ada-body-suffix ".adb" - "*Suffix of Ada body files.") - -(defvar ada-language-version 'ada95 - "*Do we program in `ada83' or `ada95'?") - -(defvar ada-case-keyword 'downcase-word +not to 'begin'." + :type 'boolean + :group 'ada) + +(defcustom ada-spec-suffix ".ads" + "*Suffix of Ada specification files." + :type 'string + :group 'ada) + +(defcustom ada-body-suffix ".adb" + "*Suffix of Ada body files." + :type 'string + :group 'ada) + +(defcustom ada-spec-suffix-as-regexp "\\.ads$" + "*Regexp to find Ada specification files." + :type 'string + :group 'ada) + +(defcustom ada-body-suffix-as-regexp "\\.adb$" + "*Regexp to find Ada body files." + :type 'string + :group 'ada) + +(defvar ada-other-file-alist + (list + (list ada-spec-suffix-as-regexp (list ada-body-suffix)) + (list ada-body-suffix-as-regexp (list ada-spec-suffix)) + ) + "*Alist of extensions to find given the current file's extension. + +This list should contain the most used extensions before the others, +since the search algorithm searches sequentially through each directory +specified in `ada-search-directories'. If a file is not found, a new one +is created with the first matching extension (`.adb' yields `.ads').") + +(defcustom ada-search-directories + '("." "/usr/adainclude" "/usr/local/adainclude" "/opt/gnu/adainclude") + "*List of directories to search for Ada files. +See the description for the `ff-search-directories' variable." + :type '(repeat (choice :tag "Directory" + (const :tag "default" nil) + (directory :format "%v"))) + :group 'ada) + +(defcustom ada-language-version 'ada95 + "*Do we program in `ada83' or `ada95'?" + :type '(choice (const ada83) + (const ada95)) + :group 'ada) + +(defcustom ada-case-keyword 'downcase-word "*Function to call to adjust the case of Ada keywords. -It may be `downcase-word', `upcase-word', `ada-loose-case-word' or -`capitalize-word'.") - -(defvar ada-case-identifier 'ada-loose-case-word +It may be `downcase-word', `upcase-word', `ada-loose-case-word' or +`capitalize-word'." + :type '(choice (const downcase-word) + (const upcase-word) + (const capitalize-word) + (const ada-loose-case-word)) + :group 'ada) + +(defcustom ada-case-identifier 'ada-loose-case-word "*Function to call to adjust the case of an Ada identifier. -It may be `downcase-word', `upcase-word', `ada-loose-case-word' or -`capitalize-word'.") - -(defvar ada-case-attribute 'capitalize-word +It may be `downcase-word', `upcase-word', `ada-loose-case-word' or +`capitalize-word'." + :type '(choice (const downcase-word) + (const upcase-word) + (const capitalize-word) + (const ada-loose-case-word)) + :group 'ada) + +(defcustom ada-case-attribute 'capitalize-word "*Function to call to adjust the case of Ada attributes. -It may be `downcase-word', `upcase-word', `ada-loose-case-word' or -`capitalize-word'.") - -(defvar ada-auto-case t +It may be `downcase-word', `upcase-word', `ada-loose-case-word' or +`capitalize-word'." + :type '(choice (const downcase-word) + (const upcase-word) + (const capitalize-word) + (const ada-loose-case-word)) + :group 'ada) + +(defcustom ada-auto-case t "*Non-nil automatically changes case of preceding word while typing. Casing is done according to `ada-case-keyword', `ada-case-identifier' -and `ada-cacse-attribute'.") - -(defvar ada-clean-buffer-before-saving nil - "*If non-nil, `remove-trailing-spaces' and `untabify' buffer before saving.") +and `ada-case-attribute'." + :type 'boolean + :group 'ada) + +(defcustom ada-clean-buffer-before-saving t + "*If non-nil, `remove-trailing-spaces' and `untabify' buffer before saving." + :type 'boolean + :group 'ada) (defvar ada-mode-hook nil - "*List of functions to call when Ada Mode is invoked. + "*List of functions to call when Ada mode is invoked. This is a good place to add Ada environment specific bindings.") -(defvar ada-external-pretty-print-program "aimap" - "*External pretty printer to call from within Ada Mode.") - -(defvar ada-tmp-directory "/tmp/" - "*Directory to store the temporary file for the Ada pretty printer.") - -(defvar ada-fill-comment-prefix "-- " - "*This is inserted in the first columns when filling a comment paragraph.") - -(defvar ada-fill-comment-postfix " --" - "*This is inserted at the end of each line when filling a comment paragraph -with `ada-fill-comment-paragraph-postfix'.") - -(defvar ada-krunch-args "0" - "*Argument of gnatk8, a string containing the max number of characters. -Set to 0, if you don't use crunched filenames.") +(defcustom ada-external-pretty-print-program "aimap" + "*External pretty printer to call from within Ada mode." + :type 'string + :group 'ada) + +(defcustom ada-tmp-directory "/tmp/" + "*Directory to store the temporary file for the Ada pretty printer." + :type 'string + :group 'ada) + +(defcustom ada-compile-options "-c" + "*Buffer local options passed to the Ada compiler. +These options are used when the compiler is invoked on the current buffer." + :type 'string + :group 'ada) +(make-variable-buffer-local 'ada-compile-options) + +(defcustom ada-make-options "-c" + "*Buffer local options passed to `ada-compiler-make' (usually `gnatmake'). +These options are used when `gnatmake' is invoked on the current buffer." + :type 'string + :group 'ada) +(make-variable-buffer-local 'ada-make-options) + +(defcustom ada-compiler-syntax-check "gcc -c -gnats" + "*Compiler command with options for syntax checking." + :type 'string + :group 'ada) + +(defcustom ada-compiler-make "gnatmake" + "*The `make' command for the given compiler." + :type 'string + :group 'ada) + +(defcustom ada-fill-comment-prefix "-- " + "*This is inserted in the first columns when filling a comment paragraph." + :type 'string + :group 'ada) + +(defcustom ada-fill-comment-postfix " --" + "*This is inserted at the end of each line when filling a comment paragraph. +with `ada-fill-comment-paragraph-postfix'." + :type 'string + :group 'ada) + +(defcustom ada-krunch-args "0" + "*Argument of gnatkr, a string containing the max number of characters. +Set to 0, if you don't use crunched filenames." + :type 'string + :group 'ada) ;;; ---- end of user configurable variables (defvar ada-mode-abbrev-table nil - "Abbrev table used in Ada Mode.") + "Abbrev table used in Ada mode.") (define-abbrev-table 'ada-mode-abbrev-table ()) (defvar ada-mode-map () - "Local keymap used for Ada Mode.") + "Local keymap used for Ada mode.") (defvar ada-mode-syntax-table nil "Syntax table to be used for editing Ada source code.") @@ -279,9 +411,9 @@ (defvar ada-end-stmt-re "\\(;\\|=>\\|^[ \t]*separate[ \t]+([a-zA-Z0-9_\\.]+)\\|\ -\\<\\(begin\\|else\\|record\\|loop\\|select\\|do\\|\ +\\<\\(begin\\|else\\|record\\|loop\\|select\\|do\\|then\\|\ declare\\|generic\\|private\\)\\>\\|\ -^[ \t]*\\(package\\|procedure\\|function\\)[ \ta-zA-Z0-9_\\.]+is\\|\ +^[ \t]*\\(package\\|procedure\\|function\\)\\>[ \ta-zA-Z0-9_\\.]+\\<is\\>\\|\ ^[ \t]*exception\\>\\)" "Regexp of possible ends for a non-broken statement. A new statement starts after these.") @@ -295,12 +427,16 @@ task\\|accept\\|entry\\)\\>" "Regexp for the start of a subprogram.") +(defvar ada-named-block-re + "[ \t]*[a-zA-Z_0-9]+ *:[^=]" + "Regexp of the name of a block or loop.") + ;; Written by Christian Egli <Christian.Egli@hcsd.hac.com> ;; (defvar ada-imenu-generic-expression - '((nil "^\\s-*\\(procedure\\|function\\)\\s-+\\([A-Za-z0-9_]+\\)" 2) - ("Type Defs" "^\\s-*\\(sub\\)?type\\s-+\\([A-Za-z0-9_]+\\)" 2)) + '((nil "^\\s-*\\(procedure\\|function\\)\\s-+\\([A-Za-z0-9_]+\\)" 2) + ("Type Defs" "^\\s-*\\(sub\\)?type\\s-+\\([A-Za-z0-9_]+\\)" 2)) "Imenu generic expression for Ada mode. See `imenu-generic-expression'.") @@ -313,7 +449,7 @@ (string-match "XEmacs" emacs-version))) (defun ada-create-syntax-table () - "Create the syntax table for Ada Mode." + "Create the syntax table for Ada mode." ;; There are two different syntax-tables. The standard one declares ;; `_' as a symbol constituent, in the second one, it is a word ;; constituent. For some search and replacing routines we @@ -321,8 +457,10 @@ (setq ada-mode-syntax-table (make-syntax-table)) (set-syntax-table ada-mode-syntax-table) - ;; define string brackets (% is alternative string bracket) - (modify-syntax-entry ?% "\"" ada-mode-syntax-table) + ;; define string brackets (`%' is alternative string bracket, but + ;; almost never used as such and throws font-lock and indentation + ;; off the track.) + (modify-syntax-entry ?% "$" ada-mode-syntax-table) (modify-syntax-entry ?\" "\"" ada-mode-syntax-table) (modify-syntax-entry ?\# "$" ada-mode-syntax-table) @@ -353,7 +491,7 @@ (modify-syntax-entry ?\f "> " ada-mode-syntax-table) (modify-syntax-entry ?\n "> " ada-mode-syntax-table) - ;; define what belongs in ada symbols + ;; define what belongs in Ada symbols (modify-syntax-entry ?_ "_" ada-mode-syntax-table) ;; define parentheses to match @@ -367,7 +505,7 @@ ;;;###autoload (defun ada-mode () - "Ada Mode is the major mode for editing Ada code. + "Ada mode is the major mode for editing Ada code. Bindings are as follows: (Note: 'LFD' is control-j.) @@ -387,7 +525,7 @@ Fill comment paragraph and justify each line '\\[ada-fill-comment-paragraph-justify]' Fill comment paragraph, justify and append postfix '\\[ada-fill-comment-paragraph-postfix]' - Next func/proc/task '\\[ada-next-procedure]' Previous func/proc/task '\\[ada-previous-procedure]' + Next func/proc/task '\\[ada-next-procedure]' Previous func/proc/task '\\[ada-previous-procedure]' Next package '\\[ada-next-package]' Previous package '\\[ada-previous-package]' Goto matching start of current 'end ...;' '\\[ada-move-to-start]' @@ -448,25 +586,40 @@ (make-local-variable 'case-fold-search) (setq case-fold-search t) + (make-local-variable 'outline-regexp) + (setq outline-regexp "[^\n\^M]") + (make-local-variable 'outline-level) + (setq outline-level 'ada-outline-level) + (make-local-variable 'fill-paragraph-function) (setq fill-paragraph-function 'ada-fill-comment-paragraph) + ;;(make-local-variable 'adaptive-fill-regexp) (make-local-variable 'imenu-generic-expression) (setq imenu-generic-expression ada-imenu-generic-expression) - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults '((ada-font-lock-keywords - ada-font-lock-keywords-1 - ada-font-lock-keywords-2) - nil t - ((?\_ . "w")) - beginning-of-line)) + (if (ada-xemacs) nil ; XEmacs uses properties + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults + '((ada-font-lock-keywords + ada-font-lock-keywords-1 ada-font-lock-keywords-2) + nil t + ((?\_ . "w")(?\. . "w")) + beginning-of-line + (font-lock-syntactic-keywords . ada-font-lock-syntactic-keywords))) + + ;; Set up support for find-file.el. + (make-variable-buffer-local 'ff-other-file-alist) + (make-variable-buffer-local 'ff-search-directories) + (setq ff-other-file-alist 'ada-other-file-alist + ff-search-directories 'ada-search-directories + ff-pre-load-hooks 'ff-which-function-are-we-in + ff-post-load-hooks 'ff-set-point-accordingly + ff-file-created-hooks 'ada-make-body)) (setq major-mode 'ada-mode) (setq mode-name "Ada") - (setq blink-matching-paren t) - (use-local-map ada-mode-map) (if ada-mode-syntax-table @@ -500,6 +653,45 @@ ;;;-------------------------- +;;; Compile support +;;;-------------------------- + +(defun ada-check-syntax () + "Check syntax of the current buffer. +Uses the function `compile' to execute `ada-compiler-syntax-check'." + (interactive) + (let ((old-compile-command compile-command)) + (setq compile-command (concat ada-compiler-syntax-check + (if (eq ada-language-version 'ada83) + "-gnat83 ") + " " ada-compile-options " " + (buffer-name))) + (setq compile-command (read-from-minibuffer + "enter command for syntax check: " + compile-command)) + (compile compile-command) + ;; restore old compile-command + (setq compile-command old-compile-command))) + +(defun ada-make-local () + "Bring current Ada unit up-to-date. +Uses the function `compile' to execute `ada-compile-make'." + (interactive) + (let ((old-compile-command compile-command)) + (setq compile-command (concat ada-compiler-make + " " ada-make-options " " + (buffer-name))) + (setq compile-command (read-from-minibuffer + "enter command for local make: " + compile-command)) + (compile compile-command) + ;; restore old compile-command + (setq compile-command old-compile-command))) + + + + +;;;-------------------------- ;;; Fill Comment Paragraph ;;;-------------------------- @@ -661,7 +853,7 @@ "Calls the external Pretty Printer. The name is specified in `ada-external-pretty-print-program'. Saves the current buffer in a directory specified by `ada-tmp-directory', -starts the pretty printer as an external process on that file and then +starts the pretty printer as external process on that file and then reloads the beautified program in the buffer and cleans up `ada-tmp-directory'." (interactive) @@ -724,7 +916,7 @@ ;;;--------------- ;; from Philippe Waroquiers <philippe@cfmu.eurocontrol.be> -;; modifiedby RE and MH +;; modified by RE and MH (defun ada-after-keyword-p () ;; returns t if cursor is after a keyword. @@ -737,14 +929,19 @@ (not (looking-at "_"))) ; (MH) (looking-at (concat ada-keywords "[^_]"))))) -(defun ada-after-char-p () - ;; returns t if after ada character "'". This is interpreted as being - ;; in a character constant. +(defun ada-in-char-const-p () + ;; Returns t if point is inside a character constant. + ;; We assume to be in a constant if the previous and the next character + ;; are "'". (save-excursion - (if (> (point) 2) - (progn - (forward-char -2) - (looking-at "'")) + (if (> (point) 1) + (and + (progn + (forward-char 1) + (looking-at "'")) + (progn + (forward-char -2) + (looking-at "'"))) nil))) @@ -756,7 +953,7 @@ (forward-char -1) (if (and (> (point) 1) (not (or (ada-in-string-p) (ada-in-comment-p) - (ada-after-char-p)))) + (ada-in-char-const-p)))) (if (eq (char-syntax (char-after (1- (point)))) ?w) (if (save-excursion (forward-word -1) @@ -801,7 +998,7 @@ ;; save original keybindings to allow swapping ret/lfd ;; when casing is activated ;; the 'or ...' is there to be sure that the value will not - ;; be changed again when Ada Mode is called more than once (MH) + ;; be changed again when Ada mode is called more than once (MH) (or ada-ret-binding (setq ada-ret-binding (key-binding "\C-M"))) (or ada-lfd-binding @@ -819,7 +1016,7 @@ ;; added by MH ;; (defun ada-loose-case-word (&optional arg) - "Capitalizes the first letter and the letters following `_'. + "Capitalizes the first letter and the letters following `_'. ARG is ignored, it's there to fit the standard casing functions' style." (let ((pos (point)) (first t)) @@ -835,6 +1032,7 @@ ;; ;; added by MH +;; modified by JSH to handle attributes ;; (defun ada-adjust-case-region (from to) "Adjusts the case of all words in the region. @@ -843,13 +1041,13 @@ (let ((begin nil) (end nil) (keywordp nil) - (reldiff nil)) + (attribp nil)) (unwind-protect (save-excursion (set-syntax-table ada-mode-symbol-syntax-table) (goto-char to) ;; - ;; loop: look for all identifiers and keywords + ;; loop: look for all identifiers, keywords, and attributes ;; (while (re-search-backward "[^a-zA-Z0-9_]\\([a-zA-Z0-9_]+\\)[^a-zA-Z0-9_]" @@ -858,16 +1056,15 @@ ;; ;; print status message ;; - (setq reldiff (- (point) from)) - (message "adjusting case ... %5d characters left" - (- (point) from)) + (message "adjusting case ... %5d characters left" (- (point) from)) + (setq attribp (looking-at "'[a-zA-Z0-9_]+[^']")) (forward-char 1) (or ;; do nothing if it is a string or comment (ada-in-string-or-comment-p) (progn ;; - ;; get the identifier or keyword + ;; get the identifier or keyword or attribute ;; (setq begin (point)) (setq keywordp (looking-at (concat ada-keywords "[^_]"))) @@ -877,7 +1074,9 @@ ;; (if keywordp (funcall ada-case-keyword -1) - (funcall ada-case-identifier -1)) + (if attribp + (funcall ada-case-attribute -1) + (funcall ada-case-identifier -1))) (goto-char begin)))) (message "adjusting case ... done")) (set-syntax-table ada-mode-syntax-table)))) @@ -888,7 +1087,7 @@ ;; (defun ada-adjust-case-buffer () "Adjusts the case of all words in the whole buffer. -Attention: This function might take very long for big buffers !" +ATTENTION: This function might take very long for big buffers !" (interactive "*") (ada-adjust-case-region (point-min) (point-max))) @@ -898,8 +1097,8 @@ ;;;------------------------;;; (defun ada-format-paramlist () - "Reformats a parameter-list. -Attention: 1) Comments inside the list are killed ! + "Reformats a parameter list. +ATTENTION: 1) Comments inside the list are killed ! 2) If the syntax is not correct (especially, if there are semicolons missing), it can get totally confused ! In such a case, use `undo', correct the syntax and try again." @@ -920,7 +1119,7 @@ ;; find start of current parameter-list ;; (ada-search-ignore-string-comment - (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil) + (concat ada-subprog-start-re "\\|\\<body\\>" ) t nil) (ada-search-ignore-string-comment "(" nil nil t) (backward-char 1) (setq begin (point)) @@ -1061,9 +1260,9 @@ (ada-goto-next-non-ws)) ;; - ;; read type of parameter + ;; read type of parameter ;; - (looking-at "\\<[a-zA-Z0-9_\\.]+\\>") + (looking-at "\\<[a-zA-Z0-9_\\.\\']+\\>") (setq param (append param (list @@ -1409,51 +1608,16 @@ (setq lines-remaining (1- lines-remaining))) ;; show line number where the error occurred (error - (error "line %d: %s" (1+ (count-lines (point-min) (point))) err))) + (error "line %d: %s" (1+ (count-lines (point-min) (point))) err) nil)) (message "indenting ... done"))) (defun ada-indent-newline-indent () "Indents the current line, inserts a newline and then indents the new line." (interactive "*") - (let ((column) - (orgpoint)) - - (ada-indent-current) - (newline) - (delete-horizontal-space) - (setq orgpoint (point)) - - (unwind-protect - (progn - (set-syntax-table ada-mode-symbol-syntax-table) - - (setq column (save-excursion - (funcall (ada-indent-function) orgpoint)))) - - ;; - ;; restore syntax-table - ;; - (set-syntax-table ada-mode-syntax-table)) - - (indent-to column) - - ;; The following is needed to ensure that indentation will still be - ;; correct if something follows behind point when typing LFD - ;; For example: Imagine point to be there (*) when LFD is typed: - ;; while cond loop - ;; null; *end loop; - ;; Result without the following statement would be: - ;; while cond loop - ;; null; - ;; *end loop; - ;; You would then have to type TAB to correct it. - ;; If that doesn't bother you, you can comment out the following - ;; statement to speed up indentation a LITTLE bit. - - (if (not (looking-at "[ \t]*$")) - (ada-indent-current)) - )) + (ada-indent-current) + (newline) + (ada-indent-current)) (defun ada-indent-current () @@ -1496,10 +1660,10 @@ (setq prev-indent (save-excursion (funcall (ada-indent-function) line-end)))) - (progn ; first line of buffer -> set indent - (beginning-of-line) ; to 0 - (delete-horizontal-space) - (setq prevline nil)))) + (progn ; first line of buffer -> set indent + (beginning-of-line) ; to 0 + (delete-horizontal-space) + (setq prevline nil)))) (if prevline ;; @@ -1511,18 +1675,17 @@ ;; (back-to-indentation) (setq cur-indent (ada-get-current-indent prev-indent)) - ;; only reindent if indentation is different then the current - (if (= (current-column) cur-indent) - nil + ;; only reindent if indentation is different then the current + (if (= (current-column) cur-indent) + nil (delete-horizontal-space) - (indent-to cur-indent)) - + (indent-to cur-indent)) ;; ;; restore position of point ;; (goto-char orgpoint) (if (< (current-column) (current-indentation)) - (back-to-indentation)))))) + (back-to-indentation)))))) ;; ;; restore syntax-table @@ -1559,27 +1722,33 @@ ;; end ;; ((looking-at "\\<end\\>") - (save-excursion - (ada-goto-matching-start 1) - - ;; - ;; found 'loop' => skip back to 'while' or 'for' - ;; if 'loop' is not on a separate line - ;; - (if (and - (looking-at "\\<loop\\>") - (save-excursion - (back-to-indentation) - (not (looking-at "\\<loop\\>")))) - (if (save-excursion - (and - (setq match-cons - (ada-search-ignore-string-comment - ada-loop-start-re t nil)) - (not (looking-at "\\<loop\\>")))) - (goto-char (car match-cons)))) - - (current-indentation))) + (let ((label 0)) + (save-excursion + (ada-goto-matching-start 1) + + ;; + ;; found 'loop' => skip back to 'while' or 'for' + ;; if 'loop' is not on a separate line + ;; + (if (and + (looking-at "\\<loop\\>") + (save-excursion + (back-to-indentation) + (not (looking-at "\\<loop\\>")))) + (if (save-excursion + (and + (setq match-cons + (ada-search-ignore-string-comment + ada-loop-start-re t nil)) + (not (looking-at "\\<loop\\>")))) + (progn + (goto-char (car match-cons)) + (save-excursion + (beginning-of-line) + (if (looking-at ada-named-block-re) + (setq label (- ada-label-indent))))))) + + (+ (current-indentation) label)))) ;; ;; exception ;; @@ -1647,9 +1816,7 @@ (save-excursion (if (ada-goto-matching-decl-start t) (current-indentation) - (progn - (message "no matching declaration start") - prev-indent)))) + prev-indent))) ;; ;; is ;; @@ -1776,8 +1943,7 @@ ;; the current statement, if NOMOVE is nil. (let ((orgpoint (point)) - (func nil) - (stmt-start nil)) + (func nil)) ;; ;; inside a parameter-list ;; @@ -1788,14 +1954,14 @@ ;; move to beginning of current statement ;; (if (not nomove) - (setq stmt-start (ada-goto-stmt-start))) + (ada-goto-stmt-start)) ;; ;; no beginning found => don't change indentation ;; (if (and (eq orgpoint (point)) (not nomove)) - (setq func 'ada-get-indent-nochange) + (setq func 'ada-get-indent-nochange) (cond ;; @@ -1813,11 +1979,6 @@ ((looking-at ada-subprog-start-re) (setq func 'ada-get-indent-subprog)) ;; - ((looking-at "\\<package\\>") - (setq func 'ada-get-indent-subprog)) ; maybe it needs a - ; special function - ; sometimes ? - ;; ((looking-at ada-block-start-re) (setq func 'ada-get-indent-block-start)) ;; @@ -1851,7 +2012,7 @@ (defun ada-get-indent-open-paren (orgpoint) ;; Returns the indentation (column #) for the new line after ORGPOINT. - ;; Assumes point to be behind an open paranthesis not yet closed. + ;; Assumes point to be behind an open parenthesis not yet closed. (ada-in-open-paren-p)) @@ -1897,6 +2058,7 @@ ;; slow, if it has to search through big files with many nested blocks. ;; Signals an error if the corresponding block-start doesn't match. (let ((defun-name nil) + (label 0) (indent nil)) ;; ;; is the line already terminated by ';' ? @@ -1923,8 +2085,9 @@ (forward-word 1) (ada-goto-stmt-start))) ;; a label ? => skip it - (if (looking-at "[a-zA-Z0-9_]+[ \n\t]+:") + (if (looking-at ada-named-block-re) (progn + (setq label (- ada-label-indent)) (goto-char (match-end 0)) (ada-goto-next-non-ws))) ;; really looking-at the right thing ? @@ -1937,7 +2100,7 @@ "loop\\|select\\|if\\|case\\|" "record\\|while\\|type\\)\\>"))) (backward-word 1)) - (current-indentation))) + (+ (current-indentation) label))) ;; ;; a named block end ;; @@ -1971,7 +2134,7 @@ (defun ada-get-indent-case (orgpoint) ;; Returns the indentation (column #) for the new line after ORGPOINT. - ;; Assumes point to be at the beginning of an case-statement. + ;; Assumes point to be at the beginning of a case-statement. (let ((cur-indent (current-indentation)) (match-cons nil) (opos (point))) @@ -1980,8 +2143,12 @@ ;; case..is..when..=> ;; ((save-excursion - (setq match-cons (ada-search-ignore-string-comment - "[ \t\n]+=>" nil orgpoint))) + (setq match-cons (and + ;; the `=>' must be after the keyword `is'. + (ada-search-ignore-string-comment + "\\<is\\>" nil orgpoint) + (ada-search-ignore-string-comment + "[ \t\n]+=>" nil orgpoint)))) (save-excursion (goto-char (car match-cons)) (if (not (ada-search-ignore-string-comment "\\<when\\>" t opos)) @@ -2092,7 +2259,7 @@ (if (save-excursion (setq match-cons (ada-search-ignore-string-comment - "\\<is\\>\\|\\<do\\>" nil orgpoint))) + "\\<\\(is\\|do\\)\\>" nil orgpoint))) ;; ;; yes, then skip to its end ;; @@ -2155,10 +2322,15 @@ (defun ada-get-indent-noindent (orgpoint) ;; Returns the indentation (column #) for the new line after ORGPOINT. ;; Assumes point to be at the beginning of a 'noindent statement'. - (if (save-excursion - (ada-search-ignore-string-comment ";" nil orgpoint)) - (current-indentation) - (+ (current-indentation) ada-broken-indent))) + (let ((label 0)) + (save-excursion + (beginning-of-line) + (if (looking-at ada-named-block-re) + (setq label (- ada-label-indent)))) + (if (save-excursion + (ada-search-ignore-string-comment ";" nil orgpoint)) + (+ (current-indentation) label) + (+ (current-indentation) ada-broken-indent label)))) (defun ada-get-indent-label (orgpoint) @@ -2183,7 +2355,7 @@ ;; ((save-excursion (setq match-cons (ada-search-ignore-string-comment - "\\<declare\\>" nil orgpoint))) + "\\<declare\\|begin\\>" nil orgpoint))) (save-excursion (goto-char (car match-cons)) (+ (current-indentation) ada-indent))) @@ -2217,7 +2389,13 @@ ;; Assumes point to be at the beginning of a loop statement ;; or (unfortunately) also a for ... use statement. (let ((match-cons nil) - (pos (point))) + (pos (point)) + (label (save-excursion + (beginning-of-line) + (if (looking-at ada-named-block-re) + (- ada-label-indent) + 0)))) + (cond ;; @@ -2225,12 +2403,12 @@ ;; ((save-excursion (ada-search-ignore-string-comment ";" nil orgpoint)) - (current-indentation)) + (+ (current-indentation) label)) ;; ;; simple loop ;; ((looking-at "loop\\>") - (ada-get-indent-block-start orgpoint)) + (+ (ada-get-indent-block-start orgpoint) label)) ;; ;; 'for'- loop (or also a for ... use statement) @@ -2274,12 +2452,12 @@ (back-to-indentation) (looking-at "\\<loop\\>"))) (goto-char pos)) - (+ (current-indentation) ada-indent)) + (+ (current-indentation) ada-indent label)) ;; ;; for-statement is broken ;; (t - (+ (current-indentation) ada-broken-indent)))) + (+ (current-indentation) ada-broken-indent label)))) ;; ;; 'while'-loop @@ -2302,9 +2480,9 @@ (back-to-indentation) (looking-at "\\<loop\\>"))) (goto-char pos)) - (+ (current-indentation) ada-indent)) - - (+ (current-indentation) ada-broken-indent)))))) + (+ (current-indentation) ada-indent label)) + + (+ (current-indentation) ada-broken-indent label)))))) (defun ada-get-indent-type (orgpoint) @@ -2387,7 +2565,7 @@ ;; (setq match-dat (ada-search-prev-end-stmt limit))) ;; - ;; if found the correct end-stetement => goto next non-ws + ;; if found the correct end-statement => goto next non-ws ;; (if match-dat (goto-char (cdr match-dat))) @@ -2418,7 +2596,6 @@ ;; End-statements are defined by 'ada-end-stmt-re'. Checks for ;; certain keywords if they follow 'end', which means they are no ;; end-statement there. - (interactive) ;; DEBUG (let ((match-dat nil) (pos nil) (found nil)) @@ -2433,18 +2610,22 @@ limit))) (goto-char (car match-dat)) - (if (not (ada-in-open-paren-p)) ;; ;; check if there is an 'end' in front of the match ;; (if (not (and - (looking-at "\\<\\(record\\|loop\\|select\\)\\>") + (looking-at + "\\<\\(record\\|loop\\|select\\|else\\|then\\)\\>") (save-excursion (ada-goto-previous-word) - (looking-at "\\<end\\>")))) - (setq found t) - + (looking-at "\\<\\(end\\|or\\|and\\)\\>")))) + (save-excursion + (goto-char (cdr match-dat)) + (ada-goto-next-word) + (if (not (looking-at "\\<\\(separate\\|new\\)\\>")) + (setq found t))) + (forward-word -1)))) ; end of loop (if found @@ -2474,18 +2655,21 @@ nil)) -(defun ada-goto-previous-word () - ;; Moves point to the beginning of the previous word of Ada code. +(defun ada-goto-next-word (&optional backward) + ;; Moves point to the beginning of the next word of Ada code. + ;; If BACKWARD is non-nil, jump to the beginning of the previous word. ;; Returns the new position of point or nil if not found. (let ((match-cons nil) (orgpoint (point))) + (if (not backward) + (skip-chars-forward "_a-zA-Z0-9\\.")) (if (setq match-cons - (ada-search-ignore-string-comment "[^ \t\n]" t nil t)) + (ada-search-ignore-string-comment "\\w" backward nil t)) ;; ;; move to the beginning of the word found ;; (progn - (goto-char (cdr match-cons)) + (goto-char (car match-cons)) (skip-chars-backward "_a-zA-Z0-9") (point)) ;; @@ -2496,6 +2680,12 @@ 'nil)))) +(defun ada-goto-previous-word () + ;; Moves point to the beginning of the previous word of Ada code. + ;; Returns the new position of point or nil if not found. + (ada-goto-next-word t)) + + (defun ada-check-matching-start (keyword) ;; Signals an error if matching block start is not KEYWORD. ;; Moves point to the matching block start. @@ -2510,45 +2700,51 @@ ;; Moves point to the beginning of the declaration. ;; - ;; 'accept' or 'package' ? - ;; - (if (not (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>")) - (ada-goto-matching-decl-start)) - ;; - ;; 'begin' of 'procedure'/'function'/'task' or 'declare' + ;; named block without a `declare' ;; - (save-excursion + (if (save-excursion + (ada-goto-previous-word) + (looking-at (concat "\\<" defun-name "\\> *:"))) + t ; do nothing ;; - ;; a named 'declare'-block ? + ;; 'accept' or 'package' ? ;; - (if (looking-at "\\<declare\\>") - (ada-goto-stmt-start) + (if (not (looking-at "\\<\\(accept\\|package\\|task\\|protected\\)\\>")) + (ada-goto-matching-decl-start)) + ;; + ;; 'begin' of 'procedure'/'function'/'task' or 'declare' + ;; + (save-excursion ;; - ;; no, => 'procedure'/'function'/'task'/'protected' + ;; a named 'declare'-block ? ;; - (progn - (forward-word 2) - (backward-word 1) + (if (looking-at "\\<declare\\>") + (ada-goto-stmt-start) ;; - ;; skip 'body' 'protected' 'type' + ;; no, => 'procedure'/'function'/'task'/'protected' ;; - (if (looking-at "\\<\\(body\\|type\\)\\>") - (forward-word 1)) - (forward-sexp 1) - (backward-sexp 1))) - ;; - ;; should be looking-at the correct name - ;; - (if (not (looking-at (concat "\\<" defun-name "\\>"))) - (error "matching defun has different name: %s" - (buffer-substring (point) - (progn (forward-sexp 1) (point))))))) + (progn + (forward-word 2) + (backward-word 1) + ;; + ;; skip 'body' 'type' + ;; + (if (looking-at "\\<\\(body\\|type\\)\\>") + (forward-word 1)) + (forward-sexp 1) + (backward-sexp 1))) + ;; + ;; should be looking-at the correct name + ;; + (if (not (looking-at (concat "\\<" defun-name "\\>"))) + (error "matching defun has different name: %s" + (buffer-substring (point) + (progn (forward-sexp 1) (point)))))))) (defun ada-goto-matching-decl-start (&optional noerror nogeneric) ;; Moves point to the matching declaration start of the current 'begin'. ;; If NOERROR is non-nil, it only returns nil if no match was found. - (interactive) ;; DEBUG (let ((nest-count 1) (pos nil) (first t) @@ -2578,25 +2774,26 @@ ;; ((looking-at "is") ;; check if it is only a type definition, but not a protected - ;; type definition, which should be handled like a procedure. - (if (save-excursion - (ada-goto-previous-word) - (skip-chars-backward "a-zA-Z0-9_.'") - (if (save-excursion - (backward-char 1) - (looking-at ")")) - (progn - (forward-char 1) - (backward-sexp 1) - (skip-chars-backward "a-zA-Z0-9_.'") - )) - (ada-goto-previous-word) - (and - (looking-at "\\<type\\>") - (save-match-data - (ada-goto-previous-word) - (not (looking-at "\\<protected\\>")))) - ); end of save-excursion + ;; type definition, which should be handled like a procedure. + (if (or (looking-at "is +<>") + (save-excursion + (ada-goto-previous-word) + (skip-chars-backward "a-zA-Z0-9_.'") + (if (save-excursion + (backward-char 1) + (looking-at ")")) + (progn + (forward-char 1) + (backward-sexp 1) + (skip-chars-backward "a-zA-Z0-9_.'") + )) + (ada-goto-previous-word) + (and + (looking-at "\\<type\\>") + (save-match-data + (ada-goto-previous-word) + (not (looking-at "\\<protected\\>")))) + )); end of `or' (goto-char (match-beginning 0)) (progn (setq nest-count (1- nest-count)) @@ -2625,13 +2822,11 @@ (and (zerop nest-count) (not flag) - (progn - (if (looking-at "is") - (ada-search-ignore-string-comment - ada-subprog-start-re t) - (looking-at "declare\\|generic"))))) + (if (looking-at "is") + (ada-search-ignore-string-comment ada-subprog-start-re t) + (looking-at "declare\\|generic")))) (if noerror nil - (error "no matching proc/func/task/declare/package/protected")) + (error "no matching proc/func/task/declare/package/protected")) t))) @@ -2672,7 +2867,7 @@ ;; check if keyword follows 'end' ;; (ada-goto-previous-word) - (if (looking-at "\\<end\\>") + (if (looking-at "\\<end\\> *[^;]") ;; it ends a block => increase nest depth (progn (setq nest-count (1+ nest-count)) @@ -3064,14 +3259,11 @@ (defun ada-in-comment-p () ;; Returns t if inside a comment. - ;; (save-excursion (and (re-search-backward "\\(--\\|\n\\)" nil 1) - ;; (looking-at "-")))) (nth 4 (parse-partial-sexp (save-excursion (beginning-of-line) (point)) (point)))) - (defun ada-in-string-p () ;; Returns t if point is inside a string ;; (Taken from pascal-mode.el, modified by MH). @@ -3083,14 +3275,25 @@ (point)) (point))) ;; check if 'string quote' is only a character constant (progn - (re-search-backward "\"" nil t) ; # not a string delimiter anymore + (re-search-backward "\"" nil t) ; `#' is not taken as a string delimiter (not (= (char-after (1- (point))) ?')))))) (defun ada-in-string-or-comment-p () - ;; Returns t if point is inside a string or a comment. - (or (ada-in-comment-p) - (ada-in-string-p))) + ;; Returns t if point is inside a string, a comment, or a character constant. + (let ((parse-result (parse-partial-sexp + (save-excursion (beginning-of-line) (point)) (point)))) + (or ;; in-comment-p + (nth 4 parse-result) + ;; in-string-p + (and + (nth 3 parse-result) + ;; check if 'string quote' is only a character constant + (progn + (re-search-backward "\"" nil t) ; `#' not regarded a string delimiter + (not (= (char-after (1- (point))) ?')))) + ;; in-char-const-p + (ada-in-char-const-p)))) (defun ada-in-paramlist-p () @@ -3117,10 +3320,12 @@ ;; If point is somewhere behind an open parenthesis not yet closed, ;; it returns the column # of the first non-ws behind this open ;; parenthesis, otherwise nil." - - (let ((start (if (< (point) ada-search-paren-char-count-limit) - 1 - (- (point) ada-search-paren-char-count-limit))) + (let ((start (if (<= (point) ada-search-paren-char-count-limit) + (point-min) + (save-excursion + (goto-char (- (point) ada-search-paren-char-count-limit)) + (beginning-of-line) + (point)))) parse-result (col nil)) (setq parse-result (parse-partial-sexp start (point))) @@ -3169,7 +3374,7 @@ (defun ada-indent-current-function () - "Ada Mode version of the indent-line-function." + "Ada mode version of the indent-line-function." (interactive "*") (let ((starting-point (point-marker))) (ada-beginning-of-line) @@ -3209,16 +3414,17 @@ (save-match-data (save-excursion (save-restriction - (widen) - (goto-char (point-min)) - (while (re-search-forward "[ \t]+$" (point-max) t) - (replace-match "" nil nil)))))) + (widen) + (goto-char (point-min)) + (while (re-search-forward "[ \t]+$" (point-max) t) + (replace-match "" nil nil)))))) (defun ada-untabify-buffer () ;; change all tabs to spaces (save-excursion - (untabify (point-min) (point-max)))) + (untabify (point-min) (point-max)) + nil)) (defun ada-uncomment-region (beg end) @@ -3234,6 +3440,23 @@ (and (fboundp 'ff-find-other-file) (ff-find-other-file t))) +;; inspired by Laurent.GUERBY@enst-bretagne.fr +(defun ada-gnat-style () + "Clean up comments, `(' and `,' for GNAT style checking switch." + (interactive) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "-- ?\\([^ -]\\)" nil t) + (replace-match "-- \\1")) + (goto-char (point-min)) + (while (re-search-forward "\\>(" nil t) + (replace-match " (")) + (goto-char (point-min)) + (while (re-search-forward ",\\<" nil t) + (replace-match ", ")) + )) + + ;;;-------------------------------;;; ;;; Moving To Procedures/Packages ;;; @@ -3304,21 +3527,25 @@ ;; Compilation (define-key ada-mode-map "\C-c\C-c" 'compile) + (define-key ada-mode-map "\C-c\C-v" 'ada-check-syntax) + (define-key ada-mode-map "\C-c\C-m" 'ada-make-local) ;; Casing (define-key ada-mode-map "\C-c\C-r" 'ada-adjust-case-region) (define-key ada-mode-map "\C-c\C-b" 'ada-adjust-case-buffer) + (define-key ada-mode-map "\177" 'backward-delete-char-untabify) + ;; Use predefined function of emacs19 for comments (RE) (define-key ada-mode-map "\C-c;" 'comment-region) (define-key ada-mode-map "\C-c:" 'ada-uncomment-region) ;; Change basic functionality - ;; `substitute-key-definition' is not defined equally in GNU Emacs + ;; `substitute-key-definition' is not defined equally in Emacs ;; and XEmacs, you cannot put in an optional 4th parameter in ;; XEmacs. I don't think it's necessary, so I leave it out for - ;; GNU Emacs as well. If you encounter any problems with the + ;; Emacs as well. If you encounter any problems with the ;; following three functions, please tell me. RE (mapcar (function (lambda (pair) (substitute-key-definition (car pair) (cdr pair) @@ -3327,7 +3554,7 @@ (end-of-line . ada-end-of-line) (forward-to-indentation . ada-forward-to-indentation) )) - ;; else GNU Emacs + ;; else Emacs ;;(mapcar (lambda (pair) ;; (substitute-key-definition (car pair) (cdr pair) ;; ada-mode-map global-map)) @@ -3342,7 +3569,7 @@ (require 'easymenu) (defun ada-add-ada-menu () - "Adds the menu 'Ada' to the menu bar in Ada Mode." + "Adds the menu 'Ada' to the menu bar in Ada mode." (easy-menu-define ada-mode-menu ada-mode-map "Menu keymap for Ada mode." '("Ada" ["Next Package" ada-next-package t] @@ -3371,7 +3598,9 @@ ["Comment Region" comment-region t] ["Uncomment Region" ada-uncomment-region t] ["----------------" nil nil] - ["Compile" compile (fboundp 'compile)] + ["Global Make" compile (fboundp 'compile)] + ["Local Make" ada-make-local t] + ["Check Syntax" ada-check-syntax t] ["Next Error" next-error (fboundp 'next-error)] ["---------------" nil nil] ["Index" imenu (fboundp 'imenu)] @@ -3382,7 +3611,7 @@ (fboundp 'ff-find-other-file)])) (if (ada-xemacs) (progn (easy-menu-add ada-mode-menu) - (setq mode-popup-menu (cons "Ada Mode" ada-mode-menu))))) + (setq mode-popup-menu (cons "Ada mode" ada-mode-menu))))) @@ -3418,37 +3647,22 @@ )) ;;;--------------------------------------------------- -;;; support for find-file +;;; support for find-file.el ;;;--------------------------------------------------- ;;;###autoload (defun ada-make-filename-from-adaname (adaname) "Determine the filename of a package/procedure from its own Ada name." - ;; this is done simply by calling gkrunch, when we work with GNAT. It + ;; this is done simply by calling `gnatkr', when we work with GNAT. It ;; must be a more complex function in other compiler environments. (interactive "s") - - ;; things that should really be done by the external process - ;; since gnat-2.0, gnatk8 can do these things. If you still use a - ;; previous version, just uncomment the following lines. (let (krunch-buf) (setq krunch-buf (generate-new-buffer "*gkrunch*")) (save-excursion (set-buffer krunch-buf) -; (insert (downcase adaname)) -; (goto-char (point-min)) -; (while (search-forward "." nil t) -; (replace-match "-" nil t)) -; (setq adaname (buffer-substring (point-min) -; (progn -; (goto-char (point-min)) -; (end-of-line) -; (point)))) -; ;; clean the buffer -; (delete-region (point-min) (point-max)) - ;; send adaname to external process "gnatk8" - (call-process "gnatk8" nil krunch-buf nil + ;; send adaname to external process `gnatkr'. + (call-process "gnatkr" nil krunch-buf nil adaname ada-krunch-args) ;; fetch output of that process (setq adaname (buffer-substring @@ -3481,74 +3695,45 @@ ;;;--------------------------------------------------- -;;; support for imenu -;;;--------------------------------------------------- - -(defun imenu-create-ada-index (&optional regexp) - "Create index alist for Ada files." - (let ((index-alist '()) - prev-pos char) - (goto-char (point-min)) - ;(imenu-progress-message prev-pos 0) - ;; Search for functions/procedures - (save-match-data - (while (re-search-forward - (or regexp ada-procedure-start-regexp) - nil t) - ;(imenu-progress-message prev-pos) - ;; do not store forward definitions - ;; right now we store them. We want to avoid them only in - ;; package bodies, not in the specs!! ???RE??? - (save-match-data -; (if (not (looking-at (concat -; "[ \t\n]*" ; WS -; "\([^)]+\)" ; parameterlist -; "\\([ \n\t]+return[ \n\t]+"; potential return -; "[a-zA-Z0-9_\\.]+\\)?" -; "[ \t]*" ; WS -; ";" ;; THIS is what we really look for -; ))) -; ; (push (imenu-example--name-and-position) index-alist) - (setq index-alist (cons (imenu-example--name-and-position) - index-alist)) -; ) - ) - ;(imenu-progress-message 100) - )) - (nreverse index-alist))) - -;;;--------------------------------------------------- ;;; support for font-lock ;;;--------------------------------------------------- -;; Strings are a real pain in Ada because both ' and " can appear in a -;; non-string quote context (the former as an operator, the latter as -;; a character string). We follow the least losing solution, in which -;; only " is a string quote. Therefore a character string of the form -;; '"' will throw fontification off on the wrong track. +;; Strings are a real pain in Ada because a single quote character is +;; overloaded as a string quote and type/instance delimiter. By default, a +;; single quote is given punctuation syntax in `ada-mode-syntax-table'. +;; So, for Font Lock mode purposes, we mark single quotes as having string +;; syntax when the gods that created Ada determine them to be. sm. + +(defconst ada-font-lock-syntactic-keywords + ;; Mark single quotes as having string quote syntax in 'c' instances. + '(("\\(\'\\).\\(\'\\)" (1 (7 . ?\')) (2 (7 . ?\'))))) (defconst ada-font-lock-keywords-1 (list ;; + ;; handle "type T is access function return S;" + ;; + (list "\\<\\(function[ \t]+return\\)\\>" '(1 font-lock-keyword-face) ) + ;; ;; accept, entry, function, package (body), protected (body|type), ;; pragma, procedure, task (body) plus name. (list (concat "\\<\\(" "accept\\|" "entry\\|" - "function\\|" - "package[ \t]+body\\|" - "package\\|" - "pragma\\|" - "procedure\\|" - "protected[ \t]+body\\|" - "protected[ \t]+type\\|" - "protected\\|" + "function\\|" + "package[ \t]+body\\|" + "package\\|" + "pragma\\|" + "procedure\\|" + "protected[ \t]+body\\|" + "protected[ \t]+type\\|" + "protected\\|" ;; "p\\(\\(ackage\\|rotected\\)\\(\\|[ \t]+\\(body\\|type\\)\\)\ ;;\\|r\\(agma\\|ocedure\\)\\)\\|" - "task\\|" "task[ \t]+body\\|" - "task[ \t]+type" + "task[ \t]+type\\|" + "task" ;; "task\\(\\|[ \t]+body\\)" "\\)\\>[ \t]*" "\\(\\sw+\\(\\.\\sw*\\)*\\)?") @@ -3575,15 +3760,15 @@ "e\\(ls\\(e\\|if\\)\\|ntry\\|x\\(ception\\|it\\)\\)\\|for\\|" "generic\\|i[fns]\\|l\\(imited\\|oop\\)\\|mod\\|n\\(ot\\|ull\\)\\|" "o\\(r\\|thers\\|ut\\)\\|pr\\(ivate\\|otected\\)\\|" - "r\\(ange\\|e\\(cord\\|m\\|names\\|queue\\|turn\\|verse\\)\\)\\|" + "r\\(a\\(ise\\|nge\\)\\|e\\(cord\\|m\\|names\\|queue\\|turn\\|verse\\)\\)\\|" "se\\(lect\\|parate\\)\\|" "t\\(agged\\|erminate\\|hen\\)\\|until\\|" ; task removed "wh\\(ile\\|en\\)\\|xor" ; "when" added "\\)\\>") ;; ;; Anything following end and not already fontified is a body name. - '("\\<\\(end\\)\\>[ \t]+\\([a-zA-Z0-9_\\.]+\\)?" - (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t)) + '("\\<\\(end\\)\\>\\([ \t]+\\)?\\([a-zA-Z0-9_\\.]+\\)?" + (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) ;; ;; Variable name plus optional keywords followed by a type name. Slow. ; (list (concat "\\<\\(\\sw+\\)\\>[ \t]*:?[ \t]*" @@ -3594,7 +3779,7 @@ ;; ;; Optional keywords followed by a type name. (list (concat ; ":[ \t]*" - "\\<\\(access\\|constant\\|in\\|in[ \t]+out\\|out\\)\\>" + "\\<\\(access\\|constant\\|in[ \t]+out\\|in\\|out\\)\\>" "[ \t]*" "\\(\\sw+\\)?") '(1 font-lock-keyword-face nil t) '(2 font-lock-type-face nil t)) @@ -3619,19 +3804,28 @@ )) "Gaudy level highlighting for Ada mode.") -;; XEmacs change -(defvar ada-font-lock-keywords (if font-lock-maximum-decoration - ada-font-lock-keywords-2 - ada-font-lock-keywords-1) - "Default Expressions to highlight in Ada mode. -See the doc to `font-lock-maximum-decoration' for user configuration.") - -;; XEmacs change -(put 'ada-mode 'font-lock-defaults - '(ada-font-lock-keywords nil t ((?\_ . "w")))) +(defvar ada-font-lock-keywords ada-font-lock-keywords-1 + "Default expressions to highlight in Ada mode.") + + +;; set font-lock properties for XEmacs +(if (ada-xemacs) + (put 'ada-mode 'font-lock-defaults + '(ada-font-lock-keywords + nil t ((?\_ . "w")(?\. . "w")) beginning-of-line))) ;;; -;;; ???? +;;; support for outline +;;; + +;; used by outline-minor-mode +(defun ada-outline-level () + (save-excursion + (skip-chars-forward "\t ") + (current-column))) + +;;; +;;; generate body ;;; (defun ada-gen-comment-until-proc () ;; comment until spec of a procedure or a function.