mirror of
https://github.com/PDP-10/its.git
synced 2026-04-27 20:48:35 +00:00
@@ -81,6 +81,7 @@ respond ":EJ" "\033xgenerate\033emacs;vt100\033emacs1;vt100\r"
|
|||||||
respond ":EJ" "\033xgenerate\033emacs;vt52\033emacs1;vt52\r"
|
respond ":EJ" "\033xgenerate\033emacs;vt52\033emacs1;vt52\r"
|
||||||
respond ":EJ" "\033xgenerate\033emacs;xlisp\033emacs1;xlisp\r"
|
respond ":EJ" "\033xgenerate\033emacs;xlisp\033emacs1;xlisp\r"
|
||||||
respond ":EJ" "\033xgenerate\033emacs;renum\033emacs1;renum\r"
|
respond ":EJ" "\033xgenerate\033emacs;renum\033emacs1;renum\r"
|
||||||
|
respond ":EJ" "\033xgenerate\033emacs;pascal\033emacs1;pascal\r"
|
||||||
|
|
||||||
respond ":EJ" "\033xrun\033einit\033? Document\r"
|
respond ":EJ" "\033xrun\033einit\033? Document\r"
|
||||||
respond "\n" "\030\003"
|
respond "\n" "\030\003"
|
||||||
|
|||||||
748
doc/info/epasc.32
Executable file
748
doc/info/epasc.32
Executable file
@@ -0,0 +1,748 @@
|
|||||||
|
-*-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.
|
||||||
|
* Hacker:: 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-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.
|
||||||
|
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.
|
||||||
|
|
||||||
|
Pascal Mode
|
||||||
|
Restart Pascal Mode
|
||||||
|
Pascal Expand Abbrevs in Region
|
||||||
|
Expands all abbrevs in region, but not in comments.
|
||||||
|
|
||||||
|
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. To get special compiler
|
||||||
|
switches or to load other files with yours, put the switches and other
|
||||||
|
files in the variable Compiler Switches.
|
||||||
|
|
||||||
|
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 *LST*. You can jump to
|
||||||
|
the position of the "next" error in your source file with the command
|
||||||
|
C-M-E. Do this till the message "(No more errors)" appears.
|
||||||
|
|
||||||
|
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). You do not want to be in ErrList mode when
|
||||||
|
you are not finding compiler errors because it is inefficient and it will be
|
||||||
|
creating a .LST file every time you compile.
|
||||||
|
|
||||||
|
Appologies: (1) In the current implementation this command creates a
|
||||||
|
compiler listing of your program, which could waste a lot of space. If this
|
||||||
|
is a problem, connect to a scratch directory while doing the compilation. It
|
||||||
|
is also a good idea to have your source program on the same directory you are
|
||||||
|
connected to. (2) The routine for jumping to the position of an error does
|
||||||
|
not adjust for changes you have made to your file after the compilation. This
|
||||||
|
means that it may show errors you have already fixed, and that the position it
|
||||||
|
jumps to will be wrong if (a) you change the number of pages before the page
|
||||||
|
with the error, or (b) you change the number of lines before the line with the
|
||||||
|
error on the page with the error, or (c) you change the number of characters
|
||||||
|
before position of the error on the line with the error.
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Automatic Capitalization: 0 If non-zero, all keywords typed or
|
||||||
|
inserted are capitalized.
|
||||||
|
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 Indent After BEGIN = 3, Indent After DO = 3, and Capitalize
|
||||||
|
Pascal Keywords = 1)
|
||||||
|
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 *)
|
||||||
|
(if Capitalize Pascal Keywords = 0, Indent After BEGIN = 4, 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 what argument to give.
|
||||||
|
|
||||||
|
^R Pascal Procedure and ^R Pascal Function will ask you for the
|
||||||
|
subprogram name and parameters before it 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,
|
||||||
|
you can 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-K ^R 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
|
||||||
|
over their <arg> lines and end up at their 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; 2 is set for the "block enders"; 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 and DO because when
|
||||||
|
they end a sub-statement, the following statement is nested from that
|
||||||
|
statement; and 10 is for BEGIN alone becuase it has significance as a
|
||||||
|
simple blocker the other "block beginners" don't have.
|
||||||
|
|
||||||
|
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 & In
|
||||||
|
ErrList Mode and the file PASCAL.MIC for places to make changes.
|
||||||
|
|
||||||
|
Also, 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 becuase 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 single quote, "'", on each
|
||||||
|
side. If your language uses different or alternate string delimiters
|
||||||
|
this will have to be changed in line, too.
|
||||||
|
|
||||||
|
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 are particularly brilliant;
|
||||||
|
instead the problem is that 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 a listing file 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.
|
||||||
|
|
||||||
|
M-X & Compile Compilation grabs the listing file in the buffer *LST*
|
||||||
|
and deletes the file from disk. Then it calls M-X & Save Errors to
|
||||||
|
extract the relevant information the errors from the listing file and
|
||||||
|
build a q-vector to contain them. To find each error we search for
|
||||||
|
a consistent string which the compiler puts on error lines. From the
|
||||||
|
error line we get the error message (to display) and the position in
|
||||||
|
the line of the error. From the previous line we extract the line
|
||||||
|
number. While we are searching for the error messages we also keep
|
||||||
|
the current page active.
|
||||||
|
|
||||||
|
M-X ^R Next Error just keeps an index into the q-vector of error
|
||||||
|
information. Each time it is called it updates the pointer, hops to
|
||||||
|
page, line, and line pos of the error and prints out the error
|
||||||
|
message.
|
||||||
|
|
||||||
|
This will all work much better when I 1) hack the compiler to put out
|
||||||
|
an error listing which contains just the errors and has the
|
||||||
|
information I need in a more direct format (I might even convince it
|
||||||
|
to give me the character position of the errors) and 2) hack TECO to
|
||||||
|
have updating marks in the file. As things stand now, if the user
|
||||||
|
inserts a page before the page of the error, or a line before the line
|
||||||
|
of the error in the page of the error, or a character before the
|
||||||
|
position of the error in the line of the error, everything is messed
|
||||||
|
up. All those operations are reasonably likely in the course of
|
||||||
|
fixing the previous errors. The fix will be to mark the positions of
|
||||||
|
all the errors with updating marks so that we can still find them
|
||||||
|
after all the changes have taken place.
|
||||||
|
|
||||||
|
|
||||||
|
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 totally ignored. I could find no clean way to handle
|
||||||
|
them.
|
||||||
|
Fix: Correct behavior = ? Statement labels (those which start on
|
||||||
|
the left margin?) should be totally ignored, 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.
|
||||||
|
D: After a THEN when it is on the same line as the IF.
|
||||||
|
|
||||||
|
2. Mark Procedure should be able to handle procedures with nested
|
||||||
|
procedures.
|
||||||
|
|
||||||
|
3. Automatic capitalization should not expand the words in comments.
|
||||||
|
This is easy but expensive to do. You just put a macro on each
|
||||||
|
expansion definition which does a search backwards for an open or
|
||||||
|
close comment. If an open comment is found, we are in an abbrev
|
||||||
|
and the abbrev should be unexpanded.
|
||||||
|
|
||||||
|
4. 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;
|
||||||
|
|
||||||
|
5. 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 "Indent After <x>" to help out.
|
||||||
|
|
||||||
|
6. The language dependancies of Mark Procedure and the insert routines
|
||||||
|
should be eliminated. The insert routines should have one driver
|
||||||
|
to which a schema is passed; they are too ad hoc and messy as it is.
|
||||||
|
| ||||||