Google
 

Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - info/epasc.info
There are no other files named epasc.info in the archive.
-*-Text-*-

File: EPASC	Node: Top	Up: (EMACS)Top	Next: Available

PASCAL mode in EMACS provides support for inputing and editing Pascal
code.  You should be in Pascal Mode automatically when you edit a
Pascal file.  You can call it directly by loading the Pascal library
(M-X Load Library <esc> Pascal <cr>) and giving the command M-X Pascal Mode.

* Menu:

* Available::		List of all special commands.
* Compile::		Macros for hopping right to your compiler errors.
* Variables::		Synopsis of the customization variables.
* Indent::		Indenting old and new lines of code.
* Statements::		Inserting complete structured statements.
* Comments::		Things you can do with comments in PASCAL mode.
* Paren Groups::	Commands which manipulate parenthesized expressions.
* Hints::		Other commands useful for editing Pascal code.
* Hackers::		Information for hackers or the very interested.

Node: Available,  Previous: Top,  Next: Compile,	Up: Top

Commands which start on keys:

C-M-I		The main indentation driver, described under Indent.
LINEFEED	Does a CRLF, then a C-M-I.  Useful at the ends of lines.
C-M-?		Explains the last indentation, if you're curious.
C-M-\,C-M-G,M-G	Indent Pascal Region (re-indent all lines in region)

Rubout		TAB-hacking Rubout (converts TABs to spaces).
C-Rubout	Normal Rubout.

M-;		Start comment at end of line. *note comments: comments.
C-M-*		Insert a comment right here (don't re-indent)
C-M-$		Global Pascal Comment

C-M-N		Forward over a BEGIN/END (or REPEAT/UNTIL etc.) pair.
C-M-P		Backward over a BEGIN/END pair.
C-M-H		Mark Procedure

C-M-.		Prefix for Structured Insert Commands. *note: St: Statements

C-M-E		If in ErrList Mode, jumps to position of next compiler error
		and prints the error in the echo area. *note Error: Compile

C-M-,		Causes file currently being edited to be compiled and run.
 		*note Compile: Compile

C-M-C		Same Capitalization, make all occurences of word same cap.
C-M-S		No Comment Search, search for something ignoring
		comment contents.

C-M-+		Turns previous variable name into command to increment
		that variable.  That is, FOO C-M-+ turns into
		FOO:= FOO + 1;
C-M-'		Inserts a string of specified length and lets you
		recursively edit the contents of the string in
		overwrite mode.  String length is in variable
		String Length Default.  *note Variables: Variables
C-M-{		Pulls non-comment text from previous line beginning at
		character (asked for) and puts it on this line.  Also
		performs indentation on the result.  Useful when you
		want to change the way a line is broken.

M-X Pascal Mode
		Restart Pascal Mode
M-X Pascal Expand Abbrevs in Region
		Expands all abbrevs in region, but not in comments.
M-X Capitalize Pascal Keywords
		Causes all keywords typed or inserted to be capitalized.
		See variable Automatic Capitalization for how to do this
		automatically.

Node: Compile,  Previous: Available,  Next: Variables,	Up: Top

  With the command M-X Compile (C-M-,) you can automatically compile
and execute your program in an inferior exec.  You will probably need
to type "POP" (on TWENEX) or $P (on ITS) after the compilation to
return from the inferior exec to EMACS.  Hint:  to get special
compiler switches or to load other files with yours, put the switches
and other files in the variable Compiler Switches; this variable will
be appended to the compile command line (*Note Variables:
(EMACS)Variables.).

  If you are in ErrList Mode, the compiler errors you see when you do
M-X Compile (C-M-,) are saved away in the buffer named *ErrList*.  The
command M-X ^R Next Error (C-M-E) will move to the position of an
error in your Pascal program and type out what the error was in the
echo area (at the bottom of the screen).

  To go into ErrList Mode, just give the command M-X ErrList Mode.  To
get out, give the same command again.  You can also get in by setting
the variable, ErrList Mode, to something other than zero.  This will
work from an init or evars file (*Note Init: (EMACS)INIT.) or a local
modes list (*Note Locals: (EMACS)Locals.).


Node: Variables, Previous: Available, Up: Top, Next: Indent

 The PASCAL library has several switches  you can set to customize  its
behavior.  For info on how to set variables *note Vars: (EMACS)Variables. 

Variable name		      D	 Explaination
----------------------------------------------------------------------------
ErrList Mode                  0  If non-zero, compiler errors found with
				 M-X Compile (C-M-,) are saved so that
				 you can step through them with C-M-E.

Indent Align Only             0  If non-zero, LINEFEED only aligns
				 with previous line (does ^R Indent Nested).

Indent After ---	      4  For any keyword, Indent After <keywd>
				 is the amount to indent extra after
				 seeing <keywd>.
Begin-Block Body Indentation  4	 Default indent after BEGIN,
				 REPEAT, CASE, LOOP, RECORD.
IF-Block Body Indentation     4	 Default indent after IF, THEN, ELSE,
				 WHILE, FOR, DO, WITH.
Decl Body Indentation         4	 Default indent after CONST, TYPE,
				 VAR, LABEL.
--- Body Indentation 	      4  Amount to indent Body, but not variables, of
				 subprogram keyword specified.  Indentation
				 for declaration section is Indent After ---
PROCEDURE Body Indentation    4  Default for both "--- Body Indentation" and
				 "Indent After ---" for PROCEDURE, FUNCTION,
				 and PROGRAM. 
Indent After Everything	      4	 Default for any value not specified.

Reindent ENDs		      1	 0 = leave ENDs & UNTILs indented same as 
				 statements in block; 1 = align END's with
				 corresponding BEGIN line.
Match Block Word	      0  If non-zero, indentation after line with
				 the keyword BEGIN, REPEAT, CASE, and RECORD
				 will start from the position of the keyword
				 within the line, not the indentation of the
				 line.
Match ----		      0  For any keyword, if this is set indentation
				 will be from that keyword, not the line's
				 indentation.
Match (			      1  Like Match ----, only it defaults to 1. 

BEGIN on same line	      0  Non-zero means inserted BEGINs are
				 left on same line as stmt.
THEN on same line	      1	 Non-zero means leave THEN on line
				 with IF.
ELSE on same line	      0  Non-zero means try to stick ELSE on
				 end of previous line.
---- on same line	      0  Like the above for many other keywords.

Automatic Capitalization      0  If non-zero before Pascal Mode Entered
				 (calling MM & Default Init Pascal Mode),
				 all keywords typed or inserted are
				 capitalized.  If set non-zero later,
				 only keywords inserted are capitalized.
				 See M-X Capitalize Pascal Keywords.

String Length Default         10 Default length for ^R Insert String
Insert Comments		      1  Non-zero means insert functions
				 insert some labeling comments.

-------------------Comment Controlling Variables--------------------
Comment Column		      0	 Where EMACS tries to start your
				 comments (here or after your code). 
Global Comment Column	      10 Comment Column when doing a Global
				 Pascal Comment.
Pascal Star Line Width	      51 Do Describe on ^R Global Pascal Comment.
Comment Rounding	      "+1"  Algorithm which EMACS uses
				 to figure where to start the comment
				 if your code extends beyond the
				 comment column.
* Menu:

* Examples::		Variable settings for various kinds of indentation.

File: EPASC, Node: Indent, Up: Top, Previous: Variables, Next: Statements

 PASCAL mode allows easy formatting of Pascal code as you type it in.  Its
main concern is with indentation, not with breaking lines, so that it fits in
well with most styles of formatting.  There is also a great deal of
customization avaialable to suit individual tastes. Note: If the load is too
high to effectively use the indentation package, or you just don't get along
with it, you can turn it off by setting Indent Align Only to 1.  This will
force the indentation to only align with the previous line, without trying to
figure out how much less or more to indent.

* Menu:

* Basics::		The basics of using PASCAL mode indentation
* Details::		Some details about how indentation mode operates
* Examples::		Variable settings for various kinds of indentation.

Node: Basics,  Previous: Indent,  Up: Indent,  Next: Details

The two indentation commands are LINEFEED and C-M-I.  C-M-I calls the
main routine to do indenting, and LINEFEED does a return, then calls
C-M-I.

While you are typing in a program, the normal mode of operation will
be to type in your lines of code, and at the end of each line type
LINEFEED instead of Return.  This will cause EMACS to decide how far
in the next statement should be indented.  You can get the same effect
by typing Return then C-M-I.  C-M-I can also be used to indent or
re-indent existing lines.  If you type C-M-I at the beginning of an
existing line, the line will be indented the way that EMACS thinks it
ought to be.  Typing C-M-I in the middle of a line will cause the rest
of the line to be lined up with a word in the line above (i.e.  M-X ^R
Pascal Indent Relative is called).

A special case is when you type LINEFEED after an END or UNTIL, or
type C-M-I at the beginning of the line after an END or UNTIL.  Doing
either of these causes EMACS to go back and decide which BEGIN or
REPEAT or other keyword the END (UNTIL) matches.  It then will go and
move the END (UNTIL) so that it lines up with the BEGIN or whatever.
This allows you to not have to worry about trying to convince it that
the line you are about to type is an END, not just another statement.
Just type the END, which will be in the wrong place, then type
LINEFEED, like you would with any line.  It will go back and move the
END so that it's in the right place.  You can turn off this "feature"
by setting the variable Reindent ENDs to zero.

Note that, even though TABs are used for indentation, RUBOUT is
redefined so that TABs act like 8 spaces.  So, if you try to rub out a
TAB, what you will get as a result is that you've moved one character
position to the left on the screen.  If you want to get the ordinary
Rubout, you can use C-Rubout, which you can get by typing Control-^
followed by Rubout.

Using LINEFEED and C-M-I, you should be able to do all of the
formatting that you want.  In cases where it fails, complain!

Node: Details, Previous: Basics, Up: Indent, Next: Statements

If you know that EMACS is about to give you indentation that you don't
want (see *note Failure: Future Work, for some known cases) you can be
more specific about the indentation you want.  Giving an argument to
LINEFEED (or C-M-I) makes it run ^R Indent Nested.  Positive arguments
make it line up with a line <arg> levels out (to the left) of the
previous line and negative arguments make in indent -arg spaces
further in (to the right).  This also works if you've set Indent Align
Only.

If there is no argument then if the cursor is not at the left margin,
the indenter calls M-X ^R Pascal Indent Relative, which lines up with
successive keywords on the previous line.  Otherwise, if there is an
un-matched open parenthesis or open comment in the previous 10 lines,
it matches that.  Otherwise it calls the indenter.

If there is a keyword on the previous line and the line doesn't end
with ";", the new line is indented to the amount of the previous line
plus the amount specified by "Indent After <keyword>" for the last
keyword on the previous line.

If no keyword is found or the line ends with a sem, we just line up
with the previous statement, which may not be the previous line if
it is a nested statement or the END of a compound statement.

If the PREVIOUS line contains an END, it will be re-indented to match
the matching BEGIN, unless Reindent END is zero.

If the indentation you just got seems strange to you, you can get a
short description of what was done (including a pointer to the point
which was matched to get the base indentation) with M-X Print Last
Pascal Indenter (C-M-?).

To make the indenter ignore a keyword which it now recognizes, set the
variable "Indent After <x>" to -1.

A description of the algorithm used is in *note Internal: Indentation.

Node: Statements,  Previous: Indent,  Up: Top,  Next: Comments

These are the available insertion commands:

C-M-. E		^R Pascal END
C-M-. W		^R Pascal WHILE
C-M-. F		^R Pascal FOR
C-M-. 	^R Pascal WITH
C-M-. I		^R Pascal IF
C-M-. 	^R Pascal ELSE
C-M-. P		^R Pascal PROCEDURE
C-M-. 	^R Pascal FUNCTION
C-M-. 	^R Pascal PROGRAM
C-M-. R		^R Pascal REPEAT
C-M-. B		^R Pascal BEGIN
C-M-. C		^R Pascal CASE
C-M-. 	^R Pascal RECORD
C-M-. B		^R Pascal BEGIN

M-X ^R Pascal End goes back to an open block statement and inserts the
corresponding close block (END or UNTIL).  Use Describe  (see *Note
Help:  (EMACS)Help.) on ^R Pascal End for more details.

The general purpose of the other commands is to insert the redundant
text in their kinds of statements. For some individualities of the
commands, you can see their internal documentation via the Describe
command.  Here are some of their general properties:

The column indented to is the current horizontal position or the
indentation of the current line, if there is text on the line.  For
instance, if the cursor is at column three and C-M-. F is pressed,
this is inserted:
   FOR <cursor here> DO
      BEGIN
	 <indented to here>
      END; (* FOR *)
(assuming Capitalize Pascal Keywords = 1, Indent After BEGIN = 3, and
Indent After DO = 3) but if the cursor is at the end of this line:
        WHILE true DO <cursor here>
and C-M-B is pressed, this results:
        WHILE true DO BEGIN
	   <cursor here>
	END;  (* WHILE *)
(assuming Capitalize Pascal Keywords = 1, Indent After BEGIN = 3, and
Match Block Word = 0).

   If given a positive argument, the macros will not insert the
BEGIN/END pair (where this makes sense), except the PROCEDURE/FUNCTION/
PROGRAM group will not insert the line with VAR.  If given a
negative argument, they will try to enclose -<arg> lines within the
BEGIN/END (or whatever) pair.  If you want to enclose the region
instead, do ^R Count Line Region (M-=) to see how many lines that is.

   ^R Pascal Procedure and ^R Pascal Function and ^R Pascal Program
will ask you for a name and parameters before they inserts the rest of
the block.  Type them normally into the buffer where the cursor is
left and exit with C-M-C (C-M-Z on Twenex).

   Undoing and fixing: Any of the calls to these functions can be be
taken back with M-X Undo$.  Remember, they insert a lot of comments;
if you don't want them, they can be killed individually with C-M-;.
Setting Insert Comments to zero will stop them all from being
inserted.

* Menu:

* Examples::		Variable settings for various kinds of indentation.

Node: Examples, Previous: Statements, Up: Top, Next: Statements


EXAMPLE1

  Variable settings.

Procedure Body Indentation: 2
Indent After Procedure: 5
Indent after IF: 2
Indent after THEN: 2
Indent after ELSE: 1
Indent after BEGIN: 3
Indent after REPEAT: 4
Indent after DO: 3
Automatic Capitalization: 0
BEGIN on same line: 0
THEN on same line: 0
ELSE on same line: 0

  Indentation (assuming start column is left margin).


procedure xx;

  var b: integer;
     begin (* xx *)
        March;
     end; (* xx *)

while Foo do
   begin
      Bar;
   end;	(* while *)

repeat
    Fosit;
until false;

if x
  then
    Bar
  else
   Rag;


EXAMPLE2:

  The modern indentation style proposed by Arthur Sale might have these
  settings:

Indent After Everything: 4
Automatic Capitalization: 1
BEGIN on same line: 1
THEN on same line: 1
ELSE on same line: 1
Match Block Word: 0

   With resulting code indented this way:
IF cond THEN BEGIN
    stmts;
END; (* IF *)

PROCEDURE Foo(bar,baz: real);

    VAR i: INTEGER;

    BEGIN (* Foo *)
	body;
    END; (* Foo *)

Node: Comments,  Previous: Statements,  Up: Top,  Next: Paren Groups

There are various things that you can do with comments in Pascal mode
(most also work in other language mode).  You can ask EMACS to start
comments for you, go to the next comment, and go to the previous
comment.  There is also a global comment mode (only in Pascal) which
allows you to enter a large comment, for instance at the beginning of
a program.

To ask EMACS to start a comment on the current line, use the command
Meta-;.  This will go to the end of the line and start a comment by
inserting open and close comment brackets and leaving the point
between them.  If there is already a comment on the line, EMACS will
realign it and then move into it.  C-U C-X ; will create a comment
lined up with comment on the previous line, and make all subsequent
comments also try to start in that column.  M-* will create a comment
at the current cursor position always (Pascal only).

If you want EMACS to always start comments no further left than a
specific column, go to the column you want, and type C-X ; (Control-X
Semicolon).  EMACS should confirm by typing Comment Column = n at the
bottom of the screen, where n is the column you changed it to.  If you
want to have the same one set up for you each time you start Pascal
mode, set the variable Comment Column in you Pascal Mode Hook.
*Note Vars: (EMACS)Variables.

If you want to go on and enter a comment at the end of the next line,
use the command M-N to move down to (and maybe create) a comment on
the next line.  Similarly, you can use M-P to go up a line and start a
comment.

To kill a comment at the end of the line use C-M-;.  You can also use
this to move a comment by killing it and then un-killing it where you
want it to be.  *Note Un-Killing: (EMACS)Un-killing.

There is another way to enter comments, and that is the global
comment mode.  To use this, use the command M-X Global Pascal Comment.
This will enter a special mode where you will be entering a block of
comments.  Each comment will start in the 2nd column, and will start
with "(**" (or "{*").  You can use the commands M-;, M-N, and M-P as
described above.  When you're done entering the block of comments,
exit the inner mode with C-M-C (C-M-Z on Twenex).  As it leaves, it
will convert the beginnings of the comments to "(* " (or "{ ", and
move the ends so that they all line up.

As it leaves the global comment mode, it will also convert any line
which looks like "(*** *)" into a line of stars and spaces:
 "(* * * ...*)".

Node: Paren Groups,  Previous: Comments,  Up: Top,  Next: Hints

The parenthesis manipulation functions are really LISP commands and
their names reflect it.  A "Sexp" is (for our purposes) either a
parenthesized expression or a single word (depending what we are next
to).  Commands for manipulating them are:

C-M-F		^R Forward Sexp
C-M-B		^R Backward Sexp
C-M-K		^R Kill Sexp
C-M-Rubout	^R Backward Kill Sexp
C-M-@		^R Mark Sexp

In addition to the Sexp's there are "Lists".  These are also
parenthesized expressions, but we have additional commands for moving
"down" inside the parens and "up" out of the paren group.

C-M-(		^R Backward Up List
C-M-)		^R Forward Up List
C-M-D		^R Down List
C-M-U		^R Backward Up List


Node: Hints,  Previous: Paren Groups,  Up: Top,  Next: Hackers

. To figure out your BEGIN/END pairing, use the command M-X Display
  Matching Lines to show only the lines with a BEGIN or END.  You can
  also use C-M-P and C-M-N to move over matching BEGIN/END (or
  REPEAT/UNTIL, etc.) pairs.

. Use M-X ^R Indent Rigidly (C-X TAB) to conveniently change the
  indentation of a block of text.

. Use ^R Back to Indentation (M-M) to move to the logical start of
  this line.  ^R Up Indented Line and ^R Down Indented Line will move
  to the <arg>th line and end up at its logical start.

Node: Hackers,  Previous: Hints,  Up: Top,  Next: Philosophy

This section is designed for people intending to do work on Pascal
Mode, to install it on another system, or to modify it into another
language.  It might also be interesting and/or helpful for a heavy
user of Pascal Mode.

* Menu:

* Philosophy::		Reasons why some things are how they are.
* Syntax Table::	Table which keeps the syntax of interesting keywords.
* Install::		Information for somebody installing or re-targetting.
* Algorithms::		Description of the less obvious algorithms used.
* Future Work::		If you know or want to learn TECO and have time...

Node: Philosophy,  Previous: Hackers,  Up: Hackers,  Next: Syntax Table

The idea behind Pascal (or any language mode) in EMACS is to give the
user extra support by allowing the editor to know something about the
higher level structure of his file.  At the same time, the reason
there is not a seperate "structured editor" for Pascal is so that the
basic commands will be common between all editing tasks.

Because of the last point, it has been my attempt in Pascal Mode to
minimize the disturbance of the user's basic editing.  That's why I
broke with standard EMACS philosophy and did not put the line indenter
on TAB.

The reasons all of the keys defined are control-meta- commands are 1)
to provide a better mnemonic for the user to remember where all the
Pascal commands are, 2) because they replace unused keys or dangerous
LISP commands, and 3) so that there will be a consistent "language
prefix" which users know will be squashed by the major modes.  It is
my opinion that more major modes should follow this practice.

A lot of work has gone in to making the indentation commands correct
and fast.  This allows the user to ignore the question of indentation
when typing in text and frees his concentration for more important
aspects of the program.  At the same time, I have attempted to keep
the base algorithm as simple as possible; the user has to understand
what is going on in the algorithm to get the most good out of it, and
simple is better for that.

Node: Syntax Table, Previous: Philosophy, Up: Hackers, Next: Install

The syntax table is read from EMACS:PASCAL.SYN by the function M-X &
Read Keywords when Pascal is loaded.  There is one line per keyword.
The first word on the line is the keyword itself, the second word is
the default indentation, and the third word is a binary word of the
"descriptor" bits.  On loading the Pascal library, the file is read
into the q-vector variable Pascal Syntax Table.  This variable exactly
mirrors the structure of the file.

The bits in the status word are decoded as follows: 1 (the least
significant) is set for keywords which are "block beginners", things
like BEGIN, REPEAT, RECORD & CASE and also "("; 2 is set for the
"block enders", END & UNTIL and ")"; 3 & 4 are set for ELSE and THEN,
resp., because these are matched up with each other when going back
over a nested statement; 5 is for non-compounding and non-if keywords
like WHILE, DO, WITH; 6 is for the subprogram statements, PROGRAM,
PROCEDURE & FUNCTION; 7 is for the declaration keywords, LABEL, TYPE,
CONST, & VAR; 8 is for the IF-Block Body keywords (IF, THEN, ELSE); 9
is for THEN, DO & OF and 10 is for CASE, WHILE, WITH & FOR because
they bracket the control part of a statement; 11 is for BEGIN alone
because it has significance as a simple blocker the other "block
beginners" don't have; 12 is for REPEAT.


Node: Install, Previous: Syntax Table, Up: Hackers, Next: Algorithms

Most of the language dependancies for indentation are keyed through
the syntax table.  If you can't get the indenter to work for your site
by making changes to the syntax table, try adding a new entry to the
syntax table and updating the indent macro for both languages.  It
will be nice to have as much in common as possible between structured
languages.

Any characters which can appear in keywords should be listed in the
routines & Back To Word and & Forward To Word.

Macros which would probably have to be replaced are Pascal Mode and &
Default Init Pascal Mode.  Macros which will have to be modified or
replaced because of language dependancies which are not in the syntax
table are the insert macros, Mark Procedure, and & Save Errors (which
goes through the listing file getting the info on all the compiler
errors when ErrList mode is in effect).  There is also a shameful but
necessary direct dependance on the syntax of the compiler.  See M-X &
Compile Compilation for places to make changes.

In general, when I look to ignore comments or strings I assume that
both "{}" and "(* *)" are comment delimiters in addition to the
variables Comment Start and Comment End.  This is because our version
of Pascal allows both those comment delimiters and more.  The routines
where this occurs are M-X & Forward To Chars, M-X & Back To Chars, and
M-X ^R Pascal Begin.  In the former two routines I pass over quoted
strings, which I assume are bounded by a the ..D quote char on each
side.

Node: Algorithms, Previous: Install, Up: Hackers, Next: Future Work

Most of the algorithms used in the file are straight forward and are
commented in line.

* Menu:

* Indentation::		How & Indent Line works
* Error Saving::	Kluges for ErrList mode

Node: Indentation, Previous: Algorithms, Up: Algorithms, Next: Error Saving

The indent macro has four phases it goes through in trying to indent a
line:  scanning for the key token, moving back over begin/end pairs,
moving back to controlling statements if the one found is nested, and
rejoining split lines.

The first involves scaning back in the immediately previous line (or
to any line which has an open paren or open comment for a close on
this line) till it finds a keyword with a non-negative indent value or
a block ender.  If a semicolon is encountered it's presence is noted
by setting the indent value to -2 (it starts as -1); after we see a
sem we usually don't care if there is a keyword with a non-negative
indent value (we want to line up with "IF x < 0 THEN Write(x);").
However, we do pick up an indent value if we see one of the subprogram
keywords or declaration keywords (you want to indent extra after "VAR
i: Integer;").

At the end of that stage, if we have found a positive indent keyword,
we are at our goal; we will indent from this statement offset by the
value of the indent for that keyword and skip the next two stages.  If
we found a Block Beginner and Match Block Word is set, allign with the
word (and goto DONE0 to avoid calculating a new position).  Otherwise
align with the indentation of this statement (DONE1).

Otherwise, we just want to line up with the proper line, but finding
it will be tricky.  In the next stage we continue back over the last
line (and those connected by parens) to see if there is a block ender.
If so, we use Back Level to move backwards to the matching beginer;
the statement controling the one with the beginner keyword is the one
we want to line up the next statement with.

This section also takes care of re-indenting ENDs.  There are two
philosophies on aligning ENDs which are supported.  One says they
should be lined up with the statements of the block.  To get this
behavior the user sets Reindent End to zero -- END's will be left
alone where the normal statement indenter put them.  The philosophy
holds that the END (or UNTIL) should match the indentation of either
the line with the beginner or (if Match Block Word is set) the
beginner word itself.  In this case the END will not be indented
correctly in the text because we indented it for a statement; this
stage takes care of properly re-aligning it.

The next stage goes back over nested statements (all substatements
which end in THEN or DO nest the next statement) and THEN/ELSE pairs
to the actual line we want to indent from.  If we come to a THEN and
the there was no SEM on the first line saw in the back parsing, assume
the user is about to type an ELSE and indent the line the same as the
THEN.

When we finally have the exact statement we want to match, we still
can't count on it's being entirely on the line we went to.  When
conditions for an IF or WHILE or such get too large people often split
them between several lines.  The simple fix is to scan back to the
matching IF or WHILE or such whenever we wound up on a DO or THEN.
The two complications are 1) we want to do the same thing for THEN
BEGIN and 2) many people like to have the THEN on a seperate line from
the IF.  To fix (1) we just move back over a BEGIN before checking for
the THEN/ELSE and to fix (2), we check to be sure that the THEN or DO
is not the first word on the line.

Now we finally have a line and a position in a line.  The indentation
is done and properly marked to be shown if the user is curious about
what happened.


Node: Error Saving, Previous: Indentation, Up: Algorithms, Next: Algorithms

None of the algorithms for this part is particularly brilliant; I
describe them because they are somewhat klugy.  There has been a
constant race with the compiler developers who like to change the
syntax for calling the compiler with an error listing and to change
the format of the listing file itself.

When ErrList mode is selected, the hooks used by M-X Compile are
arranged so that a listing file will be created on the compilation and
so that M-X & Compile Compilation will be called after the compile.  &
Compile Compilation visits the error listing file in the buffer
*ErrList*.  Then it calls M-X & Save Errors to extract the relevant
information from the listing file and build a q-vector to contain
them.

M-X ^R Next Error keeps an index into the q-vector of error
information.  Each time it is called it updates the pointer, hops to
the position of the error and prints out the error message.


Node: Future Work, Previous: Algorithms, Up: Hackers, Next: Hackers
1. Cases the indenter gets wrong
   A: After the declarations and before the BEGIN of a block we indent
      for another declaration.
   Fix: Re-indent previous line when BEGIN typed if previous keyword
      is a declaration keyword or subprogram keyword? Bad.

   B: After the last END of a procedure.  Tends to line up with a
      declaration statement of the ENDed procedure instead of with the
      PROCEDURE line itself.
   Fix: ?

   C: Labels are not dealt with. I could find no clean way to handle
	them.
   Fix: Correct behavior = ? Statement labels (those which start on
	the left margin?) should be invisible, both in syntactic
	processing (make "back to token" ignore them?) and in
	determining the indentation of the line they're on.  Case
	labels should probably have an indent after them if there is
	no text after them, but they should be ignored if there is
	text on the same line as them.

2. Mark Procedure should be able to handle nested procedures.

3. Match Block Word should be replaced by a bit per keyword saying
   whether to match that keyword.  This is for two reasons: 1) many
   people like to match RECORD but few like to match BEGIN and 2) this
   will allow people to indent like this if they want:
      IF c1 THEN WHILE c2 DO
                     s;

4. The insert commands should be hacked to be one command parsing a
   general schema string.  Maybe add a bit to the symbol table
   corresponding to "<x> on Same Line" to help out.

5. The language dependancies of Mark Procedure should be eliminated.

6. Make backward searches for keywords again use "S" instead of
   checking each word found against the syntax table.  This way is too
   inefficient.

7. Takes too long to check for user customization variables.

8. There should be some indentation after := .

9. C-M-A goes to beginning of function.