X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9aecacd08a93bffb529cee59d74477890ce96f37..b201b9880e01120b7e64f82c98464c5bea630b0d:/lisp/progmodes/meta-mode.el diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el index a2fd9cdab0..c70f5cdb6a 100644 --- a/lisp/progmodes/meta-mode.el +++ b/lisp/progmodes/meta-mode.el @@ -51,7 +51,7 @@ ;; these lines to your startup file: ;; ;; (add-hook 'meta-mode-load-hook -;; '(lambda () (require 'meta-buf))) +;; (lambda () (require 'meta-buf))) ;; ;; The add-on package loaded this way may in turn make use of the ;; mode-hooks provided in this package to activate additional features @@ -124,7 +124,7 @@ ;; ;; This package was begun on February 1, 1997, exactly 20 years after ;; the genesis of TeX took place according to Don Knuth's own account -;; (cf. ``The Errors of TeX'', reprinted in ``Literate Programming'', +;; (cf. ``The Errors of TeX'', reprinted in ``Literate Programming'', ;; Chapter 10, p. 249). What better date could there be to choose? ;; @@ -194,42 +194,42 @@ (list ;; embedded TeX code in btex ... etex (cons (concat "\\(btex\\|verbatimtex\\)" - "[ \t]+\\(.*\\)[ \t]+" + "[ \t\f]+\\(.*\\)[ \t\f]+" "\\(etex\\)") '((1 font-lock-keyword-face) (2 font-lock-string-face) (3 font-lock-keyword-face))) ;; unary macro definitions: def, vardef, let (cons (concat "\\<" macro-keywords-1 "\\>" - "[ \t]+\\(\\sw+\\|\\s_+\\|\\s.+\\)") + "[ \t\f]+\\(\\sw+\\|\\s_+\\|\\s.+\\)") '((1 font-lock-keyword-face) (2 font-lock-function-name-face))) ;; binary macro defintions: x operator y (cons (concat "\\<" macro-keywords-2 "\\>" - "[ \t]+\\(\\sw+\\)" - "[ \t]*\\(\\sw+\\|\\s.+\\)" - "[ \t]*\\(\\sw+\\)") + "[ \t\f]+\\(\\sw+\\)" + "[ \t\f]*\\(\\sw+\\|\\s.+\\)" + "[ \t\f]*\\(\\sw+\\)") '((1 font-lock-keyword-face) (2 font-lock-variable-name-face nil t) (3 font-lock-function-name-face nil t) (4 font-lock-variable-name-face nil t))) ;; variable declarations: numeric, pair, color, ... (cons (concat "\\<" type-keywords "\\>" - "\\([ \t]+\\(\\sw+\\)\\)*") + "\\([ \t\f]+\\(\\sw+\\)\\)*") '((1 font-lock-type-face) (font-lock-match-meta-declaration-item-and-skip-to-next (goto-char (match-end 1)) nil (1 font-lock-variable-name-face nil t)))) ;; argument declarations: expr, suffix, text, ... (cons (concat "\\<" args-keywords "\\>" - "\\([ \t]+\\(\\sw+\\|\\s_+\\)\\)*") + "\\([ \t\f]+\\(\\sw+\\|\\s_+\\)\\)*") '((1 font-lock-type-face) (font-lock-match-meta-declaration-item-and-skip-to-next (goto-char (match-end 1)) nil (1 font-lock-variable-name-face nil t)))) ;; special case of arguments: expr x of y - (cons (concat "\\(expr\\)[ \t]+\\(\\sw+\\)" - "[ \t]+\\(of\\)[ \t]+\\(\\sw+\\)") + (cons (concat "\\(expr\\)[ \t\f]+\\(\\sw+\\)" + "[ \t\f]+\\(of\\)[ \t\f]+\\(\\sw+\\)") '((1 font-lock-type-face) (2 font-lock-variable-name-face) (3 font-lock-keyword-face nil t) @@ -245,7 +245,7 @@ 'font-lock-keyword-face) ;; input, generate (cons (concat "\\<" input-keywords "\\>" - "[ \t]+\\(\\sw+\\)") + "[ \t\f]+\\(\\sw+\\)") '((1 font-lock-keyword-face) (2 font-lock-constant-face))) ;; embedded Metafont/MetaPost code in comments @@ -264,7 +264,7 @@ ;; `forward-sexp'. The list of items is expected to be separated ;; by commas and terminated by semicolons or equals signs. ;; - (if (looking-at "[ \t]*\\(\\sw+\\|\\s_+\\)") + (if (looking-at "[ \t\f]*\\(\\sw+\\|\\s_+\\)") (save-match-data (condition-case nil (save-restriction @@ -272,7 +272,7 @@ (narrow-to-region (point-min) limit) (goto-char (match-end 1)) ;; Move over any item value, etc., to the next item. - (while (not (looking-at "[ \t]*\\(\\(,\\)\\|;\\|=\\|$\\)")) + (while (not (looking-at "[ \t\f]*\\(\\(,\\)\\|;\\|=\\|$\\)")) (goto-char (or (scan-sexps (point) 1) (point-max)))) (goto-char (match-end 2))) (error t))))) @@ -586,7 +586,7 @@ If the list was changed, sort the list and remove duplicates first." (if (and meta-left-comment-regexp (looking-at meta-left-comment-regexp)) (current-column) - (skip-chars-backward "\t ") + (skip-chars-backward "\t\f ") (max (if (bolp) 0 (1+ (current-column))) comment-column))) @@ -605,14 +605,16 @@ If the list was changed, sort the list and remove duplicates first." (defun meta-indent-calculate () "Return the indentation of current line of Metafont or MetaPost source." + ;; Indentation within strings is not considered as Meta* don't allow multi + ;; line strings. (save-excursion (back-to-indentation) (cond - ;; Comments to the left margin. + ;; Comments to the left margin. ((and meta-left-comment-regexp (looking-at meta-left-comment-regexp)) 0) - ;; Comments to the right margin. + ;; Comments to the right margin. ((and meta-right-comment-regexp (looking-at meta-right-comment-regexp)) comment-column) @@ -620,42 +622,117 @@ If the list was changed, sort the list and remove duplicates first." ((and meta-ignore-comment-regexp (looking-at meta-ignore-comment-regexp)) (current-indentation)) + ;; Beginning of buffer. + ((eq (point-at-bol) (point-min)) + 0) ;; Backindent at end of environments. - ((looking-at + ((meta-indent-looking-at-code (concat "\\<" meta-end-environment-regexp "\\>")) - (- (meta-indent-calculate-last) meta-indent-level)) + (- (meta-indent-current-indentation) meta-indent-level)) ;; Backindent at keywords within environments. - ((looking-at + ((meta-indent-looking-at-code (concat "\\<" meta-within-environment-regexp "\\>")) - (- (meta-indent-calculate-last) meta-indent-level)) - (t (meta-indent-calculate-last))))) - -(defun meta-indent-calculate-last () - "Return the indentation of previous line of Metafont or MetaPost source." - (save-restriction - (widen) - (skip-chars-backward "\n\t ") - (move-to-column (current-indentation)) - ;; Ignore comments. - (while (and (looking-at comment-start) (not (bobp))) - (skip-chars-backward "\n\t ") - (if (not (bobp)) - (move-to-column (current-indentation)))) - (cond - ((bobp) 0) - (t (+ (current-indentation) - (meta-indent-level-count) - (cond - ;; Compensate for backindent at end of environments. - ((looking-at - (concat "\\<"meta-end-environment-regexp "\\>")) - meta-indent-level) - ;; Compensate for backindent within environments. - ((looking-at - (concat "\\<" meta-within-environment-regexp "\\>")) - meta-indent-level) - (t 0))))) - )) + (- (meta-indent-current-indentation) meta-indent-level)) + (t (meta-indent-current-indentation))))) + +(defun meta-indent-in-string-p () + "Tell if the point is in a string." + (or (nth 3 (syntax-ppss)) + (eq (get-text-property (point) 'face) font-lock-string-face))) + +(defun meta-indent-looking-at-code (regexp) + "Same as `looking-at' but checks that the point is not in a string." + (unless (meta-indent-in-string-p) + (looking-at regexp))) + +(defun meta-indent-previous-line () + "Go to the previous line of code, skipping comments." + (skip-chars-backward "\n\t\f ") + (move-to-column (current-indentation)) + ;; Ignore comments. + (while (and (looking-at comment-start) (not (bobp))) + (skip-chars-backward "\n\t\f ") + (when (not (bobp)) + (move-to-column (current-indentation))))) + +(defun meta-indent-unfinished-line () + "Tell if the current line of code ends with an unfinished expression." + (save-excursion + (end-of-line) + ;; Skip backward the comments. + (let ((point-not-in-string (point))) + (while (search-backward comment-start (point-at-bol) t) + (unless (meta-indent-in-string-p) + (setq point-not-in-string (point)))) + (goto-char point-not-in-string)) + ;; Search for the end of the previous expression. + (if (search-backward ";" (point-at-bol) t) + (progn (while (and (meta-indent-in-string-p) + (search-backward ";" (point-at-bol) t))) + (if (= (char-after) ?\;) + (forward-char) + (beginning-of-line))) + (beginning-of-line)) + ;; See if the last statement of the line is environment-related, + ;; or exists at all. + (if (meta-indent-looking-at-code + (concat "[ \t\f]*\\($\\|" (regexp-quote comment-start) + "\\|\\<" meta-end-environment-regexp "\\>" + "\\|\\<" meta-begin-environment-regexp "\\>" + "\\|\\<" meta-within-environment-regexp "\\>\\)")) + nil + t))) + +(defun meta-indent-current-indentation () + "Return the indentation wanted for the current line of code." + (+ (meta-indent-current-nesting) + (if (save-excursion + (back-to-indentation) + (and (not (looking-at (concat "\\<" meta-end-environment-regexp "\\>" + "\\|\\<" meta-within-environment-regexp "\\>"))) + (progn (meta-indent-previous-line) + (meta-indent-unfinished-line)))) + meta-indent-level + 0))) + +(defun meta-indent-current-nesting () + "Return the indentation according to the nearest environment keyword." + (save-excursion + (save-restriction + (widen) + (back-to-indentation) + (let ((to-add 0)) + ;; If we found some environment marker backward... + (if (catch 'found + (while (re-search-backward + (concat "(\\|)\\|\\<" meta-end-environment-regexp "\\>" + "\\|\\<" meta-begin-environment-regexp "\\>" + "\\|\\<" meta-within-environment-regexp "\\>") + nil t) + ;; If we aren't in a string or in a comment, we've found something. + (unless (or (meta-indent-in-string-p) + (nth 4 (syntax-ppss))) + (cond ((= (char-after) ?\() + (setq to-add (+ to-add meta-indent-level))) + ((= (char-after) ?\)) + (setq to-add (- to-add meta-indent-level))) + (t (throw 'found t)))))) + (progn + ;; ... then use it to compute the current indentation. + (back-to-indentation) + (+ to-add (current-indentation) (meta-indent-level-count) + ;; Compensate for backindent of end and within keywords. + (if (meta-indent-looking-at-code + (concat "\\<" meta-end-environment-regexp "\\>\\|" + "\\<" meta-within-environment-regexp "\\>")) + meta-indent-level + ;; Compensate for unfinished line. + (if (save-excursion + (meta-indent-previous-line) + (meta-indent-unfinished-line)) + (- meta-indent-level) + 0)))) + 0))))) (defun meta-indent-level-count () "Count indentation change for begin-end commands in the current line." @@ -671,18 +748,12 @@ If the list was changed, sort the list and remove duplicates first." (goto-char (match-beginning 0)) (cond ;; Count number of begin-end keywords within line. - ((looking-at + ((meta-indent-looking-at-code (concat "\\<" meta-begin-environment-regexp "\\>")) (setq count (+ count meta-indent-level))) - ((looking-at + ((meta-indent-looking-at-code (concat "\\<" meta-end-environment-regexp "\\>")) - (setq count (- count meta-indent-level))) - ;; Count number of open-close parentheses within line. - ((looking-at "(") - (setq count (+ count meta-indent-level))) - ((looking-at ")") - (setq count (- count meta-indent-level))) - ))) + (setq count (- count meta-indent-level)))))) count)))) @@ -715,7 +786,7 @@ Returns t unless search stops due to beginning or end of buffer." (concat "\\<" meta-begin-defun-regexp "\\>") nil t arg) (progn (goto-char (match-beginning 0)) (skip-chars-backward "%") - (skip-chars-backward " \t") t))) + (skip-chars-backward " \t\f") t))) (defun meta-end-of-defun (&optional arg) "Move forward to end of a defun in Metafont or MetaPost code. @@ -729,7 +800,7 @@ Returns t unless search stops due to beginning or end of buffer." (concat "\\<" meta-end-defun-regexp "\\>") nil t arg) (progn (goto-char (match-end 0)) (skip-chars-forward ";") - (skip-chars-forward " \t") + (skip-chars-forward " \t\f") (if (looking-at "\n") (forward-line 1)) t))) @@ -797,78 +868,74 @@ The environment marked is the one that contains point or follows point." "Abbrev table used in Metafont or MetaPost mode.") (define-abbrev-table 'meta-mode-abbrev-table ()) -(defvar meta-mode-syntax-table nil +(defvar meta-mode-syntax-table + (let ((st (make-syntax-table))) + ;; underscores are word constituents + (modify-syntax-entry ?_ "w" st) + ;; miscellaneous non-word symbols + (modify-syntax-entry ?# "_" st) + (modify-syntax-entry ?@ "_" st) + (modify-syntax-entry ?$ "_" st) + (modify-syntax-entry ?? "_" st) + (modify-syntax-entry ?! "_" st) + ;; binary operators + (modify-syntax-entry ?& "." st) + (modify-syntax-entry ?+ "." st) + (modify-syntax-entry ?- "." st) + (modify-syntax-entry ?/ "." st) + (modify-syntax-entry ?* "." st) + (modify-syntax-entry ?. "." st) + (modify-syntax-entry ?: "." st) + (modify-syntax-entry ?= "." st) + (modify-syntax-entry ?< "." st) + (modify-syntax-entry ?> "." st) + (modify-syntax-entry ?| "." st) + ;; opening and closing delimiters + (modify-syntax-entry ?\( "()" st) + (modify-syntax-entry ?\) ")(" st) + (modify-syntax-entry ?\[ "(]" st) + (modify-syntax-entry ?\] ")[" st) + (modify-syntax-entry ?\{ "(}" st) + (modify-syntax-entry ?\} "){" st) + ;; comment character + (modify-syntax-entry ?% "<" st) + (modify-syntax-entry ?\n ">" st) + ;; escape character, needed for embedded TeX code + (modify-syntax-entry ?\\ "\\" st) + st) "Syntax table used in Metafont or MetaPost mode.") -(if meta-mode-syntax-table - () - (setq meta-mode-syntax-table (make-syntax-table)) - ;; underscores are word constituents - (modify-syntax-entry ?_ "w" meta-mode-syntax-table) - ;; miscellaneous non-word symbols - (modify-syntax-entry ?# "_" meta-mode-syntax-table) - (modify-syntax-entry ?@ "_" meta-mode-syntax-table) - (modify-syntax-entry ?$ "_" meta-mode-syntax-table) - (modify-syntax-entry ?? "_" meta-mode-syntax-table) - (modify-syntax-entry ?! "_" meta-mode-syntax-table) - ;; binary operators - (modify-syntax-entry ?& "." meta-mode-syntax-table) - (modify-syntax-entry ?+ "." meta-mode-syntax-table) - (modify-syntax-entry ?- "." meta-mode-syntax-table) - (modify-syntax-entry ?/ "." meta-mode-syntax-table) - (modify-syntax-entry ?* "." meta-mode-syntax-table) - (modify-syntax-entry ?. "." meta-mode-syntax-table) - (modify-syntax-entry ?: "." meta-mode-syntax-table) - (modify-syntax-entry ?= "." meta-mode-syntax-table) - (modify-syntax-entry ?< "." meta-mode-syntax-table) - (modify-syntax-entry ?> "." meta-mode-syntax-table) - (modify-syntax-entry ?| "." meta-mode-syntax-table) - ;; opening and closing delimiters - (modify-syntax-entry ?\( "()" meta-mode-syntax-table) - (modify-syntax-entry ?\) ")(" meta-mode-syntax-table) - (modify-syntax-entry ?\[ "(]" meta-mode-syntax-table) - (modify-syntax-entry ?\] ")[" meta-mode-syntax-table) - (modify-syntax-entry ?\{ "(}" meta-mode-syntax-table) - (modify-syntax-entry ?\} "){" meta-mode-syntax-table) - ;; comment character - (modify-syntax-entry ?% "<" meta-mode-syntax-table) - (modify-syntax-entry ?\n ">" meta-mode-syntax-table) - ;; escape character, needed for embedded TeX code - (modify-syntax-entry ?\\ "\\" meta-mode-syntax-table) - ) -(defvar meta-mode-map nil +(defvar meta-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-m" 'reindent-then-newline-and-indent) + ;; Comment Paragraphs: + ;; (define-key map "\M-a" 'backward-sentence) + ;; (define-key map "\M-e" 'forward-sentence) + ;; (define-key map "\M-h" 'mark-paragraph) + ;; (define-key map "\M-q" 'fill-paragraph) + ;; Navigation: + (define-key map "\M-\C-a" 'meta-beginning-of-defun) + (define-key map "\M-\C-e" 'meta-end-of-defun) + (define-key map "\M-\C-h" 'meta-mark-defun) + ;; Indentation: + (define-key map "\M-\C-q" 'meta-indent-defun) + (define-key map "\C-c\C-qe" 'meta-indent-defun) + (define-key map "\C-c\C-qr" 'meta-indent-region) + (define-key map "\C-c\C-qb" 'meta-indent-buffer) + ;; Commenting Out: + (define-key map "\C-c%" 'meta-comment-defun) + ;; (define-key map "\C-uC-c%" 'meta-uncomment-defun) + (define-key map "\C-c;" 'meta-comment-region) + (define-key map "\C-c:" 'meta-uncomment-region) + ;; Symbol Completion: + (define-key map "\M-\t" 'meta-complete-symbol) + ;; Shell Commands: + ;; (define-key map "\C-c\C-c" 'meta-command-file) + ;; (define-key map "\C-c\C-k" 'meta-kill-job) + ;; (define-key map "\C-c\C-l" 'meta-recenter-output) + map) "Keymap used in Metafont or MetaPost mode.") -(if meta-mode-map - () - (setq meta-mode-map (make-sparse-keymap)) - (define-key meta-mode-map "\t" 'meta-indent-line) - (define-key meta-mode-map "\C-m" 'reindent-then-newline-and-indent) - ;; Comment Paragraphs: -; (define-key meta-mode-map "\M-a" 'backward-sentence) -; (define-key meta-mode-map "\M-e" 'forward-sentence) -; (define-key meta-mode-map "\M-h" 'mark-paragraph) -; (define-key meta-mode-map "\M-q" 'fill-paragraph) - ;; Navigation: - (define-key meta-mode-map "\M-\C-a" 'meta-beginning-of-defun) - (define-key meta-mode-map "\M-\C-e" 'meta-end-of-defun) - (define-key meta-mode-map "\M-\C-h" 'meta-mark-defun) - ;; Indentation: - (define-key meta-mode-map "\M-\C-q" 'meta-indent-defun) - (define-key meta-mode-map "\C-c\C-qe" 'meta-indent-defun) - (define-key meta-mode-map "\C-c\C-qr" 'meta-indent-region) - (define-key meta-mode-map "\C-c\C-qb" 'meta-indent-buffer) - ;; Commenting Out: - (define-key meta-mode-map "\C-c%" 'meta-comment-defun) -; (define-key meta-mode-map "\C-uC-c%" 'meta-uncomment-defun) - (define-key meta-mode-map "\C-c;" 'meta-comment-region) - (define-key meta-mode-map "\C-c:" 'meta-uncomment-region) - ;; Symbol Completion: - (define-key meta-mode-map "\M-\t" 'meta-complete-symbol) - ;; Shell Commands: -; (define-key meta-mode-map "\C-c\C-c" 'meta-command-file) -; (define-key meta-mode-map "\C-c\C-k" 'meta-kill-job) -; (define-key meta-mode-map "\C-c\C-l" 'meta-recenter-output) - ) + (easy-menu-define meta-mode-menu meta-mode-map @@ -947,11 +1014,14 @@ The environment marked is the one that contains point or follows point." (make-local-variable 'comment-start) (make-local-variable 'comment-end) (make-local-variable 'comment-multi-line) - (setq comment-start-skip "%+[ \t]*") + (setq comment-start-skip "%+[ \t\f]*") (setq comment-start "%") (setq comment-end "") (setq comment-multi-line nil) + ;; We use `back-to-indentation' but \f is no indentation sign. + (modify-syntax-entry ?\f "_ ") + (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments t) @@ -1033,5 +1103,5 @@ Turning on MetaPost mode calls the value of the variable (provide 'meta-mode) (run-hooks 'meta-mode-load-hook) -;;; arch-tag: ec2916b2-3a83-4cf7-962d-d8019370c006 +;; arch-tag: ec2916b2-3a83-4cf7-962d-d8019370c006 ;;; meta-mode.el ends here