Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!usc!cs.utexas.edu!uunet!watmath!watmsg!gjditchfield From: gjditchfield@watmsg.waterloo.edu (Glen Ditchfield) Newsgroups: gnu.emacs Subject: Re: Looking for Pascal mode (part 2 of 2) Keywords: Pascal, Gnu-Emacs Message-ID: <27520@watmath.waterloo.edu> Date: 5 Jul 89 15:44:28 GMT References: <349@node13.mecazh.UUCP> Sender: daemon@watmath.waterloo.edu Reply-To: gjditchfield@watmsg.waterloo.edu (Glen Ditchfield) Organization: U. of Waterloo, Ontario Lines: 366 This is a texinfo file describing a (separately posted) Pascal mode. Glen Ditchfield gjditchfield@violet.uwaterloo.ca Office: DC 2517 Dept. of Computer Science, U of Waterloo, Waterloo, Ontario, Canada, N2L 3G1 "... and the rest, we will spend foolishly!" -- _Svengali_ ------------------------------------------------------------------------------- @setfilename Pascal @node Pascal, Commands, (dir), (dir) @section Pascal Mode Pascal mode is a collection of functions which make the task of typing Pascal source easier by automating indentation and by inserting `noise' words for you. Complex Pascal structures are handled by template insertion. Skeletons of Pascal structures are inserted, and the typist fills in the missing parts. Template insertion is invoked by Emacs' abbreviation expansion mechanism, to minimize the number of key sequences used. In most cases, the abbreviations chosen are Pascal reserved words. Different indentation styles can be accommodated by changing the templates used. To use pascal mode, you should make sure that @code{pascal-mode.elc} is in one of the directories in your load path, and you should put these lines in your Emacs initialization file:@refill @example (autoload 'pascal-mode "pascal-mode" t) (setq auto-mode-alist (cons (cons "\\.p$" 'pascal-mode) auto-mode-alist)) @end example @menu * Commands:: Commands defined by pascal-mode. * Abbreviations:: Abbreviation expansion; default abbreviations. * Variables:: Variables that control Pascal mode behavior. * Customization:: How to adjust Pascal mode behavior. * Elision:: Support for selective hiding of Pascal text. @end menu Pascal mode and it's documentation is distributed under the terms of the GNU Emacs General Public License (type @key{C-h} @key{C-c}) and the statement of no warranty (type @key{C-h} @key{C-w}).@refill I am sure that Pascal mode has bugs. Please send bug reports, bug fixes, and suggestions to me. I don't promise to fix them, but you never know@dots{}. At the time of writing, my addresses are @quotation Glen Ditchfield Department of Computer Science, University of Waterloo, Waterloo, Ontario gjditchfield@violet.uwaterloo.ca @end quotation @node Commands, Abbreviations, Pascal, Pascal @subsection Commands The following commands are defined by, or particularly useful in, Pascal mode. @table @kbd @item M-x pascal-mode Switch to Pascal mode in the current buffer. @item @key{RET} Create a new line, and leave point at the left margin on the new line. (@code{newline}) @item @key{LFD} Create a new line, and indent the line. (@code{newline-check-and-indent}) @item @key{TAB} Reindent the current line. (@code{pascal-indent-line}) @item M-@key{TAB} ``Outdent'' the current line. (@code{pascal-outdent-line}). @item C-c C-b Wrap a @code{begin @dots{} end} statement around the region. (@code{pascal-beginnify-region}). @item M-C-f @itemx M-C-b Skip forward and backward, respectively, over matching parentheses, @code{record} declarations, and @code{begin}, @code{case}, and @code{repeat} statements. (Skipping backwards doesn't handle variant records properly.) (@code{pascal-forward-sexp}, @code{pascal-backward-sexp}) @item @key{DEL} Delete the previous character. Tabs are converted to spaces as the cursor moves backwards. (@code{backward-delete-char-untabify}) @item C-x ' Expand the abbreviation before point, even if Abbrev mode is turned off. (@code{expand-abbrev}) @item M-x list-abbrevs List all defined abbreviations, including those used by Pascal mode. @end table @code{pascal-mode} sets up data structures used by Pascal mode, and calls the value of @code{pascal-mode-hook} if that variable is non-nil. You may have to run this function to edit Pascal .h files, since Emacs assumes that .h files contain C code. (To avoid this, put the line `{-*-Pascal-*-}' at the start of all of your Pascal .h files.)@refill @key{LFD} is bound to @code{newline-check-and-indent}, which creates a new, properly indented line (see below). If the previous line contains an un-closed string, or if it contains an unclosed comment and you have defined `comment-multi-line' to be NIL, a warning message is printed in the minibuffer.@refill @key{TAB} reindents the current line. For both @key{TAB} and @key{LFD}, the indentation of the nearest previous line that is not flush with the left margin is used as an initial guess. If the previous line was not a complete statement, the indentation is increased by the value of `pascal-indent-level'. The heuristics used here are crude, so the indentation level may be increased unnecessarily.@refill @kbd{M-@key{TAB}} Reduces the current line's indentation. It does this by looking backwards for a line that is less indented than the current line, and using that indentation. This fixes most mistakes made by @key{TAB}.@refill @node Abbreviations, Variables, Commands, Pascal @subsection Abbreviations When Abbrev mode is on (as it normally will be), typing an abbreviation followed by a punctuation character or blank causes the abbreviation to be expanded. If the abbreviation stands for a Pascal template, Pascal mode will generally check to see if the abbreviation was typed in a comment or string. If it was, the abbreviation is not expanded. If it was typed in program text, the proper template is inserted. It is hard to decide whether the abbreviation is inside a comment or string, especially since there is no guarantee that the source code is syntactically correct. The scheme used will expand abbreviations that occur inside comments, but after nested comments. (This may not be a bad thing, since a typist in that situation is probably editing source code that has been ``commented out''.) A final problem: if the cursor just happens to be positioned at the end of a word that just happens to be an abbreviation, and you type a space, linefeed or punctuation character, the abbreviation gets expanded. If all this starts annoying you, you can turn off Abbrev-mode and use @kbd{C-x '} (`expand-abbrev') to explicitly insert templates. The default abbreviations and the Pascal structures that they insert are: @table @kbd @item ie If-then-else statement. @item if If-then statement. @item else Else clause. If the previous statement ended with a `;', that `;' is removed. @item ei Else-if-then clause. This is useful for building code sequences that look like @example if a then s1 else if b then s2 else if c then @dots{} @end example Again, any previous `;' is removed. @item while While-do statement. @item for For-to-do statement. @item with With statement. @item repeat Repeat-until statement. @item begin Begin statement. @item const Const declaration section. @item type Type declaration section. @item record Record type template. @item var Variable declaration section. Which template is inserted depends on whether the abbreviation occurs in a routine's formal parameter list or a declaration section. @item fun Function declaration. This abbreviation is also treated differently in parameter lists. @item proc Procedure declaration. This abbreviation is also treated differently in parameter lists. @item prog Program template. @item int Abbreviation for `integer'. (This makes life easier for C programmers). @end table This set of abbreviations will be installed the first time you use Pascal mode. When you leave Emacs, you will be given the option of saving them in a file called `.abbrev_defs'. Say yes, and it won't bother you again. Lots of documentation on abbreviations is stored in the Info tree; use C-h i if you are curious. @node Variables, Customization, Abbreviations, Pascal @subsection Variables You can re-define these values in your init file to adjust certain features to taste. @table @kbd @item comment-multi-line The default value, @code{nil}, means that comments should not span line boundaries. Set it to @code{t} if you let comments cross line boundaries. If it is @code{nil}, Pascal mode is more efficient, and newline-check- and-indent will warn you about unclosed comments. If you are typing a comment and use @kbd{M-@key{LFD}} to continue the comment on a new line, or if Fill mode is on and it starts a new line for you, comment delimiters will be inserted if comment-multi-line is nil. See the Info section on comments for a better explanation. @item pascal-comment-start The string you like comments to start with (default @kbd{"@{ "}). @item pascal-comment-end The string you like comments to end with (default @kbd{"\t@}"}). @item pascal-indent-level The number of columns that continued statements should be indented (default 3). @item pascal-mode-hook This variable's value should be @code{nil} or a function with no arguments. The function will be called whenever a pascal file is opened. You might use this function to turn on Fill mode, or to turn off Abbrev mode. (default @code{nil}) @item pascal-auto-newline If this variable is non-nil, typing ``;'' at the end of a line causes a new line to be started. (Default @code{nil}) @item pascal-if-else-str pascal-begin-str @itemx pascal-if-str pascal-program-str @itemx pascal-else-str pascal-procedure-str @itemx pascal-else-if-str pascal-procedure-parm-str @itemx pascal-while-str pascal-function-str @itemx pascal-for-str pascal-function-parm-str @itemx pascal-repeat-str pascal-const-str @itemx pascal-with-str pascal-type-str @itemx pascal-case-str pascal-var-str @itemx pascal-record-str pascal-var-parm-str These strings contain the templates for the associated abbreviation. See below for instructions on how to modify them. @end table @node Customization, Elision, Variables, Pascal @subsection Customization You probably hate the way everyone else indents Pascal code. Fortunately for you, Pascal mode can be adjusted. Each template is stored in a defined constant. For instance, the if-then-else template is stored in @code{pascal-if-else-str}, which looks like @example "if! then begin\n \n end\nelse begin\n \n end;" @end example If the typist enters @example ie<@key{SPC}> @end example into a Pascal mode buffer, then the result is @example if *then begin (`*' marks the location of point) end else begin end; @end example Notes: @itemize @bullet @item Formatting is controlled by putting spaces, tabs, and \n in the string. Each ``line'' in the string is inserted with the same indentation that the line containing the abbreviation had. @item The ``!'' in the string marks the approximate final location of point. When the abbreviation is expanded, the character that caused the expansion (in this case, @key{SPC}) replaces the ``!'', and point is left there. If the string contains no ``!'', point is left at the end of the inserted text. @item The @code{begin}s and @code{end}s are not necessary, but there is no good reason to leave them out of the template, since the typist won't have to type them. Blank lines with 3 ``extra'' spaces are provided to make it easy to enter correctly indented statements. Typing C-n C-e with point in the indicated spot moves point to the point immediately above the `e' in the first @code{end}. @end itemize Now, let's assume that Fred likes his if-then-else statements arranged like this: @example if condition then begin statement; end else begin statement; end; @end example In that case, Fred's init file should contain the lines @example (defconst pascal-if-else-str "if! then begin\n \nend else begin\n \nend;") @end example You can also define new templates. If you want an abbreviation to expand into a string that contains no newlines, use the normal Abbrev-mode functions as described in the Info sections on abbreviation. This is the way Pascal mode expands `int' into `integer'. If you want a multi-line template, you will have to write an abbreviation hook. The hook for `ie' looks like this: @example (defun pascal-if-else-hook () (if (= 4 (pascal-point-state)) (insert-indented-string pascal-if-else-str) (insert-string last-abbrev-text)) ) @end example The function works like this: @itemize @bullet @item pascal-point-state returns 1 if point is in a comment, 2 if it is in a string, and 4 if it is in program text. @item If point is in program text, @code{insert-indented-string} inserts the template string with proper indentation. Otherwise, expansion shouldn't be done, so the abbreviation that invoked the hook is restored. @end itemize Other useful functions are @code{pascal-in-parm}, which returns @code{t} if the cursor is in a formal parameter list, and @code{no-prev-semi}, which deletes the non-whitespace character before the cursor if it is `;'. Once you have written your hook, you can install it by putting a line similar to @example ("ie" "" pascal-if-else-hook 0) @end example in the @code{pascal-mode-abbrev-table} section of your @code{.abbrev_defs} file. @node Elision, , Customization, Pascal @subsection Elision The Elide minor mode provides support for selective hiding of text; see the Info section on Elide for further details. Elision can be tuned for Pascal text with the @file{pascal-elide} library. To use this library, you should make sure that @file{pascal-elide.elc} is in one of the directories in your load path. (This will normally be true, since @file{pascal-elide} and @file{pascal-mode} should be in the same directory.) You should put the line@refill @example (autoload 'pascal-elide-setup "pascal-elide" t); @end example in your Emacs initialization file, and the lines @example (pascal-elide-setup) (elide-mode 1) @end example in your Pascal mode-hook function. @code{pascal-elide-setup} causes functions and procedures to be treated as sections, regardless of their indentation. Hence, typing @kbd{C-c C-h} when point is in the header of a function causes the declaration and statement sections of the function to disappear. @bye