diff options
Diffstat (limited to 'emacs')
-rw-r--r-- | emacs/cperl-mode | 710 | ||||
-rw-r--r-- | emacs/cperl-mode.el | 2566 | ||||
-rw-r--r-- | emacs/emacs19 | 312 | ||||
-rw-r--r-- | emacs/perl-mode.el | 631 | ||||
-rw-r--r-- | emacs/perldb.el | 423 | ||||
-rw-r--r-- | emacs/perldb.pl | 531 | ||||
-rw-r--r-- | emacs/tedstuff | 296 |
7 files changed, 2566 insertions, 2903 deletions
diff --git a/emacs/cperl-mode b/emacs/cperl-mode deleted file mode 100644 index eb4aae2ab6..0000000000 --- a/emacs/cperl-mode +++ /dev/null @@ -1,710 +0,0 @@ -Article 15212 of comp.lang.perl: -Path: netlabs!news.cerf.net!usc!howland.reston.ans.net!spool.mu.edu!umn.edu!news-feed-2.peachnet.edu!concert!duke!khera -From: khera@cs.duke.edu (Vivek Khera) -Newsgroups: comp.lang.perl -Subject: cperl-mode.el -Message-ID: <KHERA.93Oct21140851@thneed.cs.duke.edu> -Date: 21 Oct 93 18:08:51 GMT -Sender: news@duke.cs.duke.edu -Organization: Duke University CS Dept., Durham, NC -Lines: 694 -Nntp-Posting-Host: thneed.cs.duke.edu -X-Md4-Signature: 40dd9bccfb99794a9da2ee891b5bf557 -X-Md5-Signature: e4baa8cf00c94092ebf9712514e4696b - -Since I've received requests to do so, I'm posting the cperl-mode.el -file. This allows Emacs (both version 18 and 19) to do nice things -when editing Perl code. Indentation works well, and it doesn't get -confused like the perl-mode.el that comes with Emacs 19. - -Install this file as cperl-mode.el, and add the following to your -.emacs file: - -(autoload 'perl-mode "cperl-mode" "alternate mode for editing Perl programs" t) - -This cperl-mode.el is not exactly the same as when it was originally -posted here. I made the following changes: perl-mode is an alias for -cperl-mode, and the major mode name is perl-mode, not cperl-mode. -This is so it is easier to use with Emacs 19. I suppose one could -install this as perl-mode.el and then not have to put the autoload -line in (for Emacs 19). - -Anyway, I'm not maintaining this, so don't send me bugs. - ---cut here-- -;;; From: olson@mcs.anl.gov (Bob Olson) -;;; Newsgroups: comp.lang.perl -;;; Subject: cperl-mode: Another perl mode for Gnuemacs -;;; Date: 14 Aug 91 15:20:01 GMT - -;; Perl code editing commands for Emacs -;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. - -;; This file is part of GNU Emacs. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY. No author or distributor -;; accepts responsibility to anyone for the consequences of using it -;; or for whether it serves any particular purpose or works at all, -;; unless he says so in writing. Refer to the GNU Emacs General Public -;; License for full details. - -;; Everyone is granted permission to copy, modify and redistribute -;; GNU Emacs, but only under the conditions described in the -;; GNU Emacs General Public License. A copy of this license is -;; supposed to have been given to you along with GNU Emacs so you -;; can know your rights and responsibilities. It should be in a -;; file named COPYING. Among other things, the copyright notice -;; and this notice must be preserved on all copies. - - -(defvar cperl-mode-abbrev-table nil - "Abbrev table in use in Cperl-mode buffers.") -(define-abbrev-table 'cperl-mode-abbrev-table ()) - -(defvar cperl-mode-map () - "Keymap used in C mode.") -(if cperl-mode-map - () - (setq cperl-mode-map (make-sparse-keymap)) - (define-key cperl-mode-map "{" 'electric-cperl-brace) - (define-key cperl-mode-map "}" 'electric-cperl-brace) - (define-key cperl-mode-map ";" 'electric-cperl-semi) - (define-key cperl-mode-map ":" 'electric-cperl-terminator) - (define-key cperl-mode-map "\e\C-h" 'mark-cperl-function) - (define-key cperl-mode-map "\e\C-q" 'indent-cperl-exp) - (define-key cperl-mode-map "\177" 'backward-delete-char-untabify) - (define-key cperl-mode-map "\t" 'cperl-indent-command)) - -(autoload 'cperl-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 cperl-mode-syntax-table nil - "Syntax table in use in Cperl-mode buffers.") - -(if cperl-mode-syntax-table - () - (setq cperl-mode-syntax-table (make-syntax-table)) - (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table) - (modify-syntax-entry ?/ ". 14" cperl-mode-syntax-table) - (modify-syntax-entry ?* ". 23" cperl-mode-syntax-table) - (modify-syntax-entry ?+ "." cperl-mode-syntax-table) - (modify-syntax-entry ?- "." cperl-mode-syntax-table) - (modify-syntax-entry ?= "." cperl-mode-syntax-table) - (modify-syntax-entry ?% "." cperl-mode-syntax-table) - (modify-syntax-entry ?< "." cperl-mode-syntax-table) - (modify-syntax-entry ?> "." cperl-mode-syntax-table) - (modify-syntax-entry ?& "." cperl-mode-syntax-table) - (modify-syntax-entry ?| "." cperl-mode-syntax-table)) - - -(defvar cperl-indent-level 2 - "*Indentation of C statements with respect to containing block.") -(defvar cperl-brace-imaginary-offset 0 - "*Imagined indentation of a C open brace that actually follows a statement.") -(defvar cperl-brace-offset 0 - "*Extra indentation for braces, compared with other text in same context.") -(defvar cperl-argdecl-indent 5 - "*Indentation level of declarations of C function arguments.") -(defvar cperl-label-offset -2 - "*Offset of C label lines and case statements relative to usual indentation.") -(defvar cperl-continued-statement-offset 2 - "*Extra indent for lines not starting new statements.") -(defvar cperl-continued-brace-offset 0 - "*Extra indent for substatements that start with open-braces. -This is in addition to cperl-continued-statement-offset.") - -(defvar cperl-auto-newline nil - "*Non-nil means automatically newline before and after braces, -and after colons and semicolons, inserted in C code.") - -(defvar cperl-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.") - -;; provide an alias for working with emacs 19. the perl-mode that comes -;; with it is really bad, and this lets us seamlessly replace it. -(fset 'perl-mode 'cperl-mode) -(defun cperl-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. -\\{cperl-mode-map} -Variables controlling indentation style: - cperl-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. - cperl-auto-newline - Non-nil means automatically newline before and after braces, - and after colons and semicolons, inserted in C code. - cperl-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. - cperl-continued-statement-offset - Extra indentation given to a substatement, such as the - then-clause of an if or body of a while. - cperl-continued-brace-offset - Extra indentation given to a brace that starts a substatement. - This is in addition to cperl-continued-statement-offset. - cperl-brace-offset - Extra indentation for line if it starts with an open brace. - cperl-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. - cperl-argdecl-indent - Indentation level of declarations of C function arguments. - cperl-label-offset - Extra indentation for line that is a label, or case or default. - -Settings for K&R and BSD indentation styles are - cperl-indent-level 5 8 - cperl-continued-statement-offset 5 8 - cperl-brace-offset -5 -8 - cperl-argdecl-indent 0 8 - cperl-label-offset -5 -8 - -Turning on C mode calls the value of the variable cperl-mode-hook with no args, -if that value is non-nil." - (interactive) - (kill-all-local-variables) - (use-local-map cperl-mode-map) - (setq major-mode 'perl-mode) - (setq mode-name "CPerl") - (setq local-abbrev-table cperl-mode-abbrev-table) - (set-syntax-table cperl-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 'cperl-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-hook) - (setq comment-indent-hook 'cperl-comment-indent) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t) - (run-hooks 'cperl-mode-hook)) - -;; This is used by indent-for-comment -;; to decide how much to indent a comment in C code -;; based on its context. -(defun cperl-comment-indent () - (if (looking-at "^#") - 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-cperl-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 cperl-auto-newline (progn (cperl-indent-line) (newline) t) nil))) - (progn - (insert last-command-char) - (cperl-indent-line) - (if cperl-auto-newline - (progn - (newline) - ;; (newline) may have done auto-fill - (setq insertpos (- (point) 2)) - (cperl-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-cperl-semi (arg) - "Insert character and correct line's indentation." - (interactive "P") - (if cperl-auto-newline - (electric-cperl-terminator arg) - (self-insert-command (prefix-numeric-value arg)))) - -(defun electric-cperl-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 "case[ \t]")) - (save-excursion - (forward-word 1) - (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) - (cperl-indent-line) - (and cperl-auto-newline - (not (cperl-inside-parens-p)) - (progn - (newline) - (setq insertpos (- (point) 2)) - (cperl-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 cperl-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 cperl-indent-command (&optional whole-exp) - (interactive "P") - "Indent current line as C code, or in some cases insert a tab character. -If cperl-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 C - ;; and shift remaining lines of expression the same amount. - (let ((shift-amt (cperl-indent-line)) - beg end) - (save-excursion - (if cperl-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 cperl-tab-always-indent) - (save-excursion - (skip-chars-backward " \t") - (not (bolp)))) - (insert-tab) - (cperl-indent-line)))) - -(defun cperl-indent-line () - "Indent current line as C code. -Return the amount the indentation changed by." - (let ((indent (calculate-cperl-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-cperl-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 "case[ \t]") - (and (looking-at "[A-Za-z]") - (save-excursion - (forward-sexp 1) - (looking-at ":")))) - (setq indent (max 1 (+ indent cperl-label-offset)))) - ((and (looking-at "else\\b") - (not (looking-at "else\\s_"))) - (setq indent (save-excursion - (cperl-backward-to-start-of-if) - (current-indentation)))) - ((= (following-char) ?}) - (setq indent (- indent cperl-indent-level))) - ((= (following-char) ?{) - (setq indent (+ indent cperl-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-cperl-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 - (cperl-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 accordinglu. - (let ((basic-indent - (save-excursion - (re-search-backward "^[^ \^L\t\n#]" nil 'move) - (if (and (looking-at "\\sw\\|\\s_") - (looking-at ".*(") - (progn - (goto-char (1- (match-end 0))) - (forward-sexp 1) - (and (< (point) indent-point) - (not (memq (following-char) - '(?\, ?\;)))))) - cperl-argdecl-indent 0)))) - ;; Now add a little if this is a continuation line. - (+ basic-indent (if (or (bobp) - (memq (preceding-char) '(?\) ?\; ?\}))) - 0 cperl-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) - (cperl-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) ?\,) - (cperl-backward-to-start-of-continued-exp containing-sexp)) - (beginning-of-line) - (cperl-backward-to-noncomment containing-sexp)) - ;; Now we get the answer. - (if (not (memq (preceding-char) '(nil ?\, ?\; ?\} ?\{))) - ;; This line is continuation of preceding line's statement; - ;; indent cperl-continued-statement-offset more than the - ;; previous line of the statement. - (progn - (cperl-backward-to-start-of-continued-exp containing-sexp) - (+ cperl-continued-statement-offset (current-column) - (if (save-excursion (goto-char indent-point) - (skip-chars-forward " \t") - (eq (following-char) ?{)) - cperl-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) cperl-label-offset) - (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 cperl-indent-level is zero, - ;; use cperl-brace-offset + cperl-continued-statement-offset instead. - ;; For open-braces not the first thing in a line, - ;; add in cperl-brace-imaginary-offset. - (+ (if (and (bolp) (zerop cperl-indent-level)) - (+ cperl-brace-offset cperl-continued-statement-offset) - cperl-indent-level) - ;; Move back over whitespace before the openbrace. - ;; If openbrace is not first nonwhite thing on the line, - ;; add the cperl-brace-imaginary-offset. - (progn (skip-chars-backward " \t") - (if (bolp) 0 cperl-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-cperl-indent-within-comment () - "Return the indentation amount for line, assuming that -the current line is to be regarded as part of a block comment." - (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") - (and (re-search-forward "/\\*[ \t]*" end t) - star-start - (goto-char (1+ (match-beginning 0)))) - (current-column)))) - - -(defun cperl-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) - (beginning-of-line) - (skip-chars-forward " \t") - (setq stop (or (not (looking-at "#")) (<= (point) lim))) - (if stop (goto-char opoint) - (beginning-of-line)))))) - -(defun cperl-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")) - -(defun cperl-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 (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-cperl-function () - "Put mark at end of C function, point at beginning." - (interactive) - (push-mark (point)) - (end-of-defun) - (push-mark (point)) - (beginning-of-defun) - (backward-paragraph)) - -(defun indent-cperl-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 - 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 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)) - (cperl-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 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) ?{)) - (cperl-backward-to-noncomment opoint) - (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{))) - ;; Preceding line did not end in comma or semi; - ;; indent this line cperl-continued-statement-offset - ;; more than previous. - (progn - (cperl-backward-to-start-of-continued-exp (car contain-stack)) - (setq this-indent - (+ cperl-continued-statement-offset (current-column) - (if at-brace cperl-continued-brace-offset 0)))) - ;; Preceding line ended in comma or semi; - ;; use the standard indent for this level. - (if at-else - (progn (cperl-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-cperl-indent - (if (car indent-stack) - (- (car indent-stack)))))) - (setcar indent-stack - (setq this-indent val)))) - ;; Adjust line indentation according to its contents - (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 cperl-label-offset)))) - (if (= (following-char) ?}) - (setq this-indent (- this-indent cperl-indent-level))) - (if (= (following-char) ?{) - (setq this-indent (+ this-indent cperl-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))))))))) -; (message "Indenting C expression...done") - ) ---cut here-- --- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Vivek Khera, Gradual Student/Systems Guy Department of Computer Science -Internet: khera@cs.duke.edu Box 90129 - RIPEM/PGP/MIME spoken here Durham, NC 27708-0129 (919)660-6528 - - diff --git a/emacs/cperl-mode.el b/emacs/cperl-mode.el new file mode 100644 index 0000000000..5a400ef2b7 --- /dev/null +++ b/emacs/cperl-mode.el @@ -0,0 +1,2566 @@ +;;; This code started from the following message of long time ago (IZ): + +;;; From: olson@mcs.anl.gov (Bob Olson) +;;; Newsgroups: comp.lang.perl +;;; Subject: cperl-mode: Another perl mode for Gnuemacs +;;; Date: 14 Aug 91 15:20:01 GMT + +;; Perl code editing commands for Emacs +;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. + +;; This file is not (yet) 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. + +;;; Corrections made by Ilya Zakharevich ilya@math.mps.ohio-state.edu +;;; XEmacs changes by Peter Arius arius@informatik.uni-erlangen.de + +;; $Id: cperl-mode.el,v 1.15 1995/10/07 22:23:37 ilya Exp ilya $ + +;;; To use this mode put the following into your .emacs file: + +;; (autoload 'perl-mode "cperl-mode" "alternate mode for editing Perl programs" t) + +;;; You can either fine-tune the bells and whistles of this mode or +;;; bulk enable them by putting + +;; (setq cperl-hairy t) + +;;; in your .emacs file. (Emacs rulers do not consider it politically +;;; correct to make whistles enabled by default.) + +;;; Additional useful commands to put into your .emacs file: + +;; (setq auto-mode-alist +;; (append '(("\\.[pP][Llm]$" . perl-mode)) auto-mode-alist )) +;; (setq interpreter-mode-alist (append interpreter-mode-alist +;; '(("miniperl" . perl-mode)))) + +;;; The mode information (on C-h m) provides customization help. +;;; If you use font-lock feature of this mode, it is advisable to use +;;; eather lazy-lock-mode or fast-lock-mode (available on ELisp +;;; archive in files lazy-lock.el and fast-lock.el). I prefer lazy-lock. + +;;; Faces used now: three faces for first-class and second-class keywords +;;; and control flow words, one for each: comments, string, labels, +;;; functions definitions and packages, arrays, hashes, and variable +;;; definitions. If you do not see all these faces, your font-lock does +;;; not define them, so you need to define them manually. Maybe you have +;;; an obsolete font-lock from 19.28 or earlier. Upgrade. + +;;; If you have grayscale monitor, and do not have the variable +;;; font-lock-display-type bound to 'grayscale, insert + +;;; (setq font-lock-display-type 'grayscale) + +;;; to your .emacs file. + +;;;; This mode supports font-lock, imenu and compile-mode. In the +;;;; hairy version font-lock is on, but you should activate imenu +;;;; yourself (note that compile-mode is not standard yet). Well, you +;;;; can use imenu from keyboard anyway (M-x imenu), but it is better +;;;; to bind it like that: + +;; (define-key global-map [M-S-down-mouse-3] 'imenu) + +;;; In fact the version of font-lock that this version supports can be +;;; much newer than the version you actually have. This means that a +;;; lot of faces can be set up, but are not visible on your screen +;;; since the coloring rules for this faces are not defined. + +;;; Tips: ======================================== + +;;; get newest version of this package from +;;; ftp://ftp.math.ohio-state.edu/pub/users/ilya/lisp +;;; and/or +;;; ftp://ftp.math.ohio-state.edu/pub/users/ilya/perl + +;;; Get support packages font-lock-extra.el, imenu-go.el from the same place. +;;; (Look for other files there too... ;-) Get a patch for imenu.el. + +;;; Get perl5-info from +;; http://www.metronet.com:70/9/perlinfo/perl5/manual/perl5-info.tar.gz +;;; (may be quite obsolete, but still useful). + +;;; If you use imenu-go, run imenu on perl5-info buffer (can do it from +;;; CPerl menu). + +;;;; Known problems: ======================================== + +;;; The very new pod +;;; features. The rules are: + +;;; /\n=/ should start comment mode, and +;;; /\n=cut\s/ should stop comment mode + +;;; Expansion of keywords tries to detect this kind of commenting, but +;;; a "=" that starts a perl row (as in multiline comment and here +;;; document) can confuse it. + +;;; The main trick (to +;;; make $ a "backslash") makes constructions like ${aaa} look like +;;; unbalanced braces. The only trick I can think out is to insert it as +;;; $ {aaa} (legal in perl5, not in perl4). + +;;;; Known non-problems: ======================================== + +;;; Perl quoting rules are too hard for CPerl. Try to help it: add +;;; comments with embedded quotes to fix CPerl misunderstandings: + +;;; $a='500$'; # '; + +;;; You won't need it too often. + +;;; Now the indentation code is pretty wise. If you still get wrong +;;; indentation in situation that you think the code should be able to +;;; parse, try: + +;;; a) Check what Emacs thinks about balance of your parentheses. +;;; b) Supply the code to me (IZ). + +;;; Updates: ======================================== + +;;; Made less hairy by default: parentheses not electric, +;;; linefeed not magic. Bug with abbrev-mode corrected. + +;;;; After 1.4: +;;; Better indentation: +;;; subs inside braces should work now, +;;; Toplevel braces obey customization. +;;; indent-for-comment knows about bad cases, cperl-indent-for-comment +;;; moves cursor to a correct place. +;;; cperl-indent-exp written from the scratch! Slow... (quadratic!) :-( +;;; (50 secs on DB::DB (sub of 430 lines), 486/66) +;;; Minor documentation fixes. +;;; Imenu understands packages as prefixes (including nested). +;;; Hairy options can be switched off one-by-one by setting to null. +;;; Names of functions and variables changed to conform to `cperl-' style. + +;;;; After 1.5: +;;; Some bugs with indentation of labels (and embedded subs) corrected. +;;; `cperl-indent-region' done (slow :-()). +;;; `cperl-fill-paragraph' done. +;;; Better package support for `imenu'. +;;; Progress indicator for indentation (with `imenu' loaded). +;;; `Cperl-set' was busted, now setting the individual hairy option +;;; should be better. + +;;;; After 1.6: +;;; `cperl-set-style' done. +;;; `cperl-check-syntax' done. +;;; Menu done. +;;; New config variables `cperl-close-paren-offset' and `cperl-comment-column'. +;;; Bugs with `cperl-auto-newline' corrected. +;;; `cperl-electric-lbrace' can work with `cperl-auto-newline' in situation +;;; like $hash{. + +;;;; 1.7 XEmacs (arius@informatik.uni-erlangen.de): +;;; - use `next-command-event', if `next-command-events' does not exist +;;; - use `find-face' as def. of `is-face' +;;; - corrected def. of `x-color-defined-p' +;;; - added const defs for font-lock-comment-face, +;;; font-lock-keyword-face and font-lock-function-name-face +;;; - added def. of font-lock-variable-name-face +;;; - added (require 'easymenu) inside an `eval-when-compile' +;;; - replaced 4-argument `substitute-key-definition' with ordinary +;;; `define-key's +;;; - replaced `mark-active' in menu definition by `cperl-use-region-p'. +;;; Todo (at least): +;;; - use emacs-vers.el (http://www.cs.utah.edu/~eeide/emacs/emacs-vers.el.gz) +;;; for portable code? +;;; - should `cperl-mode' do a +;;; (if (featurep 'easymenu) (easy-menu-add cperl-menu)) +;;; or should this be left to the user's `cperl-mode-hook'? + +;;; Some bugs introduced by the above fix corrected (IZ ;-). +;;; Some bugs under XEmacs introduced by the correction corrected. + +;;; Some more can remain since there are two many different variants. +;;; Please feedback! + +;;; We do not support fontification of arrays and hashes under +;;; obsolete font-lock any more. Upgrade. + +;;;; after 1.8 Minor bug with parentheses. +;;;; after 1.9 Improvements from Joe Marzot. +;;;; after 1.10 +;;; Does not need easymenu to compile under XEmacs. +;;; `vc-insert-headers' should work better. +;;; Should work with 19.29 and 19.12. +;;; Small improvements to fontification. +;;; Expansion of keywords does not depend on C-? being backspace. + +;;; after 1.10+ +;;; 19.29 and 19.12 supported. +;;; `cperl-font-lock-enhanced' deprecated. Use font-lock-extra.el. +;;; Support for font-lock-extra.el. + +;;;; After 1.11: +;;; Tools submenu. +;;; Support for perl5-info. +;;; `imenu-go-find-at-position' in Tools requires imenu-go.el (see hints above) +;;; Imenu entries do not work with stock imenu.el. Patch sent to maintainers. +;;; Fontifies `require a if b;', __DATA__. +;;; Arglist for auto-fill-mode was incorrect. + +;;;; After 1.12: +;;; `cperl-lineup-step' and `cperl-lineup' added: lineup constructions +;;; vertically. +;;; `cperl-do-auto-fill' updated for 19.29 style. +;;; `cperl-info-on-command' now has a default. +;;; Workaround for broken C-h on XEmacs. +;;; VC strings escaped. +;;; C-h f now may prompt for function name instead of going on, +;;; controlled by `cperl-info-on-command-no-prompt'. + +;;;; After 1.13: +;;; Msb buffer list includes perl files +;;; Indent-for-comment uses indent-to +;;; Can write tag files using etags. + +;;;; After 1.14: +;;; Recognizes (tries to ;-) {...} which are not blocks during indentation. +;;; `cperl-close-paren-offset' affects ?\] too (and ?\} if not block) + +(defvar cperl-extra-newline-before-brace nil + "*Non-nil means that if, elsif, while, until, else, for, foreach +and do constructs look like: + + if () + { + } + +instead of: + + if () { + } +") +(defvar cperl-indent-level 2 + "*Indentation of CPerl statements with respect to containing block.") +(defvar cperl-lineup-step nil + "*`cperl-lineup' will always lineup at multiple of this number. +If `nil', the value of `cperl-indent-level' will be used.") +(defvar cperl-brace-imaginary-offset 0 + "*Imagined indentation of a Perl open brace that actually follows a statement. +An open brace following other text is treated as if it were this far +to the right of the start of its line.") +(defvar cperl-brace-offset 0 + "*Extra indentation for braces, compared with other text in same context.") +(defvar cperl-label-offset -2 + "*Offset of CPerl label lines relative to usual indentation.") +(defvar cperl-min-label-indent 1 + "*Minimal offset of CPerl label lines.") +(defvar cperl-continued-statement-offset 2 + "*Extra indent for lines not starting new statements.") +(defvar cperl-continued-brace-offset 0 + "*Extra indent for substatements that start with open-braces. +This is in addition to cperl-continued-statement-offset.") +(defvar cperl-close-paren-offset -1 + "*Extra indent for substatements that start with close-parenthesis.") + +(defvar cperl-auto-newline nil + "*Non-nil means automatically newline before and after braces, +and after colons and semicolons, inserted in CPerl code.") + +(defvar cperl-tab-always-indent t + "*Non-nil means TAB in CPerl mode should always reindent the current line, +regardless of where in the line point is when the TAB command is used.") + +(defvar cperl-font-lock nil + "*Non-nil (and non-null) means CPerl buffers will use font-lock-mode. +Can be overwritten by `cperl-hairy' if nil.") + +(defvar cperl-electric-lbrace-space nil + "*Non-nil (and non-null) means { after $ in CPerl buffers should be preceeded by ` '. +Can be overwritten by `cperl-hairy' if nil.") + +(defvar cperl-electric-parens "" + "*List of parentheses that should be electric in CPerl, or null. +Can be overwritten by `cperl-hairy' to \"({[<\" if not 'null.") + +(defvar cperl-electric-linefeed nil + "*If true, LFD should be hairy in CPerl, otherwise C-c LFD is hairy. +In any case these two mean plain and hairy linefeeds together. +Can be overwritten by `cperl-hairy' if nil.") + +(defvar cperl-electric-keywords nil + "*Not-nil (and non-null) means keywords are electric in CPerl. +Can be overwritten by `cperl-hairy' if nil.") + +(defvar cperl-hairy nil + "*Not-nil means all the bells and whistles are enabled in CPerl.") + +(defvar cperl-comment-column 32 + "*Column to put comments in CPerl (use \\[cperl-indent]' to lineup with code).") + +(defvar cperl-vc-header-alist '((SCCS "$sccs = '%W\%' ;") + (RCS "$rcs = ' $Id\$ ' ;")) + "*What to use as `vc-header-alist' in CPerl.") + +(defvar cperl-info-on-command-no-prompt nil + "*Not-nil (and non-null) means not to prompt on C-h f. +The opposite behaviour is always available if prefixed with C-c. +Can be overwritten by `cperl-hairy' if nil.") + + +;;; Portability stuff: + +(defsubst cperl-xemacs-p () + (string-match "XEmacs\\|Lucid" emacs-version)) + +(defvar del-back-ch (car (append (where-is-internal 'delete-backward-char) + (where-is-internal 'backward-delete-char-untabify))) + "Character generated by key bound to delete-backward-char.") + +(and (vectorp del-back-ch) (= (length del-back-ch) 1) + (setq del-back-ch (aref del-back-ch 0))) + +(if (cperl-xemacs-p) + ;; "Active regions" are on: use region only if active + ;; "Active regions" are off: use region unconditionally + (defun cperl-use-region-p () + (if zmacs-regions (mark) t)) + (defun cperl-use-region-p () + (if transient-mark-mode mark-active t))) + +(defsubst cperl-enable-font-lock () + (or (cperl-xemacs-p) window-system)) + +(if (boundp 'unread-command-events) + (if (cperl-xemacs-p) + (defun cperl-putback-char (c) ; XEmacs >= 19.12 + (setq unread-command-events (list (character-to-event c)))) + (defun cperl-putback-char (c) ; Emacs 19 + (setq unread-command-events (list c)))) + (defun cperl-putback-char (c) ; XEmacs <= 19.11 + (setq unread-command-event (character-to-event c)))) + +(or (fboundp 'uncomment-region) + (defun uncomment-region (beg end) + (interactive "r") + (comment-region beg end -1))) + +;;; Probably it is too late to set these guys already, but it can help later: + +(setq auto-mode-alist + (append '(("\\.[pP][Llm]$" . perl-mode)) auto-mode-alist )) +(and (boundp 'interpreter-mode-alist) + (setq interpreter-mode-alist (append interpreter-mode-alist + '(("miniperl" . perl-mode))))) +(if (fboundp 'eval-when-compile) + (eval-when-compile + (condition-case nil + (require 'imenu) + (error nil)) + (condition-case nil + (require 'easymenu) + (error nil)) + ;; Calling `cperl-enable-font-lock' below doesn't compile on XEmacs, + ;; macros instead of defsubsts don't work on Emacs, so we do the + ;; expansion manually. Any other suggestions? + (if (or (string-match "XEmacs\\|Lucid" emacs-version) + window-system) + (require 'font-lock)) + (require 'cl) + )) + +(defvar cperl-mode-abbrev-table nil + "Abbrev table in use in Cperl-mode buffers.") + +(add-hook 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-"))) + +(defvar cperl-mode-map () "Keymap used in CPerl mode.") + +(if cperl-mode-map nil + (setq cperl-mode-map (make-sparse-keymap)) + (define-key cperl-mode-map "{" 'cperl-electric-lbrace) + (define-key cperl-mode-map "[" 'cperl-electric-paren) + (define-key cperl-mode-map "(" 'cperl-electric-paren) + (define-key cperl-mode-map "<" 'cperl-electric-paren) + (define-key cperl-mode-map "}" 'cperl-electric-brace) + (define-key cperl-mode-map ";" 'cperl-electric-semi) + (define-key cperl-mode-map ":" 'cperl-electric-terminator) + (define-key cperl-mode-map "\C-j" 'newline-and-indent) + (define-key cperl-mode-map "\C-c\C-j" 'cperl-linefeed) + (define-key cperl-mode-map "\e\C-q" 'cperl-indent-exp) ; Usually not bound + ;;(define-key cperl-mode-map "\M-q" 'cperl-fill-paragraph) + ;;(define-key cperl-mode-map "\e;" 'cperl-indent-for-comment) + (define-key cperl-mode-map "\177" 'backward-delete-char-untabify) + (define-key cperl-mode-map "\t" 'cperl-indent-command) + (if (cperl-xemacs-p) + ;; don't clobber the backspace binding: + (define-key cperl-mode-map [(control h) f] 'cperl-info-on-command) + (define-key cperl-mode-map "\C-hf" 'cperl-info-on-command)) + (if (cperl-xemacs-p) + ;; don't clobber the backspace binding: + (define-key cperl-mode-map [(control c) (control h) f] + 'cperl-info-on-current-command) + (define-key cperl-mode-map "\C-c\C-hf" 'cperl-info-on-current-command)) + (if (and (cperl-xemacs-p) + (<= emacs-minor-version 11) (<= emacs-major-version 19)) + (progn + ;; substitute-key-definition is usefulness-deenhanced... + (define-key cperl-mode-map "\M-q" 'cperl-fill-paragraph) + (define-key cperl-mode-map "\e;" 'cperl-indent-for-comment) + (define-key cperl-mode-map "\e\C-\\" 'cperl-indent-region)) + (substitute-key-definition + 'indent-sexp 'cperl-indent-exp + cperl-mode-map global-map) + (substitute-key-definition + 'fill-paragraph 'cperl-fill-paragraph + cperl-mode-map global-map) + (substitute-key-definition + 'indent-region 'cperl-indent-region + cperl-mode-map global-map) + (substitute-key-definition + 'indent-for-comment 'cperl-indent-for-comment + cperl-mode-map global-map))) + +(condition-case nil + (progn + (require 'easymenu) + (easy-menu-define cperl-menu cperl-mode-map "Menu for CPerl mode" + '("Perl" + ["Beginning of function" beginning-of-defun t] + ["End of function" end-of-defun t] + ["Mark function" mark-defun t] + ["Indent expression" cperl-indent-exp t] + ["Fill paragraph/comment" cperl-fill-paragraph t] + ["Line up a construction" cperl-lineup (cperl-use-region-p)] + "----" + ["Indent region" cperl-indent-region (cperl-use-region-p)] + ["Comment region" comment-region (cperl-use-region-p)] + ["Uncomment region" uncomment-region (cperl-use-region-p)] + "----" + ["Run" mode-compile (fboundp 'mode-compile)] + ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill) + (get-buffer "*compilation*"))] + ["Next error" next-error (get-buffer "*compilation*")] + ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)] + "----" + ["Debugger" perldb t] + "----" + ("Tools" + ["Imenu" imenu (fboundp 'imenu)] + ["Imenu on info" cperl-imenu-on-info (featurep 'imenu)] + ("Tags" + ["Create tags for current file" cperl-etags t] + ["Add tags for current file" (cperl-etags t) t] + ["Create tags for Perl files in directory" (cperl-etags nil t) t] + ["Add tags for Perl files in directory" (cperl-etags t t) t] + ["Create tags for Perl files in (sub)directories" + (cperl-etags nil 'recursive) t] + ["Add tags for Perl files in (sub)directories" + (cperl-etags t 'recursive) t]) + ["Define word at point" imenu-go-find-at-position + (fboundp 'imenu-go-find-at-position)] + ["Help on function" cperl-info-on-command t] + ["Help on function at point" cperl-info-on-current-command t]) + ("Indent styles..." + ["GNU" (cperl-set-style "GNU") t] + ["C++" (cperl-set-style "C++") t] + ["FSF" (cperl-set-style "FSF") t] + ["BSD" (cperl-set-style "BSD") t] + ["Whitesmith" (cperl-set-style "Whitesmith") t])))) + (error nil)) + +(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 cperl-mode-syntax-table nil + "Syntax table in use in Cperl-mode buffers.") + +(if cperl-mode-syntax-table + () + (setq cperl-mode-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table) + (modify-syntax-entry ?/ "." cperl-mode-syntax-table) + (modify-syntax-entry ?* "." cperl-mode-syntax-table) + (modify-syntax-entry ?+ "." cperl-mode-syntax-table) + (modify-syntax-entry ?- "." cperl-mode-syntax-table) + (modify-syntax-entry ?= "." cperl-mode-syntax-table) + (modify-syntax-entry ?% "." cperl-mode-syntax-table) + (modify-syntax-entry ?< "." cperl-mode-syntax-table) + (modify-syntax-entry ?> "." cperl-mode-syntax-table) + (modify-syntax-entry ?& "." cperl-mode-syntax-table) + (modify-syntax-entry ?$ "\\" cperl-mode-syntax-table) + (modify-syntax-entry ?\n ">" cperl-mode-syntax-table) + (modify-syntax-entry ?# "<" cperl-mode-syntax-table) + (modify-syntax-entry ?' "\"" cperl-mode-syntax-table) + (modify-syntax-entry ?` "\"" cperl-mode-syntax-table) + (modify-syntax-entry ?_ "w" cperl-mode-syntax-table) + (modify-syntax-entry ?| "." cperl-mode-syntax-table)) + + + +;; Make customization possible "in reverse" +;;(defun cperl-set (symbol to) +;; (or (eq (symbol-value symbol) 'null) (set symbol to))) +(defsubst cperl-val (symbol &optional default hairy) + (cond + ((eq (symbol-value symbol) 'null) default) + (cperl-hairy (or hairy t)) + (t (symbol-value symbol)))) + +;; provide an alias for working with emacs 19. the perl-mode that comes +;; with it is really bad, and this lets us seamlessly replace it. +(fset 'perl-mode 'cperl-mode) +(defun cperl-mode () + "Major mode for editing Perl code. +Expression and list commands understand all C brackets. +Tab indents for Perl code. +Paragraphs are separated by blank lines only. +Delete converts tabs to spaces as it moves back. + +Various characters in Perl almost always come in pairs: {}, (), [], +sometimes <>. When the user types the first, she gets the second as +well, with optional special formatting done on {}. (Disabled by +default.) You can always quote (with \\[quoted-insert]) the left +\"paren\" to avoid the expansion. The processing of < is special, +since most the time you mean \"less\". Cperl mode tries to guess +whether you want to type pair <>, and inserts is if it +appropriate. You can set `cperl-electric-parens' to the string that +contains the parenths from the above list you want to be electrical. + +CPerl mode provides expansion of the Perl control constructs: + if, else, elsif, unless, while, until, for, and foreach. +=========(Disabled by default, see `cperl-electric-keywords'.) +The user types the keyword immediately followed by a space, which causes +the construct to be expanded, and the user is positioned where she is most +likely to want to be. +eg. when the user types a space following \"if\" the following appears in +the buffer: + if () { or if () + } { + } +and the cursor is between the parentheses. The user can then type some +boolean expression within the parens. Having done that, typing +\\[cperl-linefeed] places you, appropriately indented on a new line +between the braces. If CPerl decides that you want to insert +\"English\" style construct like + bite if angry; +it will not do any expansion. See also help on variable +`cperl-extra-newline-before-brace'. + +\\[cperl-linefeed] is a convinience replacement for typing carriage +return. It places you in the next line with proper indentation, or if +you type it inside the inline block of control construct, like + foreach (@lines) {print; print} +and you are on a boundary of a statement inside braces, it will +transform the construct into a multiline and will place you into an +apporpriately indented blank line. If you need a usual +`newline-and-indent' behaviour, it is on \\[newline-and-indent], +see documentation on `cperl-electric-linefeed'. + +\\{cperl-mode-map} + +Setting the variable `cperl-font-lock' to t switches on +font-lock-mode, `cperl-electric-lbrace-space' to t switches on +electric space between $ and {, `cperl-electric-parens' is the string +that contains parentheses that should be electric in CPerl, setting +`cperl-electric-keywords' enables electric expansion of control +structures in CPerl. `cperl-electric-linefeed' governs which one of +two linefeed behavior is preferable. You can enable all these options +simultaneously (recommended mode of use) by setting `cperl-hairy' to +t. In this case you can switch separate options off by setting them +to `null'. + +If your site has perl5 documentation in info format, you can use commands +\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it. +These keys run commands `cperl-info-on-current-command' and +`cperl-info-on-command', which one is which is controlled by variable +`cperl-info-on-command-no-prompt' (in turn affected by `cperl-hairy'). + +Variables controlling indentation style: + `cperl-tab-always-indent' + Non-nil means TAB in CPerl mode should always reindent the current line, + regardless of where in the line point is when the TAB command is used. + `cperl-auto-newline' + Non-nil means automatically newline before and after braces, + and after colons and semicolons, inserted in Perl code. + `cperl-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. + `cperl-continued-statement-offset' + Extra indentation given to a substatement, such as the + then-clause of an if, or body of a while, or just a statement continuation. + `cperl-continued-brace-offset' + Extra indentation given to a brace that starts a substatement. + This is in addition to `cperl-continued-statement-offset'. + `cperl-brace-offset' + Extra indentation for line if it starts with an open brace. + `cperl-brace-imaginary-offset' + An open brace following other text is treated as if it the line started + this far to the right of the actual line indentation. + `cperl-label-offset' + Extra indentation for line that is a label. + `cperl-min-label-indent' + Minimal indentation for line that is a label. + +Settings for K&R and BSD indentation styles are + `cperl-indent-level' 5 8 + `cperl-continued-statement-offset' 5 8 + `cperl-brace-offset' -5 -8 + `cperl-label-offset' -5 -8 + +If `cperl-indent-level' is 0, the statement after opening brace in column 0 is indented on `cperl-brace-offset'+`cperl-continued-statement-offset'. + +Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook' +with no args." + (interactive) + (kill-all-local-variables) + ;;(if cperl-hairy + ;; (progn + ;; (cperl-set 'cperl-font-lock cperl-hairy) + ;; (cperl-set 'cperl-electric-lbrace-space cperl-hairy) + ;; (cperl-set 'cperl-electric-parens "{[(<") + ;; (cperl-set 'cperl-electric-keywords cperl-hairy) + ;; (cperl-set 'cperl-electric-linefeed cperl-hairy))) + (use-local-map cperl-mode-map) + (if (cperl-val 'cperl-electric-linefeed) + (progn + (local-set-key "\C-J" 'cperl-linefeed) + (local-set-key "\C-C\C-J" 'newline-and-indent))) + (if (cperl-val 'cperl-info-on-command-no-prompt) + (progn + (if (cperl-xemacs-p) + ;; don't clobber the backspace binding: + (local-set-key [(control h) f] 'cperl-info-on-current-command) + (local-set-key "\C-hf" 'cperl-info-on-current-command)) + (if (cperl-xemacs-p) + ;; don't clobber the backspace binding: + (local-set-key [(control c) (control h) f] + 'cperl-info-on-command) + (local-set-key "\C-c\C-hf" 'cperl-info-on-command)))) + (setq major-mode 'perl-mode) + (setq mode-name "CPerl") + (if (not cperl-mode-abbrev-table) + (let ((prev-a-c abbrevs-changed)) + (define-abbrev-table 'cperl-mode-abbrev-table '( + ("if" "if" cperl-electric-keyword 0) + ("elsif" "elsif" cperl-electric-keyword 0) + ("while" "while" cperl-electric-keyword 0) + ("until" "until" cperl-electric-keyword 0) + ("unless" "unless" cperl-electric-keyword 0) + ("else" "else" cperl-electric-else 0) + ("for" "for" cperl-electric-keyword 0) + ("foreach" "foreach" cperl-electric-keyword 0) + ("do" "do" cperl-electric-keyword 0))) + (setq abbrevs-changed prev-a-c))) + (setq local-abbrev-table cperl-mode-abbrev-table) + (abbrev-mode (if (cperl-val 'cperl-electric-keywords) 1 0)) + (set-syntax-table cperl-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 'cperl-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 cperl-comment-column) + (make-local-variable 'comment-start-skip) + (setq comment-start-skip "#+ *") + (make-local-variable 'defun-prompt-regexp) + (setq defun-prompt-regexp "[ \t]*sub\\s +\\([^ \t\n{;]+\\)\\s *") + (make-local-variable 'comment-indent-function) + (setq comment-indent-function 'cperl-comment-indent) + (make-local-variable 'parse-sexp-ignore-comments) + (setq parse-sexp-ignore-comments t) + (make-local-variable 'indent-region-function) + (setq indent-region-function 'cperl-indent-region) + ;;(setq auto-fill-function 'cperl-do-auto-fill) ; Need to switch on and off! + (make-local-variable 'imenu-create-index-function) + (setq imenu-create-index-function + (function imenu-example--create-perl-index)) + (make-local-variable 'vc-header-alist) + (setq vc-header-alist cperl-vc-header-alist) + (or (fboundp 'cperl-old-auto-fill-mode) + (progn + (fset 'cperl-old-auto-fill-mode (symbol-function 'auto-fill-mode)) + (defun auto-fill-mode (&optional arg) + (interactive "P") + (cperl-old-auto-fill-mode arg) + (and auto-fill-function (eq major-mode 'perl-mode) + (setq auto-fill-function 'cperl-do-auto-fill))))) + (if (cperl-enable-font-lock) + (if (cperl-val 'cperl-font-lock) (font-lock-mode 1))) + (and (boundp 'msb-menu-cond) + (not cperl-msb-fixed) + (cperl-msb-fix)) + (run-hooks 'cperl-mode-hook)) + +;; Fix for msb.el +(defvar cperl-msb-fixed nil) + +(defun cperl-msb-fix () + ;; Adds perl files to msb menu, supposes that msb is already loaded + (setq cperl-msb-fixed t) + (let* ((l (length msb-menu-cond)) + (last (nth (1- l) msb-menu-cond)) + (precdr (nthcdr (- l 2) msb-menu-cond)) ; cdr of this is last + (handle (1- (nth 1 last)))) + (setcdr precdr (list + (list + '(eq major-mode 'perl-mode) + handle + "Perl Files (%d)") + last)))) + +;; This is used by indent-for-comment +;; to decide how much to indent a comment in CPerl code +;; based on its context. Do fallback if comment is found wrong. + +(defvar cperl-wrong-comment) + +(defun cperl-comment-indent () + (let ((p (point)) (c (current-column)) was) + (if (looking-at "^#") 0 ; Existing comment at bol stays there. + ;; Wrong comment found + (save-excursion + (setq was (cperl-to-comment-or-eol)) + (if (= (point) p) + (progn + (skip-chars-backward " \t") + (max (1+ (current-column)) ; Else indent at comment column + comment-column)) + (if was nil + (insert comment-start) + (backward-char (length comment-start))) + (setq cperl-wrong-comment t) + (indent-to comment-column 1) ; Indent minimum 1 + c))))) ; except leave at least one space. + +;;;(defun cperl-comment-indent-fallback () +;;; "Is called if the standard comment-search procedure fails. +;;;Point is at start of real comment." +;;; (let ((c (current-column)) target cnt prevc) +;;; (if (= c comment-column) nil +;;; (setq cnt (skip-chars-backward "[ \t]")) +;;; (setq target (max (1+ (setq prevc +;;; (current-column))) ; Else indent at comment column +;;; comment-column)) +;;; (if (= c comment-column) nil +;;; (delete-backward-char cnt) +;;; (while (< prevc target) +;;; (insert "\t") +;;; (setq prevc (current-column))) +;;; (if (> prevc target) (progn (delete-char -1) (setq prevc (current-column)))) +;;; (while (< prevc target) +;;; (insert " ") +;;; (setq prevc (current-column))))))) + +(defun cperl-indent-for-comment () + "Substite for `indent-for-comment' in CPerl." + (interactive) + (let (cperl-wrong-comment) + (indent-for-comment) + (if cperl-wrong-comment + (progn (cperl-to-comment-or-eol) + (forward-char (length comment-start)))))) + +(defun cperl-electric-brace (arg &optional only-before) + "Insert character and correct line's indentation. +If ONLY-BEFORE and `cperl-auto-newline', will insert newline before the +place (even in empty line), but not after." + (interactive "P") + (let (insertpos) + (if (and (not arg) ; No args, end (of empty line or auto) + (eolp) + (or (and (null only-before) + (save-excursion + (skip-chars-backward " \t") + (bolp))) + (if cperl-auto-newline + (progn (cperl-indent-line) (newline) t) nil))) + (progn + (if cperl-auto-newline + (setq insertpos (point))) + (insert last-command-char) + (cperl-indent-line) + (if (and cperl-auto-newline (null only-before)) + (progn + (newline) + (cperl-indent-line))) + (save-excursion + (if insertpos (progn (goto-char insertpos) + (search-forward (make-string + 1 last-command-char)) + (setq insertpos (1- (point))))) + (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 cperl-electric-lbrace (arg) + "Insert character, correct line's indentation, correct quoting by space." + (interactive "P") + (let (pos after (cperl-auto-newline cperl-auto-newline)) + (and (cperl-val 'cperl-electric-lbrace-space) + (eq (preceding-char) ?$) + (save-excursion + (skip-chars-backward "$") + (looking-at "\\(\\$\\$\\)*\\$\\([^\\$]\\|$\\)")) + (insert ? )) + (if (cperl-after-expr) nil (setq cperl-auto-newline nil)) + (cperl-electric-brace arg) + (and (eq last-command-char ?{) + (memq last-command-char + (append (cperl-val 'cperl-electric-parens "" "([{<") nil)) + (setq last-command-char ?} pos (point)) + (progn (cperl-electric-brace arg t) + (goto-char pos))))) + +(defun cperl-electric-paren (arg) + "Insert a matching pair of parentheses." + (interactive "P") + (let ((beg (save-excursion (beginning-of-line) (point)))) + (if (and (memq last-command-char + (append (cperl-val 'cperl-electric-parens "" "([{<") nil)) + (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point)) + ;;(not (save-excursion (search-backward "#" beg t))) + (if (eq last-command-char ?<) + (cperl-after-expr nil "{};(,:=") + 1)) + (progn + (insert last-command-char) + (insert (cdr (assoc last-command-char '((?{ .?}) + (?[ . ?]) + (?( . ?)) + (?< . ?>))))) + (forward-char -1)) + (insert last-command-char) + ))) + +(defun cperl-electric-keyword () + "Insert a construction appropriate after a keyword." + (let ((beg (save-excursion (beginning-of-line) (point)))) + (and (save-excursion + (backward-sexp 1) + (cperl-after-expr nil "{};:")) + (save-excursion + (not + (re-search-backward + "[#\"'`]\\|\\<q\\(\\|[wqx]\\)\\>" + beg t))) + (save-excursion (or (not (re-search-backward "^=" nil t)) + (looking-at "=cut"))) + (progn + (cperl-indent-line) + ;;(insert " () {\n}") + (cond + (cperl-extra-newline-before-brace + (insert " ()\n") + (insert "{") + (cperl-indent-line) + (insert "\n") + (cperl-indent-line) + (insert "\n}")) + (t + (insert " () {\n}")) + ) + (or (looking-at "[ \t]\\|$") (insert " ")) + (cperl-indent-line) + (search-backward ")") + (cperl-putback-char del-back-ch))))) + +(defun cperl-electric-else () + "Insert a construction appropriate after a keyword." + (let ((beg (save-excursion (beginning-of-line) (point)))) + (and (save-excursion + (backward-sexp 1) + (cperl-after-expr nil "{};:")) + (save-excursion + (not + (re-search-backward + "[#\"'`]\\|\\<q\\(\\|[wqx]\\)\\>" + beg t))) + (save-excursion (or (not (re-search-backward "^=" nil t)) + (looking-at "=cut"))) + (progn + (cperl-indent-line) + ;;(insert " {\n\n}") + (cond + (cperl-extra-newline-before-brace + (insert "\n") + (insert "{") + (cperl-indent-line) + (insert "\n\n}")) + (t + (insert " {\n\n}")) + ) + (or (looking-at "[ \t]\\|$") (insert " ")) + (cperl-indent-line) + (forward-line -1) + (cperl-indent-line) + (cperl-putback-char del-back-ch))))) + +(defun cperl-linefeed () + "Go to end of line, open a new line and indent appropriately." + (interactive) + (let ((beg (save-excursion (beginning-of-line) (point))) + (end (save-excursion (end-of-line) (point))) + (pos (point)) start) + (if (and ; Check if we need to split: + ; i.e., on a boundary and inside "{...}" + ;;(not (search-backward "\\(^\\|[^$\\\\]\\)#" beg t)) + (save-excursion (cperl-to-comment-or-eol) + (>= (point) pos)) + (or (save-excursion + (skip-chars-backward " \t" beg) + (forward-char -1) + (looking-at "[;{]")) + (looking-at "[ \t]*}") + (re-search-forward "\\=[ \t]*;" end t)) + (save-excursion + (and + (eq (car (parse-partial-sexp pos end -1)) -1) + (looking-at "[ \t]*\\($\\|#\\)") + ;;(setq finish (point-marker)) + (progn + (backward-sexp 1) + (setq start (point-marker)) + (<= start pos)) + ;;(looking-at "[^{}\n]*}[ \t]*$") ; Will fail if there are intervening {}'s + ;;(search-backward "{" beg t) + ;;(looking-at "{[^{}\n]*}[ \t]*$") + ))) + ;;(or (looking-at "[ \t]*}") ; and on a boundary of statements + ;; (save-excursion + ;; (skip-chars-backward " \t") + ;; (forward-char -1) + ;; (looking-at "[{;]")))) + (progn + (skip-chars-backward " \t") + (or (memq (preceding-char) (append ";{" nil)) + (insert ";")) + (insert "\n") + (forward-line -1) + (cperl-indent-line) + ;;(end-of-line) + ;;(search-backward "{" beg) + (goto-char start) + (or (looking-at "{[ \t]*$") ; If there is a statement + ; before, move it to separate line + (progn + (forward-char 1) + (insert "\n") + (cperl-indent-line))) + (forward-line 1) ; We are on the target line + (cperl-indent-line) + (beginning-of-line) + (or (looking-at "[ \t]*}[ \t]*$") ; If there is a statement + ; after, move it to separate line + (progn + (end-of-line) + (search-backward "}" beg) + (skip-chars-backward " \t") + (or (memq (preceding-char) (append ";{" nil)) + (insert ";")) + (insert "\n") + (cperl-indent-line) + (forward-line -1))) + (forward-line -1) ; We are on the line before target + (end-of-line) + (newline-and-indent)) + (end-of-line) ; else + (if (not (looking-at "\n[ \t]*$")) + (newline-and-indent) + (forward-line 1) + (cperl-indent-line))))) + +(defun cperl-electric-semi (arg) + "Insert character and correct line's indentation." + (interactive "P") + (if cperl-auto-newline + (cperl-electric-terminator arg) + (self-insert-command (prefix-numeric-value arg)))) + +(defun cperl-electric-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 "case[ \t]")) + (save-excursion + (forward-word 1) + (skip-chars-forward " \t") + (and (< (point) end) + (progn (goto-char (- end 1)) + (not (looking-at ":")))))) + (progn + (beginning-of-defun) + (let ((pps (parse-partial-sexp (point) end))) + (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) + (progn + (if cperl-auto-newline + (setq insertpos (point))) + (insert last-command-char) + (cperl-indent-line) + (if cperl-auto-newline + (progn + (newline) + (cperl-indent-line))) + (save-excursion + (if insertpos (progn (goto-char insertpos) + (search-forward (make-string + 1 last-command-char)) + (setq insertpos (1- (point))))) + (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 cperl-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 cperl-indent-command (&optional whole-exp) + (interactive "P") + "Indent current line as Perl code, or in some cases insert a tab character. +If `cperl-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 Perl + ;; and shift remaining lines of expression the same amount. + (let ((shift-amt (cperl-indent-line)) + beg end) + (save-excursion + (if cperl-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 cperl-tab-always-indent) + (save-excursion + (skip-chars-backward " \t") + (not (bolp)))) + (insert-tab) + (cperl-indent-line)))) + +(defun cperl-indent-line (&optional symbol) + "Indent current line as Perl code. +Return the amount the indentation changed by." + (let (indent + beg shift-amt + (case-fold-search nil) + (pos (- (point-max) (point)))) + (setq indent (cperl-calculate-indent nil symbol)) + (beginning-of-line) + (setq beg (point)) + (cond ((eq indent nil) + (setq indent (current-indentation))) + ;;((eq indent t) ; Never? + ;; (setq indent (cperl-calculate-indent-within-comment))) + ;;((looking-at "[ \t]*#") + ;; (setq indent 0)) + (t + (skip-chars-forward " \t") + (if (listp indent) (setq indent (car indent))) + (cond ((looking-at "[A-Za-z]+:[^:]") + (and (> indent 0) + (setq indent (max cperl-min-label-indent + (+ indent cperl-label-offset))))) + ;;((and (looking-at "els\\(e\\|if\\)\\b") + ;; (not (looking-at "else\\s_"))) + ;; (setq indent (save-excursion + ;; (cperl-backward-to-start-of-if) + ;; (current-indentation)))) + ((= (following-char) ?}) + (setq indent (- indent cperl-indent-level))) + ((memq (following-char) '(?\) ?\])) ; To line up with opening paren. + (setq indent (+ indent cperl-close-paren-offset))) + ((= (following-char) ?{) + (setq indent (+ indent cperl-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)) + +(defsubst cperl-after-label () + ;; Returns true if the point is after label. Does not do save-excursion. + (and (eq (preceding-char) ?:) + (memq (char-syntax (char-after (- (point) 2))) + '(?w ?_)) + (progn + (backward-sexp) + (looking-at "[a-zA-Z_][a-zA-Z0-9_]*:")))) + +(defun cperl-calculate-indent (&optional parse-start symbol) + "Return appropriate indentation for current line as Perl 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) + (char-after (save-excursion + (skip-chars-forward " \t") + (following-char))) + state start-indent start start-state moved + containing-sexp old-containing-sexp old-indent) + (or parse-start (null symbol) + (setq parse-start (symbol-value symbol) + start-state (cadr parse-start) + start-indent (nth 2 parse-start) + parse-start (car parse-start) + old-containing-sexp (nth 1 start-state))) + (if parse-start + (goto-char parse-start) + (beginning-of-defun)) + (if start-state nil + ;; Try to go out + (while (< (point) indent-point) + (setq start (point) parse-start start moved nil + state (parse-partial-sexp start indent-point -1)) + (if (> (car state) -1) nil + ;; The current line could start like }}}, so the indentation + ;; corresponds to a different level than what we reached + (setq moved t) + (beginning-of-line 2))) ; Go to the next line. + (if start ; Not at the start of file + (progn + (goto-char start) + (setq start-indent (current-indentation)) + (if moved ; Should correct... + (setq start-indent (- start-indent cperl-indent-level)))) + (setq start-indent 0))) + (if (< (point) indent-point) (setq parse-start (point))) + (or state (setq state (parse-partial-sexp + (point) indent-point -1 nil start-state))) + (setq containing-sexp + (or (car (cdr state)) + (and (>= (nth 6 state) 0) old-containing-sexp)) + old-containing-sexp nil start-state nil) +;; (while (< (point) indent-point) +;; (setq parse-start (point)) +;; (setq state (parse-partial-sexp (point) indent-point -1 nil start-state)) +;; (setq containing-sexp +;; (or (car (cdr state)) +;; (and (>= (nth 6 state) 0) old-containing-sexp)) +;; old-containing-sexp nil start-state nil)) + (if symbol (set symbol (list indent-point state start-indent))) + (goto-char indent-point) + (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. + (skip-chars-forward " \t") + (+ start-indent + (if (= (following-char) ?{) cperl-continued-brace-offset 0) + (progn + (cperl-backward-to-noncomment (or parse-start (point-min))) + (skip-chars-backward " \t\f\n") + ;; 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. + ;; Now add a little if this is a continuation line. + (if (or (bobp) + (memq (preceding-char) (append ");}" nil)) + (memq char-after (append ")]}" nil))) + 0 + cperl-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)) + ((progn + ;; Containing-expr starts with \{. Check whether it is a hash. + (goto-char containing-sexp) + (cperl-backward-to-noncomment (or parse-start (point-min))) + (skip-chars-backward " \t\n\f") + (not + (or (memq (preceding-char) (append ";)}$@&%" nil)) ; Or label! + ; Label may be mixed up with `$blah :' + (save-excursion (cperl-after-label)) + (and (eq (char-syntax (preceding-char)) ?w) + (progn + (backward-sexp) + (or (looking-at "\\sw+[ \t\n\f]*{") ; Method call syntax + (progn + (skip-chars-backward " \t\n\f") + (and (eq (char-syntax (preceding-char)) ?w) + (progn + (backward-sexp) + (looking-at + "sub[ \t]+\\sw+[ \t\n\f]*{")))))))))) + (goto-char containing-sexp) + (+ (current-column) 1 ; Correct indentation of trailing ?\} + (if (eq char-after ?\}) (+ cperl-indent-level + cperl-close-paren-offset) + 0))) + (t + ;; Statement level. Is it a continuation or a new statement? + ;; Find previous non-comment character. + (goto-char indent-point) + (cperl-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) ?\,) + (cperl-backward-to-start-of-continued-exp containing-sexp)) + (beginning-of-line) + (cperl-backward-to-noncomment containing-sexp)) + ;; Now we get the answer. + (if (not (memq (preceding-char) (append ",;}{" '(nil)))) ; Was ?\, + ;; This line is continuation of preceding line's statement; + ;; indent `cperl-continued-statement-offset' more than the + ;; previous line of the statement. + (progn + (cperl-backward-to-start-of-continued-exp containing-sexp) + (+ (if (memq char-after (append "}])" nil)) + 0 ; Closing parenth + cperl-continued-statement-offset) + (current-column) + (if (eq char-after ?\{) + cperl-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. If the first statement begins with label, do + ;; not belive when the indentation of the label is too + ;; small. + (save-excursion + (forward-char 1) + (setq old-indent (current-indentation)) + (let ((colon-line-end 0)) + (while (progn (skip-chars-forward " \t\n") + (looking-at "#\\|[a-zA-Z0-9_$]*:[^:]")) + ;; Skip over comments and labels following openbrace. + (cond ((= (following-char) ?\#) + (forward-line 1)) + ;; 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)) ; After label + (if (> (current-indentation) + cperl-min-label-indent) + (- (current-indentation) cperl-label-offset) + ;; Do not belive: `max' is involved + (+ old-indent cperl-indent-level)) + (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 cperl-indent-level is zero, + ;; use cperl-brace-offset + cperl-continued-statement-offset instead. + ;; For open-braces not the first thing in a line, + ;; add in cperl-brace-imaginary-offset. + + ;; If first thing on a line: ????? + (+ (if (and (bolp) (zerop cperl-indent-level)) + (+ cperl-brace-offset cperl-continued-statement-offset) + cperl-indent-level) + ;; Move back over whitespace before the openbrace. + ;; If openbrace is not first nonwhite thing on the line, + ;; add the cperl-brace-imaginary-offset. + (progn (skip-chars-backward " \t") + (if (bolp) 0 cperl-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. + ;; If line starts with label, calculate label indentation + (if (save-excursion + (beginning-of-line) + (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_]*:[^:]")) + (if (> (current-indentation) cperl-min-label-indent) + (- (current-indentation) cperl-label-offset) + (cperl-calculate-indent + (if (<= parse-start (point)) parse-start))) + (current-indentation))))))))))) + +(defvar cperl-indent-alist + '((string nil) + (comment nil) + (toplevel 0) + (toplevel-after-parenth 2) + (toplevel-continued 2) + (expression 1)) + "Alist of indentation rules for CPerl mode. +The values mean: + nil: do not indent; + number: add this amount of indentation.") + +(defun cperl-where-am-i (&optional parse-start start-state) + ;; Unfinished + "Return a list (TYPE POS) of the start of enclosing construction. +POS may be nil if it is hard to find, say, when TYPE is `string' or `comment'." + (save-excursion + (let ((start-point (point)) + (case-fold-search nil) + state start-indent start moved + containing-sexp old-containing-sexp old-indent) + (if parse-start + (goto-char parse-start) + (beginning-of-defun)) + (if start-state nil + ;; Try to go out, if sub is not on the outermost level + (while (< (point) start-point) + (setq start (point) parse-start start moved nil + state (parse-partial-sexp start start-point -1)) + (if (> (car state) -1) nil + ;; The current line could start like }}}, so the indentation + ;; corresponds to a different level than what we reached + (setq moved t) + (beginning-of-line 2))) ; Go to the next line. + (if start (goto-char start))) ; Not at the start of file + (skip-chars-forward " \t") + (setq start (point)) + (if (< (point) start-point) (setq parse-start (point))) + (or state (setq state (parse-partial-sexp + (point) start-point -1 nil start-state))) + (setq containing-sexp + (or (car (cdr state)) + (and (>= (nth 6 state) 0) old-containing-sexp)) + old-containing-sexp nil start-state nil) +;; (while (< (point) start-point) +;; (setq parse-start (point)) +;; (setq state (parse-partial-sexp (point) start-point -1 nil start-state)) +;; (setq containing-sexp +;; (or (car (cdr state)) +;; (and (>= (nth 6 state) 0) old-containing-sexp)) +;; old-containing-sexp nil start-state nil)) + (goto-char start-point) + (cond ((nth 3 state) ; In string + (list 'string nil (nth 3 state))) ; What started string + ((nth 4 state) ; In comment + '(comment)) + ((null containing-sexp) + ;; Line is at top level. + ;; 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. + (cperl-backward-to-noncomment (or parse-start (point-min))) + (skip-chars-backward " \t\f\n") ; Why??? + (cond + ((or (bobp) + (memq (preceding-char) (append ";}" nil))) + (list 'toplevel start)) + ((eq (preceding-char) ?\) ) + (list 'toplevel-after-parenth start)) + (t (list 'toplevel-continued start)))) + ((/= (char-after containing-sexp) ?{) + ;; line is expression, not statement: + ;; indent to just after the surrounding open. + (list 'expression containing-sexp)) + ((progn + ;; Containing-expr starts with \{. Check whether it is a hash. + (goto-char containing-sexp) + (cperl-backward-to-noncomment (or parse-start (point-min))) + (skip-chars-backward " \t\n\f") + (not + (or (memq (preceding-char) (append ";)}$@&%" nil)) ; Or label! + ; Label may be mixed up with `$blah :' + (save-excursion (cperl-after-label)) + (and (eq (char-syntax (preceding-char)) ?w) + (progn + (backward-sexp) + (looking-at "\\sw+[ \t\n\f]*{")))))) ; Method call syntax + (list 'expression containing-sexp)) + (t + ;; Statement level. Is it a continuation or a new statement? + ;; Find previous non-comment character. + (cperl-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) ?\,) + (cperl-after-label)) + (if (eq (preceding-char) ?\,) + (cperl-backward-to-start-of-continued-exp containing-sexp)) + (beginning-of-line) + (cperl-backward-to-noncomment containing-sexp)) + ;; Now we get the answer. + (if (not (memq (preceding-char) (append ";}{" '(nil)))) ; Was ?\, + ;; This line is continuation of preceding line's statement. + '(statement-continued containing-sexp) + ;; 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. If the first statement begins with label, do + ;; not belive when the indentation of the label is too + ;; small. + (save-excursion + (forward-char 1) + (setq old-indent (current-indentation)) + (let ((colon-line-end 0)) + (while (progn (skip-chars-forward " \t\n") + (looking-at "#\\|[a-zA-Z0-9_$]*:[^:]")) + ;; Skip over comments and labels following openbrace. + (cond ((= (following-char) ?\#) + (forward-line 1)) + ;; 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) start-point) + (if (> colon-line-end (point)) ; After label + (if (> (current-indentation) + cperl-min-label-indent) + (- (current-indentation) cperl-label-offset) + ;; Do not belive: `max' is involved + (+ old-indent cperl-indent-level)) + (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 cperl-indent-level is zero, + ;; use cperl-brace-offset + cperl-continued-statement-offset instead. + ;; For open-braces not the first thing in a line, + ;; add in cperl-brace-imaginary-offset. + + ;; If first thing on a line: ????? + (+ (if (and (bolp) (zerop cperl-indent-level)) + (+ cperl-brace-offset cperl-continued-statement-offset) + cperl-indent-level) + ;; Move back over whitespace before the openbrace. + ;; If openbrace is not first nonwhite thing on the line, + ;; add the cperl-brace-imaginary-offset. + (progn (skip-chars-backward " \t") + (if (bolp) 0 cperl-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. + ;; If line starts with label, calculate label indentation + (if (save-excursion + (beginning-of-line) + (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_]*:[^:]")) + (if (> (current-indentation) cperl-min-label-indent) + (- (current-indentation) cperl-label-offset) + (cperl-calculate-indent + (if (<= parse-start (point)) parse-start))) + (current-indentation))))))))))) + +(defun cperl-calculate-indent-within-comment () + "Return the indentation amount for line, assuming that +the current line is to be regarded as part of a block comment." + (let (end star-start) + (save-excursion + (beginning-of-line) + (skip-chars-forward " \t") + (setq end (point)) + (and (= (following-char) ?#) + (forward-line -1) + (cperl-to-comment-or-eol) + (setq end (point))) + (goto-char end) + (current-column)))) + + +(defun cperl-to-comment-or-eol () + "Goes to position before comment on the current line, or to end of line. +Returns true if comment is found." + (let (state stop-in cpoint (lim (progn (end-of-line) (point)))) + (beginning-of-line) + (if (re-search-forward "\\=[ \t]*\\(#\\|$\\)" lim t) + (if (eq (preceding-char) ?\#) (progn (backward-char 1) t)) + ;; Else + (while (not stop-in) + (setq state (parse-partial-sexp (point) lim nil nil nil t)) + ; stop at comment + ;; If fails (beginning-of-line inside sexp), then contains not-comment + ;; Do simplified processing + ;;(if (re-search-forward "[^$]#" lim 1) + ;; (progn + ;; (forward-char -1) + ;; (skip-chars-backward " \t\n\f" lim)) + ;; (goto-char lim)) ; No `#' at all + ;;) + (if (nth 4 state) ; After `#'; + ; (nth 2 state) can be + ; beginning of m,s,qq and so + ; on + (if (nth 2 state) + (progn + (setq cpoint (point)) + (goto-char (nth 2 state)) + (cond + ((looking-at "\\(s\\|tr\\)\\>") + (or (re-search-forward + "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*" + lim 'move) + (setq stop-in t))) + ((looking-at "\\(m\\|q\\([qxw]\\)?\\)\\>") + (or (re-search-forward + "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#" + lim 'move) + (setq stop-in t))) + (t ; It was fair comment + (setq stop-in t) ; Finish + (goto-char (1- cpoint))))) + (setq stop-in t) ; Finish + (forward-char -1)) + (setq stop-in t)) ; Finish + ) + (nth 4 state)))) + +(defun cperl-backward-to-noncomment (lim) + (let (stop p) + (while (and (not stop) (> (point) (or lim 1))) + (skip-chars-backward " \t\n\f" lim) + (setq p (point)) + (beginning-of-line) + (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip + ;; Else + (cperl-to-comment-or-eol) + (skip-chars-backward " \t") + (if (< p (point)) (goto-char p)) + (setq stop t))))) + +(defun cperl-after-expr (&optional lim chars test) + "Returns true if the position is good for start of expression. +TEST is the expression to evaluate at the found position. If absent, +CHARS is a string that contains good characters to have before us." + (let (stop p) + (save-excursion + (while (and (not stop) (> (point) (or lim 1))) + (skip-chars-backward " \t\n\f" lim) + (setq p (point)) + (beginning-of-line) + (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip + ;; Else: last iteration (What to do with labels?) + (cperl-to-comment-or-eol) + (skip-chars-backward " \t") + (if (< p (point)) (goto-char p)) + (setq stop t))) + (or (bobp) + (progn + (backward-char 1) + (if test (eval test) + (memq (following-char) (append (or chars "{};") nil)))))))) + +(defun cperl-backward-to-start-of-continued-exp (lim) + (if (memq (preceding-char) (append ")]}" nil)) + (forward-sexp -1)) + (beginning-of-line) + (if (<= (point) lim) + (goto-char (1+ lim))) + (skip-chars-forward " \t")) + +(defun cperl-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 (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)))))) + + + +(defvar innerloop-done nil) +(defvar last-depth nil) + +(defun cperl-indent-exp () + "Simple variant of indentation of continued-sexp. +Should be slow. Will not indent comment if it starts at `comment-indent' +or looks like continuation of the comment on the previous line." + (interactive) + (save-excursion + (let ((tmp-end (progn (end-of-line) (point))) top done) + (save-excursion + (while (null done) + (beginning-of-line) + (setq top (point)) + (while (= (nth 0 (parse-partial-sexp (point) tmp-end + -1)) -1) + (setq top (point))) ; Get the outermost parenths in line + (goto-char top) + (while (< (point) tmp-end) + (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol + (or (eolp) (forward-sexp 1))) + (if (> (point) tmp-end) (progn (end-of-line) (setq tmp-end (point))) + (setq done t))) + (goto-char tmp-end) + (setq tmp-end (point-marker))) + (cperl-indent-region (point) tmp-end)))) + +(defun cperl-indent-region (start end) + "Simple variant of indentation of region in CPerl mode. +Should be slow. Will not indent comment if it starts at `comment-indent' +or looks like continuation of the comment on the previous line. +Indents all the lines whose first character is between START and END +inclusive." + (interactive "r") + (save-excursion + (let (st comm indent-info old-comm-indent new-comm-indent + (pm 0) (imenu-scanning-message "Indenting... (%3d%%)")) + (goto-char start) + (setq old-comm-indent (and (cperl-to-comment-or-eol) + (current-column)) + new-comm-indent old-comm-indent) + (goto-char start) + (or (bolp) (beginning-of-line 2)) + (or (fboundp 'imenu-progress-message) + (message "Indenting... For feedback load `imenu'...")) + (while (and (<= (point) end) (not (eobp))) ; bol to check start + (and (fboundp 'imenu-progress-message) + (imenu-progress-message + pm (/ (* 100 (- (point) start)) (- end start -1)))) + (setq st (point) + indent-info nil + ) ; Believe indentation of the current + (if (and (setq comm (looking-at "[ \t]*#")) + (or (eq (current-indentation) (or old-comm-indent + comment-column)) + (setq old-comm-indent nil))) + (if (and old-comm-indent + (= (current-indentation) old-comm-indent)) + (let ((comment-column new-comm-indent)) + (indent-for-comment))) + (progn + (cperl-indent-line 'indent-info) + (or comm + (progn + (if (setq old-comm-indent (and (cperl-to-comment-or-eol) + (current-column))) + (progn (indent-for-comment) + (skip-chars-backward " \t") + (skip-chars-backward "#") + (setq new-comm-indent (current-column)))))))) + (beginning-of-line 2)) + (if (fboundp 'imenu-progress-message) + (imenu-progress-message pm 100) + (message nil))))) + +(defun cperl-slash-is-regexp (&optional pos) + (save-excursion + (goto-char (if pos pos (1- (point)))) + (and + (not (memq (get-text-property (point) 'face) + '(font-lock-string-face font-lock-comment-face))) + (cperl-after-expr nil nil ' + (or (looking-at "[^]a-zA-Z0-9_)}]") + (eq (get-text-property (point) 'face) + 'font-lock-keyword-face)))))) + +;; Stolen from lisp-mode with a lot of improvements + +(defun cperl-fill-paragraph (&optional justify iteration) + "Like \\[fill-paragraph], but handle CPerl comments. +If any of the current line is a comment, fill the comment or the +block of it that point is in, preserving the comment's initial +indentation and initial hashes. Behaves usually outside of comment." + (interactive "P") + (let ( + ;; Non-nil if the current line contains a comment. + has-comment + + ;; If has-comment, the appropriate fill-prefix for the comment. + comment-fill-prefix + ;; Line that contains code and comment (or nil) + start + c spaces len dc (comment-column comment-column)) + ;; Figure out what kind of comment we are looking at. + (save-excursion + (beginning-of-line) + (cond + + ;; A line with nothing but a comment on it? + ((looking-at "[ \t]*#[# \t]*") + (setq has-comment t + comment-fill-prefix (buffer-substring (match-beginning 0) + (match-end 0)))) + + ;; A line with some code, followed by a comment? Remember that the + ;; semi which starts the comment shouldn't be part of a string or + ;; character. + ((cperl-to-comment-or-eol) + (setq has-comment t) + (looking-at "#+[ \t]*") + (setq start (point) c (current-column) + comment-fill-prefix + (concat (make-string (current-column) ?\ ) + (buffer-substring (match-beginning 0) (match-end 0))) + spaces (progn (skip-chars-backward " \t") + (buffer-substring (point) start)) + dc (- c (current-column)) len (- start (point)) + start (point-marker)) + (delete-char len) + (insert (make-string dc ?-))))) + (if (not has-comment) + (fill-paragraph justify) ; Do the usual thing outside of comment + ;; Narrow to include only the comment, and then fill the region. + (save-restriction + (narrow-to-region + ;; Find the first line we should include in the region to fill. + (if start (progn (beginning-of-line) (point)) + (save-excursion + (while (and (zerop (forward-line -1)) + (looking-at "^[ \t]*#+[ \t]*[^ \t\n]"))) + ;; We may have gone to far. Go forward again. + (or (looking-at "^[ \t]*#+[ \t]*[^ \t\n]") + (forward-line 1)) + (point))) + ;; Find the beginning of the first line past the region to fill. + (save-excursion + (while (progn (forward-line 1) + (looking-at "^[ \t]*#+[ \t]*[^ \t\n]"))) + (point))) + ;; Remove existing hashes + (goto-char (point-min)) + (while (progn (forward-line 1) (< (point) (point-max))) + (skip-chars-forward " \t") + (and (looking-at "#+") + (delete-char (- (match-end 0) (match-beginning 0))))) + + ;; Lines with only hashes on them can be paragraph boundaries. + (let ((paragraph-start (concat paragraph-start "\\|^[ \t#]*$")) + (paragraph-separate (concat paragraph-start "\\|^[ \t#]*$")) + (fill-prefix comment-fill-prefix)) + (fill-paragraph justify))) + (if (and start) + (progn + (goto-char start) + (if (> dc 0) + (progn (delete-char dc) (insert spaces))) + (if (or (= (current-column) c) iteration) nil + (setq comment-column c) + (indent-for-comment) + ;; Repeat once more, flagging as iteration + (cperl-fill-paragraph justify t))))))) + +(defun cperl-do-auto-fill () + ;; Break out if the line is short enough + (if (> (save-excursion + (end-of-line) + (current-column)) + fill-column) + (let ((c (save-excursion (beginning-of-line) + (cperl-to-comment-or-eol) (point))) + (s (memq (following-char) '(?\ ?\t))) marker) + (if (>= c (point)) nil + (setq marker (point-marker)) + (cperl-fill-paragraph) + (goto-char marker) + ;; Is not enough, sometimes marker is a start of line + (if (bolp) (progn (re-search-forward "#+[ \t]*") + (goto-char (match-end 0)))) + ;; Following space could have gone: + (if (or (not s) (memq (following-char) '(?\ ?\t))) nil + (insert " ") + (backward-char 1)) + ;; Previous space could have gone: + (or (memq (preceding-char) '(?\ ?\t)) (insert " ")))))) + +(defvar imenu-example--function-name-regexp-perl + "^[ \t]*\\(sub\\|package\\)[ \t\n]+\\([a-zA-Z_0-9:']+\\)[ \t]*") + +(defun imenu-example--create-perl-index (&optional regexp) + (require 'cl) + (let ((index-alist '()) (index-pack-alist '()) packages ends-ranges p + (prev-pos 0) char fchar index name (end-range 0) package) + (goto-char (point-min)) + (imenu-progress-message prev-pos 0) + ;; Search for the function + (save-match-data + (while (re-search-forward + (or regexp imenu-example--function-name-regexp-perl) + nil t) + (imenu-progress-message prev-pos) + ;;(backward-up-list 1) + (save-excursion + (goto-char (match-beginning 1)) + (setq fchar (following-char)) + ) + (setq char (following-char)) + (setq p (point)) + (while (and ends-ranges (>= p (car ends-ranges))) + ;; delete obsolete entries + (setq ends-ranges (cdr ends-ranges) packages (cdr packages))) + (setq package (or (car packages) "") + end-range (or (car ends-ranges) 0)) + (if (eq fchar ?p) + (progn + (setq name (buffer-substring (match-beginning 2) (match-end 2)) + package (concat name "::") + name (concat "package " name) + end-range + (save-excursion + (parse-partial-sexp (point) (point-max) -1) (point)) + ends-ranges (cons end-range ends-ranges) + packages (cons package packages)))) + ;; ) + ;; Skip this function name if it is a prototype declaration. + (if (and (eq fchar ?s) (eq char ?\;)) nil + (if (eq fchar ?p) nil + (setq name (buffer-substring (match-beginning 2) (match-end 2))) + (if (or (> p end-range) (string-match "[:']" name)) nil + (setq name (concat package name)))) + (setq index (imenu-example--name-and-position)) + (setcar index name) + (if (eq fchar ?p) + (push index index-pack-alist) + (push index index-alist))))) + (imenu-progress-message prev-pos 100) + (and index-pack-alist + (push (cons (imenu-create-submenu-name "Packages") index-pack-alist) + index-alist)) + (nreverse index-alist))) + +(defvar cperl-compilation-error-regexp-alist + ;; This look like a paranoiac regexp: could anybody find a better one? (which WORK). + '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]" + 2 3)) + "Alist that specifies how to match errors in perl output.") + +(if (fboundp 'eval-after-load) + (eval-after-load + "mode-compile" + '(setq perl-compilation-error-regexp-alist + cperl-compilation-error-regexp-alist))) + + +(defvar cperl-faces-init nil) + +(defun cperl-windowed-init () + "Initialization under windowed version." + (add-hook 'font-lock-mode-hook + (function + (lambda () + (if (or + (eq major-mode 'perl-mode) + (eq major-mode 'cperl-mode)) + (progn + (or cperl-faces-init (cperl-init-faces)) + (setq font-lock-keywords perl-font-lock-keywords + cperl-faces-init t))))))) + +(defun cperl-init-faces () + (condition-case nil + (progn + (require 'font-lock) + (let (t-font-lock-keywords) + ;;(defvar cperl-font-lock-enhanced nil + ;; "Set to be non-nil if font-lock allows active highlights.") + (setq + t-font-lock-keywords + (list + (cons + (concat + "\\(^\\|[^$@%&\\]\\)\\<\\(" + (mapconcat + 'identity + '("if" "until" "while" "elsif" "else" "unless" "for" + "foreach" "continue" "exit" "die" "last" "goto" "next" + "redo" "return" "local" "exec" "sub" "do" "dump" "use" + "require" "package" "eval" "my" "BEGIN" "END") + "\\|") ; Flow control + "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]" + ; In what follows we use `type' style + ; for overwritable buildins + (list + (concat + "\\(^\\|[^$@%&\\]\\)\\<\\(" + ;; "CORE" "__FILE__" "__LINE__" "abs" "accept" "alarm" "and" "atan2" + ;; "bind" "binmode" "bless" "caller" "chdir" "chmod" "chown" "chr" + ;; "chroot" "close" "closedir" "cmp" "connect" "continue" "cos" + ;; "crypt" "dbmclose" "dbmopen" "die" "dump" "endgrent" "endhostent" + ;; "endnetent" "endprotoent" "endpwent" "endservent" "eof" "eq" "exec" + ;; "exit" "exp" "fcntl" "fileno" "flock" "fork" "formline" "ge" "getc" + ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr" "gethostbyname" + ;; "gethostent" "getlogin" "getnetbyaddr" "getnetbyname" "getnetent" + ;; "getpeername" "getpgrp" "getppid" "getpriority" "getprotobyname" + ;; "getprotobynumber" "getprotoent" "getpwent" "getpwnam" "getpwuid" + ;; "getservbyname" "getservbyport" "getservent" "getsockname" + ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int" "ioctl" + ;; "join" "kill" "lc" "lcfirst" "le" "length" "link" "listen" + ;; "localtime" "log" "lstat" "lt" "mkdir" "msgctl" "msgget" "msgrcv" + ;; "msgsnd" "ne" "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe" + ;; "quotemeta" "rand" "read" "readdir" "readline" "readlink" + ;; "readpipe" "recv" "ref" "rename" "require" "reset" "reverse" + ;; "rewinddir" "rindex" "rmdir" "seek" "seekdir" "select" "semctl" + ;; "semget" "semop" "send" "setgrent" "sethostent" "setnetent" + ;; "setpgrp" "setpriority" "setprotoent" "setpwent" "setservent" + ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite" "shutdown" + ;; "sin" "sleep" "socket" "socketpair" "sprintf" "sqrt" "srand" "stat" + ;; "substr" "symlink" "syscall" "sysread" "system" "syswrite" "tell" + ;; "telldir" "time" "times" "truncate" "uc" "ucfirst" "umask" "unlink" + ;; "unpack" "utime" "values" "vec" "wait" "waitpid" "wantarray" "warn" + ;; "write" "x" "xor" + "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|" + "b\\(in\\(d\\|mode\\)\\|less\\)\\|" + "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|" + "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|" + "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|" + "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|" + "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|" + "f\\(ileno\\|cntl\\|lock\\|or\\(k\\|mline\\)\\)\\|" + "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|" + "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w" + "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|" + "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|" + "ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|" + "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|" + "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|" + "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e" + "\\(\\|ngth\\)\\|o\\(caltime\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|" + "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|" + "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|" + "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin" + "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name" + "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r" + "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|" + "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|" + "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|" + "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|tem\\|write\\)\\|" + "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|" + "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|" + "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|" + "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|" + "x\\(\\|or\\)\\|__\\(FILE__\\|LINE__\\)" + "\\)\\>") 2 'font-lock-type-face) + ;; In what follows we use `other' style + ;; for nonoverwritable buildins + ;; Somehow 's', 'm' are not autogenerated??? + (list + (concat + "\\(^\\|[^$@%&\\]\\)\\<\\(" + ;; "AUTOLOAD" "BEGIN" "DESTROY" "END" "__END__" "chomp" "chop" + ;; "defined" "delete" "do" "each" "else" "elsif" "eval" "exists" "for" + ;; "foreach" "format" "goto" "grep" "if" "keys" "last" "local" "map" + ;; "my" "next" "no" "package" "pop" "pos" "print" "printf" "push" "q" + ;; "qq" "qw" "qx" "redo" "return" "scalar" "shift" "sort" "splice" + ;; "split" "study" "sub" "tie" "tr" "undef" "unless" "unshift" "untie" + ;; "until" "use" "while" "y" + "AUTOLOAD\\|BEGIN\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|" + "o\\)\\|DESTROY\\|e\\(ach\\|val\\|xists\\|ls\\(e\\|if\\)\\)\\|" + "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|if\\|keys\\|" + "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|" + "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|" + "q\\(\\|q\\|w\\|x\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|" + "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|" + "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|" + "while\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added manually + "\\|[sm]" ; Added manually + "\\)\\>") 2 'font-lock-other-type-face) + ;; (mapconcat 'identity + ;; '("#endif" "#else" "#ifdef" "#ifndef" "#if" + ;; "#include" "#define" "#undef") + ;; "\\|") + '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0 + font-lock-function-name-face) ; Not very good, triggers at "[a-z]" + '("\\<sub[ \t]+\\([^ \t{]+\\)[ \t]*[{\n]" 1 + font-lock-function-name-face) + '("\\<\\(package\\|require\\|use\\)[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t;]" ; require A if B; + 2 font-lock-function-name-face) + (if (featurep 'font-lock-extra) + '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\([a-zA-Z0-9_:]+\\)[ \t]*}" + (2 font-lock-string-face t) + (0 '(restart 2 t))) ; To highlight $a{bc}{ef} + '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\([a-zA-Z0-9_:]+\\)[ \t]*}" + 2 font-lock-string-face t)) + '("[ \t{,(]\\([a-zA-Z0-9_:]+\\)[ \t]*=>" 1 + font-lock-string-face t) + '("^[ \t]*\\([a-zA-Z0-9_]+[ \t]*:\\)[ \t]*\\($\\|{\\|\\<\\(until\\|while\\|for\\(each\\)?\\|do\\)\\>\\)" 1 + font-lock-reference-face) ; labels + '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets + 2 font-lock-reference-face) + (if (featurep 'font-lock-extra) + '("^[ \t]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%][a-zA-Z0-9_]+\\)\\([ \t]*,\\)?" + (3 font-lock-variable-name-face) + (4 '(another 4 nil + ("[ \t]*,[ \t]*\\([$@%][a-zA-Z0-9_]+\\)\\([ \t]*,\\)?" + (1 font-lock-variable-name-face) + (2 '(restart 2 nil) nil t))) + nil t)) ; local variables, multiple + '("^[ \t]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%][a-zA-Z0-9_]+\\)" + 3 font-lock-variable-name-face)) + '("\\<for\\(each\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*(" + 2 font-lock-variable-name-face))) + (if (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock + (not (cperl-xemacs-p))) ; not yet as of XEmacs 19.12 + (setq t-font-lock-keywords + (append + t-font-lock-keywords + '(("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)" + 1 + (if (= (- (match-end 2) (match-beginning 2)) 1) + (if (eq (char-after (match-beginning 3)) ?{) + font-lock-other-emphasized-face + font-lock-emphasized-face) ; arrays and hashes + font-lock-variable-name-face) ; Just to put something + t) + ("\\(\\([@%]\\|\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1 + (if (eq (char-after (match-beginning 2)) ?%) + font-lock-other-emphasized-face + font-lock-emphasized-face) + t) ; arrays and hashes + ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2") + ;;; Too much noise from \s* @s[ and friends + ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)" + ;;(3 font-lock-function-name-face t t) + ;;(4 + ;; (if (cperl-slash-is-regexp) + ;; font-lock-function-name-face 'default) nil t)) + )))) + (defconst perl-font-lock-keywords t-font-lock-keywords + "Additional expressions to highlight in Perl mode.")) + (if (fboundp 'ps-print-buffer) (cperl-ps-print-init)) + (if (featurep 'font-lock-extra) + (font-lock-require-faces + (list + ;; Color-light Color-dark Gray-light Gray-dark Mono + (list 'font-lock-comment-face + ["Firebrick" "OrangeRed" "DimGray" "Gray80"] + nil + [nil nil t t t] + [nil nil t t t] + nil) + (list 'font-lock-string-face + ["RosyBrown" "LightSalmon" "Gray50" "LightGray"] + nil + nil + [nil nil t t t] + nil) + (list 'font-lock-keyword-face + ["Purple" "LightSteelBlue" "DimGray" "Gray90"] + nil + [nil nil t t t] + nil + nil) + (list 'font-lock-function-name-face + (vector + "Blue" "LightSkyBlue" "Gray50" "LightGray" + (cdr (assq 'background-color ; if mono + (frame-parameters)))) + (vector + nil nil nil nil + (cdr (assq 'foreground-color ; if mono + (frame-parameters)))) + [nil nil t t t] + nil + nil) + (list 'font-lock-variable-name-face + ["DarkGoldenrod" "LightGoldenrod" "DimGray" "Gray90"] + nil + [nil nil t t t] + [nil nil t t t] + nil) + (list 'font-lock-type-face + ["DarkOliveGreen" "PaleGreen" "DimGray" "Gray80"] + nil + [nil nil t t t] + nil + [nil nil t t t] + ) + (list 'font-lock-reference-face + ["CadetBlue" "Aquamarine" "Gray50" "LightGray"] + nil + [nil nil t t t] + nil + [nil nil t t t] + ) + (list 'font-lock-other-type-face + ["chartreuse3" ("orchid1" "orange") + nil "Gray80"] + [nil nil "gray90"] + [nil nil nil t t] + [nil nil t t] + [nil nil t t t] + ) + (list 'font-lock-emphasized-face + ["blue" "yellow" nil "Gray80"] + ["lightyellow2" ("navy" "os2blue" "darkgreen") + "gray90"] + t + nil + nil) + (list 'font-lock-other-emphasized-face + ["red" "red" nil "Gray80"] + ["lightyellow2" ("navy" "os2blue" "darkgreen") + "gray90"] + t + t + nil))) + (defvar cperl-guessed-background nil + "Display characteristics as guessed by cperl.") + (or (fboundp 'x-color-defined-p) + (defalias 'x-color-defined-p + (cond ((fboundp 'color-defined-p) 'color-defined-p) + ;; XEmacs >= 19.12 + ((fboundp 'valid-color-name-p) 'valid-color-name-p) + ;; XEmacs 19.11 + (t 'x-valid-color-name-p)))) + (defvar font-lock-reference-face 'font-lock-reference-face) + (defvar font-lock-variable-name-face 'font-lock-variable-name-face) + (or (boundp 'font-lock-type-face) + (defconst font-lock-type-face + 'font-lock-type-face + "Face to use for data types.") + ) + (or (boundp 'font-lock-other-type-face) + (defconst font-lock-other-type-face + 'font-lock-other-type-face + "Face to use for data types from another group.") + ) + (if (not (cperl-xemacs-p)) nil + (or (boundp 'font-lock-comment-face) + (defconst font-lock-comment-face + 'font-lock-comment-face + "Face to use for comments.") + ) + (or (boundp 'font-lock-keyword-face) + (defconst font-lock-keyword-face + 'font-lock-keyword-face + "Face to use for keywords.") + ) + (or (boundp 'font-lock-function-name-face) + (defconst font-lock-function-name-face + 'font-lock-function-name-face + "Face to use for function names.") + ) + ) + ;;(if (featurep 'font-lock) + (if (face-equal font-lock-type-face font-lock-comment-face) + (defconst font-lock-type-face + 'font-lock-type-face + "Face to use for basic data types.") + ) +;;; (if (fboundp 'eval-after-load) +;;; (eval-after-load "font-lock" +;;; '(if (face-equal font-lock-type-face +;;; font-lock-comment-face) +;;; (defconst font-lock-type-face +;;; 'font-lock-type-face +;;; "Face to use for basic data types.") +;;; ))) ; This does not work :-( Why?! +;;; ; Workaround: added to font-lock-m-h +;;; ) + (or (boundp 'font-lock-other-emphasized-face) + (defconst font-lock-other-emphasized-face + 'font-lock-other-emphasized-face + "Face to use for another type of emphasizing.") + ) + (or (boundp 'font-lock-emphasized-face) + (defconst font-lock-emphasized-face + 'font-lock-emphasized-face + "Face to use for emphasizing.") + ) + ;; Here we try to guess background + (let ((background + (if (boundp 'font-lock-background-mode) + font-lock-background-mode + 'light)) + (face-list (and (fboundp 'face-list) (face-list))) + is-face) + (fset 'is-face + (cond ((fboundp 'find-face) + (symbol-function 'find-face)) + (face-list + (function (lambda (face) (member face face-list)))) + (t + (function (lambda (face) (boundp face)))))) + (defvar cperl-guessed-background + (if (and (boundp 'font-lock-display-type) + (eq font-lock-display-type 'grayscale)) + 'gray + background) + "Background as guessed by CPerl mode") + (if (is-face 'font-lock-type-face) nil + (copy-face 'default 'font-lock-type-face) + (cond + ((eq background 'light) + (set-face-foreground 'font-lock-type-face + (if (x-color-defined-p "seagreen") + "seagreen" + "sea green"))) + ((eq background 'dark) + (set-face-foreground 'font-lock-type-face + (if (x-color-defined-p "os2pink") + "os2pink" + "pink"))) + (t + (set-face-background 'font-lock-type-face "gray90")))) + (if (is-face 'font-lock-other-type-face) + nil + (copy-face 'font-lock-type-face 'font-lock-other-type-face) + (cond + ((eq background 'light) + (set-face-foreground 'font-lock-other-type-face + (if (x-color-defined-p "chartreuse3") + "chartreuse3" + "chartreuse"))) + ((eq background 'dark) + (set-face-foreground 'font-lock-other-type-face + (if (x-color-defined-p "orchid1") + "orchid1" + "orange"))))) + (if (is-face 'font-lock-other-emphasized-face) nil + (copy-face 'bold-italic 'font-lock-other-emphasized-face) + (cond + ((eq background 'light) + (set-face-background 'font-lock-other-emphasized-face + (if (x-color-defined-p "lightyellow2") + "lightyellow2" + (if (x-color-defined-p "lightyellow") + "lightyellow" + "light yellow")))) + ((eq background 'dark) + (set-face-background 'font-lock-other-emphasized-face + (if (x-color-defined-p "navy") + "navy" + (if (x-color-defined-p "darkgreen") + "darkgreen" + "dark green")))) + (t (set-face-background 'font-lock-other-emphasized-face "gray90")))) + (if (is-face 'font-lock-emphasized-face) nil + (copy-face 'bold 'font-lock-emphasized-face) + (cond + ((eq background 'light) + (set-face-background 'font-lock-emphasized-face + (if (x-color-defined-p "lightyellow2") + "lightyellow2" + "lightyellow"))) + ((eq background 'dark) + (set-face-background 'font-lock-emphasized-face + (if (x-color-defined-p "navy") + "navy" + (if (x-color-defined-p "darkgreen") + "darkgreen" + "dark green")))) + (t (set-face-background 'font-lock-emphasized-face "gray90")))) + (if (is-face 'font-lock-variable-name-face) nil + (copy-face 'italic 'font-lock-variable-name-face)) + (if (is-face 'font-lock-reference-face) nil + (copy-face 'italic 'font-lock-reference-face))))) + (error nil))) + + +(defun cperl-ps-print-init () + "Initialization of `ps-print' components for faces used in CPerl." + ;; Guard against old versions + (defvar ps-underlined-faces nil) + (defvar ps-bold-faces nil) + (defvar ps-italic-faces nil) + (setq ps-bold-faces + (append '(font-lock-emphasized-face + font-lock-keyword-face + font-lock-variable-name-face + font-lock-reference-face + font-lock-other-emphasized-face) + ps-bold-faces)) + (setq ps-italic-faces + (append '(font-lock-other-type-face + font-lock-reference-face + font-lock-other-emphasized-face) + ps-italic-faces)) + (setq ps-underlined-faces + (append '(font-lock-emphasized-face + font-lock-other-emphasized-face + font-lock-other-type-face font-lock-type-face) + ps-underlined-faces)) + (cons 'font-lock-type-face ps-underlined-faces)) + + +(if (cperl-enable-font-lock) (cperl-windowed-init)) + +(defun cperl-set-style (style) + "Set CPerl-mode variables to use one of several different indentation styles. +The arguments are a string representing the desired style. +Available styles are GNU, K&R, BSD and Whitesmith." + (interactive + (let ((list (mapcar (function (lambda (elt) (list (car elt)))) + c-style-alist))) + (list (completing-read "Enter style: " list nil 'insist)))) + (let ((style (cdr (assoc style c-style-alist))) setting str sym) + (while style + (setq setting (car style) style (cdr style)) + (setq str (symbol-name (car setting))) + (and (string-match "^c-" str) + (setq str (concat "cperl-" (substring str 2))) + (setq sym (intern-soft str)) + (boundp sym) + (set sym (cdr setting)))))) + +(defun cperl-check-syntax () + (interactive) + (require 'mode-compile) + (let ((perl-dbg-flags "-wc")) + (mode-compile))) + +(defun cperl-info-buffer () + ;; Returns buffer with documentation. Creats if missing + (let ((info (get-buffer "*info-perl*"))) + (if info info + (save-window-excursion + ;; Get Info running + (require 'info) + (save-window-excursion + (info)) + (Info-find-node "perl5" "perlfunc") + (set-buffer "*info*") + (rename-buffer "*info-perl*") + (current-buffer))))) + +(defun cperl-word-at-point (&optional p) + ;; Returns the word at point or at P. + (save-excursion + (if p (goto-char p)) + (require 'etags) + (funcall (or (and (boundp 'find-tag-default-function) + find-tag-default-function) + (get major-mode 'find-tag-default-function) + ;; XEmacs 19.12 has `find-tag-default-hook'; it is + ;; automatically used within `find-tag-default': + 'find-tag-default)))) + +(defun cperl-info-on-command (command) + "Shows documentation for Perl command in other window." + (interactive + (let* ((default (cperl-word-at-point)) + (read (read-string + (format "Find doc for Perl function (default %s): " + default)))) + (list (if (equal read "") + default + read)))) + + (let ((buffer (current-buffer)) + (cmd-desc (concat "^" (regexp-quote command) "[ \t\n]")) + pos) + (if (string-match "^-[a-zA-Z]$" command) + (setq cmd-desc "^-X[ \t\n]")) + (set-buffer (cperl-info-buffer)) + (beginning-of-buffer) + (re-search-forward "^-X[ \t\n]") + (forward-line -1) + (if (re-search-forward cmd-desc nil t) + (progn + (setq pos (progn (beginning-of-line) + (point))) + (pop-to-buffer (cperl-info-buffer)) + (set-window-start (selected-window) pos)) + (message "No entry for %s found." command)) + (pop-to-buffer buffer))) + +(defun cperl-info-on-current-command () + "Shows documentation for Perl command at point in other window." + (interactive) + (cperl-info-on-command (cperl-word-at-point))) + +(defun cperl-imenu-info-imenu-search () + (if (looking-at "^-X[ \t\n]") nil + (re-search-backward + "^\n\\([-a-zA-Z]+\\)[ \t\n]") + (forward-line 1))) + +(defun cperl-imenu-info-imenu-name () + (buffer-substring + (match-beginning 1) (match-end 1))) + +(defun cperl-imenu-on-info () + (interactive) + (let* ((buffer (current-buffer)) + imenu-create-index-function + imenu-prev-index-position-function + imenu-extract-index-name-function + (index-item (save-restriction + (save-window-excursion + (set-buffer (cperl-info-buffer)) + (setq imenu-create-index-function + 'imenu-default-create-index-function + imenu-prev-index-position-function + 'cperl-imenu-info-imenu-search + imenu-extract-index-name-function + 'cperl-imenu-info-imenu-name) + (imenu-choose-buffer-index))))) + (and index-item + (progn + (push-mark) + (pop-to-buffer "*info-perl*") + (cond + ((markerp (cdr index-item)) + (goto-char (marker-position (cdr index-item)))) + (t + (goto-char (cdr index-item)))) + (set-window-start (selected-window) (point)) + (pop-to-buffer buffer))))) + +(defun cperl-lineup (beg end &optional step minshift) + "Lineup construction in a region. +Beginning of region should be at the start of a construction. +All first occurences of this construction in the lines that are +partially contained in the region are lined up at the same column. + +MINSHIFT is the minimal amount of space to insert before the construction. +STEP is the tabwidth to position constructions. +If STEP is `nil', `cperl-lineup-step' will be used +\(or `cperl-indent-level', if `cperl-lineup-step' is `nil'). +Will not move the position at the start to the left." + (interactive "r") + (let (search col tcol seen b e) + (save-excursion + (goto-char end) + (end-of-line) + (setq end (point-marker)) + (goto-char beg) + (skip-chars-forward " \t\f") + (setq beg (point-marker)) + (indent-region beg end nil) + (goto-char beg) + (setq col (current-column)) + (if (looking-at "\\sw") + (if (looking-at "\\<\\sw+\\>") + (setq search + (concat "\\<" + (regexp-quote + (buffer-substring (match-beginning 0) + (match-end 0))) "\\>")) + (error "Cannot line up in a middle of the word")) + (if (looking-at "$") + (error "Cannot line up end of line")) + (setq search (regexp-quote (char-to-string (following-char))))) + (setq step (or step cperl-lineup-step cperl-indent-level)) + (or minshift (setq minshift 1)) + (while (progn + (beginning-of-line 2) + (and (< (point) end) + (re-search-forward search end t) + (goto-char (match-beginning 0)))) + (setq tcol (current-column) seen t) + (if (> tcol col) (setq col tcol))) + (or seen + (error "The construction to line up occured only once")) + (goto-char beg) + (setq col (+ col minshift)) + (if (/= (% col step) 0) (setq step (* step (1+ (/ col step))))) + (while + (progn + (setq e (point)) + (skip-chars-backward " \t") + (delete-region (point) e) + (indent-to-column col); (make-string (- col (current-column)) ?\ )) + (beginning-of-line 2) + (and (< (point) end) + (re-search-forward search end t) + (goto-char (match-beginning 0)))))))) ; No body + +(defun cperl-etags (&optional add all files) + "Run etags with appropriate options for Perl files. +If optional argument ALL is `recursive', will process Perl files +in subdirectories too." + (interactive) + (let ((cmd "etags") + (args '("-l" "none" "-r" "/\\<\\(package\\|sub\\)[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)[ \\t]*\\([{#]\\|$\\)\\)/\\4/")) + res) + (if add (setq args (cons "-a" args))) + (or files (setq files (list buffer-file-name))) + (cond + ((eq all 'recursive) + ;;(error "Not implemented: recursive") + (setq args (append (list "-e" + "sub wanted {push @ARGV, $File::Find::name if /\\.[Pp][Llm]$/} + use File::Find; + find(\\&wanted, '.'); + exec @ARGV;" + cmd) args) + cmd "perl")) + (all + ;;(error "Not implemented: all") + (setq args (append (list "-e" + "push @ARGV, <*.PL *.pl *.pm>; + exec @ARGV;" + cmd) args) + cmd "perl")) + (t + (setq args (append args files)))) + (setq res (apply 'call-process cmd nil nil nil args)) + (or (eq res 0) + (message "etags returned \"%s\"" res)))) diff --git a/emacs/emacs19 b/emacs/emacs19 deleted file mode 100644 index c3bb070a64..0000000000 --- a/emacs/emacs19 +++ /dev/null @@ -1,312 +0,0 @@ -Article 15041 of comp.lang.perl: -Path: netlabs!news.cerf.net!usc!sol.ctr.columbia.edu!news.kei.com!bloom-beacon.mit.edu!paperboy.osf.org!meissner -From: meissner@osf.org (Michael Meissner) -Newsgroups: comp.lang.perl -Subject: Re: question on using perldb.el with emacs -Date: 17 Oct 1993 21:10:21 GMT -Organization: Open Software Foundation -Lines: 297 -Message-ID: <MEISSNER.93Oct17171021@pasta.osf.org> -References: <BSHAW.93Oct17143524@bobasun.spdc.ti.com> -NNTP-Posting-Host: pasta.osf.org -In-reply-to: bshaw@bobasun.spdc.ti.com's message of Sun, 17 Oct 1993 19:35:24 GMT - -In article <BSHAW.93Oct17143524@bobasun.spdc.ti.com> bshaw@bobasun.spdc.ti.com -(Bob Shaw) writes: - -| Hi folks -| -| Say, I'm trying to use perldb with emacs. I can invoke perldb -| within emacs ok and get the window *perldb-foo* but when it asks -| for "additional command line arguments" , no matter what I give it -| I get the error message Symbol's function definition is void: make- -| shell. -| -| The debugger , by itself, works fine but wanted to try out perldb in -| emacs. - -This is a symptom of using Emacs 19.xx with perldb.el which was originally made -for emacs version 18.xx. You can either install the emacs19 replacement for -perldb that hooks it in with GUD (grand unified debugger), or apply the patches -that I picked off of the net (I use the perldb replacement that uses GUD -myself): - -#!/bin/sh -# This is a shell archive (produced by shar 3.49) -# To extract the files from this archive, save it to a file, remove -# everything above the "!/bin/sh" line above, and type "sh file_name". -# -# made 10/17/1993 21:07 UTC by meissner@pasta.osf.org -# Source directory /usr/users/meissner/elisp -# -# existing files will NOT be overwritten unless -c is specified -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 4761 -rw-r--r-- emacs19-perldb.el -# 3845 -rw-rw-r-- emacs19-perldb.patches -# -# ============= emacs19-perldb.el ============== -if test -f 'emacs19-perldb.el' -a X"$1" != X"-c"; then - echo 'x - skipping emacs19-perldb.el (File already exists)' -else -echo 'x - extracting emacs19-perldb.el (Text)' -sed 's/^X//' << 'SHAR_EOF' > 'emacs19-perldb.el' && -X;; Author : Stephane Boucher -X;; Note : This is an add on for gud (Part of GNU Emacs 19). It is -X;; derived from the gdb section that is part of gud. -X -X;; Copyright (C) 1993 Stephane Boucher. -X -X;; Perldb is free software; you can redistribute it and/or modify -X;; it under the terms of the GNU General Public License as published by -X;; the Free Software Foundation; either version 2, or (at your option) -X;; any later version. -X -X;; Perldb Emacs is distributed in the hope that it will be useful, -X;; but WITHOUT ANY WARRANTY; without even the implied warranty of -X;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -X;; GNU General Public License for more details. -X -X;; You should have received a copy of the GNU General Public License -X;; along with GNU Emacs; see the file COPYING. If not, write to -X;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -X -X(require 'gud) -X -X;; ====================================================================== -X;; perldb functions -X -X;;; History of argument lists passed to perldb. -X(defvar gud-perldb-history nil) -X -X(defun gud-perldb-massage-args (file args) -X (cons "-d" (cons file (cons "-emacs" args)))) -X -X;; There's no guarantee that Emacs will hand the filter the entire -X;; marker at once; it could be broken up across several strings. We -X;; might even receive a big chunk with several markers in it. If we -X;; receive a chunk of text which looks like it might contain the -X;; beginning of a marker, we save it here between calls to the -X;; filter. -X(defvar gud-perldb-marker-acc "") -X -X(defun gud-perldb-marker-filter (string) -X (save-match-data -X (setq gud-perldb-marker-acc (concat gud-perldb-marker-acc string)) -X (let ((output "")) -X -X ;; Process all the complete markers in this chunk. -X (while (string-match "^\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" -X gud-perldb-marker-acc) -X (setq -X -X ;; Extract the frame position from the marker. -X gud-last-frame -X (cons (substring gud-perldb-marker-acc (match-beginning 1) (match-end 1)) -X (string-to-int (substring gud-perldb-marker-acc -X (match-beginning 2) -X (match-end 2)))) -X -X ;; Append any text before the marker to the output we're going -X ;; to return - we don't include the marker in this text. -X output (concat output -X (substring gud-perldb-marker-acc 0 (match-beginning 0))) -X -X ;; Set the accumulator to the remaining text. -X gud-perldb-marker-acc (substring gud-perldb-marker-acc (match-end 0)))) -X -X ;; Does the remaining text look like it might end with the -X ;; beginning of another marker? If it does, then keep it in -X ;; gud-perldb-marker-acc until we receive the rest of it. Since we -X ;; know the full marker regexp above failed, it's pretty simple to -X ;; test for marker starts. -X (if (string-match "^\032.*\\'" gud-perldb-marker-acc) -X (progn -X ;; Everything before the potential marker start can be output. -X (setq output (concat output (substring gud-perldb-marker-acc -X 0 (match-beginning 0)))) -X -X ;; Everything after, we save, to combine with later input. -X (setq gud-perldb-marker-acc -X (substring gud-perldb-marker-acc (match-beginning 0)))) -X -X (setq output (concat output gud-perldb-marker-acc) -X gud-perldb-marker-acc "")) -X -X output))) -X -X(defun gud-perldb-find-file (f) -X (find-file-noselect f)) -X -X;;;###autoload -X(defun perldb (command-line) -X "Run perldb on program FILE in buffer *gud-FILE*. -XThe directory containing FILE becomes the initial working directory -Xand source-file directory for your debugger." -X (interactive -X (list (read-from-minibuffer "Run perldb (like this): " -X (if (consp gud-perldb-history) -X (car gud-perldb-history) -X "perl ") -X nil nil -X '(gud-perldb-history . 1)))) -X (gud-overload-functions '((gud-massage-args . gud-perldb-massage-args) -X (gud-marker-filter . gud-perldb-marker-filter) -X (gud-find-file . gud-perldb-find-file) -X )) -X -X (gud-common-init command-line) -X -X (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") -X (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line") -X (gud-def gud-step "s" "\C-s" "Step one source line with display.") -X (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") -X (gud-def gud-cont "c" "\C-r" "Continue with display.") -X; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") -X; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") -X; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") -X (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.") -X -X (setq comint-prompt-regexp "^ DB<[0-9]+> ") -X (run-hooks 'perldb-mode-hook) -X ) -SHAR_EOF -chmod 0644 emacs19-perldb.el || -echo 'restore of emacs19-perldb.el failed' -Wc_c="`wc -c < 'emacs19-perldb.el'`" -test 4761 -eq "$Wc_c" || - echo 'emacs19-perldb.el: original size 4761, current size' "$Wc_c" -fi -# ============= emacs19-perldb.patches ============== -if test -f 'emacs19-perldb.patches' -a X"$1" != X"-c"; then - echo 'x - skipping emacs19-perldb.patches (File already exists)' -else -echo 'x - extracting emacs19-perldb.patches (Text)' -sed 's/^X//' << 'SHAR_EOF' > 'emacs19-perldb.patches' && -XFrom dmm0t@rincewind.mech.virginia.edu Fri Jul 16 23:17:10 1993 -XPath: paperboy.osf.org!bloom-beacon.mit.edu!biosci!uwm.edu!ux1.cso.uiuc.edu!howland.reston.ans.net!darwin.sura.net!news-feed-2.peachnet.edu!concert!uvaarpa!murdoch!rincewind.mech.virginia.edu!dmm0t -XFrom: dmm0t@rincewind.mech.virginia.edu (David Meyer) -XNewsgroups: gnu.emacs.sources -XSubject: patches to perldb.el for emacs-19 -XMessage-ID: <CA7uq9.30J@murdoch.acc.Virginia.EDU> -XDate: 15 Jul 93 17:18:07 GMT -XSender: usenet@murdoch.acc.Virginia.EDU -XOrganization: University of Virginia -XLines: 97 -X -X -XHere are my patches to perldb.el (the perl debugger mode that comes -Xwith perl 4.0xx). Basically, all I've done is to hack perldb.el to -Xuse comint.el stuff rather than the old shell.el stuff (i.e. change -Xshell-mode-map to comint-mode-map). -X -XI've been using my patched version without problem, but if anyone sees -Xsomething I've missed, please post or send e-mail. -X -X Thanks, -X Dave -X -X -X*** /Users/dmm0t/perldb.el Thu Jul 15 13:06:59 1993 -X--- perldb.el Tue Jul 6 22:24:41 1993 -X*************** -X*** 65,71 **** -X -X (if perldb-mode-map -X nil -X! (setq perldb-mode-map (copy-keymap shell-mode-map)) -X (define-key perldb-mode-map "\C-l" 'perldb-refresh)) -X -X (define-key ctl-x-map " " 'perldb-break) -X--- 65,71 ---- -X -X (if perldb-mode-map -X nil -X! (setq perldb-mode-map (copy-keymap comint-mode-map)) -X (define-key perldb-mode-map "\C-l" 'perldb-refresh)) -X -X (define-key ctl-x-map " " 'perldb-break) -X*************** -X*** 122,131 **** -X (setq mode-name "Inferior Perl") -X (setq mode-line-process '(": %s")) -X (use-local-map perldb-mode-map) -X! (make-local-variable 'last-input-start) -X! (setq last-input-start (make-marker)) -X! (make-local-variable 'last-input-end) -X! (setq last-input-end (make-marker)) -X (make-local-variable 'perldb-last-frame) -X (setq perldb-last-frame nil) -X (make-local-variable 'perldb-last-frame-displayed-p) -X--- 122,131 ---- -X (setq mode-name "Inferior Perl") -X (setq mode-line-process '(": %s")) -X (use-local-map perldb-mode-map) -X! (make-local-variable 'comint-last-input-start) -X! (setq comint-last-input-start (make-marker)) -X! (make-local-variable 'comint-last-input-end) -X! (setq comint-last-input-end (make-marker)) -X (make-local-variable 'perldb-last-frame) -X (setq perldb-last-frame nil) -X (make-local-variable 'perldb-last-frame-displayed-p) -X*************** -X*** 134,142 **** -X (setq perldb-delete-prompt-marker nil) -X (make-local-variable 'perldb-filter-accumulator) -X (setq perldb-filter-accumulator nil) -X! (make-local-variable 'shell-prompt-pattern) -X! (setq shell-prompt-pattern perldb-prompt-pattern) -X! (run-hooks 'shell-mode-hook 'perldb-mode-hook)) -X -X (defvar current-perldb-buffer nil) -X -X--- 134,142 ---- -X (setq perldb-delete-prompt-marker nil) -X (make-local-variable 'perldb-filter-accumulator) -X (setq perldb-filter-accumulator nil) -X! (make-local-variable 'comint-prompt-regexp) -X! (setq comint-prompt-regexp perldb-prompt-pattern) -X! (run-hooks 'comint-mode-hook 'perldb-mode-hook)) -X -X (defvar current-perldb-buffer nil) -X -X*************** -X*** 189,195 **** -X (setq default-directory dir) -X (or (bolp) (newline)) -X (insert "Current directory is " default-directory "\n") -X! (apply 'make-shell -X (concat "perldb-" file) perldb-command-name nil "-d" path "-emacs" -X (parse-args args)) -X (perldb-mode) -X--- 189,195 ---- -X (setq default-directory dir) -X (or (bolp) (newline)) -X (insert "Current directory is " default-directory "\n") -X! (apply 'make-comint -X (concat "perldb-" file) perldb-command-name nil "-d" path "-emacs" -X (parse-args args)) -X (perldb-mode) -X-- -XDavid M. Meyer Mechanical & Aerospace Engineering -Xdmm0t@rincewind.mech.virginia.edu University of Virginia -XNeXTmail ok -X -SHAR_EOF -chmod 0664 emacs19-perldb.patches || -echo 'restore of emacs19-perldb.patches failed' -Wc_c="`wc -c < 'emacs19-perldb.patches'`" -test 3845 -eq "$Wc_c" || - echo 'emacs19-perldb.patches: original size 3845, current size' "$Wc_c" -fi -exit 0 - --- -Michael Meissner email: meissner@osf.org phone: 617-621-8861 -Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 - -Old hackers never die, their bugs just increase. - - diff --git a/emacs/perl-mode.el b/emacs/perl-mode.el deleted file mode 100644 index cb6195dec3..0000000000 --- a/emacs/perl-mode.el +++ /dev/null @@ -1,631 +0,0 @@ -;; Perl code editing commands for GNU Emacs -;; Copyright (C) 1990 William F. Mann -;; 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 may be made part of GNU Emacs at the option of the FSF, or -;; of the perl distribution at the option of Larry Wall. - -;; This code is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY. No author or distributor -;; accepts responsibility to anyone for the consequences of using it -;; or for whether it serves any particular purpose or works at all, -;; unless he says so in writing. Refer to the GNU Emacs General Public -;; License for full details. - -;; Everyone is granted permission to copy, modify and redistribute -;; this code, but only under the conditions described in the -;; GNU Emacs General Public License. A copy of this license is -;; supposed to have been given to you along with GNU Emacs so you -;; can know your rights and responsibilities. It should be in a -;; file named COPYING. Among other things, the copyright notice -;; and this notice must be preserved on all copies. - -;; 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 elisp -;; 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 delimitors 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$//; - - -(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) -) - -(defconst perl-indent-level 4 - "*Indentation of Perl statements with respect to containing block.") -(defconst perl-continued-statement-offset 4 - "*Extra indent for lines not starting new statements.") -(defconst perl-continued-brace-offset -4 - "*Extra indent for substatements that start with open-braces. -This is in addition to perl-continued-statement-offset.") -(defconst perl-brace-offset 0 - "*Extra indentation for braces, compared with other text in same context.") -(defconst perl-brace-imaginary-offset 0 - "*Imagined indentation of an open brace that actually follows a statement.") -(defconst perl-label-offset -2 - "*Offset of Perl label lines relative to usual indentation.") - -(defconst perl-tab-always-indent t - "*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.") - -(defconst perl-tab-to-comment t - "*Non-nil means that for lines which don't need indenting, TAB will -either indent an existing comment, move to end-of-line, or if at end-of-line -already, create a new comment.") - -(defconst perl-nochange ";?#\\|\f\\|\\s(\\|\\(\\w\\|\\s_\\)+:" - "*Lines starting with this regular expression will not be auto-indented.") - -(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 will not be 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 calls the value of the variable perl-mode-hook with no -args, if that value is non-nil." - (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-hook) - (setq comment-indent-hook 'perl-comment-indent) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments nil) - (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. If at end-of-line, and not in a comment or a quote, -correct the line'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/emacs/perldb.el b/emacs/perldb.el deleted file mode 100644 index 66951be26d..0000000000 --- a/emacs/perldb.el +++ /dev/null @@ -1,423 +0,0 @@ -;; Run perl -d under Emacs -;; Based on gdb.el, as written by W. Schelter, and modified by rms. -;; Modified for Perl by Ray Lischner (uunet!mntgfx!lisch), Nov 1990. - -;; This file is part of GNU Emacs. -;; Copyright (C) 1988,1990 Free Software Foundation, Inc. - -;; GNU Emacs is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY. No author or distributor accepts responsibility -;; to anyone for the consequences of using it or for whether it serves -;; any particular purpose or works at all, unless he says so in writing. -;; Refer to the GNU Emacs General Public License for full details. - -;; Everyone is granted permission to copy, modify and redistribute GNU -;; Emacs, but only under the conditions described in the GNU Emacs -;; General Public License. A copy of this license is supposed to have -;; been given to you along with GNU Emacs so you can know your rights and -;; responsibilities. It should be in a file named COPYING. Among other -;; things, the copyright notice and this notice must be preserved on all -;; copies. - -;; Description of perl -d interface: - -;; A facility is provided for the simultaneous display of the source code -;; in one window, while using perldb to step through a function in the -;; other. A small arrow in the source window, indicates the current -;; line. - -;; Starting up: - -;; In order to use this facility, invoke the command PERLDB to obtain a -;; shell window with the appropriate command bindings. You will be asked -;; for the name of a file to run and additional command line arguments. -;; Perldb will be invoked on this file, in a window named *perldb-foo* -;; if the file is foo. - -;; M-s steps by one line, and redisplays the source file and line. - -;; You may easily create additional commands and bindings to interact -;; with the display. For example to put the perl debugger command n on \M-n -;; (def-perldb n "\M-n") - -;; This causes the emacs command perldb-next to be defined, and runs -;; perldb-display-frame after the command. - -;; perldb-display-frame is the basic display function. It tries to display -;; in the other window, the file and line corresponding to the current -;; position in the perldb window. For example after a perldb-step, it would -;; display the line corresponding to the position for the last step. Or -;; if you have done a backtrace in the perldb buffer, and move the cursor -;; into one of the frames, it would display the position corresponding to -;; that frame. - -;; perldb-display-frame is invoked automatically when a filename-and-line-number -;; appears in the output. - - -(require 'shell) - -(defvar perldb-prompt-pattern "^ DB<[0-9]+> " - "A regexp to recognize the prompt for perldb.") - -(defvar perldb-mode-map nil - "Keymap for perldb-mode.") - -(if perldb-mode-map - nil - (setq perldb-mode-map (copy-keymap shell-mode-map)) - (define-key perldb-mode-map "\C-l" 'perldb-refresh)) - -(define-key ctl-x-map " " 'perldb-break) -(define-key ctl-x-map "&" 'send-perldb-command) - -;;Of course you may use `def-perldb' with any other perldb command, including -;;user defined ones. - -(defmacro def-perldb (name key &optional doc) - (let* ((fun (intern (concat "perldb-" name)))) - (` (progn - (defun (, fun) (arg) - (, (or doc "")) - (interactive "p") - (perldb-call (if (not (= 1 arg)) - (concat (, name) arg) - (, name)))) - (define-key perldb-mode-map (, key) (quote (, fun))))))) - -(def-perldb "s" "\M-s" "Step one source line with display") -(def-perldb "n" "\M-n" "Step one source line (skip functions)") -(def-perldb "c" "\M-c" "Continue with display") -(def-perldb "r" "\C-c\C-r" "Return from current subroutine") -(def-perldb "A" "\C-c\C-a" "Delete all actions") - -(defun perldb-mode () - "Major mode for interacting with an inferior Perl debugger process. -The following commands are available: - -\\{perldb-mode-map} - -\\[perldb-display-frame] displays in the other window -the last line referred to in the perldb buffer. - -\\[perldb-s],\\[perldb-n], and \\[perldb-n] in the perldb window, -call perldb to step, next or continue and then update the other window -with the current file and position. - -If you are in a source file, you may select a point to break -at, by doing \\[perldb-break]. - -Commands: -Many commands are inherited from shell mode. -Additionally we have: - -\\[perldb-display-frame] display frames file in other window -\\[perldb-s] advance one line in program -\\[perldb-n] advance one line in program (skip over calls). -\\[send-perldb-command] used for special printing of an arg at the current point. -C-x SPACE sets break point at current line." - (interactive) - (kill-all-local-variables) - (setq major-mode 'perldb-mode) - (setq mode-name "Inferior Perl") - (setq mode-line-process '(": %s")) - (use-local-map perldb-mode-map) - (make-local-variable 'last-input-start) - (setq last-input-start (make-marker)) - (make-local-variable 'last-input-end) - (setq last-input-end (make-marker)) - (make-local-variable 'perldb-last-frame) - (setq perldb-last-frame nil) - (make-local-variable 'perldb-last-frame-displayed-p) - (setq perldb-last-frame-displayed-p t) - (make-local-variable 'perldb-delete-prompt-marker) - (setq perldb-delete-prompt-marker nil) - (make-local-variable 'perldb-filter-accumulator) - (setq perldb-filter-accumulator nil) - (make-local-variable 'shell-prompt-pattern) - (setq shell-prompt-pattern perldb-prompt-pattern) - (run-hooks 'shell-mode-hook 'perldb-mode-hook)) - -(defvar current-perldb-buffer nil) - -(defvar perldb-command-name "perl" - "Pathname for executing perl -d.") - -(defun end-of-quoted-arg (argstr start end) - (let* ((chr (substring argstr start (1+ start))) - (idx (string-match (concat "[^\\]" chr) argstr (1+ start)))) - (and idx (1+ idx)) - ) -) - -(defun parse-args-helper (arglist argstr start end) - (while (and (< start end) (string-match "[ \t\n\f\r\b]" - (substring argstr start (1+ start)))) - (setq start (1+ start))) - (cond - ((= start end) arglist) - ((string-match "[\"']" (substring argstr start (1+ start))) - (let ((next (end-of-quoted-arg argstr start end))) - (parse-args-helper (cons (substring argstr (1+ start) next) arglist) - argstr (1+ next) end))) - (t (let ((next (string-match "[ \t\n\f\b\r]" argstr start))) - (if next - (parse-args-helper (cons (substring argstr start next) arglist) - argstr (1+ next) end) - (cons (substring argstr start) arglist)))) - ) - ) - -(defun parse-args (args) - "Extract arguments from a string ARGS. -White space separates arguments, with single or double quotes -used to protect spaces. A list of strings is returned, e.g., -(parse-args \"foo bar 'two args'\") => (\"foo\" \"bar\" \"two args\")." - (nreverse (parse-args-helper '() args 0 (length args))) -) - -(defun perldb (path args) - "Run perldb on program FILE in buffer *perldb-FILE*. -The default directory for the current buffer becomes the initial -working directory, by analogy with gdb . If you wish to change this, use -the Perl command `chdir(DIR)'." - (interactive "FRun perl -d on file: \nsCommand line arguments: ") - (setq path (expand-file-name path)) - (let ((file (file-name-nondirectory path)) - (dir default-directory)) - (switch-to-buffer (concat "*perldb-" file "*")) - (setq default-directory dir) - (or (bolp) (newline)) - (insert "Current directory is " default-directory "\n") - (apply 'make-shell - (concat "perldb-" file) perldb-command-name nil "-d" path "-emacs" - (parse-args args)) - (perldb-mode) - (set-process-filter (get-buffer-process (current-buffer)) 'perldb-filter) - (set-process-sentinel (get-buffer-process (current-buffer)) 'perldb-sentinel) - (perldb-set-buffer))) - -(defun perldb-set-buffer () - (cond ((eq major-mode 'perldb-mode) - (setq current-perldb-buffer (current-buffer))))) - -;; This function is responsible for inserting output from Perl -;; into the buffer. -;; Aside from inserting the text, it notices and deletes -;; each filename-and-line-number; -;; that Perl prints to identify the selected frame. -;; It records the filename and line number, and maybe displays that file. -(defun perldb-filter (proc string) - (let ((inhibit-quit t)) - (if perldb-filter-accumulator - (perldb-filter-accumulate-marker proc - (concat perldb-filter-accumulator string)) - (perldb-filter-scan-input proc string)))) - -(defun perldb-filter-accumulate-marker (proc string) - (setq perldb-filter-accumulator nil) - (if (> (length string) 1) - (if (= (aref string 1) ?\032) - (let ((end (string-match "\n" string))) - (if end - (progn - (let* ((first-colon (string-match ":" string 2)) - (second-colon - (string-match ":" string (1+ first-colon)))) - (setq perldb-last-frame - (cons (substring string 2 first-colon) - (string-to-int - (substring string (1+ first-colon) - second-colon))))) - (setq perldb-last-frame-displayed-p nil) - (perldb-filter-scan-input proc - (substring string (1+ end)))) - (setq perldb-filter-accumulator string))) - (perldb-filter-insert proc "\032") - (perldb-filter-scan-input proc (substring string 1))) - (setq perldb-filter-accumulator string))) - -(defun perldb-filter-scan-input (proc string) - (if (equal string "") - (setq perldb-filter-accumulator nil) - (let ((start (string-match "\032" string))) - (if start - (progn (perldb-filter-insert proc (substring string 0 start)) - (perldb-filter-accumulate-marker proc - (substring string start))) - (perldb-filter-insert proc string))))) - -(defun perldb-filter-insert (proc string) - (let ((moving (= (point) (process-mark proc))) - (output-after-point (< (point) (process-mark proc))) - (old-buffer (current-buffer)) - start) - (set-buffer (process-buffer proc)) - (unwind-protect - (save-excursion - ;; Insert the text, moving the process-marker. - (goto-char (process-mark proc)) - (setq start (point)) - (insert string) - (set-marker (process-mark proc) (point)) - (perldb-maybe-delete-prompt) - ;; Check for a filename-and-line number. - (perldb-display-frame - ;; Don't display the specified file - ;; unless (1) point is at or after the position where output appears - ;; and (2) this buffer is on the screen. - (or output-after-point - (not (get-buffer-window (current-buffer)))) - ;; Display a file only when a new filename-and-line-number appears. - t)) - (set-buffer old-buffer)) - (if moving (goto-char (process-mark proc))))) - -(defun perldb-sentinel (proc msg) - (cond ((null (buffer-name (process-buffer proc))) - ;; buffer killed - ;; Stop displaying an arrow in a source file. - (setq overlay-arrow-position nil) - (set-process-buffer proc nil)) - ((memq (process-status proc) '(signal exit)) - ;; Stop displaying an arrow in a source file. - (setq overlay-arrow-position nil) - ;; Fix the mode line. - (setq mode-line-process - (concat ": " - (symbol-name (process-status proc)))) - (let* ((obuf (current-buffer))) - ;; save-excursion isn't the right thing if - ;; process-buffer is current-buffer - (unwind-protect - (progn - ;; Write something in *compilation* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) - (if (eobp) - (insert ?\n mode-name " " msg) - (save-excursion - (goto-char (point-max)) - (insert ?\n mode-name " " msg))) - ;; If 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)) - ;; Restore old buffer, but don't restore old point - ;; if obuf is the perldb buffer. - (set-buffer obuf)))))) - - -(defun perldb-refresh () - "Fix up a possibly garbled display, and redraw the arrow." - (interactive) - (redraw-display) - (perldb-display-frame)) - -(defun perldb-display-frame (&optional nodisplay noauto) - "Find, obey and delete the last filename-and-line marker from PERLDB. -The marker looks like \\032\\032FILENAME:LINE:CHARPOS\\n. -Obeying it means displaying in another window the specified file and line." - (interactive) - (perldb-set-buffer) - (and perldb-last-frame (not nodisplay) - (or (not perldb-last-frame-displayed-p) (not noauto)) - (progn (perldb-display-line (car perldb-last-frame) (cdr perldb-last-frame)) - (setq perldb-last-frame-displayed-p t)))) - -;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen -;; and that its line LINE is visible. -;; Put the overlay-arrow on the line LINE in that buffer. - -(defun perldb-display-line (true-file line) - (let* ((buffer (find-file-noselect true-file)) - (window (display-buffer buffer t)) - (pos)) - (save-excursion - (set-buffer buffer) - (save-restriction - (widen) - (goto-line line) - (setq pos (point)) - (setq overlay-arrow-string "=>") - (or overlay-arrow-position - (setq overlay-arrow-position (make-marker))) - (set-marker overlay-arrow-position (point) (current-buffer))) - (cond ((or (< pos (point-min)) (> pos (point-max))) - (widen) - (goto-char pos)))) - (set-window-point window overlay-arrow-position))) - -(defun perldb-call (command) - "Invoke perldb COMMAND displaying source in other window." - (interactive) - (goto-char (point-max)) - (setq perldb-delete-prompt-marker (point-marker)) - (perldb-set-buffer) - (send-string (get-buffer-process current-perldb-buffer) - (concat command "\n"))) - -(defun perldb-maybe-delete-prompt () - (if (and perldb-delete-prompt-marker - (> (point-max) (marker-position perldb-delete-prompt-marker))) - (let (start) - (goto-char perldb-delete-prompt-marker) - (setq start (point)) - (beginning-of-line) - (delete-region (point) start) - (setq perldb-delete-prompt-marker nil)))) - -(defun perldb-break () - "Set PERLDB breakpoint at this source line." - (interactive) - (let ((line (save-restriction - (widen) - (1+ (count-lines 1 (point)))))) - (send-string (get-buffer-process current-perldb-buffer) - (concat "b " line "\n")))) - -(defun perldb-read-token() - "Return a string containing the token found in the buffer at point. -A token can be a number or an identifier. If the token is a name prefaced -by `$', `@', or `%', the leading character is included in the token." - (save-excursion - (let (begin) - (or (looking-at "[$@%]") - (re-search-backward "[^a-zA-Z_0-9]" (point-min) 'move)) - (setq begin (point)) - (or (looking-at "[$@%]") (setq begin (+ begin 1))) - (forward-char 1) - (buffer-substring begin - (if (re-search-forward "[^a-zA-Z_0-9]" - (point-max) 'move) - (- (point) 1) - (point))) -))) - -(defvar perldb-commands nil - "List of strings or functions used by send-perldb-command. -It is for customization by the user.") - -(defun send-perldb-command (arg) - "Issue a Perl debugger command selected by the prefix arg. A numeric -arg selects the ARG'th member COMMAND of the list perldb-commands. -The token under the cursor is passed to the command. If COMMAND is a -string, (format COMMAND TOKEN) is inserted at the end of the perldb -buffer, otherwise (funcall COMMAND TOKEN) is inserted. If there is -no such COMMAND, then the token itself is inserted. For example, -\"p %s\" is a possible string to be a member of perldb-commands, -or \"p $ENV{%s}\"." - (interactive "P") - (let (comm token) - (if arg (setq comm (nth arg perldb-commands))) - (setq token (perldb-read-token)) - (if (eq (current-buffer) current-perldb-buffer) - (set-mark (point))) - (cond (comm - (setq comm - (if (stringp comm) (format comm token) (funcall comm token)))) - (t (setq comm token))) - (switch-to-buffer-other-window current-perldb-buffer) - (goto-char (dot-max)) - (insert-string comm))) diff --git a/emacs/perldb.pl b/emacs/perldb.pl deleted file mode 100644 index 958e58d874..0000000000 --- a/emacs/perldb.pl +++ /dev/null @@ -1,531 +0,0 @@ -package DB; - -# modified Perl debugger, to be run from Emacs in perldb-mode -# Ray Lischner (uunet!mntgfx!lisch) as of 5 Nov 1990 - -$header = '$RCSfile: perldb.pl,v $$Revision: 4.1 $$Date: 92/08/07 17:20:59 $'; -# -# This file is automatically included if you do perl -d. -# It's probably not useful to include this yourself. -# -# Perl supplies the values for @line and %sub. It effectively inserts -# a do DB'DB(<linenum>); in front of every place that can -# have a breakpoint. It also inserts a do 'perldb.pl' before the first line. -# -# $Log: perldb.pl,v $ - -open(IN, "</dev/tty") || open(IN, "<&STDIN"); # so we don't dingle stdin -open(OUT,">/dev/tty") || open(OUT, ">&STDOUT"); # so we don't dongle stdout -select(OUT); -$| = 1; # for DB'OUT -select(STDOUT); -$| = 1; # for real STDOUT -$sub = ''; - -# Is Perl being run from Emacs? -$emacs = $main'ARGV[$[] eq '-emacs'; -shift(@main'ARGV) if $emacs; - -$header =~ s/.Header: ([^,]+),v(\s+\S+\s+\S+).*$/$1$2/; -print OUT "\nLoading DB routines from $header\n\nEnter h for help.\n\n"; - -sub DB { - &save; - ($package, $filename, $line) = caller; - $usercontext = '($@, $!, $[, $,, $/, $\) = @saved;' . - "package $package;"; # this won't let them modify, alas - local(*dbline) = "_<$filename"; - $max = $#dbline; - if (($stop,$action) = split(/\0/,$dbline{$line})) { - if ($stop eq '1') { - $signal |= 1; - } - else { - $evalarg = "\$DB'signal |= do {$stop;}"; &eval; - $dbline{$line} =~ s/;9($|\0)/$1/; - } - } - if ($single || $trace || $signal) { - if ($emacs) { - print OUT "\032\032$filename:$line:0\n"; - } else { - print OUT "$package'" unless $sub =~ /'/; - print OUT "$sub($filename:$line):\t",$dbline[$line]; - for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i) { - last if $dbline[$i] =~ /^\s*(}|#|\n)/; - print OUT "$sub($filename:$i):\t",$dbline[$i]; - } - } - } - $evalarg = $action, &eval if $action; - if ($single || $signal) { - $evalarg = $pre, &eval if $pre; - print OUT $#stack . " levels deep in subroutine calls!\n" - if $single & 4; - $start = $line; - while ((print OUT " DB<", $#hist+1, "> "), $cmd=&gets) { - $single = 0; - $signal = 0; - $cmd eq '' && exit 0; - chop($cmd); - $cmd =~ s/\\$// && do { - print OUT " cont: "; - $cmd .= &gets; - redo; - }; - $cmd =~ /^q$/ && exit 0; - $cmd =~ /^$/ && ($cmd = $laststep); - push(@hist,$cmd) if length($cmd) > 1; - ($i) = split(/\s+/,$cmd); - eval "\$cmd =~ $alias{$i}", print OUT $@ if $alias{$i}; - $cmd =~ /^h$/ && do { - print OUT " -T Stack trace. -s Single step. -n Next, steps over subroutine calls. -r Return from current subroutine. -c [line] Continue; optionally inserts a one-time-only breakpoint - at the specified line. -<CR> Repeat last n or s. -l min+incr List incr+1 lines starting at min. -l min-max List lines. -l line List line; -l List next window. -- List previous window. -w line List window around line. -l subname List subroutine. -f filename Switch to filename. -/pattern/ Search forwards for pattern; final / is optional. -?pattern? Search backwards for pattern. -L List breakpoints and actions. -S List subroutine names. -t Toggle trace mode. -b [line] [condition] - Set breakpoint; line defaults to the current execution line; - condition breaks if it evaluates to true, defaults to \'1\'. -b subname [condition] - Set breakpoint at first line of subroutine. -d [line] Delete breakpoint. -D Delete all breakpoints. -a [line] command - Set an action to be done before the line is executed. - Sequence is: check for breakpoint, print line if necessary, - do action, prompt user if breakpoint or step, evaluate line. -A Delete all actions. -V [pkg [vars]] List some (default all) variables in package (default current). -X [vars] Same as \"V currentpackage [vars]\". -< command Define command before prompt. -| command Define command after prompt. -! number Redo command (default previous command). -! -number Redo number\'th to last command. -H -number Display last number commands (default all). -q or ^D Quit. -p expr Same as \"print DB'OUT expr\" in current package. -= [alias value] Define a command alias, or list current aliases. -command Execute as a perl statement in current package. - -"; - next; }; - $cmd =~ /^t$/ && do { - $trace = !$trace; - print OUT "Trace = ".($trace?"on":"off")."\n"; - next; }; - $cmd =~ /^S$/ && do { - foreach $subname (sort(keys %sub)) { - print OUT $subname,"\n"; - } - next; }; - $cmd =~ s/^X\b/V $package/; - $cmd =~ /^V$/ && do { - $cmd = 'V $package'; }; - $cmd =~ /^V\s*(\S+)\s*(.*)/ && do { - $packname = $1; - @vars = split(' ',$2); - do 'dumpvar.pl' unless defined &main'dumpvar; - if (defined &main'dumpvar) { - &main'dumpvar($packname,@vars); - } - else { - print DB'OUT "dumpvar.pl not available.\n"; - } - next; }; - $cmd =~ /^f\s*(.*)/ && do { - $file = $1; - if (!$file) { - print OUT "The old f command is now the r command.\n"; - print OUT "The new f command switches filenames.\n"; - next; - } - if (!defined $_main{'_<' . $file}) { - if (($try) = grep(m#^_<.*$file#, keys %_main)) { - $file = substr($try,2); - print "\n$file:\n"; - } - } - if (!defined $_main{'_<' . $file}) { - print OUT "There's no code here anything matching $file.\n"; - next; - } - elsif ($file ne $filename) { - *dbline = "_<$file"; - $max = $#dbline; - $filename = $file; - $start = 1; - $cmd = "l"; - } }; - $cmd =~ /^l\s*(['A-Za-z_]['\w]*)/ && do { - $subname = $1; - $subname = "main'" . $subname unless $subname =~ /'/; - $subname = "main" . $subname if substr($subname,0,1) eq "'"; - ($file,$subrange) = split(/:/,$sub{$subname}); - if ($file ne $filename) { - *dbline = "_<$file"; - $max = $#dbline; - $filename = $file; - } - if ($subrange) { - if (eval($subrange) < -$window) { - $subrange =~ s/-.*/+/; - } - $cmd = "l $subrange"; - } else { - print OUT "Subroutine $1 not found.\n"; - next; - } }; - $cmd =~ /^w\s*(\d*)$/ && do { - $incr = $window - 1; - $start = $1 if $1; - $start -= $preview; - $cmd = 'l ' . $start . '-' . ($start + $incr); }; - $cmd =~ /^-$/ && do { - $incr = $window - 1; - $cmd = 'l ' . ($start-$window*2) . '+'; }; - $cmd =~ /^l$/ && do { - $incr = $window - 1; - $cmd = 'l ' . $start . '-' . ($start + $incr); }; - $cmd =~ /^l\s*(\d*)\+(\d*)$/ && do { - $start = $1 if $1; - $incr = $2; - $incr = $window - 1 unless $incr; - $cmd = 'l ' . $start . '-' . ($start + $incr); }; - $cmd =~ /^l\s*(([\d\$\.]+)([-,]([\d\$\.]+))?)?/ && do { - $end = (!$2) ? $max : ($4 ? $4 : $2); - $end = $max if $end > $max; - $i = $2; - $i = $line if $i eq '.'; - $i = 1 if $i < 1; - if ($emacs) { - print OUT "\032\032$filename:$i:0\n"; - $i = $end; - } else { - for (; $i <= $end; $i++) { - print OUT "$i:\t", $dbline[$i]; - last if $signal; - } - } - $start = $i; # remember in case they want more - $start = $max if $start > $max; - next; }; - $cmd =~ /^D$/ && do { - print OUT "Deleting all breakpoints...\n"; - for ($i = 1; $i <= $max ; $i++) { - if (defined $dbline{$i}) { - $dbline{$i} =~ s/^[^\0]+//; - if ($dbline{$i} =~ s/^\0?$//) { - delete $dbline{$i}; - } - } - } - next; }; - $cmd =~ /^L$/ && do { - for ($i = 1; $i <= $max; $i++) { - if (defined $dbline{$i}) { - print OUT "$i:\t", $dbline[$i]; - ($stop,$action) = split(/\0/, $dbline{$i}); - print OUT " break if (", $stop, ")\n" - if $stop; - print OUT " action: ", $action, "\n" - if $action; - last if $signal; - } - } - next; }; - $cmd =~ /^b\s*(['A-Za-z_]['\w]*)\s*(.*)/ && do { - $subname = $1; - $cond = $2 || '1'; - $subname = "$package'" . $subname unless $subname =~ /'/; - $subname = "main" . $subname if substr($subname,0,1) eq "'"; - ($filename,$i) = split(/[:-]/, $sub{$subname}); - if ($i) { - *dbline = "_<$filename"; - ++$i while $dbline[$i] == 0 && $i < $#dbline; - $dbline{$i} =~ s/^[^\0]*/$cond/; - } else { - print OUT "Subroutine $subname not found.\n"; - } - next; }; - $cmd =~ /^b\s*(\d*)\s*(.*)/ && do { - $i = ($1?$1:$line); - $cond = $2 || '1'; - if ($dbline[$i] == 0) { - print OUT "Line $i not breakable.\n"; - } else { - $dbline{$i} =~ s/^[^\0]*/$cond/; - } - next; }; - $cmd =~ /^d\s*(\d+)?/ && do { - $i = ($1?$1:$line); - $dbline{$i} =~ s/^[^\0]*//; - delete $dbline{$i} if $dbline{$i} eq ''; - next; }; - $cmd =~ /^A$/ && do { - for ($i = 1; $i <= $max ; $i++) { - if (defined $dbline{$i}) { - $dbline{$i} =~ s/\0[^\0]*//; - delete $dbline{$i} if $dbline{$i} eq ''; - } - } - next; }; - $cmd =~ /^<\s*(.*)/ && do { - $pre = do action($1); - next; }; - $cmd =~ /^>\s*(.*)/ && do { - $post = do action($1); - next; }; - $cmd =~ /^a\s*(\d+)(\s+(.*))?/ && do { - $i = $1; - if ($dbline[$i] == 0) { - print OUT "Line $i may not have an action.\n"; - } else { - $dbline{$i} =~ s/\0[^\0]*//; - $dbline{$i} .= "\0" . do action($3); - } - next; }; - $cmd =~ /^n$/ && do { - $single = 2; - $laststep = $cmd; - last; }; - $cmd =~ /^s$/ && do { - $single = 1; - $laststep = $cmd; - last; }; - $cmd =~ /^c\s*(\d*)\s*$/ && do { - $i = $1; - if ($i) { - if ($dbline[$i] == 0) { - print OUT "Line $i not breakable.\n"; - next; - } - $dbline{$i} =~ s/(\0|$)/;9$1/; # add one-time-only b.p. - } - for ($i=0; $i <= $#stack; ) { - $stack[$i++] &= ~1; - } - last; }; - $cmd =~ /^r$/ && do { - $stack[$#stack] |= 2; - last; }; - $cmd =~ /^T$/ && do { - local($p,$f,$l,$s,$h,$a,@a,@sub); - for ($i = 1; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) { - @a = @args; - for (@a) { - if (/^StB\000/ && length($_) == length($_main{'_main'})) { - $_ = sprintf("%s",$_); - } - else { - s/'/\\'/g; - s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/; - s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg; - s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg; - } - } - $w = $w ? '@ = ' : '$ = '; - $a = $h ? '(' . join(', ', @a) . ')' : ''; - push(@sub, "$w&$s$a from file $f line $l\n"); - last if $signal; - } - for ($i=0; $i <= $#sub; $i++) { - last if $signal; - print OUT $sub[$i]; - } - next; }; - $cmd =~ /^\/(.*)$/ && do { - $inpat = $1; - $inpat =~ s:([^\\])/$:$1:; - if ($inpat ne "") { - eval '$inpat =~ m'."\n$inpat\n"; - if ($@ ne "") { - print OUT "$@"; - next; - } - $pat = $inpat; - } - $end = $start; - eval ' - for (;;) { - ++$start; - $start = 1 if ($start > $max); - last if ($start == $end); - if ($dbline[$start] =~ m'."\n$pat\n".'i) { - if ($emacs) { - print OUT "\032\032$filename:$start:0\n"; - } else { - print OUT "$start:\t", $dbline[$start], "\n"; - } - last; - } - } '; - print OUT "/$pat/: not found\n" if ($start == $end); - next; }; - $cmd =~ /^\?(.*)$/ && do { - $inpat = $1; - $inpat =~ s:([^\\])\?$:$1:; - if ($inpat ne "") { - eval '$inpat =~ m'."\n$inpat\n"; - if ($@ ne "") { - print OUT "$@"; - next; - } - $pat = $inpat; - } - $end = $start; - eval ' - for (;;) { - --$start; - $start = $max if ($start <= 0); - last if ($start == $end); - if ($dbline[$start] =~ m'."\n$pat\n".'i) { - if ($emacs) { - print OUT "\032\032$filename:$start:0\n"; - } else { - print OUT "$start:\t", $dbline[$start], "\n"; - } - last; - } - } '; - print OUT "?$pat?: not found\n" if ($start == $end); - next; }; - $cmd =~ /^!+\s*(-)?(\d+)?$/ && do { - pop(@hist) if length($cmd) > 1; - $i = ($1?($#hist-($2?$2:1)):($2?$2:$#hist)); - $cmd = $hist[$i] . "\n"; - print OUT $cmd; - redo; }; - $cmd =~ /^!(.+)$/ && do { - $pat = "^$1"; - pop(@hist) if length($cmd) > 1; - for ($i = $#hist; $i; --$i) { - last if $hist[$i] =~ $pat; - } - if (!$i) { - print OUT "No such command!\n\n"; - next; - } - $cmd = $hist[$i] . "\n"; - print OUT $cmd; - redo; }; - $cmd =~ /^H\s*(-(\d+))?/ && do { - $end = $2?($#hist-$2):0; - $hist = 0 if $hist < 0; - for ($i=$#hist; $i>$end; $i--) { - print OUT "$i: ",$hist[$i],"\n" - unless $hist[$i] =~ /^.?$/; - }; - next; }; - $cmd =~ s/^p( .*)?$/print DB'OUT$1/; - $cmd =~ /^=/ && do { - if (local($k,$v) = ($cmd =~ /^=\s*(\S+)\s+(.*)/)) { - $alias{$k}="s~$k~$v~"; - print OUT "$k = $v\n"; - } elsif ($cmd =~ /^=\s*$/) { - foreach $k (sort keys(%alias)) { - if (($v = $alias{$k}) =~ s~^s\~$k\~(.*)\~$~$1~) { - print OUT "$k = $v\n"; - } else { - print OUT "$k\t$alias{$k}\n"; - }; - }; - }; - next; }; - $evalarg = $cmd; &eval; - print OUT "\n"; - } - if ($post) { - $evalarg = $post; &eval; - } - } - ($@, $!, $[, $,, $/, $\) = @saved; -} - -sub save { - @saved = ($@, $!, $[, $,, $/, $\); - $[ = 0; $, = ""; $/ = "\n"; $\ = ""; -} - -# The following takes its argument via $evalarg to preserve current @_ - -sub eval { - eval "$usercontext $evalarg; &DB'save"; - print OUT $@; -} - -sub action { - local($action) = @_; - while ($action =~ s/\\$//) { - print OUT "+ "; - $action .= &gets; - } - $action; -} - -sub gets { - local($.); - <IN>; -} - -sub catch { - $signal = 1; -} - -sub sub { - push(@stack, $single); - $single &= 1; - $single |= 4 if $#stack == $deep; - if (wantarray) { - @i = &$sub; - $single |= pop(@stack); - @i; - } - else { - $i = &$sub; - $single |= pop(@stack); - $i; - } -} - -$single = 1; # so it stops on first executable statement -@hist = ('?'); -$SIG{'INT'} = "DB'catch"; -$deep = 100; # warning if stack gets this deep -$window = 10; -$preview = 3; - -@stack = (0); -@ARGS = @ARGV; -for (@args) { - s/'/\\'/g; - s/(.*)/'$1'/ unless /^-?[\d.]+$/; -} - -if (-f '.perldb') { - do './.perldb'; -} -elsif (-f "$ENV{'LOGDIR'}/.perldb") { - do "$ENV{'LOGDIR'}/.perldb"; -} -elsif (-f "$ENV{'HOME'}/.perldb") { - do "$ENV{'HOME'}/.perldb"; -} - -1; diff --git a/emacs/tedstuff b/emacs/tedstuff deleted file mode 100644 index 257bbc8553..0000000000 --- a/emacs/tedstuff +++ /dev/null @@ -1,296 +0,0 @@ -Article 4417 of comp.lang.perl: -Path: jpl-devvax!elroy.jpl.nasa.gov!decwrl!mcnc!uvaarpa!mmdf -From: ted@evi.com (Ted Stefanik) -Newsgroups: comp.lang.perl -Subject: Correction to Perl fatal error marking in GNU Emacs -Message-ID: <1991Feb27.065853.15801@uvaarpa.Virginia.EDU> -Date: 27 Feb 91 06:58:53 GMT -Sender: mmdf@uvaarpa.Virginia.EDU (Uvaarpa Mail System) -Reply-To: ted@evi.com (Ted Stefanik) -Organization: The Internet -Lines: 282 - -Reading my own message, it occurred to me that I didn't quite satisfy the -request of stef@zweig.sun (Stephane Payrard): - -| Does anyone has extended perdb/perdb.el to position the -| point to the first syntax error? It would be cool. - -What I posted is a way to use the "M-x compile" command to test perl scripts. -(Needless to say, the script cannot be not interactive; you can't provide input -to a *compilation* buffer). When creating new Perl programs, I use "M-x -compile" until I'm sure that they are syntatically correct; if syntax errors -occur, C-x` takes me to each in sequence. After I'm sure the syntax is -correct, I start worrying about semantics, and switch to "M-x perldb" if -necessary. - -Therefore, the stuff I posted works great with "M-x compile", but not at all -with "M-x perldb". - -Next, let me update what I posted. I found that perl's die() command doesn't -print the same format error message as perl does when it dies with a syntax -error. If you put the following in your ".emacs" file, it causes C-x` to -recognize both kinds of errors: - -(load-library "compile") -(setq compilation-error-regexp - "\\([^ :\n]+\\(: *\\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\|[^ \n]+ \\(at \\)*line [0-9]+\\)") - -Last, so I don't look like a total fool, let me propose a way to satisfy -Stephane Payrard's original request (repeated again): - -| Does anyone has extended perdb/perdb.el to position the -| point to the first syntax error? It would be cool. - -I'm not satisfied with just the "first syntax error". Perl's parser is better -than most about not getting out of sync; therefore, if it reports multiple -errors, you can usually be assured they are all real errors. - -So... I hacked in the "next-error" function from "compile.el" to form -"perldb-next-error". You can apply the patches at the end of this message -to add "perldb-next-error" to your "perldb.el". - -Notes: - 1) The patch binds "perldb-next-error" to C-x~ (because ~ is the shift - of ` on my keyboard, and C-x~ is not yet taken in my version of EMACS). - - 2) "next-error" is meant to work on a single *compilation* buffer; any new - "M-x compile" or "M-x grep" command will clear the old *compilation* - buffer and reset the compilation-error parser to start at the top of the - *compilation* buffer. - - "perldb-next-error", on the other hand, has to deal with multiple - *perldb-<foo>* buffers, each of which keep growing. "perldb-next-error" - correctly handles the constantly growing *perldb-<foo>* buffers by - keeping track of the last reported error in the "current-perldb-buffer". - - Sadly however, when you invoke a new "M-x perldb" on a different Perl - script, "perldb-next-error" will start parsing the new *perldb-<bar>* - buffer at the top (even if it was previously parsed), and will completely - lose the marker of the last reported error in *perldb-<foo>*. - - 3) "perldb-next-error" still uses "compilation-error-regexp" to find - fatal errors. Therefore, both the "M-x compile"/C-x` scheme and - the "M-x perldb"/C-x~ scheme can be used to find fatal errors that - match the common "compilation-error-regexp". You *will* want to install - that "compilation-error-regexp" stuff into your .emacs file. - - 4) The patch was developed and tested with GNU Emacs 18.55. - - 5) Since the patch was ripped off from compile.el, the code is (of - course) subject to the GNU copyleft. - -*** perldb.el.orig Wed Feb 27 00:44:27 1991 ---- perldb.el Wed Feb 27 00:44:30 1991 -*************** -*** 199,205 **** - - (defun perldb-set-buffer () - (cond ((eq major-mode 'perldb-mode) -! (setq current-perldb-buffer (current-buffer))))) - - ;; This function is responsible for inserting output from Perl - ;; into the buffer. ---- 199,211 ---- - - (defun perldb-set-buffer () - (cond ((eq major-mode 'perldb-mode) -! (cond ((not (eq current-perldb-buffer (current-buffer))) -! (perldb-forget-errors) -! (setq perldb-parsing-end 2)) ;; 2 to defeat grep defeater -! (t -! (if (> perldb-parsing-end (point-max)) -! (setq perldb-parsing-end (max (point-max) 2))))) -! (setq current-perldb-buffer (current-buffer))))) - - ;; This function is responsible for inserting output from Perl - ;; into the buffer. -*************** -*** 291,297 **** - ;; process-buffer is current-buffer - (unwind-protect - (progn -! ;; Write something in *compilation* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) ---- 297,303 ---- - ;; process-buffer is current-buffer - (unwind-protect - (progn -! ;; Write something in *perldb-<foo>* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) -*************** -*** 421,423 **** ---- 427,593 ---- - (switch-to-buffer-other-window current-perldb-buffer) - (goto-char (dot-max)) - (insert-string comm))) -+ -+ (defvar perldb-error-list nil -+ "List of error message descriptors for visiting erring functions. -+ Each error descriptor is a list of length two. -+ Its car is a marker pointing to an error message. -+ Its cadr is a marker pointing to the text of the line the message is about, -+ or nil if that 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.") -+ -+ (defvar perldb-parsing-end nil -+ "Position of end of buffer when last error messages parsed.") -+ -+ (defvar perldb-error-message "No more fatal Perl errors" -+ "Message to print when no more matches for compilation-error-regexp are found") -+ -+ (defun perldb-next-error (&optional argp) -+ "Visit next perldb error message and corresponding source code. -+ This operates on the output from the \\[perldb] command. -+ If all preparsed error messages have been processed, -+ the error message buffer is checked for new ones. -+ A non-nil argument (prefix arg, if interactive) -+ means reparse the error message buffer and start at the first error." -+ (interactive "P") -+ (if (or (eq perldb-error-list t) -+ argp) -+ (progn (perldb-forget-errors) -+ (setq perldb-parsing-end 2))) ;; 2 to defeat grep defeater -+ (if perldb-error-list -+ nil -+ (save-excursion -+ (switch-to-buffer current-perldb-buffer) -+ (perldb-parse-errors))) -+ (let ((next-error (car perldb-error-list))) -+ (if (null next-error) -+ (error (concat perldb-error-message -+ (if (and (get-buffer-process current-perldb-buffer) -+ (eq (process-status -+ (get-buffer-process -+ current-perldb-buffer)) -+ 'run)) -+ " yet" "")))) -+ (setq perldb-error-list (cdr perldb-error-list)) -+ (if (null (car (cdr next-error))) -+ nil -+ (switch-to-buffer (marker-buffer (car (cdr next-error)))) -+ (goto-char (car (cdr next-error))) -+ (set-marker (car (cdr next-error)) nil)) -+ (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))) -+ (set-marker (car next-error) nil))) -+ -+ ;; Set perldb-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 perldb-forget-errors () -+ (if (eq perldb-error-list t) -+ (setq perldb-error-list nil)) -+ (while perldb-error-list -+ (let ((next-error (car perldb-error-list))) -+ (set-marker (car next-error) nil) -+ (if (car (cdr next-error)) -+ (set-marker (car (cdr next-error)) nil))) -+ (setq perldb-error-list (cdr perldb-error-list)))) -+ -+ (defun perldb-parse-errors () -+ "Parse the current buffer as error messages. -+ This makes a list of error descriptors, perldb-error-list. -+ For each source-file, line-number pair in the buffer, -+ the source file is read in, and the text location is saved in perldb-error-list. -+ The function next-error, assigned to \\[next-error], takes the next error off the list -+ and visits its location." -+ (setq perldb-error-list nil) -+ (message "Parsing error messages...") -+ (let (text-buffer -+ last-filename last-linenum) -+ ;; Don't reparse messages already seen at last parse. -+ (goto-char perldb-parsing-end) -+ ;; Don't parse the first two lines as error messages. -+ ;; This matters for grep. -+ (if (bobp) -+ (forward-line 2)) -+ (while (re-search-forward compilation-error-regexp nil t) -+ (let (linenum filename -+ error-marker text-marker) -+ ;; Extract file name and line number from error message. -+ (save-restriction -+ (narrow-to-region (match-beginning 0) (match-end 0)) -+ (goto-char (point-max)) -+ (skip-chars-backward "[0-9]") -+ ;; If it's a lint message, use the last file(linenum) on the line. -+ ;; Normally we use the first on the line. -+ (if (= (preceding-char) ?\() -+ (progn -+ (narrow-to-region (point-min) (1+ (buffer-size))) -+ (end-of-line) -+ (re-search-backward compilation-error-regexp) -+ (skip-chars-backward "^ \t\n") -+ (narrow-to-region (point) (match-end 0)) -+ (goto-char (point-max)) -+ (skip-chars-backward "[0-9]"))) -+ ;; Are we looking at a "filename-first" or "line-number-first" form? -+ (if (looking-at "[0-9]") -+ (progn -+ (setq linenum (read (current-buffer))) -+ (goto-char (point-min))) -+ ;; Line number at start, file name at end. -+ (progn -+ (goto-char (point-min)) -+ (setq linenum (read (current-buffer))) -+ (goto-char (point-max)) -+ (skip-chars-backward "^ \t\n"))) -+ (setq filename (perldb-grab-filename))) -+ ;; Locate the erring file and line. -+ (if (and (equal filename last-filename) -+ (= linenum last-linenum)) -+ nil -+ (beginning-of-line 1) -+ (setq error-marker (point-marker)) -+ ;; text-buffer gets the buffer containing this error's file. -+ (if (not (equal filename last-filename)) -+ (setq text-buffer -+ (and (file-exists-p (setq last-filename filename)) -+ (find-file-noselect filename)) -+ last-linenum 0)) -+ (if text-buffer -+ ;; Go to that buffer and find the erring line. -+ (save-excursion -+ (set-buffer text-buffer) -+ (if (zerop last-linenum) -+ (progn -+ (goto-char 1) -+ (setq last-linenum 1))) -+ (forward-line (- linenum last-linenum)) -+ (setq last-linenum linenum) -+ (setq text-marker (point-marker)) -+ (setq perldb-error-list -+ (cons (list error-marker text-marker) -+ perldb-error-list))))) -+ (forward-line 1))) -+ (setq perldb-parsing-end (point-max))) -+ (message "Parsing error messages...done") -+ (setq perldb-error-list (nreverse perldb-error-list))) -+ -+ (defun perldb-grab-filename () -+ "Return a string which is a filename, starting at point. -+ Ignore quotes and parentheses around it, as well as trailing colons." -+ (if (eq (following-char) ?\") -+ (save-restriction -+ (narrow-to-region (point) -+ (progn (forward-sexp 1) (point))) -+ (goto-char (point-min)) -+ (read (current-buffer))) -+ (buffer-substring (point) -+ (progn -+ (skip-chars-forward "^ :,\n\t(") -+ (point))))) -+ -+ (define-key ctl-x-map "~" 'perldb-next-error) - - |