Mercurial > emacs
changeset 39836:c2db8c1499cb
Merged in changes from v4.32.
After 4.23 and: After 4.24:
(cperl-contract-levels): Restore position.
(cperl-beautify-level): Likewise.
(cperl-beautify-regexp): Likewise.
(cperl-commentify): Rudimental support for length=1 runs
(cperl-find-pods-heres): Process 1-char long REx comments too /a#/x
After 4.25:
(cperl-commentify): Was recognizing length=2 "strings" as length=1.
(imenu-example--create-perl-index): Was not enforcing
syntaxification-to-the-end.
(cperl-invert-if-unless): Allow `for', `foreach'.
(cperl-find-pods-heres): Quote `cperl-nonoverridable-face'.
Mark qw(), m()x as indentable.
(cperl-init-faces): Highlight `sysopen' too.
Highlight $var in `for my $var' too.
(cperl-invert-if-unless): Was leaving whitespace at end.
(cperl-linefeed): Was splitting $var{$foo} if point after `{'.
(cperl-calculate-indent): Remove old commented out code.
Support (primitive) indentation of qw(), m()x.
After 4.26:
(cperl-problems): Mention `fill-paragraph' on comment. \"" and
q [] with intervening newlines.
(cperl-autoindent-on-semi): New customization variable.
(cperl-electric-semi): Use `cperl-autoindent-on-semi'.
(cperl-tips): Mention how to make CPerl the default mode.
(cperl-mode): Support `outline-minor-mode'. From Mark A. Hershberger.
(cperl-outline-level): New function.
(cperl-highlight-variables-indiscriminately): New customization var.
(cperl-init-faces): Use `cperl-highlight-variables-indiscriminately'.
From Sean Kamath <kamath@pogo.wv.tek.com>.
(cperl-after-block-p): Support CHECK and INIT.
(cperl-init-faces, cperl-short-docs): Likewise and "our".
From Doug MacEachern <dougm@covalent.net>.
After 4.27:
(cperl-find-pods-heres): Recognize \"" as a string.
Mark whitespace between q and [] as `syntax-type' => `prestring'.
Allow whitespace between << and "FOO".
(cperl-problems): Remove \"" and q [] with intervening newlines.
Mention multiple <<EOF as unsupported.
(cperl-highlight-variables-indiscriminately): Doc misprint fixed.
(cperl-indent-parens-as-block): New configuration variable.
(cperl-calculate-indent): Merge cases of indenting non-BLOCK groups.
Use `cperl-indent-parens-as-block'.
(cperl-find-pods-heres): Test for =cut without empty line instead of
complaining about no =cut.
(cperl-electric-pod): Change the REx for POD from "\n\n=" to "^\n=".
(cperl-find-pods-heres): Likewise.
(cperl-electric-pod): Change `forward-sexp' to `forward-word':
POD could've been marked as comment already.
(cperl-unwind-to-safe): Unwind before start of POD too.
After 4.28:
(cperl-forward-re): Throw an error at proper moment REx unfinished.
After 4.29:
(x-color-defined-p): Make an extra case to peacify the warning.
Toplevel: `defvar' to peacify the warnings.
(cperl-find-pods-heres): Could access `font-lock-comment-face' in -nw.
No -nw-compile time warnings now.
(cperl-find-tags): TAGS file had too short substring-to-search.
Be less verbose in non-interactive mode
(imenu-example--create-perl-index): Set index-marker after name
(cperl-outline-regexp): New variable.
(cperl-outline-level): Made compatible with `cperl-outline-regexp'.
(cperl-mode): Made use `cperl-outline-regexp'.
After 4.30:
(cperl-find-pods-heres): =cut the last thing, no blank line, was error.
(cperl-outline-level): Make start-of-file same level as `package'.
After 4.31:
(cperl-electric-pod): `head1' and `over' electric only if empty.
(cperl-unreadable-ok): New variable.
(cperl-find-tags): Use `cperl-unreadable-ok', do not fail
on an unreadable file.
(cperl-write-tags): Use `cperl-unreadable-ok', do not fail
on an unreadable directory.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Fri, 12 Oct 2001 18:11:06 +0000 |
parents | 81c88c75006b |
children | ccaa40660e40 |
files | lisp/progmodes/cperl-mode.el |
diffstat | 1 files changed, 524 insertions(+), 254 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/progmodes/cperl-mode.el Fri Oct 12 17:43:05 2001 +0000 +++ b/lisp/progmodes/cperl-mode.el Fri Oct 12 18:11:06 2001 +0000 @@ -235,6 +235,12 @@ :type 'boolean :group 'cperl-autoinsert-details) +(defcustom cperl-autoindent-on-semi nil + "*Non-nil means automatically indent after insertion of (semi)colon. +Active if `cperl-auto-newline' is false." + :type 'boolean + :group 'cperl-autoinsert-details) + (defcustom cperl-auto-newline-after-colon nil "*Non-nil means automatically newline even after colons. Subject to `cperl-auto-newline' setting." @@ -379,12 +385,27 @@ :type 'boolean :group 'cperl-faces) +(defcustom cperl-highlight-variables-indiscriminately nil + "*Non-nil means perform additional highlighting on variables. +Currently only changes how scalar variables are highlighted. +Note that that variable is only read at initialization time for +the variable `cperl-font-lock-keywords-2', so changing it after you've +entered `cperl-mode' the first time will have no effect." + :type 'boolean + :group 'cperl) + (defcustom cperl-pod-here-scan t "*Not-nil means look for pod and here-docs sections during startup. You can always make lookup from menu or using \\[cperl-find-pods-heres]." :type 'boolean :group 'cperl-speed) +(defcustom cperl-regexp-scan t + "*Not-nil means make marking of regular expression more thorough. +Effective only with `cperl-pod-here-scan'. Not implemented yet." + :type 'boolean + :group 'cperl-speed) + (defcustom cperl-imenu-addback nil "*Not-nil means add backreferences to generated `imenu's. May require patched `imenu' and `imenu-go'. Obsolete." @@ -482,11 +503,17 @@ :type 'boolean :group 'cperl-indentation-details) -(defcustom cperl-syntaxify-by-font-lock - (and window-system +(defcustom cperl-indent-parens-as-block nil + "*Non-nil means that non-block ()-, {}- and []-groups are indented as blocks, +but for trailing \",\" inside the group, which won't increase indentation. +One should tune up `cperl-close-paren-offset' as well." + :type 'boolean + :group 'cperl-indentation-details) + +(defcustom cperl-syntaxify-by-font-lock + (and window-system (boundp 'parse-sexp-lookup-properties)) - "*Non-nil means that CPerl uses `font-lock's routines for syntaxification. -Having it TRUE may be not completely debugged yet." + "*Non-nil means that CPerl uses `font-lock's routines for syntaxification." :type '(choice (const message) boolean) :group 'cperl-speed) @@ -631,15 +658,21 @@ install choose-color.el, available from ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs/ +`fill-paragraph' on a comment may leave the point behind the +paragraph. Parsing of lines with several <<EOF is not implemented +yet. + Emacs had a _very_ restricted syntax parsing engine until RMS's Emacs 20.1. Most problems below are corrected starting from this version of -Emacs, and all of them should go with (future) RMS's version 20.3. - -Note that even with newer Emacsen interaction of `font-lock' and -syntaxification is not cleaned up. You may get slightly different -colors basing on the order of fontification and syntaxification. This -might be corrected by setting `cperl-syntaxify-by-font-lock' to t, but -the corresponding code is still extremely buggy. +Emacs, and all of them should go with RMS's version 20.3. (Or apply +patches to Emacs 19.33/34 - see tips.) XEmacs is very backward in +this respect. + +Note that even with newer Emacsen in some very rare cases the details +of interaction of `font-lock' and syntaxification may be not cleaned +up yet. You may get slightly different colors basing on the order of +fontification and syntaxification. Say, the initial faces is correct, +but editing the buffer breaks this. Even with older Emacsen CPerl mode tries to corrects some Emacs misunderstandings, however, for efficiency reasons the degree of @@ -702,7 +735,7 @@ By similar reasons s\"abc\"def\"; -would confuse CPerl a lot. +could confuse CPerl a lot. If you still get wrong indentation in situation that you think the code should be able to parse, try: @@ -788,8 +821,10 @@ B if A; n) Highlights (by user-choice) either 3-delimiters constructs - (such as tr/a/b/), or regular expressions and `y/tr'. - o) Highlights trailing whitespace. + (such as tr/a/b/), or regular expressions and `y/tr'; + o) Highlights trailing whitespace; + p) Is able to manipulate Perl Regular Expressions to ease + conversion to a more readable form. 5) The indentation engine was very smart, but most of tricks may be not needed anymore with the support for `syntax-table' property. Has @@ -1103,12 +1138,16 @@ ["Fill paragraph/comment" cperl-fill-paragraph t] "----" ["Line up a construction" cperl-lineup (cperl-use-region-p)] - ["Invert if/unless/while/until" cperl-invert-if-unless t] + ["Invert if/unless/while etc" cperl-invert-if-unless t] ("Regexp" ["Beautify" cperl-beautify-regexp cperl-use-syntax-table-text-property] + ["Beautify one level deep" (cperl-beautify-regexp 1) + cperl-use-syntax-table-text-property] ["Beautify a group" cperl-beautify-level cperl-use-syntax-table-text-property] + ["Beautify a group one level deep" (cperl-beautify-level 1) + cperl-use-syntax-table-text-property] ["Contract a group" cperl-contract-level cperl-use-syntax-table-text-property] ["Contract groups" cperl-contract-levels @@ -1439,6 +1478,10 @@ ("formy" "formy" cperl-electric-keyword 0) ("foreachmy" "foreachmy" cperl-electric-keyword 0) ("do" "do" cperl-electric-keyword 0) + ("=pod" "=pod" cperl-electric-pod 0) + ("=over" "=over" cperl-electric-pod 0) + ("=head1" "=head1" cperl-electric-pod 0) + ("=head2" "=head2" cperl-electric-pod 0) ("pod" "pod" cperl-electric-pod 0) ("over" "over" cperl-electric-pod 0) ("head1" "head1" cperl-electric-pod 0) @@ -1447,6 +1490,11 @@ (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 'outline-regexp) + ;; (setq outline-regexp imenu-example--function-name-regexp-perl) + (setq outline-regexp cperl-outline-regexp) + (make-local-variable 'outline-level) + (setq outline-level 'cperl-outline-level) (make-local-variable 'paragraph-start) (setq paragraph-start (concat "^$\\|" page-delimiter)) (make-local-variable 'paragraph-separate) @@ -1910,21 +1958,22 @@ (memq this-command '(self-insert-command newline)))) head1 notlast name p really-delete over) (and (save-excursion - (condition-case nil - (backward-sexp 1) - (error nil)) - (and + (forward-word -1) + (and (eq (preceding-char) ?=) (progn - (setq head1 (looking-at "head1\\>")) - (setq over (looking-at "over\\>")) + (setq head1 (looking-at "head1\\>[ \t]*$")) + (setq over (and (looking-at "over\\>[ \t]*$") + (not (looking-at "over[ \t]*\n\n\n*=item\\>")))) (forward-char -1) (bolp)) (or (get-text-property (point) 'in-pod) (cperl-after-expr-p nil "{;:") (and (re-search-backward - "\\(\\`\n?\\|\n\n\\)=\\sw+" (point-min) t) + ;; "\\(\\`\n?\\|\n\n\\)=\\sw+" + "\\(\\`\n?\\|^\n\\)=\\sw+" + (point-min) t) (not (or (looking-at "=cut") (and cperl-use-syntax-table-text-property @@ -1932,20 +1981,20 @@ 'pod))))))))) (progn (save-excursion - (setq notlast (search-forward "\n\n=" nil t))) + (setq notlast (re-search-forward "^\n=" nil t))) (or notlast (progn (insert "\n\n=cut") (cperl-ensure-newlines 2) - (forward-sexp -2) - (if (and head1 - (not + (forward-word -2) + (if (and head1 + (not (save-excursion (forward-char -1) (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\>" nil t)))) ; Only one - (progn - (forward-sexp 1) + (progn + (forward-word 1) (setq name (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) p (point)) @@ -1954,10 +2003,10 @@ "=head1 DESCRIPTION") (cperl-ensure-newlines 4) (goto-char p) - (forward-sexp 2) + (forward-word 2) (end-of-line) (setq really-delete t)) - (forward-sexp 1)))) + (forward-word 1)))) (if over (progn (setq p (point)) @@ -1965,7 +2014,7 @@ "=back") (cperl-ensure-newlines 2) (goto-char p) - (forward-sexp 1) + (forward-word 1) (end-of-line) (setq really-delete t))) (if (and delete really-delete) @@ -2034,6 +2083,7 @@ ; Leave the level of parens (looking-at "[,; \t]*\\($\\|#\\)") ; Comma to allow anon subr ; Are at end + (cperl-after-block-p (point-min)) (progn (backward-sexp 1) (setq start (point-marker)) @@ -2121,7 +2171,9 @@ (interactive "P") (if cperl-auto-newline (cperl-electric-terminator arg) - (self-insert-command (prefix-numeric-value arg)))) + (self-insert-command (prefix-numeric-value arg)) + (if cperl-autoindent-on-semi + (cperl-indent-line)))) (defun cperl-electric-terminator (arg) "Insert character and correct line's indentation." @@ -2360,8 +2412,9 @@ and closing parentheses and brackets.." (save-excursion (if (or - (memq (get-text-property (point) 'syntax-type) - '(pod here-doc here-doc-delim format)) + (and (memq (get-text-property (point) 'syntax-type) + '(pod here-doc here-doc-delim format)) + (not (get-text-property (point) 'indentable))) ;; before start of POD - whitespace found since do not have 'pod! (and (looking-at "[ \t]*\n=") (error "Spaces before pod section!")) @@ -2375,7 +2428,7 @@ (following-char))) (in-pod (get-text-property (point) 'in-pod)) (pre-indent-point (point)) - p prop look-prop) + p prop look-prop is-block delim) (cond (in-pod ;; In the verbatim part, probably code example. What to do??? @@ -2412,48 +2465,18 @@ (setcar (cddr parse-data) start)) ;; Before this point: end of statement (setq old-indent (nth 3 parse-data)))) - ;; (or parse-start (null symbol) - ;; (setq parse-start (symbol-value symbol) - ;; start-indent (nth 2 parse-start) - ;; parse-start (car parse-start))) - ;; (if parse-start - ;; (goto-char parse-start) - ;; (beginning-of-defun)) - ;; ;; 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)) + (cond ((get-text-property (point) 'indentable) + ;; indent to just after the surrounding open, + ;; skip blanks if we do not close the expression. + (goto-char (1+ (previous-single-property-change (point) 'indentable))) + (or (memq char-after (append ")]}" nil)) + (looking-at "[ \t]*\\(#\\|$\\)") + (skip-chars-forward " \t")) + (current-column)) + ((or (nth 3 state) (nth 4 state)) ;; return nil or t if should not change this line (nth 4 state)) + ;; XXXX Do we need to special-case this? ((null containing-sexp) ;; Line is at top level. May be data or function definition, ;; or may be function argument declaration. @@ -2492,9 +2515,15 @@ (list pre-indent-point))) 0) cperl-continued-statement-offset)))) - ((/= (char-after containing-sexp) ?{) - ;; line is expression, not statement: - ;; indent to just after the surrounding open, + ((not + (or (setq is-block + (and (setq delim (= (char-after containing-sexp) ?{)) + (save-excursion ; Is it a hash? + (goto-char containing-sexp) + (cperl-block-p)))) + cperl-indent-parens-as-block)) + ;; group is an expression, not a block: + ;; indent to just after the surrounding open parens, ;; skip blanks if we do not close the expression. (goto-char (1+ containing-sexp)) (or (memq char-after (append ")]}" nil)) @@ -2506,13 +2535,39 @@ (goto-char containing-sexp) (not (cperl-block-p))) (goto-char (1+ containing-sexp)) - (or (eq char-after ?\}) + (or (memq char-after + (append (if delim "}" ")]}") nil)) (looking-at "[ \t]*\\(#\\|$\\)") (skip-chars-forward " \t")) - (+ (current-column) ; Correct indentation of trailing ?\} - (if (eq char-after ?\}) (+ cperl-indent-level - cperl-close-paren-offset) + (+ (current-column) + (if (and delim + (eq char-after ?\})) + ;; Correct indentation of trailing ?\} + (+ cperl-indent-level cperl-close-paren-offset) 0))) +;;; ((and (/= (char-after containing-sexp) ?{) +;;; (not cperl-indent-parens-as-block)) +;;; ;; line is expression, not statement: +;;; ;; indent to just after the surrounding open, +;;; ;; skip blanks if we do not close the expression. +;;; (goto-char (1+ containing-sexp)) +;;; (or (memq char-after (append ")]}" nil)) +;;; (looking-at "[ \t]*\\(#\\|$\\)") +;;; (skip-chars-forward " \t")) +;;; (current-column)) +;;; ((progn +;;; ;; Containing-expr starts with \{. Check whether it is a hash. +;;; (goto-char containing-sexp) +;;; (and (not (cperl-block-p)) +;;; (not cperl-indent-parens-as-block))) +;;; (goto-char (1+ containing-sexp)) +;;; (or (eq char-after ?\}) +;;; (looking-at "[ \t]*\\(#\\|$\\)") +;;; (skip-chars-forward " \t")) +;;; (+ (current-column) ; 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. @@ -2534,11 +2589,12 @@ (beginning-of-line) (cperl-backward-to-noncomment containing-sexp)) ;; Now we get the answer. - ;; Had \?, too: - (if (not (or (memq (preceding-char) (append " ;{" '(nil))) + (if (not (or (eq (1- (point)) containing-sexp) + (memq (preceding-char) + (append (if is-block " ;{" " ,;{") '(nil))) (and (eq (preceding-char) ?\}) - (cperl-after-block-and-statement-beg - containing-sexp)))) ; Was ?\, + (cperl-after-block-and-statement-beg + containing-sexp)))) ;; This line is continuation of preceding line's statement; ;; indent `cperl-continued-statement-offset' more than the ;; previous line of the statement. @@ -2550,6 +2606,12 @@ (+ (if (memq char-after (append "}])" nil)) 0 ; Closing parenth cperl-continued-statement-offset) + (if (or is-block + (not delim) + (not (eq char-after ?\}))) + 0 + ;; Now it is a hash reference + (+ cperl-indent-level cperl-close-paren-offset)) (if (looking-at "\\w+[ \t]*:") (if (> (current-indentation) cperl-min-label-indent) (- (current-indentation) cperl-label-offset) @@ -2605,6 +2667,12 @@ (+ (if (and (bolp) (zerop cperl-indent-level)) (+ cperl-brace-offset cperl-continued-statement-offset) cperl-indent-level) + (if (or is-block + (not delim) + (not (eq char-after ?\}))) + 0 + ;; Now it is a hash reference + (+ cperl-indent-level cperl-close-paren-offset)) ;; Move back over whitespace before the openbrace. ;; If openbrace is not first nonwhite thing on the line, ;; add the cperl-brace-imaginary-offset. @@ -2892,8 +2960,11 @@ nil ;; We suppose that e is _after_ the end of construction, as after eol. (setq string (if string cperl-st-sfence cperl-st-cfence)) - (cperl-modify-syntax-type bb string) - (cperl-modify-syntax-type (1- e) string) + (if (> bb (- e 2)) + ;; one-char string/comment?! + (cperl-modify-syntax-type bb cperl-st-punct) + (cperl-modify-syntax-type bb string) + (cperl-modify-syntax-type (1- e) string)) (if (and (eq string cperl-st-sfence) (> (- e 2) bb)) (put-text-property (1+ bb) (1- e) 'syntax-table cperl-string-syntax-table)) @@ -2903,6 +2974,7 @@ (not cperl-pod-here-fontify) (put-text-property bb e 'face (if string 'font-lock-string-face 'font-lock-comment-face))))) + (defvar cperl-starters '(( ?\( . ?\) ) ( ?\[ . ?\] ) ( ?\{ . ?\} ) @@ -2912,7 +2984,7 @@ &optional ostart oend) ;; Works *before* syntax recognition is done ;; May modify syntax-type text property if the situation is too hard - (let (b starter ender st i i2 go-forward) + (let (b starter ender st i i2 go-forward reset-st) (skip-chars-forward " \t") ;; ender means matching-char matcher. (setq b (point) @@ -2945,9 +3017,13 @@ (not ender)) ;; $ has TeXish matching rules, so $$ equiv $... (forward-char 2) + (setq reset-st (syntax-table)) (set-syntax-table st) (forward-sexp 1) - (set-syntax-table cperl-mode-syntax-table) + (if (<= (point) (1+ b)) + (error "Unfinished regular expression")) + (set-syntax-table reset-st) + (setq reset-st nil) ;; Now the problem is with m;blah;; (and (not ender) (eq (preceding-char) @@ -2984,6 +3060,8 @@ ender (nth 2 ender))))) (error (goto-char lim) (setq set-st nil) + (if reset-st + (set-syntax-table reset-st)) (or end (message "End of `%s%s%c ... %c' string/RE not found: %s" @@ -3022,6 +3100,7 @@ ;; After-initial-line--to-end is marked `syntax-type' ==> `format' ;; d) 'Q'uoted string: ;; part between markers inclusive is marked `syntax-type' ==> `string' +;; part between `q' and the first marker is marked `syntax-type' ==> `prestring' (defun cperl-unwind-to-safe (before &optional end) ;; if BEFORE, go to the previous start-of-line on each step of unwinding @@ -3038,6 +3117,11 @@ (goto-char (setq pos (cperl-1- pos)))) ;; Up to the start (goto-char (point-min)))) + ;; Skip empty lines + (and (looking-at "\n*=") + (/= 0 (skip-chars-backward "\n")) + (forward-char)) + (setq pos (point)) (if end ;; Do the same for end, going small steps (progn @@ -3046,6 +3130,10 @@ end (next-single-property-change end 'syntax-type))) (or end pos))))) +(defvar cperl-nonoverridable-face) +(defvar font-lock-function-name-face) +(defvar font-lock-comment-face) + (defun cperl-find-pods-heres (&optional min max non-inter end ignore-max) "Scans the buffer for hard-to-parse Perl constructions. If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify @@ -3057,7 +3145,8 @@ cperl-syntax-done-to min)) (or max (setq max (point-max))) (let* (face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb - (cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend + is-REx is-x-REx REx-comment-start REx-comment-end was-comment i2 + (cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t) (modified (buffer-modified-p)) (after-change-functions nil) @@ -3068,7 +3157,8 @@ (point-min))) (state (if use-syntax-state (cdr cperl-syntax-state))) - (st-l '(nil)) (err-l '(nil)) i2 + ;; (st-l '(nil)) (err-l '(nil)) ; Would overwrite - propagates from a function call to a function call! + (st-l (list nil)) (err-l (list nil)) ;; Somehow font-lock may be not loaded yet... (font-lock-string-face (if (boundp 'font-lock-string-face) font-lock-string-face @@ -3080,7 +3170,11 @@ (if (boundp 'font-lock-function-name-face) font-lock-function-name-face 'font-lock-function-name-face)) - (cperl-nonoverridable-face + (font-lock-comment-face + (if (boundp 'font-lock-comment-face) + font-lock-comment-face + 'font-lock-comment-face)) + (cperl-nonoverridable-face (if (boundp 'cperl-nonoverridable-face) cperl-nonoverridable-face 'cperl-nonoverridable-face)) @@ -3089,13 +3183,14 @@ max)) (search (concat - "\\(\\`\n?\\|\n\n\\)=" + "\\(\\`\n?\\|^\n\\)=" "\\|" ;; One extra () before this: "<<" "\\(" ; 1 + 1 ;; First variant "BLAH" or just ``. - "\\([\"'`]\\)" ; 2 + 1 + "[ \t]*" ; Yes, whitespace is allowed! + "\\([\"'`]\\)" ; 2 + 1 = 3 "\\([^\"'`\n]*\\)" ; 3 + 1 "\\3" "\\|" @@ -3127,7 +3222,10 @@ "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'" ;; 1+6+2+1+1+2+1+1=15 extra () before this: "\\|" - "__\\(END\\|DATA\\)__" ; Commented - does not help with indent... + "__\\(END\\|DATA\\)__" + ;; 1+6+2+1+1+2+1+1+1=16 extra () before this: + "\\|" + "\\\\\\(['`\"]\\)" ) "")))) (unwind-protect @@ -3142,7 +3240,10 @@ here-face cperl-here-face)) (remove-text-properties min max '(syntax-type t in-pod t syntax-table t - cperl-postpone t)) + cperl-postpone t + syntax-subtype t + rear-nonsticky t + indentable t)) ;; Need to remove face as well... (goto-char min) (and (eq system-type 'emx) @@ -3156,8 +3257,8 @@ (setq tmpend nil) ; Valid for most cases (cond ((match-beginning 1) ; POD section - ;; "\\(\\`\n?\\|\n\n\\)=" - (if (looking-at "\n*cut\\>") + ;; "\\(\\`\n?\\|^\n\\)=" + (if (looking-at "cut\\>") (if ignore-max nil ; Doing a chunk only (message "=cut is not preceded by a POD section") @@ -3170,24 +3271,27 @@ b1 nil) ; error condition ;; We do not search to max, since we may be called from ;; some hook of fontification, and max is random - (or (re-search-forward "\n\n=cut\\>" stop-point 'toend) + (or (re-search-forward "^\n=cut\\>" stop-point 'toend) (progn - (message "End of a POD section not marked by =cut") - (setq b1 t) - (or (car err-l) (setcar err-l b)))) + (goto-char b) + (if (re-search-forward "\n=cut\\>" stop-point 'toend) + (progn + (message "=cut is not preceded by an empty line") + (setq b1 t) + (or (car err-l) (setcar err-l b)))))) (beginning-of-line 2) ; An empty line after =cut is not POD! (setq e (point)) - (if (and b1 (eobp)) - ;; Unrecoverable error - nil (and (> e max) - (progn - (remove-text-properties - max e '(syntax-type t in-pod t syntax-table t - 'cperl-postpone t)) - (setq tmpend tb))) + (progn + (remove-text-properties + max e '(syntax-type t in-pod t syntax-table t + cperl-postpone t + syntax-subtype t + rear-nonsticky t + indentable t)) + (setq tmpend tb))) (put-text-property b e 'in-pod t) - (put-text-property b e 'syntax-type 'in-pod) + (put-text-property b e 'syntax-type 'in-pod) (goto-char b) (while (re-search-forward "\n\n[ \t]" e t) ;; We start 'pod 1 char earlier to include the preceding line @@ -3212,19 +3316,19 @@ ;; mark the headers (cperl-postpone-fontification (match-beginning 1) (match-end 1) - 'face head-face)) - (while (re-search-forward - ;; One paragraph - "\n\n=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$" - e 'toend) - ;; mark the headers - (cperl-postpone-fontification + 'face head-face)) + (while (re-search-forward + ;; One paragraph + "^\n=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$" + e 'toend) + ;; mark the headers + (cperl-postpone-fontification (match-beginning 1) (match-end 1) 'face head-face)))) (cperl-commentify bb e nil) (goto-char e) (or (eq e (point-max)) - (forward-char -1))))) ; Prepare for immediate pod start. + (forward-char -1)))) ; Prepare for immediate pod start. ;; Here document ;; We do only one here-per-line ;; ;; One extra () before this: @@ -3359,19 +3463,19 @@ bb (char-after (1- (match-beginning b1))) ; tmp holder ;; bb == "Not a stringy" bb (if (eq b1 10) ; user variables/whatever - (or - (memq bb '(?\$ ?\@ ?\% ?\* ?\#)) ; $#y - (and (eq bb ?-) (eq c ?s)) ; -s file test - (and (eq bb ?\&) ; &&m/blah/ - (not (eq (char-after - (- (match-beginning b1) 2)) + (or + (memq bb '(?\$ ?\@ ?\% ?\* ?\#)) ; $#y + (and (eq bb ?-) (eq c ?s)) ; -s file test + (and (eq bb ?\&) + (not (eq (char-after ; &&m/blah/ + (- (match-beginning b1) 2)) ?\&)))) ;; <file> or <$file> (and (eq c ?\<) - ;; Do not stringify <FH> : + ;; Do not stringify <FH>, <$fh> : (save-match-data (looking-at - "\\s *\\$?\\([_a-zA-Z:][_a-zA-Z0-9:]*\\s *\\)?>")))) + "\\$?\\([_a-zA-Z:][_a-zA-Z0-9:]*\\)?>")))) tb (match-beginning 0)) (goto-char (match-beginning b1)) (cperl-backward-to-noncomment (point-min)) @@ -3393,8 +3497,8 @@ (and (eq (char-syntax (preceding-char)) ?w) (progn (forward-sexp -1) -;;; After these keywords `/' starts a RE. One should add all the -;;; functions/builtins which expect an argument, but ... +;; After these keywords `/' starts a RE. One should add all the +;; functions/builtins which expect an argument, but ... (if (eq (preceding-char) ?-) ;; -d ?foo? is a RE (looking-at "[a-zA-Z]\\>") @@ -3427,9 +3531,12 @@ (goto-char b) (if (or bb (nth 3 state) (nth 4 state)) (goto-char i) + ;; Skip whitespace and comments... (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+") (goto-char (match-end 0)) (skip-chars-forward " \t\n\f")) + (if (> (point) b) + (put-text-property b (point) 'syntax-type 'prestring)) ;; qtag means two-arg matcher, may be reset to ;; 2 or 3 later if some special quoting is needed. ;; e1 means matching-char matcher. @@ -3452,16 +3559,23 @@ tail (if (and i (not tag)) (1- e1)) e (if i i e1) ; end of the first part - qtag nil) ; need to preserve backslashitis + qtag nil ; need to preserve backslashitis + is-x-REx nil) ; REx has //x modifier ;; Commenting \\ is dangerous, what about ( ? (and i tail (eq (char-after i) ?\\) (setq qtag t)) + (if (looking-at "\\sw*x") ; qr//x + (setq is-x-REx t)) (if (null i) ;; Considered as 1arg form (progn (cperl-commentify b (point) t) (put-text-property b (point) 'syntax-type 'string) + (if (or is-x-REx + ;; ignore other text properties: + (string-match "^qw$" argument)) + (put-text-property b (point) 'indentable t)) (and go (setq e1 (cperl-1+ e1)) (or (eobp) @@ -3478,9 +3592,13 @@ (progn (cperl-modify-syntax-type (1- (point)) cperl-st-ket) (cperl-modify-syntax-type i cperl-st-bra))) - (put-text-property b i 'syntax-type 'string)) + (put-text-property b i 'syntax-type 'string) + (if is-x-REx + (put-text-property b i 'indentable t))) (cperl-commentify b1 (point) t) (put-text-property b (point) 'syntax-type 'string) + (if is-x-REx + (put-text-property b i 'indentable t)) (if qtag (cperl-modify-syntax-type (1+ i) cperl-st-punct)) (setq tail nil))) @@ -3489,13 +3607,16 @@ (progn (forward-word 1) ; skip modifiers s///s (if tail (cperl-commentify tail (point) t)) - (cperl-postpone-fontification - e1 (point) 'face cperl-nonoverridable-face))) + (cperl-postpone-fontification + e1 (point) 'face 'cperl-nonoverridable-face))) ;; Check whether it is m// which means "previous match" ;; and highlight differently - (if (and (eq e (+ 2 b)) - (string-match "^\\([sm]?\\|qr\\)$" argument) - ;; <> is already filtered out + (setq is-REx + (and (string-match "^\\([sm]?\\|qr\\)$" argument) + (or (not (= (length argument) 0)) + (not (eq c ?\<))))) + (if (and is-REx + (eq e (+ 2 b)) ;; split // *is* using zero-pattern (save-excursion (condition-case nil @@ -3516,7 +3637,56 @@ (cperl-postpone-fontification b (cperl-1+ b) 'face font-lock-constant-face) (cperl-postpone-fontification - (1- e) e 'face font-lock-constant-face)))) + (1- e) e 'face font-lock-constant-face))) + (if (and is-REx cperl-regexp-scan) + ;; Process RExen better + (save-excursion + (goto-char (1+ b)) + (while + (and (< (point) e) + (re-search-forward + (if is-x-REx + (if (eq (char-after b) ?\#) + "\\((\\?\\\\#\\)\\|\\(\\\\#\\)" + "\\((\\?#\\)\\|\\(#\\)") + (if (eq (char-after b) ?\#) + "\\((\\?\\\\#\\)" + "\\((\\?#\\)")) + (1- e) 'to-end)) + (goto-char (match-beginning 0)) + (setq REx-comment-start (point) + was-comment t) + (if (save-excursion + (and + ;; XXX not working if outside delimiter is # + (eq (preceding-char) ?\\) + (= (% (skip-chars-backward "$\\\\") 2) -1))) + ;; Not a comment, avoid loop: + (progn (setq was-comment nil) + (forward-char 1)) + (if (match-beginning 2) + (progn + (beginning-of-line 2) + (if (> (point) e) + (goto-char (1- e)))) + ;; Works also if the outside delimiters are (). + (or (search-forward ")" (1- e) 'toend) + (message + "Couldn't find end of (?#...)-comment in a REx, pos=%s" + REx-comment-start)))) + (if (>= (point) e) + (goto-char (1- e))) + (if was-comment + (progn + (setq REx-comment-end (point)) + (cperl-commentify + REx-comment-start REx-comment-end nil) + (cperl-postpone-fontification + REx-comment-start REx-comment-end + 'face font-lock-comment-face)))))) + (if (and is-REx is-x-REx) + (put-text-property (1+ b) (1- e) + 'syntax-subtype 'x-REx))) (if i2 (progn (cperl-postpone-fontification @@ -3569,7 +3739,7 @@ (goto-char bb)) ;; 1+6+2+1+1+2+1+1=15 extra () before this: ;; "__\\(END\\|DATA\\)__" - (t ; __END__, __DATA__ + ((match-beginning 16) ; __END__, __DATA__ (setq bb (match-end 0) b (match-beginning 0) state (parse-partial-sexp @@ -3580,7 +3750,21 @@ ;; (put-text-property b (1+ bb) 'syntax-type 'pod) ; Cheat (cperl-commentify b bb nil) (setq end t)) - (goto-char bb))) + (goto-char bb)) + ((match-beginning 17) ; "\\\\\\(['`\"]\\)" + (setq bb (match-end 0) + b (match-beginning 0)) + (goto-char b) + (skip-chars-backward "\\\\") + ;;;(setq i2 (= (% (skip-chars-backward "\\\\") 2) -1)) + (setq state (parse-partial-sexp + state-point b nil nil state) + state-point b) + (if (or (nth 3 state) (nth 4 state) ) + nil + (cperl-modify-syntax-type b cperl-st-punct)) + (goto-char bb)) + (t (error "Error in regexp of the sniffer"))) (if (> (point) stop-point) (progn (if end @@ -3629,7 +3813,7 @@ (if (eq (char-syntax (preceding-char)) ?w) ; else {} (save-excursion (forward-sexp -1) - (or (looking-at "\\(else\\|grep\\|map\\|BEGIN\\|END\\)\\>") + (or (looking-at "\\(else\\|grep\\|map\\|BEGIN\\|END\\|CHECK\\|INIT\\)\\>") ;; sub f {} (progn (cperl-backward-to-noncomment lim) @@ -3784,8 +3968,8 @@ (beginning-of-line))) ;; Looking at: ;; foreach my $var - (if (looking-at - "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\)\\(\t*\\|[ \t][ \t]+\\)[^ \t\n]") + (if (looking-at + "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)\\(\t*\\|[ \t][ \t]+\\)[^ \t\n]") (progn (forward-word 2) (delete-horizontal-space) @@ -3793,8 +3977,8 @@ (beginning-of-line))) ;; Looking at: ;; foreach my $var ( - (if (looking-at - "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\)[ \t]*\\$[_a-zA-Z0-9]+\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]") + (if (looking-at + "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)[ \t]*\\$[_a-zA-Z0-9]+\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]") (progn (forward-word 3) (delete-horizontal-space) @@ -3803,8 +3987,8 @@ (beginning-of-line))) ;; Looking at: ;; } foreach my $var () { - (if (looking-at - "[ \t]*\\(}[ \t]*\\)?\\<\\(\\els\\(e\\|if\\)\\|continue\\|if\\|unless\\|while\\|for\\(each\\)?\\(\\([ t]+\\(my\\|local\\)\\)?[ \t]*\\$[_a-zA-Z0-9]+\\)?\\|until\\)\\>\\([ \t]*(\\|[ \t\n]*{\\)\\|[ \t]*{") + (if (looking-at + "[ \t]*\\(}[ \t]*\\)?\\<\\(\\els\\(e\\|if\\)\\|continue\\|if\\|unless\\|while\\|for\\(each\\)?\\(\\([ t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\$[_a-zA-Z0-9]+\\)?\\|until\\)\\>\\([ \t]*(\\|[ \t\n]*{\\)\\|[ \t]*{") (progn (setq ml (match-beginning 8)) (re-search-forward "[({]") @@ -4145,12 +4329,13 @@ (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '()) (index-unsorted-alist '()) (i-s-f (default-value 'imenu-sort-function)) (index-meth-alist '()) meth - packages ends-ranges p + packages ends-ranges p marker (prev-pos 0) char fchar index index1 name (end-range 0) package) (goto-char (point-min)) (if noninteractive (message "Scanning Perl for index") (imenu-progress-message prev-pos 0)) + (cperl-update-syntaxification (point-max) (point-max)) ;; Search for the function (progn ;;save-match-data (while (re-search-forward @@ -4167,7 +4352,7 @@ nil) ((and (match-beginning 2) ; package or sub - ;; Skip if quoted (will not skip multi-line ''-comments :-(): + ;; Skip if quoted (will not skip multi-line ''-strings :-(): (null (get-text-property (match-beginning 1) 'syntax-table)) (null (get-text-property (match-beginning 1) 'syntax-type)) (null (get-text-property (match-beginning 1) 'in-pod))) @@ -4177,7 +4362,7 @@ ) ;; (if (looking-at "([^()]*)[ \t\n\f]*") ;; (goto-char (match-end 0))) ; Messes what follows - (setq char (following-char) + (setq char (following-char) ; ?\; for "sub foo () ;" meth nil p (point)) (while (and ends-ranges (>= p (car ends-ranges))) @@ -4200,17 +4385,19 @@ ;; ) ;; Skip this function name if it is a prototype declaration. (if (and (eq fchar ?s) (eq char ?\;)) nil - (setq index (imenu-example--name-and-position)) - (if (eq fchar ?p) nil - (setq name (buffer-substring (match-beginning 3) (match-end 3))) - (set-text-properties 0 (length name) nil name) + (setq name (buffer-substring (match-beginning 3) (match-end 3)) + marker (make-marker)) + (set-text-properties 0 (length name) nil name) + (set-marker marker (match-end 3)) + (if (eq fchar ?p) + (setq name (concat "package " name)) (cond ((string-match "[:']" name) (setq meth t)) ((> p end-range) nil) (t (setq name (concat package name) meth t)))) - (setcar index name) - (if (eq fchar ?p) + (setq index (cons name marker)) + (if (eq fchar ?p) (push index index-pack-alist) (push index index-alist)) (if meth (push index index-meth-alist)) @@ -4283,7 +4470,26 @@ index-alist)) (cperl-imenu-addback index-alist))) -(defvar cperl-compilation-error-regexp-alist + +(defvar cperl-outline-regexp + (concat cperl-imenu--function-name-regexp-perl "\\|" "\\`")) + +;; Suggested by Mark A. Hershberger +(defun cperl-outline-level () + (looking-at outline-regexp) + (cond ((not (match-beginning 1)) 0) ; beginning-of-file + ((match-beginning 2) + (if (eq (char-after (match-beginning 2)) ?p) + 0 ; package + 1)) ; sub + ((match-beginning 5) + (if (eq (char-after (match-beginning 5)) ?1) + 1 ; head1 + 2)) ; head2 + (t 3))) ; should not happen + + +(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)) @@ -4361,7 +4567,7 @@ '("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") + "require" "package" "eval" "my" "BEGIN" "END" "CHECK" "INIT") "\\|") ; Flow control "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]" ; In what follows we use `type' style @@ -4398,7 +4604,7 @@ ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite" ;; "shutdown" "sin" "sleep" "socket" "socketpair" ;; "sprintf" "sqrt" "srand" "stat" "substr" "symlink" - ;; "syscall" "sysread" "system" "syswrite" "tell" + ;; "syscall" "sysopen" "sysread" "system" "syswrite" "tell" ;; "telldir" "time" "times" "truncate" "uc" "ucfirst" ;; "umask" "unlink" "unpack" "utime" "values" "vec" ;; "wait" "waitpid" "wantarray" "warn" "write" "x" "xor" @@ -4427,7 +4633,7 @@ "\\(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\\)\\|" + "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|open\\|tem\\|write\\)\\|" "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|" "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|" "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|" @@ -4440,7 +4646,7 @@ (list (concat "\\(^\\|[^$@%&\\]\\)\\<\\(" - ;; "AUTOLOAD" "BEGIN" "DESTROY" "END" "__END__" "chomp" + ;; "AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "__END__" "chomp" ;; "chop" "defined" "delete" "do" "each" "else" "elsif" ;; "eval" "exists" "for" "foreach" "format" "goto" ;; "grep" "if" "keys" "last" "local" "map" "my" "next" @@ -4449,10 +4655,10 @@ ;; "sort" "splice" "split" "study" "sub" "tie" "tr" ;; "undef" "unless" "unshift" "untie" "until" "use" ;; "while" "y" - "AUTOLOAD\\|BEGIN\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|" + "AUTOLOAD\\|BEGIN\\|CHECK\\|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\\)\\|" + "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|INIT\\|if\\|keys\\|" + "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|our\\|" "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|" "q\\(\\|q\\|w\\|x\\|r\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|" "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|" @@ -4490,8 +4696,12 @@ font-lock-constant-face) ; labels '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets 2 font-lock-constant-face) + ;; Uncomment to get perl-mode-like vars + ;;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face) + ;;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)" + ;;; (2 (cons font-lock-variable-name-face '(underline)))) (cond ((featurep 'font-lock-extra) - '("^[ \t]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?" + '("^[ \t]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?" (3 font-lock-variable-name-face) (4 '(another 4 nil ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?" @@ -4499,16 +4709,16 @@ (2 '(restart 2 nil) nil t))) nil t))) ; local variables, multiple (font-lock-anchored - '("^[ \t{}]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)" + '("^[ \t{}]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)" (3 font-lock-variable-name-face) ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)" nil nil (1 font-lock-variable-name-face)))) - (t '("^[ \t{}]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)" + (t '("^[ \t{}]*\\(my\\|local\\our\\)[ \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))) - (setq + '("\\<for\\(each\\)?\\([ \t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*(" + 4 font-lock-variable-name-face))) + (setq t-font-lock-keywords-1 (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock (not cperl-xemacs-p) ; not yet as of XEmacs 19.12 @@ -4534,15 +4744,20 @@ ;; (if (cperl-slash-is-regexp) ;; font-lock-function-name-face 'default) nil t)) ))) - (setq cperl-font-lock-keywords-1 + (if cperl-highlight-variables-indiscriminately + (setq t-font-lock-keywords-1 + (append t-font-lock-keywords-1 + (list '("[$*]{?\\(\\sw+\\)" 1 + font-lock-variable-name-face))))) + (setq cperl-font-lock-keywords-1 (if cperl-syntaxify-by-font-lock (cons 'cperl-fontify-update t-font-lock-keywords) t-font-lock-keywords) cperl-font-lock-keywords cperl-font-lock-keywords-1 cperl-font-lock-keywords-2 (append - cperl-font-lock-keywords-1 - t-font-lock-keywords-1))) + cperl-font-lock-keywords-1 + t-font-lock-keywords-1))) (if (fboundp 'ps-print-buffer) (cperl-ps-print-init)) (if (or (featurep 'choose-color) (featurep 'font-lock-extra)) (eval ; Avoid a warning @@ -5333,19 +5548,29 @@ (imenu-progress-message prev-pos 100)) index-alist)) -(defun cperl-find-tags (file xs topdir) +(defvar cperl-unreadable-ok nil) + +(defun cperl-find-tags (ifile xs topdir) (let (ind (b (get-buffer cperl-tmp-buffer)) lst elt pos ret rel - (cperl-pod-here-fontify nil)) + (cperl-pod-here-fontify nil) f file) (save-excursion (if b (set-buffer b) (cperl-setup-tmp-buf)) (erase-buffer) - (setq file (car (insert-file-contents file))) + (condition-case err + (setq file (car (insert-file-contents ifile))) + (error (if cperl-unreadable-ok nil + (if (y-or-n-p + (format "File %s unreadable. Continue? " ifile)) + (setq cperl-unreadable-ok t) + (error "Aborting: unreadable file %s" ifile))))) + (if (not file) + (message "Unreadable file %s" ifile) (message "Scanning file %s ..." file) (if (and cperl-use-syntax-table-text-property-for-tags (not xs)) (condition-case err ; after __END__ may have garbage - (cperl-find-pods-heres) + (cperl-find-pods-heres nil nil noninteractive) (error (message "While scanning for syntax: %s" err)))) (if xs (setq lst (cperl-xsub-scan)) @@ -5362,8 +5587,8 @@ (point) (1+ (count-lines 1 (point))) ; 1+ since at beg-o-l (buffer-substring (progn - (skip-chars-forward - ":_a-zA-Z0-9") + (goto-char (cdr elt)) + ;; After name now... (or (eolp) (forward-char 1)) (point)) (progn @@ -5406,7 +5631,7 @@ (erase-buffer) (or noninteractive (message "Scanning file %s finished" file)) - ret))) + ret)))) (defun cperl-add-tags-recurse-noxs () "Add to TAGS data for Perl and XSUB files in the current directory and kids. @@ -5435,7 +5660,7 @@ (setq topdir default-directory)) (let ((tags-file-name "TAGS") (case-fold-search (eq system-type 'emx)) - xs rel) + xs rel tm) (save-excursion (cond (inbuffer nil) ; Already there ((file-exists-p tags-file-name) @@ -5449,10 +5674,18 @@ (erase (erase-buffer) (setq erase 'ignore))) - (let ((files - (directory-files file t - (if recurse nil cperl-scan-files-regexp) - t))) + (let ((files + (condition-case err + (directory-files file t + (if recurse nil cperl-scan-files-regexp) + t) + (error + (if cperl-unreadable-ok nil + (if (y-or-n-p + (format "Directory %s unreadable. Continue? " file)) + (setq cperl-unreadable-ok t + tm nil) ; Return empty list + (error "Aborting: unreadable directory %s" file))))))) (mapcar (function (lambda (file) (cond ((string-match cperl-noscan-files-regexp file) @@ -6129,6 +6362,8 @@ ARGVOUT Output filehandle with -i flag. BEGIN { ... } Immediately executed (during compilation) piece of code. END { ... } Pseudo-subroutine executed after the script finishes. +CHECK { ... } Pseudo-subroutine executed after the script is compiled. +INIT { ... } Pseudo-subroutine executed before the script starts running. DATA Input filehandle for what follows after __END__ or __DATA__. accept(NEWSOCKET,GENERICSOCKET) alarm(SECONDS) @@ -6230,6 +6465,7 @@ msgrcv(ID,VAR,SIZE,TYPE.FLAGS) msgsnd(ID,MSG,FLAGS) my VAR or my (VAR1,...) Introduces a lexical variable ($VAR, @ARR, or %HASH). +our VAR or our (VAR1,...) Lexically enable a global variable ($V, @A, or %H). ... ne ... String inequality. next [LABEL] oct(EXPR) @@ -6398,14 +6634,18 @@ 'variable-documentation)) (setq buffer-read-only t))))) -(defun cperl-beautify-regexp-piece (b e embed) +(defun cperl-beautify-regexp-piece (b e embed level) ;; b is before the starting delimiter, e before the ending ;; e should be a marker, may be changed, but remains "correct". - (let (s c tmp (m (make-marker)) (m1 (make-marker)) c1 spaces inline code) + ;; EMBED is nil iff we process the whole REx. + ;; The REx is guarantied to have //x + ;; LEVEL shows how many levels deep to go + ;; position at enter and at leave is not defined + (let (s c tmp (m (make-marker)) (m1 (make-marker)) c1 spaces inline code pos) (if (not embed) (goto-char (1+ b)) (goto-char b) - (cond ((looking-at "(\\?\\\\#") ; badly commented (?#) + (cond ((looking-at "(\\?\\\\#") ; (?#) wrongly commented when //x-ing (forward-char 2) (delete-char 1) (forward-char 1)) @@ -6423,8 +6663,9 @@ (goto-char e) (beginning-of-line) (if (re-search-forward "[^ \t]" e t) - (progn + (progn ; Something before the ending delimiter (goto-char e) + (delete-horizontal-space) (insert "\n") (indent-to-column c) (set-marker e (point)))) @@ -6467,17 +6708,27 @@ (setq tmp (point)) (if (looking-at "\\^?\\]") (goto-char (match-end 0))) - (or (re-search-forward "\\]\\([*+{?]\\)?" e t) + ;; XXXX POSIX classes?! + (while (and (not pos) + (re-search-forward "\\[:\\|\\]" e t)) + (if (eq (preceding-char) ?:) + (or (re-search-forward ":\\]" e t) + (error "[:POSIX:]-group in []-group not terminated")) + (setq pos t))) + (or (eq (preceding-char) ?\]) + (error "[]-group not terminated")) + (if (eq (following-char) ?\{) (progn - (goto-char (1- tmp)) - (error "[]-group not terminated"))) - (if (not (eq (preceding-char) ?\{)) nil - (forward-char -1) - (forward-sexp 1))) + (forward-sexp 1) + (and (eq (following-char) ??) + (forward-char 1))) + (re-search-forward "\\=\\([*+?]\\??\\)" e t))) ((match-beginning 7) ; () (goto-char (match-beginning 0)) - (or (eq (current-column) c1) + (setq pos (current-column)) + (or (eq pos c1) (progn + (delete-horizontal-space) (insert "\n") (indent-to-column c1))) (setq tmp (point)) @@ -6488,20 +6739,29 @@ ;; (error "()-group not terminated"))) (set-marker m (1- (point))) (set-marker m1 (point)) - (cond - ((not (match-beginning 8)) - (cperl-beautify-regexp-piece tmp m t)) - ((eq (char-after (+ 2 tmp)) ?\{) ; Code - t) - ((eq (char-after (+ 2 tmp)) ?\() ; Conditional - (goto-char (+ 2 tmp)) - (forward-sexp 1) - (cperl-beautify-regexp-piece (point) m t)) - ((eq (char-after (+ 2 tmp)) ?<) ; Lookbehind - (goto-char (+ 3 tmp)) - (cperl-beautify-regexp-piece (point) m t)) - (t - (cperl-beautify-regexp-piece tmp m t))) + (if (= level 1) + (if (progn ; indent rigidly if multiline + ;; In fact does not make a lot of sense, since + ;; the starting position can be already lost due + ;; to insertion of "\n" and " " + (goto-char tmp) + (search-forward "\n" m1 t)) + (indent-rigidly (point) m1 (- c1 pos))) + (setq level (1- level)) + (cond + ((not (match-beginning 8)) + (cperl-beautify-regexp-piece tmp m t level)) + ((eq (char-after (+ 2 tmp)) ?\{) ; Code + t) + ((eq (char-after (+ 2 tmp)) ?\() ; Conditional + (goto-char (+ 2 tmp)) + (forward-sexp 1) + (cperl-beautify-regexp-piece (point) m t level)) + ((eq (char-after (+ 2 tmp)) ?<) ; Lookbehind + (goto-char (+ 3 tmp)) + (cperl-beautify-regexp-piece (point) m t level)) + (t + (cperl-beautify-regexp-piece tmp m t level)))) (goto-char m1) (cond ((looking-at "[*+?]\\??") (goto-char (match-end 0))) @@ -6515,6 +6775,7 @@ (progn (or (eolp) (indent-for-comment)) (beginning-of-line 2)) + (delete-horizontal-space) (insert "\n")) (end-of-line) (setq inline nil)) @@ -6525,6 +6786,7 @@ (if (re-search-forward "[^ \t]" tmp t) (progn (goto-char tmp) + (delete-horizontal-space) (insert "\n")) ;; first at line (delete-region (point) tmp)) @@ -6534,6 +6796,7 @@ (setq spaces nil) (if (looking-at "[#\n]") (beginning-of-line 2) + (delete-horizontal-space) (insert "\n")) (end-of-line) (setq inline nil))) @@ -6542,8 +6805,8 @@ (insert " ")) (skip-chars-forward " \t")) (or (looking-at "[#\n]") - (error "unknown code \"%s\" in a regexp" (buffer-substring (point) - (1+ (point))))) + (error "unknown code \"%s\" in a regexp" + (buffer-substring (point) (1+ (point))))) (and inline (end-of-line 2))) ;; Special-case the last line of group (if (and (>= (point) (marker-position e)) @@ -6558,6 +6821,7 @@ (defun cperl-make-regexp-x () ;; Returns position of the start + ;; XXX this is called too often! Need to cache the result! (save-excursion (or cperl-use-syntax-table-text-property (error "I need to have a regexp marked!")) @@ -6588,15 +6852,19 @@ (forward-char 1))) b))) -(defun cperl-beautify-regexp () +(defun cperl-beautify-regexp (&optional deep) "do it. (Experimental, may change semantics, recheck the result.) We suppose that the regexp is scanned already." - (interactive) - (goto-char (cperl-make-regexp-x)) - (let ((b (point)) (e (make-marker))) - (forward-sexp 1) - (set-marker e (1- (point))) - (cperl-beautify-regexp-piece b e nil))) + (interactive "P") + (if deep + (prefix-numeric-value deep) + (setq deep -1)) + (save-excursion + (goto-char (cperl-make-regexp-x)) + (let ((b (point)) (e (make-marker))) + (forward-sexp 1) + (set-marker e (1- (point))) + (cperl-beautify-regexp-piece b e nil deep)))) (defun cperl-regext-to-level-start () "Goto start of an enclosing group in regexp. @@ -6618,15 +6886,16 @@ \(Experimental, may change semantics, recheck the result.) We suppose that the regexp is scanned already." (interactive) - (cperl-regext-to-level-start) - (let ((b (point)) (e (make-marker)) s c) - (forward-sexp 1) - (set-marker e (1- (point))) - (goto-char b) - (while (re-search-forward "\\(#\\)\\|\n" e t) - (cond - ((match-beginning 1) ; #-comment - (or c (setq c (current-indentation))) + ;; (save-excursion ; Can't, breaks `cperl-contract-levels' + (cperl-regext-to-level-start) + (let ((b (point)) (e (make-marker)) s c) + (forward-sexp 1) + (set-marker e (1- (point))) + (goto-char b) + (while (re-search-forward "\\(#\\)\\|\n" e 'to-end) + (cond + ((match-beginning 1) ; #-comment + (or c (setq c (current-indentation))) (beginning-of-line 2) ; Skip (setq s (point)) (skip-chars-forward " \t") @@ -6641,9 +6910,10 @@ \(Experimental, may change semantics, recheck the result.) We suppose that the regexp is scanned already." (interactive) - (condition-case nil - (cperl-regext-to-level-start) - (error ; We are outside outermost group + (save-excursion + (condition-case nil + (cperl-regext-to-level-start) + (error ; We are outside outermost group (goto-char (cperl-make-regexp-x)))) (let ((b (point)) (e (make-marker)) s c) (forward-sexp 1) @@ -6651,28 +6921,32 @@ (goto-char (1+ b)) (while (re-search-forward "\\(\\\\\\\\\\)\\|(" e t) (cond - ((match-beginning 1) ; Skip - nil) - (t ; Group - (cperl-contract-level)))))) - -(defun cperl-beautify-level () + ((match-beginning 1) ; Skip + nil) + (t ; Group + (cperl-contract-level))))))) + +(defun cperl-beautify-level (&optional deep) "Find an enclosing group in regexp and beautify it. \(Experimental, may change semantics, recheck the result.) We suppose that the regexp is scanned already." - (interactive) - (cperl-regext-to-level-start) - (let ((b (point)) (e (make-marker))) - (forward-sexp 1) - (set-marker e (1- (point))) - (cperl-beautify-regexp-piece b e nil))) + (interactive "P") + (if deep + (prefix-numeric-value deep) + (setq deep -1)) + (save-excursion + (cperl-regext-to-level-start) + (let ((b (point)) (e (make-marker))) + (forward-sexp 1) + (set-marker e (1- (point))) + (cperl-beautify-regexp-piece b e nil deep)))) (defun cperl-invert-if-unless () - "Change `if (A) {B}' into `B if A;' if possible." + "Change `if (A) {B}' into `B if A;' etc if possible." (interactive) (or (looking-at "\\<") (forward-sexp -1)) - (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\)\\>") + (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>") (let ((pos1 (point)) pos2 pos3 pos4 pos5 s1 s2 state p pos45 (s0 (buffer-substring (match-beginning 0) (match-end 0)))) @@ -6743,6 +7017,7 @@ (forward-word 1) (setq pos1 (point)) (insert " " s1 ";") + (delete-horizontal-space) (forward-char -1) (delete-horizontal-space) (goto-char pos1) @@ -6750,7 +7025,7 @@ (cperl-indent-line)) (error "`%s' (EXPR) not with an {BLOCK}" s0))) (error "`%s' not with an (EXPR)" s0))) - (error "Not at `if', `unless', `while', or `unless'"))) + (error "Not at `if', `unless', `while', `unless', `for' or `foreach'"))) ;;; By Anthony Foiani <afoiani@uswest.com> ;;; Getting help on modules in C-h f ? @@ -6879,7 +7154,8 @@ (defvar cperl-d-l nil) (defun cperl-fontify-syntaxically (end) ;; Some vars for debugging only - (let (start (dbg (point)) (iend end) + ;; (message "Syntaxifying...") + (let (start (dbg (point)) (iend end) (istate (car cperl-syntax-state))) (and cperl-syntaxify-unwind (setq end (cperl-unwind-to-safe t end))) @@ -6896,12 +7172,6 @@ (and (> end start) (setq cperl-syntax-done-to start) ; In case what follows fails (cperl-find-pods-heres start end t nil t)) - ;;(setq cperl-d-l (cons (format "Syntaxifying %s..%s from %s to %s\n" - ;; dbg end start cperl-syntax-done-to) - ;; cperl-d-l)) - ;;(let ((standard-output (get-buffer "*Messages*"))) - ;;(princ (format "Syntaxifying %s..%s from %s to %s\n" - ;; dbg end start cperl-syntax-done-to))) (if (eq cperl-syntaxify-by-font-lock 'message) (message "Syntaxified %s..%s from %s to %s(%s), state %s-->%s" dbg iend @@ -6929,7 +7199,7 @@ (cperl-fontify-syntaxically to))))) (defvar cperl-version - (let ((v "Revision: 4.23")) + (let ((v "Revision: 4.32")) (string-match ":\\s *\\([0-9.]+\\)" v) (substring v (match-beginning 1) (match-end 1))) "Version of IZ-supported CPerl package this file is based on.")