]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/delphi.el
Update AUCTeX
[gnu-emacs] / lisp / progmodes / delphi.el
index 5409e2970c79129fb78a2fedc50ae254a11d1ee2..4ebbc54969712f8bf71e760ec520457a4911b610 100644 (file)
@@ -1,4 +1,4 @@
-;; delphi.el --- Major mode for editing Delphi source (Object Pascal) in Emacs
+;;; delphi.el --- major mode for editing Delphi source (Object Pascal) in Emacs
 
 ;; Copyright (C) 1998, 1999 Free Software Foundation, Inc.
 
@@ -7,20 +7,19 @@
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; GNU Emacs is free software; you can redistribute it and/or modify it under
+;; the terms of the GNU General Public License as published by the Free
+;; Software Foundation; either version 2, or (at your option) any later
+;; version.
 
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
+;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY
+;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+;; details.
 
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; You should have received a copy of the GNU General Public License along with
+;; GNU Emacs; see the file COPYING.  If not, write to the Free Software
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
 ;; (setq auto-mode-alist
 ;;       (cons '("\\.\\(pas\\|dpr\\|dpk\\)$" . delphi-mode) auto-mode-alist))
 
+;; To get keyword, comment, and string literal coloring, be sure that font-lock
+;; is running. One can manually do M-x font-lock-mode in a Delphi buffer, or
+;; one can put in .emacs:
+;;
+;; (add-hook 'delphi-mode-hook 'turn-on-font-lock)
+
+;; If font-lock is not loaded by default, you might have to do:
+;;
+;; (autoload 'font-lock-mode "font-lock")
+;; (autoload 'turn-on-font-lock "font-lock")
+;; (setq font-lock-support-mode 'lazy-lock-mode)
+;;
+;; Lazy lock is very necessary for faster screen updates.
+
+;; For good performance, be sure to byte-compile delphi.el, e.g.
+;;
+;; M-x byte-compile-file <give the path to delphi.el when prompted>
+
+;; This will generate delphi.elc, which will be loaded instead of delphi.el
+;; when delphi-mode is autoloaded.
+
 ;; When you have entered Delphi mode, you may get more info by pressing
 ;; C-h m.
 
-;; This delphi mode implementation is fairly tolerant of syntax
-;; errors, relying as much as possible on the indentation of the
-;; previous statement. This also makes it faster and simpler, since
-;; there is less searching for properly constructed beginnings.
+;; This delphi mode implementation is fairly tolerant of syntax errors, relying
+;; as much as possible on the indentation of the previous statement. This also
+;; makes it faster and simpler, since there is less searching for properly
+;; constructed beginnings.
 
 ;;; Code:
 
 (provide 'delphi)
 
-(defconst delphi-version
-  (let ((revision "$Revision: 2.5 $"))
-    (string-match ": \\([^ ]+\\)" revision)
-    (match-string 1 revision))
-  "Version of this delphi mode.")
-;;; $Log: delphi.el,v $
-;;; Revision 2.5  1999/07/24 21:45:22  blaak
-;;; Misc changes to make debugging easier, and to conform to major mode
-;;; standards (i.e. don't require font-lock -- that forces its existence).
-;;;
-;;; Revision 2.3  1999/07/20 07:55:38  blaak
-;;; o One can now undo the effects of delphi-fill-comment.
-;;; o Object declarations are now formatted properly.
-;;;
-;;; Revision 2.2  1999/07/01 04:16:07  blaak
-;;; Handle multiple parameters on a line correctly, e.g.,
-;;;   procedure Foo (arg1 : T; arg2 : T; arg3 : T;
-;;;                  arg3 : T; // should be aligned with arg1,
-;;;                            // not arg2 or arg3
-;;;
-;;; Revision 2.1  1999/05/21 06:37:19  blaak
-;;; Indent properly after simple class declarations, even if they span
-;;; multiple lines. E.g.
-;;;   type TMetaClass = class of TClass;
-;;;   type TSimpleClass = class
-;;;                         (TBaseClass);
-;;;   type TForwardClass = class;
-;;;
-;;; Revision 2.0  1999/05/09 06:31:53  blaak
-;;; Re-release. Pre 2.0 versions considered development versions and their
-;;; histories dropped. Delphi mode is what it is.
-;;;
-;;;
-
 (eval-and-compile
   ;; Allow execution on pre Emacs 20 versions.
   (or (fboundp 'when)
 
 (defgroup delphi nil
   "Major mode for editing Delphi source in Emacs"
+  :version "21.1"
   :group 'languages)
 
 (defconst delphi-debug nil
@@ -156,36 +143,45 @@ end;                            end;"
   :type 'boolean
   :group 'delphi)
 
-(defcustom delphi-tab-always-indent t
+(defcustom delphi-tab-always-indents t
   "*Non-nil means TAB in Delphi mode should always reindent the current line,
 regardless of where in the line point is when the TAB command is used."
   :type 'boolean
   :group 'delphi)
 
+(defcustom delphi-newline-always-indents t
+  "*Non-nil means NEWLINE in Delphi mode should always reindent the current
+line, insert a blank line and move to the default indent column of the blank
+line. If nil, then no indentation occurs, and NEWLINE does the usual
+behaviour. This is useful when one needs to do customized indentation that
+differs from the default."
+  :type 'boolean
+  :group 'delphi)
+
 (defcustom delphi-comment-face 'font-lock-comment-face
   "*Face used to color delphi comments."
-  :type 'facep
+  :type 'face
   :group 'delphi)
 
 (defcustom delphi-string-face 'font-lock-string-face
   "*Face used to color delphi strings."
-  :type 'facep
+  :type 'face
   :group 'delphi)
 
 (defcustom delphi-keyword-face 'font-lock-keyword-face
   "*Face used to color delphi keywords."
-  :type 'facep
+  :type 'face
   :group 'delphi)
 
 (defcustom delphi-other-face nil
   "*Face used to color everything else."
-  :type 'facep
+  :type 'face
   :group 'delphi)
 
 (defconst delphi-directives
   '(absolute abstract assembler automated cdecl default dispid dynamic
     export external far forward index inline message name near nodefault
-    overload override pascal private protected public published read readonly 
+    overload override pascal private protected public published read readonly
     register reintroduce resident resourcestring safecall stdcall stored
     virtual write writeonly)
   "Delphi4 directives.")
@@ -196,9 +192,9 @@ regardless of where in the line point is when the TAB command is used."
      and array as asm at begin case class const constructor contains
      destructor dispinterface div do downto else end except exports
      file finalization finally for function goto if implementation implements
-     in inherited initialization interface is label library mod nil not 
+     in inherited initialization interface is label library mod nil not
      of object on or out package packed procedure program property
-     raise record repeat requires result self set shl shr then threadvar 
+     raise record repeat requires result self set shl shr then threadvar
      to try type unit uses until var while with xor
 
      ;; These routines should be keywords, if Borland had the balls.
@@ -246,8 +242,8 @@ are followed by an expression.")
 (defconst delphi-visibilities '(public private protected published automated)
   "Class visibilities.")
 
-(defconst delphi-block-statements 
-  '(begin try case repeat initialization finalization)
+(defconst delphi-block-statements
+  '(begin try case repeat initialization finalization asm)
   "Statements that contain multiple substatements.")
 
 (defconst delphi-mid-block-statements
@@ -261,7 +257,7 @@ are followed by an expression.")
   `(,@delphi-end-block-statements ,@delphi-mid-block-statements)
   "Statements that match the indentation of the parent block.")
 
-(defconst delphi-decl-sections '(type const var label)
+(defconst delphi-decl-sections '(type const var label resourcestring)
   "Denotes the start of a declaration section.")
 
 (defconst delphi-class-types '(class object)
@@ -506,7 +502,7 @@ routine.")
                 (double-quoted-string . "[\"\n]")))))
 
 (defun delphi-is-literal-start (p)
-  ;; True if the point p is at the end point of a (completed) literal.
+  ;; True if the point p is at the start point of a (completed) literal.
   (let* ((kind (delphi-literal-kind p))
          (pattern (delphi-literal-start-pattern kind)))
     (or (null kind) ; Non-literals are considered as start points.
@@ -524,7 +520,7 @@ routine.")
                  ;; We have an end only if there is some string content (at
                  ;; least a starting delimiter).
                  (not (delphi-is-literal-end (1- p)))))
-                 
+
         ;; Special case: strings cannot span lines.
         (and (delphi-is kind delphi-strings) (eq ?\n (char-after (1- p)))))))
 
@@ -566,7 +562,7 @@ routine.")
            ;; We are completing an incomplete literal.
            (let ((kind (delphi-literal-kind (1- search-start))))
              (delphi-complete-literal kind limit)
-             (delphi-set-text-properties 
+             (delphi-set-text-properties
               search-start (point) (delphi-literal-text-properties kind))))
 
           ((re-search-forward
@@ -581,7 +577,7 @@ routine.")
                  (start (match-beginning 0)))
              (delphi-set-text-properties search-start start nil)
              (delphi-complete-literal kind limit)
-             (delphi-set-text-properties 
+             (delphi-set-text-properties
               start (point) (delphi-literal-text-properties kind))))
 
           ;; Nothing found. Mark it as a non-literal.
@@ -733,14 +729,14 @@ routine.")
       (while (< p to)
         ;; Color the token and move past it.
         (setq token (delphi-token-at p))
-        (add-text-properties 
+        (add-text-properties
          (delphi-token-start token) (delphi-token-end token)
          (list 'face (delphi-face-of (delphi-token-kind token)) 'lazy-lock t))
         (setq p (delphi-token-end token))
         (delphi-step-progress p "Fontifying" delphi-fontifying-progress-step))
       (delphi-progress-done)))))
 
-(defconst delphi-ignore-changes t
+(defvar delphi-ignore-changes t
   "Internal flag to control if the delphi-mode responds to buffer changes.
 Defaults to t in case the delphi-after-change function is called on a
 non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
@@ -754,7 +750,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
        (delphi-progress-start)
        ;; Reparse at least from the token previous to the change to the end of
        ;; line after the change.
-       (delphi-parse-region-until-stable 
+       (delphi-parse-region-until-stable
         (delphi-token-start (delphi-token-at (1- change-start)))
         (progn (goto-char change-end) (end-of-line) (point)))
        (delphi-progress-done)))))
@@ -812,7 +808,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
     (catch 'done
       (while token
         (setq kind (delphi-token-kind token))
-        (cond 
+        (cond
          ;; Skip over ()/[] groups.
          ((eq 'close-group kind) (setq token (delphi-group-start token)))
 
@@ -826,10 +822,31 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
     (delphi-indent-of last-token offset)))
 
 (defun delphi-stmt-line-indent-of (from-token &optional offset)
-  ;; Like `delphi-line-indent-of' except is also stops on a use clause or ":".
-  (apply #'delphi-line-indent-of 
-         from-token offset `(;colon
-                             ,@delphi-use-clauses)))
+  ;; Like `delphi-line-indent-of' except is also stops on a use clause, and
+  ;; colons that precede statements (i.e. case labels).
+  (let ((token (delphi-previous-token from-token))
+        (last-token from-token)
+        (kind nil))
+    (catch 'done
+      (while token
+        (setq kind (delphi-token-kind token))
+        (cond
+         ((and (eq 'colon kind)
+               (delphi-is (delphi-token-kind last-token)
+                          `(,@delphi-block-statements
+                            ,@delphi-expr-statements)))
+          ;; We hit a label followed by a statement. Indent to the statement.
+          (throw 'done nil))
+
+         ;; Skip over ()/[] groups.
+         ((eq 'close-group kind) (setq token (delphi-group-start token)))
+
+         ((delphi-is kind `(newline open-group ,@delphi-use-clauses))
+          ;; Stop at the beginning of the line, an open group, or a use clause
+          (throw 'done nil)))
+        (unless (delphi-is kind delphi-whitespace) (setq last-token token))
+        (setq token (delphi-previous-token token))))
+    (delphi-indent-of last-token offset)))
 
 (defun delphi-open-group-indent (token last-token &optional offset)
   ;; Returns the indent relative to an unmatched ( or [.
@@ -893,7 +910,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
          ((delphi-composite-type-start token last-token)
           (throw 'done (if stop-on-class last-token token)))
          )
-        (unless (delphi-is token-kind delphi-whitespace) 
+        (unless (delphi-is token-kind delphi-whitespace)
           (setq last-token token))
         (setq token (delphi-previous-token token)))
       ;; Start not found.
@@ -1014,7 +1031,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
 
 (defun delphi-is-use-clause-end (at-token last-token last-colon from-kind)
   ;; True if we are after the end of a uses type clause.
-  (when (and last-token 
+  (when (and last-token
              (not last-colon)
              (eq 'comma (delphi-token-kind at-token))
              (eq 'semicolon from-kind))
@@ -1124,11 +1141,18 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
                    ;; Indent to use clause keyword.
                    (delphi-line-indent-of token))))
 
+         ;; Assembly sections always indent in from the asm keyword.
+         ((eq token-kind 'asm)
+          (throw 'done (delphi-stmt-line-indent-of token delphi-indent-level)))
+
          ;; An enclosing statement delimits a previous statement.
          ;; We try to use the existing indent of the previous statement,
          ;; otherwise we calculate from the enclosing statement.
          ((delphi-is token-kind delphi-previous-enclosing-statements)
-          (throw 'done (if last-token (delphi-line-indent-of last-token)
+          (throw 'done (if last-token
+                           ;; Otherwise indent to the last token
+                           (delphi-line-indent-of last-token)
+                         ;; Just indent from the enclosing keyword
                          (delphi-line-indent-of token delphi-indent-level))))
 
          ;; A class or record declaration also delimits a previous statement.
@@ -1206,7 +1230,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
 
          ;; An enclosing ":" means a label.
          ((and (eq 'colon token-kind)
-               (delphi-is (delphi-token-kind section-token) 
+               (delphi-is (delphi-token-kind section-token)
                           delphi-block-statements)
                (not last-terminator)
                (not expr-delimited)
@@ -1217,7 +1241,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
          ;; Block and mid block tokens are always enclosing
          ((delphi-is token-kind delphi-begin-enclosing-tokens)
           (throw 'done
-                 (delphi-line-indent-of token delphi-indent-level)))
+                 (delphi-stmt-line-indent-of token delphi-indent-level)))
 
          ;; Declaration sections and routines are delimiters, unless they
          ;; are part of a nested routine.
@@ -1240,7 +1264,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
         (from-kind (delphi-token-kind from-token))
         (token-kind nil)
         (stmt-start nil)
-        (last-token nil)        
+        (last-token nil)
         (equals-encountered nil)
         (before-equals nil)
         (expr-delimited nil))
@@ -1299,10 +1323,10 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
                  (if stmt-start
                      ;; We are not actually indenting to the case statement,
                      ;; but are within a label expression.
-                     (delphi-stmt-line-indent-of 
+                     (delphi-stmt-line-indent-of
                       stmt-start delphi-indent-level)
                    ;; Indent from the case keyword.
-                   (delphi-stmt-line-indent-of 
+                   (delphi-stmt-line-indent-of
                     token delphi-case-label-indent))))
 
          ;; Body expression statements are enclosing. Indent from the
@@ -1310,7 +1334,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
          ;; it.
          ((delphi-is token-kind delphi-body-expr-statements)
           (throw 'done
-                 (delphi-stmt-line-indent-of 
+                 (delphi-stmt-line-indent-of
                   (or stmt-start token) delphi-indent-level)))
 
          ;; An else statement is enclosing, but it doesn't have an expression.
@@ -1357,6 +1381,10 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
 
                  ((+ (delphi-section-indent-of token) delphi-indent-level)))))
 
+         ;; Assembly sections always indent in from the asm keyword.
+         ((eq token-kind 'asm)
+          (throw 'done (delphi-stmt-line-indent-of token delphi-indent-level)))
+
          ;; Stop at an enclosing statement and indent from it.
          ((delphi-is token-kind delphi-enclosing-statements)
           (throw 'done (delphi-stmt-line-indent-of
@@ -1392,18 +1420,18 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
            ;;          + 2;
            ;; which doesn't look right.
            ;;;; Align binary ops with the before token.
-           ;;((delphi-is from-kind delphi-binary-ops) 
+           ;;((delphi-is from-kind delphi-binary-ops)
            ;;(throw 'done (delphi-indent-of before-equals 0)))
 
            ;; Assignments (:=) we skip over to get a normal indent.
            ((eq (delphi-token-kind last-token) 'equals))
 
            ;; Otherwise indent in from the equals.
-           ((throw 'done 
+           ((throw 'done
                    (delphi-indent-of before-equals delphi-indent-level)))))
 
          ;; Remember any "=" we encounter if it has not already been processed.
-         ((eq token-kind 'equals) 
+         ((eq token-kind 'equals)
           (setq equals-encountered token
                 before-equals last-token))
          )
@@ -1439,7 +1467,7 @@ non-delphi buffer. Set to nil in a delphi buffer.  To override, just do:
 
                   ((delphi-is token-kind delphi-match-block-statements)
                    ;; Use the block's indentation.
-                   (let ((block-start 
+                   (let ((block-start
                           (delphi-block-start token 'stop-on-class)))
                      (cond
                       ;; When trailing a body statement, indent to
@@ -1603,23 +1631,25 @@ before the indent, the point is moved to the indent."
   (delphi-debug-tokenize-region (window-start) (window-end)))
 
 (defun delphi-newline ()
-  "Terminate the current line with a newline and indent the next."
+  "Terminate the current line with a newline and indent the next, unless
+`delphi-newline-always-indents' is nil, in which case no reindenting occurs."
   (interactive)
   ;; Remove trailing spaces
   (delete-horizontal-space)
   (newline)
-  ;; Indent both the (now) previous and current line first.
-  (save-excursion
-    (previous-line 1)
-    (delphi-indent-line))
-  (delphi-indent-line))
+  (when delphi-newline-always-indents
+    ;; Indent both the (now) previous and current line first.
+    (save-excursion
+      (previous-line 1)
+      (delphi-indent-line))
+    (delphi-indent-line)))
 
 
 (defun delphi-tab ()
   "Indent the current line or insert a TAB, depending on the value of
-delphi-tab-always-indent and the current line position."
+`delphi-tab-always-indents' and the current line position."
   (interactive)
-  (if (or delphi-tab-always-indent ; We are always indenting
+  (if (or delphi-tab-always-indents ; We are always indenting
           ;; Or we are before the first non-space character on the line.
           (save-excursion (skip-chars-backward delphi-space-chars) (bolp)))
       (delphi-indent-line)
@@ -1880,9 +1910,9 @@ comment block. If not in a // comment, just does a normal newline."
             (list '("\r" delphi-newline)
                   '("\t" delphi-tab)
                   '("\177" backward-delete-char-untabify)
-                  '("\C-cd" delphi-find-current-def)
-                  '("\C-cx" delphi-find-current-xdef)
-                  '("\C-cb" delphi-find-current-body)
+;;                '("\C-cd" delphi-find-current-def)
+;;                '("\C-cx" delphi-find-current-xdef)
+;;                '("\C-cb" delphi-find-current-body)
                   '("\C-cu" delphi-find-unit)
                   '("\M-q" delphi-fill-comment)
                   '("\M-j" delphi-new-comment-line)
@@ -1899,9 +1929,6 @@ This is ok since we do our own keyword/comment/string face coloring.")
 (defun delphi-mode (&optional skip-initial-parsing)
   "Major mode for editing Delphi code. \\<delphi-mode-map>
 \\[delphi-tab]\t- Indents the current line for Delphi code.
-\\[delphi-find-current-def]\t- Find previous definition of identifier at the point.
-\\[delphi-find-current-xdef]\t- Find definition, but also in external units.
-\\[delphi-find-current-body]\t- Find the body of the identifier at the point.
 \\[delphi-find-unit]\t- Search for a Delphi source file.
 \\[delphi-fill-comment]\t- Fill the current comment.
 \\[delphi-new-comment-line]\t- If in a // comment, do a new comment line.
@@ -1916,9 +1943,13 @@ Customization:
     Extra indentation for blocks in compound statements.
  `delphi-case-label-indent'           (default 0)
     Extra indentation for case statement labels.
- `delphi-tab-always-indent          (default t)
+ `delphi-tab-always-indents'          (default t)
     Non-nil means TAB in Delphi mode should always reindent the current line,
     regardless of where in the line point is when the TAB command is used.
+ `delphi-newline-always-indents'      (default t)
+    Non-nil means NEWLINE in Delphi mode should always reindent the current
+    line, insert a blank line and move to the default indent column of the
+    blank line.
  `delphi-search-path'                 (default .)
     Directories to search when finding external units.
  `delphi-verbose'                     (default nil)
@@ -1961,7 +1992,6 @@ no args, if that value is non-nil."
 
   ;; We need to keep track of changes to the buffer to determine if we need
   ;; to retokenize changed text.
-  (make-local-hook 'after-change-functions)
   (add-hook 'after-change-functions 'delphi-after-change nil t)
 
   (widen)
@@ -1973,3 +2003,6 @@ no args, if that value is non-nil."
        (delphi-progress-done))))
 
   (run-hooks 'delphi-mode-hook))
+
+;;; arch-tag: 410e192d-e9b5-4397-ad62-12340fc3fa41
+;;; delphi.el ends here