;;; pascal.el --- major mode for editing pascal source in Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1993-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2016 Free Software Foundation, Inc.
;; Author: Espen Skoglund <esk@gnu.org>
;; Keywords: languages
;; =====
;; 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:
+;; When you have entered Pascal mode, you can get more info by pressing
+;; C-h m. You can also get 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
:group 'languages)
(defvar pascal-mode-abbrev-table nil
- "Abbrev table in use in Pascal-mode buffers.")
+ "Abbrev table in use in Pascal mode buffers.")
(define-abbrev-table 'pascal-mode-abbrev-table ())
(defvar pascal-mode-map
(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'.")
+ "Imenu expression for Pascal mode. See `imenu-generic-expression'.")
(defvar pascal-keywords
'("and" "array" "begin" "case" "const" "div" "do" "downto" "else" "end"
"\\<\\(label\\|var\\|type\\|const\\|until\\|end\\|begin\\|repeat\\|else\\)\\>")
;;; Strings used to mark beginning and end of excluded text
-(defconst pascal-exclude-str-start "{-----\\/----- EXCLUDED -----\\/-----")
-(defconst pascal-exclude-str-end " -----/\\----- EXCLUDED -----/\\-----}")
+(defconst pascal-exclude-str-start "{-----\\/----- EXCLUDED -----\\/-----"
+ "String used to mark beginning of excluded text.")
+(defconst pascal-exclude-str-end " -----/\\----- EXCLUDED -----/\\-----}"
+ "String used to mark end of excluded text.")
(defvar pascal-mode-syntax-table
(let ((st (make-syntax-table)))
-(defconst pascal-font-lock-keywords (purecopy
- (list
- '("^[ \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-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 "\\<\\("
- "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
- "not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
- "\\)\\>")
- '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
- 1 font-lock-keyword-face)
- '("\\<\\(goto\\)\\>[ \t]*\\([0-9]+\\)?"
- 2 font-lock-keyword-face t)))
+(defconst pascal-font-lock-keywords
+ `(("\\_<\\(function\\|pro\\(cedure\\|gram\\)\\)[ \t]+\\([[:alpha:]][[:alnum:]_]*\\)"
+ (1 font-lock-keyword-face)
+ (3 font-lock-function-name-face))
+ ;; ("type" "const" "real" "integer" "char" "boolean" "var"
+ ;; "record" "array" "file")
+ (,(concat "\\_<\\(array\\|boolean\\|c\\(har\\|onst\\)\\|file\\|"
+ "integer\\|re\\(al\\|cord\\)\\|type\\|var\\)\\_>")
+ . font-lock-type-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 "\\_<\\("
+ "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
+ "not\\|o[fr]\\|repeat\\|t\\(hen\\|o\\)\\|until\\|w\\(hile\\|ith\\)"
+ "\\)\\_>")
+ ("\\_<\\(goto\\)\\_>[ \t]*\\([0-9]+\\)?"
+ (1 font-lock-keyword-face) (2 font-lock-keyword-face t)))
"Additional expressions to highlight in Pascal mode.")
-(put 'pascal-mode 'font-lock-defaults '(pascal-font-lock-keywords nil t))
+
+(defconst pascal--syntax-propertize
+ (syntax-propertize-rules
+ ;; The syntax-table settings are too coarse and end up treating /* and (/
+ ;; as comment starters. Fix it here by removing the "2" from the syntax
+ ;; of the second char of such sequences.
+ ("/\\(\\*\\)" (1 ". 3b"))
+ ("(\\(\\/\\)" (1 (prog1 ". 1c" (forward-char -1) nil)))
+ ;; Pascal uses '' and "" rather than \' and \" to escape quotes.
+ ("''\\|\"\"" (0 (if (save-excursion
+ (nth 3 (syntax-ppss (match-beginning 0))))
+ (string-to-syntax ".")
+ ;; In case of 3 or more quotes in a row, only advance
+ ;; one quote at a time.
+ (forward-char -1)
+ nil)))))
(defcustom pascal-indent-level 3
"Indentation of Pascal statements with respect to containing block."
(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.
+Specifically, this is done after the ends of case 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
+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)
+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."
:type '(set :extra-offset 8
(const :tag "Everything" all)
;;;###autoload
(define-derived-mode pascal-mode prog-mode "Pascal"
- "Major mode for editing Pascal code. \\<pascal-mode-map>
+ "Major mode for editing Pascal code.\\<pascal-mode-map>
TAB indents for Pascal code. Delete converts tabs to spaces as it moves back.
\\[completion-at-point] completes the word around current point with respect \
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'.
-
-Turning on Pascal mode calls the value of the variable pascal-mode-hook with
-no args, if that value is non-nil."
- (set (make-local-variable 'local-abbrev-table) pascal-mode-abbrev-table)
- (set (make-local-variable 'indent-line-function) 'pascal-indent-line)
- (set (make-local-variable 'comment-indent-function) 'pascal-indent-comment)
- (set (make-local-variable 'parse-sexp-ignore-comments) nil)
- (set (make-local-variable 'blink-matching-paren-dont-ignore-comments) t)
- (set (make-local-variable 'case-fold-search) t)
- (set (make-local-variable 'comment-start) "{")
- (set (make-local-variable 'comment-start-skip) "(\\*+ *\\|{ *")
- (set (make-local-variable 'comment-end) "}")
+`pascal-separator-keywords'."
+ (setq-local local-abbrev-table pascal-mode-abbrev-table)
+ (setq-local indent-line-function 'pascal-indent-line)
+ (setq-local comment-indent-function 'pascal-indent-comment)
+ (setq-local parse-sexp-ignore-comments nil)
+ (setq-local blink-matching-paren-dont-ignore-comments t)
+ (setq-local case-fold-search t)
+ (setq-local comment-start "{")
+ (setq-local comment-start-skip "(\\*+ *\\|{ *")
+ (setq-local comment-end "}")
(add-hook 'completion-at-point-functions 'pascal-completions-at-point nil t)
;; Font lock support
- (set (make-local-variable 'font-lock-defaults)
- '(pascal-font-lock-keywords nil t))
+ (setq-local font-lock-defaults '(pascal-font-lock-keywords nil t))
+ (setq-local syntax-propertize-function pascal--syntax-propertize)
;; Imenu support
- (set (make-local-variable 'imenu-generic-expression)
- pascal-imenu-generic-expression)
- (set (make-local-variable 'imenu-case-fold-search) t)
+ (setq-local imenu-generic-expression pascal-imenu-generic-expression)
+ (setq-local imenu-case-fold-search t)
;; Pascal-mode's own hide/show support.
(add-to-invisibility-spec '(pascal . t)))
(insert " "))
(defun pascal-mark-defun ()
- "Mark the current pascal function (or procedure).
+ "Mark the current Pascal function (or procedure).
This puts the mark at the end, and point at the beginning."
(interactive)
(push-mark (point))
(zmacs-activate-region)))
(defun pascal-comment-area (start end)
- "Put the region into a Pascal comment.
+ "Put the region into a Pascal comment.\\<pascal-mode-map>
The comments that are in this area are \"deformed\":
`*)' becomes `!(*' and `}' becomes `!{'.
These deformed comments are returned to normal if you use
\\[pascal-uncomment-area] to undo the commenting.
-The commented area starts with `pascal-exclude-str-start', and ends with
-`pascal-include-str-end'. But if you change these variables,
+The commented area starts with `pascal-exclude-str-start', and ends
+with `pascal-exclude-str-end'. But if you change these variables,
\\[pascal-uncomment-area] won't recognize the comments."
(interactive "r")
(save-excursion
(defun pascal-uncomment-area ()
"Uncomment a commented area; change deformed comments back to normal.
-This command does nothing if the pointer is not in a commented
-area. See also `pascal-comment-area'."
+This command does nothing if the pointer is not in a commented area.
+See also `pascal-comment-area'."
(interactive)
(save-excursion
(let ((start (point))
(defun pascal-indent-level ()
"Return the indent-level the current statement has.
-Do not count labels, case-statements or records."
+Do not count labels, case statements or records."
(save-excursion
(beginning-of-line)
(if (looking-at "[ \t]*[0-9a-zA-Z]+[ \t]*:[^=]")
(defun pascal-indent-paramlist (&optional arg)
"Indent current line in parameterlist.
-If optional arg is non-nil, just return the
+If optional ARG is non-nil, just return the
indent of the current line in parameterlist."
(save-excursion
(let* ((oldpos (point))
(let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start)
":" "="))
(stpos (if start start
- (forward-word 2) (backward-word 1) (point)))
+ (forward-word-strictly 2) (backward-word 1) (point)))
(edpos (set-marker (make-marker)
(if end end
(max (progn (pascal-declaration-end)
if ARG is omitted or nil.
When enabled, portions of the text being edited may be made
-invisible. \\<pascal-outline-map>
+invisible.\\<pascal-outline-map>
Pascal Outline mode provides some additional commands.
\\[pascal-show-all]\t- Show the whole buffer.
\\[pascal-hide-other-defuns]\
\t- Hide everything but the current function (function under the cursor).
-\\[pascal-outline]\t- Leave pascal-outline-mode."
+\\[pascal-outline]\t- Leave Pascal Outline mode."
:init-value nil :lighter " Outl" :keymap pascal-outline-map
(add-to-invisibility-spec '(pascal . t))
(unless pascal-outline-mode