rosen@siemens.UUCP (05/01/85)
------------------------------------------------------------------------------
Ada Mode for Gosling Emacs
Steven M. Rosen
Siemens Corporate Research and Support, Inc.
Research and Technology Laboratories
Princeton, NJ 08540
(609) 734-6538
rosen@siemens
------------------------------------------------------------------------------
The Ada mode Mlisp code defines a special mode for the Gosling version of
the Emacs editor. How it works with other versions of Emacs are unclear,
since it was written for and tested with the Gosling version. The Ada mode
is intended for use when editing Ada code and it is case insensitive when
dealing with reserved Ada words.
Place the file 'ada.ml' in your local Emacs Mlisp code library directory.
This is usually something like '/usr/lib/emacs/maclib'.
To have the editor invoke the Ada mode when editing Ada source code, place
the following lines in your '.emacs_pro' profile script.
(autoload "ada-mode" "ada.ml")
(auto-execute "ada-mode" "*.ada")
You can change the second line to have the Ada mode loaded when you are
editing files with extensions other than ".ada"
Ada mode automatically performs indenting while you are editing Ada code.
Is assumes that you are using a style that is similar to that used in the
Ada LRM (Language Reference Manual). It automatically indents and dedents
blocks of code by examing the syntax of the statements that you are writing.
Using very unusually or ad hoc coding styles will not produce results that
are anything spectacular.
Using this editing mode takes a bit of getting used to, but it shouldn't take
long to become comfortable with it. It is far from perfect, but I felt a
strong need to write it because the power of Emacs is too good to put to
waste and I was writting too much Ada code to be without it.
For those of you who attempt to make it run with other versions of Emacs
please let me know since I know nothing of how other versions differ from the
Gosling version. If you have any questions or find very strange bugs, send
them to the above address and I will attempt to fix them. The comment mode
was particularly hard to implement, but it does work fairly well when
writting most comments. I can't promise that writting comments won't do
strange stuff every so often. If you fix a bug or make an enhancement send
it to me so I can enjoy it as well. Have fun!
------------------------------------------------------------------------------
Variables and Functions
indent-change The number of spaces to use when indenting
statements. This number can be changed to 4 or
whatever you like. The default is 2.
^X-> Indents a region of code from 'dot' to 'mark' by
the value 'indent-change'.
^X-< Dedents a region of code from 'dot' to 'mark' by
the value 'indent-change'.
<ESC>-<TAB> Tab over to the column of the previous statement.
If at the beginning of a line, this will move the
cursor over to the same column as the most recent
line of code. If the current column is greater
that the column of the most recent line of code,
then a <TAB> character is inserted.
<TAB> Same as above, but you can disable the key binding
if hitting a <TAB> does things that you don't like.
<ESC>-<CR> If at the end of a line. inserts a <CR> and dedents
by 'indent-change'. If on a blank like, it just
dedents by 'indent-change'. This is used, for
example, when you wish to dedent a block of code,
and insert an 'end' statement such as in a 'for'
loop;
Example:
for i in 1 .. 100 loop
j := x(1);
z := sqrt(j); -- Type an <ESC>-<CR> here
end loop;
The <ESC>-<CR> is a signal that you want to close off
a block of code with and 'end' statement. If you
have forgotten to type the <ESC>-<CR> sequence and
you are sitting on a blank line type it anyway and
you will be repositioned automatically!
'--' Typing these two characters will automatically put
you into a special comment editing mode. This mode
will wrap lines automatically when you are typing
long comments. The characters '--' are
automatically created and inserted so the user does
not have to type them when writing a comment that
carries over to several lines. Typing a <CR> on
a blank line (after a '--' has been automatically
inserted), will leave the comment mode and return
you to editing statement editing by repositioning
the cursor in the correct place.
------------------------------------------------------------------------------rosen@siemens.UUCP (05/01/85)
; ----------------------------------------------------------------------------
; ada.ml - Ada mode for Emacs
; ----------------------------------------------------------------------------
;
; Ada Mode for Gosling Emacs
;
; Steven M. Rosen
;
; Siemens Corporate Research and Support, Inc.
; Research and Technology Laboratories
; Princeton, NJ 08540
; (609) 734-6538
;
; rosen@siemens
;
; ----------------------------------------------------------------------------
;
; This code is public domain and may be used or modified at your site
; in any fashion that you choose. No support or capabilities are
; implied or guaranteed by the release of this code. This disclaimer
; must be maintained in conjunction with the code.
;
; ----------------------------------------------------------------------------
;
; $Header: ada.ml,v 4.1 85/04/15 08:33:06 rosen Exp $
;
; Created 12-18-84
; Updated 04-15-85
;
; Bindings:
;
; indent-change = size of indentation (default to 2)
;
; Indent from (dot) to (mark) ^X->
; De-dent from (dot) to (mark) ^X-<
; Tab over to indent of most recent line of code <TAB>,<ESC><TAB>
; Decrease indent level and start newline <ESC>-<CR>
; Enter Ada comment mode "--"
;
; Features:
;
; o Automatically performs indentation while editing Ada code.
;
; o Automatically performs justification of Ada comments which
; begin on a blank line.
;
; o Automatically matches parentheses.
;
(defun
(ada-mode
(declare-buffer-specific in-comment-edit)
(setq-default indent-change 2)
(setq tab-size 8)
(setq in-comment-edit 0)
(setq mode-string "Ada")
(use-syntax-table "Ada")
(setq abbrev-mode 1)
(local-bind-to-key "begin-ada-comment" "-")
(local-bind-to-key "indent-region" "\^X>")
(local-bind-to-key "dedent-region" "\^X<")
(local-bind-to-key "tab-ada" "\t")
(local-bind-to-key "tab-ada" "\e\t")
(local-bind-to-key "indent-ada" "\^M")
(local-bind-to-key "de-dent-ada" "\e\^M")
(local-bind-to-key "show-matching-paren" ")")
;
; The following two lines can be include to suit local naming
; conventions:
;
; (modify-syntax-entry "w _")
; (modify-syntax-entry "w .")
;
;
(modify-syntax-entry "() (")
(modify-syntax-entry ")( )")
(modify-syntax-entry "\" \"")
(modify-syntax-entry " { --")
(modify-syntax-entry " } \n")
(error-occurred (ada-mode-hook))
(novalue)
)
)
(defun
(cond n running
(setq n 1)
(setq running 1)
(while (& running (< n (nargs)))
(if (arg n)
(setq running 0)
(setq n (+ n 2))))
(arg (+ n 1))))
(defun
(show-matching-paren
(insert-character (last-key-struck))
(save-excursion
(backward-paren)
(if (dot-is-visible)
(sit-for 5)
(progn
(beginning-of-line)
(set-mark)
(end-of-line)
(message (region-to-string)))))))
(defun
(leave-and-show
(setq abbrev-mode 1)
(show-matching-paren)))
(defun
(change-indentation colno ; indent by arg for region
(save-excursion
(if (< (mark) (dot))
(progn
(end-of-line)
(exchange-dot-and-mark)
(beginning-of-line))
(progn
(beginning-of-line)
(exchange-dot-and-mark)
(end-of-line)))
(narrow-region)
(end-of-file)
(beginning-of-line)
(setq colno (+ (current-indent) (arg 1)))
(delete-white-space)
(if (> colno 1)
(to-col colno))
(beginning-of-line)
(while (! (bobp))
(previous-line)
(setq colno (+ (current-indent) (arg 1)))
(delete-white-space)
(if (> colno 1)
(to-col colno))
(beginning-of-line))
(widen-region))))
(defun
(dedent-region ; dedents region
(change-indentation (- 0 indent-change))))
(defun
(indent-region colno ; indents region
(change-indentation indent-change)))
(defun
(tab-ada dotab colno
(if
(& (eobp) (eolp))
(progn
(insert-character '\n')
(backward-character))
)
(if
(| (& (bolp) (looking-at "[ \t]*\n"))
(< (current-column) (current-indent)))
(progn
(save-excursion
(while
(& (| (looking-at "[ \t]*\n")
(looking-at "[ \t]*--"))
(! (bobp)))
(progn
(previous-line)
(beginning-of-line)))
(setq colno (current-indent)))
(delete-white-space)
(to-col colno))
1
(insert-character '\t'))))
(defun
(de-dent-ada colno
(setq colno (- (current-indent) indent-change))
(beginning-of-line)
(if
(! (looking-at "[ \t]*\n"))
(progn
(end-of-line)
(newline)))
(delete-white-space)
(to-col colno)))
(defun
(indent-ada colno
(cond
(bolp)
(newline)
(! (eolp))
(newline-and-indent)
1
(progn
(save-excursion
(end-of-line)
(if (eobp)
(newline)))
(setq colno (current-indent))
(beginning-of-line)
(setq case-fold-search 1)
(cond
(& (= in-comment-edit 1)
(looking-at "[ \t]*-- \n"))
(progn
(setq in-comment-edit 0)
(beginning-of-line)
(kill-to-end-of-line)
(kill-to-end-of-line)
(if
(looking-at "[ \t]*\n")
(tab-ada)
1
(beginning-of-line))
(setq right-margin 1000)
(setq left-margin 1)
(setq prefix-string "")
(local-bind-to-key "begin-ada-comment" "-")
(local-bind-to-key "tab-ada" "\t")
(message "Finished editing ada comment"))
(& (= in-comment-edit 1)
(! (looking-at "[ \t]*--[ \t]*..")))
(progn
(end-of-line)
(newline)
(to-col comment-column)
(insert-string "-- "))
(& (= in-comment-edit 1)
(looking-at "[ \t]*--[ \t]*.."))
(progn
(end-of-line)
(newline-and-indent)
(insert-string "-- "))
(looking-at "[ \t]*--.*\n")
(progn
(end-of-line)
(newline)
(tab-ada))
(looking-at "[ \t]*begin\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*end\\b")
(progn
(end-of-line)
(newline)
(to-col (- colno indent-change)))
(looking-at "[ \t]*when\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*generic\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*declare\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*loop\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*if\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*elsif\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*else\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*while\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*case\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*for\\b")
(progn
(end-of-line)
(if (= (preceding-char) ';')
(newline-and-indent)
(progn
(newline)
(to-col (+ colno indent-change)))))
(looking-at "[ \t]*loop\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*or\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*exception\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*record\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*private\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(| (looking-at "[ \t]*type\\b")
(looking-at "[ \t]*subtype\\b"))
(progn
(end-of-line)
(backward-word)
(if
(looking-at "record\\b")
(progn
(setq colno (current-column))
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "is\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
1
(progn
(end-of-line)
(newline-and-indent))))
(looking-at "[ \t]*select\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*accept\\b")
(progn
(end-of-line)
(backward-word)
(if (looking-at "do\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(progn
(end-of-line)
(newline-and-indent))))
(looking-at "[ \t]*task\\b")
(progn
(end-of-line)
(backward-word)
(if (looking-at "is\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(progn
(end-of-line)
(newline-and-indent))))
(| (looking-at "[ \t]*procedure\\b")
(looking-at "[ \t]*function\\b"))
(progn
(end-of-line)
(backward-word)
(if (looking-at "is\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(progn
(end-of-line)
(newline-and-indent))))
(looking-at "[ \t]*package\\b")
(progn
(end-of-line)
(backward-word)
(if (looking-at "is\\b")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(progn
(end-of-line)
(newline-and-indent))))
(| (looking-at "[ \t]*.*:[^=].*[^;]\n")
(looking-at "[ \t]*.*:[ \t]*\n"))
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
(looking-at "[ \t]*<<.*>>")
(progn
(end-of-line)
(newline)
(to-col (+ colno indent-change)))
1
(progn
(setq colno (current-indent))
(if (looking-at "[ \t][ \t]*\n")
(kill-to-end-of-line))
(end-of-line)
(newline)
(to-col colno)))
(setq case-fold-search 0)))))
(defun
(begin-ada-comment c
(insert-character (last-key-struck))
(remove-local-binding "-")
(remove-local-binding "\t")
(setq c (get-tty-character))
(insert-character c)
(if
(&
(= c 45)
(looking-at "[ \t]*\n"))
(progn
(setq in-comment-edit 1)
(setq comment-column (- (current-column) 2))
(move-to-comment-column)
(setq left-margin comment-column)
(setq right-margin 76)
(setq prefix-string "-- ")
(cond
(looking-at "[ \t]*--")
(progn
(end-of-line)
(newline)
(to-col comment-column)
(insert-string "-- "))
1
(end-of-line))
(message "Editing ada comment")
)
1
(progn
(local-bind-to-key "begin-ada-comment" "-")
(local-bind-to-key "tab-ada" "\t")
))
)
)
(defun
(end-ada-comment
(setq in-comment-edit 0)
(setq right-margin 1000)
(if (!= (preceding-char) ' ') (insert-string " "))
(to-col comment-column)
(insert-string "--")
(newline)
(local-bind-to-key "tab-ada" "\t")
(message "Finished editing ada comment")
)
)
; ----------------------------------------------------------------------------