diff options
author | Daniel LaLiberte <liberte@gnu.org> | 1994-04-09 21:49:52 +0000 |
---|---|---|
committer | Daniel LaLiberte <liberte@gnu.org> | 1994-04-09 21:49:52 +0000 |
commit | 03cc57507bf8c3b21b12bdde2facbb63c2a5f13d (patch) | |
tree | 0c332edc81df1228e1bdc90dd2b05865af3a2bee /lisp/progmodes | |
parent | c4c197197897f6a1da4c64c4fc237f1fe3c239e5 (diff) | |
download | emacs-03cc57507bf8c3b21b12bdde2facbb63c2a5f13d.tar.gz |
BrachnCreate branch for FSF mods of edebug.el.
Diffstat (limited to 'lisp/progmodes')
-rw-r--r-- | lisp/progmodes/asm-mode.el | 219 | ||||
-rw-r--r-- | lisp/progmodes/awk-mode.el | 95 | ||||
-rw-r--r-- | lisp/progmodes/c-mode.el | 1485 | ||||
-rw-r--r-- | lisp/progmodes/cmacexp.el | 443 | ||||
-rw-r--r-- | lisp/progmodes/compile.el | 1307 | ||||
-rw-r--r-- | lisp/progmodes/cplus-md.el | 917 | ||||
-rw-r--r-- | lisp/progmodes/etags.el | 1447 | ||||
-rw-r--r-- | lisp/progmodes/fortran.el | 1292 | ||||
-rw-r--r-- | lisp/progmodes/hideif.el | 1041 | ||||
-rw-r--r-- | lisp/progmodes/icon.el | 559 | ||||
-rw-r--r-- | lisp/progmodes/inf-lisp.el | 634 | ||||
-rw-r--r-- | lisp/progmodes/make-mode.el | 1073 | ||||
-rw-r--r-- | lisp/progmodes/modula2.el | 454 | ||||
-rw-r--r-- | lisp/progmodes/pascal.el | 1404 | ||||
-rw-r--r-- | lisp/progmodes/perl-mode.el | 641 | ||||
-rw-r--r-- | lisp/progmodes/prolog.el | 271 | ||||
-rw-r--r-- | lisp/progmodes/scheme.el | 507 | ||||
-rw-r--r-- | lisp/progmodes/sh-script.el | 895 | ||||
-rw-r--r-- | lisp/progmodes/simula.el | 1291 | ||||
-rw-r--r-- | lisp/progmodes/tcl.el | 1816 |
20 files changed, 0 insertions, 17791 deletions
diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el deleted file mode 100644 index cd91a957bcf..00000000000 --- a/lisp/progmodes/asm-mode.el +++ /dev/null @@ -1,219 +0,0 @@ -;;; asm-mode.el --- mode for editing assembler code - -;; Copyright (C) 1991 Free Software Foundation, Inc. - -;; Author: Eric S. Raymond <esr@snark.thyrsus.com> -;; Last-Modified: 14 Jul 1992 -;; Keywords: tools, languages - -;; @(#)asm-mode.el 1.7 - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; This mode was written by Eric S. Raymond <esr@snark.thyrsus.com>, -;; inspired by an earlier asm-mode by Martin Neitzel. - -;; This minor mode is based on text mode. It defines a private abbrev table -;; that can be used to save abbrevs for assembler mnemonics. It binds just -;; five keys: -;; -;; TAB tab to next tab stop -;; : outdent preceding label, tab to tab stop -;; ; place or move comment -;; C-j, C-m newline and tab to tab stop -;; -;; Code is indented to the first tab stop level. -;; The ; key inserts copies of the value of asm-comment-char at an -;; appropriate spot. - -;; This mode runs two hooks: -;; 1) An asm-set-comment-hook before the part of the initialization -;; depending on asm-comment-char, and -;; 2) an asm-mode-hook at the end of initialization. - -;;; Code: - -(defvar asm-comment-char ?; - "*The comment-start character assumed by Asm mode.") - -(defvar asm-mode-syntax-table nil - "Syntax table used while in Asm mode.") - -(defvar asm-mode-abbrev-table nil - "Abbrev table used while in Asm mode.") -(define-abbrev-table 'asm-mode-abbrev-table ()) - -(defvar asm-mode-map nil - "Keymap for Asm mode.") - -(if asm-mode-map - nil - (setq asm-mode-map (make-sparse-keymap)) - (define-key asm-mode-map ";" 'asm-comment) - (define-key asm-mode-map ":" 'asm-colon) - (define-key asm-mode-map "\C-i" 'tab-to-tab-stop) - (define-key asm-mode-map "\C-j" 'asm-newline) - (define-key asm-mode-map "\C-m" 'asm-newline) - ) - -(defvar asm-code-level-empty-comment-pattern nil) -(defvar asm-flush-left-empty-comment-pattern nil) -(defvar asm-inline-empty-comment-pattern nil) - -;;;###autoload -(defun asm-mode () - "Major mode for editing typical assembler code. -Features a private abbrev table and the following bindings: - -\\[asm-colon]\toutdent a preceding label, tab to next tab stop. -\\[tab-to-tab-stop]\ttab to next tab stop. -\\[asm-newline]\tnewline, then tab to next tab stop. -\\[asm-comment]\tsmart placement of assembler comments. - -The character used for making comments is set by the variable -`asm-comment-char' (which defaults to `?;'). - -Alternatively, you may set this variable in `asm-set-comment-hook', which is -called near the beginning of mode initialization. - -Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization. - -Special commands: -\\{asm-mode-map} -" - (interactive) - (kill-all-local-variables) - (use-local-map asm-mode-map) - (setq mode-name "Assembler") - (setq major-mode 'asm-mode) - (setq local-abbrev-table asm-mode-abbrev-table) - (make-local-variable 'asm-mode-syntax-table) - (setq asm-mode-syntax-table (make-syntax-table)) - (set-syntax-table asm-mode-syntax-table) - (run-hooks 'asm-mode-set-comment-hook) - (modify-syntax-entry asm-comment-char - "<" asm-mode-syntax-table) - (modify-syntax-entry ?\n - ">" asm-mode-syntax-table) - (let ((cs (regexp-quote (char-to-string asm-comment-char)))) - (make-local-variable 'comment-start) - (setq comment-start (concat cs " ")) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip (concat cs "+[ \t]*")) - (setq asm-inline-empty-comment-pattern (concat "^.+" cs "+ *$")) - (setq asm-code-level-empty-comment-pattern (concat "^[\t ]+" cs cs " *$")) - (setq asm-flush-left-empty-comment-pattern (concat "^" cs cs cs " *$")) - ) - (make-local-variable 'comment-end) - (setq comment-end "") - (make-local-variable 'comment-column) - (setq comment-column 32) - (setq fill-prefix "\t") - (run-hooks 'asm-mode-hook) - ) - - -(defun asm-colon () - "Insert a colon; if it follows a label, delete the label's indentation." - (interactive) - (save-excursion - (beginning-of-line) - (if (looking-at "[ \t]+\\(\\sw\\|\\s_\\)+$") - (delete-horizontal-space))) - (insert ":") - (tab-to-tab-stop) - ) - -(defun asm-newline () - "Insert LFD + fill-prefix, to bring us back to code-indent level." - (interactive) - (if (eolp) (delete-horizontal-space)) - (insert "\n") - (tab-to-tab-stop) - ) - -(defun asm-line-matches (pattern &optional withcomment) - (save-excursion - (beginning-of-line) - (looking-at pattern))) - -(defun asm-pop-comment-level () - ;; Delete an empty comment ending current line. Then set up for a new one, - ;; on the current line if it was all comment, otherwise above it - (end-of-line) - (delete-horizontal-space) - (while (= (preceding-char) asm-comment-char) - (delete-backward-char 1)) - (delete-horizontal-space) - (if (bolp) - nil - (beginning-of-line) - (open-line 1)) - ) - - -(defun asm-comment () - "Convert an empty comment to a `larger' kind, or start a new one. -These are the known comment classes: - - 1 -- comment to the right of the code (at the comment-column) - 2 -- comment on its own line, indented like code - 3 -- comment on its own line, beginning at the left-most column. - -Suggested usage: while writing your code, trigger asm-comment -repeatedly until you are satisfied with the kind of comment." - (interactive) - (cond - - ;; Blank line? Then start comment at code indent level. - ((asm-line-matches "^[ \t]*$") - (delete-horizontal-space) - (tab-to-tab-stop) - (insert asm-comment-char comment-start)) - - ;; Nonblank line with no comment chars in it? - ;; Then start a comment at the current comment column - ((asm-line-matches (format "^[^%c]+$" asm-comment-char)) - (indent-for-comment)) - - ;; Flush-left comment present? Just insert character. - ((asm-line-matches asm-flush-left-empty-comment-pattern) - (insert asm-comment-char)) - - ;; Empty code-level comment already present? - ;; Then start flush-left comment, on line above if this one is nonempty. - ((asm-line-matches asm-code-level-empty-comment-pattern) - (asm-pop-comment-level) - (insert asm-comment-char asm-comment-char comment-start)) - - ;; Empty comment ends line? - ;; Then make code-level comment, on line above if this one is nonempty. - ((asm-line-matches asm-inline-empty-comment-pattern) - (asm-pop-comment-level) - (tab-to-tab-stop) - (insert asm-comment-char comment-start)) - - ;; If all else fails, insert character - (t - (insert asm-comment-char)) - - ) - (end-of-line)) - -;;; asm-mode.el ends here diff --git a/lisp/progmodes/awk-mode.el b/lisp/progmodes/awk-mode.el deleted file mode 100644 index ba3249ac357..00000000000 --- a/lisp/progmodes/awk-mode.el +++ /dev/null @@ -1,95 +0,0 @@ -;;; awk-mode.el --- AWK code editing commands for Emacs - -;; Copyright (C) 1988 Free Software Foundation, Inc. - -;; Maintainer: FSF -;; Keywords: unix, languages - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; Sets up C-mode with support for awk-style #-comments and a lightly -;; hacked syntax table. - -;;; Code: - -(defvar awk-mode-syntax-table nil - "Syntax table in use in Awk-mode buffers.") - -(if awk-mode-syntax-table - () - (setq awk-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\\ "\\" awk-mode-syntax-table) - (modify-syntax-entry ?\n "> " awk-mode-syntax-table) - (modify-syntax-entry ?\f "> " awk-mode-syntax-table) - (modify-syntax-entry ?\# "< " awk-mode-syntax-table) - (modify-syntax-entry ?/ "." awk-mode-syntax-table) - (modify-syntax-entry ?* "." awk-mode-syntax-table) - (modify-syntax-entry ?+ "." awk-mode-syntax-table) - (modify-syntax-entry ?- "." awk-mode-syntax-table) - (modify-syntax-entry ?= "." awk-mode-syntax-table) - (modify-syntax-entry ?% "." awk-mode-syntax-table) - (modify-syntax-entry ?< "." awk-mode-syntax-table) - (modify-syntax-entry ?> "." awk-mode-syntax-table) - (modify-syntax-entry ?& "." awk-mode-syntax-table) - (modify-syntax-entry ?| "." awk-mode-syntax-table) - (modify-syntax-entry ?\' "\"" awk-mode-syntax-table)) - -(defvar awk-mode-abbrev-table nil - "Abbrev table in use in Awk-mode buffers.") -(define-abbrev-table 'awk-mode-abbrev-table ()) - -;;;###autoload -(defun awk-mode () - "Major mode for editing AWK code. -This is much like C mode except for the syntax of comments. It uses -the same keymap as C mode and has the same variables for customizing -indentation. It has its own abbrev table and its own syntax table. - -Turning on AWK mode calls the value of the variable `awk-mode-hook' -with no args, if that value is non-nil." - (interactive) - (kill-all-local-variables) - (use-local-map c-mode-map) - (setq major-mode 'awk-mode) - (setq mode-name "AWK") - (setq local-abbrev-table awk-mode-abbrev-table) - (set-syntax-table awk-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'c-indent-line) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "# ") - (make-local-variable 'comment-end) - (setq comment-end "") - (make-local-variable 'comment-column) - (setq comment-column 32) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "#+ *") - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'c-comment-indent) - (run-hooks 'awk-mode-hook)) - -;;; awk-mode.el ends here diff --git a/lisp/progmodes/c-mode.el b/lisp/progmodes/c-mode.el deleted file mode 100644 index 91016c99b9b..00000000000 --- a/lisp/progmodes/c-mode.el +++ /dev/null @@ -1,1485 +0,0 @@ -;;; c-mode.el --- C code editing commands for Emacs -;; Copyright (C) 1985, 1986, 1987, 1992, 1994 Free Software Foundation, Inc. - -;; Maintainer: FSF -;; Keywords: c - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; A smart editing mode for C code. It knows a lot about C syntax and tries -;; to position the curser according to C layout conventions. You can -;; change the details of the layout style with option variables. Load it -;; and do M-x describe-mode for details. - -;;; Code: - -(defvar c-mode-abbrev-table nil - "Abbrev table in use in C mode.") -(define-abbrev-table 'c-mode-abbrev-table ()) - -(defvar c-mode-map (make-sparse-keymap) - "Keymap used in C mode.") - -(define-key c-mode-map "{" 'electric-c-brace) -(define-key c-mode-map "}" 'electric-c-brace) -(define-key c-mode-map ";" 'electric-c-semi) -(define-key c-mode-map "#" 'electric-c-sharp-sign) -(define-key c-mode-map ":" 'electric-c-terminator) -(define-key c-mode-map "\e\C-h" 'mark-c-function) -(define-key c-mode-map "\e\C-q" 'indent-c-exp) -(define-key c-mode-map "\ea" 'c-beginning-of-statement) -(define-key c-mode-map "\ee" 'c-end-of-statement) -(define-key c-mode-map "\eq" 'c-fill-paragraph) -(define-key c-mode-map "\C-c\C-n" 'c-forward-conditional) -(define-key c-mode-map "\C-c\C-p" 'c-backward-conditional) -(define-key c-mode-map "\C-c\C-u" 'c-up-conditional) -(define-key c-mode-map "\177" 'backward-delete-char-untabify) -(define-key c-mode-map "\t" 'c-indent-command) - -(define-key c-mode-map [menu-bar] (make-sparse-keymap)) - -(define-key c-mode-map [menu-bar c] - (cons "C" (make-sparse-keymap "C"))) - -(define-key c-mode-map [menu-bar c comment-region] - '("Comment Out Region" . comment-region)) -(define-key c-mode-map [menu-bar c c-macro-expand] - '("Macro Expand Region" . c-macro-expand)) -(define-key c-mode-map [menu-bar c c-backslash-region] - '("Backslashify" . c-backslash-region)) -(define-key c-mode-map [menu-bar c indent-exp] - '("Indent Expression" . indent-c-exp)) -(define-key c-mode-map [menu-bar c indent-line] - '("Indent Line" . c-indent-command)) -(define-key c-mode-map [menu-bar c fill] - '("Fill Comment Paragraph" . c-fill-paragraph)) -(define-key c-mode-map [menu-bar c up] - '("Up Conditional" . c-up-conditional)) -(define-key c-mode-map [menu-bar c backward] - '("Backward Conditional" . c-backward-conditional)) -(define-key c-mode-map [menu-bar c forward] - '("Forward Conditional" . c-forward-conditional)) -(define-key c-mode-map [menu-bar c backward-stmt] - '("Backward Statement" . c-beginning-of-statement)) -(define-key c-mode-map [menu-bar c forward-stmt] - '("Forward Statement" . c-end-of-statement)) - -(autoload 'c-macro-expand "cmacexp" - "Display the result of expanding all C macros occurring in the region. -The expansion is entirely correct because it uses the C preprocessor." - t) - -(defvar c-mode-syntax-table nil - "Syntax table in use in C-mode buffers.") - -(if c-mode-syntax-table - () - (setq c-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\\ "\\" c-mode-syntax-table) - (modify-syntax-entry ?/ ". 14" c-mode-syntax-table) - (modify-syntax-entry ?* ". 23" c-mode-syntax-table) - (modify-syntax-entry ?+ "." c-mode-syntax-table) - (modify-syntax-entry ?- "." c-mode-syntax-table) - (modify-syntax-entry ?= "." c-mode-syntax-table) - (modify-syntax-entry ?% "." c-mode-syntax-table) - (modify-syntax-entry ?< "." c-mode-syntax-table) - (modify-syntax-entry ?> "." c-mode-syntax-table) - (modify-syntax-entry ?& "." c-mode-syntax-table) - (modify-syntax-entry ?| "." c-mode-syntax-table) - (modify-syntax-entry ?\' "\"" c-mode-syntax-table)) - -(defconst c-indent-level 2 - "*Indentation of C statements with respect to containing block.") -(defconst c-brace-imaginary-offset 0 - "*Imagined indentation of a C open brace that actually follows a statement.") -(defconst c-brace-offset 0 - "*Extra indentation for braces, compared with other text in same context.") -(defconst c-argdecl-indent 5 - "*Indentation level of declarations of C function arguments.") -(defconst c-label-offset -2 - "*Offset of C label lines and case statements relative to usual indentation.") -(defconst c-continued-statement-offset 2 - "*Extra indent for lines not starting new statements.") -(defconst c-continued-brace-offset 0 - "*Extra indent for substatements that start with open-braces. -This is in addition to c-continued-statement-offset.") -(defconst c-style-alist - '(("GNU" - (c-indent-level . 2) - (c-argdecl-indent . 5) - (c-brace-offset . 0) - (c-label-offset . -2) - (c-continued-statement-offset . 2)) - ("K&R" - (c-indent-level . 5) - (c-argdecl-indent . 0) - (c-brace-offset . -5) - (c-label-offset . -5) - (c-continued-statement-offset . 5)) - ("BSD" - (c-indent-level . 4) - (c-argdecl-indent . 4) - (c-brace-offset . -4) - (c-label-offset . -4) - (c-continued-statement-offset . 4)) - ("C++" - (c-indent-level . 4) - (c-continued-statement-offset . 4) - (c-brace-offset . -4) - (c-argdecl-indent . 0) - (c-label-offset . -4) - (c-auto-newline . t)) - ("Whitesmith" - (c-indent-level . 4) - (c-argdecl-indent . 4) - (c-brace-offset . 0) - (c-label-offset . -4) - (c-continued-statement-offset . 4)))) - -(defconst c-auto-newline nil - "*Non-nil means automatically newline before and after braces, -and after colons and semicolons, inserted in C code. -If you do not want a leading newline before braces then use: - (define-key c-mode-map \"{\" 'electric-c-semi)") - -(defconst c-tab-always-indent t - "*Non-nil means TAB in C mode should always reindent the current line, -regardless of where in the line point is when the TAB command is used.") - -;;; Regular expression used internally to recognize labels in switch -;;; statements. -(defconst c-switch-label-regexp "case[ \t'/(]\\|default\\(\\S_\\|'\\)") - - -(defun c-mode () - "Major mode for editing C code. -Expression and list commands understand all C brackets. -Tab indents for C code. -Comments are delimited with /* ... */. -Paragraphs are separated by blank lines only. -Delete converts tabs to spaces as it moves back. -\\{c-mode-map} -Variables controlling indentation style: - c-tab-always-indent - Non-nil means TAB in C mode should always reindent the current line, - regardless of where in the line point is when the TAB command is used. - c-auto-newline - Non-nil means automatically newline before and after braces, - and after colons and semicolons, inserted in C code. - c-indent-level - Indentation of C statements within surrounding block. - The surrounding block's indentation is the indentation - of the line on which the open-brace appears. - c-continued-statement-offset - Extra indentation given to a substatement, such as the - then-clause of an if or body of a while. - c-continued-brace-offset - Extra indentation given to a brace that starts a substatement. - This is in addition to c-continued-statement-offset. - c-brace-offset - Extra indentation for line if it starts with an open brace. - c-brace-imaginary-offset - An open brace following other text is treated as if it were - this far to the right of the start of its line. - c-argdecl-indent - Indentation level of declarations of C function arguments. - c-label-offset - Extra indentation for line that is a label, or case or default. - -Settings for K&R and BSD indentation styles are - c-indent-level 5 8 - c-continued-statement-offset 5 8 - c-brace-offset -5 -8 - c-argdecl-indent 0 8 - c-label-offset -5 -8 - -Turning on C mode calls the value of the variable c-mode-hook with no args, -if that value is non-nil." - (interactive) - (kill-all-local-variables) - (use-local-map c-mode-map) - (setq major-mode 'c-mode) - (setq mode-name "C") - (setq local-abbrev-table c-mode-abbrev-table) - (set-syntax-table c-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'c-indent-line) - (make-local-variable 'indent-region-function) - (setq indent-region-function 'c-indent-region) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'outline-regexp) - (setq outline-regexp "[^#\n\^M]") - (make-local-variable 'outline-level) - (setq outline-level 'c-outline-level) - (make-local-variable 'comment-start) - (setq comment-start "/* ") - (make-local-variable 'comment-end) - (setq comment-end " */") - (make-local-variable 'comment-column) - (setq comment-column 32) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "/\\*+ *") - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'c-comment-indent) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t) - (run-hooks 'c-mode-hook)) - -(defun c-outline-level () - (save-excursion - (skip-chars-forward "\t ") - (current-column))) - -;; This is used by indent-for-comment -;; to decide how much to indent a comment in C code -;; based on its context. -(defun c-comment-indent () - (if (looking-at "^/\\*") - 0 ;Existing comment at bol stays there. - (let ((opoint (point))) - (save-excursion - (beginning-of-line) - (cond ((looking-at "[ \t]*}[ \t]*\\($\\|/\\*\\)") - ;; A comment following a solitary close-brace - ;; should have only one space. - (search-forward "}") - (1+ (current-column))) - ((or (looking-at "^#[ \t]*endif[ \t]*") - (looking-at "^#[ \t]*else[ \t]*")) - 7) ;2 spaces after #endif - ((progn - (goto-char opoint) - (skip-chars-backward " \t") - (and (= comment-column 0) (bolp))) - ;; If comment-column is 0, and nothing but space - ;; before the comment, align it at 0 rather than 1. - 0) - (t - (max (1+ (current-column)) ;Else indent at comment column - comment-column))))))) ; except leave at least one space. - -(defun c-fill-paragraph (&optional arg) - "Like \\[fill-paragraph] but handle C comments. -If any of the current line is a comment or within a comment, -fill the comment or the paragraph of it that point is in, -preserving the comment indentation or line-starting decorations." - (interactive "P") - (let* (comment-start-place - (first-line - ;; Check for obvious entry to comment. - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t\n") - (and (looking-at comment-start-skip) - (setq comment-start-place (point)))))) - (if (and (eq major-mode 'c++-mode) - (save-excursion - (beginning-of-line) - (looking-at ".*//"))) - (let (fill-prefix - (paragraph-start - ;; Lines containing just a comment start or just an end - ;; should not be filled into paragraphs they are next to. - (concat - paragraph-start - "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[ \t/*]*$")) - (paragraph-separate - (concat - paragraph-separate - "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[ \t/*]*$"))) - (save-excursion - (beginning-of-line) - ;; Move up to first line of this comment. - (while (and (not (bobp)) (looking-at "[ \t]*//")) - (forward-line -1)) - (if (not (looking-at ".*//")) - (forward-line 1)) - ;; Find the comment start in this line. - (re-search-forward "[ \t]*//[ \t]*") - ;; Set the fill-prefix to be what all lines except the first - ;; should start with. - (let ((endcol (current-column))) - (skip-chars-backward " \t") - (setq fill-prefix - (concat (make-string (- (current-column) 2) ?\ ) - "//" - (make-string (- endcol (current-column)) ?\ )))) - (save-restriction - ;; Narrow down to just the lines of this comment. - (narrow-to-region (point) - (save-excursion - (forward-line 1) - (while (looking-at "[ \t]*//") - (forward-line 1)) - (point))) - (insert fill-prefix) - (fill-paragraph arg) - (delete-region (point-min) - (+ (point-min) (length fill-prefix)))))) - (if (or first-line - ;; t if we enter a comment between start of function and this line. - (eq (calculate-c-indent) t) - ;; t if this line contains a comment starter. - (setq first-line - (save-excursion - (beginning-of-line) - (prog1 - (re-search-forward comment-start-skip - (save-excursion (end-of-line) - (point)) - t) - (setq comment-start-place (point)))))) - ;; Inside a comment: fill one comment paragraph. - (let ((fill-prefix - ;; The prefix for each line of this paragraph - ;; is the appropriate part of the start of this line, - ;; up to the column at which text should be indented. - (save-excursion - (beginning-of-line) - (if (looking-at "[ \t]*/\\*.*\\*/") - (progn (re-search-forward comment-start-skip) - (make-string (current-column) ?\ )) - (if first-line (forward-line 1)) - - (let ((line-width (progn (end-of-line) (current-column)))) - (beginning-of-line) - (prog1 - (buffer-substring - (point) - - ;; How shall we decide where the end of the - ;; fill-prefix is? - ;; calculate-c-indent-within-comment bases its value - ;; on the indentation of previous lines; if they're - ;; indented specially, it could return a column - ;; that's well into the current line's text. So - ;; we'll take at most that many space, tab, or * - ;; characters, and use that as our fill prefix. - (let ((max-prefix-end - (progn - (move-to-column - (calculate-c-indent-within-comment t) - t) - (point)))) - (beginning-of-line) - (skip-chars-forward " \t*" max-prefix-end) - (point))) - - ;; If the comment is only one line followed by a blank - ;; line, calling move-to-column above may have added - ;; some spaces and tabs to the end of the line; the - ;; fill-paragraph function will then delete it and the - ;; newline following it, so we'll lose a blank line - ;; when we shouldn't. So delete anything - ;; move-to-column added to the end of the line. We - ;; record the line width instead of the position of the - ;; old line end because move-to-column might break a - ;; tab into spaces, and the new characters introduced - ;; there shouldn't be deleted. - - ;; If you can see a better way to do this, please make - ;; the change. This seems very messy to me. - (delete-region (progn (move-to-column line-width) - (point)) - (progn (end-of-line) (point)))))))) - - (paragraph-start - ;; Lines containing just a comment start or just an end - ;; should not be filled into paragraphs they are next to. - (concat - paragraph-start - "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[ \t/*]*$")) - (paragraph-separate - (concat - paragraph-separate - "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[ \t/*]*$")) - (chars-to-delete 0)) - (save-restriction - ;; Don't fill the comment together with the code following it. - ;; So temporarily exclude everything before the comment start, - ;; and everything after the line where the comment ends. - ;; If comment-start-place is non-nil, the comment starter is there. - ;; Otherwise, point is inside the comment. - (narrow-to-region (save-excursion - (if comment-start-place - (goto-char comment-start-place) - (search-backward "/*")) - ;; Protect text before the comment start - ;; by excluding it. Add spaces to bring back - ;; proper indentation of that point. - (let ((column (current-column))) - (prog1 (point) - (setq chars-to-delete column) - (insert-char ?\ column)))) - (save-excursion - (if comment-start-place - (goto-char (+ comment-start-place 2))) - (search-forward "*/" nil 'move) - (forward-line 1) - (point))) - (fill-paragraph arg) - (save-excursion - ;; Delete the chars we inserted to avoid clobbering - ;; the stuff before the comment start. - (goto-char (point-min)) - (if (> chars-to-delete 0) - (delete-region (point) (+ (point) chars-to-delete))) - ;; Find the comment ender (should be on last line of buffer, - ;; given the narrowing) and don't leave it on its own line. - ;; Do this with a fill command, so as to preserve sentence - ;; boundaries. - (goto-char (point-max)) - (forward-line -1) - (search-forward "*/" nil 'move) - (beginning-of-line) - (if (looking-at "[ \t]*\\*/") - (let ((fill-column (+ fill-column 9999))) - (forward-line -1) - (fill-region-as-paragraph (point) (point-max))))))) - ;; Outside of comments: do ordinary filling. - (fill-paragraph arg))))) - -(defun electric-c-brace (arg) - "Insert character and correct line's indentation." - (interactive "P") - (let (insertpos) - (if (and (not arg) - (eolp) - (or (save-excursion - (skip-chars-backward " \t") - (bolp)) - (if c-auto-newline (progn (c-indent-line) (newline) t) nil))) - (progn - (insert last-command-char) - (c-indent-line) - (if c-auto-newline - (progn - (newline) - ;; (newline) may have done auto-fill - (setq insertpos (- (point) 2)) - (c-indent-line))) - (save-excursion - (if insertpos (goto-char (1+ insertpos))) - (delete-char -1)))) - (if insertpos - (save-excursion - (goto-char insertpos) - (self-insert-command (prefix-numeric-value arg))) - (self-insert-command (prefix-numeric-value arg))))) - -(defun electric-c-sharp-sign (arg) - "Insert character and correct line's indentation." - (interactive "P") - (if (save-excursion - (skip-chars-backward " \t") - (bolp)) - (let ((c-auto-newline nil)) - (electric-c-terminator arg)) - (self-insert-command (prefix-numeric-value arg)))) - -(defun electric-c-semi (arg) - "Insert character and correct line's indentation." - (interactive "P") - (if c-auto-newline - (electric-c-terminator arg) - (self-insert-command (prefix-numeric-value arg)))) - -(defun electric-c-terminator (arg) - "Insert character and correct line's indentation." - (interactive "P") - (let (insertpos (end (point))) - (if (and (not arg) (eolp) - (not (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (or (= (following-char) ?#) - ;; Colon is special only after a label, or case .... - ;; So quickly rule out most other uses of colon - ;; and do no indentation for them. - (and (eq last-command-char ?:) - (not (looking-at c-switch-label-regexp)) - (save-excursion - (skip-chars-forward "a-zA-Z0-9_$") - (skip-chars-forward " \t") - (< (point) end))) - (progn - (beginning-of-defun) - (let ((pps (parse-partial-sexp (point) end))) - (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) - (progn - (insert last-command-char) - (c-indent-line) - (and c-auto-newline - (not (c-inside-parens-p)) - (progn - (newline) - ;; (newline) may have done auto-fill - (setq insertpos (- (point) 2)) - (c-indent-line))) - (save-excursion - (if insertpos (goto-char (1+ insertpos))) - (delete-char -1)))) - (if insertpos - (save-excursion - (goto-char insertpos) - (self-insert-command (prefix-numeric-value arg))) - (self-insert-command (prefix-numeric-value arg))))) - -(defun c-inside-parens-p () - (condition-case () - (save-excursion - (save-restriction - (narrow-to-region (point) - (progn (beginning-of-defun) (point))) - (goto-char (point-max)) - (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\())) - (error nil))) - -(defun c-indent-command (&optional whole-exp) - "Indent current line as C code, or in some cases insert a tab character. -If `c-tab-always-indent' is non-nil (the default), always indent current line. -Otherwise, indent the current line only if point is at the left margin or -in the line's indentation; otherwise insert a tab. - -A numeric argument, regardless of its value, means indent rigidly all the -lines of the expression starting after point so that this line becomes -properly indented. The relative indentation among the lines of the -expression are preserved." - (interactive "P") - (if whole-exp - ;; If arg, always indent this line as C - ;; and shift remaining lines of expression the same amount. - (let ((shift-amt (c-indent-line)) - beg end) - (save-excursion - (if c-tab-always-indent - (beginning-of-line)) - ;; Find beginning of following line. - (save-excursion - (forward-line 1) (setq beg (point))) - ;; Find first beginning-of-sexp for sexp extending past this line. - (while (< (point) beg) - (forward-sexp 1) - (setq end (point)) - (skip-chars-forward " \t\n"))) - (if (> end beg) - (indent-code-rigidly beg end shift-amt "#"))) - (if (and (not c-tab-always-indent) - (save-excursion - (skip-chars-backward " \t") - (not (bolp)))) - (insert-tab) - (c-indent-line)))) - -(defun c-indent-line () - "Indent current line as C code. -Return the amount the indentation changed by." - (let ((indent (calculate-c-indent nil)) - beg shift-amt - (case-fold-search nil) - (pos (- (point-max) (point)))) - (beginning-of-line) - (setq beg (point)) - (cond ((eq indent nil) - (setq indent (current-indentation))) - ((eq indent t) - (setq indent (calculate-c-indent-within-comment))) - ((looking-at "[ \t]*#") - (setq indent 0)) - (t - (skip-chars-forward " \t") - (if (listp indent) (setq indent (car indent))) - (cond ((or (looking-at c-switch-label-regexp) - (and (looking-at "[A-Za-z]") - (save-excursion - (forward-sexp 1) - (looking-at ":")))) - (setq indent (max 1 (+ indent c-label-offset)))) - ((and (looking-at "else\\b") - (not (looking-at "else\\s_"))) - (setq indent (save-excursion - (c-backward-to-start-of-if) - (current-indentation)))) - ((looking-at "}[ \t]*else") - (setq indent (save-excursion - (forward-char) - (backward-sexp) - (c-backward-to-start-of-if) - (current-indentation)))) - ((and (looking-at "while\\b") - (save-excursion - (c-backward-to-start-of-do))) - ;; This is a `while' that ends a do-while. - (setq indent (save-excursion - (c-backward-to-start-of-do) - (current-indentation)))) - ((= (following-char) ?}) - (setq indent (- indent c-indent-level))) - ((= (following-char) ?{) - (setq indent (+ indent c-brace-offset)))))) - (skip-chars-forward " \t") - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - (delete-region beg (point)) - (indent-to indent) - ;; If initial point was within line's indentation, - ;; position after the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos)))) - shift-amt)) - -(defun calculate-c-indent (&optional parse-start) - "Return appropriate indentation for current line as C code. -In usual case returns an integer: the column to indent to. -Returns nil if line starts inside a string, t if in a comment." - (save-excursion - (beginning-of-line) - (let ((indent-point (point)) - (case-fold-search nil) - state - containing-sexp) - (if parse-start - (goto-char parse-start) - (beginning-of-defun)) - (while (< (point) indent-point) - (setq parse-start (point)) - (setq state (parse-partial-sexp (point) indent-point 0)) - (setq containing-sexp (car (cdr state)))) - (cond ((or (nth 3 state) (nth 4 state)) - ;; return nil or t if should not change this line - (nth 4 state)) - ((null containing-sexp) - ;; Line is at top level. May be data or function definition, - ;; or may be function argument declaration. - ;; Indent like the previous top level line - ;; unless that ends in a closeparen without semicolon, - ;; in which case this line is the first argument decl. - (goto-char indent-point) - (skip-chars-forward " \t") - (if (= (following-char) ?{) - 0 ; Unless it starts a function body - (c-backward-to-noncomment (or parse-start (point-min))) - ;; Look at previous line that's at column 0 - ;; to determine whether we are in top-level decls - ;; or function's arg decls. Set basic-indent accordingly. - (let ((basic-indent - (save-excursion - (re-search-backward "^[^ \^L\t\n#]" nil 'move) - (let (comment lim) - ;; Recognize the DEFUN macro in Emacs. - (if (save-excursion - ;; Move down to the (putative) argnames line. - (while (and (not (eobp)) - (not (looking-at " *[({}#/]"))) - (forward-line 1)) - ;; Go back to the DEFUN, if it is one. - (condition-case nil - (backward-sexp 1) - (error)) - (beginning-of-line) - (looking-at "DEFUN\\b")) - c-argdecl-indent - (if (and (looking-at "\\sw\\|\\s_") - ;; This is careful to stop at the first - ;; paren if we have - ;; int foo Proto ((int, int)); - (looking-at "[^\"\n=(]*(") - (progn - (goto-char (1- (match-end 0))) - (setq lim (point)) - (condition-case nil - (forward-sexp 1) - (error)) - (skip-chars-forward " \t\f") - (and (< (point) indent-point) - (not (memq (following-char) - '(?\, ?\;))))) - ;; Make sure the "function decl" we found - ;; is not inside a comment. - (progn - ;; Move back to the `(' starting arglist - (goto-char lim) - (beginning-of-line) - (while (and (not comment) - (search-forward "/*" lim t)) - (setq comment - (not (search-forward "*/" lim t)))) - (not comment))) - c-argdecl-indent 0)))))) - basic-indent))) - -;; ;; Now add a little if this is a continuation line. -;; (+ basic-indent (if (or (bobp) -;; (memq (preceding-char) '(?\) ?\; ?\})) -;; ;; Line with zero indentation -;; ;; is probably the return-type -;; ;; of a function definition, -;; ;; so following line is function name. -;; (= (current-indentation) 0)) -;; 0 c-continued-statement-offset)) - - ((/= (char-after containing-sexp) ?{) - ;; line is expression, not statement: - ;; indent to just after the surrounding open. - (goto-char (1+ containing-sexp)) - (current-column)) - (t - ;; Statement level. Is it a continuation or a new statement? - ;; Find previous non-comment character. - (goto-char indent-point) - (c-backward-to-noncomment containing-sexp) - ;; Back up over label lines, since they don't - ;; affect whether our line is a continuation. - (while (or (eq (preceding-char) ?\,) - (and (eq (preceding-char) ?:) - (or (eq (char-after (- (point) 2)) ?\') - (memq (char-syntax (char-after (- (point) 2))) - '(?w ?_))))) - (if (eq (preceding-char) ?\,) - (progn (forward-char -1) - (c-backward-to-start-of-continued-exp containing-sexp))) - (beginning-of-line) - (c-backward-to-noncomment containing-sexp)) - ;; Check for a preprocessor statement or its continuation lines. - ;; Move back to end of previous non-preprocessor line, - ;; or possibly beginning of buffer. - (let ((found (point)) stop) - (while (not stop) - (beginning-of-line) - (cond ((bobp) - (setq found (point) - stop t)) - ((save-excursion (forward-char -1) - (= (preceding-char) ?\\)) - (forward-char -1)) - ;; This line is not preceded by a backslash. - ;; So either it starts a preprocessor command - ;; or any following continuation lines - ;; should not be skipped. - ((= (following-char) ?#) - (forward-char -1) - (setq found (point))) - (t (setq stop t)))) - (goto-char found)) - ;; Now we get the answer. - (if (and (not (memq (preceding-char) '(0 ?\, ?\; ?\} ?\{))) - ;; But don't treat a line with a close-brace - ;; as a continuation. It is probably the - ;; end of an enum type declaration. - (save-excursion - (goto-char indent-point) - (skip-chars-forward " \t") - (not (= (following-char) ?})))) - ;; This line is continuation of preceding line's statement; - ;; indent c-continued-statement-offset more than the - ;; previous line of the statement. - (progn - (c-backward-to-start-of-continued-exp containing-sexp) - (+ c-continued-statement-offset (current-column) - (if (save-excursion (goto-char indent-point) - (skip-chars-forward " \t") - (eq (following-char) ?{)) - c-continued-brace-offset 0))) - ;; This line starts a new statement. - ;; Position following last unclosed open. - (goto-char containing-sexp) - ;; Is line first statement after an open-brace? - (or - ;; If no, find that first statement and indent like it. - (save-excursion - (forward-char 1) - (let ((colon-line-end 0)) - (while (progn (skip-chars-forward " \t\n") - (looking-at "#\\|/\\*\\|case[ \t\n'/(].*:\\|[a-zA-Z0-9_$]*:")) - ;; Skip over comments and labels following openbrace. - (cond ((= (following-char) ?\#) - (forward-line 1)) - ((= (following-char) ?\/) - (forward-char 2) - (search-forward "*/" nil 'move)) - ;; case or label: - (t - (save-excursion (end-of-line) - (setq colon-line-end (point))) - (search-forward ":")))) - ;; The first following code counts - ;; if it is before the line we want to indent. - (and (< (point) indent-point) - (- - (if (> colon-line-end (point)) - (- (current-indentation) c-label-offset) - (current-column)) - ;; If prev stmt starts with open-brace, that - ;; open brace was offset by c-brace-offset. - ;; Compensate to get the column where - ;; an ordinary statement would start. - (if (= (following-char) ?\{) c-brace-offset 0))))) - ;; If no previous statement, - ;; indent it relative to line brace is on. - ;; For open brace in column zero, don't let statement - ;; start there too. If c-indent-level is zero, - ;; use c-brace-offset + c-continued-statement-offset instead. - ;; For open-braces not the first thing in a line, - ;; add in c-brace-imaginary-offset. - (+ (if (and (bolp) (zerop c-indent-level)) - (+ c-brace-offset c-continued-statement-offset) - c-indent-level) - ;; Move back over whitespace before the openbrace. - ;; If openbrace is not first nonwhite thing on the line, - ;; add the c-brace-imaginary-offset. - (progn (skip-chars-backward " \t") - (if (bolp) 0 c-brace-imaginary-offset)) - ;; If the openbrace is preceded by a parenthesized exp, - ;; move to the beginning of that; - ;; possibly a different line - (progn - (if (eq (preceding-char) ?\)) - (forward-sexp -1)) - ;; Get initial indentation of the line we are on. - (current-indentation)))))))))) - -(defun calculate-c-indent-within-comment (&optional after-star) - "Return the indentation amount for line inside a block comment. -Optional arg AFTER-STAR means, if lines in the comment have a leading star, -return the indentation of the text that would follow this star." - (let (end star-start) - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (setq star-start (= (following-char) ?\*)) - (skip-chars-backward " \t\n") - (setq end (point)) - (beginning-of-line) - (skip-chars-forward " \t") - (if after-star - (and (looking-at "\\*") - (re-search-forward "\\*[ \t]*"))) - (and (re-search-forward "/\\*[ \t]*" end t) - star-start - (not after-star) - (goto-char (1+ (match-beginning 0)))) - (if (and (looking-at "[ \t]*$") (= (preceding-char) ?\*)) - (1+ (current-column)) - (current-column))))) - - -(defun c-backward-to-noncomment (lim) - (let (opoint stop) - (while (not stop) - (skip-chars-backward " \t\n\f" lim) - (setq opoint (point)) - (if (and (>= (point) (+ 2 lim)) - (save-excursion - (forward-char -2) - (looking-at "\\*/"))) - (search-backward "/*" lim 'move) - (setq stop (or (<= (point) lim) - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (not (looking-at "#"))))) - (or stop (beginning-of-line)))))) - -(defun c-backward-to-start-of-continued-exp (lim) - (if (memq (preceding-char) '(?\) ?\")) - (forward-sexp -1)) - (beginning-of-line) - (if (<= (point) lim) - (goto-char (1+ lim))) - (skip-chars-forward " \t")) - -(defun c-backward-to-start-of-if (&optional limit) - "Move to the start of the last \"unbalanced\" `if'." - (or limit (setq limit (save-excursion (beginning-of-defun) (point)))) - (let ((if-level 1) - (case-fold-search nil)) - (while (and (not (bobp)) (not (zerop if-level))) - (backward-sexp 1) - (cond ((looking-at "else\\b") - (setq if-level (1+ if-level))) - ((looking-at "if\\b") - (setq if-level (1- if-level))) - ((< (point) limit) - (setq if-level 0) - (goto-char limit)))))) - -(defun c-backward-to-start-of-do (&optional limit) - "If point follows a `do' statement, move to beginning of it and return t. -Otherwise return nil and don't move point." - (or limit (setq limit (save-excursion (beginning-of-defun) (point)))) - (let ((first t) - (startpos (point)) - (done nil)) - (while (not done) - (let ((next-start (point))) - (condition-case nil - ;; Move back one token or one brace or paren group. - (backward-sexp 1) - ;; If we find an open-brace, we lose. - (error (setq done 'fail))) - (if done - nil - ;; If we reached a `do', we win. - (if (looking-at "do\\b") - (setq done 'succeed) - ;; Otherwise, if we skipped a semicolon, we lose. - ;; (Exception: we can skip one semicolon before getting - ;; to a the last token of the statement, unless that token - ;; is a close brace.) - (if (save-excursion - (forward-sexp 1) - (or (and (not first) (= (preceding-char) ?})) - (search-forward ";" next-start t - (if (and first - (/= (preceding-char) ?})) - 2 1)))) - (setq done 'fail) - (setq first nil) - ;; If we go too far back in the buffer, we lose. - (if (< (point) limit) - (setq done 'fail))))))) - (if (eq done 'succeed) - t - (goto-char startpos) - nil))) - -(defun c-beginning-of-statement (count) - "Go to the beginning of the innermost C statement. -With prefix arg, go back N - 1 statements. If already at the beginning of a -statement then go to the beginning of the preceding one. -If within a string or comment, or next to a comment (only whitespace between), -move by sentences instead of statements." - (interactive "p") - (let ((here (point)) state) - (save-excursion - (beginning-of-defun) - (setq state (parse-partial-sexp (point) here nil nil))) - (if (or (nth 3 state) (nth 4 state) - (looking-at (concat "[ \t]*" comment-start-skip)) - (save-excursion (skip-chars-backward " \t") - (goto-char (- (point) 2)) - (looking-at "\\*/"))) - (forward-sentence (- count)) - (while (> count 0) - (c-beginning-of-statement-1) - (setq count (1- count))) - (while (< count 0) - (c-end-of-statement-1) - (setq count (1+ count)))))) - -(defun c-end-of-statement (count) - "Go to the end of the innermost C statement. -With prefix arg, go forward N - 1 statements. -Move forward to end of the next statement if already at end. -If within a string or comment, move by sentences instead of statements." - (interactive "p") - (c-beginning-of-statement (- count))) - -(defun c-beginning-of-statement-1 () - (let ((last-begin (point)) - (first t)) - (condition-case () - (progn - (while (and (not (bobp)) - (progn - (backward-sexp 1) - (or first - (not (re-search-forward "[;{}]" last-begin t))))) - (setq last-begin (point) first nil)) - (goto-char last-begin)) - (error (if first (backward-up-list 1) (goto-char last-begin)))))) - -(defun c-end-of-statement-1 () - (condition-case () - (progn - (while (and (not (eobp)) - (let ((beg (point))) - (forward-sexp 1) - (let ((end (point))) - (save-excursion - (goto-char beg) - (not (re-search-forward "[;{}]" end t))))))) - (re-search-backward "[;}]") - (forward-char 1)) - (error - (let ((beg (point))) - (backward-up-list -1) - (let ((end (point))) - (goto-char beg) - (search-forward ";" end 'move)))))) - -(defun mark-c-function () - "Put mark at end of C function, point at beginning." - (interactive) - (push-mark (point)) - (end-of-defun) - (push-mark (point) nil t) - (beginning-of-defun) - (backward-paragraph)) - -;; Idea of ENDPOS is, indent each line, stopping when -;; ENDPOS is encountered. But it's too much of a pain to make that work. -(defun indent-c-exp (&optional endpos) - "Indent each line of the C grouping following point." - (interactive) - (let* ((indent-stack (list nil)) - (opoint (point)) ;; May be altered below. - (contain-stack - (list (if endpos - (let (funbeg) - ;; Find previous fcn-start. - (save-excursion (forward-char 1) - (beginning-of-defun) - (setq funbeg (point))) - (setq opoint funbeg) - ;; Try to find containing open, - ;; but don't scan past that fcn-start. - (save-restriction - (narrow-to-region funbeg (point)) - (condition-case nil - (save-excursion - (backward-up-list 1) - (point)) - ;; We gave up: must be between fcns. - ;; Set opoint to beg of prev fcn - ;; since otherwise calculate-c-indent - ;; will get wrong answers. - (error (setq opoint funbeg) - (point))))) - (point)))) - (case-fold-search nil) - restart outer-loop-done inner-loop-done state ostate - this-indent last-sexp - at-else at-brace at-while - last-depth this-point - (next-depth 0)) - ;; If the braces don't match, get an error right away. - (save-excursion - (forward-sexp 1)) - ;; Realign the comment on the first line, even though we don't reindent it. - (save-excursion - (let ((beg (point))) - (and (re-search-forward - comment-start-skip - (save-excursion (end-of-line) (point)) t) - ;; Make sure this isn't a comment alone on a line - ;; (which should be indented like code instead). - (save-excursion - (goto-char (match-beginning 0)) - (skip-chars-backward " \t") - (not (bolp))) - ;; Make sure the comment starter we found - ;; is not actually in a string or quoted. - (let ((new-state - (parse-partial-sexp beg (point) - nil nil state))) - (and (not (nth 3 new-state)) (not (nth 5 new-state)))) - (progn (indent-for-comment) (beginning-of-line))))) - (save-excursion - (setq outer-loop-done nil) - (while (and (not (eobp)) - (if endpos (< (point) endpos) - (not outer-loop-done))) - (setq last-depth next-depth) - ;; Compute how depth changes over this line - ;; plus enough other lines to get to one that - ;; does not end inside a comment or string. - ;; Meanwhile, do appropriate indentation on comment lines. - (setq inner-loop-done nil) - (while (and (not inner-loop-done) - (not (and (eobp) (setq outer-loop-done t)))) - (setq ostate state) - (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) - nil nil state)) - (setq next-depth (car state)) - (if (and (car (cdr (cdr state))) - (>= (car (cdr (cdr state))) 0)) - (setq last-sexp (car (cdr (cdr state))))) - ;; If this line started within a comment, indent it as such. - (if (or (nth 4 ostate) (nth 7 ostate)) - (c-indent-line)) - ;; If it ends outside of comments or strings, exit the inner loop. - ;; Otherwise move on to next line. - (if (or (nth 3 state) (nth 4 state) (nth 7 state)) - (forward-line 1) - (setq inner-loop-done t))) - (and endpos - (while (< next-depth 0) - (setq indent-stack (append indent-stack (list nil))) - (setq contain-stack (append contain-stack (list nil))) - (setq next-depth (1+ next-depth)) - (setq last-depth (1+ last-depth)) - (setcar (nthcdr 6 state) (1+ (nth 6 state))))) - (setq outer-loop-done (and (not endpos) (<= next-depth 0))) - (if outer-loop-done - nil - ;; If this line had ..))) (((.. in it, pop out of the levels - ;; that ended anywhere in this line, even if the final depth - ;; doesn't indicate that they ended. - (while (> last-depth (nth 6 state)) - (setq indent-stack (cdr indent-stack) - contain-stack (cdr contain-stack) - last-depth (1- last-depth))) - (if (/= last-depth next-depth) - (setq last-sexp nil)) - ;; Add levels for any parens that were started in this line. - (while (< last-depth next-depth) - (setq indent-stack (cons nil indent-stack) - contain-stack (cons nil contain-stack) - last-depth (1+ last-depth))) - (if (null (car contain-stack)) - (setcar contain-stack (or (car (cdr state)) - (save-excursion (forward-sexp -1) - (point))))) - (forward-line 1) - (skip-chars-forward " \t") - ;; Don't really reindent if the line is just whitespace, - ;; or if it is past the endpos. - ;; (The exit test in the outer while - ;; does not exit until we have passed the first line - ;; past the region.) - (if (or (eolp) (and endpos (>= (point) endpos))) - nil - (if (and (car indent-stack) - (>= (car indent-stack) 0)) - ;; Line is on an existing nesting level. - ;; Lines inside parens are handled specially. - (if (/= (char-after (car contain-stack)) ?{) - (setq this-indent (car indent-stack)) - ;; Line is at statement level. - ;; Is it a new statement? Is it an else? - ;; Find last non-comment character before this line - (save-excursion - (setq this-point (point)) - (setq at-else (looking-at "else\\W")) - (setq at-brace (= (following-char) ?{)) - (setq at-while (looking-at "while\\b")) - (if (= (following-char) ?}) - (setq this-indent (car indent-stack)) - (c-backward-to-noncomment opoint) - (if (not (memq (preceding-char) '(0 ?\, ?\; ?} ?: ?{))) - ;; Preceding line did not end in comma or semi; - ;; indent this line c-continued-statement-offset - ;; more than previous. - (progn - (c-backward-to-start-of-continued-exp (car contain-stack)) - (setq this-indent - (+ c-continued-statement-offset (current-column) - (if at-brace c-continued-brace-offset 0)))) - ;; Preceding line ended in comma or semi; - ;; use the standard indent for this level. - (cond (at-else (progn (c-backward-to-start-of-if opoint) - (setq this-indent - (current-indentation)))) - ((and at-while (c-backward-to-start-of-do opoint)) - (setq this-indent (current-indentation))) - ((eq (preceding-char) ?\,) - (goto-char this-point) - (setq this-indent (calculate-c-indent))) - (t (setq this-indent (car indent-stack)))))))) - ;; Just started a new nesting level. - ;; Compute the standard indent for this level. - (let ((val (calculate-c-indent - (if (car indent-stack) - (- (car indent-stack)) - opoint)))) - ;; t means we are in a block comment and should - ;; calculate accordingly. - (if (eq val t) - (setq val (calculate-c-indent-within-comment))) - (setcar indent-stack - (setq this-indent val)))) - ;; Adjust line indentation according to its contents - (if (or (looking-at c-switch-label-regexp) - (and (looking-at "[A-Za-z]") - (save-excursion - (forward-sexp 1) - (looking-at ":")))) - (setq this-indent (max 1 (+ this-indent c-label-offset)))) - (if (= (following-char) ?}) - (setq this-indent (- this-indent c-indent-level))) - (if (= (following-char) ?{) - ;; Don't move an open-brace in column 0. - ;; This is good when constructs such as - ;; `extern "C" {' surround a function definition - ;; that should be indented as usual. - ;; It is also good for nested functions. - ;; It is bad when an open-brace is indented at column 0 - ;; and you want to fix that, but we can't win 'em all. - (if (zerop (current-column)) - (setq this-indent 0) - (setq this-indent (+ this-indent c-brace-offset)))) - ;; Don't leave indentation in empty lines. - (if (eolp) (setq this-indent 0)) - ;; Put chosen indentation into effect. - (or (= (current-column) this-indent) - (= (following-char) ?\#) - (progn - (delete-region (point) (progn (beginning-of-line) (point))) - (indent-to this-indent))) - ;; Indent any comment following the text. - (or (looking-at comment-start-skip) - (let ((beg (point))) - (and (re-search-forward - comment-start-skip - (save-excursion (end-of-line) (point)) t) - ;; Make sure the comment starter we found - ;; is not actually in a string or quoted. - (let ((new-state - (parse-partial-sexp beg (point) - nil nil state))) - (and (not (nth 3 new-state)) (not (nth 5 new-state)))) - (progn (indent-for-comment) (beginning-of-line))))))))))) - -;; Look at all comment-start strings in the current line after point. -;; Return t if one of them starts a real comment. -;; This is not used yet, because indent-for-comment -;; isn't smart enough to handle the cases this can find. -(defun indent-c-find-real-comment () - (let (win) - (while (and (not win) - (re-search-forward comment-start-skip - (save-excursion (end-of-line) (point)) - t)) - ;; Make sure the comment start is not quoted. - (let ((state-1 - (parse-partial-sexp - (save-excursion (beginning-of-line) (point)) - (point) nil nil state))) - (setq win (and (null (nth 3 state-1)) (null (nth 5 state-1)))))) - win)) - -;; Indent every line whose first char is between START and END inclusive. -(defun c-indent-region (start end) - (save-excursion - (goto-char start) - ;; Advance to first nonblank line. - (skip-chars-forward " \t\n") - (beginning-of-line) - (let ((endmark (copy-marker end)) - (c-tab-always-indent t)) - (while (and (bolp) (not (eobp)) (< (point) endmark)) - ;; Indent one line as with TAB. - (let ((shift-amt (c-indent-line)) - nextline sexpbeg sexpend) - (if (save-excursion (beginning-of-line) (looking-at "[ \t]*#")) - (forward-line 1) - (save-excursion - ;; Find beginning of following line. - (save-excursion - (forward-line 1) (setq nextline (point))) - ;; Find first beginning-of-sexp for sexp extending past this line. - (beginning-of-line) - (while (< (point) nextline) - (condition-case nil - (progn - (forward-sexp 1) - (setq sexpend (point-marker))) - (error (setq sexpend nil) - (goto-char nextline))) - (skip-chars-forward " \t\n")) - (if sexpend - (progn - ;; Make sure the sexp we found really starts on the - ;; current line and extends past it. - (goto-char sexpend) - (backward-sexp 1) - (setq sexpbeg (point))))) - ;; If that sexp ends within the region, - ;; indent it all at once, fast. - (if (and sexpend (> sexpend nextline) (<= sexpend endmark) - (< sexpbeg nextline)) - (progn - (indent-c-exp) - (goto-char sexpend))) - ;; Move to following line and try again. - (and sexpend (set-marker sexpend nil)) - (forward-line 1)))) - (set-marker endmark nil)))) - -(defun set-c-style (style &optional global) - "Set C-mode variables to use one of several different indentation styles. -The arguments are a string representing the desired style -and a flag which, if non-nil, means to set the style globally. -\(Interactively, the flag comes from the prefix argument.) -Available styles are GNU, K&R, BSD and Whitesmith." - (interactive (list (completing-read "Use which C indentation style? " - c-style-alist nil t) - current-prefix-arg)) - (let ((vars (cdr (assoc style c-style-alist)))) - (or vars - (error "Invalid C indentation style `%s'" style)) - (while vars - (or global - (make-local-variable (car (car vars)))) - (set (car (car vars)) (cdr (car vars))) - (setq vars (cdr vars))))) - -;;; This page handles insertion and removal of backslashes for C macros. - -(defvar c-backslash-column 48 - "*Minimum column for end-of-line backslashes of macro definitions.") - -(defun c-backslash-region (from to delete-flag) - "Insert, align, or delete end-of-line backslashes on the lines in the region. -With no argument, inserts backslashes and aligns existing backslashes. -With an argument, deletes the backslashes. - -This function does not modify the last line of the region if the region ends -right at the start of the following line; it does not modify blank lines -at the start of the region. So you can put the region around an entire macro -definition and conveniently use this command." - (interactive "r\nP") - (save-excursion - (goto-char from) - (let ((column c-backslash-column) - (endmark (make-marker))) - (move-marker endmark to) - ;; Compute the smallest column number past the ends of all the lines. - (if (not delete-flag) - (while (< (point) to) - (end-of-line) - (if (= (preceding-char) ?\\) - (progn (forward-char -1) - (skip-chars-backward " \t"))) - (setq column (max column (1+ (current-column)))) - (forward-line 1))) - ;; Adjust upward to a tab column, if that doesn't push past the margin. - (if (> (% column tab-width) 0) - (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width))) - (if (< adjusted (window-width)) - (setq column adjusted)))) - ;; Don't modify blank lines at start of region. - (goto-char from) - (while (and (< (point) endmark) (eolp)) - (forward-line 1)) - ;; Add or remove backslashes on all the lines. - (while (and (< (point) endmark) - ;; Don't backslashify the last line - ;; if the region ends right at the start of the next line. - (save-excursion - (forward-line 1) - (< (point) endmark))) - (if (not delete-flag) - (c-append-backslash column) - (c-delete-backslash)) - (forward-line 1)) - (move-marker endmark nil)))) - -(defun c-append-backslash (column) - (end-of-line) - ;; Note that "\\\\" is needed to get one backslash. - (if (= (preceding-char) ?\\) - (progn (forward-char -1) - (delete-horizontal-space) - (indent-to column)) - (indent-to column) - (insert "\\"))) - -(defun c-delete-backslash () - (end-of-line) - (or (bolp) - (progn - (forward-char -1) - (if (looking-at "\\\\") - (delete-region (1+ (point)) - (progn (skip-chars-backward " \t") (point))))))) - -(defun c-up-conditional (count) - "Move back to the containing preprocessor conditional, leaving mark behind. -A prefix argument acts as a repeat count. With a negative argument, -move forward to the end of the containing preprocessor conditional. -When going backwards, `#elif' is treated like `#else' followed by `#if'. -When going forwards, `#elif' is ignored." - (interactive "p") - (c-forward-conditional (- count) t)) - -(defun c-backward-conditional (count &optional up-flag) - "Move back across a preprocessor conditional, leaving mark behind. -A prefix argument acts as a repeat count. With a negative argument, -move forward across a preprocessor conditional." - (interactive "p") - (c-forward-conditional (- count) up-flag)) - -(defun c-forward-conditional (count &optional up-flag) - "Move forward across a preprocessor conditional, leaving mark behind. -A prefix argument acts as a repeat count. With a negative argument, -move backward across a preprocessor conditional." - (interactive "p") - (let* ((forward (> count 0)) - (increment (if forward -1 1)) - (search-function (if forward 're-search-forward 're-search-backward)) - (opoint (point)) - (new)) - (save-excursion - (while (/= count 0) - (let ((depth (if up-flag 0 -1)) found) - (save-excursion - ;; Find the "next" significant line in the proper direction. - (while (and (not found) - ;; Rather than searching for a # sign that comes - ;; at the beginning of a line aside from whitespace, - ;; search first for a string starting with # sign. - ;; Then verify what precedes it. - ;; This is faster on account of the fastmap feature of - ;; the regexp matcher. - (funcall search-function - "#[ \t]*\\(if\\|elif\\|endif\\)" - nil t)) - (beginning-of-line) - ;; Now verify it is really a preproc line. - (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\)") - (let ((prev depth)) - ;; Update depth according to what we found. - (beginning-of-line) - (cond ((looking-at "[ \t]*#[ \t]*endif") - (setq depth (+ depth increment))) - ((looking-at "[ \t]*#[ \t]*elif") - (if (and forward (= depth 0)) - (setq found (point)))) - (t (setq depth (- depth increment)))) - ;; If we are trying to move across, and we find - ;; an end before we find a beginning, get an error. - (if (and (< prev 0) (< depth prev)) - (error (if forward - "No following conditional at this level" - "No previous conditional at this level"))) - ;; When searching forward, start from next line - ;; so that we don't find the same line again. - (if forward (forward-line 1)) - ;; If this line exits a level of conditional, exit inner loop. - (if (< depth 0) - (setq found (point))))))) - (or found - (error "No containing preprocessor conditional")) - (goto-char (setq new found))) - (setq count (+ count increment)))) - (push-mark) - (goto-char new))) - -;;; c-mode.el ends here diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el deleted file mode 100644 index e82940d2d44..00000000000 --- a/lisp/progmodes/cmacexp.el +++ /dev/null @@ -1,443 +0,0 @@ -;;; cmacexp.el --- expand C macros in a region - -;; Copyright (C) 1992 Free Software Foundation, Inc. - -;; Author: Francesco Potorti` <pot@cnuce.cnr.it> -;; Version: $Id: cmacexp.el,v 1.9 1994/02/07 05:40:46 rms Exp rms $ -;; Adapted-By: ESR -;; Keywords: c - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; In C mode C-M-x is bound to c-macro-expand. The result of the -;; expansion is put in a separate buffer. A user option -;; allows the window displaying the buffer to be optimally sized. -;; -;; When called with a C-u prefix, c-macro-expand replaces the selected -;; region with the expansion. With two C-u's the user is offered to -;; change the flags to the preprocessor (while the results of the -;; expansion go to a separate buffer). Preprocessor arguments default -;; to the last ones entered. Both the preprocessor name and the -;; initial flag defaults can be set by the user. Setting -;; c-macro-always-prompt to a non-nil value allows one to be always -;; prompted for the flags, regardless of the prefix used. - -;; A c-macro-expansion function is provided for non-interactive use. -;; A still experimental function c-macro-eval is provided. It aims at -;; evaluating the contents of a region by using calc (by Dave -;; Gillespie). Select a region and type C-x C-e (if you followed the -;; suggestions in the INSTALLATION section) or type M-x c-ma RET v -;; RET. If you have calc installed, the computed value of the -;; expression will appear in the message area. If you give an -;; interactive C-u prefix the computed value will be shown in signed, -;; unsigned, hex and boolean representations. Two C-u's allow to -;; change the preprocessor flags via prompt. c-macro-eval works well -;; for constant expressions, but see the BUG section. - -;; A patch to calc 2.02 has been written by Dave Gillespie. It can -;; be downloaded via anonymous ftp at fly.cnuce.cnr.it:pub/calc.diff. - -;; INSTALLATION ====================================================== - -;; Put this file on your load-path, byte compile it for increased -;; speed and put part or all of the following in your ~/.emacs file. - -;; To make a directory ~/emacs be in front of your load-path: -;;(setq load-path (cons (expand-file-name "~/emacs") load-path)) -;; -;; Suggested keybindings (work only in c-mode): -;;(define-key c-mode-map "\C-\M-x" 'c-macro-expand) -;;(define-key c-mode-map "\C-x\C-e" 'c-macro-eval) -;; -;; If you want the *Macroexpansion* window to be not higher than -;; necessary: -;;(setq c-macro-shrink-window-p t) -;; -;; If you use a preprocessor other than /lib/cpp (be careful to set a -;; -C option or equivalent in order to make the preprocessor not to -;; strip the comments): -;;(setq c-macro-preprocessor "gpp -C") -;; -;; If you often use a particular set of flags, and want them to be -;; the default: -;;(setq c-macro-default-cppflags "-I /usr/include/local -DDEBUG" -;; -;; If you always want the "Preprocessor arguments: " prompt, -;; regardless of the arguments provided: -;;(setq c-macro-always-prompt-p t) -;; -;; If you want to experiment with the C constant expressions -;; evaluation feature: -;;(autoload 'c-macro-eval "cmacexp" -;; "C constant expressions evaluation. Requires calc. Experimental." t) - -;; BUG REPORTS ======================================================= - -;; Please report bugs, suggestions, complaints and so on to -;; pot@cnuce.cnr.it (Francesco Potorti`). - -;; IMPROVEMENTS OVER emacs 18.xx cmacexp.el ========================== - -;; - A lot of user visible changes. See above. -;; - #line directives are inserted, so __LINE__ and __FILE__ are -;; correctly expanded. Works even with START inside a string, a -;; comment or a region #ifdef'd away by cpp. cpp is invoked with -C, -;; making comments visible in the expansion. -;; - All work is done in core memory, no need for temporary files. -;; - The /lib/cpp process is run synchronously. This fixes an -;; infinite loop bug on Motorola Delta (cpp waiting forever for -;; end-of-file, don't know why). Fixes a similar intermittent -;; problem on SunOS 4.1. - -;; ACKNOWLEDGEMENTS ================================================== - -;; A lot of thanks to Don Maszle who did a great work of testing, bug -;; reporting and suggestion of new features and to Dave Gillespie for -;; his suggestions about calc. This work has been partially inspired by -;; Don Maszle and Jonathan Segal's. - -;; BUGS ============================================================== - -;; calc 2.02 does not handle the C operators "->", ".", "*" (as a -;; prefix), the composite assignement operators "+=" etc. It cannot -;; handle the "," operator and will be confused by ";". Almost all -;; these can be defined as no-ops using the Calc's Syntax Tables -;; feature. The built-in calc functions will cause problems in -;; certain circumstances. c-macro-eval behaves correctly only on -;; expressions not containing such operators. Does not distinguish -;; among integer and real division. - -;; If the start point of the region is inside a macro definition the -;; macro expansion is often inaccurate. - -;;; Code: - -(defvar c-macro-shrink-window-p nil - "*Non-nil means shrink the *Macroexpansion* window to fit its contents.") - -(defvar c-macro-always-prompt-p nil - "*Non-nil means always prompt for preprocessor arguments.") - -(defvar c-macro-preprocessor "/lib/cpp -C" "\ -The preprocessor used by the cmacexp package. - -If you change this, be sure to preserve the -C (don't strip comments) -option, or to set an equivalent one.") - -(defvar c-macro-default-cppflags "" - "Default cpp flags used by c-macro-expand.") - -(defconst c-macro-buffer-name "*Macroexpansion*") - -(defun c-macro-expand (start end &optional flag) "\ -Expand all C macros occurring in the region using c-macro-preprocessor. -Normally display output in temp buffer. -Prefix arg means replace the region with it. -Prompt for a string of arguments to the preprocessor, (e.g. --DDEBUG -I ./include) when prefixed with two C-u's. - -It is intended for interactive use only. -For non interactive use, see the c-macro-expansion function." - - (interactive "r\nP") - (let* ((subst (and flag (not (equal flag '(16))))) - (inbuf (current-buffer)) - (displaybuf (if subst - (get-buffer c-macro-buffer-name) - (get-buffer-create c-macro-buffer-name))) - (expansion "")) - ;; Build the command string. - (if (or c-macro-always-prompt-p (equal flag '(16))) - (setq c-macro-default-cppflags - (read-string "Preprocessor arguments: " - c-macro-default-cppflags))) - ;; Decide where to display output. - (if (and subst - (and buffer-read-only (not inhibit-read-only)) - (not (eq inbuf displaybuf))) - (progn - (message - "Buffer is read only: displaying expansion in alternate window") - (sit-for 2) - (setq subst nil) - (or displaybuf - (setq displaybuf (get-buffer-create c-macro-buffer-name))))) - ;; Expand the macro and output it. - (if (interactive-p) (message (c-macro-default-message))) - (setq expansion - (c-macro-expansion start end - (concat c-macro-preprocessor " " - c-macro-default-cppflags))) - (message (concat (c-macro-default-message) "done")) - (if subst - (let ((exchange (= (point) start))) - (delete-region start end) - (insert expansion) - (if exchange - (exchange-point-and-mark))) - (set-buffer displaybuf) - (setq buffer-read-only nil) - (buffer-flush-undo displaybuf) - (erase-buffer) - (insert expansion) - (set-buffer-modified-p nil) - (if (string= "" expansion) - (message "Null expansion") - (c-macro-display-buffer inbuf)) - (setq buffer-read-only t) - (bury-buffer displaybuf)))) - - -;; Display the current buffer in a window which is either just large -;; enough to contain the entire buffer, or half the size of the -;; screen, whichever is smaller. Put the current buffer in view-mode -;; if the Inge Frick's view-mode is installed, with buffer to return -;; to set to RETBUF (if sensible). Do not select the new window. -;; -;; Several factors influence window resizing so that the window is -;; sized optimally if it is created anew, and so that it is messed -;; with minimally if it has been created by the user. If the window -;; chosen for display exists already but contains something else, the -;; window is not re-sized. If the window already contains the current -;; buffer, it is never shrunk, but possibly expanded. Finally, if the -;; variable c-macro-shrink-window-p is nil the window size is *never* -;; changed. -(defun c-macro-display-buffer (retbuf) - - (goto-char (point-min)) - (c-mode) - (let ((oldwinheight (window-height)) - (alreadythere ;the window was already there - (get-buffer-window (current-buffer))) - (popped nil)) ;the window popped changing the layout - (or alreadythere - (progn - (display-buffer (current-buffer) t) - (setq popped (/= oldwinheight (window-height))))) - (if (and c-macro-shrink-window-p ;user wants fancy shrinking :\) - (or alreadythere popped)) - ;; Enlarge up to half screen, or shrink properly. - (let ((oldwin (selected-window)) - (minheight 0) - (maxheight 0)) - (save-excursion - (select-window (get-buffer-window (current-buffer))) - (setq minheight (if alreadythere - (window-height) - window-min-height)) - (setq maxheight (/ (screen-height) 2)) - (enlarge-window (- (min maxheight - (max minheight - (+ 2 (vertical-motion 1000000)))) - (window-height))) - (goto-char (point-min)) - (select-window oldwin)))))) - - -(defun c-macro-expansion (start end cppcommand) "\ -Expands the region between START and END in the current buffer using -the shell command CPPCOMMAND (e.g. \"/lib/cpp -C -DDEBUG\"). Be sure -to use a -C (don't strip comments) or equivalent option. -Returns the output as a string." - -;; Copy the current buffer's contents to a temporary hidden buffer. -;; Delete from END to end of buffer. Insert a preprocessor #line -;; directive at START and after each #endif following START that are -;; not inside a comment or a string. Put all the strings thus -;; inserted (without the "line" substring) in a list named linelist. -;; If START is inside a comment, prepend "*/" and append "/*" to the -;; #line directive. If inside a string, prepend and append "\"". -;; Preprocess the buffer contents, then look for all the lines stored -;; in linelist starting from end of buffer. The last line so found is -;; where START was, so return the substring from point to end of -;; buffer. - (let ((inbuf (current-buffer)) - (outbuf (get-buffer-create " *C Macro Expansion*")) - (filename (if (and buffer-file-name - (string-match (regexp-quote default-directory) - buffer-file-name)) - (substring buffer-file-name (match-end 0)) - (buffer-name))) - (start-state) - (linenum 0) - (linelist ())) - (unwind-protect - (save-excursion - (save-restriction - (widen) - (set-buffer outbuf) - (setq buffer-read-only nil) - (erase-buffer) - (set-syntax-table c-mode-syntax-table) - (insert-buffer-substring inbuf 1 end)) - - ;; We have copied inbuf to outbuf. Point is at end of - ;; outbuf. Insert a space at the end, so cpp can correctly - ;; parse a token ending at END. - - (insert " ") - - (save-excursion - (goto-char start) - (setq start-state (parse-partial-sexp 1 (point)))) - ;; Now we insert the #line directives after all #endif or - ;; #else following START. - ;(switch-to-buffer outbuf) (debug) ;debugging instructions - (while (re-search-backward "\n#\\(endif\\|else\\)\\>" start 'move) - (if (equal (nthcdr 3 (parse-partial-sexp start (point) start-state)) - '(nil nil nil 0)) ;neither in string nor in - ;comment nor after quote - (progn - (goto-char (match-end 0)) -;; (setq linenum (count-lines 1 (point))) - (setq linelist - ;; This used to be a #line command - ;; but it's not guaranteed that the output - ;; will have properly matching commands. - ;; Only the *line numbers* have to agree! - (cons (format "\n???!!!???!!!!\n") - linelist)) - (insert (car linelist)) - (skip-chars-backward "^#") - (insert "line") - (goto-char (match-beginning 0))))) - - ;; We are at START. Insert the first #line directive. This - ;; must work even inside a string or comment, or after a - ;; quote. -;;; (setq linenum (+ (count-lines 1 (point)) -;;; (if (bolp) 1 0))) - (setq linelist - (cons - (let* ((startstat (parse-partial-sexp 1 start)) - (startinstring (nth 3 startstat)) - (startincomment (nth 4 startstat)) - (startafterquote (nth 5 startstat))) - (concat (if startafterquote " ") - (cond (startinstring "\"") (startincomment "*/")) - (format "\n???!!!???!!!!") - (cond (startinstring "\"") (startincomment "/*")) - (if startafterquote "\\"))) - linelist)) - (insert (car linelist)) - (skip-chars-backward "^#") - (insert "line") - - ;; Call the preprocessor. - (call-process-region 1 (point-max) "sh" t t nil "-c" - (concat cppcommand " 2>/dev/null")) - - (while (search-backward "\n???!!!???!!!!" nil t) - (replace-match "")) - - ;; Compute the return value, keeping in account the space - ;; inserted at the end of the buffer. - (buffer-substring (point) (max (point) (- (point-max) 1)))) - - ;; Cleanup. - (kill-buffer outbuf)))) - - -;; Experimental. With an argument, print signed, unsigned, hex and -;; boolean representations. -(defun c-macro-eval (start end &optional flag) "\ -Expand region using cpp and evaluate it using calc. -Interactively print value in minibuffer and push it on the kill ring. -With a C-u argument shows the evaluation in a variety of formats. -With two C-u's prompts the user for a string of flags to the preprocessor. - -Non interactively returns value of region between START and END -as a string. Several formats are used if optional FLAG is non-nil." - - (interactive "r\nP") - (or (fboundp 'calc-eval) - (require 'calc)) - (if (or c-macro-always-prompt-p (equal flag '(16))) - (setq c-macro-default-cppflags - (read-string "Preprocessor arguments: " - c-macro-default-cppflags))) - - ;; Expand the region. - (if (interactive-p) (message (c-macro-default-message))) - (let ((evaluation - (c-macro-expansion start end - (concat c-macro-preprocessor " " - c-macro-default-cppflags))) - (evalbuf (get-buffer-create " *Macro Evaluation*"))) - (unwind-protect - (save-excursion - (set-buffer evalbuf) - (setq buffer-read-only nil) - (erase-buffer) - (insert evaluation) - - ;; Evaluate expression(s). - (if (interactive-p) - (message "Invoking calc...")) - (setq evaluation - (let ((calc-eval-error t)) - (calc-eval (list (buffer-string) 'calc-language 'c)))) - (erase-buffer) - (cond - (flag - (insert (calc-eval (list evaluation - 'calc-language 'c - 'calc-simplify-mode 'binary)) - "(u)" " == " - (calc-eval (list evaluation - 'calc-language 'c - 'calc-word-size (- calc-word-size) - 'calc-simplify-mode 'binary)) - "(d)" " == " - (calc-eval (list evaluation - 'calc-language 'c - 'calc-number-radix 16 - 'calc-simplify-mode 'binary)) - "(x)") - (save-excursion - (insert " == " (calc-eval (list evaluation - 'calc-language 'c - 'calc-number-radix 16 - 'calc-simplify-mode 'binary)))) - (while (re-search-forward "0x\\([^,]+\\)\\(, \\|\\'\\)" nil t) - (if (string= "0" - (buffer-substring (match-beginning 1) - (match-end 1))) - (replace-match "FALSE\\2") - (replace-match "TRUE\\2")))) - (t - (insert evaluation))) - - ;; Output the evaluation. - (if (interactive-p) - (progn - (copy-region-as-kill 1 (point-max)) - (message (buffer-string))) - (buffer-string))) - (kill-buffer evalbuf)))) - -(defun c-macro-default-message () - (format "Invoking %s%s%s on region..." - c-macro-preprocessor - (if (string= "" c-macro-default-cppflags) "" " ") - c-macro-default-cppflags)) - -(provide 'cmacexp) - -;;; cmacexp.el ends here. diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el deleted file mode 100644 index 813412942d1..00000000000 --- a/lisp/progmodes/compile.el +++ /dev/null @@ -1,1307 +0,0 @@ -;;; compile.el --- run compiler as inferior of Emacs, parse error messages. - -;; Copyright (C) 1985, 86, 87, 93, 94 Free Software Foundation, Inc. - -;; Author: Roland McGrath <roland@prep.ai.mit.edu> -;; Maintainer: FSF -;; Keywords: tools, processes - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; This package provides the compile and grep facilities documented in -;; the Emacs user's manual. - -;;; Code: - -;;;###autoload -(defvar compilation-mode-hook nil - "*List of hook functions run by `compilation-mode' (see `run-hooks').") - -;;;###autoload -(defconst compilation-window-height nil - "*Number of lines in a compilation window. If nil, use Emacs default.") - -(defvar compilation-error-list nil - "List of error message descriptors for visiting erring functions. -Each error descriptor is a cons (or nil). Its car is a marker pointing to -an error message. If its cdr is a marker, it points to the text of the -line the message is about. If its cdr is a cons, it is a list -\(\(DIRECTORY . FILE\) LINE [COLUMN]\). Or its cdr may be nil if that -error is not interesting. - -The value may be t instead of a list; this means that the buffer of -error messages should be reparsed the next time the list of errors is wanted. - -Some other commands (like `diff') use this list to control the error -message tracking facilites; if you change its structure, you should make -sure you also change those packages. Perhaps it is better not to change -it at all.") - -(defvar compilation-old-error-list nil - "Value of `compilation-error-list' after errors were parsed.") - -(defvar compilation-parse-errors-function 'compilation-parse-errors - "Function to call to parse error messages from a compilation. -It takes args LIMIT-SEARCH and FIND-AT-LEAST. -If LIMIT-SEARCH is non-nil, don't bother parsing past that location. -If FIND-AT-LEAST is non-nil, don't bother parsing after finding that -many new errors. -It should read in the source files which have errors and set -`compilation-error-list' to a list with an element for each error message -found. See that variable for more info.") - -;;;###autoload -(defvar compilation-buffer-name-function nil - "Function to compute the name of a compilation buffer. -The function receives one argument, the name of the major mode of the -compilation buffer. It should return a string. -nil means compute the name with `(concat \"*\" (downcase major-mode) \"*\")'.") - -;;;###autoload -(defvar compilation-finish-function nil - "*Function to call when a compilation process finishes. -It is called with two arguments: the compilation buffer, and a string -describing how the process finished.") - -(defvar compilation-last-buffer nil - "The most recent compilation buffer. -A buffer becomes most recent when its compilation is started -or when it is used with \\[next-error] or \\[compile-goto-error].") - -(defvar compilation-in-progress nil - "List of compilation processes now running.") -(or (assq 'compilation-in-progress minor-mode-alist) - (setq minor-mode-alist (cons '(compilation-in-progress " Compiling") - minor-mode-alist))) - -(defvar compilation-parsing-end nil - "Position of end of buffer when last error messages were parsed.") - -(defvar compilation-error-message "No more errors" - "Message to print when no more matches are found.") - -(defvar compilation-num-errors-found) - -(defvar compilation-error-regexp-alist - '( - ;; NOTE! This first one is repeated in grep-regexp-alist, below. - - ;; 4.3BSD grep, cc, lint pass 1: - ;; /usr/src/foo/foo.c(8): warning: w may be used before set - ;; or GNU utilities: - ;; foo.c:8: error message - ;; or HP-UX 7.0 fc: - ;; foo.f :16 some horrible error message - ;; - ;; We'll insist that the number be followed by a colon or closing - ;; paren, because otherwise this matches just about anything - ;; containing a number with spaces around it. - ("\n\\([^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)[:) \t]" 1 2) - - ;; 4.3BSD lint pass 2 - ;; strcmp: variable # of args. llib-lc(359) :: /usr/src/foo/foo.c(8) - ("[ \t:]\\([^:( \t\n]+\\)[:(](+[ \t]*\\([0-9]+\\))[:) \t]*$" 1 2) - - ;; 4.3BSD lint pass 3 - ;; bloofle defined( /users/wolfgang/foo.c(4) ), but never used - ;; This used to be - ;; ("[ \t(]+\\([^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]+" 1 2) - ;; which is regexp Impressionism - it matches almost anything! - ("([ \t]*\\([^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\))" 1 2) - - ;; Ultrix 3.0 f77: - ;; Error on line 3 of t.f: Execution error unclassifiable statement - ;; Unknown who does this: - ;; Line 45 of "foo.c": bloofel undefined - ;; Absoft FORTRAN 77 Compiler 3.1.3 - ;; error on line 19 of fplot.f: spelling error? - ;; warning on line 17 of fplot.f: data type is undefined for variable d - ("\\(\n\\|on \\)[Ll]ine[ \t]+\\([0-9]+\\)[ \t]+\ -of[ \t]+\"?\\([^\":\n]+\\)\"?:" 3 2) - - ;; Apollo cc, 4.3BSD fc: - ;; "foo.f", line 3: Error: syntax error near end of statement - ;; IBM RS6000: - ;; "vvouch.c", line 19.5: 1506-046 (S) Syntax error. - ;; Unknown compiler: - ;; File "foobar.ml", lines 5-8, characters 20-155: blah blah - ;; Microtec mcc68k: - ;; "foo.c", line 32 pos 1; (E) syntax error; unexpected symbol: "lossage" - ("\"\\([^,\" \n\t]+\\)\", lines? \\([0-9]+\\)[:., -]" 1 2) - - ;; MIPS RISC CC - the one distributed with Ultrix: - ;; ccom: Error: foo.c, line 2: syntax error - ;; DEC AXP OSF/1 cc - ;; /usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah - ("rror: \\([^,\" \n\t]+\\)[,:] \\(line \\)?\\([0-9]+\\):" 1 3) - - ;; IBM AIX PS/2 C version 1.1: - ;; ****** Error number 140 in line 8 of file errors.c ****** - ("in line \\([0-9]+\\) of file \\([^ \n]+[^. \n]\\)\\.? " 2 1) - ;; IBM AIX lint is too painful to do right this way. File name - ;; prefixes entire sections rather than being on each line. - - ;; Lucid Compiler, lcc 3.x - ;; E, file.cc(35,52) Illegal operation on pointers - ("[A-Z], \\([^(]*\\)(\\([0-9]+\\),[ \t]*\\([0-9]+\\)" 1 2 3) - - ) - "Alist that specifies how to match errors in compiler output. -Each element has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX]). -If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and -the LINE-IDX'th subexpression gives the line number. If COLUMN-IDX is -given, the COLUMN-IDX'th subexpression gives the column number on that line.") - -(defvar compilation-read-command t - "If not nil, M-x compile reads the compilation command to use. -Otherwise, M-x compile just uses the value of `compile-command'.") - -(defvar compilation-ask-about-save t - "If not nil, M-x compile asks which buffers to save before compiling. -Otherwise, it saves all modified buffers without asking.") - -(defvar grep-regexp-alist - '(("^\\([^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2)) - "Regexp used to match grep hits. See `compilation-error-regexp-alist'.") - -(defvar grep-command "grep -n " - "Last grep command used in \\{grep}; default for next grep.") - -;;;###autoload -(defvar compilation-search-path '(nil) - "*List of directories to search for source files named in error messages. -Elements should be directory names, not file names of directories. -nil as an element means to try the default directory.") - -(defvar compile-command "make -k " - "Last shell command used to do a compilation; default for next compilation. - -Sometimes it is useful for files to supply local values for this variable. -You might also use mode hooks to specify it in certain modes, like this: - - (setq c-mode-hook - '(lambda () (or (file-exists-p \"makefile\") (file-exists-p \"Makefile\") - (progn (make-local-variable 'compile-command) - (setq compile-command - (concat \"make -k \" - buffer-file-name))))))") - -(defconst compilation-enter-directory-regexp - ": Entering directory `\\(.*\\)'$" - "Regular expression matching lines that indicate a new current directory. -This must contain one \\(, \\) pair around the directory name. - -The default value matches lines printed by the `-w' option of GNU Make.") - -(defconst compilation-leave-directory-regexp - ": Leaving directory `\\(.*\\)'$" - "Regular expression matching lines that indicate restoring current directory. -This may contain one \\(, \\) pair around the name of the directory -being moved from. If it does not, the last directory entered \(by a -line matching `compilation-enter-directory-regexp'\) is assumed. - -The default value matches lines printed by the `-w' option of GNU Make.") - -(defvar compilation-directory-stack nil - "Stack of previous directories for `compilation-leave-directory-regexp'. -The head element is the directory the compilation was started in.") - -;; History of compile commands. -(defvar compile-history nil) -;; History of grep commands. -(defvar grep-history nil) - -;;;###autoload -(defun compile (command) - "Compile the program including the current buffer. Default: run `make'. -Runs COMMAND, a shell command, in a separate process asynchronously -with output going to the buffer `*compilation*'. - -You can then use the command \\[next-error] to find the next error message -and move to the source code that caused it. - -To run more than one compilation at once, start one and rename the -\`*compilation*' buffer to some other name with \\[rename-buffer]. -Then start the next one. - -The name used for the buffer is actually whatever is returned by -the function in `compilation-buffer-name-function', so you can set that -to a function that generates a unique name." - (interactive - (if compilation-read-command - (list (read-from-minibuffer "Compile command: " - compile-command nil nil - '(compile-history . 1))) - (list compile-command))) - (setq compile-command command) - (save-some-buffers (not compilation-ask-about-save) nil) - (compile-internal compile-command "No more errors")) - -;;;###autoload -(defun grep (command-args) - "Run grep, with user-specified args, and collect output in a buffer. -While grep runs asynchronously, you can use the \\[next-error] command -to find the text that grep hits refer to. - -This command uses a special history list for its arguments, so you can -easily repeat a grep command." - (interactive - (list (read-from-minibuffer "Run grep (like this): " - grep-command nil nil 'grep-history))) - (compile-internal (concat command-args " /dev/null") - "No more grep hits" "grep" - ;; Give it a simpler regexp to match. - nil grep-regexp-alist)) - -(defun compile-internal (command error-message - &optional name-of-mode parser regexp-alist - name-function) - "Run compilation command COMMAND (low level interface). -ERROR-MESSAGE is a string to print if the user asks to see another error -and there are no more errors. Third argument NAME-OF-MODE is the name -to display as the major mode in the compilation buffer. - -Fourth arg PARSER is the error parser function (nil means the default). Fifth -arg REGEXP-ALIST is the error message regexp alist to use (nil means the -default). Sixth arg NAME-FUNCTION is a function called to name the buffer (nil -means the default). The defaults for these variables are the global values of -\`compilation-parse-errors-function', `compilation-error-regexp-alist', and -\`compilation-buffer-name-function', respectively. - -Returns the compilation buffer created." - (let (outbuf) - (save-excursion - (or name-of-mode - (setq name-of-mode "Compilation")) - (setq outbuf - (get-buffer-create - (funcall (or name-function compilation-buffer-name-function - (function (lambda (mode) - (concat "*" (downcase mode) "*")))) - name-of-mode))) - (set-buffer outbuf) - (let ((comp-proc (get-buffer-process (current-buffer)))) - (if comp-proc - (if (or (not (eq (process-status comp-proc) 'run)) - (yes-or-no-p - (format "A %s process is running; kill it? " - name-of-mode))) - (condition-case () - (progn - (interrupt-process comp-proc) - (sit-for 1) - (delete-process comp-proc)) - (error nil)) - (error "Cannot have two processes in `%s' at once" - (buffer-name)) - ))) - ;; In case the compilation buffer is current, make sure we get the global - ;; values of compilation-error-regexp-alist, etc. - (kill-all-local-variables)) - (let ((regexp-alist (or regexp-alist compilation-error-regexp-alist)) - (parser (or parser compilation-parse-errors-function)) - (thisdir default-directory) - outwin) - (save-excursion - ;; Clear out the compilation buffer and make it writable. - ;; Change its default-directory to the directory where the compilation - ;; will happen, and insert a `cd' command to indicate this. - (set-buffer outbuf) - (setq buffer-read-only nil) - (erase-buffer) - (setq default-directory thisdir) - (insert "cd " thisdir "\n" command "\n") - (set-buffer-modified-p nil)) - ;; If we're already in the compilation buffer, go to the end - ;; of the buffer, so point will track the compilation output. - (if (eq outbuf (current-buffer)) - (goto-char (point-max))) - ;; Pop up the compilation buffer. - (setq outwin (display-buffer outbuf)) - (save-excursion - (set-buffer outbuf) - (compilation-mode) - (buffer-disable-undo (current-buffer)) - ;; (setq buffer-read-only t) ;;; Non-ergonomic. - (set (make-local-variable 'compilation-parse-errors-function) parser) - (set (make-local-variable 'compilation-error-message) error-message) - (set (make-local-variable 'compilation-error-regexp-alist) regexp-alist) - (setq default-directory thisdir - compilation-directory-stack (list default-directory)) - (set-window-start outwin (point-min)) - (setq mode-name name-of-mode) - (or (eq outwin (selected-window)) - (set-window-point outwin (point-min))) - (and compilation-window-height - (= (window-width outwin) (frame-width)) - (let ((w (selected-window))) - (unwind-protect - (progn - (select-window outwin) - (enlarge-window (- compilation-window-height - (window-height)))) - (select-window w)))) - ;; Start the compilation. - (if (fboundp 'start-process) - (let ((proc (start-process-shell-command (downcase mode-name) - outbuf - command))) - (set-process-sentinel proc 'compilation-sentinel) - (set-process-filter proc 'compilation-filter) - (set-marker (process-mark proc) (point) outbuf) - (setq compilation-in-progress - (cons proc compilation-in-progress))) - ;; No asynchronous processes available - (message (format "Executing `%s'..." command)) - (let ((status (call-process shell-file-name nil outbuf nil "-c" - command)))) - (message (format "Executing `%s'...done" command))))) - ;; Make it so the next C-x ` will use this buffer. - (setq compilation-last-buffer outbuf))) - -(defvar compilation-minor-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] 'compile-mouse-goto-error) - (define-key map "\C-c\C-c" 'compile-goto-error) - (define-key map "\C-c\C-k" 'kill-compilation) - (define-key map "\M-n" 'compilation-next-error) - (define-key map "\M-p" 'compilation-previous-error) - (define-key map "\M-{" 'compilation-previous-file) - (define-key map "\M-}" 'compilation-next-file) - map) - "Keymap for `compilation-minor-mode'.") - -(defvar compilation-mode-map - (let ((map (cons 'keymap compilation-minor-mode-map))) - (define-key map " " 'scroll-up) - (define-key map "\^?" 'scroll-down) - map) - "Keymap for compilation log buffers. -`compilation-minor-mode-map' is a cdr of this.") - -(defun compilation-mode () - "Major mode for compilation log buffers. -\\<compilation-mode-map>To visit the source for a line-numbered error, -move point to the error message line and type \\[compile-goto-error]. -To kill the compilation, type \\[kill-compilation]. - -Runs `compilation-mode-hook' with `run-hooks' (which see)." - (interactive) - (fundamental-mode) - (use-local-map compilation-mode-map) - (setq major-mode 'compilation-mode - mode-name "Compilation") - (compilation-setup) - (run-hooks 'compilation-mode-hook)) - -;; Prepare the buffer for the compilation parsing commands to work. -(defun compilation-setup () - ;; Make the buffer's mode line show process state. - (setq mode-line-process '(": %s")) - (set (make-local-variable 'compilation-error-list) nil) - (set (make-local-variable 'compilation-old-error-list) nil) - (set (make-local-variable 'compilation-parsing-end) 1) - (set (make-local-variable 'compilation-directory-stack) nil) - (setq compilation-last-buffer (current-buffer))) - -(defvar compilation-minor-mode nil - "Non-nil when in compilation-minor-mode. -In this minor mode, all the error-parsing commands of the -Compilation major mode are available.") -(make-variable-buffer-local 'compilation-minor-mode) - -(or (assq 'compilation-minor-mode minor-mode-alist) - (setq minor-mode-alist (cons '(compilation-minor-mode " Compilation") - minor-mode-alist))) -(or (assq 'compilation-minor-mode minor-mode-map-alist) - (setq minor-mode-map-alist (cons (cons 'compilation-minor-mode - compilation-minor-mode-map) - minor-mode-map-alist))) - -;;;###autoload -(defun compilation-minor-mode (&optional arg) - "Toggle compilation minor mode. -With arg, turn compilation mode on if and only if arg is positive. -See `compilation-mode'." - (interactive "P") - (if (setq compilation-minor-mode (if (null arg) - (null compilation-minor-mode) - (> (prefix-numeric-value arg) 0))) - (compilation-setup))) - -;; Called when compilation process changes state. -(defun compilation-sentinel (proc msg) - "Sentinel for compilation buffers." - (let ((buffer (process-buffer proc))) - (if (memq (process-status proc) '(signal exit)) - (progn - (if (null (buffer-name buffer)) - ;; buffer killed - (set-process-buffer proc nil) - (let ((obuf (current-buffer)) - omax opoint) - ;; save-excursion isn't the right thing if - ;; process-buffer is current-buffer - (unwind-protect - (progn - ;; Write something in the compilation buffer - ;; and hack its mode line. - (set-buffer buffer) - (let ((buffer-read-only nil)) - (setq omax (point-max) - opoint (point)) - (goto-char omax) - ;; Record where we put the message, so we can ignore it - ;; later on. - (insert ?\n mode-name " " msg) - (forward-char -1) - (insert " at " (substring (current-time-string) 0 19)) - (forward-char 1) - (setq mode-line-process - (concat ": " - (symbol-name (process-status proc)))) - ;; Since the buffer and mode line will show that the - ;; process is dead, we can delete it now. Otherwise it - ;; will stay around until M-x list-processes. - (delete-process proc) - ;; Force mode line redisplay soon. - (set-buffer-modified-p (buffer-modified-p))) - (if (and opoint (< opoint omax)) - (goto-char opoint)) - (if compilation-finish-function - (funcall compilation-finish-function buffer msg))) - (set-buffer obuf)))) - (setq compilation-in-progress (delq proc compilation-in-progress)) - )))) - -(defun compilation-filter (proc string) - "Process filter for compilation buffers. -Just inserts the text, but uses `insert-before-markers'." - (save-excursion - (set-buffer (process-buffer proc)) - (let ((buffer-read-only nil)) - (save-excursion - (goto-char (process-mark proc)) - (insert-before-markers string) - (set-marker (process-mark proc) (point)))))) - -;; Return the cdr of compilation-old-error-list for the error containing point. -(defun compile-error-at-point () - (compile-reinitialize-errors nil (point)) - (let ((errors compilation-old-error-list)) - (while (and errors - (> (point) (car (car errors)))) - (setq errors (cdr errors))) - errors)) - -(defsubst compilation-buffer-p (buffer) - (assq 'compilation-error-list (buffer-local-variables buffer))) - -(defun compilation-next-error (n) - "Move point to the next error in the compilation buffer. -Does NOT find the source line like \\[next-error]." - (interactive "p") - (or (compilation-buffer-p (current-buffer)) - (error "Not in a compilation buffer.")) - (setq compilation-last-buffer (current-buffer)) - - (let ((errors (compile-error-at-point))) - - ;; Move to the error after the one containing point. - (goto-char (car (if (< n 0) - (let ((i 0) - (e compilation-old-error-list)) - ;; See how many cdrs away ERRORS is from the start. - (while (not (eq e errors)) - (setq i (1+ i) - e (cdr e))) - (if (> (- n) i) - (error "Moved back past first error") - (nth (+ i n) compilation-old-error-list))) - (let ((compilation-error-list (cdr errors))) - (compile-reinitialize-errors nil nil n) - (if compilation-error-list - (nth (1- n) compilation-error-list) - (error "Moved past last error")))))))) - -(defun compilation-previous-error (n) - "Move point to the previous error in the compilation buffer. -Does NOT find the source line like \\[next-error]." - (interactive "p") - (compilation-next-error (- n))) - - -;; Given an elt of `compilation-error-list', return an object representing -;; the referenced file which is equal to (but not necessarily eq to) what -;; this function would return for another error in the same file. -(defsubst compilation-error-filedata (data) - (setq data (cdr data)) - (if (markerp data) - (marker-buffer data) - (car data))) - -;; Return a string describing a value from compilation-error-filedata. -;; This value is not necessarily useful as a file name, but should be -;; indicative to the user of what file's errors are being referred to. -(defsubst compilation-error-filedata-file-name (filedata) - (if (bufferp filedata) - (buffer-file-name filedata) - (car filedata))) - -(defun compilation-next-file (n) - "Move point to the next error for a different file than the current one." - (interactive "p") - (or (compilation-buffer-p (current-buffer)) - (error "Not in a compilation buffer.")) - (setq compilation-last-buffer (current-buffer)) - - (let ((reversed (< n 0)) - errors filedata) - - (if (not reversed) - (setq errors (or (compile-error-at-point) - (error "Moved past last error"))) - - ;; Get a reversed list of the errors up through the one containing point. - (compile-reinitialize-errors nil (point)) - (setq errors (reverse compilation-old-error-list) - n (- n)) - - ;; Ignore errors after point. (car ERRORS) will be the error - ;; containing point, (cadr ERRORS) the one before it. - (while (and errors - (< (point) (car (car errors)))) - (setq errors (cdr errors)))) - - (while (> n 0) - (setq filedata (compilation-error-filedata (car errors))) - - ;; Skip past the following errors for this file. - (while (equal filedata - (compilation-error-filedata - (car (or errors - (if reversed - (error "%s the first erring file" - (compilation-error-filedata-file-name - filedata)) - (let ((compilation-error-list nil)) - ;; Parse some more. - (compile-reinitialize-errors nil nil 2) - (setq errors compilation-error-list))) - (error "%s is the last erring file" - (compilation-error-filedata-file-name - filedata)))))) - (setq errors (cdr errors))) - - (setq n (1- n))) - - ;; Move to the following error. - (goto-char (car (car (or errors - (if reversed - (error "This is the first erring file") - (let ((compilation-error-list nil)) - ;; Parse the last one. - (compile-reinitialize-errors nil nil 1) - compilation-error-list)))))))) - -(defun compilation-previous-file (n) - "Move point to the previous error for a different file than the current one." - (interactive "p") - (compilation-next-file (- n))) - - -(defun kill-compilation () - "Kill the process made by the \\[compile] command." - (interactive) - (let ((buffer (compilation-find-buffer))) - (if (get-buffer-process buffer) - (interrupt-process (get-buffer-process buffer)) - (error "The compilation process is not running.")))) - - -;; Parse any new errors in the compilation buffer, -;; or reparse from the beginning if the user has asked for that. -(defun compile-reinitialize-errors (reparse - &optional limit-search find-at-least) - (save-excursion - (set-buffer compilation-last-buffer) - ;; If we are out of errors, or if user says "reparse", - ;; discard the info we have, to force reparsing. - (if (or (eq compilation-error-list t) - reparse) - (compilation-forget-errors)) - (if (and compilation-error-list - (or (not limit-search) - (> compilation-parsing-end limit-search)) - (or (not find-at-least) - (>= (length compilation-error-list) find-at-least))) - ;; Since compilation-error-list is non-nil, it points to a specific - ;; error the user wanted. So don't move it around. - nil - ;; This was here for a long time (before my rewrite); why? --roland - ;;(switch-to-buffer compilation-last-buffer) - (set-buffer-modified-p nil) - (if (< compilation-parsing-end (point-max)) - ;; compilation-error-list might be non-nil if we have a non-nil - ;; LIMIT-SEARCH or FIND-AT-LEAST arg. In that case its value - ;; records the current position in the error list, and we must - ;; preserve that after reparsing. - (let ((error-list-pos compilation-error-list)) - (funcall compilation-parse-errors-function - limit-search - (and find-at-least - ;; We only need enough new parsed errors to reach - ;; FIND-AT-LEAST errors past the current - ;; position. - (- find-at-least (length compilation-error-list)))) - ;; Remember the entire list for compilation-forget-errors. If - ;; this is an incremental parse, append to previous list. If - ;; we are parsing anew, compilation-forget-errors cleared - ;; compilation-old-error-list above. - (setq compilation-old-error-list - (nconc compilation-old-error-list compilation-error-list)) - (if error-list-pos - ;; We started in the middle of an existing list of parsed - ;; errors before parsing more; restore that position. - (setq compilation-error-list error-list-pos)) - ))))) - -(defun compile-mouse-goto-error (event) - (interactive "e") - (save-excursion - (set-buffer (window-buffer (posn-window (event-end event)))) - (goto-char (posn-point (event-end event))) - - (or (compilation-buffer-p (current-buffer)) - (error "Not in a compilation buffer.")) - (setq compilation-last-buffer (current-buffer)) - (compile-reinitialize-errors nil (point)) - - ;; Move to bol; the marker for the error on this line will point there. - (beginning-of-line) - - ;; Move compilation-error-list to the elt of compilation-old-error-list - ;; we want. - (setq compilation-error-list compilation-old-error-list) - (while (and compilation-error-list - (> (point) (car (car compilation-error-list)))) - (setq compilation-error-list (cdr compilation-error-list))) - (or compilation-error-list - (error "No error to go to"))) - (select-window (posn-window (event-end event))) - ;; Move to another window, so that next-error's window changes - ;; result in the desired setup. - (or (one-window-p) - (progn - (other-window -1) - ;; other-window changed the selected buffer, - ;; but we didn't want to do that. - (set-buffer compilation-last-buffer))) - - (push-mark) - (next-error 1)) - -(defun compile-goto-error (&optional argp) - "Visit the source for the error message point is on. -Use this command in a compilation log buffer. Sets the mark at point there. -\\[universal-argument] as a prefix arg means to reparse the buffer's error messages first; -other kinds of prefix arguments are ignored." - (interactive "P") - (or (compilation-buffer-p (current-buffer)) - (error "Not in a compilation buffer.")) - (setq compilation-last-buffer (current-buffer)) - (compile-reinitialize-errors (consp argp) (point)) - - ;; Move to bol; the marker for the error on this line will point there. - (beginning-of-line) - - ;; Move compilation-error-list to the elt of compilation-old-error-list - ;; we want. - (setq compilation-error-list compilation-old-error-list) - (while (and compilation-error-list - (> (point) (car (car compilation-error-list)))) - (setq compilation-error-list (cdr compilation-error-list))) - - ;; Move to another window, so that next-error's window changes - ;; result in the desired setup. - (or (one-window-p) - (progn - (other-window -1) - ;; other-window changed the selected buffer, - ;; but we didn't want to do that. - (set-buffer compilation-last-buffer))) - - (push-mark) - (next-error 1)) - -;; Return a compilation buffer. -;; If the current buffer is a compilation buffer, return it. -;; If compilation-last-buffer is set to a live buffer, use that. -;; Otherwise, look for a compilation buffer and signal an error -;; if there are none. -(defun compilation-find-buffer (&optional other-buffer) - (if (and (not other-buffer) - (compilation-buffer-p (current-buffer))) - ;; The current buffer is a compilation buffer. - (current-buffer) - (if (and compilation-last-buffer (buffer-name compilation-last-buffer) - (or (not other-buffer) (not (eq compilation-last-buffer - (current-buffer))))) - compilation-last-buffer - (let ((buffers (buffer-list))) - (while (and buffers (or (not (compilation-buffer-p (car buffers))) - (and other-buffer - (eq (car buffers) (current-buffer))))) - (setq buffers (cdr buffers))) - (if buffers - (car buffers) - (or (and other-buffer - (compilation-buffer-p (current-buffer)) - ;; The current buffer is a compilation buffer. - (progn - (if other-buffer - (message "This is the only compilation buffer.")) - (current-buffer))) - (error "No compilation started!"))))))) - -;;;###autoload -(defun next-error (&optional argp) - "Visit next compilation error message and corresponding source code. -This operates on the output from the \\[compile] command. -If all preparsed error messages have been processed, -the error message buffer is checked for new ones. - -A prefix arg specifies how many error messages to move; -negative means move back to previous error messages. -Just C-u as a prefix means reparse the error message buffer -and start at the first error. - -\\[next-error] normally applies to the most recent compilation started, -but as long as you are in the middle of parsing errors from one compilation -output buffer, you stay with that compilation output buffer. - -Use \\[next-error] in a compilation output buffer to switch to -processing errors from that compilation. - -See variables `compilation-parse-errors-function' and -\`compilation-error-regexp-alist' for customization ideas." - (interactive "P") - (setq compilation-last-buffer (compilation-find-buffer)) - (compilation-goto-locus (compilation-next-error-locus - ;; We want to pass a number here only if - ;; we got a numeric prefix arg, not just C-u. - (and (not (consp argp)) - (prefix-numeric-value argp)) - (consp argp)))) -;;;###autoload (define-key ctl-x-map "`" 'next-error) - -(defun compilation-next-error-locus (&optional move reparse) - "Visit next compilation error and return locus in corresponding source code. -This operates on the output from the \\[compile] command. -If all preparsed error messages have been processed, -the error message buffer is checked for new ones. - -Returns a cons (ERROR . SOURCE) of two markers: ERROR is a marker at the -location of the error message in the compilation buffer, and SOURCE is a -marker at the location in the source code indicated by the error message. - -Optional first arg MOVE says how many error messages to move forwards (or -backwards, if negative); default is 1. Optional second arg REPARSE, if -non-nil, says to reparse the error message buffer and reset to the first -error (plus MOVE - 1). - -The current buffer should be the desired compilation output buffer." - (or move (setq move 1)) - (compile-reinitialize-errors reparse nil (and (not reparse) - (if (< move 1) 0 (1- move)))) - (let (next-errors next-error) - (save-excursion - (set-buffer compilation-last-buffer) - ;; compilation-error-list points to the "current" error. - (setq next-errors - (if (> move 0) - (nthcdr (1- move) - compilation-error-list) - ;; Zero or negative arg; we need to move back in the list. - (let ((n (1- move)) - (i 0) - (e compilation-old-error-list)) - ;; See how many cdrs away the current error is from the start. - (while (not (eq e compilation-error-list)) - (setq i (1+ i) - e (cdr e))) - (if (> (- n) i) - (error "Moved back past first error") - (nthcdr (+ i n) compilation-old-error-list)))) - next-error (car next-errors)) - (while - (if (null next-error) - (progn - (if move (if (> move 0) - (error "Moved past last error") - (error "Moved back past first error"))) - (compilation-forget-errors) - (error (concat compilation-error-message - (and (get-buffer-process (current-buffer)) - (eq (process-status - (get-buffer-process - (current-buffer))) - 'run) - " yet")))) - (setq compilation-error-list (cdr next-errors)) - (if (null (cdr next-error)) - ;; This error is boring. Go to the next. - t - (or (markerp (cdr next-error)) - ;; This error has a filename/lineno pair. - ;; Find the file and turn it into a marker. - (let* ((fileinfo (car (cdr next-error))) - (buffer (compilation-find-file (cdr fileinfo) - (car fileinfo) - (car next-error)))) - (if (null buffer) - ;; We can't find this error's file. - ;; Remove all errors in the same file. - (progn - (setq next-errors compilation-old-error-list) - (while next-errors - (and (consp (cdr (car next-errors))) - (equal (car (cdr (car next-errors))) - fileinfo) - (progn - (set-marker (car (car next-errors)) nil) - (setcdr (car next-errors) nil))) - (setq next-errors (cdr next-errors))) - ;; Look for the next error. - t) - ;; We found the file. Get a marker for this error. - ;; compilation-old-error-list is a buffer-local - ;; variable, so we must be careful to extract its value - ;; before switching to the source file buffer. - (let ((errors compilation-old-error-list) - (last-line (nth 1 (cdr next-error))) - (column (nth 2 (cdr next-error)))) - (set-buffer buffer) - (save-excursion - (save-restriction - (widen) - (goto-line last-line) - (if column - (move-to-column column) - (beginning-of-line)) - (setcdr next-error (point-marker)) - ;; Make all the other error messages referring - ;; to the same file have markers into the buffer. - (while errors - (and (consp (cdr (car errors))) - (equal (car (cdr (car errors))) fileinfo) - (let* ((this (nth 1 (cdr (car errors)))) - (column (nth 2 (cdr (car errors)))) - (lines (- this last-line))) - (if (eq selective-display t) - ;; When selective-display is t, - ;; each C-m is a line boundary, - ;; as well as each newline. - (if (< lines 0) - (re-search-backward "[\n\C-m]" - nil 'end - (- lines)) - (re-search-forward "[\n\C-m]" - nil 'end - lines)) - (forward-line lines)) - (if column - (move-to-column column)) - (setq last-line this) - (setcdr (car errors) (point-marker)))) - (setq errors (cdr errors))))))))) - ;; If we didn't get a marker for this error, or this - ;; marker's buffer was killed, go on to the next one. - (or (not (markerp (cdr next-error))) - (not (marker-buffer (cdr next-error)))))) - (setq next-errors compilation-error-list - next-error (car next-errors)))) - - ;; Skip over multiple error messages for the same source location, - ;; so the next C-x ` won't go to an error in the same place. - (while (and compilation-error-list - (equal (cdr (car compilation-error-list)) (cdr next-error))) - (setq compilation-error-list (cdr compilation-error-list))) - - ;; We now have a marker for the position of the error source code. - ;; NEXT-ERROR is a cons (ERROR . SOURCE) of two markers. - next-error)) - -(defun compilation-goto-locus (next-error) - "Jump to an error locus returned by `compilation-next-error-locus'. -Takes one argument, a cons (ERROR . SOURCE) of two markers. -Selects a window with point at SOURCE, with another window displaying ERROR." - (switch-to-buffer (marker-buffer (cdr next-error))) - (goto-char (cdr next-error)) - ;; If narrowing got in the way of - ;; going to the right place, widen. - (or (= (point) (marker-position (cdr next-error))) - (progn - (widen) - (goto-char (cdr next-error)))) - - ;; Show compilation buffer in other window, scrolled to this error. - (let* ((pop-up-windows t) - (w (display-buffer (marker-buffer (car next-error))))) - (set-window-point w (car next-error)) - (set-window-start w (car next-error)))) - -;; Find a buffer for file FILENAME. -;; Search the directories in compilation-search-path. -;; A nil in compilation-search-path means to try the -;; current directory, which is passed in DIR. -;; If FILENAME is not found at all, ask the user where to find it. -;; Pop up the buffer containing MARKER and scroll to MARKER if we ask the user. -(defun compilation-find-file (filename dir marker) - (let ((dirs compilation-search-path) - result name) - (while (and dirs (null result)) - (setq name (expand-file-name filename (or (car dirs) dir)) - result (and (file-exists-p name) - (find-file-noselect name)) - dirs (cdr dirs))) - (or result - ;; The file doesn't exist. - ;; Ask the user where to find it. - ;; If he hits C-g, then the next time he does - ;; next-error, he'll skip past it. - (progn - (let* ((pop-up-windows t) - (w (display-buffer (marker-buffer marker)))) - (set-window-point w marker) - (set-window-start w marker)) - (setq name - (expand-file-name - (read-file-name - (format "Find this error in: (default %s) " - filename) dir filename t))) - (if (file-directory-p name) - (setq name (concat (file-name-as-directory name) filename))) - (if (file-exists-p name) - (find-file-noselect name)))))) - -;; Set compilation-error-list to nil, and unchain the markers that point to the -;; error messages and their text, so that they no longer slow down gap motion. -;; This would happen anyway at the next garbage collection, but it is better to -;; do it right away. -(defun compilation-forget-errors () - (while compilation-old-error-list - (let ((next-error (car compilation-old-error-list))) - (set-marker (car next-error) nil) - (if (markerp (cdr next-error)) - (set-marker (cdr next-error) nil))) - (setq compilation-old-error-list (cdr compilation-old-error-list))) - (setq compilation-error-list nil - compilation-directory-stack nil - compilation-parsing-end 1)) - - -(defun count-regexp-groupings (regexp) - "Return the number of \\( ... \\) groupings in REGEXP (a string)." - (let ((groupings 0) - (len (length regexp)) - (i 0) - c) - (while (< i len) - (setq c (aref regexp i) - i (1+ i)) - (cond ((= c ?\[) - ;; Find the end of this [...]. - (while (and (< i len) - (not (= (aref regexp i) ?\]))) - (setq i (1+ i)))) - ((= c ?\\) - (if (< i len) - (progn - (setq c (aref regexp i) - i (1+ i)) - (if (= c ?\)) - ;; We found the end of a grouping, - ;; so bump our counter. - (setq groupings (1+ groupings)))))))) - groupings)) - -(defun compilation-parse-errors (limit-search find-at-least) - "Parse the current buffer as grep, cc or lint error messages. -See variable `compilation-parse-errors-function' for the interface it uses." - (setq compilation-error-list nil) - (message "Parsing error messages...") - (let (text-buffer orig orig-expanded parent-expanded - regexp enter-group leave-group error-group - alist subexpr error-regexp-groups - (found-desired nil) - (compilation-num-errors-found 0)) - - ;; Don't reparse messages already seen at last parse. - (goto-char compilation-parsing-end) - ;; Don't parse the first two lines as error messages. - ;; This matters for grep. - (if (bobp) - (progn - (forward-line 2) - ;; Move back so point is before the newline. - ;; This matters because some error regexps use \n instead of ^ - ;; to be faster. - (forward-char -1))) - - ;; Compile all the regexps we want to search for into one. - (setq regexp (concat "\\(" compilation-enter-directory-regexp "\\)\\|" - "\\(" compilation-leave-directory-regexp "\\)\\|" - "\\(" (mapconcat (function - (lambda (elt) - (concat "\\(" (car elt) "\\)"))) - compilation-error-regexp-alist - "\\|") "\\)")) - - ;; Find out how many \(...\) groupings are in each of the regexps, and set - ;; *-GROUP to the grouping containing each constituent regexp (whose - ;; subgroups will come immediately thereafter) of the big regexp we have - ;; just constructed. - (setq enter-group 1 - leave-group (+ enter-group - (count-regexp-groupings - compilation-enter-directory-regexp) - 1) - error-group (+ leave-group - (count-regexp-groupings - compilation-leave-directory-regexp) - 1)) - - ;; Compile an alist (IDX FILE LINE [COL]), where IDX is the number of - ;; the subexpression for an entire error-regexp, and FILE and LINE (and - ;; possibly COL) are the numbers for the subexpressions giving the file - ;; name and line number (and possibly column number). - (setq alist (or compilation-error-regexp-alist - (error "compilation-error-regexp-alist is empty!")) - subexpr (1+ error-group)) - (while alist - (setq error-regexp-groups - (cons (list subexpr - (+ subexpr (nth 1 (car alist))) - (+ subexpr (nth 2 (car alist))) - (and (nth 2 (car alist)) - (+ subexpr (nth 2 (car alist))))) - error-regexp-groups)) - (setq subexpr (+ subexpr 1 (count-regexp-groupings (car (car alist))))) - (setq alist (cdr alist))) - - (setq orig default-directory) - (setq orig-expanded (file-truename orig)) - (setq parent-expanded (expand-file-name "../" orig-expanded)) - - (while (and (not found-desired) - ;; We don't just pass LIMIT-SEARCH to re-search-forward - ;; because we want to find matches containing LIMIT-SEARCH - ;; but which extend past it. - (re-search-forward regexp nil t)) - - ;; Figure out which constituent regexp matched. - (cond ((match-beginning enter-group) - ;; The match was the enter-directory regexp. - (let ((dir - (file-name-as-directory - (expand-file-name - (buffer-substring (match-beginning (+ enter-group 1)) - (match-end (+ enter-group 1))))))) - ;; The directory name in the "entering" message - ;; is a truename. Try to convert it to a form - ;; like what the user typed in. - (setq dir - (compile-abbreviate-directory dir orig orig-expanded - parent-expanded)) - (setq compilation-directory-stack - (cons dir compilation-directory-stack)) - (and (file-directory-p dir) - (setq default-directory dir))) - - (and limit-search (>= (point) limit-search) - ;; The user wanted a specific error, and we're past it. - ;; We do this check here (and in the leave-group case) - ;; rather than at the end of the loop because if the last - ;; thing seen is an error message, we must carefully - ;; discard the last error when it is the first in a new - ;; file (see below in the error-group case). - (setq found-desired t))) - - ((match-beginning leave-group) - ;; The match was the leave-directory regexp. - (let ((beg (match-beginning (+ leave-group 1))) - (stack compilation-directory-stack)) - (if beg - (let ((dir - (file-name-as-directory - (expand-file-name - (buffer-substring beg - (match-end (+ leave-group - 1))))))) - ;; The directory name in the "entering" message - ;; is a truename. Try to convert it to a form - ;; like what the user typed in. - (setq dir - (compile-abbreviate-directory dir orig orig-expanded - parent-expanded)) - (while (and stack - (not (string-equal (car stack) dir))) - (setq stack (cdr stack))))) - (setq compilation-directory-stack (cdr stack)) - (setq stack (car compilation-directory-stack)) - (if stack - (setq default-directory stack)) - ) - - (and limit-search (>= (point) limit-search) - ;; The user wanted a specific error, and we're past it. - ;; We do this check here (and in the enter-group case) - ;; rather than at the end of the loop because if the last - ;; thing seen is an error message, we must carefully - ;; discard the last error when it is the first in a new - ;; file (see below in the error-group case). - (setq found-desired t))) - - ((match-beginning error-group) - ;; The match was the composite error regexp. - ;; Find out which individual regexp matched. - (setq alist error-regexp-groups) - (while (and alist - (null (match-beginning (car (car alist))))) - (setq alist (cdr alist))) - (if alist - (setq alist (car alist)) - (error "compilation-parse-errors: impossible regexp match!")) - - ;; Extract the file name and line number from the error message. - (let ((beginning-of-match (match-beginning 0)) ;looking-at nukes - (filename (buffer-substring (match-beginning (nth 1 alist)) - (match-end (nth 1 alist)))) - (linenum (string-to-int - (buffer-substring - (match-beginning (nth 2 alist)) - (match-end (nth 2 alist))))) - (column (and (nth 3 alist) - (string-to-int - (buffer-substring - (match-beginning (nth 3 alist)) - (match-end (nth 3 alist))))))) - - ;; Check for a comint-file-name-prefix and prepend it if - ;; appropriate. (This is very useful for - ;; compilation-minor-mode in an rlogin-mode buffer.) - (and (boundp 'comint-file-name-prefix) - ;; If the file name is relative, default-directory will - ;; already contain the comint-file-name-prefix (done by - ;; compile-abbreviate-directory). - (file-name-absolute-p filename) - (setq filename (concat comint-file-name-prefix filename))) - (setq filename (cons default-directory filename)) - - ;; Locate the erring file and line. - ;; Cons a new elt onto compilation-error-list, - ;; giving a marker for the current compilation buffer - ;; location, and the file and line number of the error. - (save-excursion - (beginning-of-line 1) - (let ((this (cons (point-marker) - (list filename linenum column)))) - ;; Don't add the same source line more than once. - (if (equal (cdr this) (cdr (car compilation-error-list))) - nil - (setq compilation-error-list - (cons this - compilation-error-list)) - (setq compilation-num-errors-found - (1+ compilation-num-errors-found))))) - (and (or (and find-at-least (> compilation-num-errors-found - find-at-least)) - (and limit-search (>= (point) limit-search))) - ;; We have found as many new errors as the user wants, - ;; or past the buffer position he indicated. We - ;; continue to parse until we have seen all the - ;; consecutive errors in the same file, so the error - ;; positions will be recorded as markers in this buffer - ;; that might change. - (cdr compilation-error-list) ; Must check at least two. - (not (equal (car (cdr (nth 0 compilation-error-list))) - (car (cdr (nth 1 compilation-error-list))))) - (progn - ;; Discard the error just parsed, so that the next - ;; parsing run can get it and the following errors in - ;; the same file all at once. If we didn't do this, we - ;; would have the same problem we are trying to avoid - ;; with the test above, just delayed until the next run! - (setq compilation-error-list - (cdr compilation-error-list)) - (goto-char beginning-of-match) - (setq found-desired t))) - ) - ) - (t - (error "compilation-parse-errors: known groups didn't match!"))) - - (message "Parsing error messages...%d (%.0f%% of buffer)" - compilation-num-errors-found - ;; Use floating-point because (* 100 (point)) frequently - ;; exceeds the range of Emacs Lisp integers. - (/ (* 100.0 (point)) (point-max))) - - (and limit-search (>= (point) limit-search) - ;; The user wanted a specific error, and we're past it. - (setq found-desired t))) - (setq compilation-parsing-end (if found-desired - (point) - ;; We have searched the whole buffer. - (point-max)))) - (setq compilation-error-list (nreverse compilation-error-list)) - (message "Parsing error messages...done")) - -;; If directory DIR is a subdir of ORIG or of ORIG's parent, -;; return a relative name for it starting from ORIG or its parent. -;; ORIG-EXPANDED is an expanded version of ORIG. -;; PARENT-EXPANDED is an expanded version of ORIG's parent. -;; Those two args could be computed here, but we run faster by -;; having the caller compute them just once. -(defun compile-abbreviate-directory (dir orig orig-expanded parent-expanded) - ;; Check for a comint-file-name-prefix and prepend it if appropriate. - ;; (This is very useful for compilation-minor-mode in an rlogin-mode - ;; buffer.) - (if (boundp 'comint-file-name-prefix) - (setq dir (concat comint-file-name-prefix dir))) - - (if (and (> (length dir) (length orig-expanded)) - (string= orig-expanded - (substring dir 0 (length orig-expanded)))) - (setq dir - (concat orig - (substring dir (length orig-expanded))))) - (if (and (> (length dir) (length parent-expanded)) - (string= parent-expanded - (substring dir 0 (length parent-expanded)))) - (setq dir - (concat (file-name-directory - (directory-file-name orig)) - (substring dir (length parent-expanded))))) - dir) - -(provide 'compile) - -;;; compile.el ends here diff --git a/lisp/progmodes/cplus-md.el b/lisp/progmodes/cplus-md.el deleted file mode 100644 index af26f52138c..00000000000 --- a/lisp/progmodes/cplus-md.el +++ /dev/null @@ -1,917 +0,0 @@ -;;; cplus-md.el --- C++ code editing commands for Emacs -;;; Copyright (C) 1985, 1992 Free Software Foundation, Inc. - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. -;; Maintainer: Dave Detlefs <dld@cs.cmu.edu> -;; Keywords: c - -;;; Commentary: - -;; 1987 Dave Detlefs <dld@cs.cmu.edu> -;; and Stewart Clamen <clamen@cs.cmu.edu>. -;; Done by fairly faithful modification of: - -;;; Change Log: - -;; Feb, 1990 (Dave Detlefs, dld@cs.cmu.edu) -;; Fixed electric-c++-terminator to handle double colons, at the -;; request of John Hagerman. -;; -;; Jan, 1990 (Doug Lea, dl@oswego.edu) -;; Replaced c++-comment-region and c++-uncomment-region with -;; versions from Igor Metz that avoid potential infinite loops. -;; -;; Oct, 1989 (Dave Detlefs, dld@cs.cmu.edu) -;; Added contribution from Igor Metz <metz@iam.unibe.ch>: -;; functions c++-comment-region and c++-uncomment-region and -;; corresponding key-binding. -;; Also fixed bug in indentation of second line after an empty -;; arglist with empty-arglist non-null. -;; -;; Sept, 1989 (Glen Ditchfield, gjditchfield@violet.uwaterloo.ca): -;; Textual changes to more closely imitate Emacs 18.55's c-mode. -;; Fixed handling of "default:", where ":" was the last character in the -;; buffer. Fixed indentation of comments starting in column 0, and when -;; previous line contained more than one comment start string. Fixed -;; handling of "friend". -;; -;; Aug 7, 1989; John Hagerman (hagerman@ece.cmu.edu): -;; Changed calculate-c++-indent to handle member initializations -;; more flexibly. Two new variables are used to control behavior: -;; c++-member-init-indent and c++-continued-member-init-offset. -;; Note the assumption that member initializations and argument -;; declarations are not mixed in one function definition. -;; -;; June 1989 (Dave Detlefs, dld@cs.cmu.edu) -;; Fixed calculate-c++-indent to handle continued lines ending in -;; {'s. (I wasn't following C-mode closely enough, or C-mode -;; changed.) Made ' a quote character, at the behest of someone -;; whose mail I apparently deleted (if they send me mail I'll credit -;; them here in a future revision.) -;; Dan Weinreb (dlw@odi.com) pointed out that 'c++-mode successively -;; bound c++-indent-exp and c++-indent-defun to ESC-^q. ESC-^q is -;; now bound to c++-indent-exp, while, c++-indent-defun is invoked -;; with ESC-^x. - -;; February 1989 (Dave Detlefs, dld@cs.cmu.edu) -;; Fixed some errors in c++-indent-defun, as pointed out by Sam -;; Haradhvala (odi!sam@talcott.harvard.edu). -;; October 1988 (Dave Detlefs, dld@cs.cmu.edu) -;; It turns out I had only *thought* I had made -;; beginning(end)-of-defun work. It should work better now -- you -;; can either attempt to match defun headers "strongly," using a -;; very complicated regexp, or "weakly," using a simple one. This -;; is settable by a variable; the default is the cheaper weak -;; method. (Stewart Clamen was intimately involved in this, too.) -;; -;; I made "'" *not* be a string delimiter, because that was causing -;; comments containing contractions to ("// don't") to mess up paren -;; balancing. -;; -;; I also incorporated another slight indentation fix from Glen -;; Ditchfield. -;; -;; We hope this is will make into version 19 of gnu-emacs. -;; -;; September 1988: incorporated changes from Fred Calm at Schlumberger. -;; Also, made beginning(end)-of-defun, indent-defun work. -;; -;; August 1987: incorporated changes done by Glen Ditchfield of Waterloo. - -;;; Code: - -(defvar c++-mode-abbrev-table nil - "Abbrev table used in C++ mode.") -(define-abbrev-table 'c++-mode-abbrev-table ()) - -(defvar c++-mode-map () - "Keymap used in C++ mode.") -(if c++-mode-map - () - (setq c++-mode-map (make-sparse-keymap)) - (define-key c++-mode-map "\C-j" 'reindent-then-newline-and-indent) - (define-key c++-mode-map "{" 'electric-c++-brace) - (define-key c++-mode-map "}" 'electric-c++-brace) - (define-key c++-mode-map ";" 'electric-c++-semi) - (define-key c++-mode-map "\e\C-h" 'mark-c-function) - (define-key c++-mode-map "\e\C-q" 'indent-c++-exp) - (define-key c++-mode-map "\177" 'backward-delete-char-untabify) - (define-key c++-mode-map "\t" 'c++-indent-command) -;; (define-key c++-mode-map "\C-c\C-i" 'c++-insert-header) - (define-key c++-mode-map "\C-c\C-\\" 'c-backslash-region)) -;; (define-key c++-mode-map "\e\C-a" 'c++-beginning-of-defun) -;; (define-key c++-mode-map "\e\C-e" 'c++-end-of-defun) -;; (define-key c++-mode-map "\e\C-x" 'c++-indent-defun)) - -(defvar c++-mode-syntax-table nil - "Syntax table used in C++ mode.") - -(if c++-mode-syntax-table - () - (setq c++-mode-syntax-table (copy-syntax-table c-mode-syntax-table)) - (modify-syntax-entry ?* ". 23b" c++-mode-syntax-table) - (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table) - (modify-syntax-entry ?\n ">" c++-mode-syntax-table)) - -(defvar c++-continued-member-init-offset nil - "*Extra indent for continuation lines of member inits; -nil means to align with previous initializations rather than -with the colon on the first line.") -(defvar c++-member-init-indent 0 - "*Indentation level of member initializations in function declarations.") -(defvar c++-friend-offset -4 - "*Offset of C++ friend declarations relative to member declarations.") -(defvar c++-electric-colon t - "*If t, colon is an electric terminator.") -(defvar c++-empty-arglist-indent nil - "*Indicates how far to indent an line following an empty argument -list. Nil indicates to just after the paren.") - - -;;;###autoload -(defun c++-mode () - "Major mode for editing C++ code. Very much like editing C code. -Expression and list commands understand all C++ brackets. -Tab at left margin indents for C++ code -Comments are delimited with /* ... */ {or with // ... <newline>} -Paragraphs are separated by blank lines only. -Delete converts tabs to spaces as it moves back. -\\{c++-mode-map} -Variables controlling indentation style: - c-tab-always-indent - Non-nil means TAB in C mode should always reindent the current line, - regardless of where in the line point is when the TAB command is used. - Default is t. - c-auto-newline - Non-nil means automatically newline before and after braces, - and after colons and semicolons, inserted in C code. - c-indent-level - Indentation of C statements within surrounding block. - The surrounding block's indentation is the indentation - of the line on which the open-brace appears. - c-continued-statement-offset - Extra indentation given to a substatement, such as the - then-clause of an if or body of a while. - c-continued-brace-offset - Extra indentation given to a brace that starts a substatement. - This is in addition to c-continued-statement-offset. - c-brace-offset - Extra indentation for line if it starts with an open brace. - c-brace-imaginary-offset - An open brace following other text is treated as if it were - this far to the right of the start of its line. - c-argdecl-indent - Indentation level of declarations of C function arguments. - c-label-offset - Extra indentation for line that is a label, or case or ``default:'', or - ``public:'' or ``private:'', or ``protected:''. - c++-electric-colon - If non-nil at invocation of c++-mode (t is the default) colon electricly - indents. - c++-empty-arglist-indent - If non-nil, a function declaration or invocation which ends a line with a - left paren is indented this many extra spaces, instead of flush with the - left paren. - c++-friend-offset - Offset of C++ friend declarations relative to member declarations. - c++-member-init-indent - Indentation level of member initializations in function declarations, - if they are on a separate line beginning with a colon. - c++-continued-member-init-offset - Extra indentation for continuation lines of member initializations; NIL - means to align with previous initializations rather than with the colon. - -Settings for K&R, BSD, and Stroustrup indentation styles are - c-indent-level 5 8 4 - c-continued-statement-offset 5 8 4 - c-continued-brace-offset 0 - c-brace-offset -5 -8 0 - c-brace-imaginary-offset 0 - c-argdecl-indent 0 8 4 - c-label-offset -5 -8 -4 - c++-empty-arglist-indent 4 - c++-friend-offset 0 - -Turning on C++ mode calls the value of the variable `c++-mode-hook' with -no args if that value is non-nil." - (interactive) - (kill-all-local-variables) - (use-local-map c++-mode-map) - (set-syntax-table c++-mode-syntax-table) - (setq major-mode 'c++-mode - mode-name "C++" - comment-column 32 - local-abbrev-table c++-mode-abbrev-table) - (set (make-local-variable 'indent-line-function) 'c++-indent-line) - (set (make-local-variable 'comment-start) "// ") - (set (make-local-variable 'comment-end) "") - (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *") - (set (make-local-variable 'comment-indent-function) 'c++-comment-indent) - (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter)) - (set (make-local-variable 'paragraph-separate) paragraph-start) - (set (make-local-variable 'paragraph-ignore-fill-prefix) t) - (set (make-local-variable 'require-final-newline) t) - (set (make-local-variable 'parse-sexp-ignore-comments) t) - (run-hooks 'c++-mode-hook) - (if c++-electric-colon - (define-key c++-mode-map ":" 'electric-c++-terminator))) - -;; This is used by indent-for-comment -;; to decide how much to indent a comment in C++ code -;; based on its context. -(defun c++-comment-indent () - (if (looking-at "^\\(/\\*\\|//\\)") - 0 ; Existing comment at bol stays there. - (save-excursion - (skip-chars-backward " \t") - (max - ;; leave at least one space on non-empty lines. - (if (zerop (current-column)) 0 (1+ (current-column))) - (let ((cur-pt (point))) - (beginning-of-line 0) - ;; If previous line had a comment, use it's indent - (if (re-search-forward comment-start-skip cur-pt t) - (progn - (goto-char (match-beginning 0)) - (current-column)) - comment-column)))))) ; otherwise indent at comment column. - -(defun electric-c++-brace (arg) - "Insert character and correct line's indentation." - (interactive "P") - (let (insertpos) - (if (and (not arg) - (eolp) - (or (save-excursion - (skip-chars-backward " \t") - (bolp)) - (if c-auto-newline (progn (c++-indent-line) (newline) t)))) - (progn - (insert last-command-char) - (c++-indent-line) - (if c-auto-newline - (progn - (newline) - ;; (newline) may have done auto-fill - (setq insertpos (- (point) 2)) - (c++-indent-line))) - (save-excursion - (if insertpos (goto-char (1+ insertpos))) - (delete-char -1)))) - (if insertpos - (save-excursion - (goto-char insertpos) - (self-insert-command (prefix-numeric-value arg))) - (self-insert-command (prefix-numeric-value arg))))) - -(defun electric-c++-semi (arg) - "Insert character and correct line's indentation." - (interactive "P") - (if c-auto-newline - (electric-c++-terminator arg) - (self-insert-command (prefix-numeric-value arg)))) - -(defun electric-c++-terminator (arg) - "Insert character and correct line's indentation." - (interactive "P") - (let (insertpos (end (point))) - (if (and (not arg) (eolp) - (not (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (or (= (following-char) ?#) - ;; Colon is special only after a label, or - ;; case, or another colon. - ;; So quickly rule out most other uses of colon - ;; and do no indentation for them. - (and (eq last-command-char ?:) - (not (looking-at "case[ \t]")) - (save-excursion - (forward-word 1) - (skip-chars-forward " \t") - (< (point) end)) - ;; Do re-indent double colons - (save-excursion - (end-of-line 1) - (looking-at ":"))) - (progn - (beginning-of-defun) - (let ((pps (parse-partial-sexp (point) end))) - (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) - (progn - (insert last-command-char) - (c++-indent-line) - (and c-auto-newline - (not (c-inside-parens-p)) - (progn - ;; the new marker object, used to be just an integer - (setq insertpos (make-marker)) - ;; changed setq to set-marker - (set-marker insertpos (1- (point))) - ;; do this before the newline, since in auto fill can break - (newline) - (c-indent-line))) - (save-excursion - (if insertpos (goto-char (1+ insertpos))) - (delete-char -1)))) - (if insertpos - (save-excursion - (goto-char insertpos) - (self-insert-command (prefix-numeric-value arg))) - (self-insert-command (prefix-numeric-value arg))))) - -(defun c++-indent-command (&optional whole-exp) - "Indent current line as C++ code, or in some cases insert a tab character. -If `c-tab-always-indent' is non-nil (the default), always indent current -line. Otherwise, indent the current line only if point is at the left -margin or in the line's indentation; otherwise insert a tab. - -A numeric argument, regardless of its value, means indent rigidly all means -indent rigidly all the lines of the expression starting after point so that -this line becomes properly indented. The relative indentation among the -lines of the expression are preserved." - (interactive "P") - (if whole-exp - ;; If arg, always indent this line as C - ;; and shift remaining lines of expression the same amount. - (let ((shift-amt (c++-indent-line)) - beg end) - (save-excursion - (if c-tab-always-indent - (beginning-of-line)) - (setq beg (point)) - (forward-sexp 1) - (setq end (point)) - (goto-char beg) - (forward-line 1) - (setq beg (point))) - (if (> end beg) - (indent-code-rigidly beg end shift-amt "#"))) - (if (and (not c-tab-always-indent) - (save-excursion - (skip-chars-backward " \t") - (not (bolp)))) - (insert-tab) - (c++-indent-line)))) - -(defun c++-indent-line () - "Indent current line as C++ code. -Return the amount the indentation changed by." - (let ((indent (calculate-c++-indent nil)) - beg shift-amt - (case-fold-search nil) - (pos (- (point-max) (point)))) - (beginning-of-line) - (setq beg (point)) - (cond ((eq indent nil) - (setq indent (current-indentation))) - ((eq indent t) - (setq indent (calculate-c-indent-within-comment))) - ((looking-at "[ \t]*#") - (setq indent 0)) - (t - (skip-chars-forward " \t") - (if (listp indent) (setq indent (car indent))) - (cond ((looking-at "\\(default\\|public\\|private\\|protected\\):") - (setq indent (+ indent c-label-offset))) - ((or (looking-at "case\\b") - (and (looking-at "[A-Za-z]") - (save-excursion - (forward-sexp 1) - (looking-at ":[^:]")))) - (setq indent (max 1 (+ indent c-label-offset)))) - ((and (looking-at "else\\b") - (not (looking-at "else\\s_"))) - (setq indent (save-excursion - (c-backward-to-start-of-if) - (current-indentation)))) - ((looking-at "friend\[ \t]") - (setq indent (+ indent c++-friend-offset))) - ((= (following-char) ?}) - (setq indent (- indent c-indent-level))) - ((= (following-char) ?{) - (setq indent (+ indent c-brace-offset)))))) - (skip-chars-forward " \t") - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - (delete-region beg (point)) - (indent-to indent) - ;; If initial point was within line's indentation, - ;; position after the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos)))) - shift-amt)) - -(defun calculate-c++-indent (&optional parse-start) - "Return appropriate indentation for current line as C++ code. -In usual case returns an integer: the column to indent to. -Returns nil if line starts inside a string, t if in a comment." - (save-excursion - (beginning-of-line) - (let ((indent-point (point)) - (case-fold-search nil) - state - containing-sexp) - (if parse-start - (goto-char parse-start) - (beginning-of-defun)) - (while (< (point) indent-point) - (setq parse-start (point)) - (setq state (parse-partial-sexp (point) indent-point 0)) - (setq containing-sexp (car (cdr state)))) - (cond ((or (nth 3 state) (nth 4 state)) - ;; return nil or t if should not change this line - (nth 4 state)) - ((null containing-sexp) - ;; Line is at top level. May be data or function definition, or - ;; may be function argument declaration or member initialization. - ;; Indent like the previous top level line unless - ;; (1) the previous line ends in a closeparen without semicolon, - ;; in which case this line is the first argument declaration or - ;; member initialization, or - ;; (2) the previous line begins with a colon, - ;; in which case this is the second line of member inits. - ;; It is assumed that arg decls and member inits are not mixed. - (goto-char indent-point) - (skip-chars-forward " \t") - (if (= (following-char) ?{) - 0 ; Unless it starts a function body - (c++-backward-to-noncomment (or parse-start (point-min))) - (if (= (preceding-char) ?\)) - (progn ; first arg decl or member init - (goto-char indent-point) - (skip-chars-forward " \t") - (if (= (following-char) ?:) - c++-member-init-indent - c-argdecl-indent)) - (if (= (preceding-char) ?\;) - (backward-char 1)) - (if (= (preceding-char) ?}) - 0 - (beginning-of-line) ; continued arg decls or member inits - (skip-chars-forward " \t") - (if (= (following-char) ?:) - (if c++-continued-member-init-offset - (+ (current-indentation) - c++-continued-member-init-offset) - (progn - (forward-char 1) - (skip-chars-forward " \t") - (current-column))) - (current-indentation))) - ))) - ((/= (char-after containing-sexp) ?{) - ;; line is expression, not statement: - ;; indent to just after the surrounding open -- unless - ;; empty arg list, in which case we do what - ;; c++-empty-arglist-indent says to do. - (if (and c++-empty-arglist-indent - (or (null (nth 2 state)) ;; indicates empty arg - ;; list. - ;; Use a heuristic: if the first - ;; non-whitespace following left paren on - ;; same line is not a comment, - ;; is not an empty arglist. - (save-excursion - (goto-char (1+ containing-sexp)) - (not - (looking-at "\\( \\|\t\\)*[^/\n]"))))) - (progn - (goto-char containing-sexp) - (beginning-of-line) - (skip-chars-forward " \t") - (goto-char (min (+ (point) c++-empty-arglist-indent) - (1+ containing-sexp))) - (current-column)) - ;; In C-mode, we would always indent to one after the - ;; left paren. Here, though, we may have an - ;; empty-arglist, so we'll indent to the min of that - ;; and the beginning of the first argument. - (goto-char (1+ containing-sexp)) - (current-column))) - (t - ;; Statement. Find previous non-comment character. - (goto-char indent-point) - (c++-backward-to-noncomment containing-sexp) - (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?\{))) - ;; This line is continuation of preceding line's statement; - ;; indent c-continued-statement-offset more than the - ;; previous line of the statement. - (progn - (c-backward-to-start-of-continued-exp containing-sexp) - (+ c-continued-statement-offset (current-column) - (if (save-excursion (goto-char indent-point) - (skip-chars-forward " \t") - (eq (following-char) ?{)) - c-continued-brace-offset 0))) - ;; This line starts a new statement. - ;; Position following last unclosed open. - (goto-char containing-sexp) - ;; Is line first statement after an open-brace? - (or - ;; If no, find that first statement and indent like it. - (save-excursion - (forward-char 1) - (while (progn (skip-chars-forward " \t\n") - (looking-at - (concat - "#\\|/\\*\\|//" - "\\|case[ \t]" - "\\|[a-zA-Z0-9_$]*:[^:]" - "\\|friend[ \t]"))) - ;; Skip over comments and labels following openbrace. - (cond ((= (following-char) ?\#) - (forward-line 1)) - ((looking-at "/\\*") - (search-forward "*/" nil 'move)) - ((looking-at "//\\|friend[ \t]") - (forward-line 1)) - (t - (re-search-forward ":[^:]" nil 'move)))) - ;; The first following code counts - ;; if it is before the line we want to indent. - (and (< (point) indent-point) - (current-column))) - ;; If no previous statement, - ;; indent it relative to line brace is on. - ;; For open brace in column zero, don't let statement - ;; start there too. If c-indent-offset is zero, - ;; use c-brace-offset + c-continued-statement-offset instead. - ;; For open-braces not the first thing in a line, - ;; add in c-brace-imaginary-offset. - (+ (if (and (bolp) (zerop c-indent-level)) - (+ c-brace-offset c-continued-statement-offset) - c-indent-level) - ;; Move back over whitespace before the openbrace. - ;; If openbrace is not first nonwhite thing on the line, - ;; add the c-brace-imaginary-offset. - (progn (skip-chars-backward " \t") - (if (bolp) 0 c-brace-imaginary-offset)) - ;; If the openbrace is preceded by a parenthesized exp, - ;; move to the beginning of that; - ;; possibly a different line - (progn - (if (eq (preceding-char) ?\)) - (forward-sexp -1)) - ;; Get initial indentation of the line we are on. - (current-indentation)))))))))) - -(defun c++-backward-to-noncomment (lim) - (let (opoint stop) - (while (not stop) - (skip-chars-backward " \t\n\r\f" lim) - (setq opoint (point)) - (cond ((and (>= (point) (+ 2 lim)) - (save-excursion - (forward-char -2) - (looking-at "\\*/"))) - (search-backward "/*" lim 'move)) - ((and - (search-backward "//" (max (c++-point-bol) lim) 'move) - (not (c++-within-string-p (point) opoint)))) - (t (beginning-of-line) - (skip-chars-forward " \t") - (if (looking-at "#") - (setq stop (<= (point) lim)) - (setq stop t) - (goto-char opoint))))))) - -(defun indent-c++-exp () - "Indent each line of the C++ grouping following point." - (interactive) - (let ((indent-stack (list nil)) - (contain-stack (list (point))) - (case-fold-search nil) - restart outer-loop-done inner-loop-done state ostate - this-indent last-sexp last-depth - at-else at-brace - (opoint (point)) - (next-depth 0)) - (save-excursion - (forward-sexp 1)) - (save-excursion - (setq outer-loop-done nil) - (while (and (not (eobp)) (not outer-loop-done)) - (setq last-depth next-depth) - ;; Compute how depth changes over this line - ;; plus enough other lines to get to one that - ;; does not end inside a comment or string. - ;; Meanwhile, do appropriate indentation on comment lines. - (setq inner-loop-done nil) - (while (and (not inner-loop-done) - (not (and (eobp) (setq outer-loop-done t)))) - (setq ostate state) - (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) - nil nil state)) - (setq next-depth (car state)) - (if (and (car (cdr (cdr state))) - (>= (car (cdr (cdr state))) 0)) - (setq last-sexp (car (cdr (cdr state))))) - (if (or (nth 4 ostate)) - (c++-indent-line)) - (if (or (nth 3 state)) - (forward-line 1) - (setq inner-loop-done t))) - (if (<= next-depth 0) - (setq outer-loop-done t)) - (if outer-loop-done - nil - ;; If this line had ..))) (((.. in it, pop out of the levels - ;; that ended anywhere in this line, even if the final depth - ;; doesn't indicate that they ended. - (while (> last-depth (nth 6 state)) - (setq indent-stack (cdr indent-stack) - contain-stack (cdr contain-stack) - last-depth (1- last-depth))) - (if (/= last-depth next-depth) - (setq last-sexp nil)) - ;; Add levels for any parens that were started in this line. - (while (< last-depth next-depth) - (setq indent-stack (cons nil indent-stack) - contain-stack (cons nil contain-stack) - last-depth (1+ last-depth))) - (if (null (car contain-stack)) - (setcar contain-stack (or (car (cdr state)) - (save-excursion (forward-sexp -1) - (point))))) - (forward-line 1) - (skip-chars-forward " \t") - (if (eolp) - nil - (if (and (car indent-stack) - (>= (car indent-stack) 0)) - ;; Line is on an existing nesting level. - ;; Lines inside parens are handled specially. - (if (/= (char-after (car contain-stack)) ?\{) - (setq this-indent (car indent-stack)) - ;; Line is at statement level. - ;; Is it a new statement? Is it an else? - ;; Find last non-comment character before this line - (save-excursion - (setq at-else (looking-at "else\\W")) - (setq at-brace (= (following-char) ?\{)) - (c++-backward-to-noncomment opoint) - (if (not (memq (preceding-char) '(nil ?\, ?\; ?\} ?: ?\{))) - ;; Preceding line did not end in comma or semi; - ;; indent this line c-continued-statement-offset - ;; more than previous. - (progn - (c-backward-to-start-of-continued-exp - (car contain-stack)) - (setq this-indent - (+ c-continued-statement-offset - (current-column) - (if at-brace c-continued-brace-offset 0)))) - ;; Preceding line ended in comma or semi; - ;; use the standard indent for this level. - (if at-else - (progn (c-backward-to-start-of-if opoint) - (setq this-indent (current-indentation))) - (setq this-indent (car indent-stack)))))) - ;; Just started a new nesting level. - ;; Compute the standard indent for this level. - (let ((val (calculate-c++-indent - (if (car indent-stack) - (- (car indent-stack)))))) - (setcar indent-stack - (setq this-indent val)))) - ;; Adjust line indentation according to its contents - (if (looking-at "\\(public\\|private\\|protected\\):") - (setq this-indent (- this-indent c-indent-level))) - (if (or (looking-at "case[ \t]") - (and (looking-at "[A-Za-z]") - (save-excursion - (forward-sexp 1) - (looking-at ":[^:]")))) - (setq this-indent (max 1 (+ this-indent c-label-offset)))) - (if (looking-at "friend[ \t]") - (setq this-indent (+ this-indent c++-friend-offset))) - (if (= (following-char) ?\}) - (setq this-indent (- this-indent c-indent-level))) - (if (= (following-char) ?\{) - (setq this-indent (+ this-indent c-brace-offset))) - ;; Put chosen indentation into effect. - (or (= (current-column) this-indent) - (= (following-char) ?\#) - (progn - (delete-region (point) (progn (beginning-of-line) (point))) - (indent-to this-indent))) - ;; Indent any comment following the text. - (or (looking-at comment-start-skip) - (if (re-search-forward comment-start-skip - (save-excursion (end-of-line) - (point)) t) - (progn - (indent-for-comment) - (beginning-of-line)))))))))) - -(defun fill-c++-comment () - "Fill a comment contained in consecutive lines containing point. -The fill lines remain a comment." - (interactive) - (save-excursion - (let ((save fill-prefix)) - (beginning-of-line 1) - (save-excursion - (re-search-forward comment-start-skip - (save-excursion (end-of-line) (point)) - t) - (goto-char (match-end 0)) - (set-fill-prefix)) - (while (looking-at fill-prefix) - (previous-line 1)) - (next-line 1) - (insert-string "\n") - (fill-paragraph nil) - (delete-char -1) - (setq fill-prefix save)))) - -(defun c++-point-bol () - "Returns the value of the point at the beginning of the current line." - (save-excursion - (beginning-of-line) - (point))) - -;; (defun c++-insert-header () -;; "Insert header denoting C++ code at top of buffer." -;; (interactive) -;; (save-excursion -;; (goto-char (point-min)) -;; (insert "// " -;; "This may look like C code, but it is really " -;; "-*- C++ -*-" -;; "\n\n"))) - -(defun c++-within-string-p (point1 point2) - "Returns true if number of double quotes between two points is odd." - (let ((s (buffer-substring point1 point2))) - (not (zerop (% (c++-count-char-in-string ?\" s) 2))))) - -(defun c++-count-char-in-string (c s) - (let ((count 0) - (pos 0)) - (while (< pos (length s)) - (setq count (+ count (if (\= (aref s pos) c) 1 0))) - (setq pos (1+ pos))) - count)) - -;; rms: This page is creeping featurism, and not worth having. - -;;; Below are two regular expressions that attempt to match defuns -;;; "strongly" and "weakly." The strong one almost reconstructs the -;;; grammar of C++; the weak one just figures anything id or curly on -;;; the left begins a defun. The constant "c++-match-header-strongly" -;;; determines which to use; the default is the weak one. - -;; (defvar c++-match-header-strongly nil -;; "*If nil, use `c++-defun-header-weak' to identify beginning of definitions. -;; If non-nil, use `c++-defun-header-strong'.") -;; -;; (defvar c++-defun-header-strong-struct-equivs "\\(class\\|struct\\|enum\\)" -;; "Regexp to match names of structure declaration blocks in C++.") -;; -;; (defconst c++-defun-header-strong -;; (let* -;; (; valid identifiers -;; ;; There's a real weirdness here -- if I switch the below -;; (id "\\(\\w\\|_\\)+") -;; ;; to be -;; ;; (id "\\(_\\|\\w\\)+") -;; ;; things no longer work right. Try it and see! -;; -;; ; overloadable operators -;; (op-sym1 -;; "[-+*/%^&|~!=<>]\\|[-+*/%^&|<>=!]=\\|<<=?\\|>>=?") -;; (op-sym2 -;; "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]") -;; (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)")) -;; ; whitespace -;; (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*") -;; (c-comment (concat "/\\*" middle "\\*+/")) -;; (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)")) -;; (wh-opt (concat wh "*")) -;; (wh-nec (concat wh "+")) -;; (oper (concat "\\(" "operator" "\\(" -;; wh-opt op-sym "\\|" wh-nec id "\\)" "\\)")) -;; (dcl-list "([^():]*)") -;; (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)")) -;; (inits -;; (concat "\\(:" -;; "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*" -;; wh-opt id "(.*)" wh-opt "{" -;; "\\|" wh-opt "{\\)")) -;; (type-name (concat -;; "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?" -;; id)) -;; (type (concat "\\(const" wh-nec "\\)?" -;; "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|" -;; type-name wh-opt "&" "\\)")) -;; (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)") -;; (modifiers (concat "\\(" modifier wh-nec "\\)*")) -;; (func-header -;; ;; type arg-dcl -;; (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits)) -;; (inherit (concat "\\(:" wh-opt "\\(public\\|private\\)?" -;; wh-nec id "\\)")) -;; (cs-header (concat -;; c++-defun-header-strong-struct-equivs -;; wh-nec id wh-opt inherit "?" wh-opt "{"))) -;; (concat "^\\(" func-header "\\|" cs-header "\\)")) -;; "Strongly-defined regexp to match beginning of structure or function def.") -;; -;; -;; ;; This part has to do with recognizing defuns. -;; -;; ;; The weak convention we will use is that a defun begins any time -;; ;; there is a left curly brace, or some identifier on the left margin, -;; ;; followed by a left curly somewhere on the line. (This will also -;; ;; incorrectly match some continued strings, but this is after all -;; ;; just a weak heuristic.) Suggestions for improvement (short of the -;; ;; strong scheme shown above) are welcomed. -;; -;; (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{" -;; "Weakly-defined regexp to match beginning of structure or function def.") -;; -;; (defun c++-beginning-of-defun (arg) -;; (interactive "p") -;; (let ((c++-defun-header (if c++-match-header-strongly -;; c++-defun-header-strong -;; c++-defun-header-weak))) -;; (cond ((or (= arg 0) (and (> arg 0) (bobp))) nil) -;; ((and (not (looking-at c++-defun-header)) -;; (let ((curr-pos (point)) -;; (open-pos (if (search-forward "{" nil 'move) -;; (point))) -;; (beg-pos -;; (if (re-search-backward c++-defun-header nil 'move) -;; (match-beginning 0)))) -;; (if (and open-pos beg-pos -;; (< beg-pos curr-pos) -;; (> open-pos curr-pos)) -;; (progn -;; (goto-char beg-pos) -;; (if (= arg 1) t nil));; Are we done? -;; (goto-char curr-pos) -;; nil)))) -;; (t -;; (if (and (looking-at c++-defun-header) (not (bobp))) -;; (forward-char (if (< arg 0) 1 -1))) -;; (and (re-search-backward c++-defun-header nil 'move (or arg 1)) -;; (goto-char (match-beginning 0))))))) -;; -;; -;; (defun c++-end-of-defun (arg) -;; (interactive "p") -;; (let ((c++-defun-header (if c++-match-header-strongly -;; c++-defun-header-strong -;; c++-defun-header-weak))) -;; (if (and (eobp) (> arg 0)) -;; nil -;; (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1)) -;; (let ((pos (point))) -;; (c++-beginning-of-defun -;; (if (< arg 0) -;; (- (- arg (if (eobp) 0 1))) -;; arg)) -;; (if (and (< arg 0) (bobp)) -;; t -;; (if (re-search-forward c++-defun-header nil 'move) -;; (progn (forward-char -1) -;; (forward-sexp) -;; (beginning-of-line 2))) -;; (if (and (= pos (point)) -;; (re-search-forward c++-defun-header nil 'move)) -;; (c++-end-of-defun 1)))) -;; t))) -;; -;; (defun c++-indent-defun () -;; "Indents the current function definition, struct or class declaration." -;; (interactive) -;; (let ((restore (point))) -;; (c++-end-of-defun 1) -;; (beginning-of-line 1) -;; (let ((end (point))) -;; (c++-beginning-of-defun 1) -;; (while (<= (point) end) -;; (c++-indent-line) -;; (next-line 1) -;; (beginning-of-line 1))) -;; (goto-char restore))) - -;;; cplus-md.el ends here diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el deleted file mode 100644 index bbcf7e96828..00000000000 --- a/lisp/progmodes/etags.el +++ /dev/null @@ -1,1447 +0,0 @@ -;;; etags.el --- etags facility for Emacs - -;; Copyright (C) 1985, 1986, 1988, 1989, 1992, 1993, 1994 -;; Free Software Foundation, Inc. - -;; Author: Roland McGrath <roland@gnu.ai.mit.edu> -;; Keywords: tools - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Code: - -;;;###autoload -(defvar tags-file-name nil - "*File name of tags table. -To switch to a new tags table, setting this variable is sufficient. -If you set this variable, do not also set `tags-table-list'. -Use the `etags' program to make a tags table file.") -;; Make M-x set-variable tags-file-name like M-x visit-tags-table. -;;;###autoload (put 'tags-file-name 'variable-interactive "fVisit tags table: ") - -;;;###autoload -;; Use `visit-tags-table-buffer' to cycle through tags tables in this list. -(defvar tags-table-list nil - "*List of file names of tags tables to search. -An element that is a directory means the file \"TAGS\" in that directory. -To switch to a new list of tags tables, setting this variable is sufficient. -If you set this variable, do not also set `tags-file-name'. -Use the `etags' program to make a tags table file.") - -;;;###autoload -(defvar tags-add-tables 'ask-user - "*T means always add a new tags table to the current list. -Nil means never add to the current list; always start a new list. -Non-nil but not t says to ask the user whether to add a new tags table -to the current list (as opposed to starting a new list).") - -(defvar tags-table-list-pointer nil - "Pointer into `tags-table-list' where the current state of searching is. -Might instead point into a list of included tags tables. -Use `visit-tags-table-buffer' to cycle through tags tables in this list.") - -(defvar tags-table-list-started-at nil - "Pointer into `tags-table-list', where the current search started.") - -(defvar tags-table-parent-pointer-list nil - "Saved state of the tags table that included this one. -Each element is (POINTER . STARTED-AT), giving the values of - `tags-table-list-pointer' and `tags-table-list-started-at' from - before we moved into the current table.") - -(defvar tags-table-set-list nil - "List of sets of tags table which have been used together in the past. -Each element is a list of strings which are file names.") - -;;;###autoload -(defvar find-tag-hook nil - "*Hook to be run by \\[find-tag] after finding a tag. See `run-hooks'. -The value in the buffer in which \\[find-tag] is done is used, -not the value in the buffer \\[find-tag] goes to.") - -;;;###autoload -(defvar find-tag-default-function nil - "*A function of no arguments used by \\[find-tag] to pick a default tag. -If nil, and the symbol that is the value of `major-mode' -has a `find-tag-default-function' property (see `put'), that is used. -Otherwise, `find-tag-default' is used.") - -(defvar default-tags-table-function nil - "If non-nil, a function to choose a default tags file for a buffer. -This function receives no arguments and should return the default -tags table file to use for the current buffer.") - -(defvar tags-location-stack nil - "List of markers which are locations visited by \\[find-tag]. -Pop back to the last location with \\[negative-argument] \\[find-tag].") - -;; Tags table state. -;; These variables are local in tags table buffers. - -(defvar tag-lines-already-matched nil - "List of positions of beginnings of lines within the tags table -that are already matched.") - -(defvar tags-table-files nil - "List of file names covered by current tags table. -nil means it has not yet been computed; use `tags-table-files' to do so.") - -(defvar tags-completion-table nil - "Alist of tag names defined in current tags table.") - -(defvar tags-included-tables nil - "List of tags tables included by the current tags table.") - -(defvar next-file-list nil - "List of files for \\[next-file] to process.") - -;; Hooks for file formats. - -(defvar tags-table-format-hooks '(etags-recognize-tags-table - recognize-empty-tags-table) - "List of functions to be called in a tags table buffer to identify -the type of tags table. The functions are called in order, with no arguments, -until one returns non-nil. The function should make buffer-local bindings -of the format-parsing tags function variables if successful.") - -(defvar file-of-tag-function nil - "Function to do the work of `file-of-tag' (which see).") -(defvar tags-table-files-function nil - "Function to do the work of `tags-table-files' (which see).") -(defvar tags-completion-table-function nil - "Function to build the tags-completion-table.") -(defvar snarf-tag-function nil - "Function to get info about a matched tag for `goto-tag-location-function'.") -(defvar goto-tag-location-function nil - "Function of to go to the location in the buffer specified by a tag. -One argument, the tag info returned by `snarf-tag-function'.") -(defvar find-tag-regexp-search-function nil - "Search function passed to `find-tag-in-order' for finding a regexp tag.") -(defvar find-tag-regexp-tag-order nil - "Tag order passed to `find-tag-in-order' for finding a regexp tag.") -(defvar find-tag-regexp-next-line-after-failure-p nil - "Flag passed to `find-tag-in-order' for finding a regexp tag.") -(defvar find-tag-search-function nil - "Search function passed to `find-tag-in-order' for finding a tag.") -(defvar find-tag-tag-order nil - "Tag order passed to `find-tag-in-order' for finding a tag.") -(defvar find-tag-next-line-after-failure-p nil - "Flag passed to `find-tag-in-order' for finding a tag.") -(defvar list-tags-function nil - "Function to do the work of `list-tags' (which see).") -(defvar tags-apropos-function nil - "Function to do the work of `tags-apropos' (which see).") -(defvar tags-included-tables-function nil - "Function to do the work of `tags-included-tables' (which see).") -(defvar verify-tags-table-function nil - "Function to return t iff the current buffer contains a valid -\(already initialized\) tags file.") - -;; Initialize the tags table in the current buffer. -;; Returns non-nil iff it is a valid tags table. On -;; non-nil return, the tags table state variable are -;; made buffer-local and initialized to nil. -(defun initialize-new-tags-table () - (set (make-local-variable 'tag-lines-already-matched) nil) - (set (make-local-variable 'tags-table-files) nil) - (set (make-local-variable 'tags-completion-table) nil) - (set (make-local-variable 'tags-included-tables) nil) - ;; Value is t if we have found a valid tags table buffer. - (let ((hooks tags-table-format-hooks)) - (while (and hooks - (not (funcall (car hooks)))) - (setq hooks (cdr hooks))) - hooks)) - -;;;###autoload -(defun visit-tags-table (file &optional local) - "Tell tags commands to use tags table file FILE. -FILE should be the name of a file created with the `etags' program. -A directory name is ok too; it means file TAGS in that directory. - -Normally \\[visit-tags-table] sets the global value of `tags-file-name'. -With a prefix arg, set the buffer-local value instead. -When you find a tag with \\[find-tag], the buffer it finds the tag -in is given a local value of this variable which is the name of the tags -file the tag was in." - (interactive (list (read-file-name "Visit tags table: (default TAGS) " - default-directory - (expand-file-name "TAGS" - default-directory) - t) - current-prefix-arg)) - ;; Calling visit-tags-table-buffer with tags-file-name set to FILE will - ;; initialize a buffer for FILE and set tags-file-name to the - ;; fully-expanded name. - (let ((tags-file-name file)) - (save-excursion - (or (visit-tags-table-buffer 'same) - (signal 'file-error (list "Visiting tags table" - "file does not exist" - file))) - ;; Set FILE to the expanded name. - (setq file tags-file-name))) - (if local - ;; Set the local value of tags-file-name. - (set (make-local-variable 'tags-file-name) file) - ;; Set the global value of tags-file-name. - (setq-default tags-file-name file))) - -;; Move tags-table-list-pointer along and set tags-file-name. -;; If NO-INCLUDES is non-nil, ignore included tags tables. -;; Returns nil when out of tables. -(defun tags-next-table (&optional no-includes) - ;; Do we have any included tables? - (if (and (not no-includes) - (visit-tags-table-buffer 'same) - (tags-included-tables)) - - ;; Move into the included tags tables. - (setq tags-table-parent-pointer-list - ;; Save the current state of what table we are in. - (cons (cons tags-table-list-pointer tags-table-list-started-at) - tags-table-parent-pointer-list) - ;; Start the pointer in the list of included tables. - tags-table-list-pointer tags-included-tables - tags-table-list-started-at tags-included-tables) - - ;; No included tables. Go to the next table in the list. - (setq tags-table-list-pointer - (cdr tags-table-list-pointer)) - (or tags-table-list-pointer - ;; Wrap around. - (setq tags-table-list-pointer tags-table-list)) - - (if (eq tags-table-list-pointer tags-table-list-started-at) - ;; We have come full circle. No more tables. - (if tags-table-parent-pointer-list - ;; Pop back to the tags table which includes this one. - (progn - ;; Restore the state variables. - (setq tags-table-list-pointer - (car (car tags-table-parent-pointer-list)) - tags-table-list-started-at - (cdr (car tags-table-parent-pointer-list)) - tags-table-parent-pointer-list - (cdr tags-table-parent-pointer-list)) - ;; Recurse to skip to the next table after the parent. - (tags-next-table t)) - ;; All out of tags tables. - (setq tags-table-list-pointer nil)))) - - (and tags-table-list-pointer - ;; Set tags-file-name to the fully-expanded name. - (setq tags-file-name - (tags-expand-table-name (car tags-table-list-pointer))))) - -;; Expand tags table name FILE into a complete file name. -(defun tags-expand-table-name (file) - (setq file (expand-file-name file)) - (if (file-directory-p file) - (expand-file-name "TAGS" file) - file)) - -;; Return the cdr of LIST (default: tags-table-list) whose car -;; is equal to FILE after tags-expand-table-name on both sides. -(defun tags-table-list-member (file &optional list) - (or list - (setq list tags-table-list)) - (setq file (tags-expand-table-name file)) - (while (and list - (not (string= file (tags-expand-table-name (car list))))) - (setq list (cdr list))) - list) - -;; Local var in visit-tags-table-buffer-cont -;; which is set by tags-table-including. -(defvar visit-tags-table-buffer-cont) - -;; Subroutine of visit-tags-table-buffer. Frobs its local vars. -;; Search TABLES for one that has tags for THIS-FILE. Recurses on -;; included tables. Returns the tail of TABLES (or of an inner -;; included list) whose car is a table listing THIS-FILE. If -;; CORE-ONLY is non-nil, check only tags tables that are already in -;; buffers--don't visit any new files. -(defun tags-table-including (this-file tables core-only &optional recursing) - (let ((found nil)) - ;; Loop over TABLES, looking for one containing tags for THIS-FILE. - (while (and (not found) - tables) - (let ((tags-file-name (tags-expand-table-name (car tables)))) - (if (or (get-file-buffer tags-file-name) - (and (not core-only) - (file-exists-p tags-file-name))) - (progn - ;; Select the tags table buffer and get the file list up to date. - (visit-tags-table-buffer 'same) - (or tags-table-files - (setq tags-table-files - (funcall tags-table-files-function))) - - (cond ((member this-file tags-table-files) - ;; Found it. - (setq found tables)) - - ((tags-included-tables) - ;; This table has included tables. Check them. - (let ((old tags-table-parent-pointer-list)) - (unwind-protect - (progn - (or recursing - ;; At top level (not in an included tags - ;; table), set the list to nil so we can - ;; collect just the elts from this run. - (setq tags-table-parent-pointer-list nil)) - (setq found - ;; Recurse on the list of included tables. - (tags-table-including this-file - tags-included-tables - core-only - t)) - (if found - ;; One of them lists THIS-FILE. - ;; Set the table list state variables to move - ;; us inside the list of included tables. - (setq tags-table-parent-pointer-list - (cons - (cons tags-table-list-pointer - tags-table-list-started-at) - tags-table-parent-pointer-list) - tags-table-list-pointer found - tags-table-list-started-at found - ;; Set a local variable of - ;; our caller, visit-tags-table-buffer. - ;; Set it so we won't frob lists later. - visit-tags-table-buffer-cont - 'included))) - (or recursing - ;; tags-table-parent-pointer-list now describes - ;; the path of included tables taken by recursive - ;; invocations of this function. The recursive - ;; calls have consed onto the front of the list, - ;; so it is now outermost first. We want it - ;; innermost first, so reverse it. Then append - ;; the old list (from before we were called the - ;; outermost time), to get the complete current - ;; state of included tables. - (setq tags-table-parent-pointer-list - (nconc (nreverse - tags-table-parent-pointer-list) - old)))))))))) - (setq tables (cdr tables))) - found)) - -(defun visit-tags-table-buffer (&optional cont) - "Select the buffer containing the current tags table. -If optional arg is t, visit the next table in `tags-table-list'. -If optional arg is the atom `same', don't look for a new table; - just select the buffer visiting `tags-file-name'. -If arg is nil or absent, choose a first buffer from information in - `tags-file-name', `tags-table-list', `tags-table-list-pointer'. -Returns t if it visits a tags table, or nil if there are no more in the list." - - ;; Set tags-file-name to the tags table file we want to visit. - (let ((visit-tags-table-buffer-cont cont)) - (cond ((eq visit-tags-table-buffer-cont 'same) - ;; Use the ambient value of tags-file-name. - (or tags-file-name - (error (substitute-command-keys - (concat "No tags table in use! " - "Use \\[visit-tags-table] to select one."))))) - - (visit-tags-table-buffer-cont - ;; Find the next table. - (if (tags-next-table) - ;; Skip over nonexistent files. - (let (file) - (while (and (setq file - (tags-expand-table-name tags-file-name)) - (not (or (get-file-buffer file) - (file-exists-p file)))) - (tags-next-table))))) - - (t - ;; Pick a table out of our hat. - (setq tags-file-name - (or - ;; First, try a local variable. - (cdr (assq 'tags-file-name (buffer-local-variables))) - ;; Second, try a user-specified function to guess. - (and default-tags-table-function - (funcall default-tags-table-function)) - ;; Third, look for a tags table that contains - ;; tags for the current buffer's file. - ;; If one is found, the lists will be frobnicated, - ;; and VISIT-TAGS-TABLE-BUFFER-CONT - ;; will be set non-nil so we don't do it below. - (car (or - ;; First check only tables already in buffers. - (save-excursion (tags-table-including buffer-file-name - tags-table-list - t)) - ;; Since that didn't find any, now do the - ;; expensive version: reading new files. - (save-excursion (tags-table-including buffer-file-name - tags-table-list - nil)))) - ;; Fourth, use the user variable tags-file-name, if it is not - ;; already in tags-table-list. - (and tags-file-name - (not (tags-table-list-member tags-file-name)) - tags-file-name) - ;; Fifth, use the user variable giving the table list. - ;; Find the first element of the list that actually exists. - (let ((list tags-table-list) - file) - (while (and list - (setq file (tags-expand-table-name (car list))) - (not (get-file-buffer file)) - (not (file-exists-p file))) - (setq list (cdr list))) - (car list)) - ;; Finally, prompt the user for a file name. - (expand-file-name - (read-file-name "Visit tags table: (default TAGS) " - default-directory - "TAGS" - t)))))) - - ;; Expand the table name into a full file name. - (setq tags-file-name (tags-expand-table-name tags-file-name)) - - (if (and (eq visit-tags-table-buffer-cont t) - (null tags-table-list-pointer)) - ;; All out of tables. - nil - - ;; Verify that tags-file-name is a valid tags table. - (if (if (get-file-buffer tags-file-name) - ;; The file is already in a buffer. Check for the visited file - ;; having changed since we last used it. - (let (win) - (set-buffer (get-file-buffer tags-file-name)) - (setq win (or verify-tags-table-function - (initialize-new-tags-table))) - (if (or (verify-visited-file-modtime (current-buffer)) - (not (yes-or-no-p - "Tags file has changed, read new contents? "))) - (and win (funcall verify-tags-table-function)) - (revert-buffer t t) - (initialize-new-tags-table))) - (set-buffer (find-file-noselect tags-file-name)) - (or (string= tags-file-name buffer-file-name) - ;; find-file-noselect has changed the file name. - ;; Propagate the change to tags-file-name and tags-table-list. - (let ((tail (member tags-file-name tags-table-list))) - (if tail - (setcar tail buffer-file-name)) - (setq tags-file-name buffer-file-name))) - (initialize-new-tags-table)) - - ;; We have a valid tags table. - (progn - ;; Bury the tags table buffer so it - ;; doesn't get in the user's way. - (bury-buffer (current-buffer)) - - (if (memq visit-tags-table-buffer-cont '(same nil)) - ;; Look in the list for the table we chose. - (let ((elt (tags-table-list-member tags-file-name))) - (or elt - ;; The table is not in the current set. - ;; Try to find it in another previously used set. - (let ((sets tags-table-set-list)) - (while (and sets - (not (setq elt - (tags-table-list-member - tags-file-name (car sets))))) - (setq sets (cdr sets))) - (if sets - ;; Found in some other set. Switch to that set. - (progn - (or (memq tags-table-list tags-table-set-list) - ;; Save the current list. - (setq tags-table-set-list - (cons tags-table-list - tags-table-set-list))) - (setq tags-table-list (car sets))) - - ;; Not found in any existing set. - (if (and tags-table-list - (or (eq t tags-add-tables) - (and tags-add-tables - (y-or-n-p - (concat "Keep current list of " - "tags tables also? "))))) - ;; Add it to the current list. - (setq tags-table-list (cons tags-file-name - tags-table-list)) - ;; Make a fresh list, and store the old one. - (message "Starting a new list of tags tables") - (or (memq tags-table-list tags-table-set-list) - (setq tags-table-set-list - (cons tags-table-list - tags-table-set-list))) - (setq tags-table-list (list tags-file-name))) - (setq elt tags-table-list)))) - - (or visit-tags-table-buffer-cont - ;; Set the tags table list state variables to point - ;; at the table we want to use first. - (setq tags-table-list-started-at elt - tags-table-list-pointer elt)))) - - ;; Return of t says the tags table is valid. - t) - - ;; The buffer was not valid. Don't use it again. - (let ((file tags-file-name)) - (kill-local-variable 'tags-file-name) - (if (eq file tags-file-name) - (setq tags-file-name nil))) - (error "File %s is not a valid tags table" buffer-file-name))))) - -(defun file-of-tag () - "Return the file name of the file whose tags point is within. -Assumes the tags table is the current buffer. -File name returned is relative to tags table file's directory." - (funcall file-of-tag-function)) - -;;;###autoload -(defun tags-table-files () - "Return a list of files in the current tags table. -Assumes the tags table is the current buffer. -File names returned are absolute." - (or tags-table-files - (setq tags-table-files - (funcall tags-table-files-function)))) - -(defun tags-included-tables () - "Return a list of tags tables included by the current table. -Assumes the tags table is the current buffer." - (or tags-included-tables - (setq tags-included-tables (funcall tags-included-tables-function)))) - -;; Build tags-completion-table on demand. The single current tags table -;; and its included tags tables (and their included tables, etc.) have -;; their tags included in the completion table. -(defun tags-completion-table () - (or tags-completion-table - (condition-case () - (prog2 - (message "Making tags completion table for %s..." buffer-file-name) - (let ((included (tags-included-tables)) - (table (funcall tags-completion-table-function))) - (save-excursion - ;; Iterate over the list of included tables, and combine each - ;; included table's completion obarray to the parent obarray. - (while included - ;; Visit the buffer. - (let ((tags-file-name (car included))) - (visit-tags-table-buffer 'same)) - ;; Recurse in that buffer to compute its completion table. - (if (tags-completion-table) - ;; Combine the tables. - (mapatoms (function - (lambda (sym) - (intern (symbol-name sym) table))) - tags-completion-table)) - (setq included (cdr included)))) - (setq tags-completion-table table)) - (message "Making tags completion table for %s...done" - buffer-file-name)) - (quit (message "Tags completion table construction aborted.") - (setq tags-completion-table nil))))) - -;; Completion function for tags. Does normal try-completion, -;; but builds tags-completion-table on demand. -(defun tags-complete-tag (string predicate what) - (save-excursion - ;; If we need to ask for the tag table, allow that. - (let ((enable-recursive-minibuffers t)) - (visit-tags-table-buffer)) - (if (eq what t) - (all-completions string (tags-completion-table) predicate) - (try-completion string (tags-completion-table) predicate)))) - -;; Return a default tag to search for, based on the text at point. -(defun find-tag-default () - (save-excursion - (while (looking-at "\\sw\\|\\s_") - (forward-char 1)) - (if (or (re-search-backward "\\sw\\|\\s_" - (save-excursion (beginning-of-line) (point)) - t) - (re-search-forward "\\(\\sw\\|\\s_\\)+" - (save-excursion (end-of-line) (point)) - t)) - (progn (goto-char (match-end 0)) - (buffer-substring (point) - (progn (forward-sexp -1) - (while (looking-at "\\s'") - (forward-char 1)) - (point)))) - nil))) - -;; Read a tag name from the minibuffer with defaulting and completion. -(defun find-tag-tag (string) - (let* ((default (funcall (or find-tag-default-function - (get major-mode 'find-tag-default-function) - 'find-tag-default))) - (spec (completing-read (if default - (format "%s(default %s) " string default) - string) - 'tags-complete-tag))) - (if (equal spec "") - (or default (error "There is no default tag")) - spec))) - -(defvar last-tag nil - "Last tag found by \\[find-tag].") - -;; Get interactive args for find-tag{-noselect,-other-window,-regexp}. -(defun find-tag-interactive (prompt &optional no-default) - (if current-prefix-arg - (list nil (if (< (prefix-numeric-value current-prefix-arg) 0) - '- - t)) - (list (if no-default - (read-string prompt) - (find-tag-tag prompt))))) - -;;;###autoload -(defun find-tag-noselect (tagname &optional next-p regexp-p) - "Find tag (in current tags table) whose name contains TAGNAME. -Returns the buffer containing the tag's definition and moves its point there, -but does not select the buffer. -The default for TAGNAME is the expression in the buffer near point. - -If second arg NEXT-P is t (interactively, with prefix arg), search for -another tag that matches the last tagname or regexp used. When there are -multiple matches for a tag, more exact matches are found first. If NEXT-P -is the atom `-' (interactively, with prefix arg that is a negative number -or just \\[negative-argument]), pop back to the previous tag gone to. - -If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp. - -See documentation of variable `tags-file-name'." - (interactive (find-tag-interactive "Find tag: ")) - - ;; Save the current buffer's value of `find-tag-hook' before selecting the - ;; tags table buffer. - (let ((local-find-tag-hook find-tag-hook)) - (if (eq '- next-p) - ;; Pop back to a previous location. - (if (null tags-location-stack) - (error "No previous tag locations") - (let ((marker (car tags-location-stack))) - ;; Pop the stack. - (setq tags-location-stack (cdr tags-location-stack)) - (prog1 - ;; Move to the saved location. - (set-buffer (marker-buffer marker)) - (goto-char (marker-position marker)) - ;; Kill that marker so it doesn't slow down editing. - (set-marker marker nil nil) - ;; Run the user's hook. Do we really want to do this for pop? - (run-hooks 'local-find-tag-hook)))) - (if next-p - ;; Find the same table we last used. - (visit-tags-table-buffer 'same) - ;; Pick a table to use. - (visit-tags-table-buffer) - ;; Record TAGNAME for a future call with NEXT-P non-nil. - (setq last-tag tagname)) - (prog1 - ;; Record the location so we can pop back to it later. - (marker-buffer - (car - (setq tags-location-stack - (cons (let ((marker (make-marker))) - (save-excursion - (set-buffer - ;; find-tag-in-order does the real work. - (find-tag-in-order - (if next-p last-tag tagname) - (if regexp-p - find-tag-regexp-search-function - find-tag-search-function) - (if regexp-p - find-tag-regexp-tag-order - find-tag-tag-order) - (if regexp-p - find-tag-regexp-next-line-after-failure-p - find-tag-next-line-after-failure-p) - (if regexp-p "matching" "containing") - (not next-p))) - (set-marker marker (point)))) - tags-location-stack)))) - (run-hooks 'local-find-tag-hook))))) - -;;;###autoload -(defun find-tag (tagname &optional next-p regexp-p) - "Find tag (in current tags table) whose name contains TAGNAME. -Select the buffer containing the tag's definition, and move point there. -The default for TAGNAME is the expression in the buffer around or before point. - -If second arg NEXT-P is t (interactively, with prefix arg), search for -another tag that matches the last tagname or regexp used. When there are -multiple matches for a tag, more exact matches are found first. If NEXT-P -is the atom `-' (interactively, with prefix arg that is a negative number -or just \\[negative-argument]), pop back to the previous tag gone to. - -See documentation of variable `tags-file-name'." - (interactive (find-tag-interactive "Find tag: ")) - (switch-to-buffer (find-tag-noselect tagname next-p regexp-p))) -;;;###autoload (define-key esc-map "." 'find-tag) - -;;;###autoload -(defun find-tag-other-window (tagname &optional next-p regexp-p) - "Find tag (in current tags table) whose name contains TAGNAME. -Select the buffer containing the tag's definition in another window, and -move point there. The default for TAGNAME is the expression in the buffer -around or before point. - -If second arg NEXT-P is t (interactively, with prefix arg), search for -another tag that matches the last tagname or regexp used. When there are -multiple matches for a tag, more exact matches are found first. If NEXT-P -is negative (interactively, with prefix arg that is a negative number or -just \\[negative-argument]), pop back to the previous tag gone to. - -See documentation of variable `tags-file-name'." - (interactive (find-tag-interactive "Find tag other window: ")) - - ;; This hair is to deal with the case where the tag is found in the - ;; selected window's buffer; without the hair, point is moved in both - ;; windows. To prevent this, we save the selected window's point before - ;; doing find-tag-noselect, and restore it after. - (let* ((window-point (window-point (selected-window))) - (tagbuf (find-tag-noselect tagname next-p regexp-p)) - (tagpoint (progn (set-buffer tagbuf) (point)))) - (set-window-point (prog1 - (selected-window) - (switch-to-buffer-other-window tagbuf) - ;; We have to set this new window's point; it - ;; might already have been displaying a - ;; different portion of tagbuf, in which case - ;; switch-to-buffer-other-window doesn't set - ;; the window's point from the buffer. - (set-window-point (selected-window) tagpoint)) - window-point))) -;;;###autoload (define-key ctl-x-4-map "." 'find-tag-other-window) - -;;;###autoload -(defun find-tag-other-frame (tagname &optional next-p) - "Find tag (in current tags table) whose name contains TAGNAME. -Select the buffer containing the tag's definition in another frame, and -move point there. The default for TAGNAME is the expression in the buffer -around or before point. - -If second arg NEXT-P is t (interactively, with prefix arg), search for -another tag that matches the last tagname or regexp used. When there are -multiple matches for a tag, more exact matches are found first. If NEXT-P -is negative (interactively, with prefix arg that is a negative number or -just \\[negative-argument]), pop back to the previous tag gone to. - -See documentation of variable `tags-file-name'." - (interactive (find-tag-interactive "Find tag other frame: ")) - (let ((pop-up-frames t)) - (find-tag-other-window tagname next-p))) -;;;###autoload (define-key ctl-x-5-map "." 'find-tag-other-frame) - -;;;###autoload -(defun find-tag-regexp (regexp &optional next-p other-window) - "Find tag (in current tags table) whose name matches REGEXP. -Select the buffer containing the tag's definition and move point there. - -If second arg NEXT-P is t (interactively, with prefix arg), search for -another tag that matches the last tagname or regexp used. When there are -multiple matches for a tag, more exact matches are found first. If NEXT-P -is negative (interactively, with prefix arg that is a negative number or -just \\[negative-argument]), pop back to the previous tag gone to. - -If third arg OTHER-WINDOW is non-nil, select the buffer in another window. - -See documentation of variable `tags-file-name'." - (interactive (find-tag-interactive "Find tag regexp: " t)) - ;; We go through find-tag-other-window to do all the display hair there. - (funcall (if other-window 'find-tag-other-window 'find-tag) - regexp next-p t)) - -;; Internal tag finding function. - -;; PATTERN is a string to pass to second arg SEARCH-FORWARD-FUNC, and to -;; any member of the function list ORDER (third arg). If ORDER is nil, -;; use saved state to continue a previous search. - -;; Fourth arg MATCHING is a string, an English '-ing' word, to be used in -;; an error message. - -;; Fifth arg NEXT-LINE-AFTER-FAILURE-P is non-nil if after a failed match, -;; point should be moved to the next line. - -;; Algorithm is as follows. For each qualifier-func in ORDER, go to -;; beginning of tags file, and perform inner loop: for each naive match for -;; PATTERN found using SEARCH-FORWARD-FUNC, qualify the naive match using -;; qualifier-func. If it qualifies, go to the specified line in the -;; specified source file and return. Qualified matches are remembered to -;; avoid repetition. State is saved so that the loop can be continued. - -(defun find-tag-in-order (pattern - search-forward-func - order - next-line-after-failure-p - matching - first-search) - (let (file ;name of file containing tag - tag-info ;where to find the tag in FILE - tags-table-file ;name of tags file - (first-table t) - (tag-order order) - goto-func - ) - (save-excursion - (or first-search ;find-tag-noselect has already done it. - (visit-tags-table-buffer 'same)) - - ;; Get a qualified match. - (catch 'qualified-match-found - - ;; Iterate over the list of tags tables. - (while (or first-table - (visit-tags-table-buffer t)) - - (if first-search - (setq tag-lines-already-matched nil)) - - (and first-search first-table - ;; Start at beginning of tags file. - (goto-char (point-min))) - (setq first-table nil) - - (setq tags-table-file buffer-file-name) - ;; Iterate over the list of ordering predicates. - (while order - (while (funcall search-forward-func pattern nil t) - ;; Naive match found. Qualify the match. - (and (funcall (car order) pattern) - ;; Make sure it is not a previous qualified match. - ;; Use of `memq' depends on numbers being eq. - (not (memq (save-excursion (beginning-of-line) (point)) - tag-lines-already-matched)) - (throw 'qualified-match-found nil)) - (if next-line-after-failure-p - (forward-line 1))) - ;; Try the next flavor of match. - (setq order (cdr order)) - (goto-char (point-min))) - (setq order tag-order)) - ;; We throw out on match, so only get here if there were no matches. - (error "No %stags %s %s" (if first-search "" "more ") - matching pattern)) - - ;; Found a tag; extract location info. - (beginning-of-line) - (setq tag-lines-already-matched (cons (point) - tag-lines-already-matched)) - ;; Expand the filename, using the tags table buffer's default-directory. - (setq file (expand-file-name (file-of-tag)) - tag-info (funcall snarf-tag-function)) - - ;; Get the local value in the tags table buffer before switching buffers. - (setq goto-func goto-tag-location-function) - - ;; Find the right line in the specified file. - (set-buffer (find-file-noselect file)) - (widen) - (push-mark) - (funcall goto-func tag-info) - - ;; Give this buffer a local value of tags-file-name. - ;; The next time visit-tags-table-buffer is called, - ;; it will use the same tags table that found a match in this buffer. - (make-local-variable 'tags-file-name) - (setq tags-file-name tags-table-file) - - ;; Return the buffer where the tag was found. - (current-buffer)))) - -;; `etags' TAGS file format support. - -;; If the current buffer is a valid etags TAGS file, give it local values of -;; the tags table format variables, and return non-nil. -(defun etags-recognize-tags-table () - (and (etags-verify-tags-table) - ;; It is annoying to flash messages on the screen briefly, - ;; and this message is not useful. -- rms - ;; (message "%s is an `etags' TAGS file" buffer-file-name) - (mapcar (function (lambda (elt) - (set (make-local-variable (car elt)) (cdr elt)))) - '((file-of-tag-function . etags-file-of-tag) - (tags-table-files-function . etags-tags-table-files) - (tags-completion-table-function . etags-tags-completion-table) - (snarf-tag-function . etags-snarf-tag) - (goto-tag-location-function . etags-goto-tag-location) - (find-tag-regexp-search-function . re-search-forward) - (find-tag-regexp-tag-order . (tag-re-match-p)) - (find-tag-regexp-next-line-after-failure-p . t) - (find-tag-search-function . search-forward) - (find-tag-tag-order . (tag-exact-match-p tag-word-match-p - tag-any-match-p)) - (find-tag-next-line-after-failure-p . nil) - (list-tags-function . etags-list-tags) - (tags-apropos-function . etags-tags-apropos) - (tags-included-tables-function . etags-tags-included-tables) - (verify-tags-table-function . etags-verify-tags-table) - )))) - -;; Return non-nil iff the current buffer is a valid etags TAGS file. -(defun etags-verify-tags-table () - ;; Use eq instead of = in case char-after returns nil. - (eq (char-after 1) ?\f)) - -(defun etags-file-of-tag () - (save-excursion - (search-backward "\f\n") - (forward-char 2) - (buffer-substring (point) - (progn (skip-chars-forward "^,") (point))))) - -(defun etags-tags-completion-table () - (let ((table (make-vector 511 0))) - (save-excursion - (goto-char (point-min)) - ;; This monster regexp matches an etags tag line. - ;; \1 is the string to match; - ;; \2 is not interesting; - ;; \3 is the guessed tag name; XXX guess should be better eg DEFUN - ;; \4 is not interesting; - ;; \5 is the explicitly-specified tag name. - ;; \6 is the line to start searching at; - ;; \7 is the char to start searching at. - (while (re-search-forward - "^\\(\\(.+[^-a-zA-Z0-9_$]+\\)?\\([-a-zA-Z0-9_$]+\\)\ -\[^-a-zA-Z0-9_$]*\\)\177\\(\\([^\n\001]+\\)\001\\)?\ -\\([0-9]+\\)?,\\([0-9]+\\)?\n" - nil t) - (intern (if (match-beginning 5) - ;; There is an explicit tag name. - (buffer-substring (match-beginning 5) (match-end 5)) - ;; No explicit tag name. Best guess. - (buffer-substring (match-beginning 3) (match-end 3))) - table))) - table)) - -(defun etags-snarf-tag () - (let (tag-text line startpos) - (search-forward "\177") - (setq tag-text (buffer-substring (1- (point)) - (save-excursion (beginning-of-line) - (point)))) - ;; Skip explicit tag name if present. - (search-forward "\001" (save-excursion (forward-line 1) (point)) t) - (if (looking-at "[0-9]") - (setq line (string-to-int (buffer-substring - (point) - (progn (skip-chars-forward "0-9") - (point)))))) - (search-forward ",") - (if (looking-at "[0-9]") - (setq startpos (string-to-int (buffer-substring - (point) - (progn (skip-chars-forward "0-9") - (point)))))) - ;; Leave point on the next line of the tags file. - (forward-line 1) - (cons tag-text (cons line startpos)))) - -;; TAG-INFO is a cons (TEXT LINE . POSITION) where TEXT is the initial part -;; of a line containing the tag and POSITION is the character position of -;; TEXT within the file (starting from 1); LINE is the line number. Either -;; LINE or POSITION may be nil; POSITION is used if present. If the tag -;; isn't exactly at the given position then look around that position using -;; a search window which expands until it hits the start of file. -(defun etags-goto-tag-location (tag-info) - (let ((startpos (cdr (cdr tag-info))) - ;; This constant is 1/2 the initial search window. - ;; There is no sense in making it too small, - ;; since just going around the loop once probably - ;; costs about as much as searching 2000 chars. - (offset 1000) - (found nil) - (pat (concat (if (eq selective-display t) - "\\(^\\|\^m\\)" "^") - (regexp-quote (car tag-info))))) - ;; If no char pos was given, try the given line number. - (or startpos - (if (car (cdr tag-info)) - (setq startpos (progn (goto-line (car (cdr tag-info))) - (point))))) - (or startpos - (setq startpos (point-min))) - ;; First see if the tag is right at the specified location. - (goto-char startpos) - (setq found (looking-at pat)) - (while (and (not found) - (progn - (goto-char (- startpos offset)) - (not (bobp)))) - (setq found - (re-search-forward pat (+ startpos offset) t) - offset (* 3 offset))) ; expand search window - (or found - (re-search-forward pat nil t) - (error "Rerun etags: `%s' not found in %s" - pat buffer-file-name))) - ;; Position point at the right place - ;; if the search string matched an extra Ctrl-m at the beginning. - (and (eq selective-display t) - (looking-at "\^m") - (forward-char 1)) - (beginning-of-line)) - -(defun etags-list-tags (file) - (goto-char 1) - (if (not (search-forward (concat "\f\n" file ",") nil t)) - nil - (forward-line 1) - (while (not (or (eobp) (looking-at "\f"))) - (let ((tag (buffer-substring (point) - (progn (skip-chars-forward "^\177") - (point))))) - (princ (if (looking-at "[^\n]+\001") - ;; There is an explicit tag name; use that. - (buffer-substring (point) - (progn (skip-chars-forward "^\001") - (point))) - tag))) - (terpri) - (forward-line 1)) - t)) - -(defun etags-tags-apropos (string) - (goto-char 1) - (while (re-search-forward string nil t) - (beginning-of-line) - (princ (buffer-substring (point) - (progn (skip-chars-forward "^\177") - (point)))) - (terpri) - (forward-line 1))) - -(defun etags-tags-table-files () - (let ((files nil) - beg) - (goto-char (point-min)) - (while (search-forward "\f\n" nil t) - (setq beg (point)) - (skip-chars-forward "^,\n") - (or (looking-at ",include$") - ;; Expand in the default-directory of the tags table buffer. - (setq files (cons (expand-file-name (buffer-substring beg (point))) - files)))) - (nreverse files))) - -(defun etags-tags-included-tables () - (let ((files nil) - beg) - (goto-char (point-min)) - (while (search-forward "\f\n" nil t) - (setq beg (point)) - (skip-chars-forward "^,\n") - (if (looking-at ",include$") - ;; Expand in the default-directory of the tags table buffer. - (setq files (cons (expand-file-name (buffer-substring beg (point))) - files)))) - (nreverse files))) - -;; Empty tags file support. - -;; Recognize an empty file and give it local values of the tags table format -;; variables which do nothing. -(defun recognize-empty-tags-table () - (and (zerop (buffer-size)) - (mapcar (function (lambda (sym) - (set (make-local-variable sym) 'ignore))) - '(tags-table-files-function - tags-completion-table-function - find-tag-regexp-search-function - find-tag-search-function - tags-apropos-function - tags-included-tables-function)) - (set (make-local-variable 'verify-tags-table-function) - (function (lambda () - (zerop (buffer-size))))))) - -;;; Match qualifier functions for tagnames. -;;; XXX these functions assume etags file format. - -;; This might be a neat idea, but it's too hairy at the moment. -;;(defmacro tags-with-syntax (&rest body) -;; (` (let ((current (current-buffer)) -;; (otable (syntax-table)) -;; (buffer (find-file-noselect (file-of-tag))) -;; table) -;; (unwind-protect -;; (progn -;; (set-buffer buffer) -;; (setq table (syntax-table)) -;; (set-buffer current) -;; (set-syntax-table table) -;; (,@ body)) -;; (set-syntax-table otable))))) -;;(put 'tags-with-syntax 'edebug-form-spec '(&rest form)) - -;; t if point is at a tag line that matches TAG "exactly". -;; point should be just after a string that matches TAG. -(defun tag-exact-match-p (tag) - ;; The match is really exact if there is an explicit tag name. - (or (looking-at (concat "[^\177]*\177" (regexp-quote tag) "\001")) - ;; We also call it "exact" if it is surrounded by symbol boundaries. - ;; This is needed because etags does not always generate explicit names. - (and (looking-at "\\Sw.*\177") (looking-at "\\S_.*\177") - (save-excursion - (backward-char (1+ (length tag))) - (and (looking-at "\\Sw") (looking-at "\\S_")))))) - -;; t if point is at a tag line that matches TAG as a word. -;; point should be just after a string that matches TAG. -(defun tag-word-match-p (tag) - (and (looking-at "\\b.*\177") - (save-excursion (backward-char (1+ (length tag))) - (looking-at "\\b")))) - -;; t if point is in a tag line with a tag containing TAG as a substring. -(defun tag-any-match-p (tag) - (looking-at ".*\177")) - -;; t if point is at a tag line that matches RE as a regexp. -(defun tag-re-match-p (re) - (save-excursion - (beginning-of-line) - (let ((bol (point))) - (and (search-forward "\177" (save-excursion (end-of-line) (point)) t) - (re-search-backward re bol t))))) - -;;;###autoload -(defun next-file (&optional initialize novisit) - "Select next file among files in current tags table. - -A first argument of t (prefix arg, if interactive) initializes to the -beginning of the list of files in the tags table. If the argument is -neither nil nor t, it is evalled to initialize the list of files. - -Non-nil second argument NOVISIT means use a temporary buffer - to save time and avoid uninteresting warnings. - -Value is nil if the file was already visited; -if the file was newly read in, the value is the filename." - (interactive "P") - (cond ((not initialize) - ;; Not the first run. - ) - ((eq initialize t) - ;; Initialize the list from the tags table. - (save-excursion - ;; Visit the tags table buffer to get its list of files. - (visit-tags-table-buffer) - (setq next-file-list (tags-table-files)))) - (t - ;; Initialize the list by evalling the argument. - (setq next-file-list (eval initialize)))) - (or next-file-list - (save-excursion - ;; Get the files from the next tags table. - ;; When doing (visit-tags-table-buffer t), - ;; the tags table buffer must be current. - (if (and (visit-tags-table-buffer 'same) - (visit-tags-table-buffer t)) - (setq next-file-list (tags-table-files)) - (and novisit - (get-buffer " *next-file*") - (kill-buffer " *next-file*")) - (error "All files processed.")))) - (let ((new (not (get-file-buffer (car next-file-list))))) - (if (not (and new novisit)) - (set-buffer (find-file-noselect (car next-file-list) novisit)) - ;; Like find-file, but avoids random warning messages. - (set-buffer (get-buffer-create " *next-file*")) - (kill-all-local-variables) - (erase-buffer) - (setq new (car next-file-list)) - (insert-file-contents new nil)) - (setq next-file-list (cdr next-file-list)) - new)) - -(defvar tags-loop-operate nil - "Form for `tags-loop-continue' to eval to change one file.") - -(defvar tags-loop-scan - '(error (substitute-command-keys - "No \\[tags-search] or \\[tags-query-replace] in progress.")) - "Form for `tags-loop-continue' to eval to scan one file. -If it returns non-nil, this file needs processing by evalling -\`tags-loop-operate'. Otherwise, move on to the next file.") - -;;;###autoload -(defun tags-loop-continue (&optional first-time) - "Continue last \\[tags-search] or \\[tags-query-replace] command. -Used noninteractively with non-nil argument to begin such a command (the -argument is passed to `next-file', which see). -Two variables control the processing we do on each file: -the value of `tags-loop-scan' is a form to be executed on each file -to see if it is interesting (it returns non-nil if so) -and `tags-loop-operate' is a form to execute to operate on an interesting file -If the latter returns non-nil, we exit; otherwise we scan the next file." - (interactive) - (let (new - (messaged nil)) - (while - (progn - ;; Scan files quickly for the first or next interesting one. - (while (or first-time - (save-restriction - (widen) - (not (eval tags-loop-scan)))) - (setq new (next-file first-time t)) - ;; If NEW is non-nil, we got a temp buffer, - ;; and NEW is the file name. - (if (or messaged - (and (not first-time) - (> baud-rate search-slow-speed) - (setq messaged t))) - (message "Scanning file %s..." (or new buffer-file-name))) - (setq first-time nil) - (goto-char (point-min))) - - ;; If we visited it in a temp buffer, visit it now for real. - (if new - (let ((pos (point))) - (erase-buffer) - (set-buffer (find-file-noselect new)) - (widen) - (goto-char pos))) - - (switch-to-buffer (current-buffer)) - - ;; Now operate on the file. - ;; If value is non-nil, continue to scan the next file. - (eval tags-loop-operate))) - (and messaged - (null tags-loop-operate) - (message "Scanning file %s...found" buffer-file-name)))) -;;;###autoload (define-key esc-map "," 'tags-loop-continue) - -;;;###autoload -(defun tags-search (regexp &optional file-list-form) - "Search through all files listed in tags table for match for REGEXP. -Stops when a match is found. -To continue searching for next match, use command \\[tags-loop-continue]. - -See documentation of variable `tags-file-name'." - (interactive "sTags search (regexp): ") - (if (and (equal regexp "") - (eq (car tags-loop-scan) 're-search-forward) - (null tags-loop-operate)) - ;; Continue last tags-search as if by M-,. - (tags-loop-continue nil) - (setq tags-loop-scan - (list 're-search-forward regexp nil t) - tags-loop-operate nil) - (tags-loop-continue (or file-list-form t)))) - -;;;###autoload -(defun tags-query-replace (from to &optional delimited file-list-form) - "Query-replace-regexp FROM with TO through all files listed in tags table. -Third arg DELIMITED (prefix arg) means replace only word-delimited matches. -If you exit (\\[keyboard-quit] or ESC), you can resume the query-replace -with the command \\[tags-loop-continue]. - -See documentation of variable `tags-file-name'." - (interactive - "sTags query replace (regexp): \nsTags query replace %s by: \nP") - (setq tags-loop-scan (list 'prog1 - (list 'if (list 're-search-forward from nil t) - ;; When we find a match, move back - ;; to the beginning of it so perform-replace - ;; will see it. - '(goto-char (match-beginning 0)))) - tags-loop-operate (list 'perform-replace from to t t delimited)) - (tags-loop-continue (or file-list-form t))) - -;;;###autoload -(defun list-tags (file) - "Display list of tags in file FILE. -FILE should not contain a directory specification." - (interactive (list (completing-read "List tags in file: " - (save-excursion - (visit-tags-table-buffer) - (mapcar 'list - (mapcar 'file-name-nondirectory - (tags-table-files)))) - nil t nil))) - (with-output-to-temp-buffer "*Tags List*" - (princ "Tags in file ") - (princ file) - (terpri) - (save-excursion - (let ((first-time t) - (gotany nil)) - (while (visit-tags-table-buffer (not first-time)) - (setq first-time nil) - (if (funcall list-tags-function file) - (setq gotany t))) - (or gotany - (error "File %s not in current tags tables" file)))))) - -;;;###autoload -(defun tags-apropos (regexp) - "Display list of all tags in tags table REGEXP matches." - (interactive "sTags apropos (regexp): ") - (with-output-to-temp-buffer "*Tags List*" - (princ "Tags matching regexp ") - (prin1 regexp) - (terpri) - (save-excursion - (let ((first-time t)) - (while (visit-tags-table-buffer (not first-time)) - (setq first-time nil) - (funcall tags-apropos-function regexp)))))) - -;;; XXX Kludge interface. - -;; XXX If a file is in multiple tables, selection may get the wrong one. -;;;###autoload -(defun select-tags-table () - "Select a tags table file from a menu of those you have already used. -The list of tags tables to select from is stored in `tags-table-file-list'; -see the doc of that variable if you want to add names to the list." - (interactive) - (pop-to-buffer "*Tags Table List*") - (setq buffer-read-only nil) - (erase-buffer) - (setq selective-display t - selective-display-ellipses nil) - (let ((set-list tags-table-set-list) - (desired-point nil)) - (if tags-table-list - (progn - (setq desired-point (point-marker)) - (princ tags-table-list (current-buffer)) - (insert "\C-m") - (prin1 (car tags-table-list) (current-buffer)) ;invisible - (insert "\n"))) - (while set-list - (if (eq (car set-list) tags-table-list) - ;; Already printed it. - () - (princ (car set-list) (current-buffer)) - (insert "\C-m") - (prin1 (car (car set-list)) (current-buffer)) ;invisible - (insert "\n")) - (setq set-list (cdr set-list))) - (if tags-file-name - (progn - (or desired-point - (setq desired-point (point-marker))) - (insert tags-file-name "\C-m") - (prin1 tags-file-name (current-buffer)) ;invisible - (insert "\n"))) - (setq set-list (delete tags-file-name - (apply 'nconc (cons tags-table-list - (mapcar 'copy-sequence - tags-table-set-list))))) - (while set-list - (insert (car set-list) "\C-m") - (prin1 (car set-list) (current-buffer)) ;invisible - (insert "\n") - (setq set-list (delete (car set-list) set-list))) - (goto-char 1) - (insert-before-markers - "Type `t' to select a tags table or set of tags tables:\n\n") - (if desired-point - (goto-char desired-point)) - (set-window-start (selected-window) 1 t)) - (set-buffer-modified-p nil) - (setq buffer-read-only t - mode-name "Select Tags Table") - (let ((map (make-sparse-keymap))) - (define-key map "t" 'select-tags-table-select) - (define-key map " " 'next-line) - (define-key map "\^?" 'previous-line) - (define-key map "n" 'next-line) - (define-key map "p" 'previous-line) - (define-key map "q" 'select-tags-table-quit) - (use-local-map map))) - -(defun select-tags-table-select () - "Select the tags table named on this line." - (interactive) - (search-forward "\C-m") - (let ((name (read (current-buffer)))) - (visit-tags-table name) - (select-tags-table-quit) - (message "Tags table now %s" name))) - -(defun select-tags-table-quit () - "Kill the buffer and delete the selected window." - (interactive) - (kill-buffer (current-buffer)) - (or (one-window-p) - (delete-window))) - -;;;###autoload -(defun complete-tag () - "Perform tags completion on the text around point. -Completes to the set of names listed in the current tags table. -The string to complete is chosen in the same way as the default -for \\[find-tag] (which see)." - (interactive) - (or tags-table-list - tags-file-name - (error (substitute-command-keys - "No tags table loaded. Try \\[visit-tags-table]."))) - (let ((pattern (funcall (or find-tag-default-function - (get major-mode 'find-tag-default-function) - 'find-tag-default))) - beg - completion) - (or pattern - (error "Nothing to complete")) - (search-backward pattern) - (setq beg (point)) - (forward-char (length pattern)) - (setq completion (try-completion pattern 'tags-complete-tag nil)) - (cond ((eq completion t)) - ((null completion) - (message "Can't find completion for \"%s\"" pattern) - (ding)) - ((not (string= pattern completion)) - (delete-region beg (point)) - (insert completion)) - (t - (message "Making completion list...") - (with-output-to-temp-buffer " *Completions*" - (display-completion-list - (all-completions pattern 'tags-complete-tag nil))) - (message "Making completion list...%s" "done"))))) - -;;;###autoload (define-key esc-map "\t" 'complete-tag) - -(provide 'etags) - -;;; etags.el ends here diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el deleted file mode 100644 index 462f38b29b4..00000000000 --- a/lisp/progmodes/fortran.el +++ /dev/null @@ -1,1292 +0,0 @@ -;;; fortran.el --- Fortran mode for GNU Emacs - -;;; Copyright (c) 1986, 1993, 1994 Free Software Foundation, Inc. - -;; Author: Michael D. Prange <prange@erl.mit.edu> -;; Maintainer: bug-fortran-mode@erl.mit.edu -;; Version 1.30.4 (January 20, 1994) -;; Keywords: languages - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; Fortran mode has been upgraded and is now maintained by Stephen A. Wood -;; (saw@cebaf.gov). It now will use either fixed format continuation line -;; markers (character in 6th column), or tab format continuation line style -;; (digit after a TAB character.) A auto-fill mode has been added to -;; automatically wrap fortran lines that get too long. - -;; We acknowledge many contributions and valuable suggestions by -;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea, -;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon, -;; Gary Sabot and Richard Stallman. - -;;; This file may be used with GNU Emacs version 18.xx if the following -;;; variable and function substitutions are made. -;;; Replace: -;;; frame-width with screen-width -;;; auto-fill-function with auto-fill-hook -;;; comment-indent-function with comment-indent-hook -;;; (setq unread-command-events (list c)) with (setq unread-command-char c) - -;;; Bugs to bug-fortran-mode@erl.mit.edu - -(defconst fortran-mode-version "version 1.30.4") - -;;; Code: - -;;;###autoload -(defvar fortran-tab-mode-default nil - "*Default tabbing/carriage control style for empty files in Fortran mode. -A value of t specifies tab-digit style of continuation control. -A value of nil specifies that continuation lines are marked -with a character in column 6.") - -;; Buffer local, used to display mode line. -(defvar fortran-tab-mode-string nil - "String to appear in mode line when TAB format mode is on.") - -(defvar fortran-do-indent 3 - "*Extra indentation applied to DO blocks.") - -(defvar fortran-if-indent 3 - "*Extra indentation applied to IF blocks.") - -(defvar fortran-structure-indent 3 - "*Extra indentation applied to STRUCTURE, UNION, MAP and INTERFACE blocks.") - -(defvar fortran-continuation-indent 5 - "*Extra indentation applied to Fortran continuation lines.") - -(defvar fortran-comment-indent-style 'fixed - "*nil forces comment lines not to be touched, -'fixed makes fixed comment indentation to `fortran-comment-line-extra-indent' -columns beyond `fortran-minimum-statement-indent-fixed' (for -`indent-tabs-mode' of nil) or `fortran-minimum-statement-indent-tab' (for -`indent-tabs-mode' of t), and 'relative indents to current -Fortran indentation plus `fortran-comment-line-extra-indent'.") - -(defvar fortran-comment-line-extra-indent 0 - "*Amount of extra indentation for text within full-line comments.") - -(defvar comment-line-start nil - "*Delimiter inserted to start new full-line comment.") - -(defvar comment-line-start-skip nil - "*Regexp to match the start of a full-line comment.") - -(defvar fortran-minimum-statement-indent-fixed 6 - "*Minimum statement indentation for fixed format continuation style.") - -(defvar fortran-minimum-statement-indent-tab (max tab-width 6) - "*Minimum statement indentation for TAB format continuation style.") - -;; Note that this is documented in the v18 manuals as being a string -;; of length one rather than a single character. -;; The code in this file accepts either format for compatibility. -(defvar fortran-comment-indent-char " " - "*Single-character string inserted for Fortran comment indentation. -Normally a space.") - -(defvar fortran-line-number-indent 1 - "*Maximum indentation for Fortran line numbers. -5 means right-justify them within their five-column field.") - -(defvar fortran-check-all-num-for-matching-do nil - "*Non-nil causes all numbered lines to be treated as possible DO loop ends.") - -(defvar fortran-blink-matching-if nil - "*From a Fortran ENDIF statement, blink the matching IF statement. -Also, from an ENDDO statement, blink on matching DO [WHILE] statement.") - -(defvar fortran-continuation-string "$" - "*Single-character string used for Fortran continuation lines. -In fixed format continuation style, this character is inserted in -column 6 by \\[fortran-split-line] to begin a continuation line. -Also, if \\[fortran-indent-line] finds this at the beginning of a line, it will -convert the line into a continuation line of the appropriate style. -Normally $.") - -(defvar fortran-comment-region "c$$$" - "*String inserted by \\[fortran-comment-region]\ - at start of each line in region.") - -(defvar fortran-electric-line-number t - "*Non-nil causes line number digits to be moved to the correct column as\ - typed.") - -(defvar fortran-startup-message t - "*Non-nil displays a startup message when Fortran mode is first called.") - -(defvar fortran-column-ruler-fixed - "0 4 6 10 20 30 40 5\ -0 60 70\n\ -[ ]|{ | | | | | | | | \ -| | | | |}\n" - "*String displayed above current line by \\[fortran-column-ruler]. -This variable used in fixed format mode.") - -(defvar fortran-column-ruler-tab - "0 810 20 30 40 5\ -0 60 70\n\ -[ ]| { | | | | | | | | \ -| | | | |}\n" - "*String displayed above current line by \\[fortran-column-ruler]. -This variable used in TAB format mode.") - -(defconst bug-fortran-mode "bug-fortran-mode@erl.mit.edu" - "Address of mailing list for Fortran mode bugs.") - -(defvar fortran-mode-syntax-table nil - "Syntax table in use in Fortran mode buffers.") - -(defvar fortran-analyze-depth 100 - "Number of lines to scan to determine whether to use fixed or TAB format\ - style.") - -(defvar fortran-break-before-delimiters t - "*Non-nil causes `fortran-do-auto-fill' to break lines before delimiters.") - -(if fortran-mode-syntax-table - () - (setq fortran-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\; "w" fortran-mode-syntax-table) - (modify-syntax-entry ?\r " " fortran-mode-syntax-table) - (modify-syntax-entry ?+ "." fortran-mode-syntax-table) - (modify-syntax-entry ?- "." fortran-mode-syntax-table) - (modify-syntax-entry ?= "." fortran-mode-syntax-table) - (modify-syntax-entry ?* "." fortran-mode-syntax-table) - (modify-syntax-entry ?/ "." fortran-mode-syntax-table) - (modify-syntax-entry ?\' "\"" fortran-mode-syntax-table) - (modify-syntax-entry ?\" "\"" fortran-mode-syntax-table) - (modify-syntax-entry ?\\ "/" fortran-mode-syntax-table) - (modify-syntax-entry ?. "w" fortran-mode-syntax-table) - (modify-syntax-entry ?_ "w" fortran-mode-syntax-table) - (modify-syntax-entry ?\n ">" fortran-mode-syntax-table)) - -(defvar fortran-mode-map () - "Keymap used in Fortran mode.") -(if fortran-mode-map - () - (setq fortran-mode-map (make-sparse-keymap)) - (define-key fortran-mode-map ";" 'fortran-abbrev-start) - (define-key fortran-mode-map "\C-c;" 'fortran-comment-region) - (define-key fortran-mode-map "\e\C-a" 'beginning-of-fortran-subprogram) - (define-key fortran-mode-map "\e\C-e" 'end-of-fortran-subprogram) - (define-key fortran-mode-map "\e;" 'fortran-indent-comment) - (define-key fortran-mode-map "\e\C-h" 'mark-fortran-subprogram) - (define-key fortran-mode-map "\e\n" 'fortran-split-line) - (define-key fortran-mode-map "\n" 'fortran-indent-new-line) - (define-key fortran-mode-map "\e\C-q" 'fortran-indent-subprogram) - (define-key fortran-mode-map "\C-c\C-w" 'fortran-window-create-momentarily) - (define-key fortran-mode-map "\C-c\C-r" 'fortran-column-ruler) - (define-key fortran-mode-map "\C-c\C-p" 'fortran-previous-statement) - (define-key fortran-mode-map "\C-c\C-n" 'fortran-next-statement) - (define-key fortran-mode-map "\t" 'fortran-indent-line) - (define-key fortran-mode-map "0" 'fortran-electric-line-number) - (define-key fortran-mode-map "1" 'fortran-electric-line-number) - (define-key fortran-mode-map "2" 'fortran-electric-line-number) - (define-key fortran-mode-map "3" 'fortran-electric-line-number) - (define-key fortran-mode-map "4" 'fortran-electric-line-number) - (define-key fortran-mode-map "5" 'fortran-electric-line-number) - (define-key fortran-mode-map "6" 'fortran-electric-line-number) - (define-key fortran-mode-map "7" 'fortran-electric-line-number) - (define-key fortran-mode-map "8" 'fortran-electric-line-number) - (define-key fortran-mode-map "9" 'fortran-electric-line-number)) - -(defvar fortran-mode-abbrev-table nil) -(if fortran-mode-abbrev-table - () - (let ((ac abbrevs-changed)) - (define-abbrev-table 'fortran-mode-abbrev-table ()) - (define-abbrev fortran-mode-abbrev-table ";au" "automatic" nil) - (define-abbrev fortran-mode-abbrev-table ";b" "byte" nil) - (define-abbrev fortran-mode-abbrev-table ";bd" "block data" nil) - (define-abbrev fortran-mode-abbrev-table ";ch" "character" nil) - (define-abbrev fortran-mode-abbrev-table ";cl" "close" nil) - (define-abbrev fortran-mode-abbrev-table ";c" "continue" nil) - (define-abbrev fortran-mode-abbrev-table ";cm" "common" nil) - (define-abbrev fortran-mode-abbrev-table ";cx" "complex" nil) - (define-abbrev fortran-mode-abbrev-table ";df" "define" nil) - (define-abbrev fortran-mode-abbrev-table ";di" "dimension" nil) - (define-abbrev fortran-mode-abbrev-table ";do" "double" nil) - (define-abbrev fortran-mode-abbrev-table ";dc" "double complex" nil) - (define-abbrev fortran-mode-abbrev-table ";dp" "double precision" nil) - (define-abbrev fortran-mode-abbrev-table ";dw" "do while" nil) - (define-abbrev fortran-mode-abbrev-table ";e" "else" nil) - (define-abbrev fortran-mode-abbrev-table ";ed" "enddo" nil) - (define-abbrev fortran-mode-abbrev-table ";el" "elseif" nil) - (define-abbrev fortran-mode-abbrev-table ";en" "endif" nil) - (define-abbrev fortran-mode-abbrev-table ";eq" "equivalence" nil) - (define-abbrev fortran-mode-abbrev-table ";ew" "endwhere" nil) - (define-abbrev fortran-mode-abbrev-table ";ex" "external" nil) - (define-abbrev fortran-mode-abbrev-table ";ey" "entry" nil) - (define-abbrev fortran-mode-abbrev-table ";f" "format" nil) - (define-abbrev fortran-mode-abbrev-table ";fa" ".false." nil) - (define-abbrev fortran-mode-abbrev-table ";fu" "function" nil) - (define-abbrev fortran-mode-abbrev-table ";g" "goto" nil) - (define-abbrev fortran-mode-abbrev-table ";im" "implicit" nil) - (define-abbrev fortran-mode-abbrev-table ";ib" "implicit byte" nil) - (define-abbrev fortran-mode-abbrev-table ";ic" "implicit complex" nil) - (define-abbrev fortran-mode-abbrev-table ";ich" "implicit character" nil) - (define-abbrev fortran-mode-abbrev-table ";ii" "implicit integer" nil) - (define-abbrev fortran-mode-abbrev-table ";il" "implicit logical" nil) - (define-abbrev fortran-mode-abbrev-table ";ir" "implicit real" nil) - (define-abbrev fortran-mode-abbrev-table ";inc" "include" nil) - (define-abbrev fortran-mode-abbrev-table ";in" "integer" nil) - (define-abbrev fortran-mode-abbrev-table ";intr" "intrinsic" nil) - (define-abbrev fortran-mode-abbrev-table ";l" "logical" nil) - (define-abbrev fortran-mode-abbrev-table ";n" "namelist" nil) - (define-abbrev fortran-mode-abbrev-table ";o" "open" nil) ; was ;op - (define-abbrev fortran-mode-abbrev-table ";pa" "parameter" nil) - (define-abbrev fortran-mode-abbrev-table ";pr" "program" nil) - (define-abbrev fortran-mode-abbrev-table ";ps" "pause" nil) - (define-abbrev fortran-mode-abbrev-table ";p" "print" nil) - (define-abbrev fortran-mode-abbrev-table ";rc" "record" nil) - (define-abbrev fortran-mode-abbrev-table ";re" "real" nil) - (define-abbrev fortran-mode-abbrev-table ";r" "read" nil) - (define-abbrev fortran-mode-abbrev-table ";rt" "return" nil) - (define-abbrev fortran-mode-abbrev-table ";rw" "rewind" nil) - (define-abbrev fortran-mode-abbrev-table ";s" "stop" nil) - (define-abbrev fortran-mode-abbrev-table ";sa" "save" nil) - (define-abbrev fortran-mode-abbrev-table ";st" "structure" nil) - (define-abbrev fortran-mode-abbrev-table ";sc" "static" nil) - (define-abbrev fortran-mode-abbrev-table ";su" "subroutine" nil) - (define-abbrev fortran-mode-abbrev-table ";tr" ".true." nil) - (define-abbrev fortran-mode-abbrev-table ";ty" "type" nil) - (define-abbrev fortran-mode-abbrev-table ";vo" "volatile" nil) - (define-abbrev fortran-mode-abbrev-table ";w" "write" nil) - (define-abbrev fortran-mode-abbrev-table ";wh" "where" nil) - (setq abbrevs-changed ac))) - -;;;###autoload -(defun fortran-mode () - "Major mode for editing Fortran code. -\\[fortran-indent-line] indents the current Fortran line correctly. -DO statements must not share a common CONTINUE. - -Type ;? or ;\\[help-command] to display a list of built-in\ - abbrevs for Fortran keywords. - -Key definitions: -\\{fortran-mode-map} - -Variables controlling indentation style and extra features: - - comment-start - Normally nil in Fortran mode. If you want to use comments - starting with `!', set this to the string \"!\". - fortran-do-indent - Extra indentation within do blocks. (default 3) - fortran-if-indent - Extra indentation within if blocks. (default 3) - fortran-structure-indent - Extra indentation within structure, union, map and interface blocks. - (default 3) - fortran-continuation-indent - Extra indentation applied to continuation statements. (default 5) - fortran-comment-line-extra-indent - Amount of extra indentation for text within full-line comments. (default 0) - fortran-comment-indent-style - nil means don't change indentation of text in full-line comments, - fixed means indent that text at `fortran-comment-line-extra-indent' beyond - the value of `fortran-minimum-statement-indent-fixed' (for fixed - format continuation style) or `fortran-minimum-statement-indent-tab' - (for TAB format continuation style). - relative means indent at `fortran-comment-line-extra-indent' beyond the - indentation for a line of code. - (default 'fixed) - fortran-comment-indent-char - Single-character string to be inserted instead of space for - full-line comment indentation. (default \" \") - fortran-minimum-statement-indent-fixed - Minimum indentation for Fortran statements in fixed format mode. (def.6) - fortran-minimum-statement-indent-tab - Minimum indentation for Fortran statements in TAB format mode. (default 9) - fortran-line-number-indent - Maximum indentation for line numbers. A line number will get - less than this much indentation if necessary to avoid reaching - column 5. (default 1) - fortran-check-all-num-for-matching-do - Non-nil causes all numbered lines to be treated as possible \"continue\" - statements. (default nil) - fortran-blink-matching-if - From a Fortran ENDIF statement, blink the matching IF statement. - Also, from an ENDDO statement, blink on matching DO [WHILE] statement. - (default nil) - fortran-continuation-string - Single-character string to be inserted in column 5 of a continuation - line. (default \"$\") - fortran-comment-region - String inserted by \\[fortran-comment-region] at start of each line in - region. (default \"c$$$\") - fortran-electric-line-number - Non-nil causes line number digits to be moved to the correct column - as typed. (default t) - fortran-break-before-delimiters - Non-nil causes `fortran-do-auto-fill' breaks lines before delimiters. - (default t) - fortran-startup-message - Set to nil to inhibit message first time Fortran mode is used. - -Turning on Fortran mode calls the value of the variable `fortran-mode-hook' -with no args, if that value is non-nil." - (interactive) - (kill-all-local-variables) - (if fortran-startup-message - (message "Emacs Fortran mode %s. Bugs to %s" - fortran-mode-version bug-fortran-mode)) - (setq fortran-startup-message nil) - (setq local-abbrev-table fortran-mode-abbrev-table) - (set-syntax-table fortran-mode-syntax-table) - (make-local-variable 'fortran-break-before-delimiters) - (setq fortran-break-before-delimiters t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'fortran-indent-line) - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'fortran-comment-hook) - (make-local-variable 'comment-line-start-skip) - (setq comment-line-start-skip - "^[Cc*]\\(\\([^ \t\n]\\)\\2\\2*\\)?[ \t]*\\|^#.*") - (make-local-variable 'comment-line-start) - (setq comment-line-start "c") - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "![ \t]*") - (make-local-variable 'comment-start) - (setq comment-start nil) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'abbrev-all-caps) - (setq abbrev-all-caps t) - (make-local-variable 'indent-tabs-mode) - (setq indent-tabs-mode nil) -;;;(setq abbrev-mode t) ; ?? (abbrev-mode 1) instead?? - (setq fill-column 72) ; Already local? - (use-local-map fortran-mode-map) - (setq mode-name "Fortran") - (setq major-mode 'fortran-mode) -;;;(make-local-variable 'fortran-tab-mode) - (make-local-variable 'fortran-comment-line-extra-indent) - (make-local-variable 'fortran-minimum-statement-indent-fixed) - (make-local-variable 'fortran-minimum-statement-indent-tab) - (make-local-variable 'fortran-column-ruler-fixed) - (make-local-variable 'fortran-column-ruler-tab) - (make-local-variable 'fortran-tab-mode-string) - (setq fortran-tab-mode-string " TAB-format") - (setq indent-tabs-mode (fortran-analyze-file-format)) - (run-hooks 'fortran-mode-hook)) - -(defun fortran-comment-hook () - (save-excursion - (skip-chars-backward " \t") - (max (+ 1 (current-column)) - comment-column))) - -(defun fortran-indent-comment () - "Align or create comment on current line. -Existing comments of all types are recognized and aligned. -If the line has no comment, a side-by-side comment is inserted and aligned -if the value of comment-start is not nil. -Otherwise, a separate-line comment is inserted, on this line -or on a new line inserted before this line if this line is not blank." - (interactive) - (beginning-of-line) - ;; Recognize existing comments of either kind. - (cond ((looking-at comment-line-start-skip) - (fortran-indent-line)) - ((fortran-find-comment-start-skip) ; catches any inline comment and - ; leaves point after comment-start-skip - (if comment-start-skip - (progn (goto-char (match-beginning 0)) - (if (not (= (current-column) (fortran-comment-hook))) - (progn (delete-horizontal-space) - (indent-to (fortran-comment-hook))))) - (end-of-line))) ; otherwise goto end of line or sth else? - ;; No existing comment. - ;; If side-by-side comments are defined, insert one, - ;; unless line is now blank. - ((and comment-start (not (looking-at "^[ \t]*$"))) - (end-of-line) - (delete-horizontal-space) - (indent-to (fortran-comment-hook)) - (insert comment-start)) - ;; Else insert separate-line comment, making a new line if nec. - (t - (if (looking-at "^[ \t]*$") - (delete-horizontal-space) - (beginning-of-line) - (insert "\n") - (forward-char -1)) - (insert comment-line-start) - (insert-char (if (stringp fortran-comment-indent-char) - (aref fortran-comment-indent-char 0) - fortran-comment-indent-char) - (- (calculate-fortran-indent) (current-column)))))) - -(defun fortran-comment-region (beg-region end-region arg) - "Comments every line in the region. -Puts fortran-comment-region at the beginning of every line in the region. -BEG-REGION and END-REGION are args which specify the region boundaries. -With non-nil ARG, uncomments the region." - (interactive "*r\nP") - (let ((end-region-mark (make-marker)) (save-point (point-marker))) - (set-marker end-region-mark end-region) - (goto-char beg-region) - (beginning-of-line) - (if (not arg) ;comment the region - (progn (insert fortran-comment-region) - (while (and (= (forward-line 1) 0) - (< (point) end-region-mark)) - (insert fortran-comment-region))) - (let ((com (regexp-quote fortran-comment-region))) ;uncomment the region - (if (looking-at com) - (delete-region (point) (match-end 0))) - (while (and (= (forward-line 1) 0) - (< (point) end-region-mark)) - (if (looking-at com) - (delete-region (point) (match-end 0)))))) - (goto-char save-point) - (set-marker end-region-mark nil) - (set-marker save-point nil))) - -(defun fortran-abbrev-start () - "Typing ;\\[help-command] or ;? lists all the Fortran abbrevs. -Any other key combination is executed normally." - (interactive) - (let (c) - (insert last-command-char) - (if (or (eq (setq c (read-event)) ??) ;insert char if not equal to `?' - (eq c help-char)) - (fortran-abbrev-help) - (setq unread-command-events (list c))))) - -(defun fortran-abbrev-help () - "List the currently defined abbrevs in Fortran mode." - (interactive) - (message "Listing abbrev table...") - (display-buffer (fortran-prepare-abbrev-list-buffer)) - (message "Listing abbrev table...done")) - -(defun fortran-prepare-abbrev-list-buffer () - (save-excursion - (set-buffer (get-buffer-create "*Abbrevs*")) - (erase-buffer) - (insert-abbrev-table-description 'fortran-mode-abbrev-table t) - (goto-char (point-min)) - (set-buffer-modified-p nil) - (edit-abbrevs-mode)) - (get-buffer-create "*Abbrevs*")) - -(defun fortran-column-ruler () - "Inserts a column ruler momentarily above current line, till next keystroke. -The ruler is defined by the value of `fortran-column-ruler-fixed' when in fixed -format mode, and `fortran-column-ruler-tab' when in TAB format mode. -The key typed is executed unless it is SPC." - (interactive) - (momentary-string-display - (if indent-tabs-mode - fortran-column-ruler-tab - fortran-column-ruler-fixed) - (save-excursion - (beginning-of-line) - (if (eq (window-start (selected-window)) - (window-point (selected-window))) - (progn (forward-line) (point)) - (point))) - nil "Type SPC or any command to erase ruler.")) - -(defun fortran-window-create () - "Makes the window 72 columns wide. -See also `fortran-window-create-momentarily'." - (interactive) - (condition-case error - (progn - (let ((window-min-width 2)) - (if (< (window-width) (frame-width)) - (enlarge-window-horizontally (- (frame-width) - (window-width) 1))) - (split-window-horizontally 73) - (other-window 1) - (switch-to-buffer " fortran-window-extra" t) - (select-window (previous-window)))) - (error (message "No room for Fortran window.") - 'error))) - -(defun fortran-window-create-momentarily (&optional arg) - "Momentarily makes the window 72 columns wide. -Optional ARG non-nil and non-unity disables the momentary feature. -See also `fortran-window-create'." - (interactive "p") - (if (or (not arg) - (= arg 1)) - (save-window-excursion - (if (not (equal (fortran-window-create) 'error)) - (progn (message "Type SPC to continue editing.") - (let ((char (read-event))) - (or (equal char (string-to-char " ")) - (setq unread-command-events (list char))))))) - (fortran-window-create))) - -(defun fortran-split-line () - "Break line at point and insert continuation marker and alignment." - (interactive) - (delete-horizontal-space) - (if (save-excursion (beginning-of-line) (looking-at comment-line-start-skip)) - (insert "\n" comment-line-start " ") - (if indent-tabs-mode - (progn - (insert "\n\t") - (insert-char (fortran-numerical-continuation-char) 1)) - (insert "\n " fortran-continuation-string)));Space after \n important - (fortran-indent-line)) ;when the cont string is C, c or *. - -(defun fortran-numerical-continuation-char () - "Return a digit for tab-digit style of continuation lines. -If, previous line is a tab-digit continuation line, returns that digit -plus one. Otherwise return 1. Zero not allowed." - (save-excursion - (forward-line -1) - (if (looking-at "\t[1-9]") - (+ ?1 (% (- (char-after (+ (point) 1)) ?0) 9)) - ?1))) - -(defun delete-horizontal-regexp (chars) - "Delete all characters in CHARS around point. -CHARS is like the inside of a [...] in a regular expression -except that ] is never special and \ quotes ^, - or \." - (interactive "*s") - (skip-chars-backward chars) - (delete-region (point) (progn (skip-chars-forward chars) (point)))) - -(defun fortran-electric-line-number (arg) - "Self insert, but if part of a Fortran line number indent it automatically. -Auto-indent does not happen if a numeric arg is used." - (interactive "P") - (if (or arg (not fortran-electric-line-number)) - (if arg - (self-insert-command (prefix-numeric-value arg)) - (self-insert-command 1)) - (if (or (and (= 5 (current-column)) - (save-excursion - (beginning-of-line) - (looking-at " ")));In col 5 with only spaces to left. - (and (= (if indent-tabs-mode - fortran-minimum-statement-indent-tab - fortran-minimum-statement-indent-fixed) (current-column)) - (save-excursion - (beginning-of-line) - (looking-at "\t"));In col 8 with a single tab to the left. - (not (or (eq last-command 'fortran-indent-line) - (eq last-command - 'fortran-indent-new-line)))) - (save-excursion - (re-search-backward "[^ \t0-9]" - (save-excursion - (beginning-of-line) - (point)) - t)) ;not a line number - (looking-at "[0-9]") ;within a line number - ) - (self-insert-command (prefix-numeric-value arg)) - (skip-chars-backward " \t") - (insert last-command-char) - (fortran-indent-line)))) - -(defun beginning-of-fortran-subprogram () - "Moves point to the beginning of the current Fortran subprogram." - (interactive) - (let ((case-fold-search t)) - (beginning-of-line -1) - (re-search-backward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) - (if (looking-at "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]") - (forward-line 1)))) - -(defun end-of-fortran-subprogram () - "Moves point to the end of the current Fortran subprogram." - (interactive) - (let ((case-fold-search t)) - (beginning-of-line 2) - (re-search-forward "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]" nil 'move) - (goto-char (match-beginning 0)) - (forward-line 1))) - -(defun mark-fortran-subprogram () - "Put mark at end of Fortran subprogram, point at beginning. -The marks are pushed." - (interactive) - (end-of-fortran-subprogram) - (push-mark (point)) - (beginning-of-fortran-subprogram)) - -(defun fortran-previous-statement () - "Moves point to beginning of the previous Fortran statement. -Returns `first-statement' if that statement is the first -non-comment Fortran statement in the file, and nil otherwise." - (interactive) - (let (not-first-statement continue-test) - (beginning-of-line) - (setq continue-test - (and - (not (looking-at comment-line-start-skip)) - (or (looking-at - (concat "[ \t]*" (regexp-quote fortran-continuation-string))) - (or (looking-at " [^ 0\n]") - (looking-at "\t[1-9]"))))) - (while (and (setq not-first-statement (= (forward-line -1) 0)) - (or (looking-at comment-line-start-skip) - (looking-at "[ \t]*$") - (looking-at " [^ 0\n]") - (looking-at "\t[1-9]") - (looking-at (concat "[ \t]*" comment-start-skip))))) - (cond ((and continue-test - (not not-first-statement)) - (message "Incomplete continuation statement.")) - (continue-test - (fortran-previous-statement)) - ((not not-first-statement) - 'first-statement)))) - -(defun fortran-next-statement () - "Moves point to beginning of the next Fortran statement. -Returns `last-statement' if that statement is the last -non-comment Fortran statement in the file, and nil otherwise." - (interactive) - (let (not-last-statement) - (beginning-of-line) - (while (and (setq not-last-statement - (and (= (forward-line 1) 0) - (not (eobp)))) - (or (looking-at comment-line-start-skip) - (looking-at "[ \t]*$") - (looking-at " [^ 0\n]") - (looking-at "\t[1-9]") - (looking-at (concat "[ \t]*" comment-start-skip))))) - (if (not not-last-statement) - 'last-statement))) - -(defun fortran-blink-matching-if () - "From a Fortran ENDIF statement, blink the matching IF statement." - (let ((count 1) (top-of-window (window-start)) matching-if - (endif-point (point)) message) - (if (save-excursion (beginning-of-line) - (skip-chars-forward " \t0-9") - (looking-at "end[ \t]*if\\b")) - (progn - (save-excursion - (while (and (not (= count 0)) - (not (eq (fortran-previous-statement) - 'first-statement)) - (not (looking-at - "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) - ; Keep local to subprogram - (skip-chars-forward " \t0-9") - (cond ((looking-at "if[ \t]*(") - (save-excursion - (if (or - (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t(=a-z0-9]") - (let (then-test);multi-line if-then - (while - (and (= (forward-line 1) 0) - ;search forward for then - (or (looking-at " [^ 0\n]") - (looking-at "\t[1-9]")) - (not - (setq - then-test - (looking-at - ".*then\\b[ \t]*[^ \t(=a-z0-9]"))))) - then-test)) - (setq count (- count 1))))) - ((looking-at "end[ \t]*if\\b") - (setq count (+ count 1))))) - (if (not (= count 0)) - (setq message "No matching if.") - (if (< (point) top-of-window) - (setq message (concat "Matches " (buffer-substring - (progn (beginning-of-line) - (point)) - (progn (end-of-line) - (point))))) - (setq matching-if (point))))) - (if message - (message "%s" message) - (goto-char matching-if) - (sit-for 1) - (goto-char endif-point)))))) - -(defun fortran-blink-matching-do () - ;; From a Fortran ENDDO statement, blink on the matching DO or DO WHILE - ;; statement. This is basically copied from fortran-blink-matching-if. - (let ((count 1) (top-of-window (window-start)) matching-do - (enddo-point (point)) message) - (if (save-excursion (beginning-of-line) - (skip-chars-forward " \t0-9") - (looking-at "end[ \t]*do\\b")) - (progn - (save-excursion - (while (and (not (= count 0)) - (not (eq (fortran-previous-statement) - 'first-statement)) - (not (looking-at - "^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]"))) - ; Keep local to subprogram - (skip-chars-forward " \t0-9") - (cond ((looking-at "do[ \t]+") - (setq count (- count 1))) - ((looking-at "end[ \t]*do\\b") - (setq count (+ count 1))))) - (if (not (= count 0)) - (setq message "No matching do.") - (if (< (point) top-of-window) - (setq message (concat "Matches " (buffer-substring - (progn (beginning-of-line) - (point)) - (progn (end-of-line) - (point))))) - (setq matching-do (point))))) - (if message - (message "%s" message) - (goto-char matching-do) - (sit-for 1) - (goto-char enddo-point)))))) - -(defun fortran-indent-line () - "Indents current Fortran line based on its contents and on previous lines." - (interactive) - (let ((cfi (calculate-fortran-indent))) - (save-excursion - (beginning-of-line) - (if (or (not (= cfi (fortran-current-line-indentation))) - (and (re-search-forward "^[ \t]*[0-9]+" (+ (point) 4) t) - (not (fortran-line-number-indented-correctly-p)))) - (fortran-indent-to-column cfi) - (beginning-of-line) - (if (and (not (looking-at comment-line-start-skip)) - (fortran-find-comment-start-skip)) - (fortran-indent-comment)))) - ;; Never leave point in left margin. - (if (< (current-column) cfi) - (move-to-column cfi)) - (if (and auto-fill-function - (> (save-excursion (end-of-line) (current-column)) fill-column)) - (save-excursion - (end-of-line) - (fortran-do-auto-fill))) - (if fortran-blink-matching-if - (progn - (fortran-blink-matching-if) - (fortran-blink-matching-do))))) - -(defun fortran-indent-new-line () - "Reindent the current Fortran line, insert a newline and indent the newline. -An abbrev before point is expanded if `abbrev-mode' is non-nil." - (interactive) - (if abbrev-mode (expand-abbrev)) - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (if (or (looking-at "[0-9]") ;Reindent only where it is most - (looking-at "end") ;likely to be necessary - (looking-at "else") - (looking-at (regexp-quote fortran-continuation-string))) - (fortran-indent-line))) - (newline) - (fortran-indent-line)) - -(defun fortran-indent-subprogram () - "Properly indents the Fortran subprogram which contains point." - (interactive) - (save-excursion - (mark-fortran-subprogram) - (message "Indenting subprogram...") - (indent-region (point) (mark) nil)) - (message "Indenting subprogram...done.")) - -(defun calculate-fortran-indent () - "Calculates the Fortran indent column based on previous lines." - (let (icol first-statement (case-fold-search t) - (fortran-minimum-statement-indent - (if indent-tabs-mode - fortran-minimum-statement-indent-tab - fortran-minimum-statement-indent-fixed))) - (save-excursion - (setq first-statement (fortran-previous-statement)) - (if first-statement - (setq icol fortran-minimum-statement-indent) - (progn - (if (= (point) (point-min)) - (setq icol fortran-minimum-statement-indent) - (setq icol (fortran-current-line-indentation))) - (skip-chars-forward " \t0-9") - (cond ((looking-at "if[ \t]*(") - (if (or (looking-at ".*)[ \t]*then\\b[ \t]*[^ \t_$(=a-z0-9]") - (let (then-test) ;multi-line if-then - (while (and (= (forward-line 1) 0) - ;;search forward for then - (or (looking-at " [^ 0\n]") - (looking-at "\t[1-9]")) - (not (setq then-test (looking-at - ".*then\\b[ \t]\ -*[^ \t_$(=a-z0-9]"))))) - then-test)) - (setq icol (+ icol fortran-if-indent)))) - ((looking-at "\\(else\\|elseif\\)\\b") - (setq icol (+ icol fortran-if-indent))) - ((looking-at "select[ \t]*case[ \t](.*)\\b") - (setq icol (+ icol fortran-if-indent))) - ((looking-at "case[ \t]*(.*)[ \t]*\n") - (setq icol (+ icol fortran-if-indent))) - ((looking-at "case[ \t]*default\\b") - (setq icol (+ icol fortran-if-indent))) - ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") - (setq icol (+ icol fortran-if-indent))) - ((looking-at "where[ \t]*(.*)[ \t]*\n") - (setq icol (+ icol fortran-if-indent))) - ((looking-at "do\\b") - (setq icol (+ icol fortran-do-indent))) - ((looking-at - "\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]") - (setq icol (+ icol fortran-structure-indent))) - ((looking-at "end\\b[ \t]*[^ \t=(a-z]") - ;; Previous END resets indent to minimum - (setq icol fortran-minimum-statement-indent)))))) - (save-excursion - (beginning-of-line) - (cond ((looking-at "[ \t]*$")) - ((looking-at comment-line-start-skip) - (cond ((eq fortran-comment-indent-style 'relative) - (setq icol (+ icol fortran-comment-line-extra-indent))) - ((eq fortran-comment-indent-style 'fixed) - (setq icol (+ fortran-minimum-statement-indent - fortran-comment-line-extra-indent)))) - (setq fortran-minimum-statement-indent 0)) - ((or (looking-at (concat "[ \t]*" - (regexp-quote - fortran-continuation-string))) - (looking-at " [^ 0\n]") - (looking-at "\t[1-9]")) - (setq icol (+ icol fortran-continuation-indent))) - ((looking-at "[ \t]*#") ; Check for cpp directive. - (setq fortran-minimum-statement-indent 0 icol 0)) - (first-statement) - ((and fortran-check-all-num-for-matching-do - (looking-at "[ \t]*[0-9]+") - (fortran-check-for-matching-do)) - (setq icol (- icol fortran-do-indent))) - (t - (skip-chars-forward " \t0-9") - (cond ((looking-at "end[ \t]*if\\b") - (setq icol (- icol fortran-if-indent))) - ((looking-at "\\(else\\|elseif\\)\\b") - (setq icol (- icol fortran-if-indent))) - ((looking-at "case[ \t]*(.*)[ \t]*\n") - (setq icol (- icol fortran-if-indent))) - ((looking-at "case[ \t]*default\\b") - (setq icol (- icol fortran-if-indent))) - ((looking-at "\\(otherwise\\|else[ \t]*where\\)\\b") - (setq icol (- icol fortran-if-indent))) - ((looking-at "end[ \t]*where\\b") - (setq icol (- icol fortran-if-indent))) - ((and (looking-at "continue\\b") - (fortran-check-for-matching-do)) - (setq icol (- icol fortran-do-indent))) - ((looking-at "end[ \t]*do\\b") - (setq icol (- icol fortran-do-indent))) - ((looking-at - "end[ \t]*\ -\\(structure\\|union\\|map\\|interface\\)\\b[ \t]*[^ \t=(a-z]") - (setq icol (- icol fortran-structure-indent))) - ((looking-at - "end[ \t]*select\\b[ \t]*[^ \t=(a-z]") - (setq icol (- icol fortran-if-indent))) - ((and (looking-at "end\\b[ \t]*[^ \t=(a-z]") - (not (= icol fortran-minimum-statement-indent))) - (message "Warning: `end' not in column %d. Probably\ - an unclosed block." fortran-minimum-statement-indent)))))) - (max fortran-minimum-statement-indent icol))) - -(defun fortran-current-line-indentation () - "Indentation of current line, ignoring Fortran line number or continuation. -This is the column position of the first non-whitespace character -aside from the line number and/or column 5/8 line-continuation character. -For comment lines, returns indentation of the first -non-indentation text within the comment." - (save-excursion - (beginning-of-line) - (cond ((looking-at comment-line-start-skip) - (goto-char (match-end 0)) - (skip-chars-forward - (if (stringp fortran-comment-indent-char) - fortran-comment-indent-char - (char-to-string fortran-comment-indent-char)))) - ((or (looking-at " [^ 0\n]") - (looking-at "\t[1-9]")) - (goto-char (match-end 0))) - (t - ;; Move past line number. - (skip-chars-forward "[ \t0-9]");From Uli - )) - ;; Move past whitespace. - (skip-chars-forward " \t") - (current-column))) - -(defun fortran-indent-to-column (col) - "Indents current line with spaces to column COL. -notes: 1) A non-zero/non-blank character in column 5 indicates a continuation - line, and this continuation character is retained on indentation; - 2) If `fortran-continuation-string' is the first non-whitespace - character, this is a continuation line; - 3) A non-continuation line which has a number as the first - non-whitespace character is a numbered line. - 4) A TAB followed by a digit indicates a continuation line." - (save-excursion - (beginning-of-line) - (if (looking-at comment-line-start-skip) - (if fortran-comment-indent-style - (let ((char (if (stringp fortran-comment-indent-char) - (aref fortran-comment-indent-char 0) - fortran-comment-indent-char))) - (goto-char (match-end 0)) - (delete-horizontal-regexp (concat " \t" (char-to-string char))) - (insert-char char (- col (current-column))))) - (if (looking-at "\t[1-9]") - (if indent-tabs-mode - (goto-char (match-end 0)) - (delete-char 2) - (insert " ") - (insert fortran-continuation-string)) - (if (looking-at " [^ 0\n]") - (if indent-tabs-mode - (progn (delete-char 6) - (insert "\t") - (insert-char (fortran-numerical-continuation-char) 1)) - (forward-char 6)) - (delete-horizontal-space) - ;; Put line number in columns 0-4 - ;; or put continuation character in column 5. - (cond ((eobp)) - ((looking-at (regexp-quote fortran-continuation-string)) - (if indent-tabs-mode - (progn - (indent-to - (if indent-tabs-mode - fortran-minimum-statement-indent-tab - fortran-minimum-statement-indent-fixed)) - (delete-char 1) - (insert-char (fortran-numerical-continuation-char) 1)) - (indent-to 5) - (forward-char 1))) - ((looking-at "[0-9]+") - (let ((extra-space (- 5 (- (match-end 0) (point))))) - (if (< extra-space 0) - (message "Warning: line number exceeds 5-digit limit.") - (indent-to (min fortran-line-number-indent extra-space)))) - (skip-chars-forward "0-9"))))) - ;; Point is now after any continuation character or line number. - ;; Put body of statement where specified. - (delete-horizontal-space) - (indent-to col) - ;; Indent any comment following code on the same line. - (if (and comment-start-skip - (fortran-find-comment-start-skip)) - (progn (goto-char (match-beginning 0)) - (if (not (= (current-column) (fortran-comment-hook))) - (progn (delete-horizontal-space) - (indent-to (fortran-comment-hook))))))))) - -(defun fortran-line-number-indented-correctly-p () - "Return t if current line's line number is correctly indented. -Do not call if there is no line number." - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (and (<= (current-column) fortran-line-number-indent) - (or (= (current-column) fortran-line-number-indent) - (progn (skip-chars-forward "0-9") - (= (current-column) 5)))))) - -(defun fortran-check-for-matching-do () - "When called from a numbered statement, returns t if matching DO is found. -Otherwise return a nil." - (let (charnum - (case-fold-search t)) - (save-excursion - (beginning-of-line) - (if (looking-at "[ \t]*[0-9]+") - (progn - (skip-chars-forward " \t") - (skip-chars-forward "0") ;skip past leading zeros - (setq charnum (buffer-substring (point) - (progn (skip-chars-forward "0-9") - (point)))) - (beginning-of-line) - (and (re-search-backward - (concat - "\\(^[ \t0-9]*end\\b[ \t]*[^ \t=(a-z]\\)\\|\\(^[ \t0-9]*do\ -[ \t]*0*" - charnum "\\b\\)\\|\\(^[ \t]*0*" charnum "\\b\\)") - nil t) - (looking-at (concat "^[ \t0-9]*do[ \t]*0*" charnum)))))))) - -(defun fortran-find-comment-start-skip () - "Move to past `comment-start-skip' found on current line. -Return t if `comment-start-skip' found, nil if not." -;;; In order to move point only if comment-start-skip is found, -;;; this one uses a lot of save-excursions. Note that re-search-forward -;;; moves point even if comment-start-skip is inside a string-constant. -;;; Some code expects certain values for match-beginning and end - (interactive) - (let ((save-match-beginning) (save-match-end)) - (if (save-excursion - (re-search-forward comment-start-skip - (save-excursion (end-of-line) (point)) t)) - (progn - (setq save-match-beginning (match-beginning 0)) - (setq save-match-end (match-end 0)) - (if (fortran-is-in-string-p (match-beginning 0)) - (progn - (save-excursion - (goto-char save-match-end) - (fortran-find-comment-start-skip)) ; recurse for rest of line - ) - (goto-char save-match-beginning) - (re-search-forward comment-start-skip - (save-excursion (end-of-line) (point)) t) - (goto-char (match-end 0)) - t)) - nil))) - -;;;From: ralf@up3aud1.gwdg.de (Ralf Fassel) -;;; Test if TAB format continuation lines work. -(defun fortran-is-in-string-p (where) - "Return non-nil if POS (a buffer position) is inside a Fortran string, -nil else." - (save-excursion - (goto-char where) - (cond - ((bolp) nil) ; bol is never inside a string - ((save-excursion ; comment lines too - (beginning-of-line)(looking-at comment-line-start-skip)) nil) - (t (let (;; ok, serious now. Init some local vars: - (parse-state '(0 nil nil nil nil nil 0)) - (quoted-comment-start (if comment-start - (regexp-quote comment-start))) - (not-done t) - parse-limit - end-of-line - ) - ;; move to start of current statement - (fortran-next-statement) - (fortran-previous-statement) - ;; now parse up to WHERE - (while not-done - (if (or ;; skip to next line if: - ;; - comment line? - (looking-at comment-line-start-skip) - ;; - at end of line? - (eolp) - ;; - not in a string and after comment-start? - (and (not (nth 3 parse-state)) - comment-start - (equal comment-start - (char-to-string (preceding-char))))) - ;; get around a bug in forward-line in versions <= 18.57 - (if (or (> (forward-line 1) 0) (eobp)) - (setq not-done nil)) - ;; else: - ;; if we are at beginning of code line, skip any - ;; whitespace, labels and tab continuation markers. - (if (bolp) (skip-chars-forward " \t0-9")) - ;; if we are in column <= 5 now, check for continuation char - (cond ((= 5 (current-column)) (forward-char 1)) - ((and (< (current-column) 5) - (equal fortran-continuation-string - (char-to-string (following-char))) - (forward-char 1)))) - ;; find out parse-limit from here - (setq end-of-line (save-excursion (end-of-line)(point))) - (setq parse-limit (min where end-of-line)) - ;; parse max up to comment-start, if non-nil and in current line - (if comment-start - (save-excursion - (if (re-search-forward quoted-comment-start end-of-line t) - (setq parse-limit (min (point) parse-limit))))) - ;; now parse if still in limits - (if (< (point) where) - (setq parse-state (parse-partial-sexp - (point) parse-limit nil nil parse-state)) - (setq not-done nil)) - )) - ;; result is - (nth 3 parse-state)))))) - -(defun fortran-auto-fill-mode (arg) - "Toggle fortran-auto-fill mode. -With ARG, turn `fortran-auto-fill' mode on iff ARG is positive. -In `fortran-auto-fill' mode, inserting a space at a column beyond `fill-column' -automatically breaks the line at a previous space." - (interactive "P") - (prog1 (setq auto-fill-function - (if (if (null arg) - (not auto-fill-function) - (> (prefix-numeric-value arg) 0)) - 'fortran-indent-line - nil)) - ;; update mode-line - (set-buffer-modified-p (buffer-modified-p)))) - -(defun fortran-do-auto-fill () - (interactive) - (let* ((opoint (point)) - (bol (save-excursion (beginning-of-line) (point))) - (eol (save-excursion (end-of-line) (point))) - (bos (min eol (+ bol (fortran-current-line-indentation)))) - (quote - (save-excursion - (goto-char bol) - (if (looking-at comment-line-start-skip) - nil ; OK to break quotes on comment lines. - (move-to-column fill-column) - (cond ((fortran-is-in-string-p (point)) - (save-excursion (re-search-backward "[^']'[^']" bol t) - (if fortran-break-before-delimiters - (point) - (1+ (point))))) - (t nil))))) - ;; - ;; decide where to split the line. If a position for a quoted - ;; string was found above then use that, else break the line - ;; before the last delimiter. - ;; Delimiters are whitespace, commas, and operators. - ;; Will break before a pair of *'s. - ;; - (fill-point - (or quote - (save-excursion - (move-to-column (1+ fill-column)) - (skip-chars-backward "^ \t\n,'+-/*=)" -;;; (if fortran-break-before-delimiters -;;; "^ \t\n,'+-/*=" "^ \t\n,'+-/*=)") - ) - (if (<= (point) (1+ bos)) - (progn - (move-to-column (1+ fill-column)) -;;;what is this doing??? - (if (not (re-search-forward "[\t\n,'+-/*)=]" eol t)) - (goto-char bol)))) - (if (bolp) - (re-search-forward "[ \t]" opoint t) - (forward-char -1) - (if (looking-at "'") - (forward-char 1) - (skip-chars-backward " \t\*"))) - (if fortran-break-before-delimiters - (point) - (1+ (point)))))) - ) - ;; if we are in an in-line comment, don't break unless the - ;; line of code is longer than it should be. Otherwise - ;; break the line at the column computed above. - ;; - ;; Need to use fortran-find-comment-start-skip to make sure that quoted !'s - ;; don't prevent a break. - (if (not (or (save-excursion - (if (and (re-search-backward comment-start-skip bol t) - (not (fortran-is-in-string-p (point)))) - (progn - (skip-chars-backward " \t") - (< (current-column) (1+ fill-column))))) - (save-excursion - (goto-char fill-point) - (bolp)))) - (if (> (save-excursion - (goto-char fill-point) (current-column)) - (1+ fill-column)) - (progn (goto-char fill-point) - (fortran-break-line)) - (save-excursion - (if (> (save-excursion - (goto-char fill-point) - (current-column)) - (+ (calculate-fortran-indent) fortran-continuation-indent)) - (progn - (goto-char fill-point) - (fortran-break-line)))))) - )) -(defun fortran-break-line () - (let ((opoint (point)) - (bol (save-excursion (beginning-of-line) (point))) - (eol (save-excursion (end-of-line) (point))) - (comment-string nil)) - - (save-excursion - (if (and comment-start-skip (fortran-find-comment-start-skip)) - (progn - (re-search-backward comment-start-skip bol t) - (setq comment-string (buffer-substring (point) eol)) - (delete-region (point) eol)))) -;;; Forward line 1 really needs to go to next non white line - (if (save-excursion (forward-line 1) - (or (looking-at " [^ 0\n]") - (looking-at "\t[1-9]"))) - (progn - (forward-line 1) - (delete-indentation) - (delete-char 2) - (delete-horizontal-space) - (fortran-do-auto-fill)) - (fortran-split-line)) - (if comment-string - (save-excursion - (goto-char bol) - (end-of-line) - (delete-horizontal-space) - (indent-to (fortran-comment-hook)) - (insert comment-string))))) - -(defun fortran-analyze-file-format () - "Returns nil if fixed format is used, t if TAB formatting is used. -Use `fortran-tab-mode-default' if no non-comment statements are found in the -file before the end or the first `fortran-analyze-depth' lines." - (let ((i 0)) - (save-excursion - (goto-char (point-min)) - (setq i 0) - (while (not (or - (eobp) - (looking-at "\t") - (looking-at " ") - (> i fortran-analyze-depth))) - (forward-line) - (setq i (1+ i))) - (cond - ((looking-at "\t") t) - ((looking-at " ") nil) - (fortran-tab-mode-default t) - (t nil))))) - -(or (assq 'fortran-tab-mode-string minor-mode-alist) - (setq minor-mode-alist (cons - '(fortran-tab-mode-string - (indent-tabs-mode fortran-tab-mode-string)) - minor-mode-alist))) - -(provide 'fortran) - -;;; fortran.el ends here - diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el deleted file mode 100644 index a48e471f753..00000000000 --- a/lisp/progmodes/hideif.el +++ /dev/null @@ -1,1041 +0,0 @@ -;;; hide-ifdef-mode.el --- hides selected code within ifdef. - -;;; Copyright (C) 1988 Free Software Foundation, Inc. - -;; Author: Dan LaLiberte <liberte@a.cs.uiuc.edu> -;; Keywords: c - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;;; To initialize, toggle the hide-ifdef minor mode with -;;; -;;; M-x hide-ifdef-mode -;;; -;;; This will set up key bindings and call hide-ifdef-mode-hook if it -;;; has a value. To explicitly hide ifdefs using a buffer-local -;;; define list (default empty), type -;;; -;;; M-x hide-ifdefs or C-c h -;;; -;;; Hide-ifdef suppresses the display of code that the preprocessor wouldn't -;;; pass through. The support of constant expressions in #if lines is -;;; limited to identifiers, parens, and the operators: &&, ||, !, and -;;; "defined". Please extend this. -;;; -;;; The hidden code is marked by ellipses (...). Be -;;; cautious when editing near ellipses, since the hidden text is -;;; still in the buffer, and you can move the point into it and modify -;;; text unawares. If you don't want to see the ellipses, set -;;; selective-display-ellipses to nil. But this can be dangerous. -;;; You can make your buffer read-only while hide-ifdef-hiding by setting -;;; hide-ifdef-read-only to a non-nil value. You can toggle this -;;; variable with hide-ifdef-toggle-read-only (C-c C-q). -;;; -;;; You can undo the effect of hide-ifdefs by typing -;;; -;;; M-x show-ifdefs or C-c s -;;; -;;; Use M-x hide-ifdef-define (C-c d) to define a symbol. -;;; Use M-x hide-ifdef-undef (C-c u) to undefine a symbol. -;;; -;;; If you define or undefine a symbol while hide-ifdef-mode is in effect, -;;; the display will be updated. Only the define list for the current -;;; buffer will be affected. You can save changes to the local define -;;; list with hide-ifdef-set-define-alist. This adds entries -;;; to hide-ifdef-define-alist. -;;; -;;; If you have defined a hide-ifdef-mode-hook, you can set -;;; up a list of symbols that may be used by hide-ifdefs as in the -;;; following example: -;;; -;;; (setq hide-ifdef-mode-hook -;;; '(lambda () -;;; (if (not hide-ifdef-define-alist) -;;; (setq hide-ifdef-define-alist -;;; '((list1 ONE TWO) -;;; (list2 TWO THREE) -;;; ))) -;;; (hide-ifdef-use-define-alist 'list2) ; use list2 by default -;;; )) -;;; -;;; You can call hide-ifdef-use-define-alist (C-c u) at any time to specify -;;; another list to use. -;;; -;;; To cause ifdefs to be hidden as soon as hide-ifdef-mode is called, -;;; set hide-ifdef-initially to non-nil. -;;; -;;; If you set hide-ifdef-lines to t, hide-ifdefs hides all the #ifdef lines. -;;; In the absence of highlighting, that might be a bad idea. If you set -;;; hide-ifdef-lines to nil (the default), the surrounding preprocessor -;;; lines will be displayed. That can be confusing in its own -;;; right. Other variations on display are possible, but not much -;;; better. -;;; -;;; You can explicitly hide or show individual ifdef blocks irrespective -;;; of the define list by using hide-ifdef-block and show-ifdef-block. -;;; -;;; You can move the point between ifdefs with forward-ifdef, backward-ifdef, -;;; up-ifdef, down-ifdef, next-ifdef, and previous-ifdef. -;;; -;;; If you have minor-mode-alist in your mode line (the default) two labels -;;; may appear. "Ifdef" will appear when hide-ifdef-mode is active. "Hiding" -;;; will appear when text may be hidden ("hide-ifdef-hiding" is non-nil). -;;; -;;; Written by Brian Marick, at Gould, Computer Systems Division, Urbana IL. -;;; Extensively modified by Daniel LaLiberte (while at Gould). -;;; -;;; You may freely modify and distribute this, but keep a record -;;; of modifications and send comments to: -;;; liberte@a.cs.uiuc.edu or ihnp4!uiucdcs!liberte -;;; I will continue to upgrade hide-ifdef-mode -;;; with your contributions. - -;;; Change Log: -;;; -;;; Revision 1.7 88/02/16 03:12:58 liberte -;;; Fixed comments and doc strings. -;;; Added optional prefix arg for ifdef motion commands. -;;; -;;; Revision 1.6 88/02/05 00:36:18 liberte -;;; Bug fixes. -;;; 1. A multi-line comment that starts on an #ifdef line -;;; now ends on that line. -;;; 2. Fix bad function name: hide-hif-ifdef-toggle-read-only -;;; 3. Make ifdef-block hiding work outside of ifdefs. -;;; -;;; Revision 1.5 88/01/31 23:19:31 liberte -;;; Major clean up. -;;; Prefix internal names with "hif-". -;;; -;;; Revision 1.4 88/01/30 14:09:38 liberte -;;; Add hide-ifdef-hiding and hide-ifdef-mode to minor-mode-alist. -;;; -;;; Revision 1.3 88/01/29 00:38:19 liberte -;;; Fix three bugs. -;;; 1. Function "defined" is just like lookup. -;;; 2. Skip to newline or cr in case text is hidden. -;;; 3. Use car of token list if just one symbol. -;;; -;;; Revision 1.2 88/01/28 23:32:46 liberte -;;; Use hide-ifdef-mode-prefix-key. -;;; Copy current-local-map so other buffers do not get -;;; hide-ifdef-mode bindings. -;;; - -;;; Code: - -(defvar hide-ifdef-mode-map nil - "Keymap used with Hide-Ifdef mode") - -(defconst hide-ifdef-mode-prefix-key "\C-c" - "Prefix key for all Hide-Ifdef mode commands.") - -(defvar hide-ifdef-mode-map-before nil - "Buffer-local variable to store a copy of the local keymap -before `hide-ifdef-mode' modifies it.") - -(defun define-hide-ifdef-mode-map () - (if hide-ifdef-mode-map - () ; dont redefine it. - (setq hide-ifdef-mode-map (make-sparse-keymap)) - (define-key hide-ifdef-mode-map "\ed" 'hide-ifdef-define) - (define-key hide-ifdef-mode-map "\eu" 'hide-ifdef-undef) - (define-key hide-ifdef-mode-map "\eD" 'hide-ifdef-set-define-alist) - (define-key hide-ifdef-mode-map "\eU" 'hide-ifdef-use-define-alist) - - (define-key hide-ifdef-mode-map "\eh" 'hide-ifdefs) - (define-key hide-ifdef-mode-map "\es" 'show-ifdefs) - (define-key hide-ifdef-mode-map "\C-h" 'hide-ifdef-block) - (define-key hide-ifdef-mode-map "\C-s" 'show-ifdef-block) - - (define-key hide-ifdef-mode-map "\C-f" 'forward-ifdef) - (define-key hide-ifdef-mode-map "\C-b" 'backward-ifdef) - (define-key hide-ifdef-mode-map "\C-d" 'down-ifdef) - (define-key hide-ifdef-mode-map "\C-u" 'up-ifdef) - (define-key hide-ifdef-mode-map "\C-n" 'next-ifdef) - (define-key hide-ifdef-mode-map "\C-p" 'previous-ifdef) - (define-key hide-ifdef-mode-map "\C-q" 'hide-ifdef-toggle-read-only) - (let ((where (where-is-internal 'toggle-read-only nil nil t))) - (if where - (define-key hide-ifdef-mode-map - where - 'hide-ifdef-toggle-outside-read-only))) - ) - (fset 'hide-ifdef-mode-map hide-ifdef-mode-map) ; the function is the map - ) - -(defun hif-update-mode-line () - "Update mode-line by setting buffer-modified to itself." - (set-buffer-modified-p (buffer-modified-p))) - -(defvar hide-ifdef-mode nil - "non-nil when hide-ifdef-mode is activated.") - -(defvar hide-ifdef-hiding nil - "non-nil when text may be hidden.") - -(or (assq 'hide-ifdef-hiding minor-mode-alist) - (setq minor-mode-alist - (cons '(hide-ifdef-hiding " Hiding") - minor-mode-alist))) - -(or (assq 'hide-ifdef-mode minor-mode-alist) - (setq minor-mode-alist - (cons '(hide-ifdef-mode " Ifdef") - minor-mode-alist))) - -;;;###autoload -(defun hide-ifdef-mode (arg) - "Toggle Hide-Ifdef mode. This is a minor mode, albeit a large one. -With ARG, turn Hide-Ifdef mode on iff arg is positive. -In Hide-Ifdef mode, code within #ifdef constructs that the C preprocessor -would eliminate may be hidden from view. Several variables affect -how the hiding is done: - -hide-ifdef-env - An association list of defined and undefined symbols for the - current buffer. Initially, the global value of `hide-ifdef-env' - is used. - -hide-ifdef-define-alist - An association list of defined symbol lists. - Use `hide-ifdef-set-define-alist' to save the current `hide-ifdef-env' - and `hide-ifdef-use-define-alist' to set the current `hide-ifdef-env' - from one of the lists in `hide-ifdef-define-alist'. - -hide-ifdef-lines - Set to non-nil to not show #if, #ifdef, #ifndef, #else, and - #endif lines when hiding. - -hide-ifdef-initially - Indicates whether `hide-ifdefs' should be called when Hide-Ifdef mode - is activated. - -hide-ifdef-read-only - Set to non-nil if you want to make buffers read only while hiding. - After `show-ifdefs', read-only status is restored to previous value. - -\\{hide-ifdef-mode-map}" - - (interactive "P") - (make-local-variable 'hide-ifdef-mode) - (setq hide-ifdef-mode - (if (null arg) - (not hide-ifdef-mode) - (> (prefix-numeric-value arg) 0))) - - (hif-update-mode-line) - - (if hide-ifdef-mode - (progn - ; fix c-mode syntax table so we can recognize whole symbols. - (modify-syntax-entry ?_ "w") - (modify-syntax-entry ?& ".") - (modify-syntax-entry ?\| ".") - - ; inherit global values - (make-local-variable 'hide-ifdef-env) - (setq hide-ifdef-env (default-value 'hide-ifdef-env)) - - (make-local-variable 'hide-ifdef-hiding) - (setq hide-ifdef-hiding (default-value 'hide-ifdef-hiding)) - - (make-local-variable 'hif-outside-read-only) - (setq hif-outside-read-only buffer-read-only) - - (make-local-variable 'hide-ifdef-mode-map-before) - (setq hide-ifdef-mode-map-before (current-local-map)) - (use-local-map (copy-keymap (current-local-map))) - (local-unset-key hide-ifdef-mode-prefix-key) - (local-set-key hide-ifdef-mode-prefix-key 'hide-ifdef-mode-map) - (define-hide-ifdef-mode-map) - - (run-hooks 'hide-ifdef-mode-hook) - - (if hide-ifdef-initially - (hide-ifdefs) - (show-ifdefs)) - (message "Enter hide-ifdef-mode.") - ) - ; else end hide-ifdef-mode - (if hide-ifdef-hiding - (show-ifdefs)) - (use-local-map hide-ifdef-mode-map-before) - (message "Exit hide-ifdef-mode.") - )) - - -;; from outline.el with docstring fixed. -(defun hif-outline-flag-region (from to flag) - "Hides or shows lines from FROM to TO, according to FLAG. If FLAG -is \\n (newline character) then text is shown, while if FLAG is \\^M -\(control-M) the text is hidden." - (let ((modp (buffer-modified-p))) - (unwind-protect (progn - (subst-char-in-region from to - (if (= flag ?\n) ?\^M ?\n) - flag t) ) - (set-buffer-modified-p modp)) - )) - -(defun hif-show-all () - "Show all of the text in the current buffer." - (interactive) - (hif-outline-flag-region (point-min) (point-max) ?\n)) - -(defun hide-ifdef-region (start end) - "START is the start of a #if or #else form. END is the ending part. -Everything including these lines is made invisible." - (hif-outline-flag-region start end ?\^M) - ) - -(defun hif-show-ifdef-region (start end) - "Everything between START and END is made visible." - (hif-outline-flag-region start end ?\n) - ) - - - -;===%%SF%% evaluation (Start) === - -(defvar hide-ifdef-evaluator 'eval - "The evaluator is given a canonical form and returns T if text under -that form should be displayed.") - -(defvar hif-undefined-symbol nil - "...is by default considered to be false.") - -(defvar hide-ifdef-env nil - "An alist of defined symbols and their values.") - - -(defun hif-set-var (var value) - "Prepend (var value) pair to hide-ifdef-env." - (setq hide-ifdef-env (cons (cons var value) hide-ifdef-env))) - - -(defun hif-lookup (var) -; (message "hif-lookup %s" var) - (let ((val (assoc var hide-ifdef-env))) - (if val - (cdr val) - hif-undefined-symbol))) - -(defun hif-defined (var) - (hif-lookup var) - ; when #if expressions are fully supported, defined result should be 1 - ; (if (assoc var hide-ifdef-env) - ; 1 - ; nil) -) - - -;===%%SF%% evaluation (End) === - - - -;===%%SF%% parsing (Start) === -;;; The code that understands what ifs and ifdef in files look like. - -(defconst hif-cpp-prefix "\\(^\\|\r\\)[ \t]*#[ \t]*") -(defconst hif-ifndef-regexp (concat hif-cpp-prefix "ifndef")) -(defconst hif-ifx-regexp (concat hif-cpp-prefix "if\\(n?def\\)?[ \t]+")) -(defconst hif-else-regexp (concat hif-cpp-prefix "else")) -(defconst hif-endif-regexp (concat hif-cpp-prefix "endif")) -(defconst hif-ifx-else-endif-regexp - (concat hif-ifx-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp)) - - -(defun hif-infix-to-prefix (token-list) - "Convert list of tokens in infix into prefix list" -; (message "hif-infix-to-prefix: %s" token-list) - (if (= 1 (length token-list)) - (` (hif-lookup (quote (, (car token-list))))) - (hif-parse-if-exp token-list)) - ) - -; pattern to match initial identifier, !, &&, ||, (, or ). -(defconst hif-token-regexp "^\\(!\\|&&\\|||\\|[()]\\|\\w+\\)") -(defconst hif-end-of-comment "\\*/") - - -(defun hif-tokenize (expr-string) - "Separate string into a list of tokens" - (let ((token-list nil) - (expr-start 0) - (expr-length (length expr-string))) - - (while (< expr-start expr-length) -; (message "expr-start = %d" expr-start) (sit-for 1) - (cond - ((string-match "^[ \t]+" expr-string expr-start) - ; skip whitespace - (setq expr-start (match-end 0)) - ; stick newline in string so ^ matches on the next string-match - (aset expr-string (1- expr-start) ?\n) - ) - - ((string-match "^/\\*" expr-string expr-start) - (setq expr-start (match-end 0)) - (aset expr-string (1- expr-start) ?\n) - (or - (string-match hif-end-of-comment - expr-string expr-start) ; eat comment - (string-match "$" expr-string expr-start)) ; multi-line comment - (setq expr-start (match-end 0)) - (aset expr-string (1- expr-start) ?\n) - ) - - ((string-match "^//" expr-string expr-start) - (string-match "$" expr-string expr-start) - (setq expr-start (match-end 0)) - ) - - ((string-match hif-token-regexp expr-string expr-start) - (let ((token (substring expr-string expr-start (match-end 0)))) - (setq expr-start (match-end 0)) - (aset expr-string (1- expr-start) ?\n) -; (message "token: %s" token) (sit-for 1) - (setq token-list - (cons - (cond - ((string-equal token "||") 'or) - ((string-equal token "&&") 'and) - ((string-equal token "!") 'not) - ((string-equal token "defined") 'hif-defined) - ((string-equal token "(") 'lparen) - ((string-equal token ")") 'rparen) - (t (intern token))) - token-list)) - )) - (t (error "Bad #if expression: %s" expr-string)) - )) - (nreverse token-list) - )) - -;;;----------------------------------------------------------------- -;;; Translate C preprocessor #if expressions using recursive descent. -;;; This parser is limited to the operators &&, ||, !, and "defined". - -(defun hif-parse-if-exp (token-list) - "Parse the TOKEN-LIST. Return translated list in prefix form." - (hif-nexttoken) - (prog1 - (hif-expr) - (if token ; is there still a token? - (error "Error: unexpected token: %s" token)))) - -(defun hif-nexttoken () - "Pop the next token from token-list into the let variable \"token\"." - (setq token (car token-list)) - (setq token-list (cdr token-list)) - token) - -(defun hif-expr () - "Parse and expression of the form - expr : term | expr '||' term." - (let ((result (hif-term))) - (while (eq token 'or) - (hif-nexttoken) - (setq result (list 'or result (hif-term)))) - result)) - -(defun hif-term () - "Parse a term of the form - term : factor | term '&&' factor." - (let ((result (hif-factor))) - (while (eq token 'and) - (hif-nexttoken) - (setq result (list 'and result (hif-factor)))) - result)) - -(defun hif-factor () - "Parse a factor of the form - factor : '!' factor | '(' expr ')' | 'defined(' id ')' | id." - (cond - ((eq token 'not) - (hif-nexttoken) - (list 'not (hif-factor))) - - ((eq token 'lparen) - (hif-nexttoken) - (let ((result (hif-expr))) - (if (not (eq token 'rparen)) - (error "Bad token in parenthesized expression: %s" token) - (hif-nexttoken) - result))) - - ((eq token 'hif-defined) - (hif-nexttoken) - (if (not (eq token 'lparen)) - (error "Error: expected \"(\" after \"defined\"")) - (hif-nexttoken) - (let ((ident token)) - (if (memq token '(or and not hif-defined lparen rparen)) - (error "Error: unexpected token: %s" token)) - (hif-nexttoken) - (if (not (eq token 'rparen)) - (error "Error: expected \")\" after identifier")) - (hif-nexttoken) - (` (hif-defined (quote (, ident)))) - )) - - (t ; identifier - (let ((ident token)) - (if (memq ident '(or and)) - (error "Error: missing identifier")) - (hif-nexttoken) - (` (hif-lookup (quote (, ident)))) - )) - )) - -;;;----------- end of parser ----------------------- - - -(defun hif-canonicalize () - "When at beginning of #ifX, returns a canonical (evaluatable) - form for the expression." - (save-excursion - (let ((negate (looking-at hif-ifndef-regexp))) - (re-search-forward hif-ifx-regexp) - (let* ((expr-string - (buffer-substring (point) - (progn (skip-chars-forward "^\n\r") (point)))) - (expr (hif-infix-to-prefix (hif-tokenize expr-string)))) -; (message "hif-canonicalized: %s" expr) - (if negate - (list 'not expr) - expr))))) - - -(defun hif-find-any-ifX () - "Position at beginning of next #if, #ifdef, or #ifndef, including one on -this line." -; (message "find ifX at %d" (point)) - (prog1 - (re-search-forward hif-ifx-regexp (point-max) t) - (beginning-of-line))) - - -(defun hif-find-next-relevant () - "Position at beginning of next #ifdef, #ifndef, #else, #endif, -NOT including one on this line." -; (message "hif-find-next-relevant at %d" (point)) - (end-of-line) - ; avoid infinite recursion by only going to beginning of line if match found - (if (re-search-forward hif-ifx-else-endif-regexp (point-max) t) - (beginning-of-line))) - -(defun hif-find-previous-relevant () - "Position at beginning of previous #ifdef, #ifndef, #else, #endif, -NOT including one on this line." -; (message "hif-find-previous-relevant at %d" (point)) - (beginning-of-line) - ; avoid infinite recursion by only going to beginning of line if match found - (if (re-search-backward hif-ifx-else-endif-regexp (point-min) t) - (beginning-of-line))) - - -(defun hif-looking-at-ifX () ;; Should eventually see #if - (looking-at hif-ifx-regexp)) -(defun hif-looking-at-endif () - (looking-at hif-endif-regexp)) -(defun hif-looking-at-else () - (looking-at hif-else-regexp)) - - - -(defun hif-ifdef-to-endif () - "If positioned at #ifX or #else form, skip to corresponding #endif." -; (message "hif-ifdef-to-endif at %d" (point)) (sit-for 1) - (hif-find-next-relevant) - (cond ((hif-looking-at-ifX) - (hif-ifdef-to-endif) ; find endif of nested if - (hif-ifdef-to-endif)) ; find outer endif or else - ((hif-looking-at-else) - (hif-ifdef-to-endif)) ; find endif following else - ((hif-looking-at-endif) - 'done) - (t - (error "Mismatched #ifdef #endif pair")))) - - -(defun hif-endif-to-ifdef () - "If positioned at #endif form, skip backward to corresponding #ifX." -; (message "hif-endif-to-ifdef at %d" (point)) - (let ((start (point))) - (hif-find-previous-relevant) - (if (= start (point)) - (error "Mismatched #ifdef #endif pair"))) - (cond ((hif-looking-at-endif) - (hif-endif-to-ifdef) ; find beginning of nested if - (hif-endif-to-ifdef)) ; find beginning of outer if or else - ((hif-looking-at-else) - (hif-endif-to-ifdef)) - ((hif-looking-at-ifX) - 'done) - (t))) ; never gets here - - -(defun forward-ifdef (&optional arg) - "Move point to beginning of line of the next ifdef-endif. -With argument, do this that many times." - (interactive "p") - (or arg (setq arg 1)) - (if (< arg 0) - (backward-ifdef (- arg))) - (while (< 0 arg) - (setq arg (- arg)) - (let ((start (point))) - (if (not (hif-looking-at-ifX)) - (hif-find-next-relevant)) - (if (hif-looking-at-ifX) - (hif-ifdef-to-endif) - (goto-char start) - (error "No following #ifdef") - )))) - - -(defun backward-ifdef (&optional arg) - "Move point to beginning of the previous ifdef-endif. -With argument, do this that many times." - (interactive "p") - (or arg (setq arg 1)) - (if (< arg 0) - (forward-ifdef (- arg))) - (while (< 0 arg) - (setq arg (1- arg)) - (beginning-of-line) - (let ((start (point))) - (if (not (hif-looking-at-endif)) - (hif-find-previous-relevant)) - (if (hif-looking-at-endif) - (hif-endif-to-ifdef) - (goto-char start) - (error "No previous #ifdef"))))) - - -(defun down-ifdef () - "Move point to beginning of nested ifdef or else-part." - (interactive) - (let ((start (point))) - (hif-find-next-relevant) - (if (or (hif-looking-at-ifX) (hif-looking-at-else)) - () - (goto-char start) - (error "No following #ifdef")))) - - -(defun up-ifdef () - "Move point to beginning of enclosing ifdef or else-part." - (interactive) - (beginning-of-line) - (let ((start (point))) - (if (not (hif-looking-at-endif)) - (hif-find-previous-relevant)) - (if (hif-looking-at-endif) - (hif-endif-to-ifdef)) - (if (= start (point)) - (error "No previous #ifdef")))) - -(defun next-ifdef (&optional arg) - "Move to the beginning of the next #ifX, #else, or #endif. -With argument, do this that many times." - (interactive "p") - (or arg (setq arg 1)) - (if (< arg 0) - (previous-ifdef (- arg))) - (while (< 0 arg) - (setq arg (1- arg)) - (hif-find-next-relevant) - (if (eolp) - (progn - (beginning-of-line) - (error "No following #ifdefs, #elses, or #endifs"))))) - -(defun previous-ifdef (&optional arg) - "Move to the beginning of the previous #ifX, #else, or #endif. -With argument, do this that many times." - (interactive "p") - (or arg (setq arg 1)) - (if (< arg 0) - (next-ifdef (- arg))) - (while (< 0 arg) - (setq arg (1- arg)) - (let ((start (point))) - (hif-find-previous-relevant) - (if (= start (point)) - (error "No previous #ifdefs, #elses, or #endifs") - )))) - - -;===%%SF%% parsing (End) === - - -;===%%SF%% hide-ifdef-hiding (Start) === - - -;;; A range is a structure with four components: -;;; ELSE-P True if there was an else clause for the ifdef. -;;; START The start of the range. (beginning of line) -;;; ELSE The else marker (beginning of line) -;;; Only valid if ELSE-P is true. -;;; END The end of the range. (beginning of line) - -(defun hif-make-range (else-p start end &optional else) - (list else-p start else end)) - -(defun hif-range-else-p (range) (elt range 0)) -(defun hif-range-start (range) (elt range 1)) -(defun hif-range-else (range) (elt range 2)) -(defun hif-range-end (range) (elt range 3)) - - - -;;; Find-Range -;;; The workhorse, it delimits the #if region. Reasonably simple: -;;; Skip until an #else or #endif is found, remembering positions. If -;;; an #else was found, skip some more, looking for the true #endif. - -(defun hif-find-range () - "Returns a Range structure describing the current #if region. -Point is left unchanged." -; (message "hif-find-range at %d" (point)) - (save-excursion - (beginning-of-line) - (let ((start (point)) - (else-p nil) - (else nil) - (end nil)) - ;; Part one. Look for either #endif or #else. - ;; This loop-and-a-half dedicated to E. Dijkstra. - (hif-find-next-relevant) - (while (hif-looking-at-ifX) ; Skip nested ifdef - (hif-ifdef-to-endif) - (hif-find-next-relevant)) - ;; Found either a #else or an #endif. - (cond ((hif-looking-at-else) - (setq else-p t) - (setq else (point))) - (t - (setq end (point)) ; (save-excursion (end-of-line) (point)) - )) - ;; If found #else, look for #endif. - (if else-p - (progn - (hif-find-next-relevant) - (while (hif-looking-at-ifX) ; Skip nested ifdef - (hif-ifdef-to-endif) - (hif-find-next-relevant)) - (if (hif-looking-at-else) - (error "Found two elses in a row? Broken!")) - (setq end (point)) ; (save-excursion (end-of-line) (point)) - )) - (hif-make-range else-p start end else)))) - - -;;; A bit slimy. -;;; NOTE: If there's an #ifdef at the beginning of the file, we can't -;;; hide it. There's no previous newline to replace. If we added -;;; one, we'd throw off all the counts. Feh. - -(defun hif-hide-line (point) - "Hide the line containing point. Does nothing if `hide-ifdef-lines' is nil." - (if hide-ifdef-lines - (save-excursion - (goto-char point) - (let ((modp (buffer-modified-p))) - (unwind-protect - (progn - (beginning-of-line) - (if (not (= (point) 1)) - (hide-ifdef-region (1- (point)) (point)))) - (set-buffer-modified-p modp)) - )) - )) - - -;;; Hif-Possibly-Hide -;;; There are four cases. The #ifX expression is "taken" if it -;;; the hide-ifdef-evaluator returns T. Presumably, this means the code -;;; inside the #ifdef would be included when the program was -;;; compiled. -;;; -;;; Case 1: #ifX taken, and there's an #else. -;;; The #else part must be hidden. The #if (then) part must be -;;; processed for nested #ifX's. -;;; Case 2: #ifX taken, and there's no #else. -;;; The #if part must be processed for nested #ifX's. -;;; Case 3: #ifX not taken, and there's an #else. -;;; The #if part must be hidden. The #else part must be processed -;;; for nested #ifs. -;;; Case 4: #ifX not taken, and there's no #else. -;;; The #ifX part must be hidden. -;;; -;;; Further processing is done by narrowing to the relevant region -;;; and just recursively calling hide-ifdef-guts. -;;; -;;; When hif-possibly-hide returns, point is at the end of the -;;; possibly-hidden range. - -(defun hif-recurse-on (start end) - "Call `hide-ifdef-guts' after narrowing to end of START line and END line." - (save-excursion - (save-restriction - (goto-char start) - (end-of-line) - (narrow-to-region (point) end) - (hide-ifdef-guts)))) - -(defun hif-possibly-hide () - "Called at #ifX expression, this hides those parts that should be -hidden, according to judgement of `hide-ifdef-evaluator'." -; (message "hif-possibly-hide") (sit-for 1) - (let ((test (hif-canonicalize)) - (range (hif-find-range))) -; (message "test = %s" test) (sit-for 1) - - (hif-hide-line (hif-range-end range)) - (if (funcall hide-ifdef-evaluator test) - (cond ((hif-range-else-p range) ; case 1 - (hif-hide-line (hif-range-else range)) - (hide-ifdef-region (hif-range-else range) - (1- (hif-range-end range))) - (hif-recurse-on (hif-range-start range) - (hif-range-else range))) - (t ; case 2 - (hif-recurse-on (hif-range-start range) - (hif-range-end range)))) - (cond ((hif-range-else-p range) ; case 3 - (hif-hide-line (hif-range-else range)) - (hide-ifdef-region (hif-range-start range) - (1- (hif-range-else range))) - (hif-recurse-on (hif-range-else range) - (hif-range-end range))) - (t ; case 4 - (hide-ifdef-region (point) - (1- (hif-range-end range)))) - )) - (hif-hide-line (hif-range-start range)) ; Always hide start. - (goto-char (hif-range-end range)) - (end-of-line) - )) - - - -(defun hide-ifdef-guts () - "Does the work of `hide-ifdefs', except for the work that's pointless -to redo on a recursive entry." -; (message "hide-ifdef-guts") - (save-excursion - (goto-char (point-min)) - (while (hif-find-any-ifX) - (hif-possibly-hide)))) - -;===%%SF%% hide-ifdef-hiding (End) === - - -;===%%SF%% exports (Start) === - -;;;###autoload -(defvar hide-ifdef-initially nil - "*Non-nil if `hide-ifdefs' should be called when Hide-Ifdef mode -is first activated.") - -(defvar hide-ifdef-hiding nil - "Non-nil if text might be hidden.") - -;;;###autoload -(defvar hide-ifdef-read-only nil - "*Set to non-nil if you want buffer to be read-only while hiding text.") - -(defvar hif-outside-read-only nil - "Internal variable. Saves the value of `buffer-read-only' while hiding.") - -;;;###autoload -(defvar hide-ifdef-lines nil - "*Set to t if you don't want to see the #ifX, #else, and #endif lines.") - -(defun hide-ifdef-toggle-read-only () - "Toggle hide-ifdef-read-only." - (interactive) - (setq hide-ifdef-read-only (not hide-ifdef-read-only)) - (message "Hide-Read-Only %s" - (if hide-ifdef-read-only "ON" "OFF")) - (if hide-ifdef-hiding - (setq buffer-read-only (or hide-ifdef-read-only hif-outside-read-only))) - (hif-update-mode-line)) - -(defun hide-ifdef-toggle-outside-read-only () - "Replacement for `toggle-read-only' within Hide Ifdef mode." - (interactive) - (setq hif-outside-read-only (not hif-outside-read-only)) - (message "Read only %s" - (if hif-outside-read-only "ON" "OFF")) - (setq buffer-read-only - (or (and hide-ifdef-hiding hide-ifdef-read-only) - hif-outside-read-only) - ) - (hif-update-mode-line)) - - -(defun hide-ifdef-define (var) - "Define a VAR so that #ifdef VAR would be included." - (interactive "SDefine what? ") - (hif-set-var var t) - (if hide-ifdef-hiding (hide-ifdefs))) - -(defun hide-ifdef-undef (var) - "Undefine a VAR so that #ifdef VAR would not be included." - (interactive "SUndefine what? ") - (hif-set-var var nil) - (if hide-ifdef-hiding (hide-ifdefs))) - - -(defun hide-ifdefs () - "Hide the contents of some #ifdefs. -Assume that defined symbols have been added to `hide-ifdef-env'. -The text hidden is the text that would not be included by the C -preprocessor if it were given the file with those symbols defined. - -Turn off hiding by calling `show-ifdef'." - - (interactive) - (message "Hiding...") - (if (not hide-ifdef-mode) - (hide-ifdef-mode 1)) ; turn on hide-ifdef-mode - (if hide-ifdef-hiding - (show-ifdefs)) ; Otherwise, deep confusion. - (if buffer-read-only (toggle-read-only)) ; make it writable temporarily - (setq selective-display t) - (setq hide-ifdef-hiding t) - (hide-ifdef-guts) - (if (or hide-ifdef-read-only hif-outside-read-only) - (toggle-read-only)) ; make it read only - (message "Hiding done")) - - -(defun show-ifdefs () - "Cancel the effects of `hide-ifdef'. The contents of all #ifdefs is shown." - (interactive) - (if buffer-read-only (toggle-read-only)) ; make it writable temporarily - (setq selective-display nil) ; defaults - (hif-show-all) - (if hif-outside-read-only - (toggle-read-only)) ; make it read only - (setq hide-ifdef-hiding nil)) - - -(defun hif-find-ifdef-block () - "Utility for hide and show `ifdef-block'. -Set top and bottom of ifdef block." - (let (max-bottom) - (save-excursion - (beginning-of-line) - (if (not (or (hif-looking-at-else) (hif-looking-at-ifX))) - (up-ifdef)) - (setq top (point)) - (hif-ifdef-to-endif) - (setq max-bottom (1- (point)))) - (save-excursion - (beginning-of-line) - (if (not (hif-looking-at-endif)) - (hif-find-next-relevant)) - (while (hif-looking-at-ifX) - (hif-ifdef-to-endif) - (hif-find-next-relevant)) - (setq bottom (min max-bottom (1- (point)))))) - ) - - -(defun hide-ifdef-block () - "Hide the ifdef block (true or false part) enclosing or before the cursor." - (interactive) - (if (not hide-ifdef-mode) - (hide-ifdef-mode 1)) - (if buffer-read-only (toggle-read-only)) - (setq selective-display t) - (let (top bottom) - (hif-find-ifdef-block) ; set top and bottom - dynamic scoping - (hide-ifdef-region top bottom) - (if hide-ifdef-lines - (progn - (hif-hide-line top) - (hif-hide-line (1+ bottom)))) - (setq hide-ifdef-hiding t)) - (if (or hide-ifdef-read-only hif-outside-read-only) - (toggle-read-only))) - - -(defun show-ifdef-block () - "Show the ifdef block (true or false part) enclosing or before the cursor." - (interactive) - (let ((old-read-only buffer-read-only)) - (if old-read-only (toggle-read-only)) - (if hide-ifdef-lines - (save-excursion - (beginning-of-line) - (hif-show-ifdef-region (1- (point)) (progn (end-of-line) (point)))) - - (let (top bottom) - (hif-find-ifdef-block) - (hif-show-ifdef-region (1- top) bottom)) - ) - - ; restore read only status since we dont know if all is shown. - (if old-read-only (toggle-read-only)))) - - -;;; definition alist support - -(defvar hide-ifdef-define-alist nil - "A global assoc list of pre-defined symbol lists") - -(defun hif-compress-define-list (env) - "Compress the define list ENV into a list of defined symbols only." - (let ((defs (mapcar '(lambda (arg) - (if (hif-lookup (car arg)) (car arg))) - env)) - (new-defs nil)) - (while defs - (if (car defs) - (setq new-defs (cons (car defs) new-defs))) - (setq defs (cdr defs))) - new-defs)) - -(defun hide-ifdef-set-define-alist (name) - "Set the association for NAME to `hide-ifdef-env'." - (interactive "SSet define list: ") - (setq hide-ifdef-define-alist - (cons (cons name (hif-compress-define-list hide-ifdef-env)) - hide-ifdef-define-alist))) - -(defun hide-ifdef-use-define-alist (name) - "Set `hide-ifdef-env' to the define list specified by NAME." - (interactive "SUse define list: ") - (let ((define-list (assoc name hide-ifdef-define-alist))) - (if define-list - (setq hide-ifdef-env - (mapcar '(lambda (arg) (cons arg t)) - (cdr define-list))) - (error "No define list for %s" name)) - (if hide-ifdef-hiding (hide-ifdefs)))) - -;;; hideif.el ends here - diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el deleted file mode 100644 index f64ed19dd37..00000000000 --- a/lisp/progmodes/icon.el +++ /dev/null @@ -1,559 +0,0 @@ -;;; icon.el --- mode for editing Icon code - -;; Copyright (C) 1989 Free Software Foundation, Inc. - -;; Author: Chris Smith <convex!csmith> -;; Created: 15 Feb 89 -;; Keywords: languages - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; A major mode for editing the Icon programming language. -;; -;; Note: use -;; (autoload 'icon-mode "icon" nil t) -;; (setq auto-mode-alist (cons '("\\.icn$" . icon-mode) auto-mode-alist)) -;; if not permanently installed in your emacs - -;;; Code: - -(defvar icon-mode-abbrev-table nil - "Abbrev table in use in Icon-mode buffers.") -(define-abbrev-table 'icon-mode-abbrev-table ()) - -(defvar icon-mode-map () - "Keymap used in Icon mode.") -(if icon-mode-map - () - (setq icon-mode-map (make-sparse-keymap)) - (define-key icon-mode-map "{" 'electric-icon-brace) - (define-key icon-mode-map "}" 'electric-icon-brace) - (define-key icon-mode-map "\e\C-h" 'mark-icon-function) - (define-key icon-mode-map "\e\C-a" 'beginning-of-icon-defun) - (define-key icon-mode-map "\e\C-e" 'end-of-icon-defun) - (define-key icon-mode-map "\e\C-q" 'indent-icon-exp) - (define-key icon-mode-map "\177" 'backward-delete-char-untabify) - (define-key icon-mode-map "\t" 'icon-indent-command)) - -(defvar icon-mode-syntax-table nil - "Syntax table in use in Icon-mode buffers.") - -(if icon-mode-syntax-table - () - (setq icon-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\\ "\\" icon-mode-syntax-table) - (modify-syntax-entry ?# "<" icon-mode-syntax-table) - (modify-syntax-entry ?\n ">" icon-mode-syntax-table) - (modify-syntax-entry ?$ "." icon-mode-syntax-table) - (modify-syntax-entry ?/ "." icon-mode-syntax-table) - (modify-syntax-entry ?* "." icon-mode-syntax-table) - (modify-syntax-entry ?+ "." icon-mode-syntax-table) - (modify-syntax-entry ?- "." icon-mode-syntax-table) - (modify-syntax-entry ?= "." icon-mode-syntax-table) - (modify-syntax-entry ?% "." icon-mode-syntax-table) - (modify-syntax-entry ?< "." icon-mode-syntax-table) - (modify-syntax-entry ?> "." icon-mode-syntax-table) - (modify-syntax-entry ?& "." icon-mode-syntax-table) - (modify-syntax-entry ?| "." icon-mode-syntax-table) - (modify-syntax-entry ?\' "\"" icon-mode-syntax-table)) - -(defconst icon-indent-level 4 - "*Indentation of Icon statements with respect to containing block.") -(defconst icon-brace-imaginary-offset 0 - "*Imagined indentation of a Icon open brace that actually follows a statement.") -(defconst icon-brace-offset 0 - "*Extra indentation for braces, compared with other text in same context.") -(defconst icon-continued-statement-offset 4 - "*Extra indent for lines not starting new statements.") -(defconst icon-continued-brace-offset 0 - "*Extra indent for substatements that start with open-braces. -This is in addition to icon-continued-statement-offset.") - -(defconst icon-auto-newline nil - "*Non-nil means automatically newline before and after braces -inserted in Icon code.") - -(defconst icon-tab-always-indent t - "*Non-nil means TAB in Icon mode should always reindent the current line, -regardless of where in the line point is when the TAB command is used.") - -(defun icon-mode () - "Major mode for editing Icon code. -Expression and list commands understand all Icon brackets. -Tab indents for Icon code. -Paragraphs are separated by blank lines only. -Delete converts tabs to spaces as it moves back. -\\{icon-mode-map} -Variables controlling indentation style: - icon-tab-always-indent - Non-nil means TAB in Icon mode should always reindent the current line, - regardless of where in the line point is when the TAB command is used. - icon-auto-newline - Non-nil means automatically newline before and after braces - inserted in Icon code. - icon-indent-level - Indentation of Icon statements within surrounding block. - The surrounding block's indentation is the indentation - of the line on which the open-brace appears. - icon-continued-statement-offset - Extra indentation given to a substatement, such as the - then-clause of an if or body of a while. - icon-continued-brace-offset - Extra indentation given to a brace that starts a substatement. - This is in addition to `icon-continued-statement-offset'. - icon-brace-offset - Extra indentation for line if it starts with an open brace. - icon-brace-imaginary-offset - An open brace following other text is treated as if it were - this far to the right of the start of its line. - -Turning on Icon mode calls the value of the variable `icon-mode-hook' -with no args, if that value is non-nil." - (interactive) - (kill-all-local-variables) - (use-local-map icon-mode-map) - (setq major-mode 'icon-mode) - (setq mode-name "Icon") - (setq local-abbrev-table icon-mode-abbrev-table) - (set-syntax-table icon-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'icon-indent-line) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "# ") - (make-local-variable 'comment-end) - (setq comment-end "") - (make-local-variable 'comment-column) - (setq comment-column 32) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "# *") - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'icon-comment-indent) - (run-hooks 'icon-mode-hook)) - -;; This is used by indent-for-comment to decide how much to -;; indent a comment in Icon code based on its context. -(defun icon-comment-indent () - (if (looking-at "^#") - 0 - (save-excursion - (skip-chars-backward " \t") - (max (if (bolp) 0 (1+ (current-column))) - comment-column)))) - -(defun electric-icon-brace (arg) - "Insert character and correct line's indentation." - (interactive "P") - (let (insertpos) - (if (and (not arg) - (eolp) - (or (save-excursion - (skip-chars-backward " \t") - (bolp)) - (if icon-auto-newline - (progn (icon-indent-line) (newline) t) - nil))) - (progn - (insert last-command-char) - (icon-indent-line) - (if icon-auto-newline - (progn - (newline) - ;; (newline) may have done auto-fill - (setq insertpos (- (point) 2)) - (icon-indent-line))) - (save-excursion - (if insertpos (goto-char (1+ insertpos))) - (delete-char -1)))) - (if insertpos - (save-excursion - (goto-char insertpos) - (self-insert-command (prefix-numeric-value arg))) - (self-insert-command (prefix-numeric-value arg))))) - -(defun icon-indent-command (&optional whole-exp) - (interactive "P") - "Indent current line as Icon code, or in some cases insert a tab character. -If `icon-tab-always-indent' is non-nil (the default), always indent current -line. Otherwise, indent the current line only if point is at the left margin -or in the line's indentation; otherwise insert a tab. - -A numeric argument, regardless of its value, means indent rigidly all the -lines of the expression starting after point so that this line becomes -properly indented. The relative indentation among the lines of the -expression are preserved." - (if whole-exp - ;; If arg, always indent this line as Icon - ;; and shift remaining lines of expression the same amount. - (let ((shift-amt (icon-indent-line)) - beg end) - (save-excursion - (if icon-tab-always-indent - (beginning-of-line)) - (setq beg (point)) - (forward-sexp 1) - (setq end (point)) - (goto-char beg) - (forward-line 1) - (setq beg (point))) - (if (> end beg) - (indent-code-rigidly beg end shift-amt "#"))) - (if (and (not icon-tab-always-indent) - (save-excursion - (skip-chars-backward " \t") - (not (bolp)))) - (insert-tab) - (icon-indent-line)))) - -(defun icon-indent-line () - "Indent current line as Icon code. -Return the amount the indentation changed by." - (let ((indent (calculate-icon-indent nil)) - beg shift-amt - (case-fold-search nil) - (pos (- (point-max) (point)))) - (beginning-of-line) - (setq beg (point)) - (cond ((eq indent nil) - (setq indent (current-indentation))) - ((eq indent t) - (setq indent (calculate-icon-indent-within-comment))) - ((looking-at "[ \t]*#") - (setq indent 0)) - (t - (skip-chars-forward " \t") - (if (listp indent) (setq indent (car indent))) - (cond ((and (looking-at "else\\b") - (not (looking-at "else\\s_"))) - (setq indent (save-excursion - (icon-backward-to-start-of-if) - (current-indentation)))) - ((or (= (following-char) ?}) - (looking-at "end\\b")) - (setq indent (- indent icon-indent-level))) - ((= (following-char) ?{) - (setq indent (+ indent icon-brace-offset)))))) - (skip-chars-forward " \t") - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - (delete-region beg (point)) - (indent-to indent) - ;; If initial point was within line's indentation, - ;; position after the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos)))) - shift-amt)) - -(defun calculate-icon-indent (&optional parse-start) - "Return appropriate indentation for current line as Icon code. -In usual case returns an integer: the column to indent to. -Returns nil if line starts inside a string, t if in a comment." - (save-excursion - (beginning-of-line) - (let ((indent-point (point)) - (case-fold-search nil) - state - containing-sexp - toplevel) - (if parse-start - (goto-char parse-start) - (setq toplevel (beginning-of-icon-defun))) - (while (< (point) indent-point) - (setq parse-start (point)) - (setq state (parse-partial-sexp (point) indent-point 0)) - (setq containing-sexp (car (cdr state)))) - (cond ((or (nth 3 state) (nth 4 state)) - ;; return nil or t if should not change this line - (nth 4 state)) - ((and containing-sexp - (/= (char-after containing-sexp) ?{)) - ;; line is expression, not statement: - ;; indent to just after the surrounding open. - (goto-char (1+ containing-sexp)) - (current-column)) - (t - (if toplevel - ;; Outside any procedures. - (progn (icon-backward-to-noncomment (point-min)) - (if (icon-is-continuation-line) - icon-continued-statement-offset 0)) - ;; Statement level. - (if (null containing-sexp) - (progn (beginning-of-icon-defun) - (setq containing-sexp (point)))) - (goto-char indent-point) - ;; Is it a continuation or a new statement? - ;; Find previous non-comment character. - (icon-backward-to-noncomment containing-sexp) - ;; Now we get the answer. - (if (icon-is-continuation-line) - ;; This line is continuation of preceding line's statement; - ;; indent icon-continued-statement-offset more than the - ;; first line of the statement. - (progn - (icon-backward-to-start-of-continued-exp containing-sexp) - (+ icon-continued-statement-offset (current-column) - (if (save-excursion (goto-char indent-point) - (skip-chars-forward " \t") - (eq (following-char) ?{)) - icon-continued-brace-offset 0))) - ;; This line starts a new statement. - ;; Position following last unclosed open. - (goto-char containing-sexp) - ;; Is line first statement after an open-brace? - (or - ;; If no, find that first statement and indent like it. - (save-excursion - (if (looking-at "procedure\\s ") - (forward-sexp 3) - (forward-char 1)) - (while (progn (skip-chars-forward " \t\n") - (looking-at "#")) - ;; Skip over comments following openbrace. - (forward-line 1)) - ;; The first following code counts - ;; if it is before the line we want to indent. - (and (< (point) indent-point) - (current-column))) - ;; If no previous statement, - ;; indent it relative to line brace is on. - ;; For open brace in column zero, don't let statement - ;; start there too. If icon-indent-level is zero, - ;; use icon-brace-offset + icon-continued-statement-offset - ;; instead. - ;; For open-braces not the first thing in a line, - ;; add in icon-brace-imaginary-offset. - (+ (if (and (bolp) (zerop icon-indent-level)) - (+ icon-brace-offset - icon-continued-statement-offset) - icon-indent-level) - ;; Move back over whitespace before the openbrace. - ;; If openbrace is not first nonwhite thing on the line, - ;; add the icon-brace-imaginary-offset. - (progn (skip-chars-backward " \t") - (if (bolp) 0 icon-brace-imaginary-offset)) - ;; Get initial indentation of the line we are on. - (current-indentation)))))))))) - -;; List of words to check for as the last thing on a line. -;; If cdr is t, next line is a continuation of the same statement, -;; if cdr is nil, next line starts a new (possibly indented) statement. - -(defconst icon-resword-alist - '(("by" . t) ("case" . t) ("create") ("do") ("dynamic" . t) ("else") - ("every" . t) ("if" . t) ("global" . t) ("initial" . t) - ("link" . t) ("local" . t) ("of") ("record" . t) ("repeat" . t) - ("static" . t) ("then") ("to" . t) ("until" . t) ("while" . t))) - -(defun icon-is-continuation-line () - (let* ((ch (preceding-char)) - (ch-syntax (char-syntax ch))) - (if (eq ch-syntax ?w) - (assoc (buffer-substring - (progn (forward-word -1) (point)) - (progn (forward-word 1) (point))) - icon-resword-alist) - (not (memq ch '(0 ?\; ?\} ?\{ ?\) ?\] ?\" ?\' ?\n)))))) - -(defun icon-backward-to-noncomment (lim) - (let (opoint stop) - (while (not stop) - (skip-chars-backward " \t\n\f" lim) - (setq opoint (point)) - (beginning-of-line) - (if (and (nth 5 (parse-partial-sexp (point) opoint)) - (< lim (point))) - (search-backward "#") - (setq stop t))))) - -(defun icon-backward-to-start-of-continued-exp (lim) - (if (memq (preceding-char) '(?\) ?\])) - (forward-sexp -1)) - (beginning-of-line) - (skip-chars-forward " \t") - (cond - ((<= (point) lim) (goto-char (1+ lim))) - ((not (icon-is-continued-line)) 0) - ((and (eq (char-syntax (following-char)) ?w) - (cdr - (assoc (buffer-substring (point) - (save-excursion (forward-word 1) (point))) - icon-resword-alist))) 0) - (t (end-of-line 0) (icon-backward-to-start-of-continued-exp lim)))) - -(defun icon-is-continued-line () - (save-excursion - (end-of-line 0) - (icon-is-continuation-line))) - -(defun icon-backward-to-start-of-if (&optional limit) - "Move to the start of the last \"unbalanced\" if." - (or limit (setq limit (save-excursion (beginning-of-icon-defun) (point)))) - (let ((if-level 1) - (case-fold-search nil)) - (while (not (zerop if-level)) - (backward-sexp 1) - (cond ((looking-at "else\\b") - (setq if-level (1+ if-level))) - ((looking-at "if\\b") - (setq if-level (1- if-level))) - ((< (point) limit) - (setq if-level 0) - (goto-char limit)))))) - -(defun mark-icon-function () - "Put mark at end of Icon function, point at beginning." - (interactive) - (push-mark (point)) - (end-of-icon-defun) - (push-mark (point)) - (beginning-of-line 0) - (beginning-of-icon-defun)) - -(defun beginning-of-icon-defun () - "Go to the start of the enclosing procedure; return t if at top level." - (interactive) - (if (re-search-backward "^procedure\\s \\|^end[ \t\n]" (point-min) 'move) - (looking-at "e") - t)) - -(defun end-of-icon-defun () - (interactive) - (if (not (bobp)) (forward-char -1)) - (re-search-forward "\\(\\s \\|^\\)end\\(\\s \\|$\\)" (point-max) 'move) - (forward-word -1) - (forward-line 1)) - -(defun indent-icon-exp () - "Indent each line of the Icon grouping following point." - (interactive) - (let ((indent-stack (list nil)) - (contain-stack (list (point))) - (case-fold-search nil) - restart outer-loop-done inner-loop-done state ostate - this-indent last-sexp - at-else at-brace at-do - (opoint (point)) - (next-depth 0)) - (save-excursion - (forward-sexp 1)) - (save-excursion - (setq outer-loop-done nil) - (while (and (not (eobp)) (not outer-loop-done)) - (setq last-depth next-depth) - ;; Compute how depth changes over this line - ;; plus enough other lines to get to one that - ;; does not end inside a comment or string. - ;; Meanwhile, do appropriate indentation on comment lines. - (setq innerloop-done nil) - (while (and (not innerloop-done) - (not (and (eobp) (setq outer-loop-done t)))) - (setq ostate state) - (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) - nil nil state)) - (setq next-depth (car state)) - (if (and (car (cdr (cdr state))) - (>= (car (cdr (cdr state))) 0)) - (setq last-sexp (car (cdr (cdr state))))) - (if (or (nth 4 ostate)) - (icon-indent-line)) - (if (or (nth 3 state)) - (forward-line 1) - (setq innerloop-done t))) - (if (<= next-depth 0) - (setq outer-loop-done t)) - (if outer-loop-done - nil - (if (/= last-depth next-depth) - (setq last-sexp nil)) - (while (> last-depth next-depth) - (setq indent-stack (cdr indent-stack) - contain-stack (cdr contain-stack) - last-depth (1- last-depth))) - (while (< last-depth next-depth) - (setq indent-stack (cons nil indent-stack) - contain-stack (cons nil contain-stack) - last-depth (1+ last-depth))) - (if (null (car contain-stack)) - (setcar contain-stack (or (car (cdr state)) - (save-excursion (forward-sexp -1) - (point))))) - (forward-line 1) - (skip-chars-forward " \t") - (if (eolp) - nil - (if (and (car indent-stack) - (>= (car indent-stack) 0)) - ;; Line is on an existing nesting level. - ;; Lines inside parens are handled specially. - (if (/= (char-after (car contain-stack)) ?{) - (setq this-indent (car indent-stack)) - ;; Line is at statement level. - ;; Is it a new statement? Is it an else? - ;; Find last non-comment character before this line - (save-excursion - (setq at-else (looking-at "else\\W")) - (setq at-brace (= (following-char) ?{)) - (icon-backward-to-noncomment opoint) - (if (icon-is-continuation-line) - ;; Preceding line did not end in comma or semi; - ;; indent this line icon-continued-statement-offset - ;; more than previous. - (progn - (icon-backward-to-start-of-continued-exp (car contain-stack)) - (setq this-indent - (+ icon-continued-statement-offset (current-column) - (if at-brace icon-continued-brace-offset 0)))) - ;; Preceding line ended in comma or semi; - ;; use the standard indent for this level. - (if at-else - (progn (icon-backward-to-start-of-if opoint) - (setq this-indent (current-indentation))) - (setq this-indent (car indent-stack)))))) - ;; Just started a new nesting level. - ;; Compute the standard indent for this level. - (let ((val (calculate-icon-indent - (if (car indent-stack) - (- (car indent-stack)))))) - (setcar indent-stack - (setq this-indent val)))) - ;; Adjust line indentation according to its contents - (if (or (= (following-char) ?}) - (looking-at "end\\b")) - (setq this-indent (- this-indent icon-indent-level))) - (if (= (following-char) ?{) - (setq this-indent (+ this-indent icon-brace-offset))) - ;; Put chosen indentation into effect. - (or (= (current-column) this-indent) - (progn - (delete-region (point) (progn (beginning-of-line) (point))) - (indent-to this-indent))) - ;; Indent any comment following the text. - (or (looking-at comment-start-skip) - (if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t) - (progn (indent-for-comment) (beginning-of-line)))))))))) - -;;; icon.el ends here diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el deleted file mode 100644 index a6b4f76713f..00000000000 --- a/lisp/progmodes/inf-lisp.el +++ /dev/null @@ -1,634 +0,0 @@ -;;; inf-lisp.el --- an inferior-lisp mode -;;; Copyright (C) 1988, 1993 Free Software Foundation, Inc. - -;; Author: Olin Shivers <shivers@cs.cmu.edu> -;; Keywords: processes, lisp - -;;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu). 8/88 - -;;; This file defines a a lisp-in-a-buffer package (inferior-lisp -;;; mode) built on top of comint mode. This version is more -;;; featureful, robust, and uniform than the Emacs 18 version. The -;;; key bindings are also more compatible with the bindings of Hemlock -;;; and Zwei (the Lisp Machine emacs). - -;;; Since this mode is built on top of the general command-interpreter-in- -;;; a-buffer mode (comint mode), it shares a common base functionality, -;;; and a common set of bindings, with all modes derived from comint mode. -;;; This makes these modes easier to use. - -;;; For documentation on the functionality provided by comint mode, and -;;; the hooks available for customising it, see the file comint.el. -;;; For further information on inferior-lisp mode, see the comments below. - -;;; Needs fixin: -;;; The load-file/compile-file default mechanism could be smarter -- it -;;; doesn't know about the relationship between filename extensions and -;;; whether the file is source or executable. If you compile foo.lisp -;;; with compile-file, then the next load-file should use foo.bin for -;;; the default, not foo.lisp. This is tricky to do right, particularly -;;; because the extension for executable files varies so much (.o, .bin, -;;; .lbin, .mo, .vo, .ao, ...). -;;; -;;; It would be nice if inferior-lisp (and inferior scheme, T, ...) modes -;;; had a verbose minor mode wherein sending or compiling defuns, etc. -;;; would be reflected in the transcript with suitable comments, e.g. -;;; ";;; redefining fact". Several ways to do this. Which is right? -;;; -;;; When sending text from a source file to a subprocess, the process-mark can -;;; move off the window, so you can lose sight of the process interactions. -;;; Maybe I should ensure the process mark is in the window when I send -;;; text to the process? Switch selectable? - -;;; Code: - -(require 'comint) -(require 'lisp-mode) - - -;;;###autoload -(defvar inferior-lisp-filter-regexp "\\`\\s *\\(:\\(\\w\\|\\s_\\)\\)?\\s *\\'" - "*What not to save on inferior Lisp's input history. -Input matching this regexp is not saved on the input history in Inferior Lisp -mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword -(as in :a, :c, etc.)") - -(defvar inferior-lisp-mode-map nil) -(cond ((not inferior-lisp-mode-map) - (setq inferior-lisp-mode-map - (copy-keymap comint-mode-map)) - (setq inferior-lisp-mode-map - (nconc inferior-lisp-mode-map shared-lisp-mode-map)) - (define-key inferior-lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) - (define-key inferior-lisp-mode-map "\C-c\C-l" 'lisp-load-file) - (define-key inferior-lisp-mode-map "\C-c\C-k" 'lisp-compile-file) - (define-key inferior-lisp-mode-map "\C-c\C-a" 'lisp-show-arglist) - (define-key inferior-lisp-mode-map "\C-c\C-d" 'lisp-describe-sym) - (define-key inferior-lisp-mode-map "\C-c\C-f" - 'lisp-show-function-documentation) - (define-key inferior-lisp-mode-map "\C-c\C-v" - 'lisp-show-variable-documentation))) - -;;; These commands augment Lisp mode, so you can process Lisp code in -;;; the source files. -(define-key lisp-mode-map "\M-\C-x" 'lisp-eval-defun) ; Gnu convention -(define-key lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) ; Gnu convention -(define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-defun) -(define-key lisp-mode-map "\C-c\C-r" 'lisp-eval-region) -(define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-defun) -(define-key lisp-mode-map "\C-c\C-z" 'switch-to-lisp) -(define-key lisp-mode-map "\C-c\C-l" 'lisp-load-file) -(define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file) ; "kompile" file -(define-key lisp-mode-map "\C-c\C-a" 'lisp-show-arglist) -(define-key lisp-mode-map "\C-c\C-d" 'lisp-describe-sym) -(define-key lisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation) -(define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation) - - -;;; This function exists for backwards compatibility. -;;; Previous versions of this package bound commands to C-c <letter> -;;; bindings, which is not allowed by the gnumacs standard. - -;;; "This function binds many inferior-lisp commands to C-c <letter> bindings, -;;;where they are more accessible. C-c <letter> bindings are reserved for the -;;;user, so these bindings are non-standard. If you want them, you should -;;;have this function called by the inferior-lisp-load-hook: -;;; (setq inferior-lisp-load-hook '(inferior-lisp-install-letter-bindings)) -;;;You can modify this function to install just the bindings you want." -(defun inferior-lisp-install-letter-bindings () - (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go) - (define-key lisp-mode-map "\C-cr" 'lisp-eval-region-and-go) - (define-key lisp-mode-map "\C-cc" 'lisp-compile-defun-and-go) - (define-key lisp-mode-map "\C-cz" 'switch-to-lisp) - (define-key lisp-mode-map "\C-cl" 'lisp-load-file) - (define-key lisp-mode-map "\C-ck" 'lisp-compile-file) - (define-key lisp-mode-map "\C-ca" 'lisp-show-arglist) - (define-key lisp-mode-map "\C-cd" 'lisp-describe-sym) - (define-key lisp-mode-map "\C-cf" 'lisp-show-function-documentation) - (define-key lisp-mode-map "\C-cv" 'lisp-show-variable-documentation) - - (define-key inferior-lisp-mode-map "\C-cl" 'lisp-load-file) - (define-key inferior-lisp-mode-map "\C-ck" 'lisp-compile-file) - (define-key inferior-lisp-mode-map "\C-ca" 'lisp-show-arglist) - (define-key inferior-lisp-mode-map "\C-cd" 'lisp-describe-sym) - (define-key inferior-lisp-mode-map "\C-cf" 'lisp-show-function-documentation) - (define-key inferior-lisp-mode-map "\C-cv" - 'lisp-show-variable-documentation)) - - -;;;###autoload -(defvar inferior-lisp-program "lisp" - "*Program name for invoking an inferior Lisp with for Inferior Lisp mode.") - -;;;###autoload -(defvar inferior-lisp-load-command "(load \"%s\")\n" - "*Format-string for building a Lisp expression to load a file. -This format string should use `%s' to substitute a file name -and should result in a Lisp expression that will command the inferior Lisp -to load that file. The default works acceptably on most Lisps. -The string \"(progn (load \\\"%s\\\" :verbose nil :print t) (values))\\\n\" -produces cosmetically superior output for this application, -but it works only in Common Lisp.") - -;;;###autoload -(defvar inferior-lisp-prompt "^[^> \n]*>+:? *" - "Regexp to recognise prompts in the Inferior Lisp mode. -Defaults to \"^[^> \\n]*>+:? *\", which works pretty good for Lucid, kcl, -and franz. This variable is used to initialize `comint-prompt-regexp' in the -Inferior Lisp buffer. - -More precise choices: -Lucid Common Lisp: \"^\\(>\\|\\(->\\)+\\) *\" -franz: \"^\\(->\\|<[0-9]*>:\\) *\" -kcl: \"^>+ *\" - -This is a fine thing to set in your .emacs file.") - -(defvar inferior-lisp-buffer nil "*The current inferior-lisp process buffer. - -MULTIPLE PROCESS SUPPORT -=========================================================================== -To run multiple Lisp processes, you start the first up -with \\[inferior-lisp]. It will be in a buffer named `*inferior-lisp*'. -Rename this buffer with \\[rename-buffer]. You may now start up a new -process with another \\[inferior-lisp]. It will be in a new buffer, -named `*inferior-lisp*'. You can switch between the different process -buffers with \\[switch-to-buffer]. - -Commands that send text from source buffers to Lisp processes -- -like `lisp-eval-defun' or `lisp-show-arglist' -- have to choose a process -to send to, when you have more than one Lisp process around. This -is determined by the global variable `inferior-lisp-buffer'. Suppose you -have three inferior Lisps running: - Buffer Process - foo inferior-lisp - bar inferior-lisp<2> - *inferior-lisp* inferior-lisp<3> -If you do a \\[lisp-eval-defun] command on some Lisp source code, -what process do you send it to? - -- If you're in a process buffer (foo, bar, or *inferior-lisp*), - you send it to that process. -- If you're in some other buffer (e.g., a source file), you - send it to the process attached to buffer `inferior-lisp-buffer'. -This process selection is performed by function `inferior-lisp-proc'. - -Whenever \\[inferior-lisp] fires up a new process, it resets -`inferior-lisp-buffer' to be the new process's buffer. If you only run -one process, this does the right thing. If you run multiple -processes, you can change `inferior-lisp-buffer' to another process -buffer with \\[set-variable].") - -;;;###autoload -(defvar inferior-lisp-mode-hook '() - "*Hook for customising Inferior Lisp mode.") - -(defun inferior-lisp-mode () - "Major mode for interacting with an inferior Lisp process. -Runs a Lisp interpreter as a subprocess of Emacs, with Lisp I/O through an -Emacs buffer. Variable `inferior-lisp-program' controls which Lisp interpreter -is run. Variables `inferior-lisp-prompt', `inferior-lisp-filter-regexp' and -`inferior-lisp-load-command' can customize this mode for different Lisp -interpreters. - -For information on running multiple processes in multiple buffers, see -documentation for variable `inferior-lisp-buffer'. - -\\{inferior-lisp-mode-map} - -Customisation: Entry to this mode runs the hooks on `comint-mode-hook' and -`inferior-lisp-mode-hook' (in that order). - -You can send text to the inferior Lisp process from other buffers containing -Lisp source. - switch-to-lisp switches the current buffer to the Lisp process buffer. - lisp-eval-defun sends the current defun to the Lisp process. - lisp-compile-defun compiles the current defun. - lisp-eval-region sends the current region to the Lisp process. - lisp-compile-region compiles the current region. - - Prefixing the lisp-eval/compile-defun/region commands with - a \\[universal-argument] causes a switch to the Lisp process buffer after sending - the text. - -Commands: -Return after the end of the process' output sends the text from the - end of process to point. -Return before the end of the process' output copies the sexp ending at point - to the end of the process' output, and sends it. -Delete converts tabs to spaces as it moves back. -Tab indents for Lisp; with argument, shifts rest - of expression rigidly with the current line. -C-M-q does Tab on each line starting within following expression. -Paragraphs are separated only by blank lines. Semicolons start comments. -If you accidentally suspend your process, use \\[comint-continue-subjob] -to continue it." - (interactive) - (comint-mode) - (setq comint-prompt-regexp inferior-lisp-prompt) - (setq major-mode 'inferior-lisp-mode) - (setq mode-name "Inferior Lisp") - (setq mode-line-process '(": %s")) - (lisp-mode-variables t) - (use-local-map inferior-lisp-mode-map) ;c-c c-k for "kompile" file - (setq comint-get-old-input (function lisp-get-old-input)) - (setq comint-input-filter (function lisp-input-filter)) - (setq comint-input-sentinel 'ignore) - (run-hooks 'inferior-lisp-mode-hook)) - -(defun lisp-get-old-input () - "Return a string containing the sexp ending at point." - (save-excursion - (let ((end (point))) - (backward-sexp) - (buffer-substring (point) end)))) - -(defun lisp-input-filter (str) - "t if STR does not match `inferior-lisp-filter-regexp'." - (not (string-match inferior-lisp-filter-regexp str))) - -;;;###autoload -(defun inferior-lisp (cmd) - "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'. -If there is a process already running in `*inferior-lisp*', just switch -to that buffer. -With argument, allows you to edit the command line (default is value -of `inferior-lisp-program'). Runs the hooks from -`inferior-lisp-mode-hook' (after the `comint-mode-hook' is run). -\(Type \\[describe-mode] in the process buffer for a list of commands.)" - (interactive (list (if current-prefix-arg - (read-string "Run lisp: " inferior-lisp-program) - inferior-lisp-program))) - (if (not (comint-check-proc "*inferior-lisp*")) - (let ((cmdlist (inferior-lisp-args-to-list cmd))) - (set-buffer (apply (function make-comint) - "inferior-lisp" (car cmdlist) nil (cdr cmdlist))) - (inferior-lisp-mode))) - (setq inferior-lisp-buffer "*inferior-lisp*") - (switch-to-buffer "*inferior-lisp*")) - -;;;###autoload -(defalias 'run-lisp 'inferior-lisp) - -;;; Break a string up into a list of arguments. -;;; This will break if you have an argument with whitespace, as in -;;; string = "-ab +c -x 'you lose'". -(defun inferior-lisp-args-to-list (string) - (let ((where (string-match "[ \t]" string))) - (cond ((null where) (list string)) - ((not (= where 0)) - (cons (substring string 0 where) - (inferior-lisp-args-to-list (substring string (+ 1 where) - (length string))))) - (t (let ((pos (string-match "[^ \t]" string))) - (if (null pos) - nil - (inferior-lisp-args-to-list (substring string pos - (length string))))))))) - -(defun lisp-eval-region (start end &optional and-go) - "Send the current region to the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "r\nP") - (comint-send-region (inferior-lisp-proc) start end) - (comint-send-string (inferior-lisp-proc) "\n") - (if and-go (switch-to-lisp t))) - -(defun lisp-eval-defun (&optional and-go) - "Send the current defun to the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "P") - (save-excursion - (end-of-defun) - (skip-chars-backward " \t\n\r\f") ; Makes allegro happy - (let ((end (point))) - (beginning-of-defun) - (lisp-eval-region (point) end))) - (if and-go (switch-to-lisp t))) - -(defun lisp-eval-last-sexp (&optional and-go) - "Send the previous sexp to the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "P") - (lisp-eval-region (save-excursion (backward-sexp) (point)) (point) and-go)) - -;;; Common Lisp COMPILE sux. -(defun lisp-compile-region (start end &optional and-go) - "Compile the current region in the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "r\nP") - (comint-send-string - (inferior-lisp-proc) - (format "(funcall (compile nil `(lambda () (progn 'compile %s))))\n" - (buffer-substring start end))) - (if and-go (switch-to-lisp t))) - -(defun lisp-compile-defun (&optional and-go) - "Compile the current defun in the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "P") - (save-excursion - (end-of-defun) - (skip-chars-backward " \t\n\r\f") ; Makes allegro happy - (let ((e (point))) - (beginning-of-defun) - (lisp-compile-region (point) e))) - (if and-go (switch-to-lisp t))) - -(defun switch-to-lisp (eob-p) - "Switch to the inferior Lisp process buffer. -With argument, positions cursor at end of buffer." - (interactive "P") - (if (get-buffer inferior-lisp-buffer) - (pop-to-buffer inferior-lisp-buffer) - (error "No current inferior Lisp buffer")) - (cond (eob-p - (push-mark) - (goto-char (point-max))))) - - -;;; Now that lisp-compile/eval-defun/region takes an optional prefix arg, -;;; these commands are redundant. But they are kept around for the user -;;; to bind if he wishes, for backwards functionality, and because it's -;;; easier to type C-c e than C-u C-c C-e. - -(defun lisp-eval-region-and-go (start end) - "Send the current region to the inferior Lisp, and switch to its buffer." - (interactive "r") - (lisp-eval-region start end t)) - -(defun lisp-eval-defun-and-go () - "Send the current defun to the inferior Lisp, and switch to its buffer." - (interactive) - (lisp-eval-defun t)) - -(defun lisp-compile-region-and-go (start end) - "Compile the current region in the inferior Lisp, and switch to its buffer." - (interactive "r") - (lisp-compile-region start end t)) - -(defun lisp-compile-defun-and-go () - "Compile the current defun in the inferior Lisp, and switch to its buffer." - (interactive) - (lisp-compile-defun t)) - -;;; A version of the form in H. Shevis' soar-mode.el package. Less robust. -;;; (defun lisp-compile-sexp (start end) -;;; "Compile the s-expression bounded by START and END in the inferior lisp. -;;; If the sexp isn't a DEFUN form, it is evaluated instead." -;;; (cond ((looking-at "(defun\\s +") -;;; (goto-char (match-end 0)) -;;; (let ((name-start (point))) -;;; (forward-sexp 1) -;;; (process-send-string "inferior-lisp" -;;; (format "(compile '%s #'(lambda " -;;; (buffer-substring name-start -;;; (point))))) -;;; (let ((body-start (point))) -;;; (goto-char start) (forward-sexp 1) ; Can't use end-of-defun. -;;; (process-send-region "inferior-lisp" -;;; (buffer-substring body-start (point)))) -;;; (process-send-string "inferior-lisp" ")\n")) -;;; (t (lisp-eval-region start end))))) -;;; -;;; (defun lisp-compile-region (start end) -;;; "Each s-expression in the current region is compiled (if a DEFUN) -;;; or evaluated (if not) in the inferior lisp." -;;; (interactive "r") -;;; (save-excursion -;;; (goto-char start) (end-of-defun) (beginning-of-defun) ; error check -;;; (if (< (point) start) (error "region begins in middle of defun")) -;;; (goto-char start) -;;; (let ((s start)) -;;; (end-of-defun) -;;; (while (<= (point) end) ; Zip through -;;; (lisp-compile-sexp s (point)) ; compiling up defun-sized chunks. -;;; (setq s (point)) -;;; (end-of-defun)) -;;; (if (< s end) (lisp-compile-sexp s end))))) -;;; -;;; End of HS-style code - - -(defvar lisp-prev-l/c-dir/file nil - "Record last directory and file used in loading or compiling. -This holds a cons cell of the form `(DIRECTORY . FILE)' -describing the last `lisp-load-file' or `lisp-compile-file' command.") - -(defvar lisp-source-modes '(lisp-mode) - "*Used to determine if a buffer contains Lisp source code. -If it's loaded into a buffer that is in one of these major modes, it's -considered a Lisp source file by `lisp-load-file' and `lisp-compile-file'. -Used by these commands to determine defaults.") - -(defun lisp-load-file (file-name) - "Load a Lisp file into the inferior Lisp process." - (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file - lisp-source-modes nil)) ; NIL because LOAD - ; doesn't need an exact name - (comint-check-source file-name) ; Check to see if buffer needs saved. - (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name) - (file-name-nondirectory file-name))) - (comint-send-string (inferior-lisp-proc) - (format inferior-lisp-load-command file-name)) - (switch-to-lisp t)) - - -(defun lisp-compile-file (file-name) - "Compile a Lisp file in the inferior Lisp process." - (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file - lisp-source-modes nil)) ; NIL = don't need - ; suffix .lisp - (comint-check-source file-name) ; Check to see if buffer needs saved. - (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name) - (file-name-nondirectory file-name))) - (comint-send-string (inferior-lisp-proc) (concat "(compile-file \"" - file-name - "\"\)\n")) - (switch-to-lisp t)) - - - -;;; Documentation functions: function doc, var doc, arglist, and -;;; describe symbol. -;;; =========================================================================== - -;;; Command strings -;;; =============== - -(defvar lisp-function-doc-command - "(let ((fn '%s)) - (format t \"Documentation for ~a:~&~a\" - fn (documentation fn 'function)) - (values))\n" - "Command to query inferior Lisp for a function's documentation.") - -(defvar lisp-var-doc-command - "(let ((v '%s)) - (format t \"Documentation for ~a:~&~a\" - v (documentation v 'variable)) - (values))\n" - "Command to query inferior Lisp for a variable's documentation.") - -(defvar lisp-arglist-command - "(let ((fn '%s)) - (format t \"Arglist for ~a: ~a\" fn (arglist fn)) - (values))\n" - "Command to query inferior Lisp for a function's arglist.") - -(defvar lisp-describe-sym-command - "(describe '%s)\n" - "Command to query inferior Lisp for a variable's documentation.") - - -;;; Ancillary functions -;;; =================== - -;;; Reads a string from the user. -(defun lisp-symprompt (prompt default) - (list (let* ((prompt (if default - (format "%s (default %s): " prompt default) - (concat prompt ": "))) - (ans (read-string prompt))) - (if (zerop (length ans)) default ans)))) - - -;;; Adapted from function-called-at-point in help.el. -(defun lisp-fn-called-at-pt () - "Returns the name of the function called in the current call. -The value is nil if it can't find one." - (condition-case nil - (save-excursion - (save-restriction - (narrow-to-region (max (point-min) (- (point) 1000)) (point-max)) - (backward-up-list 1) - (forward-char 1) - (let ((obj (read (current-buffer)))) - (and (symbolp obj) obj)))) - (error nil))) - - -;;; Adapted from variable-at-point in help.el. -(defun lisp-var-at-pt () - (condition-case () - (save-excursion - (forward-sexp -1) - (skip-chars-forward "'") - (let ((obj (read (current-buffer)))) - (and (symbolp obj) obj))) - (error nil))) - - -;;; Documentation functions: fn and var doc, arglist, and symbol describe. -;;; ====================================================================== - -(defun lisp-show-function-documentation (fn) - "Send a command to the inferior Lisp to give documentation for function FN. -See variable `lisp-function-doc-command'." - (interactive (lisp-symprompt "Function doc" (lisp-fn-called-at-pt))) - (comint-proc-query (inferior-lisp-proc) - (format lisp-function-doc-command fn))) - -(defun lisp-show-variable-documentation (var) - "Send a command to the inferior Lisp to give documentation for function FN. -See variable `lisp-var-doc-command'." - (interactive (lisp-symprompt "Variable doc" (lisp-var-at-pt))) - (comint-proc-query (inferior-lisp-proc) (format lisp-var-doc-command var))) - -(defun lisp-show-arglist (fn) - "Send a query to the inferior Lisp for the arglist for function FN. -See variable `lisp-arglist-command'." - (interactive (lisp-symprompt "Arglist" (lisp-fn-called-at-pt))) - (comint-proc-query (inferior-lisp-proc) (format lisp-arglist-command fn))) - -(defun lisp-describe-sym (sym) - "Send a command to the inferior Lisp to describe symbol SYM. -See variable `lisp-describe-sym-command'." - (interactive (lisp-symprompt "Describe" (lisp-var-at-pt))) - (comint-proc-query (inferior-lisp-proc) - (format lisp-describe-sym-command sym))) - - -;; "Returns the current inferior Lisp process. -;; See variable `inferior-lisp-buffer'." -(defun inferior-lisp-proc () - (let ((proc (get-buffer-process (if (eq major-mode 'inferior-lisp-mode) - (current-buffer) - inferior-lisp-buffer)))) - (or proc - (error "No Lisp subprocess; see variable `inferior-lisp-buffer'")))) - - -;;; Do the user's customisation... -;;;=============================== -(defvar inferior-lisp-load-hook nil - "This hook is run when the library `inf-lisp' is loaded. -This is a good place to put keybindings.") - -(run-hooks 'inferior-lisp-load-hook) - -;;; CHANGE LOG -;;; =========================================================================== -;;; 7/21/92 Jim Blandy -;;; - Changed all uses of the cmulisp name or prefix to inferior-lisp; -;;; this is now the official inferior lisp package. Use the global -;;; ChangeLog from now on. -;;; 5/24/90 Olin -;;; - Split cmulisp and cmushell modes into separate files. -;;; Not only is this a good idea, it's apparently the way it'll be rel 19. -;;; - Upgraded process sends to use comint-send-string instead of -;;; process-send-string. -;;; - Explicit references to process "cmulisp" have been replaced with -;;; (cmulisp-proc). This allows better handling of multiple process bufs. -;;; - Added process query and var/function/symbol documentation -;;; commands. Based on code written by Douglas Roberts. -;;; - Added lisp-eval-last-sexp, bound to C-x C-e. -;;; -;;; 9/20/90 Olin -;;; Added a save-restriction to lisp-fn-called-at-pt. This bug and fix -;;; reported by Lennart Staflin. -;;; -;;; 3/12/90 Olin -;;; - lisp-load-file and lisp-compile-file no longer switch-to-lisp. -;;; Tale suggested this. -;;; - Reversed this decision 7/15/91. You need the visual feedback. -;;; -;;; 7/25/91 Olin -;;; Changed all keybindings of the form C-c <letter>. These are -;;; supposed to be reserved for the user to bind. This affected -;;; mainly the compile/eval-defun/region[-and-go] commands. -;;; This was painful, but necessary to adhere to the gnumacs standard. -;;; For some backwards compatibility, see the -;;; cmulisp-install-letter-bindings -;;; function. -;;; -;;; 8/2/91 Olin -;;; - The lisp-compile/eval-defun/region commands now take a prefix arg, -;;; which means switch-to-lisp after sending the text to the Lisp process. -;;; This obsoletes all the -and-go commands. The -and-go commands are -;;; kept around for historical reasons, and because the user can bind -;;; them to key sequences shorter than C-u C-c C-<letter>. -;;; - If M-x cmulisp is invoked with a prefix arg, it allows you to -;;; edit the command line. - -(provide 'inf-lisp) - -;;; inf-lisp.el ends here diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el deleted file mode 100644 index 042ca570ac1..00000000000 --- a/lisp/progmodes/make-mode.el +++ /dev/null @@ -1,1073 +0,0 @@ -;;; makefile.el --- makefile editing commands for Emacs - -;; Copyright (C) 1992, 1994 Free Software Foundation, Inc. - -;; Author: Thomas Neumann <tom@smart.bo.open.de> -;; Eric S. Raymond <esr@snark.thyrsus.com> -;; Adapted-By: ESR -;; Keywords: unix, tools - -;; RMS: -;; This needs work. The electric characters are too obnoxious. -;; It should not define C-c LETTER. -;; It should support knowing the list of existing macros and targets -;; via M-TAB completion, not by preempting insertion of references. -;; Also, the doc strings need fixing: the first line doesn't stand alone, -;; and other usage is not high quality. Symbol names don't have `...'. - -;; So, for the meantime, this is not the default mode for makefiles. - -;; $Id: makefile.el,v 1.16 1994/02/28 18:05:55 tom Exp $ - -;; 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 1, 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. - -;; 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; A major mode for editing makefiles. The mode knows about Makefile -;; syntax and defines M-n and M-p to move to next and previous productions. -;; -;; The keys $, =, : and . are electric; they try to help you fill in a -;; macro reference, macro definition, ordinary target name, or special -;; target name, respectively. Such names are completed using a list of -;; targets and macro names parsed out of the makefile. This list is -;; automatically updated, if necessary, whenever you invoke one of -;; these commands. You can force it to be updated with C-c C-p. -;; -;; The command C-c f adds certain filenames in the current directory -;; as targets. You can filter out filenames by setting the variable -;; makefile-ignored-files-in-pickup-regex. -;; -;; The command C-c C-u grinds for a bit, then pops up a report buffer -;; showing which target names are up-to-date with respect to their -;; prerequisites, which targets are out-of-date, and which have no -;; prerequisites. -;; -;; The command C-c b pops up a browser window listing all target and -;; macro names. You can mark or unmark items wit C-c SPC, and insert -;; all marked items back in the Makefile with C-c TAB. -;; -;; The command C-c TAB in the makefile buffer inserts a GNU make builtin. -;; You will be prompted for the builtin's args. -;; -;; There are numerous other customization variables. - -;;; Code: - -(provide 'makefile) - -;;; ------------------------------------------------------------ -;;; Configurable stuff -;;; ------------------------------------------------------------ - -(defconst makefile-mode-name "Makefile" - "The \"pretty name\" of makefile-mode, as it appears in the modeline.") - -(defvar makefile-browser-buffer-name "*Macros and Targets*" - "Name of the macro- and target browser buffer.") - -(defvar makefile-target-colon ":" - "The string that gets appended to all target names -inserted by makefile-insert-target. -\":\" or \"::\" are quite common values.") - -(defvar makefile-macro-assign " = " - "The string that gets appended to all macro names -inserted by makefile-insert-macro. -The normal value should be \" = \", since this is what -standard make expects. However, newer makes such as dmake -allow a larger variety of different macro assignments, so you -might prefer to use \" += \" or \" := \" .") - -(defvar makefile-use-curly-braces-for-macros-p nil - "Controls the style of generated macro references. -Set this variable to a non-nil value if you prefer curly braces -in macro-references, so it looks like ${this}. A value of nil -will cause makefile-mode to use parentheses, making macro references -look like $(this) .") - -(defvar makefile-tab-after-target-colon t - "If you want a TAB (instead of a space) to be appended after the -target colon, then set this to a non-nil value.") - -(defvar makefile-browser-leftmost-column 10 - "Number of blanks to the left of the browser selection mark.") - -(defvar makefile-browser-cursor-column 10 - "Column in which the cursor is positioned when it moves -up or down in the browser.") - -(defvar makefile-browser-selected-mark "+ " - "String used to mark selected entries in the browser.") - -(defvar makefile-browser-unselected-mark " " - "String used to mark unselected entries in the browser.") - -(defvar makefile-browser-auto-advance-after-selection-p t - "If non-nil, the cursor will automagically advance to the next line after -an item has been selected in the browser.") - -(defvar makefile-pickup-everything-picks-up-filenames-p nil - "If non-nil, makefile-pickup-everything also picks up filenames as targets -(i.e. it calls makefile-find-filenames-as-targets), otherwise filenames are -omitted.") - -(defvar makefile-cleanup-continuations-p t - "If non-nil, makefile-mode will assure that no line in the file ends with a -backslash (the continuation character) followed by any whitespace. This is -done by silently removing the trailing whitespace, leaving the backslash itself -intact. IMPORTANT: Please note that enabling this option causes makefile-mode -to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'.") - -(defvar makefile-browser-hook '() - "A function or list of functions to be called just before the -browser is entered. This is executed in the makefile buffer.") - -;; -;; Special targets for DMake, Sun's make ... -;; -(defvar makefile-special-targets-list - '(("DEFAULT") ("DONE") ("ERROR") ("EXPORT") - ("FAILED") ("GROUPEPILOG") ("GROUPPROLOG") ("IGNORE") - ("IMPORT") ("INCLUDE") ("INCLUDEDIRS") ("INIT") - ("KEEP_STATE") ("MAKEFILES") ("MAKE_VERSION") ("NO_PARALLEL") - ("PARALLEL") ("PHONY") ("PRECIOUS") ("REMOVE") - ("SCCS_GET") ("SILENT") ("SOURCE") ("SUFFIXES") - ("WAIT") ("c.o") ("C.o") ("m.o") - ("el.elc") ("y.c") ("s.o")) - "List of special targets. You will be offered to complete -on one of those in the minibuffer whenever you enter a \".\" -at the beginning of a line in makefile-mode.") - -(defvar makefile-runtime-macros-list - '(("@") ("&") (">") ("<") ("*") ("^") ("?") ("%")) - "List of macros that are resolved by make at runtime. -If you insert a macro reference using makefile-insert-macro-ref, the name -of the macro is checked against this list. If it can be found its name will -not be enclosed in { } or ( ).") - -(defconst makefile-dependency-regex - "^[^ \t#:]+\\([ \t]+[^ \t#:]+\\)*[ \t]*:\\([ \t]*$\\|\\([^=\n].*$\\)\\)" - "Regex used to find dependency lines in a makefile.") - -(defconst makefile-macroassign-regex - "^[^ \t][^:#=]*[\\*:\\+]?:?=.*$" - "Regex used to find macro assignment lines in a makefile.") - -(defconst makefile-ignored-files-in-pickup-regex - "\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)\\|\\(\\.[chy]\\)" - "Regex for filenames that will NOT be included in the target list.") - -;;; ------------------------------------------------------------ -;;; The following configurable variables are used in the -;;; up-to-date overview . -;;; The standard configuration assumes that your `make' program -;;; can be run in question/query mode using the `-q' option, this -;;; means that the command -;;; -;;; make -q foo -;;; -;;; should return an exit status of zero if the target `foo' is -;;; up to date and a nonzero exit status otherwise. -;;; Many makes can do this although the docs/manpages do not mention -;;; it. Try it with your favourite one. GNU make, System V make, and -;;; Dennis Vadura's DMake have no problems. -;;; Set the variable `makefile-brave-make' to the name of the -;;; make utility that does this on your system. -;;; To understand what this is all about see the function definition -;;; of `makefile-query-by-make-minus-q' . -;;; ------------------------------------------------------------ - -(defvar makefile-brave-make "make" - "A make that can handle the \'-q\' option.") - -(defvar makefile-query-one-target-method 'makefile-query-by-make-minus-q - "A function symbol [one that can be used as the first argument to -funcall] that provides a function that must conform to the following -interface: - -* As its first argument, it must accept the name of the target to - be checked, as a string. - -* As its second argument, it may accept the name of a makefile - as a string. Depending on what you're going to do you may - not need this. - -* It must return the integer value 0 (zero) if the given target - should be considered up-to-date in the context of the given - makefile, any nonzero integer value otherwise.") - -(defvar makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*" - "Name of the Up-to-date overview buffer.") - -;;; --- end of up-to-date-overview configuration ------------------ - -(defvar makefile-mode-map nil - "The keymap that is used in makefile-mode.") -(if makefile-mode-map - () - (setq makefile-mode-map (make-sparse-keymap)) - ;; set up the keymap - (define-key makefile-mode-map "$" 'makefile-insert-macro-ref) - (define-key makefile-mode-map "\C-c:" 'makefile-insert-target-ref) - (define-key makefile-mode-map ":" 'makefile-electric-colon) - (define-key makefile-mode-map "=" 'makefile-electric-equal) - (define-key makefile-mode-map "." 'makefile-electric-dot) - (define-key makefile-mode-map "\C-c\C-f" 'makefile-pickup-filenames-as-targets) - (define-key makefile-mode-map "\C-c\C-b" 'makefile-switch-to-browser) - (define-key makefile-mode-map "\C-c\C-p" 'makefile-pickup-everything) - (define-key makefile-mode-map "\C-c\C-u" 'makefile-create-up-to-date-overview) - (define-key makefile-mode-map "\C-c\C-i" 'makefile-insert-gmake-function) - (define-key makefile-mode-map "\M-p" 'makefile-previous-dependency) - (define-key makefile-mode-map "\M-n" 'makefile-next-dependency)) - -(defvar makefile-browser-map nil - "The keymap that is used in the macro- and target browser.") -(if makefile-browser-map - () - (setq makefile-browser-map (make-sparse-keymap)) - (define-key makefile-browser-map "n" 'makefile-browser-next-line) - (define-key makefile-browser-map "\C-n" 'makefile-browser-next-line) - (define-key makefile-browser-map "p" 'makefile-browser-previous-line) - (define-key makefile-browser-map "\C-p" 'makefile-browser-previous-line) - (define-key makefile-browser-map " " 'makefile-browser-toggle) - (define-key makefile-browser-map "i" 'makefile-browser-insert-selection) - (define-key makefile-browser-map "I" 'makefile-browser-insert-selection-and-quit) - (define-key makefile-browser-map "\C-c\C-m" 'makefile-browser-insert-continuation) - (define-key makefile-browser-map "q" 'makefile-browser-quit) - ;; disable horizontal movement - (define-key makefile-browser-map "\C-b" 'undefined) - (define-key makefile-browser-map "\C-f" 'undefined)) - - -(defvar makefile-mode-syntax-table nil - "The syntax-table used in makefile mode.") -(if makefile-mode-syntax-table - () - (setq makefile-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\( "() " makefile-mode-syntax-table) - (modify-syntax-entry ?\) ")( " makefile-mode-syntax-table) - (modify-syntax-entry ?\[ "(] " makefile-mode-syntax-table) - (modify-syntax-entry ?\] "([ " makefile-mode-syntax-table) - (modify-syntax-entry ?\{ "(} " makefile-mode-syntax-table) - (modify-syntax-entry ?\} "){ " makefile-mode-syntax-table) - (modify-syntax-entry ?# "< " makefile-mode-syntax-table) - (modify-syntax-entry ?\n "> " makefile-mode-syntax-table)) - - -;;; ------------------------------------------------------------ -;;; Internal variables. -;;; You don't need to configure below this line. -;;; ------------------------------------------------------------ - -(defvar makefile-target-table nil - "Table of all targets that have been inserted in -this Makefile buffer using makefile-insert-target or picked up -using makefile-pickup-targets.") - -(defvar makefile-macro-table nil - "Table of all macros that have been iserted in -this Makefile buffer using makefile-insert-macro or picked up -using makefile-pickup-macros.") - -(defvar makefile-browser-client - "A buffer in makefile-mode that is currently using the browser.") - -(defvar makefile-browser-selection-vector nil) -(defvar makefile-has-prereqs nil) -(defvar makefile-need-target-pickup t) -(defvar makefile-need-macro-pickup t) - -(defvar makefile-mode-hook '()) - -(defconst makefile-gnumake-functions-alist - '( - ;; Text functions - ("subst" "From" "To" "In") - ("patsubst" "Pattern" "Replacement" "In") - ("strip" "Text") - ("findstring" "Find what" "In") - ("filter" "Pattern" "Text") - ("filter-out" "Pattern" "Text") - ("sort" "List") - ;; Filename functions - ("dir" "Names") - ("notdir" "Names") - ("suffix" "Names") - ("basename" "Names") - ("addsuffix" "Suffix" "Names") - ("join" "List 1" "List 2") - ("word" "Index" "Text") - ("words" "Text") - ("firstword" "Text") - ("wildcard" "Pattern") - ;; Misc functions - ("foreach" "Variable" "List" "Text") - ("origin" "Variable") - ("shell" "Command")) - "A list of GNU make function names associated with -the prompts for each function. -This is used in the function makefile-insert-gmake-function .") - - -;;; ------------------------------------------------------------ -;;; The mode function itself. -;;; ------------------------------------------------------------ - -;;;###autoload -(defun makefile-mode () - "Major mode for editing Makefiles. -Calling this function invokes the function(s) \"makefile-mode-hook\" before -doing anything else. - -\\{makefile-mode-map} - -In the browser, use the following keys: - -\\{makefile-browser-map} - -makefile-mode can be configured by modifying the following -variables: - -makefile-mode-name: - The \"pretty name\" of makefile-mode, as it - appears in the modeline. - -makefile-browser-buffer-name: - Name of the macro- and target browser buffer. - -makefile-target-colon: - The string that gets appended to all target names - inserted by makefile-insert-target. - \":\" or \"::\" are quite common values. - -makefile-macro-assign: - The string that gets appended to all macro names - inserted by makefile-insert-macro. - The normal value should be \" = \", since this is what - standard make expects. However, newer makes such as dmake - allow a larger variety of different macro assignments, so you - might prefer to use \" += \" or \" := \" . - -makefile-tab-after-target-colon: - If you want a TAB (instead of a space) to be appended after the - target colon, then set this to a non-nil value. - -makefile-browser-leftmost-column: - Number of blanks to the left of the browser selection mark. - -makefile-browser-cursor-column: - Column in which the cursor is positioned when it moves - up or down in the browser. - -makefile-browser-selected-mark: - String used to mark selected entries in the browser. - -makefile-browser-unselected-mark: - String used to mark unselected entries in the browser. - -makefile-browser-auto-advance-after-selection-p: - If this variable is set to a non-nil value the cursor - will automagically advance to the next line after an item - has been selected in the browser. - -makefile-pickup-everything-picks-up-filenames-p: - If this variable is set to a non-nil value then - makefile-pickup-everything also picks up filenames as targets - (i.e. it calls makefile-find-filenames-as-targets), otherwise - filenames are omitted. - -makefile-cleanup-continuations-p: - If this variable is set to a non-nil value then makefile-mode - will assure that no line in the file ends with a backslash - (the continuation character) followed by any whitespace. - This is done by silently removing the trailing whitespace, leaving - the backslash itself intact. - IMPORTANT: Please note that enabling this option causes makefile-mode - to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'. - -makefile-browser-hook: - A function or list of functions to be called just before the - browser is entered. This is executed in the makefile buffer. - -makefile-special-targets-list: - List of special targets. You will be offered to complete - on one of those in the minibuffer whenever you enter a \".\" - at the beginning of a line in makefile-mode." - (interactive) - (kill-all-local-variables) - (make-local-file 'local-write-file-hooks) - (setq local-write-file-hooks - '(makefile-cleanup-continuations 'makefile-warn-suspicious-lines)) - (make-local-variable 'makefile-target-table) - (make-local-variable 'makefile-macro-table) - (make-local-variable 'makefile-has-prereqs) - (make-local-variable 'makefile-need-target-pickup) - (make-local-variable 'makefile-need-macro-pickup) - (make-local-variable 'comment-start) - (make-local-variable 'comment-end) - (make-local-variable 'comment-start-skip) - (setq comment-start "#") - (setq comment-end "") - (setq comment-start-skip "#[ \t]*") - ;; become the current major mode - (setq major-mode 'makefile-mode) - (setq mode-name makefile-mode-name) - ;; activate keymap - (use-local-map makefile-mode-map) - (set-syntax-table makefile-mode-syntax-table) - (setq indent-tabs-mode t) ;real TABs are important in makefiles - (run-hooks 'makefile-mode-hook)) - -(defun makefile-next-dependency () - "Move (point) to the beginning of the next dependency line below (point)." - (interactive) - (let ((here (point))) - (end-of-line) - (if (re-search-forward makefile-dependency-regex (point-max) t) - (progn (beginning-of-line) t) ; indicate success - (goto-char here) nil))) - -(defun makefile-previous-dependency () - "Move (point) to the beginning of the next dependency line above (point)." - (interactive) - (let ((here (point))) - (beginning-of-line) - (if (re-search-backward makefile-dependency-regex (point-min) t) - (progn (beginning-of-line) t) ; indicate success - (goto-char here) nil))) - - -;;; Stuff below here depends on the pickup state - -(defun makefile-electric-dot () - "At (bol), offer completion on makefile-special-targets-list. -Anywhere else just insert a dot." - (interactive) - (if (bolp) - (makefile-insert-special-target) - (insert "."))) - -(defun makefile-insert-special-target () - "Complete on makefile-special-targets-list, insert result at (point)." - (interactive) - (makefile-pickup-targets) - (let - ((special-target - (completing-read "Special target: " - makefile-special-targets-list nil nil nil))) - (if (zerop (length special-target)) - () - (insert (format ".%s:" special-target)) - (makefile-forward-after-target-colon)))) - -(defun makefile-electric-equal () - "At (bol) do makefile-insert-macro. Anywhere else just self-insert." - (interactive) - (makefile-pickup-macros) - (if (bolp) - (call-interactively 'makefile-insert-macro) - (insert "="))) - -(defun makefile-insert-macro (macro-name) - "Prepare definition of a new macro." - (interactive "sMacro Name: ") - (makefile-pickup-macros) - (if (not (zerop (length macro-name))) - (progn - (beginning-of-line) - (insert (format "%s%s" macro-name makefile-macro-assign)) - (setq makefile-need-macro-pickup t) - (makefile-remember-macro macro-name)))) - -(defun makefile-insert-macro-ref (macro-name) - "Complete on a list of known macros, then insert complete ref at (point)." - (interactive - (list - (progn - (makefile-pickup-macros) - (completing-read "Refer to macro: " makefile-macro-table nil nil nil)))) - (if (not (zerop (length macro-name))) - (if (assoc macro-name makefile-runtime-macros-list) - (insert (format "$%s" macro-name)) - (insert (makefile-format-macro-ref macro-name))))) - -(defun makefile-insert-target (target-name) - "Prepare definition of a new target (dependency line)." - (interactive "sTarget: ") - (if (not (zerop (length target-name))) - (progn - (beginning-of-line) - (insert (format "%s%s" target-name makefile-target-colon)) - (makefile-forward-after-target-colon) - (end-of-line) - (setq makefile-need-target-pickup t) - (makefile-remember-target target-name)))) - -(defun makefile-insert-target-ref (target-name) - "Complete on a list of known targets, then insert target-ref at (point) ." - (interactive - (list - (progn - (makefile-pickup-targets) - (completing-read "Refer to target: " makefile-target-table nil nil nil)))) - (if (not (zerop (length target-name))) - (progn - (insert (format "%s " target-name))))) - -(defun makefile-electric-colon () - "At (bol) defines a new target, anywhere else just self-insert ." - (interactive) - (if (bolp) - (call-interactively 'makefile-insert-target) - (insert ":"))) - -;;; ------------------------------------------------------------ -;;; Extracting targets and macros from an existing makefile -;;; ------------------------------------------------------------ - -(defun makefile-pickup-targets () - "Scan a buffer that contains a makefile for target definitions (dependencies) -and add them to the list of known targets." - (interactive) - (if (not makefile-need-target-pickup) - nil - (setq makefile-need-target-pickup nil) - (setq makefile-target-table nil) - (setq makefile-has-prereqs nil) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward makefile-dependency-regex (point-max) t) - (makefile-add-this-line-targets))) - (message "Read targets OK."))) - -(defun makefile-add-this-line-targets () - (save-excursion - (beginning-of-line) - (let ((done-with-line nil) - (line-number (1+ (count-lines (point-min) (point))))) - (while (not done-with-line) - (skip-chars-forward " \t") - (if (not (setq done-with-line (or (eolp) - (char-equal (char-after (point)) ?:)))) - (progn - (let* ((start-of-target-name (point)) - (target-name - (progn - (skip-chars-forward "^ \t:#") - (buffer-substring start-of-target-name (point)))) - (has-prereqs - (not (looking-at ":[ \t]*$")))) - (if (makefile-remember-target target-name has-prereqs) - (message "Picked up target \"%s\" from line %d" - target-name line-number))))))))) - - -(defun makefile-pickup-macros () - "Scan a buffer that contains a makefile for macro definitions -and add them to the list of known macros." - (interactive) - (if (not makefile-need-macro-pickup) - nil - (setq makefile-need-macro-pickup nil) - (setq makefile-macro-table nil) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward makefile-macroassign-regex (point-max) t) - (makefile-add-this-line-macro) - (forward-line 1))) - (message "Read macros OK."))) - -(defun makefile-add-this-line-macro () - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (if (not (eolp)) - (let* ((start-of-macro-name (point)) - (line-number (1+ (count-lines (point-min) (point)))) - (macro-name (progn - (skip-chars-forward "^ \t:#=*") - (buffer-substring start-of-macro-name (point))))) - (if (makefile-remember-macro macro-name) - (message "Picked up macro \"%s\" from line %d" - macro-name line-number)))))) - -(defun makefile-pickup-everything () - "Calls makefile-pickup-targets and makefile-pickup-macros. -See their documentation for what they do." - (interactive) - (makefile-pickup-macros) - (makefile-pickup-targets) - (if makefile-pickup-everything-picks-up-filenames-p - (makefile-pickup-filenames-as-targets))) - - -(defun makefile-pickup-filenames-as-targets () - "Scan the current directory for filenames, check each filename -against makefile-ignored-files-in-pickup-regex and add all qualifying -names to the list of known targets." - (interactive) - (let* ((dir (file-name-directory (buffer-file-name))) - (raw-filename-list (if dir - (file-name-all-completions "" dir) - (file-name-all-completions "" "")))) - (mapcar '(lambda (name) - (if (and (not (file-directory-p name)) - (not (string-match makefile-ignored-files-in-pickup-regex - name))) - (if (makefile-remember-target name) - (message "Picked up file \"%s\" as target" name)))) - raw-filename-list))) - -;;; ------------------------------------------------------------ -;;; The browser window -;;; ------------------------------------------------------------ - -(defun makefile-browser-format-target-line (target selected) - (format - (concat (make-string makefile-browser-leftmost-column ?\ ) - (if selected - makefile-browser-selected-mark - makefile-browser-unselected-mark) - "%s%s") - target makefile-target-colon)) - -(defun makefile-browser-format-macro-line (macro selected) - (format - (concat (make-string makefile-browser-leftmost-column ?\ ) - (if selected - makefile-browser-selected-mark - makefile-browser-unselected-mark) - (makefile-format-macro-ref macro)))) - -(defun makefile-browser-fill (targets macros) - (let ((inhibit-read-only t)) - (goto-char (point-min)) - (erase-buffer) - (mapconcat - (function - (lambda (item) (insert (makefile-browser-format-target-line (car item) nil) "\n"))) - targets - "") - (mapconcat - (function - (lambda (item) (insert (makefile-browser-format-macro-line (car item) nil) "\n"))) - macros - "") - (sort-lines nil (point-min) (point-max)) - (goto-char (1- (point-max))) - (delete-char 1) ; remove unnecessary newline at eob - (goto-char (point-min)) - (forward-char makefile-browser-cursor-column))) - -;;; -;;; Moving up and down in the browser -;;; - -(defun makefile-browser-next-line () - "Move the browser selection cursor to the next line." - (interactive) - (if (not (makefile-last-line-p)) - (progn - (forward-line 1) - (forward-char makefile-browser-cursor-column)))) - -(defun makefile-browser-previous-line () - "Move the browser selection cursor to the previous line." - (interactive) - (if (not (makefile-first-line-p)) - (progn - (forward-line -1) - (forward-char makefile-browser-cursor-column)))) - -;;; -;;; Quitting the browser (returns to client buffer) -;;; - -(defun makefile-browser-quit () - "Leave the makefile-browser-buffer and return to the buffer -from that it has been entered." - (interactive) - (let ((my-client makefile-browser-client)) - (setq makefile-browser-client nil) ; we quitted, so NO client! - (set-buffer-modified-p nil) - (kill-buffer (current-buffer)) - (pop-to-buffer my-client))) - -;;; -;;; Toggle state of a browser item -;;; - -(defun makefile-browser-toggle () - "Toggle the selection state of the browser item at the cursor position." - (interactive) - (let ((this-line (count-lines (point-min) (point)))) - (setq this-line (max 1 this-line)) - (makefile-browser-toggle-state-for-line this-line) - (goto-line this-line) - (let ((inhibit-read-only t)) - (beginning-of-line) - (if (makefile-browser-on-macro-line-p) - (let ((macro-name (makefile-browser-this-line-macro-name))) - (kill-line) - (insert - (makefile-browser-format-macro-line - macro-name - (makefile-browser-get-state-for-line this-line)))) - (let ((target-name (makefile-browser-this-line-target-name))) - (kill-line) - (insert - (makefile-browser-format-target-line - target-name - (makefile-browser-get-state-for-line this-line)))))) - (beginning-of-line) - (forward-char makefile-browser-cursor-column) - (if makefile-browser-auto-advance-after-selection-p - (makefile-browser-next-line)))) - -;;; -;;; Making insertions into the client buffer -;;; - -(defun makefile-browser-insert-continuation () - "Insert a makefile continuation. -In the browser\'s client buffer, go to (end-of-line), insert a \'\\\' -character, insert a new blank line, go to that line and indent by one TAB. -This is most useful in the process of creating continued lines when copying -large dependencies from the browser to the client buffer. -(point) advances accordingly in the client buffer." - (interactive) - (save-excursion - (set-buffer makefile-browser-client) - (end-of-line) - (insert "\\\n\t"))) - -(defun makefile-browser-insert-selection () - "Insert all browser-selected targets and/or macros in the browser\'s -client buffer. -Insertion takes place at (point)." - (interactive) - (save-excursion - (goto-line 1) - (let ((current-line 1)) - (while (not (eobp)) - (if (makefile-browser-get-state-for-line current-line) - (makefile-browser-send-this-line-item)) - (forward-line 1) - (setq current-line (1+ current-line)))))) - -(defun makefile-browser-insert-selection-and-quit () - (interactive) - (makefile-browser-insert-selection) - (makefile-browser-quit)) - -(defun makefile-browser-send-this-line-item () - (if (makefile-browser-on-macro-line-p) - (save-excursion - (let ((macro-name (makefile-browser-this-line-macro-name))) - (set-buffer makefile-browser-client) - (insert (makefile-format-macro-ref macro-name) " "))) - (save-excursion - (let ((target-name (makefile-browser-this-line-target-name))) - (set-buffer makefile-browser-client) - (insert target-name " "))))) - -(defun makefile-browser-start-interaction () - (use-local-map makefile-browser-map) - (setq buffer-read-only t)) - -(defun makefile-browse (targets macros) - (interactive) - (if (zerop (+ (length targets) (length macros))) - (progn - (beep) - (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'")) - (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name))) - (pop-to-buffer browser-buffer) - (make-variable-buffer-local 'makefile-browser-selection-vector) - (makefile-browser-fill targets macros) - (shrink-window-if-larger-than-buffer) - (setq makefile-browser-selection-vector - (make-vector (+ (length targets) (length macros)) nil)) - (makefile-browser-start-interaction)))) - -(defun makefile-switch-to-browser () - (interactive) - (run-hooks 'makefile-browser-hook) - (setq makefile-browser-client (current-buffer)) - (makefile-pickup-targets) - (makefile-pickup-macros) - (makefile-browse makefile-target-table makefile-macro-table)) - - -;;; ------------------------------------------------------------ -;;; Up-to-date overview buffer -;;; ------------------------------------------------------------ - -(defun makefile-create-up-to-date-overview () - "Create a buffer containing an overview of the state of all known targets. -Known targets are targets that are explicitly defined in that makefile; -in other words, all targets that appear on the left hand side of a -dependency in the makefile." - (interactive) - (if (y-or-n-p "Are you sure that the makefile being edited is consistent? ") - ;; - ;; The rest of this function operates on a temporary makefile, created by - ;; writing the current contents of the makefile buffer. - ;; - (let ((saved-target-table makefile-target-table) - (this-buffer (current-buffer)) - (makefile-up-to-date-buffer - (get-buffer-create makefile-up-to-date-buffer-name)) - (filename (makefile-save-temporary)) - ;; - ;; Forget the target table because it may contain picked-up filenames - ;; that are not really targets in the current makefile. - ;; We don't want to query these, so get a new target-table with just the - ;; targets that can be found in the makefile buffer. - ;; The 'old' target table will be restored later. - ;; - (real-targets (progn - (makefile-pickup-targets) - makefile-target-table)) - (prereqs makefile-has-prereqs) - ) - - (set-buffer makefile-up-to-date-buffer) - (setq buffer-read-only nil) - (erase-buffer) - (makefile-query-targets filename real-targets prereqs) - (if (zerop (buffer-size)) ; if it did not get us anything - (progn - (kill-buffer (current-buffer)) - (message "No overview created!"))) - (set-buffer this-buffer) - (setq makefile-target-table saved-target-table) - (if (get-buffer makefile-up-to-date-buffer-name) - (progn - (pop-to-buffer (get-buffer makefile-up-to-date-buffer-name)) - (shrink-window-if-larger-than-buffer) - (sort-lines nil (point-min) (point-max)) - (setq buffer-read-only t)))))) - -(defun makefile-save-temporary () - "Create a temporary file from the current makefile buffer." - (let ((filename (makefile-generate-temporary-filename))) - (write-region (point-min) (point-max) filename nil 0) - filename)) ; return the filename - -(defun makefile-generate-temporary-filename () - "Create a filename suitable for use in makefile-save-temporary. -Be careful to allow brain-dead file systems (DOS, SYSV ...) to cope -with the generated name !" - (let ((my-name (user-login-name)) - (my-uid (int-to-string (user-uid)))) - (concat "mktmp" - (if (> (length my-name) 3) - (substring my-name 0 3) - my-name) - "." - (if (> (length my-uid) 3) - (substring my-uid 0 3) - my-uid)))) - -(defun makefile-query-targets (filename target-table prereq-list) - "This function fills the up-to-date-overview-buffer. -It checks each target in target-table using makefile-query-one-target-method -and generates the overview, one line per target name." - (insert - (mapconcat - (function (lambda (item) - (let* ((target-name (car item)) - (no-prereqs (not (member target-name prereq-list))) - (needs-rebuild (or no-prereqs - (funcall - makefile-query-one-target-method - target-name - filename)))) - (format "\t%s%s" - target-name - (cond (no-prereqs " .. has no prerequisites") - (needs-rebuild " .. NEEDS REBUILD") - (t " .. is up to date")))) - )) - target-table "\n")) - (goto-char (point-min)) - (delete-file filename)) ; remove the tmpfile - -(defun makefile-query-by-make-minus-q (target &optional filename) - (not (zerop (call-process makefile-brave-make nil nil nil "-f" filename "-q" target)))) - -;;; ------------------------------------------------------------ -;;; Continuation cleanup -;;; ------------------------------------------------------------ - -(defun makefile-cleanup-continuations () - (if (eq major-mode 'makefile-mode) - (if (and makefile-cleanup-continuations-p - (not buffer-read-only)) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "\\\\[ \t]+$" (point-max) t) - (replace-match "\\" t t)))))) - - -;;; ------------------------------------------------------------ -;;; Warn of suspicious lines -;;; ------------------------------------------------------------ - -(defun makefile-warn-suspicious-lines () - (let ((dont-save nil)) - (if (eq major-mode 'makefile-mode) - (let ((suspicious - (save-excursion - (goto-char (point-min)) - (re-search-forward - "\\(^[\t]+$\\)\\|\\(^[ ]+[\t]\\)" (point-max) t)))) - (if suspicious - (let ((line-nr (count-lines (point-min) suspicious))) - (setq dont-save - (not (y-or-n-p - (format "Suspicious line %d. Save anyway " - line-nr)))))))) - dont-save)) - - -;;; ------------------------------------------------------------ -;;; GNU make function support -;;; ------------------------------------------------------------ - -(defun makefile-insert-gmake-function () - "This function is intended to help you using the numerous -macro-like \'function calls\' of GNU make. -It will ask you for the name of the function you wish to -use (with completion), then, after you selected the function, -it will prompt you for all required parameters. -This function \'knows\' about the required parameters of every -GNU make function and will use meaningfull prompts for the -various args, making it much easier to take advantage of this -powerful GNU make feature." - (interactive) - (let* ((gm-function-name (completing-read - "Function: " - makefile-gnumake-functions-alist - nil t nil)) - (gm-function-prompts - (cdr (assoc gm-function-name makefile-gnumake-functions-alist)))) - (if (not (zerop (length gm-function-name))) - (insert (makefile-format-macro-ref - (concat gm-function-name " " - (makefile-prompt-for-gmake-funargs - gm-function-name gm-function-prompts))) - " ")))) - -(defun makefile-prompt-for-gmake-funargs (function-name prompt-list) - (mapconcat - (function (lambda (one-prompt) - (read-string (format "[%s] %s: " function-name one-prompt) nil))) - prompt-list - ",")) - - - -;;; ------------------------------------------------------------ -;;; Utility functions -;;; ------------------------------------------------------------ - -(defun makefile-remember-target (target-name &optional has-prereqs) - "Remember a given target if it is not already remembered for this buffer." - (if (not (zerop (length target-name))) - (progn - (if (not (assoc target-name makefile-target-table)) - (setq makefile-target-table - (cons (list target-name) makefile-target-table))) - (if has-prereqs - (setq makefile-has-prereqs - (cons target-name makefile-has-prereqs)))))) - -(defun makefile-remember-macro (macro-name) - "Remember a given macro if it is not already remembered for this buffer." - (if (not (zerop (length macro-name))) - (if (not (assoc macro-name makefile-macro-table)) - (setq makefile-macro-table - (cons (list macro-name) makefile-macro-table))))) - -(defun makefile-forward-after-target-colon () -"Move point forward after the terminating colon -of a target has been inserted. -This accts according to the value of makefile-tab-after-target-colon ." - (if makefile-tab-after-target-colon - (insert "\t") - (insert " "))) - -(defun makefile-browser-on-macro-line-p () - "Determine if point is on a macro line in the browser." - (save-excursion - (beginning-of-line) - (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t))) - -(defun makefile-browser-this-line-target-name () - "Extract the target name from a line in the browser." - (save-excursion - (end-of-line) - (skip-chars-backward "^ \t") - (buffer-substring (point) (1- (makefile-end-of-line-point))))) - -(defun makefile-browser-this-line-macro-name () - "Extract the macro name from a line in the browser." - (save-excursion - (beginning-of-line) - (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t) - (let ((macro-start (point))) - (skip-chars-forward "^})") - (buffer-substring macro-start (point))))) - -(defun makefile-format-macro-ref (macro-name) - "Format a macro reference according to the value of the -configuration variable makefile-use-curly-braces-for-macros-p ." - (if (or (char-equal ?\( (string-to-char macro-name)) - (char-equal ?\{ (string-to-char macro-name))) - (format "$%s" macro-name) - (if makefile-use-curly-braces-for-macros-p - (format "${%s}" macro-name) - (format "$(%s)" macro-name)))) - -(defun makefile-browser-get-state-for-line (n) - (aref makefile-browser-selection-vector (1- n))) - -(defun makefile-browser-set-state-for-line (n to-state) - (aset makefile-browser-selection-vector (1- n) to-state)) - -(defun makefile-browser-toggle-state-for-line (n) - (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n)))) - -(defun makefile-beginning-of-line-point () - (save-excursion - (beginning-of-line) - (point))) - -(defun makefile-end-of-line-point () - (save-excursion - (end-of-line) - (point))) - -(defun makefile-last-line-p () - (= (makefile-end-of-line-point) (point-max))) - -(defun makefile-first-line-p () - (= (makefile-beginning-of-line-point) (point-min))) - -;; makefile.el ends here diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el deleted file mode 100644 index 21b7d475b30..00000000000 --- a/lisp/progmodes/modula2.el +++ /dev/null @@ -1,454 +0,0 @@ -;;; modula2.el --- Modula-2 editing support package - -;; Author: Michael Schmidt <michael@pbinfo.UUCP> -;; Tom Perrine <Perrin@LOGICON.ARPA> -;; Keywords: languages - -;; The authors distributed this without a copyright notice -;; back in 1988, so it is in the public domain. The original included -;; the following credit: - -;; Author Mick Jordan -;; amended Peter Robinson - -;;; Commentary: - -;; A major mode for editing Modula-2 code. It provides convenient abbrevs -;; for Modula-2 keywords, knows about the standard layout rules, and supports -;; a native compile command. - -;;; Code: - -;;; Added by Tom Perrine (TEP) -(defvar m2-mode-syntax-table nil - "Syntax table in use in Modula-2 buffers.") - -(defvar m2-compile-command "m2c" - "Command to compile Modula-2 programs") - -(defvar m2-link-command "m2l" - "Command to link Modula-2 programs") - -(defvar m2-link-name nil - "Name of the executable.") - - -(if m2-mode-syntax-table - () - (let ((table (make-syntax-table))) - (modify-syntax-entry ?\\ "\\" table) - (modify-syntax-entry ?\( ". 1" table) - (modify-syntax-entry ?\) ". 4" table) - (modify-syntax-entry ?* ". 23" table) - (modify-syntax-entry ?+ "." table) - (modify-syntax-entry ?- "." table) - (modify-syntax-entry ?= "." table) - (modify-syntax-entry ?% "." table) - (modify-syntax-entry ?< "." table) - (modify-syntax-entry ?> "." table) - (modify-syntax-entry ?\' "\"" table) - (setq m2-mode-syntax-table table))) - -;;; Added by TEP -(defvar m2-mode-map nil - "Keymap used in Modula-2 mode.") - -(if m2-mode-map () - (let ((map (make-sparse-keymap))) - (define-key map "\^i" 'm2-tab) - (define-key map "\C-cb" 'm2-begin) - (define-key map "\C-cc" 'm2-case) - (define-key map "\C-cd" 'm2-definition) - (define-key map "\C-ce" 'm2-else) - (define-key map "\C-cf" 'm2-for) - (define-key map "\C-ch" 'm2-header) - (define-key map "\C-ci" 'm2-if) - (define-key map "\C-cm" 'm2-module) - (define-key map "\C-cl" 'm2-loop) - (define-key map "\C-co" 'm2-or) - (define-key map "\C-cp" 'm2-procedure) - (define-key map "\C-c\C-w" 'm2-with) - (define-key map "\C-cr" 'm2-record) - (define-key map "\C-cs" 'm2-stdio) - (define-key map "\C-ct" 'm2-type) - (define-key map "\C-cu" 'm2-until) - (define-key map "\C-cv" 'm2-var) - (define-key map "\C-cw" 'm2-while) - (define-key map "\C-cx" 'm2-export) - (define-key map "\C-cy" 'm2-import) - (define-key map "\C-c{" 'm2-begin-comment) - (define-key map "\C-c}" 'm2-end-comment) - (define-key map "\C-j" 'm2-newline) - (define-key map "\C-c\C-z" 'suspend-emacs) - (define-key map "\C-c\C-v" 'm2-visit) - (define-key map "\C-c\C-t" 'm2-toggle) - (define-key map "\C-c\C-l" 'm2-link) - (define-key map "\C-c\C-c" 'm2-compile) - (setq m2-mode-map map))) - -(defvar m2-indent 5 "*This variable gives the indentation in Modula-2-Mode") - -;;;###autoload -(defun modula-2-mode () - "This is a mode intended to support program development in Modula-2. -All control constructs of Modula-2 can be reached by typing C-c -followed by the first character of the construct. -\\<m2-mode-map> - \\[m2-begin] begin \\[m2-case] case - \\[m2-definition] definition \\[m2-else] else - \\[m2-for] for \\[m2-header] header - \\[m2-if] if \\[m2-module] module - \\[m2-loop] loop \\[m2-or] or - \\[m2-procedure] procedure Control-c Control-w with - \\[m2-record] record \\[m2-stdio] stdio - \\[m2-type] type \\[m2-until] until - \\[m2-var] var \\[m2-while] while - \\[m2-export] export \\[m2-import] import - \\[m2-begin-comment] begin-comment \\[m2-end-comment] end-comment - \\[suspend-emacs] suspend Emacs \\[m2-toggle] toggle - \\[m2-compile] compile \\[m2-next-error] next-error - \\[m2-link] link - - `m2-indent' controls the number of spaces for each indentation. - `m2-compile-command' holds the command to compile a Modula-2 program. - `m2-link-command' holds the command to link a Modula-2 program." - (interactive) - (kill-all-local-variables) - (use-local-map m2-mode-map) - (setq major-mode 'modula-2-mode) - (setq mode-name "Modula-2") - (make-local-variable 'comment-column) - (setq comment-column 41) - (make-local-variable 'end-comment-column) - (setq end-comment-column 75) - (set-syntax-table m2-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) -; (make-local-variable 'indent-line-function) -; (setq indent-line-function 'c-indent-line) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "(* ") - (make-local-variable 'comment-end) - (setq comment-end " *)") - (make-local-variable 'comment-column) - (setq comment-column 41) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "/\\*+ *") - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'c-comment-indent) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t) - (run-hooks 'm2-mode-hook)) - -(defun m2-newline () - "Insert a newline and indent following line like previous line." - (interactive) - (let ((hpos (current-indentation))) - (newline) - (indent-to hpos))) - -(defun m2-tab () - "Indent to next tab stop." - (interactive) - (indent-to (* (1+ (/ (current-indentation) m2-indent)) m2-indent))) - -(defun m2-begin () - "Insert a BEGIN keyword and indent for the next line." - (interactive) - (insert "BEGIN") - (m2-newline) - (m2-tab)) - -(defun m2-case () - "Build skeleton CASE statment, prompting for the <expression>." - (interactive) - (let ((name (read-string "Case-Expression: "))) - (insert "CASE " name " OF") - (m2-newline) - (m2-newline) - (insert "END (* case " name " *);")) - (end-of-line 0) - (m2-tab)) - -(defun m2-definition () - "Build skeleton DEFINITION MODULE, prompting for the <module name>." - (interactive) - (insert "DEFINITION MODULE ") - (let ((name (read-string "Name: "))) - (insert name ";\n\n\n\nEND " name ".\n")) - (previous-line 3)) - -(defun m2-else () - "Insert ELSE keyword and indent for next line." - (interactive) - (m2-newline) - (backward-delete-char-untabify m2-indent ()) - (insert "ELSE") - (m2-newline) - (m2-tab)) - -(defun m2-for () - "Build skeleton FOR loop statment, prompting for the loop parameters." - (interactive) - (insert "FOR ") - (let ((name (read-string "Loop Initialiser: ")) limit by) - (insert name " TO ") - (setq limit (read-string "Limit: ")) - (insert limit) - (setq by (read-string "Step: ")) - (if (not (string-equal by "")) - (insert " BY " by)) - (insert " DO") - (m2-newline) - (m2-newline) - (insert "END (* for " name " to " limit " *);")) - (end-of-line 0) - (m2-tab)) - -(defun m2-header () - "Insert a comment block containing the module title, author, etc." - (interactive) - (insert "(*\n Title: \t") - (insert (read-string "Title: ")) - (insert "\n Created:\t") - (insert (current-time-string)) - (insert "\n Author: \t") - (insert (user-full-name)) - (insert (concat "\n\t\t<" (user-login-name) "@" (system-name) ">\n")) - (insert "*)\n\n")) - -(defun m2-if () - "Insert skeleton IF statment, prompting for <boolean-expression>." - (interactive) - (insert "IF ") - (let ((thecondition (read-string "<boolean-expression>: "))) - (insert thecondition " THEN") - (m2-newline) - (m2-newline) - (insert "END (* if " thecondition " *);")) - (end-of-line 0) - (m2-tab)) - -(defun m2-loop () - "Build skeleton LOOP (with END)." - (interactive) - (insert "LOOP") - (m2-newline) - (m2-newline) - (insert "END (* loop *);") - (end-of-line 0) - (m2-tab)) - -(defun m2-module () - "Build skeleton IMPLEMENTATION MODULE, prompting for <module-name>." - (interactive) - (insert "IMPLEMENTATION MODULE ") - (let ((name (read-string "Name: "))) - (insert name ";\n\n\n\nEND " name ".\n") - (previous-line 3) - (m2-header) - (m2-type) - (newline) - (m2-var) - (newline) - (m2-begin) - (m2-begin-comment) - (insert " Module " name " Initialisation Code ")) - (m2-end-comment) - (newline) - (m2-tab)) - -(defun m2-or () - (interactive) - (m2-newline) - (backward-delete-char-untabify m2-indent) - (insert "|") - (m2-newline) - (m2-tab)) - -(defun m2-procedure () - (interactive) - (insert "PROCEDURE ") - (let ((name (read-string "Name: " )) - args) - (insert name " (") - (insert (read-string "Arguments: ") ")") - (setq args (read-string "Result Type: ")) - (if (not (string-equal args "")) - (insert " : " args)) - (insert ";") - (m2-newline) - (insert "BEGIN") - (m2-newline) - (m2-newline) - (insert "END ") - (insert name) - (insert ";") - (end-of-line 0) - (m2-tab))) - -(defun m2-with () - (interactive) - (insert "WITH ") - (let ((name (read-string "Record-Type: "))) - (insert name) - (insert " DO") - (m2-newline) - (m2-newline) - (insert "END (* with " name " *);")) - (end-of-line 0) - (m2-tab)) - -(defun m2-record () - (interactive) - (insert "RECORD") - (m2-newline) - (m2-newline) - (insert "END (* record *);") - (end-of-line 0) - (m2-tab)) - -(defun m2-stdio () - (interactive) - (insert " -FROM TextIO IMPORT - WriteCHAR, ReadCHAR, WriteINTEGER, ReadINTEGER, - WriteCARDINAL, ReadCARDINAL, WriteBOOLEAN, ReadBOOLEAN, - WriteREAL, ReadREAL, WriteBITSET, ReadBITSET, - WriteBasedCARDINAL, ReadBasedCARDINAL, WriteChars, ReadChars, - WriteString, ReadString, WhiteSpace, EndOfLine; - -FROM SysStreams IMPORT sysIn, sysOut, sysErr; - -")) - -(defun m2-type () - (interactive) - (insert "TYPE") - (m2-newline) - (m2-tab)) - -(defun m2-until () - (interactive) - (insert "REPEAT") - (m2-newline) - (m2-newline) - (insert "UNTIL ") - (insert (read-string "<boolean-expression>: ") ";") - (end-of-line 0) - (m2-tab)) - -(defun m2-var () - (interactive) - (m2-newline) - (insert "VAR") - (m2-newline) - (m2-tab)) - -(defun m2-while () - (interactive) - (insert "WHILE ") - (let ((name (read-string "<boolean-expression>: "))) - (insert name " DO" ) - (m2-newline) - (m2-newline) - (insert "END (* while " name " *);")) - (end-of-line 0) - (m2-tab)) - -(defun m2-export () - (interactive) - (insert "EXPORT QUALIFIED ")) - -(defun m2-import () - (interactive) - (insert "FROM ") - (insert (read-string "Module: ")) - (insert " IMPORT ")) - -(defun m2-begin-comment () - (interactive) - (if (not (bolp)) - (indent-to comment-column 0)) - (insert "(* ")) - -(defun m2-end-comment () - (interactive) - (if (not (bolp)) - (indent-to end-comment-column)) - (insert "*)")) - -(defun m2-compile () - (interactive) - (setq modulename (buffer-name)) - (compile (concat m2-compile-command " " modulename))) - -(defun m2-link () - (interactive) - (setq modulename (buffer-name)) - (if m2-link-name - (compile (concat m2-link-command " " m2-link-name)) - (compile (concat m2-link-command " " - (setq m2-link-name (read-string "Name of executable: " - modulename)))))) - -(defun execute-monitor-command (command) - (let* ((shell shell-file-name) - (csh (equal (file-name-nondirectory shell) "csh"))) - (call-process shell nil t t "-cf" (concat "exec " command)))) - -(defun m2-visit () - (interactive) - (let ((deffile nil) - (modfile nil) - modulename) - (save-excursion - (setq modulename - (read-string "Module name: ")) - (switch-to-buffer "*Command Execution*") - (execute-monitor-command (concat "m2whereis " modulename)) - (goto-char (point-min)) - (condition-case () - (progn (re-search-forward "\\(.*\\.def\\) *$") - (setq deffile (buffer-substring (match-beginning 1) - (match-end 1)))) - (search-failed ())) - (condition-case () - (progn (re-search-forward "\\(.*\\.mod\\) *$") - (setq modfile (buffer-substring (match-beginning 1) - (match-end 1)))) - (search-failed ())) - (if (not (or deffile modfile)) - (error "I can find neither definition nor implementation of %s" - modulename))) - (cond (deffile - (find-file deffile) - (if modfile - (save-excursion - (find-file modfile)))) - (modfile - (find-file modfile))))) - -(defun m2-toggle () - "Toggle between .mod and .def files for the module." - (interactive) - (cond ((string-equal (substring (buffer-name) -4) ".def") - (find-file-other-window - (concat (substring (buffer-name) 0 -4) ".mod"))) - ((string-equal (substring (buffer-name) -4) ".mod") - (find-file-other-window - (concat (substring (buffer-name) 0 -4) ".def"))) - ((string-equal (substring (buffer-name) -3) ".mi") - (find-file-other-window - (concat (substring (buffer-name) 0 -3) ".md"))) - ((string-equal (substring (buffer-name) -3) ".md") - (find-file-other-window - (concat (substring (buffer-name) 0 -3) ".mi"))))) - -;;; modula2.el ends here diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el deleted file mode 100644 index 026c383fe90..00000000000 --- a/lisp/progmodes/pascal.el +++ /dev/null @@ -1,1404 +0,0 @@ -;;; pascal.el - Major mode for editing pascal source in emacs. - -;;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. - -;;; Author: Espen Skoglund (espensk@stud.cs.uit.no) -;;; Keywords: languages - -;;; 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. - -;;; 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. - -;;; 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. - -;;; 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-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. - -;;; Code: - -(defconst pascal-mode-version "2.1a" - "Version of `pascal-mode.el'.") - -(defvar pascal-mode-abbrev-table nil - "Abbrev table in use in Pascal-mode buffers.") -(define-abbrev-table 'pascal-mode-abbrev-table ()) - -(defvar pascal-mode-map () - "Keymap used in Pascal mode.") -(if pascal-mode-map - () - (setq pascal-mode-map (make-sparse-keymap)) - (define-key pascal-mode-map ";" 'electric-pascal-semi-or-dot) - (define-key pascal-mode-map "." 'electric-pascal-semi-or-dot) - (define-key pascal-mode-map ":" 'electric-pascal-colon) - (define-key pascal-mode-map "=" 'electric-pascal-equal) - (define-key pascal-mode-map "\r" 'electric-pascal-terminate-line) - (define-key pascal-mode-map "\t" 'electric-pascal-tab) - (define-key pascal-mode-map "\e\t" 'pascal-complete-word) - (define-key pascal-mode-map "\e?" 'pascal-show-completions) - (define-key pascal-mode-map "\177" 'backward-delete-char-untabify) - (define-key pascal-mode-map "\e\C-h" 'pascal-mark-defun) - (define-key pascal-mode-map "\C-cb" 'pascal-insert-block) - (define-key pascal-mode-map "\M-*" 'pascal-star-comment) - (define-key pascal-mode-map "\C-c\C-c" 'pascal-comment-area) - (define-key pascal-mode-map "\C-c\C-u" 'pascal-uncomment-area) - (define-key pascal-mode-map "\e\C-a" 'pascal-beg-of-defun) - (define-key pascal-mode-map "\e\C-e" 'pascal-end-of-defun) - (define-key pascal-mode-map "\C-cg" 'pascal-goto-defun) - (define-key pascal-mode-map "\C-c\C-o" 'pascal-outline) -;;; A command to change the whole buffer won't be used terribly -;;; often, so no need for a key binding. -; (define-key pascal-mode-map "\C-cd" 'pascal-downcase-keywords) -; (define-key pascal-mode-map "\C-cu" 'pascal-upcase-keywords) -; (define-key pascal-mode-map "\C-cc" 'pascal-capitalize-keywords) - ) - -(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" - "type" "until" "var" "while" "with" - ;; The following are not standard in pascal, but widely used. - "get" "put" "input" "output" "read" "readln" "reset" "rewrite" "write" - "writeln")) - -;;; -;;; Regular expressions used to calculate indent, etc. -;;; -(defconst pascal-symbol-re "\\<[a-zA-Z_][a-zA-Z_0-9.]*\\>") -(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-defun-re "\\<\\(function\\|procedure\\|program\\)\\>") -(defconst pascal-sub-block-re "\\<\\(if\\|else\\|for\\|while\\|with\\)\\>") -(defconst pascal-noindent-re "\\<\\(begin\\|end\\|until\\|else\\)\\>") -(defconst pascal-nosemi-re "\\<\\(begin\\|repeat\\|then\\|do\\|else\\)\\>") -(defconst pascal-autoindent-lines-re - "\\<\\(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 -----/\\-----}") - -(defvar pascal-mode-syntax-table nil - "Syntax table in use in Pascal-mode buffers.") - -(if pascal-mode-syntax-table - () - (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 ?) ")(4" pascal-mode-syntax-table) - (modify-syntax-entry ?* ". 23" 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 ?< "." 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)) - -(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-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 - '("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.") -(defvar 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.) -The procedures and variables defined within the Pascal program -will be completed runtime and should not be added to this list.") -(defvar 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.") - -;;; -;;; Macros -;;; - -(defsubst pascal-get-beg-of-line (&optional arg) - (save-excursion - (beginning-of-line arg) - (point))) - -(defsubst pascal-get-end-of-line (&optional arg) - (save-excursion - (end-of-line arg) - (point))) - -(defun pascal-declaration-end () - (let ((nest 1)) - (while (and (> nest 0) - (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))))))) - -(defun pascal-declaration-beg () - (let ((nest 1)) - (while (and (> nest 0) - (re-search-backward "[:=]\\|\\<\\(type\\|var\\|label\\|const\\)\\>\\|\\(\\<record\\>\\)\\|\\(\\<end\\>\\)" (pascal-get-beg-of-line -0) t)) - (cond ((match-beginning 1) (setq nest 0)) - ((match-beginning 2) (setq nest (1- nest))) - ((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))))) - - -;;;###autoload -(defun pascal-mode () - "Major mode for editing Pascal code. \\<pascal-mode-map> -TAB indents for Pascal code. Delete converts tabs to spaces as it moves back. - -\\[pascal-complete-word] completes the word around current point with respect \ -to position in code -\\[pascal-show-completions] shows all possible completions at this point. - -Other useful functions are: - -\\[pascal-mark-defun]\t- Mark function. -\\[pascal-insert-block]\t- insert begin ... end; -\\[pascal-star-comment]\t- insert (* ... *) -\\[pascal-comment-area]\t- Put marked area in a comment, fixing nested comments. -\\[pascal-uncomment-area]\t- Uncomment an area commented with \ -\\[pascal-comment-area]. -\\[pascal-beg-of-defun]\t- Move to beginning of current function. -\\[pascal-end-of-defun]\t- Move to end of current function. -\\[pascal-goto-defun]\t- Goto function prompted for in the minibuffer. -\\[pascal-outline]\t- Enter pascal-outline-mode (see also pascal-outline). - -Variables controlling indentation/edit style: - - pascal-indent-level (default 3) - Indentation of Pascal statements with respect to containing block. - 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-tab-always-indent (defualt 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) - 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. - -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." - (interactive) - (kill-all-local-variables) - (use-local-map pascal-mode-map) - (setq major-mode 'pascal-mode) - (setq mode-name "Pascal") - (setq local-abbrev-table pascal-mode-abbrev-table) - (set-syntax-table pascal-mode-syntax-table) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'pascal-indent-line) - (setq comment-indent-function 'pascal-indent-comment) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t) - (make-local-variable 'case-fold-search) - (setq case-fold-search t) - (run-hooks 'pascal-mode-hook)) - - - -;;; -;;; Electric functions -;;; -(defun electric-pascal-terminate-line () - "Terminate line and indent next line." - (interactive) - ;; First, check if current line should be indented - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (if (looking-at pascal-autoindent-lines-re) - (pascal-indent-line))) - (delete-horizontal-space) ; Removes trailing whitespaces - (newline) - ;; Indent next line - (pascal-indent-line) - ;; Maybe we should set some endcomments - (if pascal-auto-endcomments - (pascal-set-auto-comments)) - ;; Check if we shall indent inside comment - (let ((setstar nil)) - (save-excursion - (forward-line -1) - (skip-chars-forward " \t") - (cond ((looking-at "\\*[ \t]+)") - ;; Delete region between `*' and `)' if there is only whitespaces. - (forward-char 1) - (delete-horizontal-space)) - ((and (looking-at "(\\*\\|\\*[^)]") - (not (save-excursion - (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) - (pascal-indent-line) - (insert "* ")))) - - -(defun electric-pascal-semi-or-dot () - "Insert `;' or `.' character and reindent the line." - (interactive) - (insert last-command-char) - (save-excursion - (beginning-of-line) - (pascal-indent-line)) - (if pascal-auto-newline - (electric-pascal-terminate-line))) - -(defun electric-pascal-colon () - "Insert `:' and do all indentions except line indent on this line." - (interactive) - (insert last-command-char) - ;; Do nothing if within string. - (if (pascal-within-string) - () - (save-excursion - (beginning-of-line) - (pascal-indent-line)) - (let ((pascal-tab-always-indent nil)) - (pascal-indent-command)))) - -(defun electric-pascal-equal () - "Insert `=', and do indention if within type declaration." - (interactive) - (insert last-command-char) - (if (eq (car (pascal-calculate-indent)) 'declaration) - (let ((pascal-tab-always-indent nil)) - (pascal-indent-command)))) - -(defun electric-pascal-tab () - "Function called when TAB is pressed in Pascal mode." - (interactive) - ;; Do nothing if within a string. - (if (pascal-within-string) - (insert "\t") - ;; If pascal-tab-always-indent, indent the beginning of the line. - (if pascal-tab-always-indent - (save-excursion - (beginning-of-line) - (pascal-indent-line)) - (insert "\t")) - (pascal-indent-command))) - - - -;;; -;;; Interactive functions -;;; -(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) - (insert "end;") - (beginning-of-line) - (pascal-indent-line))) - -(defun pascal-star-comment () - "Insert Pascal star comment at point." - (interactive) - (pascal-indent-line) - (insert "(*") - (electric-pascal-terminate-line) - (save-excursion - (electric-pascal-terminate-line) - (delete-horizontal-space) - (insert ")")) - (insert " ")) - -(defun pascal-mark-defun () - "Mark the current pascal function (or procedure). -This puts the mark at the end, and point at the beginning." - (interactive) - (push-mark (point)) - (pascal-end-of-defun) - (push-mark (point)) - (pascal-beg-of-defun) - (if (fboundp 'zmacs-activate-region) - (zmacs-activate-region))) - -(defun pascal-comment-area (start end) - "Put the region into a Pascal comment. -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, -\\[pascal-uncomment-area] won't recognize the comments." - (interactive "r") - (save-excursion - ;; Insert start and endcomments - (goto-char end) - (if (and (save-excursion (skip-chars-forward " \t") (eolp)) - (not (save-excursion (skip-chars-backward " \t") (bolp)))) - (forward-line 1) - (beginning-of-line)) - (insert pascal-exclude-str-end) - (setq end (point)) - (newline) - (goto-char start) - (beginning-of-line) - (insert pascal-exclude-str-start) - (newline) - ;; Replace end-comments within commented area - (goto-char end) - (save-excursion - (while (re-search-backward "\\*)" start t) - (replace-match "!(*" t t))) - (save-excursion - (while (re-search-backward "}" start t) - (replace-match "!{" t t))))) - -(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'." - (interactive) - (save-excursion - (let ((start (point)) - (end (point))) - ;; Find the boundaries of the comment - (save-excursion - (setq start (progn (search-backward pascal-exclude-str-start nil t) - (point))) - (setq end (progn (search-forward pascal-exclude-str-end nil t) - (point)))) - ;; Check if we're really inside a comment - (if (or (equal start (point)) (<= end (point))) - (message "Not standing within commented area.") - (progn - ;; Remove endcomment - (goto-char end) - (beginning-of-line) - (let ((pos (point))) - (end-of-line) - (delete-region pos (1+ (point)))) - ;; Change comments back to normal - (save-excursion - (while (re-search-backward "!{" start t) - (replace-match "}" t t))) - (save-excursion - (while (re-search-backward "!(\\*" start t) - (replace-match "*)" t t))) - ;; Remove startcomment - (goto-char start) - (beginning-of-line) - (let ((pos (point))) - (end-of-line) - (delete-region pos (1+ (point))))))))) - -(defun pascal-beg-of-defun () - "Move backward to the beginning of the current function or procedure." - (interactive) - (catch 'found - (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 "\\|" - pascal-end-block-re "\\|" - pascal-defun-re))) - (while (re-search-backward reg nil 'move) - (cond ((let ((state (save-excursion - (parse-partial-sexp (point-min) (point))))) - (or (nth 3 state) (nth 4 state))) ; Inside string or comment - ()) - ((match-end 1) ; begin|case|record|repeat - (if (and (looking-at "\\<record\\>") (>= max 0)) - (setq func (1- func))) - (setq nest (1+ nest) - max (max nest max))) - ((match-end 2) ; end|until - (if (and (= nest max) (>= max 0)) - (setq func (1+ func))) - (setq nest (1- nest))) - ((match-end 3) ; function|procedure - (if (= 0 func) - (throw 'found t) - (setq func (1- func))))))) - nil)) - -(defun pascal-end-of-defun () - "Move forward to the end of the current function or procedure." - (interactive) - (if (looking-at "\\s ") - (forward-sexp 1)) - (if (not (looking-at pascal-defun-re)) - (pascal-beg-of-defun)) - (forward-char 1) - (let ((nest 0) (func 1) - (reg (concat pascal-beg-block-re "\\|" - pascal-end-block-re "\\|" - pascal-defun-re))) - (while (and (/= func 0) - (re-search-forward reg nil 'move)) - (cond ((let ((state (save-excursion - (parse-partial-sexp (point-min) (point))))) - (or (nth 3 state) (nth 4 state))) ; Inside string or comment - ()) - ((match-end 1) - (setq nest (1+ nest)) - (if (save-excursion - (goto-char (match-beginning 0)) - (looking-at "\\<record\\>")) - (setq func (1+ func)))) - ((match-end 2) - (setq nest (1- nest)) - (if (= nest 0) - (setq func (1- func)))) - ((match-end 3) - (setq func (1+ func)))))) - (forward-line 1)) - -(defun pascal-downcase-keywords () - "Downcase all Pascal keywords in the buffer." - (interactive) - (pascal-change-keywords 'downcase-word)) - -(defun pascal-upcase-keywords () - "Upcase all Pascal keywords in the buffer." - (interactive) - (pascal-change-keywords 'upcase-word)) - -(defun pascal-capitalize-keywords () - "Capitalize all Pascal keywords in the buffer." - (interactive) - (pascal-change-keywords 'capitalize-word)) - -;; Change the keywords according to argument. -(defun pascal-change-keywords (change-word) - (save-excursion - (let ((keyword-re (concat "\\<\\(" - (mapconcat 'identity pascal-keywords "\\|") - "\\)\\>"))) - (goto-char (point-min)) - (while (re-search-forward keyword-re nil t) - (funcall change-word -1))))) - - - -;;; -;;; Other functions -;;; -(defun pascal-set-auto-comments () - "Insert `{ case }' or `{ NAME }' on this line if appropriate. -Insert `{ case }' if there is an `end' on the line which -ends a case block. Insert `{ NAME }' if there is an `end' -on the line which ends a function or procedure named NAME." - (save-excursion - (forward-line -1) - (skip-chars-forward " \t") - (if (and (looking-at "\\<end;") - (not (save-excursion - (end-of-line) - (search-backward "{" (pascal-get-beg-of-line) t)))) - (let ((type (car (pascal-calculate-indent)))) - (if (eq type 'declaration) - () - (if (eq type 'case) - ;; This is a case block - (progn - (end-of-line) - (delete-horizontal-space) - (insert " { case }")) - (let ((nest 1)) - ;; Check if this is the end of a function - (save-excursion - (while (not (or (looking-at pascal-defun-re) (bobp))) - (backward-sexp 1) - (cond ((looking-at pascal-beg-block-re) - (setq nest (1- nest))) - ((looking-at pascal-end-block-re) - (setq nest (1+ nest))))) - (if (bobp) - (setq nest 1))) - (if (zerop nest) - (progn - (end-of-line) - (delete-horizontal-space) - (insert " { ") - (let (b e) - (save-excursion - (setq b (progn (pascal-beg-of-defun) - (skip-chars-forward "^ \t") - (skip-chars-forward " \t") - (point)) - e (progn (skip-chars-forward "a-zA-Z0-9_") - (point)))) - (insert-buffer-substring (current-buffer) b e)) - (insert " }")))))))))) - - - -;;; -;;; Indentation -;;; -(defconst pascal-indent-alist - '((block . (+ ind pascal-indent-level)) - (case . (+ ind pascal-case-indent)) - (declaration . (+ ind pascal-indent-level)) - (paramlist . (pascal-indent-paramlist t)) - (comment . (pascal-indent-comment t)) - (defun . ind) (contexp . ind) - (unknown . 0) (string . 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)))) - (cond ((eq type 'paramlist) - (pascal-indent-paramlist) - (pascal-indent-paramlist)) - ((eq type 'declaration) - (pascal-indent-declaration)) - ((and (eq type 'case) (not (looking-at "^[ \t]*$"))) - (pascal-indent-case))) - (if (looking-at "[ \t]+$") - (skip-chars-forward " \t")))) - -(defun pascal-indent-line () - "Indent current line as a Pascal statement." - (let* ((indent-str (pascal-calculate-indent)) - (type (car indent-str)) - (ind (car (cdr indent-str)))) - (if (looking-at "^[0-9a-zA-Z]+[ \t]*:[^=]") - (search-forward ":" nil t)) - (delete-horizontal-space) - ;; Some thing should not be indented - (if (or (and (eq type 'declaration) (looking-at pascal-declaration-re)) - (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)))) - )))) - -(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)) - (state (save-excursion (parse-partial-sexp (point-min) (point)))) - (nest 0) (par 0) (complete nil) - (elsed (looking-at "[ \t]*else\\>")) - (type (catch 'nesting - ;; Check if inside a string, comment or parenthesis - (cond ((nth 3 state) (throw 'nesting 'string)) - ((nth 4 state) (throw 'nesting 'comment)) - ((> (car state) 0) - (goto-char (scan-lists (point) -1 (car state))) - (setq par (1+ (current-column))))) - ;; Loop until correct indent is found - (while t - (backward-sexp 1) - (cond (;--Nest block outwards - (looking-at pascal-beg-block-re) - (if (= nest 0) - (cond ((looking-at "case\\>") - (throw 'nesting 'case)) - ((looking-at "record\\>") - (throw 'nesting 'declaration)) - (t (throw 'nesting 'block))) - (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)) - (setq complete t - nest (1+ nest))) - (;--Defun (or parameter list) - (looking-at pascal-defun-re) - (if (= 0 par) - (throw 'nesting 'defun) - (setq par 0) - (let ((n 0)) - (while (re-search-forward - "\\(\\<record\\>\\)\\|\\<end\\>" - oldpos t) - (if (match-end 1) - (setq n (1+ n)) (setq n (1- n)))) - (if (> n 0) - (throw 'nesting 'declaration) - (throw 'nesting 'paramlist))))) - (;--Declaration part - (looking-at pascal-declaration-re) - (if (save-excursion - (goto-char oldpos) - (forward-line -1) - (looking-at "^[ \t]*$")) - (throw 'nesting 'unknown) - (throw 'nesting 'declaration))) - (;--If, else or while statement - (and (not complete) - (looking-at pascal-sub-block-re)) - (throw 'nesting 'block)) - (;--Found complete statement - (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 - (list 'contexp par) - (list type (pascal-indent-level)))))) - -(defun pascal-indent-level () - "Return the indent-level the current statement has. -Do not count labels, case-statements or records." - (save-excursion - (beginning-of-line) - (if (looking-at "[ \t]*[0-9a-zA-Z]+[ \t]*:[^=]") - (search-forward ":" nil t) - (if (looking-at ".*=[ \t]*record\\>") - (search-forward "=" nil t))) - (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-case () - "Indent within case statements." - (skip-chars-forward ": \t") - (let ((end (prog2 - (end-of-line) - (point-marker) - (re-search-backward "\\<case\\>" nil t))) - (beg (point)) - (ind 0)) - ;; Get right indent - (while (< (point) (marker-position 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))) - (beginning-of-line 2)) - (goto-char beg) - ;; Indent all case statements - (while (< (point) (marker-position end)) - (if (re-search-forward - "^[ \t]*[^ \t,:]+[ \t]*\\(,[ \t]*[^ \t,:]+[ \t]*\\)*:" - (marker-position end) 'move) - (forward-char -1)) - (indent-to (1+ ind)) - (if (/= (following-char) ?:) - () - (forward-char 1) - (delete-horizontal-space) - (insert " "))))) - -(defun pascal-indent-paramlist (&optional arg) - "Indent current line in parameterlist. -If optional arg is non-nil, just return the -indent of the current line in parameterlist." - (save-excursion - (let* ((oldpos (point)) - (stpos (progn (goto-char (scan-lists (point) -1 1)) (point))) - (stcol (1+ (current-column))) - (edpos (progn (pascal-declaration-end) - (search-backward ")" (pascal-get-beg-of-line) t) - (point))) - (usevar (re-search-backward "\\<var\\>" stpos t))) - (if arg (progn - ;; If arg, just return indent - (goto-char oldpos) - (beginning-of-line) - (if (or (not usevar) (looking-at "[ \t]*var\\>")) - stcol (+ 4 stcol))) - (goto-char stpos) - (forward-char 1) - (delete-horizontal-space) - (if (and usevar (not (looking-at "var\\>"))) - (indent-to (+ 4 stcol))) - (pascal-indent-declaration nil stpos edpos))))) - -(defun pascal-indent-declaration (&optional arg start end) - "Indent current lines as declaration, lining up the `:'s or `='s." - (let ((pos (point-marker))) - (if (and (not (or arg start)) (not (pascal-declaration-beg))) - () - (let ((lineup (if (or (looking-at "\\<var\\>\\|\\<record\\>") arg start) - ":" "=")) - (stpos (if start start - (forward-word 2) (backward-word 1) (point))) - (edpos (set-marker (make-marker) - (if end end - (max (progn (pascal-declaration-end) - (point)) - pos)))) - ind) - - (goto-char stpos) - ;; Indent lines in record block - (if arg - (while (<= (point) (marker-position edpos)) - (beginning-of-line) - (delete-horizontal-space) - (if (looking-at "end\\>") - (indent-to arg) - (indent-to (+ arg pascal-indent-level))) - (forward-line 1))) - - ;; Do lineup - (setq ind (pascal-get-lineup-indent stpos edpos lineup)) - (goto-char stpos) - (while (<= (point) (marker-position edpos)) - (if (search-forward lineup (pascal-get-end-of-line) 'move) - (forward-char -1)) - (delete-horizontal-space) - (indent-to ind) - (if (not (looking-at lineup)) - (forward-line 1) ; No more indent if there is no : or = - (forward-char 1) - (delete-horizontal-space) - (insert " ") - ;; Indent record block - (if (looking-at "record\\>") - (pascal-indent-declaration (current-column))) - (forward-line 1))))) - - ;; If arg - move point - (if arg (forward-line -1) - (goto-char (marker-position 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) - (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) - ;; 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))) - (end-of-line))))) - ;; In case no lineup was found - (if (> ind 0) - (1+ ind) - ;; No lineup-string found - (goto-char b) - (end-of-line) - (skip-chars-backward " \t") - (1+ (current-column)))))) - - - -;;; -;;; Completion -;;; -(defun pascal-string-diff (str1 str2) - "Return index of first letter where STR1 and STR2 differs." - (catch 'done - (let ((diff 0)) - (while t - (if (or (> (1+ diff) (length str1)) - (> (1+ diff) (length str2))) - (throw 'done diff)) - (or (equal (aref str1 diff) (aref str2 diff)) - (throw 'done diff)) - (setq diff (1+ diff)))))) - -;; Calculate all possible completions for functions if argument is `function', -;; completions for procedures if argument is `procedure' or both functions and -;; procedures otherwise. - -(defun pascal-func-completion (type) - ;; Build regular expression for function/procedure names - (if (string= str "") - (setq str "[a-zA-Z_]")) - (let ((str (concat (cond ((eq type 'procedure) "\\<\\(procedure\\)\\s +") - ((eq type 'function) "\\<\\(function\\)\\s +") - (t "\\<\\(function\\|procedure\\)\\s +")) - "\\<\\(" str "[a-zA-Z0-9_.]*\\)\\>")) - match) - - (if (not (looking-at "\\<\\(function\\|procedure\\)\\>")) - (re-search-backward "\\<\\(function\\|procedure\\)\\>" nil t)) - (forward-char 1) - - ;; Search through all reachable functions - (while (pascal-beg-of-defun) - (if (re-search-forward str (pascal-get-end-of-line) t) - (progn (setq match (buffer-substring (match-beginning 2) - (match-end 2))) - (if (or (null predicate) - (funcall prdicate match)) - (setq all (cons match all))))) - (goto-char (match-beginning 0))))) - -(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' - (let ((end (save-excursion (pascal-declaration-end) - (point))) - match) - ;; Traverse lines - (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\\)\\>\\)\\|" - pascal-symbol-re) - (pascal-get-beg-of-line) t) - (not (match-end 1))) - (setq match (buffer-substring (match-beginning 0) (match-end 0))) - (if (string-match (concat "\\<" str) match) - (if (or (null predicate) - (funcall predicate match)) - (setq all (cons match all)))))) - (if (re-search-forward "\\<record\\>" (pascal-get-end-of-line) t) - (pascal-declaration-end) - (forward-line 1))))) - -(defun pascal-type-completion () - "Calculate all possible completions for types." - (let ((start (point)) - goon) - ;; Search for all reachable type declarations - (while (or (pascal-beg-of-defun) - (setq goon (not goon))) - (save-excursion - (if (and (< start (prog1 (save-excursion (pascal-end-of-defun) - (point)) - (forward-char 1))) - (re-search-forward - "\\<type\\>\\|\\<\\(begin\\|function\\|proceudre\\)\\>" - start t) - (not (match-end 1))) - ;; Check current type declaration - (pascal-get-completion-decl)))))) - -(defun pascal-var-completion () - "Calculate all possible completions for variables (or constants)." - (let ((start (point)) - goon twice) - ;; Search for all reachable var declarations - (while (or (pascal-beg-of-defun) - (setq goon (not goon))) - (save-excursion - (if (> start (prog1 (save-excursion (pascal-end-of-defun) - (point)))) - () ; Declarations not reacable - (if (search-forward "(" (pascal-get-end-of-line) t) - ;; Check parameterlist - (pascal-get-completion-decl)) - (setq twice 2) - (while (>= (setq twice (1- twice)) 0) - (cond ((and (re-search-forward - (concat "\\<\\(var\\|const\\)\\>\\|" - "\\<\\(begin\\|function\\|procedure\\)\\>") - start t) - (not (match-end 2))) - ;; Check var/const declarations - (pascal-get-completion-decl)) - ((match-end 2) - (setq twice 0))))))))) - - -(defun pascal-keyword-completion (keyword-list) - "Give list of all possible completions of keywords in KEYWORD-LIST." - (mapcar '(lambda (s) - (if (string-match (concat "\\<" str) s) - (if (or (null predicate) - (funcall predicate s)) - (setq all (cons s all))))) - keyword-list)) - -;; Function passed to completing-read, try-completion or -;; all-completions to get completion on STR. If predicate is non-nil, -;; it must be a function to be called for every match to check if this -;; should really be a match. If flag is t, the function returns a list -;; of all possible completions. If it is nil it returns a string, the -;; longest possible completion, or t if STR is an exact match. If flag -;; is 'lambda, the function returns t if STR is an exact match, nil -;; otherwise. - -(defun pascal-completion (str predicate flag) - (save-excursion - (let ((all nil)) - ;; Set buffer to use for searching labels. This should be set - ;; within functins which use pascal-completions - (set-buffer buffer-to-use) - - ;; Determine what should be completed - (let ((state (car (pascal-calculate-indent)))) - (cond (;--Within a declaration or parameterlist - (or (eq state 'declaration) (eq state 'paramlist) - (and (eq state 'defun) - (save-excursion - (re-search-backward ")[ \t]*:" (pascal-get-beg-of-line) t)))) - (if (or (eq state 'paramlist) (eq state 'defun)) - (pascal-beg-of-defun)) - (pascal-type-completion) - (pascal-keyword-completion pascal-type-keywords)) - (;--Starting a new statement - (and (not (eq state 'contexp)) - (save-excursion - (skip-chars-backward "a-zA-Z0-9_.") - (backward-sexp 1) - (or (looking-at pascal-nosemi-re) - (progn - (forward-sexp 1) - (looking-at "\\s *\\(;\\|:[^=]\\)"))))) - (save-excursion (pascal-var-completion)) - (pascal-func-completion 'procedure) - (pascal-keyword-completion pascal-start-keywords)) - (t;--Anywhere else - (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)))) - -(defun pascal-completion-response () - (cond ((or (equal flag 'lambda) (null flag)) - ;; This was not called by all-completions - (if (null all) - ;; Return nil if there was no matching label - nil - ;; Get longest string common in the labels - (let* ((elm (cdr all)) - (match (car all)) - (min (length match)) - exact tmp) - (if (string= match str) - ;; Return t if first match was an exact match - (setq match t) - (while (not (null elm)) - ;; Find longest common string - (if (< (setq tmp (pascal-string-diff match (car elm))) min) - (progn - (setq min tmp) - (setq match (substring match 0 min)))) - ;; Terminate with match=t if this is an exact match - (if (string= (car elm) str) - (progn - (setq match t) - (setq elm nil)) - (setq elm (cdr elm))))) - ;; If this is a test just for exact match, return nil ot t - (if (and (equal flag 'lambda) (not (equal match 't))) - nil - match)))) - ;; If flag is t, this was called by all-completions. Return - ;; list of all possible completions - (flag - all))) - -(defvar pascal-last-word-numb 0) -(defvar pascal-last-word-shown nil) -(defvar pascal-last-completions nil) - -(defun pascal-complete-word () - "Complete word at current point. -\(See also `pascal-toggle-completions', `pascal-type-keywords', -`pascal-start-keywords' and `pascal-separator-keywords'.)" - (interactive) - (let* ((b (save-excursion (skip-chars-backward "a-zA-Z0-9_") (point))) - (e (save-excursion (skip-chars-forward "a-zA-Z0-9_") (point))) - (str (buffer-substring b e)) - ;; The following variable is used in pascal-completion - (buffer-to-use (current-buffer)) - (allcomp (if (and pascal-toggle-completions - (string= pascal-last-word-shown str)) - pascal-last-completions - (all-completions str 'pascal-completion))) - (match (if pascal-toggle-completions - "" (try-completion - str (mapcar '(lambda (elm) (cons elm 0)) allcomp))))) - ;; Delete old string - (delete-region b e) - - ;; Toggle-completions inserts whole labels - (if pascal-toggle-completions - (progn - ;; Update entry number in list - (setq pascal-last-completions allcomp - pascal-last-word-numb - (if (>= pascal-last-word-numb (1- (length allcomp))) - 0 - (1+ pascal-last-word-numb))) - (setq pascal-last-word-shown (elt allcomp pascal-last-word-numb)) - ;; Display next match or same string if no match was found - (if (not (null allcomp)) - (insert "" pascal-last-word-shown) - (insert "" str) - (message "(No match)"))) - ;; The other form of completion does not necessarly do that. - - ;; Insert match if found, or the original string if no match - (if (or (null match) (equal match 't)) - (progn (insert "" str) - (message "(No match)")) - (insert "" match)) - ;; Give message about current status of completion - (cond ((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 - ;; on completing the label. - ((and (not (null (cdr allcomp))) (= (length str) (length match))) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list allcomp)) - ;; Wait for a keypress. Then delete *Completion* window - (momentary-string-display "" (point)) - (delete-window (get-buffer-window (get-buffer "*Completions*"))) - ))))) - -(defun pascal-show-completions () - "Show all possible completions at current point." - (interactive) - (let* ((b (save-excursion (skip-chars-backward "a-zA-Z0-9_") (point))) - (e (save-excursion (skip-chars-forward "a-zA-Z0-9_") (point))) - (str (buffer-substring b e)) - ;; The following variable is used in pascal-completion - (buffer-to-use (current-buffer)) - (allcomp (if (and pascal-toggle-completions - (string= pascal-last-word-shown str)) - pascal-last-completions - (all-completions str 'pascal-completion)))) - ;; Show possible completions in a temporary buffer. - (with-output-to-temp-buffer "*Completions*" - (display-completion-list allcomp)) - ;; Wait for a keypress. Then delete *Completion* window - (momentary-string-display "" (point)) - (delete-window (get-buffer-window (get-buffer "*Completions*"))))) - - -(defun pascal-get-default-symbol () - "Return symbol around current point as a string." - (save-excursion - (buffer-substring (progn - (skip-chars-backward " \t") - (skip-chars-backward "a-zA-Z0-9_") - (point)) - (progn - (skip-chars-forward "a-zA-Z0-9_") - (point))))) - -(defun pascal-build-defun-re (str &optional arg) - "Return function/procedure starting with STR as regular expression. -With optional second arg non-nil, STR is the complete name of the instruction." - (if arg - (concat "^\\(function\\|procedure\\)[ \t]+\\(" str "\\)\\>") - (concat "^\\(function\\|procedure\\)[ \t]+\\(" str "[a-zA-Z0-9_]*\\)\\>"))) - -;; Function passed to completing-read, try-completion or -;; all-completions to get completion on any function name. If -;; predicate is non-nil, it must be a function to be called for every -;; match to check if this should really be a match. If flag is t, the -;; function returns a list of all possible completions. If it is nil -;; it returns a string, the longest possible completion, or t if STR -;; is an exact match. If flag is 'lambda, the function returns t if -;; STR is an exact match, nil otherwise. - -(defun pascal-comp-defun (str predicate flag) - (save-excursion - (let ((all nil) - match) - - ;; Set buffer to use for searching labels. This should be set - ;; within functins which use pascal-completions - (set-buffer buffer-to-use) - - (let ((str str)) - ;; Build regular expression for functions - (if (string= str "") - (setq str (pascal-build-defun-re "[a-zA-Z_]")) - (setq str (pascal-build-defun-re str))) - (goto-char (point-min)) - - ;; Build a list of all possible completions - (while (re-search-forward str nil t) - (setq match (buffer-substring (match-beginning 2) (match-end 2))) - (if (or (null predicate) - (funcall predicate match)) - (setq all (cons match all))))) - - ;; Now we have built a list of all matches. Give response to caller - (pascal-completion-response)))) - -(defun pascal-goto-defun () - "Move to specified Pascal function/procedure. -The default is a name found in the buffer around point." - (interactive) - (let* ((default (pascal-get-default-symbol)) - ;; The following variable is used in pascal-comp-function - (buffer-to-use (current-buffer)) - (default (if (pascal-comp-defun default nil 'lambda) - default "")) - (label (if (not (string= default "")) - ;; Do completion with default - (completing-read (concat "Label: (default " default ") ") - 'pascal-comp-defun nil t "") - ;; There is no default value. Complete without it - (completing-read "Label: " - 'pascal-comp-defun nil t "")))) - ;; If there was no response on prompt, use default value - (if (string= label "") - (setq label default)) - ;; Goto right place in buffer if label is not an empty string - (or (string= label "") - (progn - (goto-char (point-min)) - (re-search-forward (pascal-build-defun-re label t)) - (beginning-of-line))))) - - - -;;; -;;; Pascal-outline-mode -;;; -(defvar pascal-outline-map nil "Keymap used in Pascal Outline mode.") - -(if pascal-outline-map - nil - (if (boundp 'set-keymap-name) - (set-keymap-name pascal-outline-map 'pascal-outline-map)) - (if (not (boundp 'set-keymap-parent)) - (setq pascal-outline-map (copy-keymap pascal-mode-map)) - (setq pascal-outline-map (make-sparse-keymap)) - (set-keymap-parent pascal-outline-map pascal-mode-map)) - (define-key pascal-outline-map "\e\C-a" 'pascal-outline-prev-defun) - (define-key pascal-outline-map "\e\C-e" 'pascal-outline-next-defun) - (define-key pascal-outline-map "\C-cg" 'pascal-outline-goto-defun) - (define-key pascal-outline-map "\C-c\C-s" 'pascal-show-all) - (define-key pascal-outline-map "\C-c\C-h" 'pascal-hide-other-defuns)) - -(defvar pascal-outline-mode nil "Non-nil while using Pascal Outline mode.") -(make-variable-buffer-local 'pascal-outline-mode) -(set-default 'pascal-outline-mode nil) -(if (not (assoc 'pascal-outline-mode minor-mode-alist)) - (setq minor-mode-alist (append minor-mode-alist - (list '(pascal-outline-mode " Outl"))))) - -(defun pascal-outline (&optional arg) - "Outline-line minor mode for Pascal mode. -When in Pascal Outline mode, portions -of the text being edited may be made invisible. \\<pascal-outline-map> - -Pascal Outline mode provides some additional commands. - -\\[pascal-outline-prev-defun]\ -\t- Move to previous function/procedure, hiding everything else. -\\[pascal-outline-next-defun]\ -\t- Move to next function/procedure, hiding everything else. -\\[pascal-outline-goto-defun]\ -\t- Goto function/procedure prompted for in minibuffer, -\t hide all other functions. -\\[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." - (interactive "P") - (setq pascal-outline-mode - (if (null arg) (not pascal-outline-mode) t)) - (if (boundp 'redraw-mode-line) - (redraw-mode-line)) - (if pascal-outline-mode - (progn - (setq selective-display t) - (use-local-map pascal-outline-map)) - (progn - (setq selective-display nil) - (pascal-show-all) - (use-local-map pascal-mode-map)))) - -(defun pascal-outline-change (b e flag) - (let ((modp (buffer-modified-p))) - (unwind-protect - (subst-char-in-region b e (if (= flag ?\n) ?\^M ?\n) flag) - (set-buffer-modified-p modp)))) - -(defun pascal-show-all () - "Show all of the text in the buffer." - (interactive) - (pascal-outline-change (point-min) (point-max) ?\n)) - -(defun pascal-hide-other-defuns () - "Show only the current defun." - (interactive) - (save-excursion - (let ((beg (progn (if (not (looking-at "\\(function\\|procedure\\)\\>")) - (pascal-beg-of-defun)) - (point))) - (end (progn (pascal-end-of-defun) - (backward-sexp 1) - (search-forward "\n\\|\^M" nil t) - (point))) - (opoint (point-min))) - (goto-char (point-min)) - - ;; Hide all functions before current function - (while (re-search-forward "^\\(function\\|procedure\\)\\>" beg 'move) - (pascal-outline-change opoint (1- (match-beginning 0)) ?\^M) - (setq opoint (point)) - ;; Functions may be nested - (if (> (progn (pascal-end-of-defun) (point)) beg) - (goto-char opoint))) - (if (> beg opoint) - (pascal-outline-change opoint (1- beg) ?\^M)) - - ;; Show current function - (pascal-outline-change beg end ?\n) - ;; Hide nested functions - (forward-char 1) - (while (re-search-forward "^\\(function\\|procedure\\)\\>" end 'move) - (setq opoint (point)) - (pascal-end-of-defun) - (pascal-outline-change opoint (point) ?\^M)) - - (goto-char end) - (setq opoint end) - - ;; Hide all function after current function - (while (re-search-forward "^\\(function\\|procedure\\)\\>" nil 'move) - (pascal-outline-change opoint (1- (match-beginning 0)) ?\^M) - (setq opoint (point)) - (pascal-end-of-defun)) - (pascal-outline-change opoint (point-max) ?\^M) - - ;; Hide main program - (if (< (progn (forward-line -1) (point)) end) - (progn - (goto-char beg) - (pascal-end-of-defun) - (backward-sexp 1) - (pascal-outline-change (point) (point-max) ?\^M)))))) - -(defun pascal-outline-next-defun () - "Move to next function/procedure, hiding all others." - (interactive) - (pascal-end-of-defun) - (pascal-hide-other-defuns)) - -(defun pascal-outline-prev-defun () - "Move to previous function/procedure, hiding all others." - (interactive) - (pascal-beg-of-defun) - (pascal-hide-other-defuns)) - -(defun pascal-outline-goto-defun () - "Move to specified function/procedure, hiding all others." - (interactive) - (pascal-goto-defun) - (pascal-hide-other-defuns)) - -;;; pascal.el ends here diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el deleted file mode 100644 index ac2c260ad0b..00000000000 --- a/lisp/progmodes/perl-mode.el +++ /dev/null @@ -1,641 +0,0 @@ -;;; perl-mode.el --- Perl code editing commands for GNU Emacs - -;; Copyright (C) 1990 Free Software Foundation, Inc. - -;; Author: William F. Mann -;; Adapted-By: ESR -;; Keywords: languages - -;; Adapted from C code editing commands 'c-mode.el', Copyright 1987 by the -;; Free Software Foundation, under terms of its General Public License. - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; To enter perl-mode automatically, add (autoload 'perl-mode "perl-mode") -;; to your .emacs file and change the first line of your perl script to: -;; #!/usr/bin/perl -- # -*-Perl-*- -;; With argments to perl: -;; #!/usr/bin/perl -P- # -*-Perl-*- -;; To handle files included with do 'filename.pl';, add something like -;; (setq auto-mode-alist (append (list (cons "\\.pl$" 'perl-mode)) -;; auto-mode-alist)) -;; to your .emacs file; otherwise the .pl suffix defaults to prolog-mode. - -;; This code is based on the 18.53 version c-mode.el, with extensive -;; rewriting. Most of the features of c-mode survived intact. - -;; I added a new feature which adds functionality to TAB; it is controlled -;; by the variable perl-tab-to-comment. With it enabled, TAB does the -;; first thing it can from the following list: change the indentation; -;; move past leading white space; delete an empty comment; reindent a -;; comment; move to end of line; create an empty comment; tell you that -;; the line ends in a quoted string, or has a # which should be a \#. - -;; If your machine is slow, you may want to remove some of the bindings -;; to electric-perl-terminator. I changed the indenting defaults to be -;; what Larry Wall uses in perl/lib, but left in all the options. - -;; I also tuned a few things: comments and labels starting in column -;; zero are left there by indent-perl-exp; perl-beginning-of-function -;; goes back to the first open brace/paren in column zero, the open brace -;; in 'sub ... {', or the equal sign in 'format ... ='; indent-perl-exp -;; (meta-^q) indents from the current line through the close of the next -;; brace/paren, so you don't need to start exactly at a brace or paren. - -;; It may be good style to put a set of redundant braces around your -;; main program. This will let you reindent it with meta-^q. - -;; Known problems (these are all caused by limitations in the Emacs Lisp -;; parsing routine (parse-partial-sexp), which was not designed for such -;; a rich language; writing a more suitable parser would be a big job): -;; 1) Regular expression delimiters do not act as quotes, so special -;; characters such as `'"#:;[](){} may need to be backslashed -;; in regular expressions and in both parts of s/// and tr///. -;; 2) The globbing syntax <pattern> is not recognized, so special -;; characters in the pattern string must be backslashed. -;; 3) The q, qq, and << quoting operators are not recognized; see below. -;; 4) \ (backslash) always quotes the next character, so '\' is -;; treated as the start of a string. Use "\\" as a work-around. -;; 5) To make variables such a $' and $#array work, perl-mode treats -;; $ just like backslash, so '$' is the same as problem 5. -;; 6) Unfortunately, treating $ like \ makes ${var} be treated as an -;; unmatched }. See below. -;; 7) When ' (quote) is used as a package name separator, perl-mode -;; doesn't understand, and thinks it is seeing a quoted string. - -;; Here are some ugly tricks to bypass some of these problems: the perl -;; expression /`/ (that's a back-tick) usually evaluates harmlessly, -;; but will trick perl-mode into starting a quoted string, which -;; can be ended with another /`/. Assuming you have no embedded -;; back-ticks, this can used to help solve problem 3: -;; -;; /`/; $ugly = q?"'$?; /`/; -;; -;; To solve problem 6, add a /{/; before each use of ${var}: -;; /{/; while (<${glob_me}>) ... -;; -;; Problem 7 is even worse, but this 'fix' does work :-( -;; $DB'stop#' -;; [$DB'line#' -;; ] =~ s/;9$//; - -;;; Code: - -(defvar perl-mode-abbrev-table nil - "Abbrev table in use in perl-mode buffers.") -(define-abbrev-table 'perl-mode-abbrev-table ()) - -(defvar perl-mode-map () - "Keymap used in Perl mode.") -(if perl-mode-map - () - (setq perl-mode-map (make-sparse-keymap)) - (define-key perl-mode-map "{" 'electric-perl-terminator) - (define-key perl-mode-map "}" 'electric-perl-terminator) - (define-key perl-mode-map ";" 'electric-perl-terminator) - (define-key perl-mode-map ":" 'electric-perl-terminator) - (define-key perl-mode-map "\e\C-a" 'perl-beginning-of-function) - (define-key perl-mode-map "\e\C-e" 'perl-end-of-function) - (define-key perl-mode-map "\e\C-h" 'mark-perl-function) - (define-key perl-mode-map "\e\C-q" 'indent-perl-exp) - (define-key perl-mode-map "\177" 'backward-delete-char-untabify) - (define-key perl-mode-map "\t" 'perl-indent-command)) - -(autoload 'c-macro-expand "cmacexp" - "Display the result of expanding all C macros occurring in the region. -The expansion is entirely correct because it uses the C preprocessor." - t) - -(defvar perl-mode-syntax-table nil - "Syntax table in use in perl-mode buffers.") - -(if perl-mode-syntax-table - () - (setq perl-mode-syntax-table (make-syntax-table (standard-syntax-table))) - (modify-syntax-entry ?\n ">" perl-mode-syntax-table) - (modify-syntax-entry ?# "<" perl-mode-syntax-table) - (modify-syntax-entry ?$ "/" perl-mode-syntax-table) - (modify-syntax-entry ?% "." perl-mode-syntax-table) - (modify-syntax-entry ?& "." perl-mode-syntax-table) - (modify-syntax-entry ?\' "\"" perl-mode-syntax-table) - (modify-syntax-entry ?* "." perl-mode-syntax-table) - (modify-syntax-entry ?+ "." perl-mode-syntax-table) - (modify-syntax-entry ?- "." perl-mode-syntax-table) - (modify-syntax-entry ?/ "." perl-mode-syntax-table) - (modify-syntax-entry ?< "." perl-mode-syntax-table) - (modify-syntax-entry ?= "." perl-mode-syntax-table) - (modify-syntax-entry ?> "." perl-mode-syntax-table) - (modify-syntax-entry ?\\ "\\" perl-mode-syntax-table) - (modify-syntax-entry ?` "\"" perl-mode-syntax-table) - (modify-syntax-entry ?| "." perl-mode-syntax-table) -) - -(defvar perl-indent-level 4 - "*Indentation of Perl statements with respect to containing block.") -(defvar perl-continued-statement-offset 4 - "*Extra indent for lines not starting new statements.") -(defvar perl-continued-brace-offset -4 - "*Extra indent for substatements that start with open-braces. -This is in addition to `perl-continued-statement-offset'.") -(defvar perl-brace-offset 0 - "*Extra indentation for braces, compared with other text in same context.") -(defvar perl-brace-imaginary-offset 0 - "*Imagined indentation of an open brace that actually follows a statement.") -(defvar perl-label-offset -2 - "*Offset of Perl label lines relative to usual indentation.") - -(defvar perl-tab-always-indent t - "*Non-nil means TAB in Perl mode always indents the current line. -Otherwise it inserts a tab character if you type it past the first -nonwhite character on the line.") - -(defvar perl-tab-to-comment t - "*Non-nil means TAB moves to eol or makes a comment in some cases. -For lines which don't need indenting, TAB either indents an -existing comment, moves to end-of-line, or if at end-of-line already, -create a new comment.") - -(defvar perl-nochange ";?#\\|\f\\|\\s(\\|\\(\\w\\|\\s_\\)+:" - "*Lines starting with this regular expression are not auto-indented.") - -;;;###autoload -(defun perl-mode () - "Major mode for editing Perl code. -Expression and list commands understand all Perl brackets. -Tab indents for Perl code. -Comments are delimited with # ... \\n. -Paragraphs are separated by blank lines only. -Delete converts tabs to spaces as it moves back. -\\{perl-mode-map} -Variables controlling indentation style: - perl-tab-always-indent - Non-nil means TAB in Perl mode should always indent the current line, - regardless of where in the line point is when the TAB command is used. - perl-tab-to-comment - Non-nil means that for lines which don't need indenting, TAB will - either delete an empty comment, indent an existing comment, move - to end-of-line, or if at end-of-line already, create a new comment. - perl-nochange - Lines starting with this regular expression are not auto-indented. - perl-indent-level - Indentation of Perl statements within surrounding block. - The surrounding block's indentation is the indentation - of the line on which the open-brace appears. - perl-continued-statement-offset - Extra indentation given to a substatement, such as the - then-clause of an if or body of a while. - perl-continued-brace-offset - Extra indentation given to a brace that starts a substatement. - This is in addition to `perl-continued-statement-offset'. - perl-brace-offset - Extra indentation for line if it starts with an open brace. - perl-brace-imaginary-offset - An open brace following other text is treated as if it were - this far to the right of the start of its line. - perl-label-offset - Extra indentation for line that is a label. - -Various indentation styles: K&R BSD BLK GNU LW - perl-indent-level 5 8 0 2 4 - perl-continued-statement-offset 5 8 4 2 4 - perl-continued-brace-offset 0 0 0 0 -4 - perl-brace-offset -5 -8 0 0 0 - perl-brace-imaginary-offset 0 0 4 0 0 - perl-label-offset -5 -8 -2 -2 -2 - -Turning on Perl mode runs the normal hook `perl-mode-hook'." - (interactive) - (kill-all-local-variables) - (use-local-map perl-mode-map) - (setq major-mode 'perl-mode) - (setq mode-name "Perl") - (setq local-abbrev-table perl-mode-abbrev-table) - (set-syntax-table perl-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'perl-indent-line) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "# ") - (make-local-variable 'comment-end) - (setq comment-end "") - (make-local-variable 'comment-column) - (setq comment-column 32) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *") - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'perl-comment-indent) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t) - (run-hooks 'perl-mode-hook)) - -;; This is used by indent-for-comment -;; to decide how much to indent a comment in Perl code -;; based on its context. -(defun perl-comment-indent () - (if (and (bolp) (not (eolp))) - 0 ;Existing comment at bol stays there. - (save-excursion - (skip-chars-backward " \t") - (max (1+ (current-column)) ;Else indent at comment column - comment-column)))) ; except leave at least one space. - -(defun electric-perl-terminator (arg) - "Insert character and adjust indentation. -If at end-of-line, and not in a comment or a quote, correct the's indentation." - (interactive "P") - (let ((insertpos (point))) - (and (not arg) ; decide whether to indent - (eolp) - (save-excursion - (beginning-of-line) - (and (not ; eliminate comments quickly - (re-search-forward comment-start-skip insertpos t)) - (or (/= last-command-char ?:) - ;; Colon is special only after a label .... - (looking-at "\\s-*\\(\\w\\|\\s_\\)+$")) - (let ((pps (parse-partial-sexp - (perl-beginning-of-function) insertpos))) - (not (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))) - (progn ; must insert, indent, delete - (insert-char last-command-char 1) - (perl-indent-line) - (delete-char -1)))) - (self-insert-command (prefix-numeric-value arg))) - -;; not used anymore, but may be useful someday: -;;(defun perl-inside-parens-p () -;; (condition-case () -;; (save-excursion -;; (save-restriction -;; (narrow-to-region (point) -;; (perl-beginning-of-function)) -;; (goto-char (point-max)) -;; (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\())) -;; (error nil))) - -(defun perl-indent-command (&optional arg) - "Indent current line as Perl code, or optionally, insert a tab character. - -With an argument, indent the current line, regardless of other options. - -If `perl-tab-always-indent' is nil and point is not in the indentation -area at the beginning of the line, simply insert a tab. - -Otherwise, indent the current line. If point was within the indentation -area it is moved to the end of the indentation area. If the line was -already indented properly and point was not within the indentation area, -and if `perl-tab-to-comment' is non-nil (the default), then do the first -possible action from the following list: - - 1) delete an empty comment - 2) move forward to start of comment, indenting if necessary - 3) move forward to end of line - 4) create an empty comment - 5) move backward to start of comment, indenting if necessary." - (interactive "P") - (if arg ; If arg, just indent this line - (perl-indent-line "\f") - (if (and (not perl-tab-always-indent) - (<= (current-column) (current-indentation))) - (insert-tab) - (let (bof lsexp delta (oldpnt (point))) - (beginning-of-line) - (setq lsexp (point)) - (setq bof (perl-beginning-of-function)) - (goto-char oldpnt) - (setq delta (perl-indent-line "\f\\|;?#" bof)) - (and perl-tab-to-comment - (= oldpnt (point)) ; done if point moved - (if (listp delta) ; if line starts in a quoted string - (setq lsexp (or (nth 2 delta) bof)) - (= delta 0)) ; done if indenting occurred - (let (eol state) - (end-of-line) - (setq eol (point)) - (if (= (char-after bof) ?=) - (if (= oldpnt eol) - (message "In a format statement")) - (setq state (parse-partial-sexp lsexp eol)) - (if (nth 3 state) - (if (= oldpnt eol) ; already at eol in a string - (message "In a string which starts with a %c." - (nth 3 state))) - (if (not (nth 4 state)) - (if (= oldpnt eol) ; no comment, create one? - (indent-for-comment)) - (beginning-of-line) - (if (re-search-forward comment-start-skip eol 'move) - (if (eolp) - (progn ; kill existing comment - (goto-char (match-beginning 0)) - (skip-chars-backward " \t") - (kill-region (point) eol)) - (if (or (< oldpnt (point)) (= oldpnt eol)) - (indent-for-comment) ; indent existing comment - (end-of-line))) - (if (/= oldpnt eol) - (end-of-line) - (message "Use backslash to quote # characters.") - (ding t)))))))))))) - -(defun perl-indent-line (&optional nochange parse-start) - "Indent current line as Perl code. -Return the amount the indentation -changed by, or (parse-state) if line starts in a quoted string." - (let ((case-fold-search nil) - (pos (- (point-max) (point))) - (bof (or parse-start (save-excursion (perl-beginning-of-function)))) - beg indent shift-amt) - (beginning-of-line) - (setq beg (point)) - (setq shift-amt - (cond ((= (char-after bof) ?=) 0) - ((listp (setq indent (calculate-perl-indent bof))) indent) - ((looking-at (or nochange perl-nochange)) 0) - (t - (skip-chars-forward " \t\f") - (cond ((looking-at "\\(\\w\\|\\s_\\)+:") - (setq indent (max 1 (+ indent perl-label-offset)))) - ((= (following-char) ?}) - (setq indent (- indent perl-indent-level))) - ((= (following-char) ?{) - (setq indent (+ indent perl-brace-offset)))) - (- indent (current-column))))) - (skip-chars-forward " \t\f") - (if (and (numberp shift-amt) (/= 0 shift-amt)) - (progn (delete-region beg (point)) - (indent-to indent))) - ;; If initial point was within line's indentation, - ;; position after the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - shift-amt)) - -(defun calculate-perl-indent (&optional parse-start) - "Return appropriate indentation for current line as Perl code. -In usual case returns an integer: the column to indent to. -Returns (parse-state) if line starts inside a string." - (save-excursion - (beginning-of-line) - (let ((indent-point (point)) - (case-fold-search nil) - (colon-line-end 0) - state containing-sexp) - (if parse-start ;used to avoid searching - (goto-char parse-start) - (perl-beginning-of-function)) - (while (< (point) indent-point) ;repeat until right sexp - (setq parse-start (point)) - (setq state (parse-partial-sexp (point) indent-point 0)) -; state = (depth_in_parens innermost_containing_list last_complete_sexp -; string_terminator_or_nil inside_commentp following_quotep -; minimum_paren-depth_this_scan) -; Parsing stops if depth in parentheses becomes equal to third arg. - (setq containing-sexp (nth 1 state))) - (cond ((nth 3 state) state) ; In a quoted string? - ((null containing-sexp) ; Line is at top level. - (skip-chars-forward " \t\f") - (if (= (following-char) ?{) - 0 ; move to beginning of line if it starts a function body - ;; indent a little if this is a continuation line - (perl-backward-to-noncomment) - (if (or (bobp) - (memq (preceding-char) '(?\; ?\}))) - 0 perl-continued-statement-offset))) - ((/= (char-after containing-sexp) ?{) - ;; line is expression, not statement: - ;; indent to just after the surrounding open. - (goto-char (1+ containing-sexp)) - (current-column)) - (t - ;; Statement level. Is it a continuation or a new statement? - ;; Find previous non-comment character. - (perl-backward-to-noncomment) - ;; Back up over label lines, since they don't - ;; affect whether our line is a continuation. - (while (or (eq (preceding-char) ?\,) - (and (eq (preceding-char) ?:) - (memq (char-syntax (char-after (- (point) 2))) - '(?w ?_)))) - (if (eq (preceding-char) ?\,) - (perl-backward-to-start-of-continued-exp containing-sexp)) - (beginning-of-line) - (perl-backward-to-noncomment)) - ;; Now we get the answer. - (if (not (memq (preceding-char) '(?\; ?\} ?\{))) - ;; This line is continuation of preceding line's statement; - ;; indent perl-continued-statement-offset more than the - ;; previous line of the statement. - (progn - (perl-backward-to-start-of-continued-exp containing-sexp) - (+ perl-continued-statement-offset (current-column) - (if (save-excursion (goto-char indent-point) - (looking-at "[ \t]*{")) - perl-continued-brace-offset 0))) - ;; This line starts a new statement. - ;; Position at last unclosed open. - (goto-char containing-sexp) - (or - ;; If open paren is in col 0, close brace is special - (and (bolp) - (save-excursion (goto-char indent-point) - (looking-at "[ \t]*}")) - perl-indent-level) - ;; Is line first statement after an open-brace? - ;; If no, find that first statement and indent like it. - (save-excursion - (forward-char 1) - ;; Skip over comments and labels following openbrace. - (while (progn - (skip-chars-forward " \t\f\n") - (cond ((looking-at ";?#") - (forward-line 1) t) - ((looking-at "\\(\\w\\|\\s_\\)+:") - (save-excursion - (end-of-line) - (setq colon-line-end (point))) - (search-forward ":"))))) - ;; The first following code counts - ;; if it is before the line we want to indent. - (and (< (point) indent-point) - (if (> colon-line-end (point)) - (- (current-indentation) perl-label-offset) - (current-column)))) - ;; If no previous statement, - ;; indent it relative to line brace is on. - ;; For open paren in column zero, don't let statement - ;; start there too. If perl-indent-level is zero, - ;; use perl-brace-offset + perl-continued-statement-offset - ;; For open-braces not the first thing in a line, - ;; add in perl-brace-imaginary-offset. - (+ (if (and (bolp) (zerop perl-indent-level)) - (+ perl-brace-offset perl-continued-statement-offset) - perl-indent-level) - ;; Move back over whitespace before the openbrace. - ;; If openbrace is not first nonwhite thing on the line, - ;; add the perl-brace-imaginary-offset. - (progn (skip-chars-backward " \t") - (if (bolp) 0 perl-brace-imaginary-offset)) - ;; If the openbrace is preceded by a parenthesized exp, - ;; move to the beginning of that; - ;; possibly a different line - (progn - (if (eq (preceding-char) ?\)) - (forward-sexp -1)) - ;; Get initial indentation of the line we are on. - (current-indentation)))))))))) - -(defun perl-backward-to-noncomment () - "Move point backward to after the first non-white-space, skipping comments." - (interactive) - (let (opoint stop) - (while (not stop) - (setq opoint (point)) - (beginning-of-line) - (if (re-search-forward comment-start-skip opoint 'move 1) - (progn (goto-char (match-end 1)) - (skip-chars-forward ";"))) - (skip-chars-backward " \t\f") - (setq stop (or (bobp) - (not (bolp)) - (forward-char -1)))))) - -(defun perl-backward-to-start-of-continued-exp (lim) - (if (= (preceding-char) ?\)) - (forward-sexp -1)) - (beginning-of-line) - (if (<= (point) lim) - (goto-char (1+ lim))) - (skip-chars-forward " \t\f")) - -;; note: this may be slower than the c-mode version, but I can understand it. -(defun indent-perl-exp () - "Indent each line of the Perl grouping following point." - (interactive) - (let* ((case-fold-search nil) - (oldpnt (point-marker)) - (bof-mark (save-excursion - (end-of-line 2) - (perl-beginning-of-function) - (point-marker))) - eol last-mark lsexp-mark delta) - (if (= (char-after (marker-position bof-mark)) ?=) - (message "Can't indent a format statement") - (message "Indenting Perl expression...") - (save-excursion (end-of-line) (setq eol (point))) - (save-excursion ; locate matching close paren - (while (and (not (eobp)) (<= (point) eol)) - (parse-partial-sexp (point) (point-max) 0)) - (setq last-mark (point-marker))) - (setq lsexp-mark bof-mark) - (beginning-of-line) - (while (< (point) (marker-position last-mark)) - (setq delta (perl-indent-line nil (marker-position bof-mark))) - (if (numberp delta) ; unquoted start-of-line? - (progn - (if (eolp) - (delete-horizontal-space)) - (setq lsexp-mark (point-marker)))) - (end-of-line) - (setq eol (point)) - (if (nth 4 (parse-partial-sexp (marker-position lsexp-mark) eol)) - (progn ; line ends in a comment - (beginning-of-line) - (if (or (not (looking-at "\\s-*;?#")) - (listp delta) - (and (/= 0 delta) - (= (- (current-indentation) delta) comment-column))) - (if (re-search-forward comment-start-skip eol t) - (indent-for-comment))))) ; indent existing comment - (forward-line 1)) - (goto-char (marker-position oldpnt)) - (message "Indenting Perl expression...done")))) - -(defun perl-beginning-of-function (&optional arg) - "Move backward to next beginning-of-function, or as far as possible. -With argument, repeat that many times; negative args move forward. -Returns new value of point in all cases." - (interactive "p") - (or arg (setq arg 1)) - (if (< arg 0) (forward-char 1)) - (and (/= arg 0) - (re-search-backward "^\\s(\\|^\\s-*sub\\b[^{]+{\\|^\\s-*format\\b[^=]*=\\|^\\." - nil 'move arg) - (goto-char (1- (match-end 0)))) - (point)) - -;; note: this routine is adapted directly from emacs lisp.el, end-of-defun; -;; no bugs have been removed :-) -(defun perl-end-of-function (&optional arg) - "Move forward to next end-of-function. -The end of a function is found by moving forward from the beginning of one. -With argument, repeat that many times; negative args move backward." - (interactive "p") - (or arg (setq arg 1)) - (let ((first t)) - (while (and (> arg 0) (< (point) (point-max))) - (let ((pos (point)) npos) - (while (progn - (if (and first - (progn - (forward-char 1) - (perl-beginning-of-function 1) - (not (bobp)))) - nil - (or (bobp) (forward-char -1)) - (perl-beginning-of-function -1)) - (setq first nil) - (forward-list 1) - (skip-chars-forward " \t") - (if (looking-at "[#\n]") - (forward-line 1)) - (<= (point) pos)))) - (setq arg (1- arg))) - (while (< arg 0) - (let ((pos (point))) - (perl-beginning-of-function 1) - (forward-sexp 1) - (forward-line 1) - (if (>= (point) pos) - (if (progn (perl-beginning-of-function 2) (not (bobp))) - (progn - (forward-list 1) - (skip-chars-forward " \t") - (if (looking-at "[#\n]") - (forward-line 1))) - (goto-char (point-min))))) - (setq arg (1+ arg))))) - -(defun mark-perl-function () - "Put mark at end of Perl function, point at beginning." - (interactive) - (push-mark (point)) - (perl-end-of-function) - (push-mark (point)) - (perl-beginning-of-function) - (backward-paragraph)) - -;;;;;;;; That's all, folks! ;;;;;;;;; diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el deleted file mode 100644 index 52b65113073..00000000000 --- a/lisp/progmodes/prolog.el +++ /dev/null @@ -1,271 +0,0 @@ -;;; prolog.el --- major mode for editing and running Prolog under Emacs - -;; Copyright (C) 1986, 1987 Free Software Foundation, Inc. - -;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet> -;; Keywords: languages - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; This package provides a major mode for editing Prolog. It knows -;; about Prolog syntax and comments, and can send regions to an inferior -;; Prolog interpreter process. - -;;; Code: - -(defvar prolog-mode-syntax-table nil) -(defvar prolog-mode-abbrev-table nil) -(defvar prolog-mode-map nil) - -(defvar prolog-program-name "prolog" - "*Program name for invoking an inferior Prolog with `run-prolog'.") - -(defvar prolog-consult-string "reconsult(user).\n" - "*(Re)Consult mode (for C-Prolog and Quintus Prolog). ") - -(defvar prolog-compile-string "compile(user).\n" - "*Compile mode (for Quintus Prolog).") - -(defvar prolog-eof-string "end_of_file.\n" - "*String that represents end of file for prolog. -nil means send actual operating system end of file.") - -(defvar prolog-indent-width 4) - -(if prolog-mode-syntax-table - () - (let ((table (make-syntax-table))) - (modify-syntax-entry ?_ "w" table) - (modify-syntax-entry ?\\ "\\" table) - (modify-syntax-entry ?/ "." table) - (modify-syntax-entry ?* "." table) - (modify-syntax-entry ?+ "." table) - (modify-syntax-entry ?- "." table) - (modify-syntax-entry ?= "." table) - (modify-syntax-entry ?% "<" table) - (modify-syntax-entry ?< "." table) - (modify-syntax-entry ?> "." table) - (modify-syntax-entry ?\' "\"" table) - (setq prolog-mode-syntax-table table))) - -(define-abbrev-table 'prolog-mode-abbrev-table ()) - -(defun prolog-mode-variables () - (set-syntax-table prolog-mode-syntax-table) - (setq local-abbrev-table prolog-mode-abbrev-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^%%\\|^$\\|" page-delimiter)) ;'%%..' - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'prolog-indent-line) - (make-local-variable 'comment-start) - (setq comment-start "%") - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "%+ *") - (make-local-variable 'comment-column) - (setq comment-column 48) - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'prolog-comment-indent)) - -(defun prolog-mode-commands (map) - (define-key map "\t" 'prolog-indent-line) - (define-key map "\e\C-x" 'prolog-consult-region)) - -(if prolog-mode-map - nil - (setq prolog-mode-map (make-sparse-keymap)) - (prolog-mode-commands prolog-mode-map)) - -;;;###autoload -(defun prolog-mode () - "Major mode for editing Prolog code for Prologs. -Blank lines and `%%...' separate paragraphs. `%'s start comments. -Commands: -\\{prolog-mode-map} -Entry to this mode calls the value of `prolog-mode-hook' -if that value is non-nil." - (interactive) - (kill-all-local-variables) - (use-local-map prolog-mode-map) - (setq major-mode 'prolog-mode) - (setq mode-name "Prolog") - (prolog-mode-variables) - (run-hooks 'prolog-mode-hook)) - -(defun prolog-indent-line (&optional whole-exp) - "Indent current line as Prolog code. -With argument, indent any additional lines of the same clause -rigidly along with this one (not yet)." - (interactive "p") - (let ((indent (prolog-indent-level)) - (pos (- (point-max) (point))) beg) - (beginning-of-line) - (setq beg (point)) - (skip-chars-forward " \t") - (if (zerop (- indent (current-column))) - nil - (delete-region beg (point)) - (indent-to indent)) - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - )) - -(defun prolog-indent-level () - "Compute prolog indentation level." - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (cond - ((looking-at "%%%") 0) ;Large comment starts - ((looking-at "%[^%]") comment-column) ;Small comment starts - ((bobp) 0) ;Beginning of buffer - (t - (let ((empty t) ind more less) - (if (looking-at ")") - (setq less t) ;Find close - (setq less nil)) - ;; See previous indentation - (while empty - (forward-line -1) - (beginning-of-line) - (if (bobp) - (setq empty nil) - (skip-chars-forward " \t") - (if (not (or (looking-at "%[^%]") (looking-at "\n"))) - (setq empty nil)))) - (if (bobp) - (setq ind 0) ;Beginning of buffer - (setq ind (current-column))) ;Beginning of clause - ;; See its beginning - (if (looking-at "%%[^%]") - ind - ;; Real prolog code - (if (looking-at "(") - (setq more t) ;Find open - (setq more nil)) - ;; See its tail - (end-of-prolog-clause) - (or (bobp) (forward-char -1)) - (cond ((looking-at "[,(;>]") - (if (and more (looking-at "[^,]")) - (+ ind prolog-indent-width) ;More indentation - (max tab-width ind))) ;Same indentation - ((looking-at "-") tab-width) ;TAB - ((or less (looking-at "[^.]")) - (max (- ind prolog-indent-width) 0)) ;Less indentation - (t 0)) ;No indentation - ))) - ))) - -(defun end-of-prolog-clause () - "Go to end of clause in this line." - (beginning-of-line 1) - (let* ((eolpos (save-excursion (end-of-line) (point)))) - (if (re-search-forward comment-start-skip eolpos 'move) - (goto-char (match-beginning 0))) - (skip-chars-backward " \t"))) - -(defun prolog-comment-indent () - "Compute prolog comment indentation." - (cond ((looking-at "%%%") 0) - ((looking-at "%%") (prolog-indent-level)) - (t - (save-excursion - (skip-chars-backward " \t") - ;; Insert one space at least, except at left margin. - (max (+ (current-column) (if (bolp) 0 1)) - comment-column))) - )) - - -;;; -;;; Inferior prolog mode -;;; -(defvar inferior-prolog-mode-map nil) - -(defun inferior-prolog-mode () - "Major mode for interacting with an inferior Prolog process. - -The following commands are available: -\\{inferior-prolog-mode-map} - -Entry to this mode calls the value of `prolog-mode-hook' with no arguments, -if that value is non-nil. Likewise with the value of `comint-mode-hook'. -`prolog-mode-hook' is called after `comint-mode-hook'. - -You can send text to the inferior Prolog from other buffers -using the commands `send-region', `send-string' and \\[prolog-consult-region]. - -Commands: -Tab indents for Prolog; with argument, shifts rest - of expression rigidly with the current line. -Paragraphs are separated only by blank lines and '%%'. -'%'s start comments. - -Return at end of buffer sends line as input. -Return not at end copies rest of line to end and sends it. -\\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing. -\\[comint-interrupt-subjob] interrupts the shell or its current subjob if any. -\\[comint-stop-subjob] stops. \\[comint-quit-subjob] sends quit signal." - (interactive) - (require 'comint) - (comint-mode) - (setq major-mode 'inferior-prolog-mode - mode-name "Inferior Prolog" - comint-prompt-regexp "^| [ ?][- ] *") - (prolog-mode-variables) - (if inferior-prolog-mode-map nil - (setq inferior-prolog-mode-map (copy-keymap comint-mode-map)) - (prolog-mode-commands inferior-prolog-mode-map)) - (use-local-map inferior-prolog-mode-map) - (run-hooks 'prolog-mode-hook)) - -;;;###autoload -(defun run-prolog () - "Run an inferior Prolog process, input and output via buffer *prolog*." - (interactive) - (require 'comint) - (switch-to-buffer (make-comint "prolog" prolog-program-name)) - (inferior-prolog-mode)) - -(defun prolog-consult-region (compile beg end) - "Send the region to the Prolog process made by \"M-x run-prolog\". -If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode." - (interactive "P\nr") - (save-excursion - (if compile - (send-string "prolog" prolog-compile-string) - (send-string "prolog" prolog-consult-string)) - (send-region "prolog" beg end) - (send-string "prolog" "\n") ;May be unnecessary - (if prolog-eof-string - (send-string "prolog" prolog-eof-string) - (process-send-eof "prolog")))) ;Send eof to prolog process. - -(defun prolog-consult-region-and-go (compile beg end) - "Send the region to the inferior Prolog, and switch to *prolog* buffer. -If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode." - (interactive "P\nr") - (prolog-consult-region compile beg end) - (switch-to-buffer "*prolog*")) - -;;; prolog.el ends here diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el deleted file mode 100644 index caf74e3b3b9..00000000000 --- a/lisp/progmodes/scheme.el +++ /dev/null @@ -1,507 +0,0 @@ -;;; scheme.el --- Scheme mode, and its idiosyncratic commands. - -;; Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. - -;; Author: Bill Rozas <jinz@prep.ai.mit.edu> -;; Keywords: languages, lisp - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; Adapted from Lisp mode by Bill Rozas, jinx@prep. -;; Initially a query replace of Lisp mode, except for the indentation -;; of special forms. Probably the code should be merged at some point -;; so that there is sharing between both libraries. - -;;; Code: - -(defvar scheme-mode-syntax-table nil "") -(if (not scheme-mode-syntax-table) - (let ((i 0)) - (setq scheme-mode-syntax-table (make-syntax-table)) - (set-syntax-table scheme-mode-syntax-table) - - ;; Default is atom-constituent. - (while (< i 256) - (modify-syntax-entry i "_ ") - (setq i (1+ i))) - - ;; Word components. - (setq i ?0) - (while (<= i ?9) - (modify-syntax-entry i "w ") - (setq i (1+ i))) - (setq i ?A) - (while (<= i ?Z) - (modify-syntax-entry i "w ") - (setq i (1+ i))) - (setq i ?a) - (while (<= i ?z) - (modify-syntax-entry i "w ") - (setq i (1+ i))) - - ;; Whitespace - (modify-syntax-entry ?\t " ") - (modify-syntax-entry ?\n "> ") - (modify-syntax-entry ?\f " ") - (modify-syntax-entry ?\r " ") - (modify-syntax-entry ? " ") - - ;; These characters are delimiters but otherwise undefined. - ;; Brackets and braces balance for editing convenience. - (modify-syntax-entry ?[ "(] ") - (modify-syntax-entry ?] ")[ ") - (modify-syntax-entry ?{ "(} ") - (modify-syntax-entry ?} "){ ") - (modify-syntax-entry ?\| " 23") - - ;; Other atom delimiters - (modify-syntax-entry ?\( "() ") - (modify-syntax-entry ?\) ")( ") - (modify-syntax-entry ?\; "< ") - (modify-syntax-entry ?\" "\" ") - (modify-syntax-entry ?' " p") - (modify-syntax-entry ?` " p") - - ;; Special characters - (modify-syntax-entry ?, "_ p") - (modify-syntax-entry ?@ "_ p") - (modify-syntax-entry ?# "_ p14") - (modify-syntax-entry ?\\ "\\ "))) - -(defvar scheme-mode-abbrev-table nil "") -(define-abbrev-table 'scheme-mode-abbrev-table ()) - -(defun scheme-mode-variables () - (set-syntax-table scheme-mode-syntax-table) - (setq local-abbrev-table scheme-mode-abbrev-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'scheme-indent-line) - (make-local-variable 'comment-start) - (setq comment-start ";") - (make-local-variable 'comment-start-skip) - (setq comment-start-skip ";+[ \t]*") - (make-local-variable 'comment-column) - (setq comment-column 40) - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'scheme-comment-indent) - (setq mode-line-process '("" scheme-mode-line-process))) - -(defvar scheme-mode-line-process "") - -(defun scheme-mode-commands (map) - (define-key map "\t" 'scheme-indent-line) - (define-key map "\177" 'backward-delete-char-untabify) - (define-key map "\e\C-q" 'scheme-indent-sexp)) - -(defvar scheme-mode-map nil) -(if (not scheme-mode-map) - (progn - (setq scheme-mode-map (make-sparse-keymap)) - (scheme-mode-commands scheme-mode-map))) - -;;;###autoload -(defun scheme-mode () - "Major mode for editing Scheme code. -Editing commands are similar to those of lisp-mode. - -In addition, if an inferior Scheme process is running, some additional -commands will be defined, for evaluating expressions and controlling -the interpreter, and the state of the process will be displayed in the -modeline of all Scheme buffers. The names of commands that interact -with the Scheme process start with \"xscheme-\". For more information -see the documentation for xscheme-interaction-mode. - -Commands: -Delete converts tabs to spaces as it moves back. -Blank lines separate paragraphs. Semicolons start comments. -\\{scheme-mode-map} -Entry to this mode calls the value of scheme-mode-hook -if that value is non-nil." - (interactive) - (kill-all-local-variables) - (scheme-mode-initialize) - (scheme-mode-variables) - (run-hooks 'scheme-mode-hook)) - -(defun scheme-mode-initialize () - (use-local-map scheme-mode-map) - (setq major-mode 'scheme-mode) - (setq mode-name "Scheme")) - -(defvar scheme-mit-dialect t - "If non-nil, scheme mode is specialized for MIT Scheme. -Set this to nil if you normally use another dialect.") - -(defun scheme-comment-indent (&optional pos) - (save-excursion - (if pos (goto-char pos)) - (cond ((looking-at ";;;") (current-column)) - ((looking-at ";;") - (let ((tem (calculate-scheme-indent))) - (if (listp tem) (car tem) tem))) - (t - (skip-chars-backward " \t") - (max (if (bolp) 0 (1+ (current-column))) - comment-column))))) - -(defvar scheme-indent-offset nil "") -(defvar scheme-indent-function 'scheme-indent-function "") - -(defun scheme-indent-line (&optional whole-exp) - "Indent current line as Scheme code. -With argument, indent any additional lines of the same expression -rigidly along with this one." - (interactive "P") - (let ((indent (calculate-scheme-indent)) shift-amt beg end - (pos (- (point-max) (point)))) - (beginning-of-line) - (setq beg (point)) - (skip-chars-forward " \t") - (if (looking-at "[ \t]*;;;") - ;; Don't alter indentation of a ;;; comment line. - nil - (if (listp indent) (setq indent (car indent))) - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - nil - (delete-region beg (point)) - (indent-to indent)) - ;; If initial point was within line's indentation, - ;; position after the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - ;; If desired, shift remaining lines of expression the same amount. - (and whole-exp (not (zerop shift-amt)) - (save-excursion - (goto-char beg) - (forward-sexp 1) - (setq end (point)) - (goto-char beg) - (forward-line 1) - (setq beg (point)) - (> end beg)) - (indent-code-rigidly beg end shift-amt))))) - -(defun calculate-scheme-indent (&optional parse-start) - "Return appropriate indentation for current line as scheme code. -In usual case returns an integer: the column to indent to. -Can instead return a list, whose car is the column to indent to. -This means that following lines at the same level of indentation -should not necessarily be indented the same way. -The second element of the list is the buffer position -of the start of the containing expression." - (save-excursion - (beginning-of-line) - (let ((indent-point (point)) state paren-depth desired-indent (retry t) - last-sexp containing-sexp first-sexp-list-p) - (if parse-start - (goto-char parse-start) - (beginning-of-defun)) - ;; Find outermost containing sexp - (while (< (point) indent-point) - (setq state (parse-partial-sexp (point) indent-point 0))) - ;; Find innermost containing sexp - (while (and retry (setq paren-depth (car state)) (> paren-depth 0)) - (setq retry nil) - (setq last-sexp (nth 2 state)) - (setq containing-sexp (car (cdr state))) - ;; Position following last unclosed open. - (goto-char (1+ containing-sexp)) - ;; Is there a complete sexp since then? - (if (and last-sexp (> last-sexp (point))) - ;; Yes, but is there a containing sexp after that? - (let ((peek (parse-partial-sexp last-sexp indent-point 0))) - (if (setq retry (car (cdr peek))) (setq state peek)))) - (if (not retry) - ;; Innermost containing sexp found - (progn - (goto-char (1+ containing-sexp)) - (if (not last-sexp) - ;; indent-point immediately follows open paren. - ;; Don't call hook. - (setq desired-indent (current-column)) - ;; Move to first sexp after containing open paren - (parse-partial-sexp (point) last-sexp 0 t) - (setq first-sexp-list-p (looking-at "\\s(")) - (cond - ((> (save-excursion (forward-line 1) (point)) - last-sexp) - ;; Last sexp is on same line as containing sexp. - ;; It's almost certainly a function call. - (parse-partial-sexp (point) last-sexp 0 t) - (if (/= (point) last-sexp) - ;; Indent beneath first argument or, if only one sexp - ;; on line, indent beneath that. - (progn (forward-sexp 1) - (parse-partial-sexp (point) last-sexp 0 t))) - (backward-prefix-chars)) - (t - ;; Indent beneath first sexp on same line as last-sexp. - ;; Again, it's almost certainly a function call. - (goto-char last-sexp) - (beginning-of-line) - (parse-partial-sexp (point) last-sexp 0 t) - (backward-prefix-chars))))))) - ;; If looking at a list, don't call hook. - (if first-sexp-list-p - (setq desired-indent (current-column))) - ;; Point is at the point to indent under unless we are inside a string. - ;; Call indentation hook except when overridden by scheme-indent-offset - ;; or if the desired indentation has already been computed. - (cond ((car (nthcdr 3 state)) - ;; Inside a string, don't change indentation. - (goto-char indent-point) - (skip-chars-forward " \t") - (setq desired-indent (current-column))) - ((and (integerp scheme-indent-offset) containing-sexp) - ;; Indent by constant offset - (goto-char containing-sexp) - (setq desired-indent (+ scheme-indent-offset (current-column)))) - ((not (or desired-indent - (and (boundp 'scheme-indent-function) - scheme-indent-function - (not retry) - (setq desired-indent - (funcall scheme-indent-function - indent-point state))))) - ;; Use default indentation if not computed yet - (setq desired-indent (current-column)))) - desired-indent))) - -(defun scheme-indent-function (indent-point state) - (let ((normal-indent (current-column))) - (save-excursion - (goto-char (1+ (car (cdr state)))) - (re-search-forward "\\sw\\|\\s_") - (if (/= (point) (car (cdr state))) - (let ((function (buffer-substring (progn (forward-char -1) (point)) - (progn (forward-sexp 1) (point)))) - method) - ;; Who cares about this, really? - ;(if (not (string-match "\\\\\\||" function))) - (setq function (downcase function)) - (setq method (get (intern-soft function) 'scheme-indent-function)) - (cond ((integerp method) - (scheme-indent-specform method state indent-point)) - (method - (funcall method state indent-point)) - ((and (> (length function) 3) - (string-equal (substring function 0 3) "def")) - (scheme-indent-defform state indent-point)))))))) - -(defvar scheme-body-indent 2 "") - -(defun scheme-indent-specform (count state indent-point) - (let ((containing-form-start (car (cdr state))) (i count) - body-indent containing-form-column) - ;; Move to the start of containing form, calculate indentation - ;; to use for non-distinguished forms (> count), and move past the - ;; function symbol. scheme-indent-function guarantees that there is at - ;; least one word or symbol character following open paren of containing - ;; form. - (goto-char containing-form-start) - (setq containing-form-column (current-column)) - (setq body-indent (+ scheme-body-indent containing-form-column)) - (forward-char 1) - (forward-sexp 1) - ;; Now find the start of the last form. - (parse-partial-sexp (point) indent-point 1 t) - (while (and (< (point) indent-point) - (condition-case nil - (progn - (setq count (1- count)) - (forward-sexp 1) - (parse-partial-sexp (point) indent-point 1 t)) - (error nil)))) - ;; Point is sitting on first character of last (or count) sexp. - (cond ((> count 0) - ;; A distinguished form. Use double scheme-body-indent. - (list (+ containing-form-column (* 2 scheme-body-indent)) - containing-form-start)) - ;; A non-distinguished form. Use body-indent if there are no - ;; distinguished forms and this is the first undistinguished - ;; form, or if this is the first undistinguished form and - ;; the preceding distinguished form has indentation at least - ;; as great as body-indent. - ((and (= count 0) - (or (= i 0) - (<= body-indent normal-indent))) - body-indent) - (t - normal-indent)))) - -(defun scheme-indent-defform (state indent-point) - (goto-char (car (cdr state))) - (forward-line 1) - (if (> (point) (car (cdr (cdr state)))) - (progn - (goto-char (car (cdr state))) - (+ scheme-body-indent (current-column))))) - -;;; Let is different in Scheme - -(defun would-be-symbol (string) - (not (string-equal (substring string 0 1) "("))) - -(defun next-sexp-as-string () - ;; Assumes that protected by a save-excursion - (forward-sexp 1) - (let ((the-end (point))) - (backward-sexp 1) - (buffer-substring (point) the-end))) - -;; This is correct but too slow. -;; The one below works almost always. -;;(defun scheme-let-indent (state indent-point) -;; (if (would-be-symbol (next-sexp-as-string)) -;; (scheme-indent-specform 2 state indent-point) -;; (scheme-indent-specform 1 state indent-point))) - -(defun scheme-let-indent (state indent-point) - (skip-chars-forward " \t") - (if (looking-at "[-a-zA-Z0-9+*/?!@$%^&_:~]") - (scheme-indent-specform 2 state indent-point) - (scheme-indent-specform 1 state indent-point))) - -;; (put 'begin 'scheme-indent-function 0), say, causes begin to be indented -;; like defun if the first form is placed on the next line, otherwise -;; it is indented like any other form (i.e. forms line up under first). - -(put 'begin 'scheme-indent-function 0) -(put 'case 'scheme-indent-function 1) -(put 'delay 'scheme-indent-function 0) -(put 'do 'scheme-indent-function 2) -(put 'lambda 'scheme-indent-function 1) -(put 'let 'scheme-indent-function 'scheme-let-indent) -(put 'let* 'scheme-indent-function 1) -(put 'letrec 'scheme-indent-function 1) -(put 'sequence 'scheme-indent-function 0) - -(put 'call-with-input-file 'scheme-indent-function 1) -(put 'with-input-from-file 'scheme-indent-function 1) -(put 'with-input-from-port 'scheme-indent-function 1) -(put 'call-with-output-file 'scheme-indent-function 1) -(put 'with-output-to-file 'scheme-indent-function 1) -(put 'with-output-to-port 'scheme-indent-function 1) - -;;;; MIT Scheme specific indentation. - -(if scheme-mit-dialect - (progn - (put 'fluid-let 'scheme-indent-function 1) - (put 'in-package 'scheme-indent-function 1) - (put 'let-syntax 'scheme-indent-function 1) - (put 'local-declare 'scheme-indent-function 1) - (put 'macro 'scheme-indent-function 1) - (put 'make-environment 'scheme-indent-function 0) - (put 'named-lambda 'scheme-indent-function 1) - (put 'using-syntax 'scheme-indent-function 1) - - (put 'with-input-from-string 'scheme-indent-function 1) - (put 'with-output-to-string 'scheme-indent-function 0) - (put 'with-values 'scheme-indent-function 1) - - (put 'syntax-table-define 'scheme-indent-function 2) - (put 'list-transform-positive 'scheme-indent-function 1) - (put 'list-transform-negative 'scheme-indent-function 1) - (put 'list-search-positive 'scheme-indent-function 1) - (put 'list-search-negative 'scheme-indent-function 1) - - (put 'access-components 'scheme-indent-function 1) - (put 'assignment-components 'scheme-indent-function 1) - (put 'combination-components 'scheme-indent-function 1) - (put 'comment-components 'scheme-indent-function 1) - (put 'conditional-components 'scheme-indent-function 1) - (put 'disjunction-components 'scheme-indent-function 1) - (put 'declaration-components 'scheme-indent-function 1) - (put 'definition-components 'scheme-indent-function 1) - (put 'delay-components 'scheme-indent-function 1) - (put 'in-package-components 'scheme-indent-function 1) - (put 'lambda-components 'scheme-indent-function 1) - (put 'lambda-components* 'scheme-indent-function 1) - (put 'lambda-components** 'scheme-indent-function 1) - (put 'open-block-components 'scheme-indent-function 1) - (put 'pathname-components 'scheme-indent-function 1) - (put 'procedure-components 'scheme-indent-function 1) - (put 'sequence-components 'scheme-indent-function 1) - (put 'unassigned\?-components 'scheme-indent-function 1) - (put 'unbound\?-components 'scheme-indent-function 1) - (put 'variable-components 'scheme-indent-function 1))) - -(defun scheme-indent-sexp () - "Indent each line of the list starting just after point." - (interactive) - (let ((indent-stack (list nil)) (next-depth 0) bol - outer-loop-done inner-loop-done state this-indent) - (save-excursion (forward-sexp 1)) - (save-excursion - (setq outer-loop-done nil) - (while (not outer-loop-done) - (setq last-depth next-depth - innerloop-done nil) - (while (and (not innerloop-done) - (not (setq outer-loop-done (eobp)))) - (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) - nil nil state)) - (setq next-depth (car state)) - (if (car (nthcdr 4 state)) - (progn (indent-for-comment) - (end-of-line) - (setcar (nthcdr 4 state) nil))) - (if (car (nthcdr 3 state)) - (progn - (forward-line 1) - (setcar (nthcdr 5 state) nil)) - (setq innerloop-done t))) - (if (setq outer-loop-done (<= next-depth 0)) - nil - (while (> last-depth next-depth) - (setq indent-stack (cdr indent-stack) - last-depth (1- last-depth))) - (while (< last-depth next-depth) - (setq indent-stack (cons nil indent-stack) - last-depth (1+ last-depth))) - (forward-line 1) - (setq bol (point)) - (skip-chars-forward " \t") - (if (or (eobp) (looking-at "[;\n]")) - nil - (if (and (car indent-stack) - (>= (car indent-stack) 0)) - (setq this-indent (car indent-stack)) - (let ((val (calculate-scheme-indent - (if (car indent-stack) (- (car indent-stack)))))) - (if (integerp val) - (setcar indent-stack - (setq this-indent val)) - (setcar indent-stack (- (car (cdr val)))) - (setq this-indent (car val))))) - (if (/= (current-column) this-indent) - (progn (delete-region bol (point)) - (indent-to this-indent))))))))) - -(provide 'scheme) - -;;; scheme.el ends here diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el deleted file mode 100644 index b0fd04d4a13..00000000000 --- a/lisp/progmodes/sh-script.el +++ /dev/null @@ -1,895 +0,0 @@ -;;; sh-script.el --- shell-script editing commands for Emacs -;; Copyright (C) 1993 Free Software Foundation, Inc. - -;; Author: Daniel Pfeiffer, fax (+49 69) 75 88 529, c/o <bonhoure@cict.fr> -;; Maintainer: FSF -;; Keywords: shell programming - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; Major mode for editing shell scripts. Currently sh, ksh, bash and csh, -;; tcsh are supported. Structured statements can be inserted with one -;; command. - -;;; Code: - -;; page 1: variables and settings -;; page 2: mode-command and utility functions -;; page 3: statement syntax-commands for various shells -;; page 4: various other commands - - -;;;###autoload -(setq auto-mode-alist - ;; matches files - ;; - who's path contains /bin/, but not directories - (cons '("/bin/" . sh-or-other-mode) - ;; - that have a suffix .sh or .shar (shell archive) - ;; - that contain ressources for the various shells - ;; - startup files for X11 - (cons '("\\.sh$\\|\\.shar$\\|/\\.\\(profile\\|bash_profile\\|login\\|bash_login\\|logout\\|bash_logout\\|bashrc\\|t?cshrc\\|xinitrc\\|startxrc\\|xsession\\)$" . sh-mode) - auto-mode-alist))) - - -(defvar sh-mode-syntax-table - (let ((table (copy-syntax-table))) - (modify-syntax-entry ?\# "<" table) - (modify-syntax-entry ?\^l ">#" table) - (modify-syntax-entry ?\n ">#" table) - (modify-syntax-entry ?\" "\"\"" table) - (modify-syntax-entry ?\' "\"'" table) - (modify-syntax-entry ?\` "$`" table) - (modify-syntax-entry ?$ "_" table) - (modify-syntax-entry ?! "_" table) - (modify-syntax-entry ?% "_" table) - (modify-syntax-entry ?: "_" table) - (modify-syntax-entry ?. "_" table) - (modify-syntax-entry ?^ "_" table) - (modify-syntax-entry ?~ "_" table) - table) - "Syntax table in use in Shell-Script mode.") - - - -(defvar sh-use-prefix nil - "If non-nil when loading, `$' and `<' will be C-c $ and C-c < .") - -(defvar sh-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-c(" 'sh-function) - (define-key map "\C-c\C-w" 'sh-while) - (define-key map "\C-c\C-u" 'sh-until) - (define-key map "\C-c\C-s" 'sh-select) - (define-key map "\C-c\C-l" 'sh-indexed-loop) - (define-key map "\C-c\C-i" 'sh-if) - (define-key map "\C-c\C-f" 'sh-for) - (define-key map "\C-c\C-c" 'sh-case) - - (define-key map (if sh-use-prefix "\C-c$" "$") - 'sh-query-for-variable) - (define-key map "=" 'sh-assignment) - (define-key map "\C-c+" 'sh-add) - (define-key map (if sh-use-prefix "\C-c<" "<") - 'sh-maybe-here-document) - (define-key map "(" 'pair-insert-maybe) - (define-key map "{" 'pair-insert-maybe) - (define-key map "[" 'pair-insert-maybe) - (define-key map "'" 'pair-insert-maybe) - (define-key map "`" 'pair-insert-maybe) - (define-key map "\"" 'pair-insert-maybe) - - (define-key map "\t" 'sh-indent-line) - (substitute-key-definition 'complete-tag 'comint-dynamic-complete-filename - map (current-global-map)) - (substitute-key-definition 'newline-and-indent 'sh-newline-and-indent - map (current-global-map)) - ;; Now that tabs work properly, this might be unwanted. - (substitute-key-definition 'delete-backward-char - 'backward-delete-char-untabify - map (current-global-map)) - (define-key map "\C-c:" 'sh-set-shell) - (substitute-key-definition 'beginning-of-defun - 'sh-beginning-of-compound-command - map (current-global-map)) - (substitute-key-definition 'backward-sentence 'sh-beginning-of-command - map (current-global-map)) - (substitute-key-definition 'forward-sentence 'sh-end-of-command - map (current-global-map)) - (substitute-key-definition 'manual-entry 'sh-manual-entry - map (current-global-map)) - (define-key map [menu-bar insert] - (cons "Insert" (make-sparse-keymap "Insert"))) - (define-key map [menu-bar insert sh-while] - '("While loop" . sh-while)) - (define-key map [menu-bar insert sh-until] - '("Until loop" . sh-until)) - (define-key map [menu-bar insert sh-select] - '("Select statement" . sh-select)) - (define-key map [menu-bar insert sh-indexed-loop] - '("Indexed loop" . sh-indexed-loop)) - (define-key map [menu-bar insert sh-if] - '("If statement" . sh-if)) - (define-key map [menu-bar insert sh-for] - '("For loop" . sh-for)) - (define-key map [menu-bar insert sh-case] - '("Case statement" . sh-case)) - map) - "Keymap used in Shell-Script mode.") - - - -(defvar sh-find-file-modifies t - "*What to do when newly found file has no magic number: - nil do nothing - t insert magic number - other insert magic number, but mark as unmodified.") - - -(defvar sh-query-for-magic t - "*If non-nil, ask user before changing or inserting magic number.") - - -(defvar sh-magicless-file-regexp "/\\.[^/]+$" - "*On files with this kind of name no magic is inserted or changed.") - - -;; someone who understands /etc/magic better than me should beef this up -;; this currently covers only SCO Unix and Sinix executables -;; the elegant way would be to read /etc/magic -(defvar magic-number-alist '(("L\^a\^h\\|\^?ELF" . hexl-mode) - ("#!.*perl" . perl-mode)) - "A regexp to match the magic number of a found file. -Currently this is only used by function `sh-or-other-mode'.") - - -(defvar sh-executable ".* is \\([^ \t]*\\)\n" - "*Regexp to match the output of sh builtin `type' command on your machine. -The regexp must match the whole output, and must contain a \\(something\\) -construct which matches the actual executable.") - - - -(defvar sh-chmod-argument "755" - "*After saving, if the file is not executable, set this mode. -The mode can be absolute \"511\" or relative \"u+x\". Do nothing if this is nil.") - - -(defvar sh-shell-path (or (getenv "SHELL") "/bin/sh") - "*The executable of the shell being programmed.") - -(defvar sh-shell-argument nil - "*A single argument for the magic number, or nil.") - -(defvar sh-shell nil - "The shell being programmed. This is set by \\[sh-set-shell].") - -(defvar sh-shell-is-csh nil - "The shell being programmed. This is set by \\[sh-set-shell].") - -(defvar sh-tab-width 4 - "The default value for `tab-width' in Shell-Script mode. -This is the width of tab stops after the indentation of the preceeding line.") - -(defvar sh-remember-variable-min 3 - "*Don't remember variables less than this length for completing reads.") - - -(defvar sh-beginning-of-command - "\\([;({`|&]\\|^\\)[ \t]*\\([/~:a-zA-Z0-9]\\)" - "*Regexp to determine the beginning of a shell command. -The actual command starts at the beginning of the second \\(grouping\\).") - -(defvar sh-end-of-command - "\\([/~:a-zA-Z0-9]\\)[ \t]*\\([;#)}`|&]\\|$\\)" - "*Regexp to determine the end of a shell command. -The actual command ends at the end of the first \\(grouping\\).") - - - -(defvar sh-assignment-space '(csh tcsh) - "List of shells that allow spaces around the assignment =.") - -(defvar sh-here-document-word "+" - "Word to delimit here documents.") - - -;process-environment -(defvar sh-variables - '(("addsuffix" tcsh) ("allow_null_glob_expansion" bash) - ("ampm" tcsh) ("argv" csh tcsh) - ("autocorrect" tcsh) ("autoexpand" tcsh) - ("autolist" tcsh) ("autologout" tcsh) - ("auto_resume" bash) ("BASH" bash) - ("BASH_VERSION" bash) ("cdable_vars" bash) - ("cdpath" csh tcsh) ("CDPATH" sh ksh bash) - ("chase_symlinks" tcsh) ("child" csh tcsh) - ("COLUMNS" ksh tcsh) ("correct" tcsh) - ("dextract" tcsh) ("echo" csh tcsh) - ("edit" tcsh) ("EDITOR") - ("el" tcsh) ("ENV" ksh bash) - ("ERRNO" ksh) ("EUID" bash) - ("FCEDIT" ksh bash) ("FIGNORE" bash) - ("fignore" tcsh) ("FPATH" ksh) - ("gid" tcsh) ("glob_dot_filenames" bash) - ("histchars" bash csh tcsh) ("HISTFILE" ksh bash) - ("HISTFILESIZE" bash) ("histlit" tcsh) - ("history" csh tcsh) ("history_control" bash) - ("HISTSIZE" bash) ("home" csh tcsh) - ("HOME") ("HOST" tcsh) - ("hostname_completion_file" bash) ("HOSTTYPE" bash tcsh) - ("HPATH" tcsh) ("HUSHLOGIN") - ("IFS" sh ksh bash) ("ignoreeof" bash csh tcsh) - ("IGNOREEOF" bash) ("ignore_symlinks" tcsh) - ("LANG") ("LC_COLLATE") - ("LC_CTYPE") ("LC_MESSAGES") - ("LC_MONETARY") ("LC_NUMERIC") - ("LC_TIME") ("LINENO" ksh bash) - ("LINES" ksh tcsh) ("listjobs" tcsh) - ("listlinks" tcsh) ("listmax" tcsh) - ("LOGNAME") ("mail" csh tcsh) - ("MAIL") ("MAILCHECK") - ("MAILPATH") ("MAIL_WARNING" bash) - ("matchbeep" tcsh) ("nobeep" tcsh) - ("noclobber" bash csh tcsh) ("noglob" csh tcsh) - ("nolinks" bash) ("nonomatch" csh tcsh) - ("NOREBIND" tcsh) ("notify" bash) - ("no_exit_on_failed_exec" bash) ("NO_PROMPT_VARS" bash) - ("oid" tcsh) ("OLDPWD" ksh bash) - ("OPTARG" sh ksh bash) ("OPTERR" bash) - ("OPTIND" sh ksh bash) ("PAGER") - ("path" csh tcsh) ("PATH") - ("PPID" ksh bash) ("printexitvalue" tcsh) - ("prompt" csh tcsh) ("prompt2" tcsh) - ("prompt3" tcsh) ("PROMPT_COMMAND" bash) - ("PS1" sh ksh bash) ("PS2" sh ksh bash) - ("PS3" ksh) ("PS4" ksh bash) - ("pushdsilent" tcsh) ("pushdtohome" tcsh) - ("pushd_silent" bash) ("PWD" ksh bash) - ("RANDOM" ksh bash) ("recexact" tcsh) - ("recognize_only_executables" tcsh) ("REPLY" ksh bash) - ("rmstar" tcsh) ("savehist" tcsh) - ("SECONDS" ksh bash) ("shell" csh tcsh) - ("SHELL") ("SHLVL" bash tcsh) - ("showdots" tcsh) ("sl" tcsh) - ("status" csh tcsh) ("SYSTYPE" tcsh) - ("tcsh" tcsh) ("term" tcsh) - ("TERM") ("TERMCAP") - ("time" csh tcsh) ("TMOUT" ksh bash) - ("tperiod" tcsh) ("tty" tcsh) - ("UID" bash) ("uid" tcsh) - ("verbose" csh tcsh) ("version" tcsh) - ("visiblebell" tcsh) ("VISUAL") - ("watch" tcsh) ("who" tcsh) - ("wordchars" tcsh)) - "Alist of all environment and shell variables used for completing read. -Variables only understood by some shells are associated to a list of those.") - - - -(defvar sh-font-lock-keywords - '(("[ \t]\\(#.*\\)" 1 font-lock-comment-face) - ("\"[^`]*\"\\|'.*'\\|\\\\[^\nntc]" . font-lock-string-face)) - "*Rules for highlighting shell scripts. -This variable is included into the various variables -`sh-SHELL-font-lock-keywords'. If no such variable exists for some shell, -this one is used.") - - -(defvar sh-sh-font-lock-keywords - (append sh-font-lock-keywords - '(("\\(^\\|[^-._a-z0-9]\\)\\(case\\|do\\|done\\|elif\\|else\\|esac\\|fi\\|for\\|if\\|in\\|then\\|until\\|while\\)\\($\\|[^-._a-z0-9]\\)" 2 font-lock-keyword-face t))) - "*Rules for highlighting Bourne shell scripts.") - -(defvar sh-ksh-font-lock-keywords - (append sh-sh-font-lock-keywords - '(("\\(^\\|[^-._a-z0-9]\\)\\(function\\|select\\)\\($\\|[^-._a-z0-9]\\)" 2 font-lock-keyword-face t))) - "*Rules for highlighting Korn shell scripts.") - -(defvar sh-bash-font-lock-keywords - (append sh-sh-font-lock-keywords - '(("\\(^\\|[^-._a-z0-9]\\)\\(function\\)\\($\\|[^-._a-z0-9]\\)" 2 font-lock-keyword-face t))) - "*Rules for highlighting Bourne again shell scripts.") - - -(defvar sh-csh-font-lock-keywords - (append sh-font-lock-keywords - '(("\\(^\\|[^-._a-z0-9]\\)\\(breaksw\\|case\\|default\\|else\\|end\\|endif\\|foreach\\|if\\|switch\\|then\\|while\\)\\($\\|[^-._a-z0-9]\\)" 2 font-lock-keyword-face t))) - "*Rules for highlighting C shell scripts.") - -(defvar sh-tcsh-font-lock-keywords sh-csh-font-lock-keywords - "*Rules for highlighting Toronto C shell scripts.") - - - -;; mode-command and utility functions - -;;;###autoload -(defun sh-or-other-mode () - "Decide whether this is a compiled executable or a script. -Usually the file-names of scripts and binaries cannot be automatically -distinguished, so the presence of an executable's magic number is used." - (funcall (or (let ((l magic-number-alist)) - (while (and l - (not (looking-at (car (car l))))) - (setq l (cdr l))) - (cdr (car l))) - 'sh-mode))) - - -;;;###autoload -(defun sh-mode () - "Major mode for editing shell scripts. -This mode works for many shells, since they all have roughly the same syntax, -as far as commands, arguments, variables, pipes, comments etc. are concerned. -Unless the file's magic number indicates the shell, your usual shell is -assumed. Since filenames rarely give a clue, they are not further analyzed. - -The syntax of the statements varies with the shell being used. The syntax of -statements can be modified by putting a property on the command or new ones -defined with `define-sh-skeleton'. For example - - (put 'sh-until 'ksh '(() \"until \" _ \\n > \"do\" \\n \"done\")) -or - (put 'sh-if 'smush '(\"What? \" \"If ya got ( \" str \" ) ya betta { \" _ \" }\")) - -where `sh-until' or `sh-if' have been or will be defined by `define-sh-skeleton'. - -The following commands are available, based on the current shell's syntax: - -\\[sh-case] case statement -\\[sh-for] for loop -\\[sh-function] function definition -\\[sh-if] if statement -\\[sh-indexed-loop] indexed loop from 1 to n -\\[sh-select] select statement -\\[sh-until] until loop -\\[sh-while] while loop - -\\[backward-delete-char-untabify] Delete backward one position, even if it was a tab. -\\[sh-newline-and-indent] Delete unquoted space and indent new line same as this one. -\\[sh-end-of-command] Go to end of successive commands. -\\[sh-beginning-of-command] Go to beginning of successive commands. -\\[sh-set-shell] Set this buffer's shell, and maybe its magic number. -\\[sh-manual-entry] Display the Unix manual entry for the current command or shell. - -\\[sh-query-for-variable] Unless quoted with \\, query for a variable with completions offered. -\\[sh-maybe-here-document] Without prefix, following an unquoted < inserts here document. -{, (, [, ', \", ` - Unless quoted with \\, insert the pairs {}, (), [], or '', \"\", ``." - (interactive) - (kill-all-local-variables) - (set-syntax-table sh-mode-syntax-table) - (use-local-map sh-mode-map) - (make-local-variable 'indent-line-function) - (make-local-variable 'comment-start) - (make-local-variable 'comment-start-skip) - (make-local-variable 'after-save-hook) - (make-local-variable 'require-final-newline) - (make-local-variable 'sh-shell-path) - (make-local-variable 'sh-shell) - (make-local-variable 'sh-shell-is-csh) - (make-local-variable 'pair-alist) - (make-local-variable 'pair-filter) - (make-local-variable 'font-lock-keywords) - (make-local-variable 'font-lock-keywords-case-fold-search) - (make-local-variable 'sh-variables) - (setq major-mode 'sh-mode - mode-name "Shell-script" - ;; Why can't Emacs have one standard function with some parameters? - ;; Only few modes actually analyse the previous line's contents - indent-line-function 'sh-indent-line - comment-start "# " - after-save-hook 'sh-chmod - tab-width sh-tab-width - ;; C shells do - require-final-newline t - font-lock-keywords-case-fold-search nil - pair-alist '((?` _ ?`)) - pair-filter 'sh-quoted-p) - ; parse or insert magic number for exec() - (goto-char (point-min)) - (sh-set-shell - (if (looking-at "#![\t ]*\\([^\t\n ]+\\)") - (buffer-substring (match-beginning 1) (match-end 1)) - sh-shell-path)) - ;; find-file is set by `normal-mode' when called by `after-find-file' - (and (boundp 'find-file) find-file - (or (eq sh-find-file-modifies t) - (set-buffer-modified-p nil))) - (run-hooks 'sh-mode-hook)) -;;;###autoload -(defalias 'shell-script-mode 'sh-mode) - - - -(defmacro define-sh-skeleton (command documentation &rest definitions) - "Define COMMAND with [DOCSTRING] to insert statements as in DEFINITION ... -Prior definitions (e.g. from ~/.emacs) are maintained. -Each definition is built up as (SHELL PROMPT ELEMENT ...). Alternately -a synonym definition can be (SHELL . PREVIOUSLY-DEFINED-SHELL). - -For the meaning of (PROMPT ELEMENT ...) see `skeleton-insert'. -Each DEFINITION is actually stored as - (put COMMAND SHELL (PROMPT ELEMENT ...)), -which you can also do yourself." - (or (stringp documentation) - (setq definitions (cons documentation definitions) - documentation "")) - ;; The compiled version doesn't. - (require 'backquote) - (`(progn - (let ((definitions '(, definitions))) - (while definitions - ;; skeleton need not be loaded to define these - (or (and (not (if (boundp 'skeleton-debug) skeleton-debug)) - (get '(, command) (car (car definitions)))) - (put '(, command) (car (car definitions)) - (if (symbolp (cdr (car definitions))) - (get '(, command) (cdr (car definitions))) - (cdr (car definitions))))) - (setq definitions (cdr definitions)))) - (put '(, command) 'menu-enable '(get '(, command) sh-shell)) - (defun (, command) () - (, documentation) - (interactive) - (skeleton-insert - (or (get '(, command) sh-shell) - (error "%s statement syntax not defined for shell %s." - '(, command) sh-shell))))))) - - - -(defun sh-indent-line () - "Indent as far as preceding line, then by steps of `tab-width'. -If previous line starts with a comment, it's considered empty." - (interactive) - (let ((previous (save-excursion - (line-move -1) - (back-to-indentation) - (if (looking-at comment-start-skip) - 0 - (current-column))))) - (save-excursion - (indent-to (if (eq this-command 'newline-and-indent) - previous - (if (< (current-column) - (progn (back-to-indentation) - (current-column))) - (if (eolp) previous 0) - (if (eolp) - (max previous (* (1+ (/ (current-column) tab-width)) - tab-width)) - (* (1+ (/ (current-column) tab-width)) tab-width)))))) - (if (< (current-column) (current-indentation)) - (skip-chars-forward " \t")))) - - -(defun sh-remember-variable (var) - "Make VARIABLE available for future completing reads in this buffer." - (or (< (length var) sh-remember-variable-min) - (assoc var sh-variables) - (setq sh-variables (cons (list var) sh-variables))) - var) - - -;; Augment the standard variables by those found in the environment. -(if (boundp 'process-environment)(let ((l process-environment)) - (while l - (sh-remember-variable (substring (car l) - 0 (string-match "=" (car l)))) - (setq l (cdr l))))) - - - -(defun sh-quoted-p () - "Is point preceded by an odd number of backslashes?" - (eq 1 (% (- (point) (save-excursion - (skip-chars-backward "\\\\") - (point))) - 2))) - - - -(defun sh-executable (command) - "If COMMAND is an executable in $PATH its full name is returned. Else nil." - (let ((point (point)) - (buffer-modified-p (buffer-modified-p)) - buffer-read-only after-change-function) - (call-process "sh" nil t nil "-c" (concat "type " command)) - (setq point (prog1 (point) - (goto-char point))) - (prog1 - (and (looking-at sh-executable) - (eq point (match-end 0)) - (buffer-substring (match-beginning 1) (match-end 1))) - (delete-region (point) point) - (set-buffer-modified-p buffer-modified-p)))) - - - -(defun sh-chmod () - "This gets called after saving a file to assure that it be executable. -You can set the absolute or relative mode with `sh-chmod-argument'." - (if sh-chmod-argument - (or (file-executable-p buffer-file-name) - (shell-command (concat "chmod " sh-chmod-argument - " " buffer-file-name))))) - -;; statement syntax-commands for various shells - -;; You are welcome to add the syntax or even completely new statements as -;; appropriate for your favorite shell. - -(define-sh-skeleton sh-case - "Insert a case/switch statement in the current shell's syntax." - (sh "expression: " - "case " str " in" \n - > (read-string "pattern: ") ?\) \n - > _ \n - ";;" \n - ( "other pattern, %s: " - < str ?\) \n - > \n - ";;" \n) - < "*)" \n - > \n - resume: - < < "esac") - (ksh . sh) - (bash . sh) - (csh "expression: " - "switch( " str " )" \n - > "case " (read-string "pattern: ") ?: \n - > _ \n - "breaksw" \n - ( "other pattern, %s: " - < "case " str ?: \n - > \n - "breaksw" \n) - < "default:" \n - > \n - resume: - < < "endsw") - (tcsh . csh)) - - - -(define-sh-skeleton sh-for - "Insert a for loop in the current shell's syntax." - (sh "Index variable: " - "for " str " in " _ "; do" \n - > ?$ (sh-remember-variable str) \n - < "done") - (ksh . sh) - (bash . sh) - (csh "Index variable: " - "foreach " str " ( " _ " )" \n - > ?$ (sh-remember-variable str) \n - < "end") - (tcsh . csh)) - - - -(define-sh-skeleton sh-indexed-loop - "Insert an indexed loop from 1 to n in the current shell's syntax." - (sh "Index variable: " - str "=1" \n - "while [ $" str " -le " - (read-string "upper limit: ") - " ]; do" \n - > _ ?$ str \n - str ?= (sh-add (sh-remember-variable str) 1) \n - < "done") - (ksh . sh) - (bash . sh) - (csh "Index variable: " - "@ " str " = 1" \n - "while( $" str " <= " - (read-string "upper limit: ") - " )" \n - > _ ?$ (sh-remember-variable str) \n - "@ " str "++" \n - < "end") - (tcsh . csh)) - - - -(defun sh-add (var delta) - "Insert an addition of VAR and prefix DELTA for Bourne type shells." - (interactive - (list (sh-remember-variable - (completing-read "Variable: " sh-variables - (lambda (element) - (or (not (cdr element)) - (memq sh-shell (cdr element)))))) - (prefix-numeric-value current-prefix-arg))) - (setq delta (concat (if (< delta 0) " - " " + ") - (abs delta))) - (skeleton-insert - (assq sh-shell - '((sh "`expr $" var delta "`") - (ksh "$(( $" var delta " ))") - (bash "$[ $" var delta " ]"))) - t)) - - - -(define-sh-skeleton sh-function - "Insert a function definition in the current shell's syntax." - (sh () - "() {" \n - > _ \n - < "}") - (ksh "name: " - "function " str " {" \n - > _ \n - < "}") - (bash "name: " - "function " str "() {" \n - > _ \n - < "}")) - - - -(define-sh-skeleton sh-if - "Insert an if statement in the current shell's syntax." - (sh "condition: " - "if [ " str " ]; then" \n - > _ \n - ( "other condition, %s: " - < "elif [ " str " ]; then" \n - > \n) - < "else" \n - > \n - resume: - < "fi") - (ksh . sh) - (bash . sh) - (csh "condition: " - "if( " str " ) then" \n - > _ \n - ( "other condition, %s: " - < "else if ( " str " ) then" \n - > \n) - < "else" \n - > \n - resume: - < "endif") - (tcsh . csh)) - - - -(define-sh-skeleton sh-select - "Insert a select statement in the current shell's syntax." - (ksh "Index variable: " - "select " str " in " _ "; do" \n - > ?$ str \n - < "done")) -(put 'sh-select 'menu-enable '(get 'sh-select sh-shell)) - - - -(define-sh-skeleton sh-until - "Insert an until loop in the current shell's syntax." - (sh "condition: " - "until [ " str " ]; do" \n - > _ \n - < "done") - (ksh . sh) - (bash . sh)) -(put 'sh-until 'menu-enable '(get 'sh-until sh-shell)) - - -(define-sh-skeleton sh-while - "Insert a while loop in the current shell's syntax." - (sh "condition: " - "while [ " str " ]; do" \n - > _ \n - < "done") - (ksh . sh) - (bash . sh) - (csh "condition: " - "while( " str " )" \n - > _ \n - < "end") - (tcsh . csh)) - - - -(defun sh-query-for-variable (arg) - "Unless quoted with `\\', query for variable-name with completions. -Prefix arg 0 means don't insert `$' before the variable. -Prefix arg 2 or more means only do self-insert that many times. - If { is pressed as the first character, it will surround the variable name." - (interactive "*p") - (or (prog1 (or (> arg 1) - (sh-quoted-p)) - (self-insert-command arg)) - (let (completion-ignore-case - (minibuffer-local-completion-map - (or (get 'sh-query-for-variable 'keymap) - (put 'sh-query-for-variable 'keymap - (copy-keymap minibuffer-local-completion-map)))) - (buffer (current-buffer))) - ;; local function that depends on `arg' and `buffer' - (define-key minibuffer-local-completion-map "{" - (lambda () (interactive) - (if (or arg (> (point) 1)) - (beep) - (save-window-excursion - (setq arg t) - (switch-to-buffer-other-window buffer) - (insert "{}"))))) - (insert - (prog1 - (sh-remember-variable - (completing-read "Variable: " sh-variables - (lambda (element) - (or (not (cdr element)) - (memq sh-shell (cdr element)))))) - (if (eq t arg) (forward-char 1)))) - (if (eq t arg) (forward-char 1))))) - - - -(defun sh-assignment (arg) - "Insert self. Remember previous identifier for future completing read." - (interactive "p") - (if (eq arg 1) - (sh-remember-variable - (save-excursion - (buffer-substring - (progn - (if (memq sh-shell sh-assignment-space) - (skip-chars-backward " \t")) - (point)) - (progn - (skip-chars-backward "a-zA-Z0-9_") - (point)))))) - (self-insert-command arg)) - - - -(defun sh-maybe-here-document (arg) - "Inserts self. Without prefix, following unquoted `<' inserts here document. -The document is bounded by `sh-here-document-word'." - (interactive "*P") - (self-insert-command (prefix-numeric-value arg)) - (or arg - (not (eq (char-after (- (point) 2)) last-command-char)) - (save-excursion - (goto-char (- (point) 2)) - (sh-quoted-p)) - (progn - (insert sh-here-document-word) - (or (looking-at "[ \t\n]") (insert ? )) - (end-of-line 1) - (newline) - (save-excursion (insert ?\n sh-here-document-word))))) - - -;; various other commands - -(autoload 'comint-dynamic-complete-filename "comint" - "Dynamically complete the filename at point." t) - - - -(defun sh-newline-and-indent (&optional arg) - "Strip unquoted whitespace, insert newline, and indent like current line. -Unquoted whitespace is stripped from the current line's end, unless a -prefix ARG is given." - (interactive "*P") - (let ((previous (current-indentation)) - (end-of-line (point))) - (if arg () - (skip-chars-backward " \t") - (and (< (point) end-of-line) - (sh-quoted-p) - (forward-char 1)) - (delete-region (point) end-of-line)) - (newline) - (indent-to previous))) - - - -(defun sh-set-shell (shell) - "Set this buffer's shell to SHELL (a string). -Calls the value of `sh-set-shell-hook' if set." - (interactive "sName or path of shell: ") - (save-excursion - (goto-char (point-min)) - (setq sh-shell-path (if (file-name-absolute-p shell) - shell - (or (sh-executable shell) - (error "Cannot find %s." shell))) - sh-shell (intern (file-name-nondirectory sh-shell-path)) - sh-shell-is-csh (memq sh-shell '(csh tcsh)) - font-lock-keywords - (intern-soft (format "sh-%s-font-lock-keywords" sh-shell)) - font-lock-keywords (if (and font-lock-keywords - (boundp font-lock-keywords)) - (symbol-value font-lock-keywords) - sh-font-lock-keywords) - comment-start-skip (if sh-shell-is-csh - "\\(^\\|[^$]\\|\\$[^{]\\)#+[\t ]*" - "\\(^\\|[^$]\\|\\$[^{]\\)\\B#+[\t ]*") - mode-line-process (format ": %s" sh-shell) - shell (concat sh-shell-path - (and sh-shell-argument " ") - sh-shell-argument)) - (and (not buffer-read-only) - (not (if buffer-file-name - (string-match sh-magicless-file-regexp buffer-file-name))) - ;; find-file is set by `normal-mode' when called by `after-find-file' - (if (and (boundp 'find-file) find-file) sh-find-file-modifies t) - (if (looking-at "#!") - (and (skip-chars-forward "#! \t") - (not (string= shell - (buffer-substring (point) - (save-excursion (end-of-line) - (point))))) - (if sh-query-for-magic - (y-or-n-p (concat "Replace magic number by ``#! " - shell "''? ")) - (message "Magic number ``%s'' replaced." - (buffer-substring (point-min) (point)))) - (not (delete-region (point) (progn (end-of-line) (point)))) - (insert shell)) - (insert "#! " shell ?\n)))) - (run-hooks 'sh-set-shell-hook)) - - - -(defun sh-beginning-of-command () - "Move point to successive beginnings of commands." - (interactive) - (if (re-search-backward sh-beginning-of-command nil t) - (goto-char (match-beginning 2)))) - - - -(defun sh-end-of-command () - "Move point to successive ends of commands." - (interactive) - (if (re-search-forward sh-end-of-command nil t) - (goto-char (match-end 1)))) - - - -(defun sh-manual-entry (arg) - "Display the Unix manual entry for the current command or shell. -Universal argument ARG, is passed to `Man-getpage-in-background'." - (interactive "P") - (let ((command (save-excursion - (sh-beginning-of-command) - (sh-executable - (buffer-substring (point) - (progn (forward-sexp) (point))))))) - (setq command (read-input (concat "Manual entry (default " - (symbol-name sh-shell) - "): ") - (if command - (file-name-nondirectory command)))) - (manual-entry (if (string= command "") - (symbol-name sh-shell) - command) - arg))) - -;; sh-script.el ends here diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el deleted file mode 100644 index 82c5b87401a..00000000000 --- a/lisp/progmodes/simula.el +++ /dev/null @@ -1,1291 +0,0 @@ -;;; simula.el --- SIMULA 87 code editing commands for Emacs - -;; Copyright (C) 1992 Free Software Foundation, Inc. - -;; Author: Hans Henrik Eriksen <hhe@ifi.uio.no> -;; Maintainer: simula-mode@ifi.uio.no -;; Version: 0.992 -;; Adapted-By: ESR -;; Keywords: languages - -;; 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; A major mode for editing the Simula language. It knows about Simula -;; syntax and standard indentation commands. It also provides convenient -;; abbrevs for Simula keywords. -;; -;; Hans Henrik Eriksen (the author) may be reached at: -;; Institutt for informatikk, -;; Universitetet i Oslo - -;;; Code: - -(provide 'simula-mode) - -(defconst simula-tab-always-indent nil - "*Non-nil means TAB in SIMULA mode should always reindent the current line. -Otherwise TAB indents only when point is within -the run of whitespace at the beginning of the line.") - -(defconst simula-indent-level 3 - "*Indentation of SIMULA statements with respect to containing block.") - -(defconst simula-substatement-offset 3 - "*Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE.") - -(defconst simula-continued-statement-offset 3 - "*Extra indentation for lines not starting a statement or substatement. -If value is a list, each line in a multipleline continued statement -will have the car of the list extra indentation with respect to -the previous line of the statement.") - -(defconst simula-label-offset -4711 - "*Offset of SIMULA label lines relative to usual indentation.") - -(defconst simula-if-indent '(0 . 0) - "*Extra indentation of THEN and ELSE with respect to the starting IF. -Value is a cons cell, the car is extra THEN indentation and the cdr -extra ELSE indentation. IF after ELSE is indented as the starting IF.") - -(defconst simula-inspect-indent '(0 . 0) - "*Extra indentation of WHEN and OTHERWISE with respect to the INSPECT. -Value is a cons cell, the car is extra WHEN indentation -and the cdr extra OTHERWISE indentation.") - -(defconst simula-electric-indent nil - "*Non-nil means `simula-indent-line' function may reindent previous line.") - -(defconst simula-abbrev-keyword 'upcase - "*Specify how to convert case for SIMULA keywords. -Value is one of the symbols `upcase', `downcase', `capitalize', -(as in) `abbrev-table' or nil if they should not be changed.") - -(defconst simula-abbrev-stdproc 'abbrev-table - "*Specify how to convert case for standard SIMULA procedure and class names. -Value is one of the symbols `upcase', `downcase', `capitalize', -(as in) `abbrev-table', or nil if they should not be changed.") - -(defvar simula-abbrev-file nil - "*File with extra abbrev definitions for use in SIMULA mode. -These are used together with the standard abbrev definitions for SIMULA. -Please note that the standard definitions are required -for SIMULA mode to function correctly.") - -(defvar simula-mode-syntax-table nil - "Syntax table in SIMULA mode buffers.") - -(if simula-mode-syntax-table - () - (setq simula-mode-syntax-table (copy-syntax-table (standard-syntax-table))) - (modify-syntax-entry ?! "<" simula-mode-syntax-table) - (modify-syntax-entry ?$ "." simula-mode-syntax-table) - (modify-syntax-entry ?% "." simula-mode-syntax-table) - (modify-syntax-entry ?' "\"" simula-mode-syntax-table) - (modify-syntax-entry ?\( "()" simula-mode-syntax-table) - (modify-syntax-entry ?\) ")(" simula-mode-syntax-table) - (modify-syntax-entry ?\; ">" simula-mode-syntax-table) - (modify-syntax-entry ?\[ "." simula-mode-syntax-table) - (modify-syntax-entry ?\\ "." simula-mode-syntax-table) - (modify-syntax-entry ?\] "." simula-mode-syntax-table) - (modify-syntax-entry ?_ "w" simula-mode-syntax-table) - (modify-syntax-entry ?\| "." simula-mode-syntax-table) - (modify-syntax-entry ?\{ "." simula-mode-syntax-table) - (modify-syntax-entry ?\} "." simula-mode-syntax-table)) - -(defvar simula-mode-map () - "Keymap used in SIMULA mode.") - -(if simula-mode-map - () - (setq simula-mode-map (make-sparse-keymap)) - (define-key simula-mode-map "\C-c\C-u" 'simula-backward-up-level) - (define-key simula-mode-map "\C-c\C-p" 'simula-previous-statement) - (define-key simula-mode-map "\C-c\C-d" 'simula-forward-down-level) - (define-key simula-mode-map "\C-c\C-n" 'simula-next-statement) - ;(define-key simula-mode-map "\C-c\C-g" 'simula-goto-definition) - ;(define-key simula-mode-map "\C-c\C-h" 'simula-standard-help) - (define-key simula-mode-map "\177" 'backward-delete-char-untabify) - (define-key simula-mode-map ":" 'simula-electric-label) - (define-key simula-mode-map "\t" 'simula-indent-command)) - -(defvar simula-mode-abbrev-table nil - "Abbrev table in SIMULA mode buffers") - - -(defun simula-mode () - "Major mode for editing SIMULA code. -\\{simula-mode-map} -Variables controlling indentation style: - simula-tab-always-indent - Non-nil means TAB in SIMULA mode should always reindent the current line, - regardless of where in the line point is when the TAB command is used. - simula-indent-level - Indentation of SIMULA statements with respect to containing block. - simula-substatement-offset - Extra indentation after DO, THEN, ELSE, WHEN and OTHERWISE. - simula-continued-statement-offset 3 - Extra indentation for lines not starting a statement or substatement, - e.g. a nested FOR-loop. If value is a list, each line in a multiple- - line continued statement will have the car of the list extra indentation - with respect to the previous line of the statement. - simula-label-offset -4711 - Offset of SIMULA label lines relative to usual indentation. - simula-if-indent '(0 . 0) - Extra indentation of THEN and ELSE with respect to the starting IF. - Value is a cons cell, the car is extra THEN indentation and the cdr - extra ELSE indentation. IF after ELSE is indented as the starting IF. - simula-inspect-indent '(0 . 0) - Extra indentation of WHEN and OTHERWISE with respect to the - corresponding INSPECT. Value is a cons cell, the car is - extra WHEN indentation and the cdr extra OTHERWISE indentation. - simula-electric-indent nil - If this variable is non-nil, `simula-indent-line' - will check the previous line to see if it has to be reindented. - simula-abbrev-keyword 'upcase - Determine how SIMULA keywords will be expanded. Value is one of - the symbols `upcase', `downcase', `capitalize', (as in) `abbrev-table', - or nil if they should not be changed. - simula-abbrev-stdproc 'abbrev-table - Determine how standard SIMULA procedure and class names will be - expanded. Value is one of the symbols `upcase', `downcase', `capitalize', - (as in) `abbrev-table', or nil if they should not be changed. - -Turning on SIMULA mode calls the value of the variable simula-mode-hook -with no arguments, if that value is non-nil - -Warning: simula-mode-hook should not read in an abbrev file without calling -the function simula-install-standard-abbrevs afterwards, preferably not -at all." - (interactive) - (kill-all-local-variables) - (use-local-map simula-mode-map) - (setq major-mode 'simula-mode) - (setq mode-name "SIMULA") - (make-local-variable 'comment-column) - (setq comment-column 40) - (make-local-variable 'end-comment-column) - (setq end-comment-column 75) - (set-syntax-table simula-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start "^[ \t]*$\\|\\f") - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'simula-indent-line) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "! ") - (make-local-variable 'comment-end) - (setq comment-end " ;") - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "!+ *") - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments nil) - (make-local-variable 'comment-multi-line) - (setq comment-multi-line t) - (if simula-mode-abbrev-table - () - (if simula-abbrev-file - (read-abbrev-file simula-abbrev-file) - (define-abbrev-table 'simula-mode-abbrev-table ())) - (let (abbrevs-changed) - (simula-install-standard-abbrevs))) - (setq local-abbrev-table simula-mode-abbrev-table) - (abbrev-mode 1) - (run-hooks 'simula-mode-hook)) - - - -(defun simula-indent-line () - "Indent this line as SIMULA code. -If `simula-electric-indent' is non-nil, indent previous line if necessary." - (let ((origin (- (point-max) (point))) - (indent (simula-calculate-indent)) - (case-fold-search t)) - (unwind-protect - (progn - ;; - ;; manually expand abbrev on last line, if any - ;; - (end-of-line 0) - (expand-abbrev) - ;; now maybe we should reindent that line - (if simula-electric-indent - (progn - (beginning-of-line) - (skip-chars-forward " \t\f") - (if (and - (looking-at - "\\(end\\|if\\|then\\|else\\|when\\|otherwise\\)\\>") - (not (simula-context))) - ;; yes - reindent - (let ((post-indent (simula-calculate-indent))) - (if (eq (current-indentation) post-indent) - () - (delete-horizontal-space) - (indent-to post-indent))))))) - (goto-char (- (point-max) origin)) - (if (eq (current-indentation) indent) - (back-to-indentation) - (delete-horizontal-space) - (indent-to indent))))) - - -(defun simula-indent-command (&optional whole-exp) - "Indent current line as SIMULA code, or insert TAB character. -If `simula-tab-always-indent' is non-nil, always indent current line. -Otherwise, indent only if point is before any non-whitespace -character on the line. - -A numeric argument, regardless of its value, means indent rigidly -all the lines of the SIMULA statement after point so that this line -becomes properly indented. -The relative indentation among the lines of the statement are preserved." - (interactive "P") - (let ((case-fold-search t)) - (if (or whole-exp simula-tab-always-indent - (save-excursion - (skip-chars-backward " \t\f") - (bolp))) - ;; reindent current line - (let ((indent (save-excursion - (beginning-of-line) - (simula-calculate-indent))) - (current (current-indentation)) - (origin (- (point-max) (point))) - (bol (save-excursion - (skip-chars-backward " \t\f") - (bolp))) - beg end) - (unwind-protect - (if (eq current indent) - (if (save-excursion - (skip-chars-backward " \t\f") - (bolp)) - (back-to-indentation)) - (beginning-of-line) - (delete-horizontal-space) - (indent-to indent)) - (if (not bol) - (goto-char (- (point-max) origin)))) - (setq origin (point)) - (if whole-exp - (save-excursion - (beginning-of-line 2) - (setq beg (point)) - (goto-char origin) - (simula-next-statement 1) - (setq end (point)) - (if (and (> end beg) (not (eq indent current))) - (indent-code-rigidly beg end (- indent current) "%"))))) - (insert-tab)))) - - -(defun simula-context () - "Returns value according to syntactic SIMULA context of point. - 0 point inside COMMENT comment - 1 point on SIMULA-compiler directive line - 2 point inside END comment - 3 point inside string - 4 point inside character constant - nil otherwise." - ;; first, find out if this is a compiler directive line - (if (save-excursion - (beginning-of-line) - (eq (following-char) ?%)) - ;; YES - return 1 - 1 - (save-excursion - ;; The current line is NOT a compiler directive line. - ;; Now, the strategy is to search backward to find a semicolon - ;; that is NOT inside a string. The point after semicolon MUST be - ;; outside a comment, since semicolons are comment-ending and - ;; comments are non-recursive. We take advantage of the fact - ;; that strings MUST end on the same line as they started, so - ;; that we can easily decide whether we are inside a string or not. - (let (return-value (origin (point))) - (skip-chars-backward "^;" (point-min)) - ;; found semicolon or beginning of buffer - (let (loopvalue (saved-point origin)) - (while (and (not (bobp)) - (if (progn - (beginning-of-line) - ;; compiler directive line? If so, cont searching.. - (eq (following-char) ?%)) - t - (while (< (point) saved-point) - (skip-chars-forward "^;\"'") - (forward-char 1) - (cond - ((eq (preceding-char) ?\;) - (setq saved-point (point))) - ((eq (preceding-char) ?\") - (skip-chars-forward "^\";") - (if (eq (following-char) ?\;) - (setq saved-point (point) loopvalue t) - (forward-char 1))) - (t - (if (eq (following-char) ?') - (forward-char 1)) - (skip-chars-forward "^';") - (if (eq (following-char) ?\;) - (setq saved-point (point) loopvalue t) - (forward-char 1))))) - loopvalue)) - (backward-char 1) - (skip-chars-backward "^;") - (setq saved-point (point) loopvalue nil))) - ;; Now we are CERTAIN that we are outside comments and strings. - ;; The job now is to search forward again towards the origin - ;; skipping directives, comments and strings correctly, - ;; so that we know what context we are in when we find the origin. - (while (and - (< (point) origin) - (re-search-forward - "\\<end\\>\\|!\\|\"\\|'\\|^%\\|\\<comment\\>" origin 'move)) - (cond - ((memq (preceding-char) '(?d ?D)) - (setq return-value 2) - (while (and (memq (preceding-char) '(?d ?D)) (not return-value)) - (while (and (re-search-forward - ";\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>\\|^%" - origin 'move) - (eq (preceding-char) ?%)) - (beginning-of-line 2))) - (if (looking-at "[ \t\n\f]*\\(;\\|\\<end\\>\\|\\<else\\>\\|\\<otherwise\\>\\|\\<when\\>\\)") - (setq return-value nil))) - ((memq (preceding-char) '(?! ?t ?T)) - ; skip comment - (setq return-value 0) - (skip-chars-forward "^%;" origin) - (while (and return-value (< (point) origin)) - (if (eq (following-char) ?\;) - (setq return-value nil) - (if (bolp) - (beginning-of-line 2) ; skip directive inside comment - (forward-char 1)) ; or single '%' - (skip-chars-forward "^%;" origin)))) - ((eq (preceding-char) ?\") - (if (not (search-forward "\"" origin 'move)) - (setq return-value 3))) - ((eq (preceding-char) ?\') - (if (or (eq (point) origin) (eobp)) - (setq return-value 4) - (forward-char 1) - (if (not (search-forward "'" origin 'move)) - (setq return-value 4)))) - ;; compiler directive line - skip - (t (beginning-of-line 2)))) - return-value) - ))) - - -(defun simula-electric-label () - "If this is a label that starts the line, reindent the line." - (interactive) - (expand-abbrev) - (insert ?:) - (let ((origin (- (point-max) (point))) - (case-fold-search t) - ;; don't mix a label with an assignment operator := :- - ;; therefore look at next typed character... - (next-char (setq unread-command-events (list (read-event)))) - (com-char last-command-char)) - (unwind-protect - ;; Problem: find out if character just read is a command char - ;; that would insert something after ':' making it a label. - ;; At least \n, \r (and maybe \t) falls into this category. - ;; This is a real crock, it depends on traditional keymap - ;; bindings, that is, printing characters doing self-insert, - ;; and no other command sequence inserting '-' or '='. - ;; simula-electric-label can be easily fooled... - (if (and (not (memq next-char '(?= ?-))) - (or (memq next-char '(?\n ?\r)) - (and (eq next-char ?\t) - simula-tab-always-indent) - (not (memq (following-char) '(?= ?-)))) - (not (simula-context)) - ;; label? - (progn - (backward-char 1) - (skip-chars-backward " \t\f") - (skip-chars-backward "a-zA-Z0-9_") - (if (looking-at "virtual\\>") - nil - (skip-chars-backward " \t\f") - (bolp)))) - (let ((amount (simula-calculate-indent))) - (delete-horizontal-space) - (indent-to amount))) - (goto-char (- (point-max) origin))))) - - -(defun simula-backward-up-level (count) - "Move backward up COUNT block levels. -If COUNT is negative, move forward up block level instead." - (interactive "p") - (let ((origin (point)) - (case-fold-search t)) - (condition-case () - (if (> count 0) - (while (> count 0) - (re-search-backward "\\<begin\\>\\|\\<end\\>") - (if (not (simula-context)) - (setq count (if (memq (following-char) '(?b ?B)) - (1- count) - (1+ count))))) - (while (< count 0) - (re-search-forward "\\<begin\\>\\|\\<end\\>") - (backward-word 1) - (if (not (simula-context)) - (setq count (if (memq (following-char) '(?e ?E)) - (1+ count) - (1- count)))) - (backward-word -1))) - ;; If block level not found, jump back to origin and signal an error - (error (progn - (goto-char origin) - (error "No higher block level"))) - (quit (progn - (goto-char origin) - (signal 'quit nil)))))) - - -(defun simula-forward-down-level (count) - "Move forward down COUNT block levels. -If COUNT is negative, move backward down block level instead." - (interactive "p") - ;; When we search for a deeper block level, we must never - ;; get out of the block where we started -> count >= start-count - (let ((start-count count) - (origin (point)) - (case-fold-search t)) - (condition-case () - (if (< count 0) - (while (< count 0) - (re-search-backward "\\<begin\\>\\|\\<end\\>") - (if (not (simula-context)) - (setq count (if (memq (following-char) '(?e ?E)) - (1+ count) - (1- count)))) - (if (< count start-count) (signal 'error nil))) - (while (> count 0) - (re-search-forward "\\<begin\\>\\|\\<end\\>") - (backward-word 1) - (if (not (simula-context)) - (setq count (if (memq (following-char) '(?b ?B)) - (1- count) - (1+ count)))) - (backward-word -1) - ;; deeper level has to be found within starting block - (if (> count start-count) (signal 'error nil)))) - ;; If block level not found, jump back to origin and signal an error - (error (progn - (goto-char origin) - (error "No containing block level"))) - (quit (progn - (goto-char origin) - (signal 'quit nil)))))) - - -(defun simula-previous-statement (count) - "Move backward COUNT statements. -If COUNT is negative, move forward instead." - (interactive "p") - (if (< count 0) - (simula-next-statement (- count)) - (let (status - (case-fold-search t) - (origin (point))) - (condition-case () - (progn - (simula-skip-comment-backward) - (if (memq (preceding-char) '(?n ?N)) - (progn - (backward-word 1) - (if (not (looking-at "\\<begin\\>")) - (backward-word -1))) - (if (eq (preceding-char) ?\;) - (backward-char 1))) - (while (and (natnump (setq count (1- count))) - (setq status (simula-search-backward - ";\\|\\<begin\\>" nil 'move)))) - (if status - (progn - (if (eq (following-char) ?\;) - (forward-char 1) - (backward-word -1)))) - (simula-skip-comment-forward)) - (error (progn (goto-char origin) - (error "Incomplete statement (too many ENDs)"))) - (quit (progn (goto-char origin) (signal 'quit nil))))))) - - -(defun simula-next-statement (count) - "Move forward COUNT statements. -If COUNT is negative, move backward instead." - (interactive "p") - (if (< count 0) - (simula-previous-statement (- count)) - (let (status - (case-fold-search t) - (origin (point))) - (condition-case () - (progn - (simula-skip-comment-forward) - (if (looking-at "\\<end\\>") (forward-word 1)) - (while (and (natnump (setq count (1- count))) - (setq status (simula-search-forward - ";\\|\\<end\\>" (point-max) 'move)))) - (if (and status (/= (preceding-char) ?\;)) - (progn - (backward-word 1) - (simula-skip-comment-backward)))) - (error (progn (goto-char origin) - (error "Incomplete statement (too few ENDs)"))) - (quit (progn (goto-char origin) (signal 'quit nil))))))) - - -(defun simula-skip-comment-backward () - "Search towards bob to find first char that is outside a comment." - (interactive) - (catch 'simula-out - (let (context) - (while t - (skip-chars-backward " \t\n\f") - (if (eq (preceding-char) ?\;) - (save-excursion - (backward-char 1) - (setq context (simula-context))) - (setq context (simula-context))) - (cond - ((memq context '(nil 3 4)) - ;; check to see if we found a label - (if (and (eq (preceding-char) ?:) - (not (memq (following-char) '(?- ?=))) - (save-excursion - (skip-chars-backward ": \t\fa-zA-Z0-9_") - (not (looking-at "virtual\\>")))) - (skip-chars-backward ": \t\fa-zA-Z0-9_") - (throw 'simula-out nil))) - ((eq context 0) - ;; since we are inside a comment, it must start somewhere! - (while (and (re-search-backward "!\\|\\<comment\\>") - (memq (simula-context) '(0 1))))) - ((eq context 1) - (end-of-line 0) - (if (bobp) - (throw 'simula-out nil))) - ((eq context 2) - ;; an END-comment must belong to an END - (re-search-backward "\\<end\\>") - (forward-word 1) - (throw 'simula-out nil)) - ;; should be impossible to get here.. - ))))) - - -(defun simula-skip-comment-forward () - "Search towards eob to find first char that is outside a comment." - ;; this function assumes we start with point .outside a comment - (interactive) - (catch 'simula-out - (while t - (skip-chars-forward " \t\n\f") - (cond - ((looking-at "!\\|\\<comment\\>") - (search-forward ";" nil 'move)) - ((and (bolp) (eq (following-char) ?%)) - (beginning-of-line 2)) - ((and (looking-at "[a-z0-9_]*[ \t\f]*:[^-=]") - (not (looking-at "virtual\\>"))) - (skip-chars-forward "a-zA-Z0-9_ \t\f:")) - (t - (throw 'simula-out t)))))) - - -(defun simula-forward-up-level () - (let ((continue-loop t) - (origin (point)) - (case-fold-search t) - return-value - temp) - (while continue-loop - (if (re-search-backward "\\<begin\\>\\|\\<end\\>" (point-min) 'move) - (setq temp (simula-context) - return-value (and (memq (preceding-char) '(?d ?D)) - (memq temp '(nil 2))) - continue-loop (and (not return-value) - (simula-forward-up-level))) - (setq continue-loop nil))) - (if return-value - t - (goto-char origin) - nil))) - - -(defun simula-calculate-indent () - (save-excursion - (let ((where (simula-context)) - (origin (point)) - (indent 0) - continued - start-line - temp - found-end - prev-cont) - (cond - ((eq where 0) - ;; - ;; Comment. - ;; If comment started on previous non-blank line, indent to the - ;; column where the comment started, else indent as that line. - ;; - (skip-chars-backward " \t\n\f") - (while (and (not (bolp)) (eq (simula-context) 0)) - (re-search-backward "^\\|!\\|\\<comment\\>")) - (skip-chars-forward " \t\n\f") - (prog1 - (current-column) - (goto-char origin))) - ;; - ;; Detect missing string delimiters - ;; - ((eq where 3) - (error "Inside string")) - ((eq where 4) - (error "Inside character constant")) - ;; - ;; check to see if inside ()'s - ;; - ((setq temp (simula-inside-parens)) - temp) - ;; - ;; Calculate non-comment indentation - (t - ;; first, find out if this line starts with something that needs - ;; special indentation (END/IF/THEN/ELSE/WHEN/OTHERWISE or label) - ;; - (skip-chars-forward " \t\f") - (cond - ;; - ;; END - ;; - ((looking-at "end\\>") - (setq indent (- simula-indent-level) - found-end t)) - ;; - ;; IF/THEN/ELSE - ;; - ((looking-at "if\\>\\|then\\>\\|else\\>") - ;; search for the *starting* IF - (cond - ((memq (following-char) '(?T ?t)) - (setq indent (car simula-if-indent))) - ((memq (following-char) '(?E ?e)) - (setq indent (cdr simula-if-indent))) - (t - (forward-word 1) - (setq indent 0))) - (simula-find-if)) - ;; - ;; WHEN/OTHERWISE - ;; - ((looking-at "when\\>\\|otherwise\\>") - ;; search for corresponding INSPECT - (if (memq (following-char) '(?W ?w)) - (setq indent (car simula-inspect-indent)) - (setq indent (cdr simula-inspect-indent))) - (simula-find-inspect)) - ;; - ;; label: - ;; - ((and (not (looking-at "virtual\\>")) - (looking-at "[a-z0-9_]*[ \t\f]*:[^-=]")) - (setq indent simula-label-offset))) - ;; find line with non-comment text - (simula-skip-comment-backward) - (if (and found-end - (not (eq (preceding-char) ?\;)) - (if (memq (preceding-char) '(?N ?n)) - (save-excursion - (backward-word 1) - (not (looking-at "begin\\>"))) - t)) - (progn - (simula-previous-statement 1) - (simula-skip-comment-backward))) - (setq start-line - (save-excursion (beginning-of-line) (point)) - ;; - perhaps this is a continued statement - continued - (save-excursion - (and (not (bobp)) - ;; (not found-end) - (if (eq (char-syntax (preceding-char)) ?w) - (progn - (backward-word 1) - (not (looking-at - "begin\\|then\\|else\\|when\\|otherwise\\|do" - ))) - (not (memq (preceding-char) '(?: ?\;))))))) - ;; - ;; MAIN calculation loop - count BEGIN/DO etc. - ;; - (while (not (bolp)) - (if (re-search-backward - ";\\|\\<\\(begin\\|end\\|if\\|else\\|then\\|when\\|otherwise\\|do\\)\\>" - start-line 'move) - (if (simula-context) - ();; found something in a comment/string - ignore - (setq temp (following-char)) - (cond - ((eq temp ?\;) - (simula-previous-statement 1)) - ((looking-at "begin\\>") - (setq indent (+ indent simula-indent-level))) - ((looking-at "end\\>") - (forward-word 1) - (simula-previous-statement 1)) - ((looking-at "do\\>") - (setq indent (+ indent simula-substatement-offset)) - (simula-find-do-match)) - ((looking-at "\\(if\\|then\\|else\\)\\>") - (if (memq temp '(?I ?i)) - (forward-word 1) - (setq indent (+ indent - simula-substatement-offset - (if (memq temp '(?T ?t)) - (car simula-if-indent) - (cdr simula-if-indent))))) - (simula-find-if)) - ((looking-at "\\<when\\>\\|\\<otherwise\\>") - (setq indent (+ indent - simula-substatement-offset - (if (memq temp '(?W ?w)) - (car simula-if-indent) - (cdr simula-if-indent)))) - (simula-find-inspect))) - ;; found the start of a [sub]statement - ;; add indentation for continued statement - (if continued - (setq indent - (+ indent - (if (listp simula-continued-statement-offset) - (car simula-continued-statement-offset) - simula-continued-statement-offset)))) - (setq start-line - (save-excursion (beginning-of-line) (point)) - continued nil)) - ;; search failed .. point is at beginning of line - ;; determine if we should continue searching - ;; (at or before comment or label) - ;; temp = t means finished - (setq temp - (and (not (simula-context)) - (save-excursion - (skip-chars-forward " \t\f") - (or (looking-at "virtual") - (not - (looking-at - "!\\|comment\\>\\|[a-z0-9_]*[ \t\f]*:[^-=]"))))) - prev-cont continued) - ;; if we are finished, find current line's indentation - (if temp - (setq indent (+ indent (current-indentation)))) - ;; find next line with non-comment SIMULA text - ;; maybe indent extra if statement continues - (simula-skip-comment-backward) - (setq continued - (and (not (bobp)) - (if (eq (char-syntax (preceding-char)) ?w) - (save-excursion - (backward-word 1) - (not (looking-at - "begin\\|then\\|else\\|when\\|otherwise\\|do"))) - (not (memq (preceding-char) '(?: ?\;)))))) - ;; if we the state of the continued-variable - ;; changed, add indentation for continued statement - (if (or (and prev-cont (not continued)) - (and continued - (listp simula-continued-statement-offset))) - (setq indent - (+ indent - (if (listp simula-continued-statement-offset) - (car simula-continued-statement-offset) - simula-continued-statement-offset)))) - ;; while ends if point is at beginning of line at loop test - (if (not temp) - (setq start-line (save-excursion (beginning-of-line) (point))) - (beginning-of-line)))) - ;; - ;; return indentation - ;; - indent))))) - - -(defun simula-find-if () - "Find starting IF of a IF-THEN[-ELSE[-IF-THEN...]] statement." - (catch 'simula-out - (while t - (if (and (simula-search-backward "\\<if\\>\\|;\\|\\<begin\\>"nil t) - (memq (following-char) '(?I ?i))) - (save-excursion - ;; - ;; find out if this IF was really the start of the IF statement - ;; - (simula-skip-comment-backward) - (if (and (eq (char-syntax (preceding-char)) ?w) - (progn - (backward-word 1) - (looking-at "else\\>"))) - () - (throw 'simula-out t))) - (if (not (looking-at "\\<if\\>")) - (error "Missing IF or misplaced BEGIN or ';' (can't find IF)") - ;; - ;; we were at the starting IF in the first place.. - ;; - (throw 'simula-out t)))))) - - -(defun simula-find-inspect () - "Find INSPECT matching WHEN or OTHERWISE." - (catch 'simula-out - (let ((level 0)) - ;; - ;; INSPECTs can be nested, have to find the corresponding one - ;; - (while t - (if (and (simula-search-backward "\\<inspect\\>\\|\\<otherwise\\>\\|;" - nil t) - (/= (following-char) ?\;)) - (if (memq (following-char) '(?O ?o)) - (setq level (1+ level)) - (if (zerop level) - (throw 'simula-out t) - (setq level (1- level)))) - (error "Missing INSPECT or misplaced ';' (can't find INSPECT)")))))) - - -(defun simula-find-do-match () - "Find keyword matching DO: FOR, WHILE, INSPECT or WHEN" - (while (and (re-search-backward - "\\<\\(do\\|for\\|while\\|inspect\\|when\\|end\\|begin\\)\\>\\|;" - nil 'move) - (simula-context))) - (if (and (looking-at "\\<\\(for\\|while\\|inspect\\|when\\)\\>") - (not (simula-context))) - () ;; found match - (error "No matching FOR, WHILE or INSPECT for DO, or misplaced ';'"))) - - -(defun simula-inside-parens () - "Return position after `(' on line if inside parentheses, nil otherwise." - (save-excursion - (let ((parlevel 0)) - (catch 'simula-out - (while t - (if (re-search-backward "(\\|)\\|;" nil t) - (if (eq (simula-context) nil) - ;; found something - check it out - (cond - ((eq (following-char) ?\;) - (if (zerop parlevel) - (throw 'simula-out nil) - (error "Parenthesis mismatch or misplaced ';'"))) - ((eq (following-char) ?\() - (if (zerop parlevel) - (throw 'simula-out (1+ (current-column))) - (setq parlevel (1- parlevel)))) - (t (setq parlevel (1+ parlevel)))) - );; nothing - inside comment or string - ;; search failed - (throw 'simula-out nil))))))) - - -(defun simula-goto-definition () - "Goto point of definition of variable, procedure or class." - (interactive)) - - -(defun simula-expand-stdproc () - (if (or (not simula-abbrev-stdproc) (simula-context)) - (unexpand-abbrev) - (cond - ((eq simula-abbrev-stdproc 'upcase) (upcase-word -1)) - ((eq simula-abbrev-stdproc 'downcase) (downcase-word -1)) - ((eq simula-abbrev-stdproc 'capitalize) (capitalize-word -1))))) - - -(defun simula-expand-keyword () - (if (or (not simula-abbrev-keyword) (simula-context)) - (unexpand-abbrev) - (cond - ((eq simula-abbrev-keyword 'upcase) (upcase-word -1)) - ((eq simula-abbrev-keyword 'downcase) (downcase-word -1)) - ((eq simula-abbrev-keyword 'capitalize) (capitalize-word -1))))) - - -(defun simula-electric-keyword () - "Expand SIMULA keyword. If it starts the line, reindent." - ;; redisplay - (let ((show-char (eq this-command 'self-insert-command))) - ;; If the abbrev expansion results in reindentation, the user may have - ;; to wait some time before the character he typed is displayed - ;; (the char causing the expansion is inserted AFTER the hook function - ;; is called). This is annoying in case of normal characters. - ;; However, if the user pressed a key bound to newline, it is better - ;; to have the line inserted after the begin-end match. - (if show-char - (progn - (insert-char last-command-char 1) - (sit-for 0) - (backward-char 1))) - (if (let ((where (simula-context)) - (case-fold-search t)) - (if where - (if (and (eq where 2) (eq (char-syntax (preceding-char)) ?w)) - (save-excursion - (backward-word 1) - (not (looking-at "end\\>")))))) - (unexpand-abbrev) - (cond - ((not simula-abbrev-keyword) (unexpand-abbrev)) - ((eq simula-abbrev-keyword 'upcase) (upcase-word -1)) - ((eq simula-abbrev-keyword 'downcase) (downcase-word -1)) - ((eq simula-abbrev-keyword 'capitalize) (capitalize-word -1))) - (let ((pos (- (point-max) (point))) - (case-fold-search t) - null) - (condition-case null - (progn - ;; check if the expanded word is on the beginning of the line. - (if (and (eq (char-syntax (preceding-char)) ?w) - (progn - (backward-word 1) - (if (looking-at "end\\>") - (save-excursion - (simula-backward-up-level 1) - (if (pos-visible-in-window-p) - (sit-for 1) - (message - (concat "Matches " - (buffer-substring - (point) - (+ (point) (window-width)))))))) - (skip-chars-backward " \t\f") - (bolp))) - (let ((indent (simula-calculate-indent))) - (if (eq indent (current-indentation)) - () - (delete-horizontal-space) - (indent-to indent))) - (skip-chars-forward " \t\f")) - ;; check for END - blow whistles and ring bells - - (goto-char (- (point-max) pos)) - (if show-char - (delete-char 1))) - (quit (goto-char (- (point-max) pos)))))))) - - -(defun simula-search-backward (string &optional limit move) - (setq string (concat string "\\|\\<end\\>")) - (let (level) - (catch 'simula-out - (while (re-search-backward string limit move) - (if (simula-context) - () - (if (looking-at "\\<end\\>") - (progn - (setq level 0) - (while (natnump level) - (re-search-backward "\\<begin\\>\\|\\<end\\>") - (if (simula-context) - () - (setq level (if (memq (following-char) '(?b ?B)) - (1- level) - (1+ level)))))) - (throw 'simula-out t))))))) - - -(defun simula-search-forward (string &optional limit move) - (setq string (concat string "\\|\\<begin\\>")) - (let (level) - (catch 'exit - (while (re-search-forward string limit move) - (goto-char (match-beginning 0)) - (if (simula-context) - (goto-char (1- (match-end 0))) - (if (looking-at "\\<begin\\>") - (progn - (goto-char (1- (match-end 0))) - (setq level 0) - (while (natnump level) - (re-search-forward "\\<begin\\>\\|\\<end\\>") - (backward-word 1) - (if (not (simula-context)) - (setq level (if (memq (following-char) '(?e ?E)) - (1- level) - (1+ level)))) - (backward-word -1))) - (goto-char (1- (match-end 0))) - (throw 'exit t))))))) - - -(defun simula-install-standard-abbrevs () - "Define Simula keywords, procedures and classes in local abbrev table." - ;; procedure and class names are as of the SIMULA 87 standard. - (interactive) - (mapcar (function (lambda (args) - (apply 'define-abbrev simula-mode-abbrev-table args))) - '(("abs" "Abs" simula-expand-stdproc) - ("accum" "Accum" simula-expand-stdproc) - ("activate" "ACTIVATE" simula-expand-keyword) - ("addepsilon" "AddEpsilon" simula-expand-stdproc) - ("after" "AFTER" simula-expand-keyword) - ("and" "AND" simula-expand-keyword) - ("arccos" "ArcCos" simula-expand-stdproc) - ("arcsin" "ArcSin" simula-expand-stdproc) - ("arctan" "ArcTan" simula-expand-stdproc) - ("arctan2" "ArcTan2" simula-expand-stdproc) - ("array" "ARRAY" simula-expand-keyword) - ("at" "AT" simula-expand-keyword) - ("before" "BEFORE" simula-expand-keyword) - ("begin" "BEGIN" simula-expand-keyword) - ("blanks" "Blanks" simula-expand-stdproc) - ("boolean" "BOOLEAN" simula-expand-keyword) - ("breakoutimage" "BreakOutImage" simula-expand-stdproc) - ("bytefile" "ByteFile" simula-expand-stdproc) - ("call" "Call" simula-expand-stdproc) - ("cancel" "Cancel" simula-expand-stdproc) - ("cardinal" "Cardinal" simula-expand-stdproc) - ("char" "Char" simula-expand-stdproc) - ("character" "CHARACTER" simula-expand-keyword) - ("checkpoint" "CheckPoint" simula-expand-stdproc) - ("class" "CLASS" simula-expand-keyword) - ("clear" "Clear" simula-expand-stdproc) - ("clocktime" "ClockTime" simula-expand-stdproc) - ("close" "Close" simula-expand-stdproc) - ("comment" "COMMENT" simula-expand-keyword) - ("constant" "Constant" simula-expand-stdproc) - ("copy" "Copy" simula-expand-stdproc) - ("cos" "Cos" simula-expand-stdproc) - ("cosh" "CosH" simula-expand-stdproc) - ("cotan" "CoTan" simula-expand-stdproc) - ("cputime" "CpuTime" simula-expand-stdproc) - ("current" "Current" simula-expand-stdproc) - ("datetime" "DateTime" simula-expand-stdproc) - ("decimalmark" "DecimalMark" simula-expand-stdproc) - ("delay" "DELAY" simula-expand-keyword) - ("deleteimage" "DeleteImage" simula-expand-stdproc) - ("detach" "Detach" simula-expand-stdproc) - ("digit" "Digit" simula-expand-stdproc) - ("directbytefile" "DirectByteFile" simula-expand-stdproc) - ("directfile" "DirectFile" simula-expand-stdproc) - ("discrete" "Discrete" simula-expand-stdproc) - ("do" "DO" simula-expand-keyword) - ("downcase" "Downcase" simula-expand-stdproc) - ("draw" "Draw" simula-expand-stdproc) - ("eject" "Eject" simula-expand-stdproc) - ("else" "ELSE" simula-electric-keyword) - ("empty" "Empty" simula-expand-stdproc) - ("end" "END" simula-electric-keyword) - ("endfile" "Endfile" simula-expand-stdproc) - ("entier" "Entier" simula-expand-stdproc) - ("eq" "EQ" simula-expand-keyword) - ("eqv" "EQV" simula-expand-keyword) - ("erlang" "Erlang" simula-expand-stdproc) - ("error" "Error" simula-expand-stdproc) - ("evtime" "EvTime" simula-expand-stdproc) - ("exp" "Exp" simula-expand-stdproc) - ("external" "EXTERNAL" simula-expand-keyword) - ("false" "FALSE" simula-expand-keyword) - ("field" "Field" simula-expand-stdproc) - ("file" "File" simula-expand-stdproc) - ("first" "First" simula-expand-stdproc) - ("follow" "Follow" simula-expand-stdproc) - ("for" "FOR" simula-expand-keyword) - ("ge" "GE" simula-expand-keyword) - ("getchar" "GetChar" simula-expand-stdproc) - ("getfrac" "GetFrac" simula-expand-stdproc) - ("getint" "GetInt" simula-expand-stdproc) - ("getreal" "GetReal" simula-expand-stdproc) - ("go" "GO" simula-expand-keyword) - ("goto" "GOTO" simula-expand-keyword) - ("gt" "GT" simula-expand-keyword) - ("head" "Head" simula-expand-stdproc) - ("hidden" "HIDDEN" simula-expand-keyword) - ("histd" "HistD" simula-expand-stdproc) - ("histo" "Histo" simula-expand-stdproc) - ("hold" "Hold" simula-expand-stdproc) - ("idle" "Idle" simula-expand-stdproc) - ("if" "IF" simula-expand-keyword) - ("image" "Image" simula-expand-stdproc) - ("imagefile" "ImageFile" simula-expand-stdproc) - ("imp" "IMP" simula-expand-keyword) - ("in" "IN" simula-expand-keyword) - ("inbyte" "InByte" simula-expand-stdproc) - ("inbytefile" "InByteFile" simula-expand-stdproc) - ("inchar" "InChar" simula-expand-stdproc) - ("infile" "InFile" simula-expand-stdproc) - ("infrac" "InFrac" simula-expand-stdproc) - ("inimage" "InImage" simula-expand-stdproc) - ("inint" "InInt" simula-expand-stdproc) - ("inner" "INNER" simula-expand-keyword) - ("inreal" "InReal" simula-expand-stdproc) - ("inrecord" "InRecord" simula-expand-stdproc) - ("inspect" "INSPECT" simula-expand-keyword) - ("integer" "INTEGER" simula-expand-keyword) - ("intext" "InText" simula-expand-stdproc) - ("into" "Into" simula-expand-stdproc) - ("is" "IS" simula-expand-keyword) - ("isochar" "ISOChar" simula-expand-stdproc) - ("isopen" "IsOpen" simula-expand-stdproc) - ("isorank" "ISORank" simula-expand-stdproc) - ("label" "LABEL" simula-expand-keyword) - ("last" "Last" simula-expand-stdproc) - ("lastitem" "LastItem" simula-expand-stdproc) - ("lastloc" "LastLoc" simula-expand-stdproc) - ("le" "LE" simula-expand-keyword) - ("length" "Length" simula-expand-stdproc) - ("letter" "Letter" simula-expand-stdproc) - ("line" "Line" simula-expand-stdproc) - ("linear" "Linear" simula-expand-stdproc) - ("linesperpage" "LinesPerPage" simula-expand-stdproc) - ("link" "Link" simula-expand-stdproc) - ("linkage" "Linkage" simula-expand-stdproc) - ("ln" "Ln" simula-expand-stdproc) - ("locate" "Locate" simula-expand-stdproc) - ("location" "Location" simula-expand-stdproc) - ("lock" "Lock" simula-expand-stdproc) - ("locked" "Locked" simula-expand-stdproc) - ("log10" "Log10" simula-expand-stdproc) - ("long" "LONG" simula-expand-keyword) - ("lowcase" "LowCase" simula-expand-stdproc) - ("lowerbound" "LowerBound" simula-expand-stdproc) - ("lowten" "LowTen" simula-expand-stdproc) - ("lt" "LT" simula-expand-keyword) - ("main" "Main" simula-expand-stdproc) - ("max" "Max" simula-expand-stdproc) - ("maxint" "MaxInt" simula-expand-stdproc) - ("maxlongreal" "MaxLongReal" simula-expand-stdproc) - ("maxloc" "MaxLoc" simula-expand-stdproc) - ("maxrank" "MaxRank" simula-expand-stdproc) - ("maxreal" "MaxReal" simula-expand-stdproc) - ("min" "Min" simula-expand-stdproc) - ("minint" "MinInt" simula-expand-stdproc) - ("minlongreal" "MinLongReal" simula-expand-stdproc) - ("minrank" "MinRank" simula-expand-stdproc) - ("minreal" "MinReal" simula-expand-stdproc) - ("mod" "Mod" simula-expand-stdproc) - ("more" "More" simula-expand-stdproc) - ("name" "NAME" simula-expand-keyword) - ("ne" "NE" simula-expand-keyword) - ("negexp" "NegExp" simula-expand-stdproc) - ("new" "NEW" simula-expand-keyword) - ("nextev" "NextEv" simula-expand-stdproc) - ("none" "NONE" simula-expand-keyword) - ("normal" "Normal" simula-expand-stdproc) - ("not" "NOT" simula-expand-keyword) - ("notext" "NOTEXT" simula-expand-keyword) - ("open" "Open" simula-expand-stdproc) - ("or" "OR" simula-expand-keyword) - ("otherwise" "OTHERWISE" simula-electric-keyword) - ("out" "Out" simula-expand-stdproc) - ("outbyte" "OutByte" simula-expand-stdproc) - ("outbytefile" "OutByteFile" simula-expand-stdproc) - ("outchar" "OutChar" simula-expand-stdproc) - ("outfile" "OutFile" simula-expand-stdproc) - ("outfix" "OutFix" simula-expand-stdproc) - ("outfrac" "OutFrac" simula-expand-stdproc) - ("outimage" "OutImage" simula-expand-stdproc) - ("outint" "OutInt" simula-expand-stdproc) - ("outreal" "OutReal" simula-expand-stdproc) - ("outrecord" "OutRecord" simula-expand-stdproc) - ("outtext" "OutText" simula-expand-stdproc) - ("page" "Page" simula-expand-stdproc) - ("passivate" "Passivate" simula-expand-stdproc) - ("poisson" "Poisson" simula-expand-stdproc) - ("pos" "Pos" simula-expand-stdproc) - ("precede" "Precede" simula-expand-stdproc) - ("pred" "Pred" simula-expand-stdproc) - ("prev" "Prev" simula-expand-stdproc) - ("printfile" "PrintFile" simula-expand-stdproc) - ("prior" "PRIOR" simula-expand-keyword) - ("procedure" "PROCEDURE" simula-expand-keyword) - ("process" "Process" simula-expand-stdproc) - ("protected" "PROTECTED" simula-expand-keyword) - ("putchar" "PutChar" simula-expand-stdproc) - ("putfix" "PutFix" simula-expand-stdproc) - ("putfrac" "PutFrac" simula-expand-stdproc) - ("putint" "PutInt" simula-expand-stdproc) - ("putreal" "PutReal" simula-expand-stdproc) - ("qua" "QUA" simula-expand-keyword) - ("randint" "RandInt" simula-expand-stdproc) - ("rank" "Rank" simula-expand-stdproc) - ("reactivate" "REACTIVATE" simula-expand-keyword) - ("real" "REAL" simula-expand-keyword) - ("ref" "REF" simula-expand-keyword) - ("resume" "Resume" simula-expand-stdproc) - ("setaccess" "SetAccess" simula-expand-stdproc) - ("setpos" "SetPos" simula-expand-stdproc) - ("short" "SHORT" simula-expand-keyword) - ("sign" "Sign" simula-expand-stdproc) - ("simset" "SimSet" simula-expand-stdproc) - ("simulaid" "SimulaId" simula-expand-stdproc) - ("simulation" "Simulation" simula-expand-stdproc) - ("sin" "Sin" simula-expand-stdproc) - ("sinh" "SinH" simula-expand-stdproc) - ("sourceline" "SourceLine" simula-expand-stdproc) - ("spacing" "Spacing" simula-expand-stdproc) - ("sqrt" "Sqrt" simula-expand-stdproc) - ("start" "Start" simula-expand-stdproc) - ("step" "STEP" simula-expand-keyword) - ("strip" "Strip" simula-expand-stdproc) - ("sub" "Sub" simula-expand-stdproc) - ("subepsilon" "SubEpsilon" simula-expand-stdproc) - ("suc" "Suc" simula-expand-stdproc) - ("switch" "SWITCH" simula-expand-keyword) - ("sysin" "SysIn" simula-expand-stdproc) - ("sysout" "SysOut" simula-expand-stdproc) - ("tan" "Tan" simula-expand-stdproc) - ("tanh" "TanH" simula-expand-stdproc) - ("terminate_program" "Terminate_Program" simula-expand-stdproc) - ("terminated" "Terminated" simula-expand-stdproc) - ("text" "TEXT" simula-expand-keyword) - ("then" "THEN" simula-electric-keyword) - ("this" "THIS" simula-expand-keyword) - ("time" "Time" simula-expand-stdproc) - ("to" "TO" simula-expand-keyword) - ("true" "TRUE" simula-expand-keyword) - ("uniform" "Uniform" simula-expand-stdproc) - ("unlock" "Unlock" simula-expand-stdproc) - ("until" "UNTIL" simula-expand-keyword) - ("upcase" "Upcase" simula-expand-stdproc) - ("upperbound" "UpperBound" simula-expand-stdproc) - ("value" "VALUE" simula-expand-keyword) - ("virtual" "VIRTUAL" simula-expand-keyword) - ("wait" "Wait" simula-expand-stdproc) - ("when" "WHEN" simula-electric-keyword) - ("while" "WHILE" simula-expand-keyword)))) - -;;; simula.el ends here diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el deleted file mode 100644 index 02466483e19..00000000000 --- a/lisp/progmodes/tcl.el +++ /dev/null @@ -1,1816 +0,0 @@ -;; tcl.el --- Tcl code editing commands for Emacs - -;; Copyright (C) 1994 Free Software Foundation, Inc. - -;; Maintainer: Tom Tromey <tromey@busco.lanl.gov> -;; Author: Tom Tromey <tromey@busco.lanl.gov> -;; Chris Lindblad <cjl@lcs.mit.edu> -;; Keywords: languages tcl modes -;; Version: $Revision: 1.4 $ - -;; 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 1, 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. - -;; 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, 675 Mass Ave, Cambridge, MA 02139, USA. - -;; HOW TO INSTALL: -;; Put the following forms in your .emacs to enable autoloading of Tcl -;; mode, and auto-recognition of ".tcl" files. -;; -;; (autoload 'tcl-mode "tcl" "Tcl mode." t) -;; (autoload 'inferior-tcl "tcl" "Run inferior Tcl process." t) -;; (setq auto-mode-alist (append '(("\\.tcl$" . tcl-mode)) auto-mode-alist)) -;; -;; If you plan to use the interface to the TclX help files, you must -;; set the variable tcl-help-directory to point to the topmost -;; directory containing the TclX help files. Eg: -;; -;; (setq tcl-help-directory "/usr/local/lib/tclx/help") -;; -;; Also you will want to add the following to your .emacs: -;; -;; (autoload 'tcl-help-on-word "tcl" "Help on Tcl commands" t) -;; -;; FYI a *very* useful thing to do is nroff all the Tk man pages and -;; put them in a subdir of the help system. -;; - -;;; Commentary: - -;; LCD Archive Entry: -;; tcl|Tom Tromey|tromey@busco.lanl.gov| -;; Major mode for editing Tcl| -;; $Date: 1994/04/07 00:23:36 $|$Revision: 1.4 $|~/modes/tcl.el.Z| - -;; CUSTOMIZATION NOTES: -;; * tcl-proc-list can be used to customize a list of things that -;; "define" other things. Eg in my project I put "defvar" in this -;; list. -;; * tcl-typeword-list is similar, but uses font-lock-type-face. -;; * tcl-keyword-list is a list of keywords. I've generally used this -;; for flow-control words. Eg I add "unwind_protect" to this list. -;; * tcl-type-alist can be used to minimally customize indentation -;; according to context. - -;; Change log: -;; 18-Mar-1994 Tom Tromey Fourth beta release. -;; Added {un,}comment-region to menu. Idea from -;; Mike Scheidler <c23mts@kocrsv01.delcoelect.com> -;; 17-Mar-1994 Tom Tromey -;; Fixed tcl-restart-with-file. Bug fix attempt in -;; tcl-internal-end-of-defun. -;; 16-Mar-1994 Tom Tromey Third beta release -;; Added support code for menu (from Tcl mode written by -;; schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid)). -;; 12-Mar-1994 Tom Tromey -;; Better documentation for inferior-tcl-buffer. Wrote -;; tcl-restart-with-file. Wrote Lucid Emacs menu (but no -;; code to install it). -;; 12-Mar-1994 Tom Tromey -;; Wrote tcl-guess-application. Another stab at making -;; tcl-omit-ws-regexp work. -;; 10-Mar-1994 Tom Tromey Second beta release -;; Last Modified: Thu Mar 10 01:24:25 1994 (Tom Tromey) -;; Wrote perl-mode style line indentation command. -;; Wrote more documentation. Added tcl-continued-indent-level. -;; Integrated help code. -;; 8-Mar-1994 Tom Tromey -;; Last Modified: Tue Mar 8 11:58:44 1994 (Tom Tromey) -;; Bug fixes. -;; 6-Mar-1994 Tom Tromey -;; Last Modified: Sun Mar 6 18:55:41 1994 (Tom Tromey) -;; Updated auto-newline support. -;; 6-Mar-1994 Tom Tromey Beta release -;; Last Modified: Sat Mar 5 17:24:32 1994 (Tom Tromey) -;; Wrote tcl-hashify-buffer. Other minor bug fixes. -;; 5-Mar-1994 Tom Tromey -;; Last Modified: Sat Mar 5 16:11:20 1994 (Tom Tromey) -;; Wrote electric-hash code. -;; 3-Mar-1994 Tom Tromey -;; Last Modified: Thu Mar 3 02:53:40 1994 (Tom Tromey) -;; Added code to handle auto-fill in comments. -;; Added imenu support code. -;; Cleaned up code. -;; Better font-lock support. -;; 28-Feb-1994 Tom Tromey -;; Last Modified: Mon Feb 28 14:08:05 1994 (Tom Tromey) -;; Made tcl-figure-type more easily configurable. -;; 28-Feb-1994 Tom Tromey -;; Last Modified: Mon Feb 28 01:02:58 1994 (Tom Tromey) -;; Wrote inferior-tcl mode. -;; 16-Feb-1994 Tom Tromey -;; Last Modified: Wed Feb 16 17:05:19 1994 (Tom Tromey) -;; Added support for font-lock-mode. -;; 29-Oct-1993 Tom Tromey -;; Last Modified: Sun Oct 24 17:39:14 1993 (Tom Tromey) -;; Patches from Guido Bosch to make things work with Lucid Emacs. -;; 22-Oct-1993 Tom Tromey -;; Last Modified: Fri Oct 22 15:26:46 1993 (Tom Tromey) -;; Made many characters have "_" syntax class; suggested by Guido -;; Bosch <Guido.Bosch@loria.fr>. Note that this includes the "$" -;; character, which might be a change you'd notice. -;; 21-Oct-1993 Tom Tromey -;; Last Modified: Thu Oct 21 20:28:40 1993 (Tom Tromey) -;; More fixes for tcl-omit-ws-regexp. -;; 20-Oct-1993 Tom Tromey -;; Started keeping history. Fixed tcl-{beginning,end}-of-defun. -;; Added some code to make things work with Emacs 18. - -;; THANKS TO: -;; Guido Bosch <Guido.Bosch@loria.fr> -;; pgs1002@esc.cam.ac.uk (Dr P.G. Sjoerdsma) -;; Mike Scheidler <c23mts@kocrsv01.delcoelect.com> -;; Matt Newman <men@charney.colorado.edu> -;; rwhitby@research.canon.oz.au (Rod Whitby) -;; h9118101@hkuxa.hku.hk (Yip Chi Lap [Beta]) -;; Pertti Tapio Kasanen <ptk@delta.hut.fi> -;; schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid) - -;; KNOWN BUGS: -;; * indent-region should skip blank lines. (It does in v19, so I'm -;; not motivated to fix it here). -;; * In Tcl "#" is not always a comment character. This can confuse -;; tcl.el in certain circumstances. For now the only workaround is -;; to enclose offending hash characters in quotes or precede it with -;; a backslash. Note that using braces won't work -- quotes change -;; the syntax class of characters between them, while braces do not. -;; The electric-# mode helps alleviate this problem somewhat. -;; * indent-tcl-exp is untested. -;; * Doesn't work under Emacs 18 yet. -;; * There's been a report that font-lock does strange things under -;; Lucid Emacs 19.6. For instance in "proc foobar", the space -;; before "foobar" is highlighted. - -;; TODO: -;; * make add-log-tcl-defun smarter. should notice if we are in the -;; middle of a defun, or between defuns. should notice if point is -;; on first line of defun (or maybe even in comments before defun). -;; * Allow continuation lines to be indented under the first argument -;; of the preceeding line, like this: -;; [list something \ -;; something-else] -;; * There is a request that indentation work like this: -;; button .fred -label Fred \ -;; -command {puts fred} -;; * Should have tcl-complete-symbol that queries the inferior process. -;; * Should have describe-symbol that works by sending the magic -;; command to a tclX process. -;; * Need C-x C-e binding (tcl-eval-last-exp). -;; * Write indent-region function that is faster than indenting each -;; line individually. -;; * tcl-figure-type should stop at "beginning of line" (only ws -;; before point, and no "\" on previous line). (see tcl-real-command-p). -;; * Fix beginning-of-defun. I believe this will be fully possible in -;; FSF Emacs 19.23 -;; * overrides some comint keybindings; fix. -;; * Trailing \ will eat blank lines. Should deal with this. -;; (this would help catch some potential bugs). -;; * Inferior should display in half the screen, not the whole screen. - - - -;;; Code: - -(require 'comint) - -;; -;; User variables. -;; - -(defvar tcl-indent-level 4 - "*Indentation of Tcl statements with respect to containing block.") - -(defvar tcl-continued-indent-level 4 - "*Indentation of continuation line relative to first line of command.") - -(defvar tcl-auto-newline nil - "*Non-nil means automatically newline before and after braces -inserted in Tcl code.") - -(defvar tcl-tab-always-indent t - "*Control effect of TAB key. -If t (the default), always indent current line. -If nil and point is not in the indentation area at the beginning of -the line, a TAB is inserted. -Other values cause the first possible action from the following list -to take place: - - 1. Move from beginning of line to correct indentation. - 2. Delete an empty comment. - 3. Move forward to start of comment, indenting if necessary. - 4. Move forward to end of line, indenting if necessary. - 5. Create an empty comment. - 6. Move backward to start of comment, indenting if necessary.") - -(defvar tcl-use-hairy-comment-detector t - "*If not `nil', the the more complicated, but slower, comment -detecting function is used. This variable is only used in GNU Emacs -19 (the fast function is always used elsewhere).") - -(defvar tcl-electric-hash-style 'smart - "*Style of electric hash insertion to use. -Possible values are 'backslash, meaning that `\\' quoting should be -done; `quote, meaning that `\"' quoting should be done; 'smart, -meaning that the choice between 'backslash and 'quote should be -made depending on the number of hashes inserted; or nil, meaning that -no quoting should be done. Any other value for this variable is -taken to mean 'smart. The default is 'smart.") - -(defvar tcl-help-directory nil - "*Name of topmost directory containing TclX help files") - -(defvar tcl-use-smart-word-finder t - "*If not nil, use a better way of finding the current word when -looking up help on a Tcl command.") - -(defvar tcl-application "wish" - "*Name of Tcl application to run in inferior Tcl mode.") - -(defvar tcl-command-switches nil - "*Switches to supply to `tcl-application'.") - -(defvar tcl-prompt-regexp "^\\(% \\|\\)" - "*If not nil, a regexp that will match the prompt in the inferior process. -If nil, the prompt is the name of the application with \">\" appended. - -The default is \"^\\(% \\|\\)\", which will match the default primary -and secondary prompts for tclsh and wish.") - -(defvar inferior-tcl-source-command "source %s\n" - "*Format-string for building a Tcl command to load a file. -This format string should use `%s' to substitute a file name -and should result in a Tcl expression that will command the -inferior Tcl to load that file. The filename will be appropriately -quoted for Tcl.") - -;; -;; Keymaps, abbrevs, syntax tables. -;; - -(defvar tcl-mode-abbrev-table nil - "Abbrev table in use in Tcl-mode buffers.") -(if tcl-mode-abbrev-table - () - (define-abbrev-table 'tcl-mode-abbrev-table ())) - -;; I sure wish Emacs had a package that made it easy to extract this -;; sort of information. -(defconst tcl-using-emacs-19 (string-match "19\\." emacs-version) - "Nil unless using Emacs 19 (Lucid or FSF).") - -;; FIXME this will break on Emacs 19.100. -(defconst tcl-using-emacs-19.23 - (string-match "19\\.\\(2[3-9]\\|[3-9][0-9]\\)" emacs-version) - "Nil unless using Emacs 19.23 or later.") - -(defconst tcl-using-lemacs-19 (string-match "Lucid" emacs-version) - "Nil unless using Lucid Emacs).") - -(defvar tcl-mode-map () - "Keymap used in Tcl mode.") -(if tcl-mode-map - () - (setq tcl-mode-map (make-sparse-keymap)) - (define-key tcl-mode-map "{" 'tcl-electric-char) - (define-key tcl-mode-map "}" 'tcl-electric-brace) - (define-key tcl-mode-map "[" 'tcl-electric-char) - (define-key tcl-mode-map "]" 'tcl-electric-char) - (define-key tcl-mode-map ";" 'tcl-electric-char) - (define-key tcl-mode-map "#" 'tcl-electric-hash) - ;; FIXME. - (define-key tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun) - ;; FIXME. - (define-key tcl-mode-map "\e\C-e" 'tcl-end-of-defun) - ;; FIXME. - (define-key tcl-mode-map "\e\C-h" 'mark-tcl-function) - (define-key tcl-mode-map "\e\C-q" 'indent-tcl-exp) - (define-key tcl-mode-map "\177" 'backward-delete-char-untabify) - (define-key tcl-mode-map "\t" 'tcl-indent-command) - (define-key tcl-mode-map "\M-\C-x" 'tcl-eval-defun) - (and (fboundp 'comment-region) - (define-key tcl-mode-map "\C-c\C-c" 'comment-region)) - (define-key tcl-mode-map "\C-c\C-d" 'tcl-help-on-word) - (define-key tcl-mode-map "\C-c\C-e" 'tcl-eval-defun) - (define-key tcl-mode-map "\C-c\C-l" 'tcl-load-file) - (define-key tcl-mode-map "\C-c\C-p" 'inferior-tcl) - (define-key tcl-mode-map "\C-c\C-r" 'tcl-eval-region) - (define-key tcl-mode-map "\C-c\C-z" 'switch-to-tcl)) - -(defvar tcl-mode-syntax-table nil - "Syntax table in use in Tcl-mode buffers.") -(if tcl-mode-syntax-table - () - (setq tcl-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?% "_" tcl-mode-syntax-table) - (modify-syntax-entry ?@ "_" tcl-mode-syntax-table) - (modify-syntax-entry ?& "_" tcl-mode-syntax-table) - (modify-syntax-entry ?* "_" tcl-mode-syntax-table) - (modify-syntax-entry ?+ "_" tcl-mode-syntax-table) - (modify-syntax-entry ?- "_" tcl-mode-syntax-table) - (modify-syntax-entry ?. "_" tcl-mode-syntax-table) - (modify-syntax-entry ?: "_" tcl-mode-syntax-table) - (modify-syntax-entry ?! "_" tcl-mode-syntax-table) - (modify-syntax-entry ?$ "_" tcl-mode-syntax-table) ; FIXME use "'"? - (modify-syntax-entry ?/ "_" tcl-mode-syntax-table) - (modify-syntax-entry ?~ "_" tcl-mode-syntax-table) - (modify-syntax-entry ?< "_" tcl-mode-syntax-table) - (modify-syntax-entry ?= "_" tcl-mode-syntax-table) - (modify-syntax-entry ?> "_" tcl-mode-syntax-table) - (modify-syntax-entry ?| "_" tcl-mode-syntax-table) - (modify-syntax-entry ?\( "()" tcl-mode-syntax-table) - (modify-syntax-entry ?\) ")(" tcl-mode-syntax-table) - (modify-syntax-entry ?\; "." tcl-mode-syntax-table) - (modify-syntax-entry ?\n "> " tcl-mode-syntax-table) - (modify-syntax-entry ?\f "> " tcl-mode-syntax-table) - (modify-syntax-entry ?# "< " tcl-mode-syntax-table)) - -(defvar inferior-tcl-mode-map nil - "Keymap used in Inferior Tcl mode.") -(if inferior-tcl-mode-map - () - ;; FIXME Use keymap inheritance here? FIXME we override comint - ;; keybindings here. Maybe someone has a better set? - (setq inferior-tcl-mode-map (copy-keymap comint-mode-map)) - (define-key inferior-tcl-mode-map "\e\C-a" 'tcl-beginning-of-defun) - (define-key inferior-tcl-mode-map "\e\C-e" 'tcl-end-of-defun) - (define-key inferior-tcl-mode-map "\177" 'backward-delete-char-untabify) - (define-key inferior-tcl-mode-map "\M-\C-x" 'tcl-eval-defun) - (define-key inferior-tcl-mode-map "\C-c\C-d" 'tcl-help-on-word) - (define-key inferior-tcl-mode-map "\C-c\C-e" 'tcl-eval-defun) - (define-key inferior-tcl-mode-map "\C-c\C-l" 'tcl-load-file) - (define-key inferior-tcl-mode-map "\C-c\C-p" 'inferior-tcl) - (define-key inferior-tcl-mode-map "\C-c\C-r" 'tcl-eval-region) - (define-key inferior-tcl-mode-map "\C-c\C-z" 'switch-to-tcl)) - -;; Lucid Emacs menu. -(defvar tcl-lucid-menu - '("Tcl" - ["Beginning of function" tcl-beginning-of-defun t] - ["End of function" tcl-end-of-defun t] - ["Mark function" mark-tcl-function t] - ["Indent region" indent-region t] - ["Comment region" comment-region t] - ["Uncomment region" tcl-uncomment-region t] - "----" - ["Show Tcl process buffer" inferior-tcl t] - ["Send function to Tcl process" tcl-eval-defun t] - ["Send region to Tcl process" tcl-eval-region t] - ["Send file to Tcl process" tcl-load-file t] - ["Restart Tcl process with file" tcl-restart-with-file t] - "----" - ["Tcl help" tcl-help-on-word t])) - -(defvar inferior-tcl-buffer nil - "*The current inferior-tcl process buffer. - -MULTIPLE PROCESS SUPPORT -=========================================================================== -To run multiple Tcl processes, you start the first up with -\\[inferior-tcl]. It will be in a buffer named `*inferior-tcl*'. -Rename this buffer with \\[rename-buffer]. You may now start up a new -process with another \\[inferior-tcl]. It will be in a new buffer, -named `*inferior-tcl*'. You can switch between the different process -buffers with \\[switch-to-buffer]. - -Commands that send text from source buffers to Tcl processes -- like -`tcl-eval-defun' or `tcl-load-file' -- have to choose a process to -send to, when you have more than one Tcl process around. This is -determined by the global variable `inferior-tcl-buffer'. Suppose you -have three inferior Lisps running: - Buffer Process - foo inferior-tcl - bar inferior-tcl<2> - *inferior-tcl* inferior-tcl<3> -If you do a \\[tcl-eval-defun] command on some Lisp source code, what -process do you send it to? - -- If you're in a process buffer (foo, bar, or *inferior-tcl*), - you send it to that process. -- If you're in some other buffer (e.g., a source file), you - send it to the process attached to buffer `inferior-tcl-buffer'. -This process selection is performed by function `inferior-tcl-proc'. - -Whenever \\[inferior-tcl] fires up a new process, it resets -`inferior-tcl-buffer' to be the new process's buffer. If you only run -one process, this does the right thing. If you run multiple -processes, you can change `inferior-tcl-buffer' to another process -buffer with \\[set-variable].") - -;; -;; Hooks and other customization. -;; - -(defvar tcl-mode-hook nil - "Hook run on entry to Tcl mode. - -Several functions exist which are useful to run from your -`tcl-mode-hook' (see each function's documentation for more -information): - - tcl-install-menubar - Puts a \"Tcl\" menu on the menubar. Doesn't work in Emacs 18. - tcl-guess-application - Guesses a default setting for `tcl-application' based on any - \"#!\" line at the top of the file. - tcl-hashify-buffer - Quotes all \"#\" characters that don't correspond to actual - Tcl comments. (Useful when editing code not originally created - with this mode). - tcl-auto-fill-mode - Auto-filling of Tcl comments. - -Emacs 19 users can add functions to the hook with `add-hook': - - (add-hook 'tcl-mode-hook 'tcl-guess-application) - -Emacs 18 users must use `setq': - - (setq tcl-mode-hook (cons 'tcl-guess-application tcl-mode-hook))") - - -(defvar inferior-tcl-mode-hook nil - "Hook for customizing Inferior Tcl mode.") - -(defvar tcl-proc-list - '("proc") - "List of commands whose first argument defines something. -This exists because some people (eg, me) use \"defvar\" et al. -Call `tcl-set-proc-regexp' and `tcl-set-font-lock-keywords' -after changing this list.") - -(defvar tcl-proc-regexp nil - "Regexp to use when matching proc headers.") - -(defvar tcl-typeword-list - '("global" "upvar") - "List of Tcl keywords deonting \"type\". Used only for highlighting. -Call `tcl-set-font-lock-keywords' after changing this list.") - -;; Generally I've picked control operators to be keywords. -(defvar tcl-keyword-list - '("if" "then" "else" "elseif" "for" "foreach" "break" "continue" "while" - "eval" "case" "in" "switch" "default" "exit" "error" "proc" "return" - "uplevel" "loop" "for_array_keys" "for_recursive_glob" "for_file") - "List of Tcl keywords. Used only for highlighting. -Default list includes some TclX keywords. -Call `tcl-set-font-lock-keywords' after changing this list.") - -(defvar tcl-font-lock-keywords nil - "Keywords to highlight for Tcl. See variable `font-lock-keywords'. -This variable is generally set from `tcl-proc-regexp', -`tcl-typeword-list', and `tcl-keyword-list' by the function -`tcl-set-font-lock-keywords'.") - -;; FIXME need some way to recognize variables because array refs look -;; like 2 sexps. -(defvar tcl-type-alist - '( - ("expr" tcl-expr) - ("catch" tcl-commands) - ("if" tcl-expr "then" tcl-commands) - ("elseif" tcl-expr "then" tcl-commands) - ("elseif" tcl-expr tcl-commands) - ("if" tcl-expr tcl-commands) - ("while" tcl-expr tcl-commands) - ("for" tcl-commands tcl-expr tcl-commands tcl-commands) - ("foreach" nil nil tcl-commands) - ("for_file" nil nil tcl-commands) - ("for_array_keys" nil nil tcl-commands) - ("for_recursive_glob" nil nil nil tcl-commands) - ;; Loop handling is not perfect, because the third argument can be - ;; either a command or an expr, and there is no real way to look - ;; forward. - ("loop" nil tcl-expr tcl-expr tcl-commands) - ("loop" nil tcl-expr tcl-commands) - ) - "Alist that controls indentation. -\(Actually, this really only controls what happens on continuation lines). -Each entry looks like `(KEYWORD TYPE ...)'. -Each type entry describes a sexp after the keyword, and can be one of: -* nil, meaning that this sexp has no particular type. -* tcl-expr, meaning that this sexp is an arithmetic expression. -* tcl-commands, meaning that this sexp holds Tcl commands. -* a string, which must exactly match the string at the corresponding - position for a match to be made. - -For example, the entry for the \"loop\" command is: - - (\"loop\" nil tcl-expr tcl-commands) - -This means that the \"loop\" command has three arguments. The first -argument is ignored (for indentation purposes). The second argument -is a Tcl expression, and the last argument is Tcl commands.") - -(defvar tcl-explain-indentation nil - "If not `nil', debugging message will be printed during indentation.") - - - -;; -;; Work around differences between various versions of Emacs. -;; - -;; We use this because Lemacs 19.9 has what we need. -(defconst tcl-pps-has-arg-6 - (or tcl-using-emacs-19 - (and tcl-using-lemacs-19 - (condition-case nil - (progn - (parse-partial-sexp (point) (point) nil nil nil t) - t) - (error nil)))) - "t if using an emacs which supports sixth (\"commentstop\") argument -to parse-partial-sexp.") - -;; Its pretty bogus to have to do this, but there is no easier way to -;; say "match not syntax-1 and not syntax-2". Too bad you can't put -;; \s in [...]. This sickness is used in Emacs 19 to match a defun -;; starter. (It is used for this in v18 as well). -;;(defconst tcl-omit-ws-regexp -;; (concat "^\\(\\s" -;; (mapconcat 'char-to-string "w_.()\"\\$'/" "\\|\\s") -;; "\\)\\S(*") -;; "Regular expression that matches everything except space, comment -;;starter, and comment ender syntax codes.") - -;; FIXME? Instead of using the hairy regexp above, we just use a -;; simple one. -;;(defconst tcl-omit-ws-regexp "^[^] \t\n#}]\\S(*" -;; "Regular expression used in locating function definitions.") - -;; Here's another stab. I think this one actually works. Now the -;; problem seems to be that there is a bug in Emacs 19.22 where -;; end-of-defun doesn't really use the brace matching the one that -;; trails defun-prompt-regexp. -(defconst tcl-omit-ws-regexp "^[^ \t\n#}][^\n}]+}*[ \t]+") - -(defun tcl-internal-beginning-of-defun (&optional arg) - "Move backward to next beginning-of-defun. -With argument, do this that many times. -Returns t unless search stops due to end of buffer." - (interactive "p") - (if (or (null arg) (= arg 0)) - (setq arg 1)) - (let (success) - (while (progn - (setq arg (1- arg)) - (and (>= arg 0) - (setq success - (re-search-backward tcl-omit-ws-regexp nil 'move 1)))) - (while (and (looking-at "[]#}]") - (setq success - (re-search-backward tcl-omit-ws-regexp nil 'move 1))))) - (beginning-of-line) - (not (null success)))) - -(defun tcl-internal-end-of-defun (&optional arg) - "Move forward to next end of defun. -An end of a defun is found by moving forward from the beginning of one." - (interactive "p") - (if (or (null arg) (= arg 0)) (setq arg 1)) - (let ((start (point))) - ;; Was forward-char. I think this works a little better. - (forward-line) - (tcl-beginning-of-defun) - (while (> arg 0) - (while (and (re-search-forward tcl-omit-ws-regexp nil 'move 1) - (progn (beginning-of-line) t) - (looking-at "[]#}]") - (progn (forward-line) t))) - (let ((next-line (save-excursion - (forward-line) - (point)))) - (while (< (point) next-line) - (forward-sexp))) - (forward-line) - (if (> (point) start) (setq arg (1- arg)))))) - -;; In Emacs 19, we can use begining-of-defun as long as we set up a -;; certain regexp. In Emacs 18, we need our own function. -(fset 'tcl-beginning-of-defun - (if tcl-using-emacs-19 - 'beginning-of-defun - 'tcl-internal-beginning-of-defun)) - -;; Only FSF Emacs 19 works correctly using end-of-defun. Emacs 18 and -;; Lucid need our own function. -(fset 'tcl-end-of-defun - (if (and tcl-using-emacs-19 (not tcl-using-lemacs-19)) - 'end-of-defun - 'tcl-internal-end-of-defun)) - - - -;; -;; Some helper functions. -;; - -(defun tcl-set-proc-regexp () - "Set `tcl-proc-regexp' from variable `tcl-proc-list'." - (setq tcl-proc-regexp (concat "^\\(" - (mapconcat 'identity tcl-proc-list "\\|") - "\\)[ \t]+"))) - -(defun tcl-set-font-lock-keywords () - "Set `tcl-font-lock-keywords'. -Uses variables `tcl-proc-regexp' and `tcl-keyword-list'." - (setq tcl-font-lock-keywords - (list - ;; Names of functions (and other "defining things"). - (list (concat tcl-proc-regexp "\\([^ \t\n]+\\)") - 2 'font-lock-function-name-face) - - ;; Names of type-defining things. - (list (concat "\\(\\s-\\|^\\)\\(" - ;; FIXME Use 'regexp-quote? - (mapconcat 'identity tcl-typeword-list "\\|") - "\\)\\(\\s-\\|$\\)") - 2 'font-lock-type-face) - - ;; Keywords. Only recognized if surrounded by whitespace. - ;; FIXME consider using "not word or symbol", not - ;; "whitespace". - (cons (concat "\\(\\s-\\|^\\)\\(" - ;; FIXME Use regexp-quote? - (mapconcat 'identity tcl-keyword-list "\\|") - "\\)\\(\\s-\\|$\\)") - 2) - ))) - -(if tcl-proc-regexp - () - (tcl-set-proc-regexp)) - -(if tcl-font-lock-keywords - () - (tcl-set-font-lock-keywords)) - - - -;; -;; The mode itself. -;; - -(defun tcl-mode () - "Major mode for editing Tcl code. -Expression and list commands understand all Tcl brackets. -Tab indents for Tcl code. -Paragraphs are separated by blank lines only. -Delete converts tabs to spaces as it moves back. - -Variables controlling indentation style: - tcl-indent-level - Indentation of Tcl statements within surrounding block. - tcl-continued-indent-level - Indentation of continuation line relative to first line of command. - -Variables controlling user interaction with mode (see variable -documentation for details): - tcl-tab-always-indent - Controls action of TAB key. - tcl-auto-newline - Non-nil means automatically newline before and after braces, brackets, - and semicolons inserted in Tcl code. - tcl-electric-hash-style - Controls action of `#' key. - tcl-use-hairy-comment-detector - If t, use more complicated, but slower, comment detector. - This variable is only used in GNU Emacs 19. - -Turning on Tcl mode calls the value of the variable `tcl-mode-hook' -with no args, if that value is non-nil. Read the documentation for -`tcl-mode-hook' to see what kinds of interesting hook functions -already exist. - -Commands: -\\{tcl-mode-map}" - (interactive) - (kill-all-local-variables) - (use-local-map tcl-mode-map) - (setq major-mode 'tcl-mode) - (setq mode-name "Tcl") - (setq local-abbrev-table tcl-mode-abbrev-table) - (set-syntax-table tcl-mode-syntax-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'tcl-indent-line) - ;; Tcl doesn't require a final newline. - ;; (make-local-variable 'require-final-newline) - ;; (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "# ") - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "#+ *") - (make-local-variable 'comment-column) - (setq comment-column 40) - (make-local-variable 'comment-end) - (setq comment-end "") - (make-local-variable 'font-lock-keywords) - (setq font-lock-keywords tcl-font-lock-keywords) - (setq imenu-create-index-function 'tcl-imenu-create-index-function) - (make-local-variable 'parse-sexp-ignore-comments) - (if tcl-using-emacs-19 - (progn - ;; This can only be set to t in Emacs 19 and Lucid Emacs. - ;; Emacs 18 and Epoch lose. - (setq parse-sexp-ignore-comments t) - ;; Lucid Emacs has defun-prompt-regexp, but I don't believe - ;; that it works for end-of-defun -- only for - ;; beginning-of-defun. - (make-local-variable 'defun-prompt-regexp) - (setq defun-prompt-regexp tcl-omit-ws-regexp) - ;; The following doesn't work in Lucid Emacs 19.6, but maybe - ;; it will appear in later versions. - (make-local-variable 'add-log-current-defun-function) - (setq add-log-current-defun-function 'add-log-tcl-defun)) - (setq parse-sexp-ignore-comments nil)) - (run-hooks 'tcl-mode-hook)) - - - -;; This is used for braces, brackets, and semi (except for closing -;; braces, which are handled specially). -(defun tcl-electric-char (arg) - "Insert character and correct line's indentation." - (interactive "p") - ;; Indent line first; this looks better if parens blink. - (tcl-indent-line) - (self-insert-command arg) - (if (and tcl-auto-newline (= last-command-char ?\;)) - (progn - (newline) - (tcl-indent-line)))) - -;; This is used for closing braces. If tcl-auto-newline is set, can -;; insert a newline both before and after the brace, depending on -;; context. FIXME should this be configurable? Does anyone use this? -(defun tcl-electric-brace (arg) - "Insert character and correct line's indentation." - (interactive "p") - ;; If auto-newlining and there is stuff on the same line, insert a - ;; newline first. - (if tcl-auto-newline - (progn - (if (save-excursion - (skip-chars-backward " \t") - (bolp)) - () - (tcl-indent-line) - (newline)) - ;; In auto-newline case, must insert a newline after each - ;; brace. So an explicit loop is needed. - (while (> arg 0) - (insert last-command-char) - (tcl-indent-line) - (newline) - (setq arg (1- arg)))) - (self-insert-command arg)) - (tcl-indent-line)) - - - -(defun tcl-indent-command (&optional arg) - "Indent current line as Tcl code, or in some cases insert a tab character. -If tcl-tab-always-indent is t (the default), always indent current line. -If tcl-tab-always-indent is nil and point is not in the indentation -area at the beginning of the line, a TAB is inserted. -Other values of tcl-tab-always-indent cause the first possible action -from the following list to take place: - - 1. Move from beginning of line to correct indentation. - 2. Delete an empty comment. - 3. Move forward to start of comment, indenting if necessary. - 4. Move forward to end of line, indenting if necessary. - 5. Create an empty comment. - 6. Move backward to start of comment, indenting if necessary." - (interactive "p") - (cond - ((not tcl-tab-always-indent) - ;; Indent if in identation area, otherwise insert TAB. - (if (<= (current-column) (current-indentation)) - (tcl-indent-line) - (self-insert-command arg))) - ((eq tcl-tab-always-indent t) - ;; Always indent. - (tcl-indent-line)) - (t - ;; "Perl-mode" style TAB command. - (let* ((ipoint (point)) - (eolpoint (progn - (end-of-line) - (point))) - (comment-p (tcl-in-comment))) - (cond - ((= ipoint (save-excursion - (beginning-of-line) - (point))) - (beginning-of-line) - (tcl-indent-line) - ;; If indenting didn't leave us in column 0, go to the - ;; indentation. Otherwise leave point at end of line. This - ;; is a hack. - (if (= (point) (save-excursion - (beginning-of-line) - (point))) - (end-of-line) - (back-to-indentation))) - ((and comment-p (looking-at "[ \t]*$")) - ;; Empty comment, so delete it. We also delete any ";" - ;; characters at the end of the line. I think this is - ;; friendlier, but I don't know how other people will feel. - (backward-char) - (skip-chars-backward " \t;") - (delete-region (point) eolpoint)) - ((and comment-p (< ipoint (point))) - ;; Before comment, so skip to it. - (tcl-indent-line) - (indent-for-comment)) - ((/= ipoint eolpoint) - ;; Go to end of line (since we're not there yet). - (goto-char eolpoint) - (tcl-indent-line)) - ((not comment-p) - ;; Create an empty comment (since there isn't one on this - ;; line). If line is not blank, make sure we insert a ";" - ;; first. - (beginning-of-line) - (if (/= (point) eolpoint) - (progn - (goto-char eolpoint) - (or (tcl-real-command-p) - (insert ";")))) - (tcl-indent-line) - (indent-for-comment)) - (t - ;; Go to start of comment. We don't leave point where it is - ;; because we want to skip comment-start-skip. - (tcl-indent-line) - (indent-for-comment))))))) - -(defun tcl-indent-line () - "Indent current line as Tcl code. -Return the amount the indentation changed by." - (let ((indent (calculate-tcl-indent nil)) - beg shift-amt - (case-fold-search nil) - (pos (- (point-max) (point)))) - (beginning-of-line) - (setq beg (point)) - (cond ((eq indent nil) - (setq indent (current-indentation))) - (t - (skip-chars-forward " \t") - (if (listp indent) (setq indent (car indent))) - (cond ((= (following-char) ?}) - (setq indent (- indent tcl-indent-level))) - ((= (following-char) ?\]) - (setq indent (- indent 1)))))) - (skip-chars-forward " \t") - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - (delete-region beg (point)) - (indent-to indent) - ;; If initial point was within line's indentation, - ;; position after the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos)))) - shift-amt)) - -(defun tcl-figure-type () - "Determine type of sexp at point. -This is either 'tcl-expr, 'tcl-commands, or nil. Puts point at start -of sexp that indicates types. - -See documentation for variable `tcl-type-alist' for more information." - (let ((count 0) - result - word-stack) - (while (and (< count 5) - (not result)) - (condition-case nil - (progn - ;; FIXME should use "tcl-backward-sexp", which would skip - ;; over entire variables, etc. - (backward-sexp) - (if (looking-at "[a-zA-Z_]+") - (let ((list tcl-type-alist) - entry) - (setq word-stack (cons (current-word) word-stack)) - (while (and list (not result)) - (setq entry (car list)) - (setq list (cdr list)) - (let ((index 0)) - (while (and entry (<= index count)) - ;; Abort loop if string does not match word on - ;; stack. - (and (stringp (car entry)) - (not (string= (car entry) - (nth index word-stack))) - (setq entry nil)) - (setq entry (cdr entry)) - (setq index (1+ index))) - (and (> index count) - (not (stringp (car entry))) - (setq result (car entry))) - ))) - (setq word-stack (cons nil word-stack)))) - (error nil)) - (setq count (1+ count))) - (and tcl-explain-indentation - (message "Indentation type %s" result)) - result)) - -(defun calculate-tcl-indent (&optional parse-start) - "Return appropriate indentation for current line as Tcl code. -In usual case returns an integer: the column to indent to. -Returns nil if line starts inside a string, t if in a comment." - (save-excursion - (beginning-of-line) - (let* ((indent-point (point)) - (case-fold-search nil) - (continued-line - (save-excursion - (if (bobp) - nil - (backward-char) - (= ?\\ (preceding-char))))) - (continued-indent-value (if continued-line - tcl-continued-indent-level - 0)) - state - containing-sexp - found-next-line) - (if parse-start - (goto-char parse-start) - (tcl-beginning-of-defun)) - (while (< (point) indent-point) - (setq parse-start (point)) - (setq state (parse-partial-sexp (point) indent-point 0)) - (setq containing-sexp (car (cdr state)))) - (cond ((or (nth 3 state) (nth 4 state)) - ;; Inside comment or string. Return nil or t if should - ;; not change this line - (nth 4 state)) - ((null containing-sexp) - ;; Line is at top level. - continued-indent-value) - (t - ;; Set expr-p if we are looking at the expression part of - ;; an "if", "expr", etc statement. Set commands-p if we - ;; are looking at the body part of an if, while, etc - ;; statement. FIXME Should check for "for" loops here. - (goto-char containing-sexp) - (let* ((sexpr-type (tcl-figure-type)) - (expr-p (eq sexpr-type 'tcl-expr)) - (commands-p (eq sexpr-type 'tcl-commands)) - (expr-start (point))) - ;; Find the first statement in the block and indent - ;; like it. The first statement in the block might be - ;; on the same line, so what we do is skip all - ;; "virtually blank" lines, looking for a non-blank - ;; one. A line is virtually blank if it only contains - ;; a comment and whitespace. FIXME continued comments - ;; aren't supported. They are a wart on Tcl anyway. - ;; We do it this funky way because we want to know if - ;; we've found a statement on some line _after_ the - ;; line holding the sexp opener. - (goto-char containing-sexp) - (forward-char) - (if (and (< (point) indent-point) - (looking-at "[ \t]*\\(#.*\\)?$")) - (progn - (forward-line) - (while (and (< (point) indent-point) - (looking-at "[ \t]*\\(#.*\\)?$")) - (setq found-next-line t) - (forward-line)))) - (if (or continued-line - (/= (char-after containing-sexp) ?{) - expr-p) - (progn - ;; Line is continuation line, or the sexp opener - ;; is not a curly brace, or we are are looking at - ;; an `expr' expression (which must be split - ;; specially). So indentation is column of first - ;; good spot after sexp opener (with some added - ;; in the continued-line case). If there is no - ;; nonempty line before the indentation point, we - ;; use the column of the character after the sexp - ;; opener. - (if (>= (point) indent-point) - (progn - (goto-char containing-sexp) - (forward-char)) - (skip-chars-forward " \t")) - (+ (current-column) continued-indent-value)) - ;; After a curly brace, and not a continuation line. - ;; So take indentation from first good line after - ;; start of block, unless that line is on the same - ;; line as the opening brace. In this case use the - ;; indentation of the opening brace's line, plus - ;; another indent step. If we are in the body part - ;; of an "if" or "while" then the indentation is - ;; taken from the line holding the start of the - ;; statement. - (if (and (< (point) indent-point) - found-next-line) - (current-indentation) - (if commands-p - (goto-char expr-start) - (goto-char containing-sexp)) - (+ (current-indentation) tcl-indent-level))))))))) - - - -(defun mark-tcl-function () - "Put mark at end of Tcl function, point at beginning." - (interactive) - (push-mark (point)) - (tcl-end-of-defun) - (if tcl-using-emacs-19 - (push-mark (point) nil t) - (push-mark (point))) - (tcl-beginning-of-defun) - (backward-paragraph)) - - - -(defun indent-tcl-exp () - "Indent each line of the Tcl grouping following point." - (interactive) - (let ((indent-stack (list nil)) - (contain-stack (list (point))) - (case-fold-search nil) - outer-loop-done inner-loop-done state ostate - this-indent last-sexp continued-line - (next-depth 0) - last-depth) - (save-excursion - (forward-sexp 1)) - (save-excursion - (setq outer-loop-done nil) - (while (and (not (eobp)) (not outer-loop-done)) - (setq last-depth next-depth) - ;; Compute how depth changes over this line - ;; plus enough other lines to get to one that - ;; does not end inside a comment or string. - ;; Meanwhile, do appropriate indentation on comment lines. - (setq inner-loop-done nil) - (while (and (not inner-loop-done) - (not (and (eobp) (setq outer-loop-done t)))) - (setq ostate state) - (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) - nil nil state)) - (setq next-depth (car state)) - (if (and (car (cdr (cdr state))) - (>= (car (cdr (cdr state))) 0)) - (setq last-sexp (car (cdr (cdr state))))) - (if (or (nth 4 ostate)) - (tcl-indent-line)) - (if (or (nth 3 state)) - (forward-line 1) - (setq inner-loop-done t))) - (if (<= next-depth 0) - (setq outer-loop-done t)) - (if outer-loop-done - nil - ;; If this line had ..))) (((.. in it, pop out of the levels - ;; that ended anywhere in this line, even if the final depth - ;; doesn't indicate that they ended. - (while (> last-depth (nth 6 state)) - (setq indent-stack (cdr indent-stack) - contain-stack (cdr contain-stack) - last-depth (1- last-depth))) - (if (/= last-depth next-depth) - (setq last-sexp nil)) - ;; Add levels for any parens that were started in this line. - (while (< last-depth next-depth) - (setq indent-stack (cons nil indent-stack) - contain-stack (cons nil contain-stack) - last-depth (1+ last-depth))) - (if (null (car contain-stack)) - (setcar contain-stack - (or (car (cdr state)) - (save-excursion - (forward-sexp -1) - (point))))) - (forward-line 1) - (setq continued-line - (save-excursion - (backward-char) - (= (preceding-char) ?\\))) - (skip-chars-forward " \t") - (if (eolp) - nil - (if (and (car indent-stack) - (>= (car indent-stack) 0)) - ;; Line is on an existing nesting level. - (setq this-indent (car indent-stack)) - ;; Just started a new nesting level. - ;; Compute the standard indent for this level. - (let ((val (calculate-tcl-indent - (if (car indent-stack) - (- (car indent-stack)))))) - (setcar indent-stack - (setq this-indent val)) - (setq continued-line nil))) - (cond ((not (numberp this-indent))) - ((= (following-char) ?}) - (setq this-indent (- this-indent tcl-indent-level))) - ((= (following-char) ?\]) - (setq this-indent (- this-indent 1)))) - ;; Put chosen indentation into effect. - (or (null this-indent) - (= (current-column) - (if continued-line - (+ this-indent tcl-indent-level) - this-indent)) - (progn - (delete-region (point) (progn (beginning-of-line) (point))) - (indent-to - (if continued-line - (+ this-indent tcl-indent-level) - this-indent))))))))) - ) - - - -;; -;; Interfaces to other packages. -;; - -(defun tcl-imenu-create-index-function () - "Generate alist of indices for imenu." - (let ((re (concat tcl-proc-regexp "\\([^ \t\n{]+\\)")) - alist) - (imenu-progress-message 0) - (goto-char (point-min)) - (while (re-search-forward re nil t) - (imenu-progress-message nil) - ;; Position on start of proc name, not beginning of line. - (setq alist (cons - (cons (buffer-substring (match-beginning 2) (match-end 2)) - (match-beginning 2)) - alist))) - (imenu-progress-message 100) - (nreverse alist))) - -;; FIXME Definition of function is very ad-hoc. Should use -;; tcl-beginning-of-defun. Also has incestuous knowledge about the -;; format of tcl-proc-regexp. -(defun add-log-tcl-defun () - "Return name of Tcl function point is in, or nil." - (save-excursion - (if (re-search-backward - (concat tcl-proc-regexp "\\([^ \t\n{]+\\)") nil t) - (buffer-substring (match-beginning 2) - (match-end 2))))) - - - -;; -;; Helper functions for inferior Tcl mode. -;; - -;; This exists to let us delete the prompt when commands are sent -;; directly to the inferior Tcl. See gud.el for an explanation of how -;; it all works (I took it from there). This stuff doesn't really -;; work as well as I'd like it to. But I don't believe there is -;; anything useful that can be done. -(defvar inferior-tcl-delete-prompt-marker nil) - -(defun tcl-filter (proc string) - (let ((inhibit-quit t)) - (save-excursion - (set-buffer (process-buffer proc)) - (goto-char (process-mark proc)) - ;; Delete prompt if requested. - (if (marker-buffer inferior-tcl-delete-prompt-marker) - (progn - (delete-region (point) inferior-tcl-delete-prompt-marker) - (set-marker inferior-tcl-delete-prompt-marker nil))))) - (comint-output-filter proc string)) - -(defun tcl-send-string (proc string) - (save-excursion - (set-buffer (process-buffer proc)) - (goto-char (process-mark proc)) - (beginning-of-line) - (if (looking-at comint-prompt-regexp) - (set-marker inferior-tcl-delete-prompt-marker (point)))) - (comint-send-string proc string)) - -(defun tcl-send-region (proc start end) - (save-excursion - (set-buffer (process-buffer proc)) - (goto-char (process-mark proc)) - (beginning-of-line) - (if (looking-at comint-prompt-regexp) - (set-marker inferior-tcl-delete-prompt-marker (point)))) - (comint-send-region proc start end)) - -(defun switch-to-tcl (eob-p) - "Switch to inferior Tcl process buffer. -With argument, positions cursor at end of buffer." - (interactive "P") - (if (get-buffer inferior-tcl-buffer) - (pop-to-buffer inferior-tcl-buffer) - (error "No current inferior Tcl buffer")) - (cond (eob-p - (push-mark) - (goto-char (point-max))))) - -(defun inferior-tcl-proc () - "Return current inferior Tcl process. -See variable `inferior-tcl-buffer'." - (let ((proc (get-buffer-process (if (eq major-mode 'inferior-tcl-mode) - (current-buffer) - inferior-tcl-buffer)))) - (or proc - (error "No Tcl process; see variable `inferior-tcl-buffer'")))) - -(defun tcl-eval-region (start end &optional and-go) - "Send the current region to the inferior Tcl process. -Prefix argument means switch to the Tcl buffer afterwards." - (interactive "r\nP") - (let ((proc (inferior-tcl-proc))) - (tcl-send-region proc start end) - (tcl-send-string proc "\n") - (if and-go (switch-to-tcl t)))) - -(defun tcl-eval-defun (&optional and-go) - "Send the current defun to the inferior Tcl process. -Prefix argument means switch to the Tcl buffer afterwards." - (interactive "P") - (save-excursion - (tcl-end-of-defun) - (let ((end (point))) - (tcl-beginning-of-defun) - (tcl-eval-region (point) end))) - (if and-go (switch-to-tcl t))) - - - -;; -;; Inferior Tcl mode itself. -;; - -(defun inferior-tcl-mode () - "Major mode for interacting with Tcl interpreter. - -A Tcl process can be started with M-x inferior-tcl. - -Entry to this mode runs the hooks comint-mode-hook and -inferior-tcl-mode-hook, in that order. - -You can send text to the inferior Tcl process from other buffers -containing Tcl source. - -Variables controlling Inferior Tcl mode: - tcl-application - Name of program to run. - tcl-command-switches - Command line arguments to `tcl-application'. - tcl-prompt-regexp - Matches prompt. - inferior-tcl-source-command - Command to use to read Tcl file in running application. - inferior-tcl-buffer - The current inferior Tcl process buffer. See variable - documentation for details on multiple-process support. - -The following commands are available: -\\{inferior-tcl-mode-map}" - (interactive) - (comint-mode) - (setq comint-prompt-regexp (or tcl-prompt-regexp - (concat "^" - (regexp-quote tcl-application) - ">"))) - (setq major-mode 'inferior-tcl-mode) - (setq mode-name "Inferior Tcl") - (setq mode-line-process '(": %s")) - (use-local-map inferior-tcl-mode-map) - (setq local-abbrev-table tcl-mode-abbrev-table) - (set-syntax-table tcl-mode-syntax-table) - (if tcl-using-emacs-19 - (progn - (make-local-variable 'defun-prompt-regexp) - (setq defun-prompt-regexp tcl-omit-ws-regexp))) - (make-local-variable 'inferior-tcl-delete-prompt-marker) - (setq inferior-tcl-delete-prompt-marker (make-marker)) - (set-process-filter (get-buffer-process (current-buffer)) 'tcl-filter) - (run-hooks 'inferior-tcl-mode-hook)) - -(defun inferior-tcl (cmd) - "Run inferior Tcl process. -Prefix arg means enter program name interactively. -See documentation for function `inferior-tcl-mode' for more information." - (interactive - (list (if current-prefix-arg - (read-string "Run Tcl: " tcl-application) - tcl-application))) - (if (not (comint-check-proc "*inferior-tcl*")) - (progn - (set-buffer (apply (function make-comint) "inferior-tcl" cmd nil - tcl-command-switches)) - (inferior-tcl-mode))) - (make-local-variable 'tcl-application) - (setq tcl-application cmd) - (setq inferior-tcl-buffer "*inferior-tcl*") - (switch-to-buffer "*inferior-tcl*")) - -(and (fboundp 'defalias) - (defalias 'run-tcl 'inferior-tcl)) - - - -;; -;; Auto-fill support. -;; - -(defun tcl-real-command-p () - "Return nil if point is not at the beginning of a command. -A command is the first word on an otherwise empty line, or the -first word following a semicolon, opening brace, or opening bracket." - (save-excursion - (skip-chars-backward " \t") - (cond - ((bobp) t) - ((bolp) - (backward-char) - ;; Note -- continued comments are not supported here. I - ;; consider those to be a wart on the language. - (not (eq ?\\ (preceding-char)))) - (t - (memq (preceding-char) '(?\; ?{ ?\[)))))) - -;; FIXME doesn't actually return t. See last case. -(defun tcl-real-comment-p () - "Return t if point is just after the `#' beginning a real comment. -Does not check to see if previous char is actually `#'. -A real comment is either at the beginning of the buffer, -preceeded only by whitespace on the line, or has a preceeding -semicolon, opening brace, or opening bracket on the same line." - (save-excursion - (backward-char) - (tcl-real-command-p))) - -(defun tcl-hairy-scan-for-comment (state end always-stop) - "Determine if point is in a comment. -Returns a list of the form `(FLAG . STATE)'. STATE can be used -as input to future invocations. FLAG is nil if not in comment, -t otherwise. If in comment, leaves point at beginning of comment. -Only works in Emacs 19. See also `tcl-simple-scan-for-comment', a -simpler version that is often right, and works in Emacs 18." - (let ((bol (save-excursion - (goto-char end) - (beginning-of-line) - (point))) - real-comment - last-cstart) - (while (and (not last-cstart) (< (point) end)) - (setq real-comment nil) ;In case we've looped around and it is - ;set. - (setq state (parse-partial-sexp (point) end nil nil state t)) - (if (nth 4 state) - (progn - ;; If ALWAYS-STOP is set, stop even if we don't have a - ;; real comment, or if the comment isn't on the same line - ;; as the end. - (if always-stop (setq last-cstart (point))) - ;; If we have a real comment, then set the comment - ;; starting point if we are on the same line as the ending - ;; location. - (setq real-comment (tcl-real-comment-p)) - (if real-comment - (progn - (and (> (point) bol) (setq last-cstart (point))) - ;; NOTE Emacs 19 has a misfeature whereby calling - ;; parse-partial-sexp with COMMENTSTOP set and with - ;; an initial list that says point is in a comment - ;; will cause an immediate return. So we must skip - ;; over the comment ourselves. - (beginning-of-line 2))) - ;; Frob the state to make it look like we aren't in a - ;; comment. - (setcar (nthcdr 4 state) nil)))) - (and last-cstart - (goto-char last-cstart)) - (cons real-comment state))) - -(defun tcl-hairy-in-comment () - "Return t if point is in a comment, and leave point at beginning -of comment." - (let ((save (point))) - (tcl-beginning-of-defun) - (car (tcl-hairy-scan-for-comment nil save nil)))) - -(defun tcl-simple-in-comment () - "Return t if point is in comment, and leave point at beginning -of comment. This is faster that `tcl-hairy-in-comment', but is -correct less often." - (let ((save (point)) - comment) - (beginning-of-line) - (while (and (< (point) save) (not comment)) - (search-forward "#" save 'move) - (setq comment (tcl-real-comment-p))) - comment)) - -(defun tcl-in-comment () - "Return t if point is in comment, and leave point at beginning -of comment." - (if (and tcl-pps-has-arg-6 - tcl-use-hairy-comment-detector) - (tcl-hairy-in-comment) - (tcl-simple-in-comment))) - -(defun tcl-do-auto-fill () - "Auto-fill function for Tcl mode. Only auto-fills in a comment." - (let (in-comment - col) - (save-excursion - (setq in-comment (tcl-in-comment)) - (if in-comment - (setq col (1- (current-column))))) - (if in-comment - (progn - (do-auto-fill) - (save-excursion - (back-to-indentation) - (delete-region (point) (save-excursion - (beginning-of-line) - (point))) - (indent-to-column col)))))) - - - -;; -;; Help-related code. -;; - -(defvar tcl-help-saved-dir nil - "Saved help directory. If `tcl-help-directory' changes, this allows -tcl-help-on-word to update the alist") - -(defvar tcl-help-alist nil - "Alist with command names as keys and filenames as values.") - -(defun tcl-help-snarf-commands (dir) - "Build alist of commands and filenames. There is probably a much -better implementation of this, but I'm too tired to think of it right -now." - (let ((files (directory-files dir t))) - (while files - (if (and (file-directory-p (car files)) - (not - (let ((fpart (file-name-nondirectory (car files)))) - (or (equal fpart ".") - (equal fpart ".."))))) - (let ((matches (directory-files (car files) t))) - (while matches - (or (file-directory-p (car matches)) - (setq tcl-help-alist - (cons - (cons (file-name-nondirectory (car matches)) - (car matches)) - tcl-help-alist))) - (setq matches (cdr matches))))) - (setq files (cdr files))))) - -(defun tcl-reread-help-files () - "Set up to re-read files, and then do it." - (interactive) - (message "Building Tcl help file index...") - (setq tcl-help-saved-dir tcl-help-directory) - (setq tcl-help-alist nil) - (tcl-help-snarf-commands tcl-help-directory) - (message "Building Tcl help file index...done")) - -(defun tcl-current-word (flag) - "Return current command word, or nil. -If FLAG is nil, just uses `current-word'. -Otherwise scans backward for most likely Tcl command word." - (if (and flag (eq major-mode 'tcl-mode)) - (condition-case nil - (save-excursion - ;; Look backward for first word actually in alist. - (if (bobp) - () - (while (and (not (bobp)) - (not (tcl-real-command-p))) - (backward-sexp))) - (if (assoc (current-word) tcl-help-alist) - (current-word))) - (error nil)) - (current-word))) - -(defun tcl-help-on-word (command &optional arg) - "Get help on Tcl command. Default is word at point. -Prefix argument means invert sense of `tcl-use-smart-word-finder'." - (interactive - (list - (progn - (if (not (string= tcl-help-directory tcl-help-saved-dir)) - (tcl-reread-help-files)) - (let ((word (tcl-current-word - (if current-prefix-arg - (not tcl-use-smart-word-finder) - tcl-use-smart-word-finder)))) - (completing-read - (if (or (null word) (string= word "")) - "Help on Tcl command: " - (format "Help on Tcl command (default %s): " word)) - tcl-help-alist nil t))) - current-prefix-arg)) - (if (not (string= tcl-help-directory tcl-help-saved-dir)) - (tcl-reread-help-files)) - (if (string= command "") - (setq command (tcl-current-word - (if arg - (not tcl-use-smart-word-finder) - tcl-use-smart-word-finder)))) - (let* ((help (get-buffer-create "*Tcl help*")) - (cell (assoc command tcl-help-alist)) - (file (and cell (cdr cell)))) - (set-buffer help) - (delete-region (point-min) (point-max)) - (if file - (progn - (insert "*** " command "\n\n") - (insert-file-contents file)) - (if (string= command "") - (insert "Magical Pig!") - (insert "Tcl command " command " not in help\n"))) - (set-buffer-modified-p nil) - (goto-char (point-min)) - (display-buffer help))) - - - -;; -;; Other interactive stuff. -;; - -(defvar tcl-previous-dir/file nil - "Record last directory and file used in loading. -This holds a cons cell of the form `(DIRECTORY . FILE)' -describing the last `tcl-load-file' command.") - -(defun tcl-load-file (file &optional and-go) - "Load a Tcl file into the inferior Tcl process. -Prefix argument means switch to the Tcl buffer afterwards." - (interactive - (list - ;; car because comint-get-source returns a list holding the - ;; filename. - (car (comint-get-source "Load Tcl file: " tcl-previous-dir/file - '(tcl-mode) t)) - current-prefix-arg)) - (comint-check-source file) - (setq tcl-previous-dir/file (cons (file-name-directory file) - (file-name-nondirectory file))) - (tcl-send-string (inferior-tcl-proc) - (format inferior-tcl-source-command (tcl-quote file))) - (if and-go (switch-to-tcl t))) - -;; Maybe this should work just like tcl-load-file. But I think what -;; I've implemented will turn out to be more useful. -(defun tcl-restart-with-file (file &optional and-go) - "Restart inferior Tcl with file. -If an inferior Tcl process exists, it is killed first. -Prefix argument means switch to the Tcl buffer afterwards." - (interactive - (list - (car (comint-get-source "Restart with Tcl file: " - (or (and - (eq major-mode 'tcl-mode) - (buffer-file-name)) - tcl-previous-dir/file) - '(tcl-mode) t)) - current-prefix-arg)) - (let* ((buf (if (eq major-mode 'inferior-tcl-mode) - (current-buffer) - inferior-tcl-buffer)) - (proc (and buf (get-process buf)))) - (cond - ((not (and buf (get-buffer buf))) - ;; I think this will be ok. - (inferior-tcl tcl-application) - (tcl-load-file file and-go)) - ((or - (not (comint-check-proc buf)) - (yes-or-no-p - "A Tcl process is running, are you sure you want to reset it? ")) - (save-excursion - (comint-check-source file) - (setq tcl-previous-dir/file (cons (file-name-directory file) - (file-name-nondirectory file))) - (comint-exec (get-buffer-create buf) - (if proc - (process-name proc) - "inferior-tcl") - tcl-application file tcl-command-switches) - (if and-go (switch-to-tcl t))))))) - -;; FIXME I imagine you can do this under Emacs 18. I just don't know -;; how. -(defun tcl-auto-fill-mode (&optional arg) - "Like `auto-fill-mode', but controls filling of Tcl comments." - (interactive "P") - (and (not tcl-using-emacs-19) - (error "You must use Emacs 19 to get this feature.")) - ;; Following code taken from "auto-fill-mode" (simple.el). - (prog1 - (setq auto-fill-function - (if (if (null arg) - (not auto-fill-function) - (> (prefix-numeric-value arg) 0)) - 'tcl-do-auto-fill - nil)) - ;; Update mode line. FIXME I'd use force-mode-line-update, but I - ;; don't know if it exists in v18. - (set-buffer-modified-p (buffer-modified-p)))) - -(defun tcl-electric-hash (&optional count) - "Insert a `#' and quote if it does not start a real comment. -Prefix arg is number of `#'s to insert. -See variable `tcl-electric-hash-style' for description of quoting -styles." - (interactive "p") - (or count (setq count 1)) - (if (> count 0) - (let ((type - (if (eq tcl-electric-hash-style 'smart) - (if (> count 3) ; FIXME what is "smart"? - 'quote - 'backslash) - tcl-electric-hash-style)) - comment) - (if type - (progn - (save-excursion - (insert "#") - (setq comment (tcl-in-comment))) - (delete-char 1) - (and tcl-explain-indentation (message "comment: %s" comment)) - (cond - ((eq type 'quote) - (if (not comment) - (insert "\""))) - ((eq type 'backslash) - ;; The following will set count to 0, so the - ;; insert-char can still be run. - (if (not comment) - (while (> count 0) - (insert "\\#") - (setq count (1- count))))) - (t nil)))) - (insert-char ?# count)))) - -(defun tcl-hashify-buffer () - "Quote all `#'s in current buffer that aren't Tcl comments." - (interactive) - (save-excursion - (goto-char (point-min)) - (if (and tcl-pps-has-arg-6 tcl-use-hairy-comment-detector) - (let (state - result) - (while (< (point) (point-max)) - (setq result (tcl-hairy-scan-for-comment state (point-max) t)) - (if (car result) - (beginning-of-line 2) - (backward-char) - (if (eq ?# (following-char)) - (insert "\\")) - (forward-char)) - (setq state (cdr result)))) - (while (and (< (point) (point-max)) - (search-forward "#" nil 'move)) - (if (tcl-real-comment-p) - (beginning-of-line 2) - ;; There's really no good way for the simple converter to - ;; work. So we just quote # if it isn't already quoted. - ;; Bogus, but it works. - (backward-char) - (if (not (eq ?\\ (preceding-char))) - (insert "\\")) - (forward-char)))))) - -;; The following was inspired by the Tcl editing mode written by -;; Gregor Schmid <schmid@fb3-s7.math.TU-Berlin.DE>. His version also -;; attempts to snarf the command line options from the command line, -;; but I didn't think that would really be that helpful (doesn't seem -;; like it owould be right enough. His version also looks for the -;; "#!/bin/csh ... exec" hack, but that seemed even less useful. -(defun tcl-guess-application () - "Attempt to guess Tcl application by looking at first line. -The first line is assumed to look like \"#!.../program ...\"." - (save-excursion - (goto-char (point-min)) - (if (looking-at "#![^ \t]*/\\([^ \t/]+\\)\\([ \t]\\|$\\)") - (progn - (make-local-variable 'tcl-application) - (setq tcl-application (buffer-substring (match-beginning 1) - (match-end 1))))))) - -;; This only exists to put on the menubar. I couldn't figure out any -;; other way to do it. FIXME should take "number of #-marks" -;; argument. -(defun tcl-uncomment-region (beg end) - "Uncomment region." - (interactive "r") - (comment-region beg end -1)) - - - -;; -;; Lucid menu support. -;; Taken from schmid@fb3-s7.math.TU-Berlin.DE (Gregor Schmid), -;; who wrote a different Tcl mode. -;; We also have simple support for menus in FSF. We do this by -;; loading the Lucid menu emulation code. -;; - -;; Put this into your tcl-mode-hook. -(defun tcl-install-menubar () - (and tcl-using-emacs-19 - (not tcl-using-lemacs-19) - (if tcl-using-emacs-19.23 - (require 'lmenu) - ;; CAVEATS: - ;; * lmenu.el provides 'menubar, which is bogus. - ;; * lmenu.el causes menubars to be turned on everywhere. - ;; Doubly bogus! - ;; Both of these problems are fixed in Emacs 19.23. People - ;; using an Emacs before that just suffer. - (require 'menubar "lmenu"))) - (if (not (assoc "Tcl" current-menubar)) - (progn - (set-buffer-menubar (copy-sequence current-menubar)) - (add-menu nil "Tcl" (cdr tcl-lucid-menu)))) - ;; You might want to do something like the below. I have it - ;; commented out because it overrides existing bindings. - ;; For Lucid: - ;; (define-key tcl-mode-map 'button3 'tcl-popup-menu) - ;; For FSF: - ;; (define-key tcl-mode-map [down-mouse-3] 'tcl-popup-menu) - ) - -(defun tcl-popup-menu (e) - (interactive "e") - (and tcl-using-emacs-19 - (not tcl-using-lemacs-19) - (if tcl-using-emacs-19.23 - (require 'lmenu) - ;; CAVEATS: - ;; * lmenu.el provides 'menubar, which is bogus. - ;; * lmenu.el causes menubars to be turned on everywhere. - ;; Doubly bogus! - ;; Both of these problems are fixed in Emacs 19.23. People - ;; using an Emacs before that just suffer. - (require 'menubar "lmenu"))) ;; This is annoying - ;;(mouse-set-point e) - ;; IMHO popup-menu should be autoloaded. Oh well. - (popup-menu tcl-lucid-menu)) - - - -;; -;; Quoting and unquoting functions. -;; - -;; This quoting is sufficient to protect eg a filename from any sort -;; of expansion or splitting. Tcl quoting sure sucks. -(defun tcl-quote (string) - "Quote STRING according to Tcl rules." - (mapconcat (function (lambda (char) - (if (memq char '(?[ ?] ?{ ?} ?\\ ?\" ?$ ? ?\;)) - (concat "\\" (char-to-string char)) - (char-to-string char)))) - string "")) - - - -(provide 'tcl) - -;;; tcl.el ends here |