-;;; pascal.el - Major mode for editing pascal source in emacs.
+;;; pascal.el --- major mode for editing pascal source in Emacs
-;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 94, 95, 96, 97, 98, 1999, 2000 Free Software Foundation, Inc.
-;;; Author: Espen Skoglund (espensk@stud.cs.uit.no)
-;;; Keywords: languages
+;; Author: Espen Skoglund <esk@gnu.org>
+;; Keywords: languages
-;;; This file is part of GNU Emacs.
+;; This file is part of GNU Emacs.
-;;; This program 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 of the License, 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.
-;;; This program 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 this program; if not, write to the Free Software
-;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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:
-;;; USAGE
-;;; =====
-
-;;; Emacs should enter Pascal mode when you find a Pascal source file.
-;;; When you have entered Pascal mode, you may get more info by pressing
-;;; C-h m. You may also get online help describing various functions by:
-;;; C-h f <Name of function you want described>
-
-;;; If you want to customize Pascal mode to fit you better, you may add
-;;; these lines (the values of the variables presented here are the defaults):
-;;;
-;;; ;; User customization for Pascal mode
-;;; (setq pascal-indent-level 3
-;;; pascal-case-indent 2
-;;; pascal-auto-newline nil
-;;; pascal-tab-always-indent t
-;;; pascal-auto-endcomments t
-;;; pascal-auto-lineup '(all)
-;;; pascal-toggle-completions nil
-;;; pascal-type-keywords '("array" "file" "packed" "char"
-;;; "integer" "real" "string" "record")
-;;; pascal-start-keywords '("begin" "end" "function" "procedure"
-;;; "repeat" "until" "while" "read" "readln"
-;;; "reset" "rewrite" "write" "writeln")
-;;; pascal-separator-keywords '("downto" "else" "mod" "div" "then"))
-
-;;; KNOWN BUGS / BUGREPORTS
-;;; =======================
-;;; As far as I know, there are no bugs in the current version of this
-;;; package. This may not be true however, since I never use this mode
-;;; myself and therefore would never notice them anyway. If you do
-;;; find any bugs, you may submit them to: espensk@stud.cs.uit.no
-;;; as well as to bug-gnu-emacs@prep.ai.mit.edu.
+;; USAGE
+;; =====
+
+;; Emacs should enter Pascal mode when you find a Pascal source file.
+;; When you have entered Pascal mode, you may get more info by pressing
+;; C-h m. You may also get online help describing various functions by:
+;; C-h f <Name of function you want described>
+
+;; If you want to customize Pascal mode to fit you better, you may add
+;; these lines (the values of the variables presented here are the defaults):
+;;
+;; ;; User customization for Pascal mode
+;; (setq pascal-indent-level 3
+;; pascal-case-indent 2
+;; pascal-auto-newline nil
+;; pascal-tab-always-indent t
+;; pascal-auto-endcomments t
+;; pascal-auto-lineup '(all)
+;; pascal-toggle-completions nil
+;; pascal-type-keywords '("array" "file" "packed" "char"
+;; "integer" "real" "string" "record")
+;; pascal-start-keywords '("begin" "end" "function" "procedure"
+;; "repeat" "until" "while" "read" "readln"
+;; "reset" "rewrite" "write" "writeln")
+;; pascal-separator-keywords '("downto" "else" "mod" "div" "then"))
+
+;; KNOWN BUGS / BUGREPORTS
+;; =======================
+;; As far as I know, there are no bugs in the current version of this
+;; package. This may not be true however, since I never use this mode
+;; myself and therefore would never notice them anyway. If you do
+;; find any bugs, you may submit them to: esk@gnu.org as well as to
+;; bug-gnu-emacs@gnu.org.
\f
;;; Code:
+(defgroup pascal nil
+ "Major mode for editing Pascal source in Emacs"
+ :group 'languages)
+
(defvar pascal-mode-abbrev-table nil
"Abbrev table in use in Pascal-mode buffers.")
(define-abbrev-table 'pascal-mode-abbrev-table ())
; (define-key pascal-mode-map "\C-cu" 'pascal-upcase-keywords)
; (define-key pascal-mode-map "\C-cc" 'pascal-capitalize-keywords)
)
-
+
+(defvar pascal-imenu-generic-expression
+ '((nil "^[ \t]*\\(function\\|procedure\\)[ \t\n]+\\([a-zA-Z0-9_.:]+\\)" 2))
+ "Imenu expression for Pascal-mode. See `imenu-generic-expression'.")
+
(defvar pascal-keywords
- '("and" "array" "begin" "case" "const" "div" "do" "downto" "else" "end"
- "file" "for" "function" "goto" "if" "in" "label" "mod" "nil" "not" "of"
- "or" "packed" "procedure" "program" "record" "repeat" "set" "then" "to"
+ '("and" "array" "begin" "case" "const" "div" "do" "downto" "else" "end"
+ "file" "for" "function" "goto" "if" "in" "label" "mod" "nil" "not" "of"
+ "or" "packed" "procedure" "program" "record" "repeat" "set" "then" "to"
"type" "until" "var" "while" "with"
;; The following are not standard in pascal, but widely used.
"get" "put" "input" "output" "read" "readln" "reset" "rewrite" "write"
(defconst pascal-beg-block-re "\\<\\(begin\\|case\\|record\\|repeat\\)\\>")
(defconst pascal-end-block-re "\\<\\(end\\|until\\)\\>")
(defconst pascal-declaration-re "\\<\\(const\\|label\\|type\\|var\\)\\>")
+(defconst pascal-progbeg-re "\\<\\program\\>")
(defconst pascal-defun-re "\\<\\(function\\|procedure\\|program\\)\\>")
(defconst pascal-sub-block-re "\\<\\(if\\|else\\|for\\|while\\|with\\)\\>")
(defconst pascal-noindent-re "\\<\\(begin\\|end\\|until\\|else\\)\\>")
()
(setq pascal-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\\ "." pascal-mode-syntax-table)
- (modify-syntax-entry ?( "()1" pascal-mode-syntax-table)
+ (modify-syntax-entry ?( "()1" pascal-mode-syntax-table)
(modify-syntax-entry ?) ")(4" pascal-mode-syntax-table)
- (modify-syntax-entry ?* ". 23" pascal-mode-syntax-table)
+ (modify-syntax-entry ?* ". 23b" pascal-mode-syntax-table)
(modify-syntax-entry ?{ "<" pascal-mode-syntax-table)
(modify-syntax-entry ?} ">" pascal-mode-syntax-table)
(modify-syntax-entry ?+ "." pascal-mode-syntax-table)
(modify-syntax-entry ?> "." pascal-mode-syntax-table)
(modify-syntax-entry ?& "." pascal-mode-syntax-table)
(modify-syntax-entry ?| "." pascal-mode-syntax-table)
- (modify-syntax-entry ?_ "w" pascal-mode-syntax-table)
+ (modify-syntax-entry ?_ "_" pascal-mode-syntax-table)
(modify-syntax-entry ?\' "\"" pascal-mode-syntax-table))
-(defvar pascal-font-lock-keywords
+(defconst pascal-font-lock-keywords (purecopy
(list
- '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\(\\sw+\\)?"
- (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
+ '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\([a-z]\\)"
+ 1 font-lock-keyword-face)
+ '("^[ \t]*\\(function\\|pro\\(cedure\\|gram\\)\\)\\>[ \t]*\\([a-z][a-z0-9_]*\\)"
+ 3 font-lock-function-name-face t)
; ("type" "const" "real" "integer" "char" "boolean" "var"
; "record" "array" "file")
(cons (concat "\\<\\(array\\|boolean\\|c\\(har\\|onst\\)\\|file\\|"
"integer\\|re\\(al\\|cord\\)\\|type\\|var\\)\\>")
'font-lock-type-face)
- '("\\<\\(label\\|external\\|forward\\)\\>" . font-lock-reference-face)
- '("\\<\\([0-9]+\\)[ \t]*:" 1 font-lock-reference-face)
+ '("\\<\\(label\\|external\\|forward\\)\\>" . font-lock-constant-face)
+ '("\\<\\([0-9]+\\)[ \t]*:" 1 font-lock-function-name-face)
; ("of" "to" "for" "if" "then" "else" "case" "while"
; "do" "until" "and" "or" "not" "in" "with" "repeat" "begin" "end")
(concat "\\<\\("
"not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
"\\)\\>")
'("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
- (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)))
+ 1 font-lock-keyword-face)
+ '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
+ 2 font-lock-keyword-face t)))
"Additional expressions to highlight in Pascal mode.")
-
-(defvar pascal-indent-level 3
- "*Indentation of Pascal statements with respect to containing block.")
-
-(defvar pascal-case-indent 2
- "*Indentation for case statements.")
-
-(defvar pascal-auto-newline nil
- "*Non-nil means automatically newline after simcolons and the punctation mark
-after an end.")
-
-(defvar pascal-tab-always-indent t
- "*Non-nil means TAB in Pascal mode should always reindent the current line,
-regardless of where in the line point is when the TAB command is used.")
-
-(defvar pascal-auto-endcomments t
- "*Non-nil means a comment { ... } is set after the ends which ends cases and
-functions. The name of the function or case will be set between the braces.")
-
-(defvar pascal-auto-lineup '(all)
+(put 'pascal-mode 'font-lock-defaults '(pascal-font-lock-keywords nil t))
+
+(defcustom pascal-indent-level 3
+ "*Indentation of Pascal statements with respect to containing block."
+ :type 'integer
+ :group 'pascal)
+
+(defcustom pascal-case-indent 2
+ "*Indentation for case statements."
+ :type 'integer
+ :group 'pascal)
+
+(defcustom pascal-auto-newline nil
+ "*Non-nil means automatically insert newlines in certain cases.
+These include after semicolons and after the punctuation mark after an `end'."
+ :type 'boolean
+ :group 'pascal)
+
+(defcustom pascal-indent-nested-functions t
+ "*Non-nil means nested functions are indented."
+ :type 'boolean
+ :group 'pascal)
+
+(defcustom pascal-tab-always-indent t
+ "*Non-nil means TAB in Pascal mode should always reindent the current line.
+If this is nil, TAB inserts a tab if it is at the end of the line
+and follows non-whitespace text."
+ :type 'boolean
+ :group 'pascal)
+
+(defcustom pascal-auto-endcomments t
+ "*Non-nil means automatically insert comments after certain `end's.
+Specifically, this is done after the ends of cases statements and functions.
+The name of the function or case is included between the braces."
+ :type 'boolean
+ :group 'pascal)
+
+(defcustom pascal-auto-lineup '(all)
"*List of contexts where auto lineup of :'s or ='s should be done.
Elements can be of type: 'paramlist', 'declaration' or 'case', which will
do auto lineup in parameterlist, declarations or case-statements
respectively. The word 'all' will do all lineups. '(case paramlist) for
instance will do lineup in case-statements and parameterlist, while '(all)
-will do all lineups.")
-
-(defvar pascal-toggle-completions nil
- "*Non-nil means that \\<pascal-mode-map>\\[pascal-complete-label] should \
-not display a completion buffer when
-the label couldn't be completed, but instead toggle the possible completions
-with repeated \\[pascal-complete-label]'s.")
-
-(defvar pascal-type-keywords
+will do all lineups."
+ :type '(set :extra-offset 8
+ (const :tag "Everything" all)
+ (const :tag "Parameter lists" paramlist)
+ (const :tag "Decalrations" declaration)
+ (const :tag "Case statements" case))
+ :group 'pascal)
+
+(defcustom pascal-toggle-completions nil
+ "*Non-nil means \\<pascal-mode-map>\\[pascal-complete-word] should try all possible completions one by one.
+Repeated use of \\[pascal-complete-word] will show you all of them.
+Normally, when there is more than one possible completion,
+it displays a list of all possible completions."
+ :type 'boolean
+ :group 'pascal)
+
+(defcustom pascal-type-keywords
'("array" "file" "packed" "char" "integer" "real" "string" "record")
"*Keywords for types used when completing a word in a declaration or parmlist.
-\(eg. integer, real, char.) The types defined within the Pascal program
-will be completed runtime, and should not be added to this list.")
+These include integer, real, char, etc.
+The types defined within the Pascal program
+are handled in another way, and should not be added to this list."
+ :type '(repeat (string :tag "Keyword"))
+ :group 'pascal)
-(defvar pascal-start-keywords
+(defcustom pascal-start-keywords
'("begin" "end" "function" "procedure" "repeat" "until" "while"
"read" "readln" "reset" "rewrite" "write" "writeln")
"*Keywords to complete when standing at the first word of a statement.
-\(eg. begin, repeat, until, readln.)
+These are keywords such as begin, repeat, until, readln.
The procedures and variables defined within the Pascal program
-will be completed runtime and should not be added to this list.")
+are handled in another way, and should not be added to this list."
+ :type '(repeat (string :tag "Keyword"))
+ :group 'pascal)
-(defvar pascal-separator-keywords
+(defcustom pascal-separator-keywords
'("downto" "else" "mod" "div" "then")
"*Keywords to complete when NOT standing at the first word of a statement.
-\(eg. downto, else, mod, then.)
-Variables and function names defined within the
-Pascal program are completed runtime and should not be added to this list.")
+These are keywords such as downto, else, mod, then.
+Variables and function names defined within the Pascal program
+are handled in another way, and should not be added to this list."
+ :type '(repeat (string :tag "Keyword"))
+ :group 'pascal)
+
;;;
;;; Macros
(defun pascal-declaration-end ()
(let ((nest 1))
(while (and (> nest 0)
- (re-search-forward
- "[:=]\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)"
+ (re-search-forward
+ "[:=]\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)"
(save-excursion (end-of-line 2) (point)) t))
(cond ((match-beginning 1) (setq nest (1+ nest)))
- ((match-beginning 2) (setq nest (1- nest)))))))
+ ((match-beginning 2) (setq nest (1- nest)))
+ ((looking-at "[^(\n]+)") (setq nest 0))))))
(defun pascal-declaration-beg ()
((match-beginning 3) (setq nest (1+ nest)))))
(= nest 0)))
-
+
(defsubst pascal-within-string ()
(save-excursion
(nth 3 (parse-partial-sexp (pascal-get-beg-of-line) (point)))))
Variables controlling indentation/edit style:
- pascal-indent-level (default 3)
+ pascal-indent-level (default 3)
Indentation of Pascal statements with respect to containing block.
- pascal-case-indent (default 2)
+ pascal-case-indent (default 2)
Indentation for case statements.
- pascal-auto-newline (default nil)
- Non-nil means automatically newline after simcolons and the punctation mark
- after an end.
+ pascal-auto-newline (default nil)
+ Non-nil means automatically newline after semicolons and the punctuation
+ mark after an end.
+ pascal-indent-nested-functions (default t)
+ Non-nil means nested functions are indented.
pascal-tab-always-indent (default t)
Non-nil means TAB in Pascal mode should always reindent the current line,
regardless of where in the line point is when the TAB command is used.
- pascal-auto-endcomments (default t)
+ pascal-auto-endcomments (default t)
Non-nil means a comment { ... } is set after the ends which ends cases and
functions. The name of the function or case will be set between the braces.
- pascal-auto-lineup (default t)
- List of contexts where auto lineup of :'s or ='s hould be done.
+ pascal-auto-lineup (default t)
+ List of contexts where auto lineup of :'s or ='s should be done.
See also the user variables pascal-type-keywords, pascal-start-keywords and
pascal-separator-keywords.
(set-syntax-table pascal-mode-syntax-table)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'pascal-indent-line)
+ (make-local-variable 'comment-indent-function)
(setq comment-indent-function 'pascal-indent-comment)
(make-local-variable 'parse-sexp-ignore-comments)
(setq parse-sexp-ignore-comments nil)
+ (make-local-variable 'blink-matching-paren-dont-ignore-comments)
+ (setq blink-matching-paren-dont-ignore-comments t)
(make-local-variable 'case-fold-search)
(setq case-fold-search t)
+ (make-local-variable 'comment-start)
+ (setq comment-start "{")
(make-local-variable 'comment-start-skip)
(setq comment-start-skip "(\\*+ *\\|{ *")
(make-local-variable 'comment-end)
(setq comment-end "}")
+ ;; Font lock support
(make-local-variable 'font-lock-defaults)
(setq font-lock-defaults '(pascal-font-lock-keywords nil t))
+ ;; Imenu support
+ (make-local-variable 'imenu-generic-expression)
+ (setq imenu-generic-expression pascal-imenu-generic-expression)
+ (setq imenu-case-fold-search t)
(run-hooks 'pascal-mode-hook))
\f
(search-forward "*)" (pascal-get-end-of-line) t))))
(setq setstar t))))
;; If last line was a star comment line then this one shall be too.
- (if (null setstar)
+ (if (null setstar)
(pascal-indent-line)
(insert "* "))))
(pascal-indent-command))))
(defun electric-pascal-hash ()
- "Insert `#', and indent to coulmn 0 if this is a CPP directive."
+ "Insert `#', and indent to column 0 if this is a CPP directive."
(interactive)
(insert last-command-char)
(if (save-excursion (beginning-of-line) (looking-at "^[ \t]*#"))
(save-excursion
(beginning-of-line)
(pascal-indent-line))
- (insert "\t"))
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (bolp))
+ (pascal-indent-line)
+ (insert "\t")))
(pascal-indent-command)))
\f
(defun pascal-insert-block ()
"Insert Pascal begin ... end; block in the code with right indentation."
(interactive)
- (pascal-indent-line)
(insert "begin")
(electric-pascal-terminate-line)
(save-excursion
- (electric-pascal-terminate-line)
+ (newline)
(insert "end;")
(beginning-of-line)
(pascal-indent-line)))
(if (not (looking-at (concat "\\s \\|\\s)\\|" pascal-defun-re)))
(forward-sexp 1))
(let ((nest 0) (max -1) (func 0)
- (reg (concat pascal-beg-block-re "\\|"
+ (reg (concat pascal-beg-block-re "\\|"
pascal-end-block-re "\\|"
pascal-defun-re)))
(while (re-search-backward reg nil 'move)
(pascal-beg-of-defun))
(forward-char 1)
(let ((nest 0) (func 1)
- (reg (concat pascal-beg-block-re "\\|"
+ (reg (concat pascal-beg-block-re "\\|"
pascal-end-block-re "\\|"
pascal-defun-re)))
(while (and (/= func 0)
(defun pascal-end-of-statement ()
"Move forward to end of current statement."
(interactive)
- (let ((nest 0) pos
+ (let ((parse-sexp-ignore-comments t)
+ (nest 0) pos
(regexp (concat "\\(" pascal-beg-block-re "\\)\\|\\("
pascal-end-block-re "\\)")))
(if (not (looking-at "[ \t\n]")) (forward-sexp -1))
(catch 'found
(while t
(re-search-forward regexp nil 'move)
- (setq nest (if (match-end 1)
+ (setq nest (if (match-end 1)
(1+ nest)
(1- nest)))
(cond ((eobp)
(caseblock . ind) (cpp . 0)
(declaration . (+ ind pascal-indent-level))
(paramlist . (pascal-indent-paramlist t))
- (comment . (pascal-indent-comment t))
+ (comment . (pascal-indent-comment))
(defun . ind) (contexp . ind)
- (unknown . 0) (string . 0)))
+ (unknown . ind) (string . 0) (progbeg . 0)))
(defun pascal-indent-command ()
"Indent for special part of code."
(let* ((indent-str (pascal-calculate-indent))
(type (car indent-str))
(ind (car (cdr indent-str))))
- (if (looking-at "^[0-9a-zA-Z]+[ \t]*:[^=]")
+ ;; Labels should not be indented.
+ (if (and (looking-at "^[0-9a-zA-Z]+[ \t]*:[^=]")
+ (not (eq type 'declaration)))
(search-forward ":" nil t))
(delete-horizontal-space)
- ;; Some things should not be indented
- (if (or (and (eq type 'declaration) (looking-at pascal-declaration-re))
- (eq type 'cpp)
- (looking-at pascal-defun-re))
- ()
- ;; Other things should have no extra indent
- (if (looking-at pascal-noindent-re)
- (indent-to ind)
- ;; But most lines are treated this way:
- (indent-to (eval (cdr (assoc type pascal-indent-alist))))
- ))))
+ (cond (; Some things should not be indented
+ (or (and (eq type 'declaration) (looking-at pascal-declaration-re))
+ (eq type 'cpp))
+ ())
+ (; Other things should have no extra indent
+ (looking-at pascal-noindent-re)
+ (indent-to ind))
+ (; Nested functions should be indented
+ (looking-at pascal-defun-re)
+ (if (and pascal-indent-nested-functions
+ (eq type 'defun))
+ (indent-to (+ ind pascal-indent-level))
+ (indent-to ind)))
+ (; But most lines are treated this way
+ (indent-to (eval (cdr (assoc type pascal-indent-alist))))
+ ))))
(defun pascal-calculate-indent ()
"Calculate the indent of the current Pascal line.
Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(save-excursion
- (let* ((oldpos (point))
+ (let* ((parse-sexp-ignore-comments t)
+ (oldpos (point))
(state (save-excursion (parse-partial-sexp (point-min) (point))))
(nest 0) (par 0) (complete (looking-at "[ \t]*end\\>"))
- (elsed (looking-at "[ \t]*else\\>"))
+ (elsed (looking-at "[ \t]*else\\>")) (funccnt 0)
+ (did-func (looking-at "[ \t]*\\(procedure\\|function\\)\\>"))
(type (catch 'nesting
;; Check if inside a string, comment or parenthesis
(cond ((nth 3 state) (throw 'nesting 'string))
(point))
(point)))
(throw 'nesting 'caseblock))
+ (;--Beginning of program
+ (looking-at pascal-progbeg-re)
+ (throw 'nesting 'progbeg))
+ (;--No known statements
+ (bobp)
+ (throw 'nesting 'progbeg))
(;--Nest block outwards
(looking-at pascal-beg-block-re)
(if (= nest 0)
((looking-at "record\\>")
(throw 'nesting 'declaration))
(t (throw 'nesting 'block)))
+ (if (and (looking-at "record\\>") (= nest 1))
+ (setq funccnt (1- funccnt)))
(setq nest (1- nest))))
(;--Nest block inwards
(looking-at pascal-end-block-re)
(if (and (looking-at "end\\s ")
elsed (not complete))
(throw 'nesting 'block))
+ (if (= nest 0)
+ (setq funccnt (1+ funccnt)))
(setq complete t
nest (1+ nest)))
(;--Defun (or parameter list)
- (looking-at pascal-defun-re)
+ (and (looking-at pascal-defun-re)
+ (progn (setq funccnt (1- funccnt)
+ did-func t)
+ (or (bolp) (< funccnt 0))))
+ ;; Prevent searching whole buffer
+ (if (and (bolp) (>= funccnt 0))
+ (throw 'nesting 'progbeg))
(if (= 0 par)
(throw 'nesting 'defun)
(setq par 0)
(throw 'nesting 'declaration)
(throw 'nesting 'paramlist)))))
(;--Declaration part
- (looking-at pascal-declaration-re)
+ (and (looking-at pascal-declaration-re)
+ (not did-func)
+ (= funccnt 0))
(if (save-excursion
(goto-char oldpos)
(forward-line -1)
(save-excursion (forward-sexp 1)
(= (following-char) ?\;))
(setq complete t))
- (;--No known statements
- (bobp)
- (throw 'nesting 'unknown))
)))))
;; Return type of block and indent level.
- (if (> par 0) ; Unclosed Parenthesis
+ (if (> par 0) ; Unclosed Parenthesis
(list 'contexp par)
(list type (pascal-indent-level))))))
(skip-chars-forward " \t")
(current-column)))
-(defun pascal-indent-comment (&optional arg)
- "Indent current line as comment.
-If optional arg is non-nil, just return the
-column number the line should be indented to."
- (let* ((stcol (save-excursion
- (re-search-backward "(\\*\\|{" nil t)
- (1+ (current-column)))))
- (if arg stcol
- (delete-horizontal-space)
- (indent-to stcol))))
+(defun pascal-indent-comment ()
+ "Return indent for current comment."
+ (save-excursion
+ (re-search-backward "\\((\\*\\)\\|{" nil t)
+ (if (match-beginning 1)
+ (1+ (current-column))
+ (current-column))))
(defun pascal-indent-case ()
"Indent within case statements."
- (skip-chars-forward ": \t")
- (let ((end (prog2
+ (let ((savepos (point-marker))
+ (end (prog2
(end-of-line)
(point-marker)
(re-search-backward "\\<case\\>" nil t)))
(beg (point)) oldpos
(ind 0))
;; Get right indent
- (while (< (point) (marker-position end))
- (if (re-search-forward
+ (while (< (point) end)
+ (if (re-search-forward
"^[ \t]*[^ \t,:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
(marker-position end) 'move)
(forward-char -1))
- (delete-horizontal-space)
- (if (> (current-column) ind)
- (setq ind (current-column)))
- (pascal-end-of-statement))
+ (if (< (point) end)
+ (progn
+ (delete-horizontal-space)
+ (if (> (current-column) ind)
+ (setq ind (current-column)))
+ (pascal-end-of-statement))))
(goto-char beg)
(setq oldpos (marker-position end))
;; Indent all case statements
- (while (< (point) (marker-position end))
+ (while (< (point) end)
(if (re-search-forward
"^[ \t]*[^][ \t,\\.:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:"
(marker-position end) 'move)
(insert " "))
(setq oldpos (point))
(pascal-end-of-statement))
- (goto-char oldpos)))
+ (goto-char savepos)))
(defun pascal-indent-paramlist (&optional arg)
"Indent current line in parameterlist.
(let* ((oldpos (point))
(stpos (progn (goto-char (scan-lists (point) -1 1)) (point)))
(stcol (1+ (current-column)))
- (edpos (progn (pascal-declaration-end)
+ (edpos (progn (pascal-declaration-end)
(search-backward ")" (pascal-get-beg-of-line) t)
(point)))
(usevar (re-search-backward "\\<var\\>" stpos t)))
(let ((pos (point-marker)))
(if (and (not (or arg start)) (not (pascal-declaration-beg)))
()
- (let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start)
+ (let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start)
":" "="))
(stpos (if start start
(forward-word 2) (backward-word 1) (point)))
(goto-char stpos)
;; Indent lines in record block
(if arg
- (while (<= (point) (marker-position edpos))
+ (while (<= (point) edpos)
(beginning-of-line)
(delete-horizontal-space)
(if (looking-at "end\\>")
;; Do lineup
(setq ind (pascal-get-lineup-indent stpos edpos lineup))
(goto-char stpos)
- (while (<= (point) (marker-position edpos))
+ (while (and (<= (point) edpos) (not (eobp)))
(if (search-forward lineup (pascal-get-end-of-line) 'move)
(forward-char -1))
(delete-horizontal-space)
;; If arg - move point
(if arg (forward-line -1)
- (goto-char (marker-position pos)))))
+ (goto-char pos))))
; "Return the indent level that will line up several lines within the region
;from b to e nicely. The lineup string is str."
(defun pascal-get-lineup-indent (b e str)
(save-excursion
(let ((ind 0)
- (reg (concat str "\\|\\(\\<record\\>\\)"))
- nest)
+ (reg (concat str "\\|\\(\\<record\\>\\)\\|" pascal-defun-re)))
(goto-char b)
;; Get rightmost position
(while (< (point) e)
- (setq nest 1)
- (if (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move)
- (progn
- ;; Skip record blocks
- (if (match-beginning 1)
- (pascal-declaration-end)
- (progn
- (goto-char (match-beginning 0))
- (skip-chars-backward " \t")
- (if (> (current-column) ind)
- (setq ind (current-column)))
- (goto-char (match-end 0)))))))
+ (and (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move)
+ (cond ((match-beginning 1)
+ ;; Skip record blocks
+ (pascal-declaration-end))
+ ((match-beginning 2)
+ ;; We have entered a new procedure. Exit.
+ (goto-char e))
+ (t
+ (goto-char (match-beginning 0))
+ (skip-chars-backward " \t")
+ (if (> (current-column) ind)
+ (setq ind (current-column)))
+ (goto-char (match-end 0))
+ (end-of-line)
+ ))))
;; In case no lineup was found
(if (> ind 0)
(1+ ind)
(end-of-line)
(skip-chars-backward " \t")
(1+ (current-column))))))
-
+
\f
;;;
(t "\\<\\(function\\|procedure\\)\\s +"))
"\\<\\(" pascal-str "[a-zA-Z0-9_.]*\\)\\>"))
match)
-
+
(if (not (looking-at "\\<\\(function\\|procedure\\)\\>"))
(re-search-backward "\\<\\(function\\|procedure\\)\\>" nil t))
(forward-char 1)
(defun pascal-get-completion-decl ()
;; Macro for searching through current declaration (var, type or const)
- ;; for matches of `str' and adding the occurence tp `all'
+ ;; for matches of `str' and adding the occurrence to `all'
(let ((end (save-excursion (pascal-declaration-end)
(point)))
match)
(while (< (point) end)
(if (re-search-forward "[:=]" (pascal-get-end-of-line) t)
;; Traverse current line
- (while (and (re-search-backward
- (concat "\\((\\|\\<\\(var\\|type\\|const\\)\\>\\)\\|"
+ (while (and (re-search-backward
+ (concat "\\((\\|\\<\\(var\\|type\\|const\\)\\>\\)\\|"
pascal-symbol-re)
(pascal-get-beg-of-line) t)
(not (match-end 1)))
(save-excursion
(if (> start (prog1 (save-excursion (pascal-end-of-defun)
(point))))
- () ; Declarations not reacable
+ () ; Declarations not reachable
(if (search-forward "(" (pascal-get-end-of-line) t)
;; Check parameterlist
(pascal-get-completion-decl))
(defun pascal-keyword-completion (keyword-list)
"Give list of all possible completions of keywords in KEYWORD-LIST."
- (mapcar '(lambda (s)
+ (mapcar '(lambda (s)
(if (string-match (concat "\\<" pascal-str) s)
(if (or (null pascal-pred)
(funcall pascal-pred s))
(save-excursion
(let ((pascal-all nil))
;; Set buffer to use for searching labels. This should be set
- ;; within functins which use pascal-completions
+ ;; within functions which use pascal-completions
(set-buffer pascal-buffer-to-use)
;; Determine what should be completed
(save-excursion (pascal-var-completion))
(pascal-func-completion 'function)
(pascal-keyword-completion pascal-separator-keywords))))
-
+
;; Now we have built a list of all matches. Give response to caller
(pascal-completion-response))))
(let* ((elm (cdr pascal-all))
(match (car pascal-all))
(min (length match))
- exact tmp)
+ tmp)
(if (string= match pascal-str)
;; Return t if first match was an exact match
(setq match t)
(progn
;; Update entry number in list
(setq pascal-last-completions allcomp
- pascal-last-word-numb
+ pascal-last-word-numb
(if (>= pascal-last-word-numb (1- (length allcomp)))
0
(1+ pascal-last-word-numb)))
(insert "" pascal-last-word-shown)
(insert "" pascal-str)
(message "(No match)")))
- ;; The other form of completion does not necessarly do that.
+ ;; The other form of completion does not necessarily do that.
;; Insert match if found, or the original string if no match
(if (or (null match) (equal match 't))
(if (not (null (cdr allcomp)))
(message "(Complete but not unique)")
(message "(Sole completion)")))
- ;; Display buffer if the current completion didn't help
+ ;; Display buffer if the current completion didn't help
;; on completing the label.
((and (not (null (cdr allcomp))) (= (length pascal-str)
(length match)))
match)
;; Set buffer to use for searching labels. This should be set
- ;; within functins which use pascal-completions
+ ;; within functions which use pascal-completions
(set-buffer pascal-buffer-to-use)
(let ((pascal-str pascal-str))
(setq pascal-str (pascal-build-defun-re "[a-zA-Z_]"))
(setq pascal-str (pascal-build-defun-re pascal-str)))
(goto-char (point-min))
-
+
;; Build a list of all possible completions
(while (re-search-forward pascal-str nil t)
(setq match (buffer-substring (match-beginning 2) (match-end 2)))
(defun pascal-outline-change (b e pascal-flag)
(let ((modp (buffer-modified-p)))
(unwind-protect
- (subst-char-in-region b e (if (= pascal-flag ?\n)
+ (subst-char-in-region b e (if (= pascal-flag ?\n)
?\^M ?\n) pascal-flag)
(set-buffer-modified-p modp))))
(pascal-goto-defun)
(pascal-hide-other-defuns))
+(provide 'pascal)
+
+;;; arch-tag: 04535136-fd93-40b4-a505-c9bebdc051f5
;;; pascal.el ends here