Commit 27b53c17 authored by Richard M. Stallman's avatar Richard M. Stallman
Browse files

(pascal-beg-of-defun): More intuitive behavior when having nested functons.

(pascal-indent-nested-functions) (pascal-indent-line)
(pascal-calculate-indent) (pascal-get-lineup-indent): Support for
indenting nested functions.
parent 9658746b
;;; pascal.el --- major mode for editing pascal source in Emacs ;;; pascal.el --- major mode for editing pascal source in Emacs
;; Copyright (C) 1993, 1994, 95, 96, 97, 1998 Free Software Foundation, Inc. ;; Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
;; Author: Espen Skoglund <espensk@stud.cs.uit.no> ;; Author: Espen Skoglund <espensk@stud.cs.uit.no>
;; Keywords: languages ;; Keywords: languages
...@@ -119,6 +119,7 @@ ...@@ -119,6 +119,7 @@
(defconst pascal-beg-block-re "\\<\\(begin\\|case\\|record\\|repeat\\)\\>") (defconst pascal-beg-block-re "\\<\\(begin\\|case\\|record\\|repeat\\)\\>")
(defconst pascal-end-block-re "\\<\\(end\\|until\\)\\>") (defconst pascal-end-block-re "\\<\\(end\\|until\\)\\>")
(defconst pascal-declaration-re "\\<\\(const\\|label\\|type\\|var\\)\\>") (defconst pascal-declaration-re "\\<\\(const\\|label\\|type\\|var\\)\\>")
(defconst pascal-progbeg-re "\\<\\program\\>")
(defconst pascal-defun-re "\\<\\(function\\|procedure\\|program\\)\\>") (defconst pascal-defun-re "\\<\\(function\\|procedure\\|program\\)\\>")
(defconst pascal-sub-block-re "\\<\\(if\\|else\\|for\\|while\\|with\\)\\>") (defconst pascal-sub-block-re "\\<\\(if\\|else\\|for\\|while\\|with\\)\\>")
(defconst pascal-noindent-re "\\<\\(begin\\|end\\|until\\|else\\)\\>") (defconst pascal-noindent-re "\\<\\(begin\\|end\\|until\\|else\\)\\>")
...@@ -195,6 +196,11 @@ These include after semicolons and after the punctuation mark after an `end'." ...@@ -195,6 +196,11 @@ These include after semicolons and after the punctuation mark after an `end'."
:type 'boolean :type 'boolean
:group 'pascal) :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 (defcustom pascal-tab-always-indent t
"*Non-nil means TAB in Pascal mode should always reindent the current line. "*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 If this is nil, TAB inserts a tab if it is at the end of the line
...@@ -216,10 +222,11 @@ do auto lineup in parameterlist, declarations or case-statements ...@@ -216,10 +222,11 @@ do auto lineup in parameterlist, declarations or case-statements
respectively. The word 'all' will do all lineups. '(case paramlist) for respectively. The word 'all' will do all lineups. '(case paramlist) for
instance will do lineup in case-statements and parameterlist, while '(all) instance will do lineup in case-statements and parameterlist, while '(all)
will do all lineups." will do all lineups."
:type '(repeat (choice (const all) :type '(set :extra-offset 8
(const paramlist) (const :tag "Everything" all)
(const declaration) (const :tag "Parameter lists" paramlist)
(const case))) (const :tag "Decalrations" declaration)
(const :tag "Case statements" case))
:group 'pascal) :group 'pascal)
(defcustom pascal-toggle-completions nil (defcustom pascal-toggle-completions nil
...@@ -323,20 +330,22 @@ Other useful functions are: ...@@ -323,20 +330,22 @@ Other useful functions are:
Variables controlling indentation/edit style: Variables controlling indentation/edit style:
pascal-indent-level (default 3) pascal-indent-level (default 3)
Indentation of Pascal statements with respect to containing block. Indentation of Pascal statements with respect to containing block.
pascal-case-indent (default 2) pascal-case-indent (default 2)
Indentation for case statements. Indentation for case statements.
pascal-auto-newline (default nil) pascal-auto-newline (default nil)
Non-nil means automatically newline after semicolons and the punctuation Non-nil means automatically newline after semicolons and the punctuation
mark after an end. mark after an end.
pascal-indent-nested-functions (default t)
Non-nil means nested functions are indented.
pascal-tab-always-indent (default t) pascal-tab-always-indent (default t)
Non-nil means TAB in Pascal mode should always reindent the current line, 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. 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 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. functions. The name of the function or case will be set between the braces.
pascal-auto-lineup (default t) pascal-auto-lineup (default t)
List of contexts where auto lineup of :'s or ='s should be done. 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 See also the user variables pascal-type-keywords, pascal-start-keywords and
...@@ -611,7 +620,7 @@ area. See also `pascal-comment-area'." ...@@ -611,7 +620,7 @@ area. See also `pascal-comment-area'."
(setq func (1+ func))) (setq func (1+ func)))
(setq nest (1- nest))) (setq nest (1- nest)))
((match-end 3) ; function|procedure ((match-end 3) ; function|procedure
(if (or (> nest 0) (= 0 func)) (if (= 0 func)
(throw 'found t) (throw 'found t)
(setq func (1- func))))))) (setq func (1- func)))))))
nil)) nil))
...@@ -777,7 +786,7 @@ on the line which ends a function or procedure named NAME." ...@@ -777,7 +786,7 @@ on the line which ends a function or procedure named NAME."
(paramlist . (pascal-indent-paramlist t)) (paramlist . (pascal-indent-paramlist t))
(comment . (pascal-indent-comment t)) (comment . (pascal-indent-comment t))
(defun . ind) (contexp . ind) (defun . ind) (contexp . ind)
(unknown . 0) (string . 0))) (unknown . ind) (string . 0) (progbeg . 0)))
(defun pascal-indent-command () (defun pascal-indent-command ()
"Indent for special part of code." "Indent for special part of code."
...@@ -805,20 +814,27 @@ on the line which ends a function or procedure named NAME." ...@@ -805,20 +814,27 @@ on the line which ends a function or procedure named NAME."
(let* ((indent-str (pascal-calculate-indent)) (let* ((indent-str (pascal-calculate-indent))
(type (car indent-str)) (type (car indent-str))
(ind (car (cdr 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)) (search-forward ":" nil t))
(delete-horizontal-space) (delete-horizontal-space)
;; Some things should not be indented (cond (; Some things should not be indented
(if (or (and (eq type 'declaration) (looking-at pascal-declaration-re)) (or (and (eq type 'declaration) (looking-at pascal-declaration-re))
(eq type 'cpp) (eq type 'cpp))
(looking-at pascal-defun-re)) ())
() (; Other things should have no extra indent
;; Other things should have no extra indent (looking-at pascal-noindent-re)
(if (looking-at pascal-noindent-re) (indent-to ind))
(indent-to ind) (; Nested functions should be indented
;; But most lines are treated this way: (looking-at pascal-defun-re)
(indent-to (eval (cdr (assoc type pascal-indent-alist)))) (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 () (defun pascal-calculate-indent ()
"Calculate the indent of the current Pascal line. "Calculate the indent of the current Pascal line.
...@@ -828,7 +844,8 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." ...@@ -828,7 +844,8 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(oldpos (point)) (oldpos (point))
(state (save-excursion (parse-partial-sexp (point-min) (point)))) (state (save-excursion (parse-partial-sexp (point-min) (point))))
(nest 0) (par 0) (complete (looking-at "[ \t]*end\\>")) (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 (type (catch 'nesting
;; Check if inside a string, comment or parenthesis ;; Check if inside a string, comment or parenthesis
(cond ((nth 3 state) (throw 'nesting 'string)) (cond ((nth 3 state) (throw 'nesting 'string))
...@@ -855,6 +872,12 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." ...@@ -855,6 +872,12 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(point)) (point))
(point))) (point)))
(throw 'nesting 'caseblock)) (throw 'nesting 'caseblock))
(;--Beginning of program
(looking-at pascal-progbeg-re)
(throw 'nesting 'progbeg))
(;--No known statements
(bobp)
(throw 'nesting 'progbeg))
(;--Nest block outwards (;--Nest block outwards
(looking-at pascal-beg-block-re) (looking-at pascal-beg-block-re)
(if (= nest 0) (if (= nest 0)
...@@ -863,16 +886,26 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." ...@@ -863,16 +886,26 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
((looking-at "record\\>") ((looking-at "record\\>")
(throw 'nesting 'declaration)) (throw 'nesting 'declaration))
(t (throw 'nesting 'block))) (t (throw 'nesting 'block)))
(if (and (looking-at "record\\>") (= nest 1))
(setq funccnt (1- funccnt)))
(setq nest (1- nest)))) (setq nest (1- nest))))
(;--Nest block inwards (;--Nest block inwards
(looking-at pascal-end-block-re) (looking-at pascal-end-block-re)
(if (and (looking-at "end\\s ") (if (and (looking-at "end\\s ")
elsed (not complete)) elsed (not complete))
(throw 'nesting 'block)) (throw 'nesting 'block))
(if (= nest 0)
(setq funccnt (1+ funccnt)))
(setq complete t (setq complete t
nest (1+ nest))) nest (1+ nest)))
(;--Defun (or parameter list) (;--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) (if (= 0 par)
(throw 'nesting 'defun) (throw 'nesting 'defun)
(setq par 0) (setq par 0)
...@@ -886,7 +919,9 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." ...@@ -886,7 +919,9 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(throw 'nesting 'declaration) (throw 'nesting 'declaration)
(throw 'nesting 'paramlist))))) (throw 'nesting 'paramlist)))))
(;--Declaration part (;--Declaration part
(looking-at pascal-declaration-re) (and (looking-at pascal-declaration-re)
(not did-func)
(= funccnt 0))
(if (save-excursion (if (save-excursion
(goto-char oldpos) (goto-char oldpos)
(forward-line -1) (forward-line -1)
...@@ -897,9 +932,6 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." ...@@ -897,9 +932,6 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(and (not complete) (and (not complete)
(looking-at pascal-sub-block-re)) (looking-at pascal-sub-block-re))
(throw 'nesting 'block)) (throw 'nesting 'block))
(;--No known statements
(bobp)
(throw 'nesting 'unknown))
(;--Found complete statement (;--Found complete statement
(save-excursion (forward-sexp 1) (save-excursion (forward-sexp 1)
(= (following-char) ?\;)) (= (following-char) ?\;))
...@@ -1052,23 +1084,25 @@ indent of the current line in parameterlist." ...@@ -1052,23 +1084,25 @@ indent of the current line in parameterlist."
(defun pascal-get-lineup-indent (b e str) (defun pascal-get-lineup-indent (b e str)
(save-excursion (save-excursion
(let ((ind 0) (let ((ind 0)
(reg (concat str "\\|\\(\\<record\\>\\)"))) (reg (concat str "\\|\\(\\<record\\>\\)\\|" pascal-defun-re)))
(goto-char b) (goto-char b)
;; Get rightmost position ;; Get rightmost position
(while (< (point) e) (while (< (point) e)
(if (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move) (and (re-search-forward reg (min e (pascal-get-end-of-line 2)) 'move)
(progn (cond ((match-beginning 1)
;; Skip record blocks ;; Skip record blocks
(if (match-beginning 1) (pascal-declaration-end))
(pascal-declaration-end) ((match-beginning 2)
(progn ;; We have entered a new procedure. Exit.
(goto-char (match-beginning 0)) (goto-char e))
(skip-chars-backward " \t") (t
(if (> (current-column) ind) (goto-char (match-beginning 0))
(setq ind (current-column))) (skip-chars-backward " \t")
(goto-char (match-end 0)) (if (> (current-column) ind)
(end-of-line) (setq ind (current-column)))
))))) (goto-char (match-end 0))
(end-of-line)
))))
;; In case no lineup was found ;; In case no lineup was found
(if (> ind 0) (if (> ind 0)
(1+ ind) (1+ ind)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment