Fix up comment convention on the arch-tag lines.
[bpt/emacs.git] / lisp / progmodes / cperl-mode.el
CommitLineData
f83d2997
KH
1;;; cperl-mode.el --- Perl code editing commands for Emacs
2
034babe1 3;; Copyright (C) 1985, 1986, 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
4e643dd2 4;; 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
f83d2997
KH
5;; Free Software Foundation, Inc.
6
7;; Author: Ilya Zakharevich and Bob Olson
4ab89e7b 8;; Maintainer: Ilya Zakharevich <ilyaz@cpan.org>
f83d2997
KH
9;; Keywords: languages, Perl
10
11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
1a484753 15;; the Free Software Foundation; either version 3, or (at your option)
f83d2997
KH
16;; any later version.
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
f83d2997 27
4ab89e7b 28;;; Corrections made by Ilya Zakharevich ilyaz@cpan.org
f83d2997
KH
29
30;;; Commentary:
31
83261a2f
SM
32;; You can either fine-tune the bells and whistles of this mode or
33;; bulk enable them by putting
f83d2997
KH
34
35;; (setq cperl-hairy t)
36
83261a2f
SM
37;; in your .emacs file. (Emacs rulers do not consider it politically
38;; correct to make whistles enabled by default.)
f83d2997 39
83261a2f
SM
40;; DO NOT FORGET to read micro-docs (available from `Perl' menu) <<<<<<
41;; or as help on variables `cperl-tips', `cperl-problems', <<<<<<
15ca5699 42;; `cperl-praise', `cperl-speed'. <<<<<<
f83d2997 43
83261a2f
SM
44;; The mode information (on C-h m) provides some customization help.
45;; If you use font-lock feature of this mode, it is advisable to use
46;; either lazy-lock-mode or fast-lock-mode. I prefer lazy-lock.
f83d2997 47
83261a2f
SM
48;; Faces used now: three faces for first-class and second-class keywords
49;; and control flow words, one for each: comments, string, labels,
50;; functions definitions and packages, arrays, hashes, and variable
51;; definitions. If you do not see all these faces, your font-lock does
52;; not define them, so you need to define them manually.
f83d2997 53
83261a2f
SM
54;; This mode supports font-lock, imenu and mode-compile. In the
55;; hairy version font-lock is on, but you should activate imenu
56;; yourself (note that mode-compile is not standard yet). Well, you
57;; can use imenu from keyboard anyway (M-x imenu), but it is better
58;; to bind it like that:
f83d2997
KH
59
60;; (define-key global-map [M-S-down-mouse-3] 'imenu)
61
83261a2f
SM
62;;; Font lock bugs as of v4.32:
63
64;; The following kinds of Perl code erroneously start strings:
65;; \$` \$' \$"
66;; $opt::s $opt_s $opt{s} (s => ...) /\s+.../
67;; likewise with m, tr, y, q, qX instead of s
68
f83d2997 69;;; Code:
4ab89e7b 70\f
b5b0cb34
JB
71(defvar vc-rcs-header)
72(defvar vc-sccs-header)
73
80585273 74(eval-when-compile
4ab89e7b
SM
75 (condition-case nil
76 (require 'custom)
77 (error nil))
78 (condition-case nil
79 (require 'man)
80 (error nil))
4ab89e7b 81 (defvar cperl-can-font-lock
6546555e 82 (or (featurep 'xemacs)
4ab89e7b
SM
83 (and (boundp 'emacs-major-version)
84 (or window-system
85 (> emacs-major-version 20)))))
86 (if cperl-can-font-lock
87 (require 'font-lock))
88 (defvar msb-menu-cond)
89 (defvar gud-perldb-history)
90 (defvar font-lock-background-mode) ; not in Emacs
91 (defvar font-lock-display-type) ; ditto
92 (defvar paren-backwards-message) ; Not in newer XEmacs?
93 (or (fboundp 'defgroup)
94 (defmacro defgroup (name val doc &rest arr)
95 nil))
96 (or (fboundp 'custom-declare-variable)
97 (defmacro defcustom (name val doc &rest arr)
9edd6ee6 98 `(defvar ,name ,val ,doc)))
4ab89e7b
SM
99 (or (and (fboundp 'custom-declare-variable)
100 (string< "19.31" emacs-version)) ; Checked with 19.30: defface does not work
101 (defmacro defface (&rest arr)
102 nil))
103 ;; Avoid warning (tmp definitions)
104 (or (fboundp 'x-color-defined-p)
105 (defmacro x-color-defined-p (col)
9edd6ee6 106 (cond ((fboundp 'color-defined-p) `(color-defined-p ,col))
4ab89e7b 107 ;; XEmacs >= 19.12
9edd6ee6 108 ((fboundp 'valid-color-name-p) `(valid-color-name-p ,col))
4ab89e7b 109 ;; XEmacs 19.11
9edd6ee6 110 ((fboundp 'x-valid-color-name-p) `(x-valid-color-name-p ,col))
4ab89e7b
SM
111 (t '(error "Cannot implement color-defined-p")))))
112 (defmacro cperl-is-face (arg) ; Takes quoted arg
113 (cond ((fboundp 'find-face)
9edd6ee6 114 `(find-face ,arg))
4ab89e7b
SM
115 (;;(and (fboundp 'face-list)
116 ;; (face-list))
117 (fboundp 'face-list)
9edd6ee6
SM
118 `(member ,arg (and (fboundp 'face-list)
119 (face-list))))
4ab89e7b 120 (t
9edd6ee6 121 `(boundp ,arg))))
4ab89e7b
SM
122 (defmacro cperl-make-face (arg descr) ; Takes unquoted arg
123 (cond ((fboundp 'make-face)
9edd6ee6 124 `(make-face (quote ,arg)))
4ab89e7b 125 (t
9edd6ee6 126 `(defvar ,arg (quote ,arg) ,descr))))
4ab89e7b 127 (defmacro cperl-force-face (arg descr) ; Takes unquoted arg
9edd6ee6
SM
128 `(progn
129 (or (cperl-is-face (quote ,arg))
130 (cperl-make-face ,arg ,descr))
131 (or (boundp (quote ,arg)) ; We use unquoted variants too
132 (defvar ,arg (quote ,arg) ,descr))))
6546555e 133 (if (featurep 'xemacs)
4ab89e7b 134 (defmacro cperl-etags-snarf-tag (file line)
9edd6ee6
SM
135 `(progn
136 (beginning-of-line 2)
137 (list ,file ,line)))
4ab89e7b 138 (defmacro cperl-etags-snarf-tag (file line)
9edd6ee6 139 `(etags-snarf-tag)))
6546555e 140 (if (featurep 'xemacs)
4ab89e7b 141 (defmacro cperl-etags-goto-tag-location (elt)
9edd6ee6
SM
142 ;;(progn
143 ;; (switch-to-buffer (get-file-buffer (elt ,elt 0)))
144 ;; (set-buffer (get-file-buffer (elt ,elt 0)))
145 ;; Probably will not work due to some save-excursion???
146 ;; Or save-file-position?
147 ;; (message "Did I get to line %s?" (elt ,elt 1))
148 `(goto-line (string-to-int (elt ,elt 1))))
4ab89e7b
SM
149 ;;)
150 (defmacro cperl-etags-goto-tag-location (elt)
9edd6ee6 151 `(etags-goto-tag-location ,elt))))
5bd52f0e 152
83261a2f 153(defvar cperl-can-font-lock
6546555e 154 (or (featurep 'xemacs)
83261a2f
SM
155 (and (boundp 'emacs-major-version)
156 (or window-system
157 (> emacs-major-version 20)))))
158
5bd52f0e
RS
159(defun cperl-choose-color (&rest list)
160 (let (answer)
161 (while list
162 (or answer
163 (if (or (x-color-defined-p (car list))
164 (null (cdr list)))
165 (setq answer (car list))))
166 (setq list (cdr list)))
167 answer))
168
ccc3ce39
SE
169(defgroup cperl nil
170 "Major mode for editing Perl code."
171 :prefix "cperl-"
db133cb6
RS
172 :group 'languages
173 :version "20.3")
174
175(defgroup cperl-indentation-details nil
176 "Indentation."
177 :prefix "cperl-"
178 :group 'cperl)
179
180(defgroup cperl-affected-by-hairy nil
181 "Variables affected by `cperl-hairy'."
182 :prefix "cperl-"
183 :group 'cperl)
184
185(defgroup cperl-autoinsert-details nil
186 "Auto-insert tuneup."
187 :prefix "cperl-"
188 :group 'cperl)
189
190(defgroup cperl-faces nil
191 "Fontification colors."
8ec3bce0 192 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
db133cb6
RS
193 :prefix "cperl-"
194 :group 'cperl)
195
196(defgroup cperl-speed nil
197 "Speed vs. validity tuneup."
198 :prefix "cperl-"
199 :group 'cperl)
200
201(defgroup cperl-help-system nil
202 "Help system tuneup."
203 :prefix "cperl-"
204 :group 'cperl)
ccc3ce39 205
f83d2997 206\f
ccc3ce39 207(defcustom cperl-extra-newline-before-brace nil
f83d2997
KH
208 "*Non-nil means that if, elsif, while, until, else, for, foreach
209and do constructs look like:
210
211 if ()
212 {
213 }
214
215instead of:
216
217 if () {
83261a2f 218 }"
ccc3ce39 219 :type 'boolean
db133cb6
RS
220 :group 'cperl-autoinsert-details)
221
5c8b7eaf 222(defcustom cperl-extra-newline-before-brace-multiline
db133cb6
RS
223 cperl-extra-newline-before-brace
224 "*Non-nil means the same as `cperl-extra-newline-before-brace', but
225for constructs with multiline if/unless/while/until/for/foreach condition."
226 :type 'boolean
227 :group 'cperl-autoinsert-details)
ccc3ce39
SE
228
229(defcustom cperl-indent-level 2
230 "*Indentation of CPerl statements with respect to containing block."
231 :type 'integer
db133cb6 232 :group 'cperl-indentation-details)
f152a898 233
2d5590e0 234;; Is is not unusual to put both things like perl-indent-level and
f152a898
DN
235;; cperl-indent-level in the local variable section of a file. If only
236;; one of perl-mode and cperl-mode is in use, a warning will be issued
2d5590e0 237;; about the variable. Autoload these here, so that no warning is
f152a898
DN
238;; issued when using either perl-mode or cperl-mode.
239;;;###autoload(put 'cperl-indent-level 'safe-local-variable 'integerp)
2d5590e0
DN
240;;;###autoload(put 'cperl-brace-offset 'safe-local-variable 'integerp)
241;;;###autoload(put 'cperl-continued-brace-offset 'safe-local-variable 'integerp)
242;;;###autoload(put 'cperl-label-offset 'safe-local-variable 'integerp)
243;;;###autoload(put 'cperl-continued-statement-offset 'safe-local-variable 'integerp)
244;;;###autoload(put 'cperl-extra-newline-before-brace 'safe-local-variable 'booleanp)
245;;;###autoload(put 'cperl-merge-trailing-else 'safe-local-variable 'booleanp)
f83d2997 246
ccc3ce39 247(defcustom cperl-lineup-step nil
f83d2997 248 "*`cperl-lineup' will always lineup at multiple of this number.
029cb4d5 249If nil, the value of `cperl-indent-level' will be used."
ccc3ce39 250 :type '(choice (const nil) integer)
db133cb6
RS
251 :group 'cperl-indentation-details)
252
ccc3ce39 253(defcustom cperl-brace-imaginary-offset 0
f83d2997
KH
254 "*Imagined indentation of a Perl open brace that actually follows a statement.
255An open brace following other text is treated as if it were this far
ccc3ce39
SE
256to the right of the start of its line."
257 :type 'integer
db133cb6 258 :group 'cperl-indentation-details)
ccc3ce39
SE
259
260(defcustom cperl-brace-offset 0
261 "*Extra indentation for braces, compared with other text in same context."
262 :type 'integer
db133cb6 263 :group 'cperl-indentation-details)
ccc3ce39
SE
264(defcustom cperl-label-offset -2
265 "*Offset of CPerl label lines relative to usual indentation."
266 :type 'integer
db133cb6 267 :group 'cperl-indentation-details)
ccc3ce39
SE
268(defcustom cperl-min-label-indent 1
269 "*Minimal offset of CPerl label lines."
270 :type 'integer
db133cb6 271 :group 'cperl-indentation-details)
ccc3ce39
SE
272(defcustom cperl-continued-statement-offset 2
273 "*Extra indent for lines not starting new statements."
274 :type 'integer
db133cb6 275 :group 'cperl-indentation-details)
ccc3ce39 276(defcustom cperl-continued-brace-offset 0
f83d2997 277 "*Extra indent for substatements that start with open-braces.
ccc3ce39
SE
278This is in addition to cperl-continued-statement-offset."
279 :type 'integer
db133cb6 280 :group 'cperl-indentation-details)
ccc3ce39
SE
281(defcustom cperl-close-paren-offset -1
282 "*Extra indent for substatements that start with close-parenthesis."
283 :type 'integer
db133cb6 284 :group 'cperl-indentation-details)
ccc3ce39 285
4ab89e7b
SM
286(defcustom cperl-indent-wrt-brace t
287 "*Non-nil means indent statements in if/etc block relative brace, not if/etc.
288Versions 5.2 ... 5.20 behaved as if this were `nil'."
289 :type 'boolean
290 :group 'cperl-indentation-details)
291
ccc3ce39 292(defcustom cperl-auto-newline nil
f83d2997
KH
293 "*Non-nil means automatically newline before and after braces,
294and after colons and semicolons, inserted in CPerl code. The following
295\\[cperl-electric-backspace] will remove the inserted whitespace.
5c8b7eaf 296Insertion after colons requires both this variable and
ccc3ce39
SE
297`cperl-auto-newline-after-colon' set."
298 :type 'boolean
db133cb6 299 :group 'cperl-autoinsert-details)
f83d2997 300
6c389151
SM
301(defcustom cperl-autoindent-on-semi nil
302 "*Non-nil means automatically indent after insertion of (semi)colon.
303Active if `cperl-auto-newline' is false."
304 :type 'boolean
305 :group 'cperl-autoinsert-details)
306
ccc3ce39 307(defcustom cperl-auto-newline-after-colon nil
f83d2997 308 "*Non-nil means automatically newline even after colons.
ccc3ce39
SE
309Subject to `cperl-auto-newline' setting."
310 :type 'boolean
db133cb6 311 :group 'cperl-autoinsert-details)
f83d2997 312
ccc3ce39 313(defcustom cperl-tab-always-indent t
f83d2997 314 "*Non-nil means TAB in CPerl mode should always reindent the current line,
ccc3ce39
SE
315regardless of where in the line point is when the TAB command is used."
316 :type 'boolean
db133cb6 317 :group 'cperl-indentation-details)
f83d2997 318
ccc3ce39 319(defcustom cperl-font-lock nil
029cb4d5 320 "*Non-nil (and non-null) means CPerl buffers will use `font-lock-mode'.
ccc3ce39 321Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
322 :type '(choice (const null) boolean)
323 :group 'cperl-affected-by-hairy)
f83d2997 324
ccc3ce39 325(defcustom cperl-electric-lbrace-space nil
029cb4d5 326 "*Non-nil (and non-null) means { after $ should be preceded by ` '.
ccc3ce39 327Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
328 :type '(choice (const null) boolean)
329 :group 'cperl-affected-by-hairy)
f83d2997 330
ccc3ce39 331(defcustom cperl-electric-parens-string "({[]})<"
f83d2997 332 "*String of parentheses that should be electric in CPerl.
ccc3ce39
SE
333Closing ones are electric only if the region is highlighted."
334 :type 'string
db133cb6 335 :group 'cperl-affected-by-hairy)
f83d2997 336
ccc3ce39 337(defcustom cperl-electric-parens nil
f83d2997 338 "*Non-nil (and non-null) means parentheses should be electric in CPerl.
ccc3ce39 339Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
340 :type '(choice (const null) boolean)
341 :group 'cperl-affected-by-hairy)
342
343(defvar zmacs-regions) ; Avoid warning
344
5c8b7eaf 345(defcustom cperl-electric-parens-mark
f83d2997
KH
346 (and window-system
347 (or (and (boundp 'transient-mark-mode) ; For Emacs
348 transient-mark-mode)
349 (and (boundp 'zmacs-regions) ; For XEmacs
350 zmacs-regions)))
351 "*Not-nil means that electric parens look for active mark.
ccc3ce39
SE
352Default is yes if there is visual feedback on mark."
353 :type 'boolean
db133cb6 354 :group 'cperl-autoinsert-details)
f83d2997 355
ccc3ce39 356(defcustom cperl-electric-linefeed nil
f83d2997
KH
357 "*If true, LFD should be hairy in CPerl, otherwise C-c LFD is hairy.
358In any case these two mean plain and hairy linefeeds together.
ccc3ce39 359Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
360 :type '(choice (const null) boolean)
361 :group 'cperl-affected-by-hairy)
f83d2997 362
ccc3ce39 363(defcustom cperl-electric-keywords nil
f83d2997 364 "*Not-nil (and non-null) means keywords are electric in CPerl.
350b4cb9
EZ
365Can be overwritten by `cperl-hairy' if nil.
366
367Uses `abbrev-mode' to do the expansion. If you want to use your
368own abbrevs in cperl-mode, but do not want keywords to be
369electric, you must redefine `cperl-mode-abbrev-table': do
370\\[edit-abbrevs], search for `cperl-mode-abbrev-table', and, in
371that paragraph, delete the words that appear at the ends of lines and
372that begin with \"cperl-electric\".
373"
db133cb6
RS
374 :type '(choice (const null) boolean)
375 :group 'cperl-affected-by-hairy)
ccc3ce39 376
f739b53b
SM
377(defcustom cperl-electric-backspace-untabify t
378 "*Not-nil means electric-backspace will untabify in CPerl."
379 :type 'boolean
380 :group 'cperl-autoinsert-details)
381
ccc3ce39 382(defcustom cperl-hairy nil
db133cb6 383 "*Not-nil means most of the bells and whistles are enabled in CPerl.
5c8b7eaf 384Affects: `cperl-font-lock', `cperl-electric-lbrace-space',
db133cb6
RS
385`cperl-electric-parens', `cperl-electric-linefeed', `cperl-electric-keywords',
386`cperl-info-on-command-no-prompt', `cperl-clobber-lisp-bindings',
387`cperl-lazy-help-time'."
ccc3ce39 388 :type 'boolean
db133cb6 389 :group 'cperl-affected-by-hairy)
ccc3ce39
SE
390
391(defcustom cperl-comment-column 32
392 "*Column to put comments in CPerl (use \\[cperl-indent] to lineup with code)."
393 :type 'integer
db133cb6 394 :group 'cperl-indentation-details)
ccc3ce39 395
4ab89e7b
SM
396(defcustom cperl-indent-comment-at-column-0 nil
397 "*Non-nil means that comment started at column 0 should be indentable."
398 :type 'boolean
399 :group 'cperl-indentation-details)
e1a5828f
AS
400
401(defcustom cperl-vc-sccs-header '("($sccs) = ('%W\%' =~ /(\\d+(\\.\\d+)+)/) ;")
402 "*Special version of `vc-sccs-header' that is used in CPerl mode buffers."
403 :type '(repeat string)
404 :group 'cperl)
405
4ab89e7b 406(defcustom cperl-vc-rcs-header '("($rcs) = (' $Id\$ ' =~ /(\\d+(\\.\\d+)+)/);")
e1a5828f
AS
407 "*Special version of `vc-rcs-header' that is used in CPerl mode buffers."
408 :type '(repeat string)
4ab89e7b
SM
409 :group 'cperl)
410
411;; This became obsolete...
412(defvar cperl-vc-header-alist nil)
413(make-obsolete-variable
414 'cperl-vc-header-alist
415 "use cperl-vc-rcs-header or cperl-vc-sccs-header instead.")
ccc3ce39 416
5c8b7eaf 417(defcustom cperl-clobber-mode-lists
5bd52f0e
RS
418 (not
419 (and
420 (boundp 'interpreter-mode-alist)
421 (assoc "miniperl" interpreter-mode-alist)
422 (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist)))
423 "*Whether to install us into `interpreter-' and `extension' mode lists."
424 :type 'boolean
425 :group 'cperl)
426
ccc3ce39 427(defcustom cperl-info-on-command-no-prompt nil
f83d2997 428 "*Not-nil (and non-null) means not to prompt on C-h f.
6292d528 429The opposite behavior is always available if prefixed with C-c.
ccc3ce39 430Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
431 :type '(choice (const null) boolean)
432 :group 'cperl-affected-by-hairy)
433
434(defcustom cperl-clobber-lisp-bindings nil
435 "*Not-nil (and non-null) means not overwrite C-h f.
436The function is available on \\[cperl-info-on-command], \\[cperl-get-help].
437Can be overwritten by `cperl-hairy' if nil."
438 :type '(choice (const null) boolean)
439 :group 'cperl-affected-by-hairy)
f83d2997 440
ccc3ce39 441(defcustom cperl-lazy-help-time nil
db133cb6
RS
442 "*Not-nil (and non-null) means to show lazy help after given idle time.
443Can be overwritten by `cperl-hairy' to be 5 sec if nil."
300f7bb3 444 :type '(choice (const null) (const nil) integer)
db133cb6 445 :group 'cperl-affected-by-hairy)
f83d2997 446
ccc3ce39 447(defcustom cperl-pod-face 'font-lock-comment-face
83261a2f 448 "*Face for POD highlighting."
ccc3ce39 449 :type 'face
db133cb6 450 :group 'cperl-faces)
f83d2997 451
ccc3ce39 452(defcustom cperl-pod-head-face 'font-lock-variable-name-face
83261a2f 453 "*Face for POD highlighting.
ccc3ce39
SE
454Font for POD headers."
455 :type 'face
db133cb6 456 :group 'cperl-faces)
f83d2997 457
ccc3ce39 458(defcustom cperl-here-face 'font-lock-string-face
80585273 459 "*Face for here-docs highlighting."
ccc3ce39 460 :type 'face
db133cb6 461 :group 'cperl-faces)
f83d2997 462
4ab89e7b 463;;; Some double-evaluation happened with font-locks... Needed with 21.2...
6546555e 464(defvar cperl-singly-quote-face (featurep 'xemacs))
4ab89e7b 465
224ca9c9
CY
466(defcustom cperl-invalid-face 'underline
467 "*Face for highlighting trailing whitespace."
80585273 468 :type 'face
ac6857fb 469 :version "21.1"
5bd52f0e
RS
470 :group 'cperl-faces)
471
ccc3ce39 472(defcustom cperl-pod-here-fontify '(featurep 'font-lock)
83261a2f 473 "*Not-nil after evaluation means to highlight POD and here-docs sections."
ccc3ce39 474 :type 'boolean
db133cb6 475 :group 'cperl-faces)
f83d2997 476
5bd52f0e
RS
477(defcustom cperl-fontify-m-as-s t
478 "*Not-nil means highlight 1arg regular expressions operators same as 2arg."
479 :type 'boolean
480 :group 'cperl-faces)
481
6c389151
SM
482(defcustom cperl-highlight-variables-indiscriminately nil
483 "*Non-nil means perform additional highlighting on variables.
484Currently only changes how scalar variables are highlighted.
485Note that that variable is only read at initialization time for
486the variable `cperl-font-lock-keywords-2', so changing it after you've
f94a632a 487entered CPerl mode the first time will have no effect."
6c389151
SM
488 :type 'boolean
489 :group 'cperl)
490
ccc3ce39 491(defcustom cperl-pod-here-scan t
83261a2f 492 "*Not-nil means look for POD and here-docs sections during startup.
ccc3ce39
SE
493You can always make lookup from menu or using \\[cperl-find-pods-heres]."
494 :type 'boolean
db133cb6 495 :group 'cperl-speed)
f83d2997 496
6c389151
SM
497(defcustom cperl-regexp-scan t
498 "*Not-nil means make marking of regular expression more thorough.
4ab89e7b
SM
499Effective only with `cperl-pod-here-scan'."
500 :type 'boolean
501 :group 'cperl-speed)
502
503(defcustom cperl-hook-after-change t
504 "*Not-nil means install hook to know which regions of buffer are changed.
505May significantly speed up delayed fontification. Changes take effect
506after reload."
6c389151
SM
507 :type 'boolean
508 :group 'cperl-speed)
509
ccc3ce39 510(defcustom cperl-imenu-addback nil
f83d2997 511 "*Not-nil means add backreferences to generated `imenu's.
db133cb6 512May require patched `imenu' and `imenu-go'. Obsolete."
ccc3ce39 513 :type 'boolean
db133cb6 514 :group 'cperl-help-system)
f83d2997 515
ccc3ce39
SE
516(defcustom cperl-max-help-size 66
517 "*Non-nil means shrink-wrapping of info-buffer allowed up to these percents."
518 :type '(choice integer (const nil))
db133cb6 519 :group 'cperl-help-system)
f83d2997 520
ccc3ce39
SE
521(defcustom cperl-shrink-wrap-info-frame t
522 "*Non-nil means shrink-wrapping of info-buffer-frame allowed."
523 :type 'boolean
db133cb6 524 :group 'cperl-help-system)
f83d2997 525
ccc3ce39 526(defcustom cperl-info-page "perl"
f83d2997 527 "*Name of the info page containing perl docs.
ccc3ce39
SE
528Older version of this page was called `perl5', newer `perl'."
529 :type 'string
db133cb6 530 :group 'cperl-help-system)
f83d2997 531
5c8b7eaf 532(defcustom cperl-use-syntax-table-text-property
f83d2997 533 (boundp 'parse-sexp-lookup-properties)
ccc3ce39
SE
534 "*Non-nil means CPerl sets up and uses `syntax-table' text property."
535 :type 'boolean
db133cb6 536 :group 'cperl-speed)
f83d2997 537
5c8b7eaf 538(defcustom cperl-use-syntax-table-text-property-for-tags
f83d2997 539 cperl-use-syntax-table-text-property
ccc3ce39
SE
540 "*Non-nil means: set up and use `syntax-table' text property generating TAGS."
541 :type 'boolean
db133cb6 542 :group 'cperl-speed)
ccc3ce39
SE
543
544(defcustom cperl-scan-files-regexp "\\.\\([pP][Llm]\\|xs\\)$"
545 "*Regexp to match files to scan when generating TAGS."
546 :type 'regexp
547 :group 'cperl)
548
8937f01b
RS
549(defcustom cperl-noscan-files-regexp
550 "/\\(\\.\\.?\\|SCCS\\|RCS\\|CVS\\|blib\\)$"
ccc3ce39
SE
551 "*Regexp to match files/dirs to skip when generating TAGS."
552 :type 'regexp
553 :group 'cperl)
554
555(defcustom cperl-regexp-indent-step nil
556 "*Indentation used when beautifying regexps.
029cb4d5 557If nil, the value of `cperl-indent-level' will be used."
ccc3ce39 558 :type '(choice integer (const nil))
db133cb6 559 :group 'cperl-indentation-details)
ccc3ce39
SE
560
561(defcustom cperl-indent-left-aligned-comments t
562 "*Non-nil means that the comment starting in leftmost column should indent."
563 :type 'boolean
db133cb6 564 :group 'cperl-indentation-details)
ccc3ce39 565
8f222248 566(defcustom cperl-under-as-char nil
ccc3ce39
SE
567 "*Non-nil means that the _ (underline) should be treated as word char."
568 :type 'boolean
569 :group 'cperl)
f83d2997 570
db133cb6
RS
571(defcustom cperl-extra-perl-args ""
572 "*Extra arguments to use when starting Perl.
573Currently used with `cperl-check-syntax' only."
574 :type 'string
575 :group 'cperl)
576
577(defcustom cperl-message-electric-keyword t
578 "*Non-nil means that the `cperl-electric-keyword' prints a help message."
579 :type 'boolean
580 :group 'cperl-help-system)
581
582(defcustom cperl-indent-region-fix-constructs 1
583 "*Amount of space to insert between `}' and `else' or `elsif'
584in `cperl-indent-region'. Set to nil to leave as is. Values other
585than 1 and nil will probably not work."
586 :type '(choice (const nil) (const 1))
587 :group 'cperl-indentation-details)
588
589(defcustom cperl-break-one-line-blocks-when-indent t
590 "*Non-nil means that one-line if/unless/while/until/for/foreach BLOCKs
2022c546 591need to be reformatted into multiline ones when indenting a region."
db133cb6
RS
592 :type 'boolean
593 :group 'cperl-indentation-details)
594
595(defcustom cperl-fix-hanging-brace-when-indent t
596 "*Non-nil means that BLOCK-end `}' may be put on a separate line
5c8b7eaf 597when indenting a region.
db133cb6
RS
598Braces followed by else/elsif/while/until are excepted."
599 :type 'boolean
600 :group 'cperl-indentation-details)
601
602(defcustom cperl-merge-trailing-else t
5c8b7eaf 603 "*Non-nil means that BLOCK-end `}' followed by else/elsif/continue
db133cb6
RS
604may be merged to be on the same line when indenting a region."
605 :type 'boolean
606 :group 'cperl-indentation-details)
607
6c389151
SM
608(defcustom cperl-indent-parens-as-block nil
609 "*Non-nil means that non-block ()-, {}- and []-groups are indented as blocks,
610but for trailing \",\" inside the group, which won't increase indentation.
611One should tune up `cperl-close-paren-offset' as well."
612 :type 'boolean
613 :group 'cperl-indentation-details)
614
a1506d29 615(defcustom cperl-syntaxify-by-font-lock
83261a2f 616 (and cperl-can-font-lock
5bd52f0e 617 (boundp 'parse-sexp-lookup-properties))
6c389151 618 "*Non-nil means that CPerl uses `font-lock's routines for syntaxification."
5bd52f0e
RS
619 :type '(choice (const message) boolean)
620 :group 'cperl-speed)
621
622(defcustom cperl-syntaxify-unwind
623 t
f94a632a 624 "*Non-nil means that CPerl unwinds to a start of a long construction
5bd52f0e 625when syntaxifying a chunk of buffer."
db133cb6
RS
626 :type 'boolean
627 :group 'cperl-speed)
628
4ab89e7b
SM
629(defcustom cperl-syntaxify-for-menu
630 t
631 "*Non-nil means that CPerl syntaxifies up to the point before showing menu.
632This way enabling/disabling of menu items is more correct."
633 :type 'boolean
634 :group 'cperl-speed)
635
5bd52f0e
RS
636(defcustom cperl-ps-print-face-properties
637 '((font-lock-keyword-face nil nil bold shadow)
638 (font-lock-variable-name-face nil nil bold)
639 (font-lock-function-name-face nil nil bold italic box)
640 (font-lock-constant-face nil "LightGray" bold)
4ab89e7b
SM
641 (cperl-array-face nil "LightGray" bold underline)
642 (cperl-hash-face nil "LightGray" bold italic underline)
5bd52f0e
RS
643 (font-lock-comment-face nil "LightGray" italic)
644 (font-lock-string-face nil nil italic underline)
4ab89e7b 645 (cperl-nonoverridable-face nil nil italic underline)
5bd52f0e 646 (font-lock-type-face nil nil underline)
4ab89e7b 647 (font-lock-warning-face nil "LightGray" bold italic box)
5bd52f0e
RS
648 (underline nil "LightGray" strikeout))
649 "List given as an argument to `ps-extend-face-list' in `cperl-ps-print'."
5c8b7eaf 650 :type '(repeat (cons symbol
5bd52f0e
RS
651 (cons (choice (const nil) string)
652 (cons (choice (const nil) string)
653 (repeat symbol)))))
654 :group 'cperl-faces)
655
5cc679ab
JB
656(defvar cperl-dark-background
657 (cperl-choose-color "navy" "os2blue" "darkgreen"))
658(defvar cperl-dark-foreground
659 (cperl-choose-color "orchid1" "orange"))
660
4ab89e7b 661(defface cperl-nonoverridable-face
5cc679ab
JB
662 `((((class grayscale) (background light))
663 (:background "Gray90" :slant italic :underline t))
664 (((class grayscale) (background dark))
665 (:foreground "Gray80" :slant italic :underline t :weight bold))
666 (((class color) (background light))
667 (:foreground "chartreuse3"))
668 (((class color) (background dark))
669 (:foreground ,cperl-dark-foreground))
670 (t (:weight bold :underline t)))
c73fce9a 671 "Font Lock mode face used non-overridable keywords and modifiers of regexps."
5cc679ab
JB
672 :group 'cperl-faces)
673
4ab89e7b 674(defface cperl-array-face
5cc679ab
JB
675 `((((class grayscale) (background light))
676 (:background "Gray90" :weight bold))
677 (((class grayscale) (background dark))
678 (:foreground "Gray80" :weight bold))
679 (((class color) (background light))
680 (:foreground "Blue" :background "lightyellow2" :weight bold))
681 (((class color) (background dark))
682 (:foreground "yellow" :background ,cperl-dark-background :weight bold))
683 (t (:weight bold)))
684 "Font Lock mode face used to highlight array names."
685 :group 'cperl-faces)
686
4ab89e7b 687(defface cperl-hash-face
5cc679ab
JB
688 `((((class grayscale) (background light))
689 (:background "Gray90" :weight bold :slant italic))
690 (((class grayscale) (background dark))
691 (:foreground "Gray80" :weight bold :slant italic))
692 (((class color) (background light))
693 (:foreground "Red" :background "lightyellow2" :weight bold :slant italic))
694 (((class color) (background dark))
695 (:foreground "Red" :background ,cperl-dark-background :weight bold :slant italic))
696 (t (:weight bold :slant italic)))
697 "Font Lock mode face used to highlight hash names."
698 :group 'cperl-faces)
5bd52f0e 699
f83d2997
KH
700\f
701
702;;; Short extra-docs.
703
704(defvar cperl-tips 'please-ignore-this-line
83261a2f 705 "Get maybe newer version of this package from
4ab89e7b 706 http://ilyaz.org/software/emacs
db133cb6
RS
707Subdirectory `cperl-mode' may contain yet newer development releases and/or
708patches to related files.
f83d2997 709
5bd52f0e
RS
710For best results apply to an older Emacs the patches from
711 ftp://ftp.math.ohio-state.edu/pub/users/ilya/cperl-mode/patches
83261a2f 712\(this upgrades syntax-parsing abilities of Emacsen v19.34 and
8e3acc66 713v20.2 up to the level of Emacs v20.3 - a must for a good Perl
83261a2f 714mode.) As of beginning of 2003, XEmacs may provide a similar ability.
5bd52f0e 715
f83d2997
KH
716Get support packages choose-color.el (or font-lock-extra.el before
71719.30), imenu-go.el from the same place. \(Look for other files there
718too... ;-). Get a patch for imenu.el in 19.29. Note that for 19.30 and
5c8b7eaf 719later you should use choose-color.el *instead* of font-lock-extra.el
f83d2997
KH
720\(and you will not get smart highlighting in C :-().
721
722Note that to enable Compile choices in the menu you need to install
723mode-compile.el.
724
5efe6a56
SM
725If your Emacs does not default to `cperl-mode' on Perl files, and you
726want it to: put the following into your .emacs file:
727
728 (defalias 'perl-mode 'cperl-mode)
729
a1506d29 730Get perl5-info from
4ab89e7b
SM
731 $CPAN/doc/manual/info/perl5-old/perl5-info.tar.gz
732Also, one can generate a newer documentation running `pod2texi' converter
733 $CPAN/doc/manual/info/perl5/pod2texi-0.1.tar.gz
f83d2997
KH
734
735If you use imenu-go, run imenu on perl5-info buffer (you can do it
5bd52f0e
RS
736from Perl menu). If many files are related, generate TAGS files from
737Tools/Tags submenu in Perl menu.
f83d2997
KH
738
739If some class structure is too complicated, use Tools/Hierarchy-view
029cb4d5 740from Perl menu, or hierarchic view of imenu. The second one uses the
f83d2997 741current buffer only, the first one requires generation of TAGS from
5bd52f0e
RS
742Perl/Tools/Tags menu beforehand.
743
744Run Perl/Tools/Insert-spaces-if-needed to fix your lazy typing.
745
746Switch auto-help on/off with Perl/Tools/Auto-help.
747
748Though with contemporary Emaxen CPerl mode should maintain the correct
749parsing of Perl even when editing, sometimes it may be lost. Fix this by
750
029cb4d5 751 \\[normal-mode]
f83d2997 752
5bd52f0e 753In cases of more severe confusion sometimes it is helpful to do
f83d2997 754
029cb4d5
SM
755 \\[load-library] cperl-mode RET
756 \\[normal-mode]
f83d2997 757
5bd52f0e
RS
758Before reporting (non-)problems look in the problem section of online
759micro-docs on what I know about CPerl problems.")
f83d2997
KH
760
761(defvar cperl-problems 'please-ignore-this-line
f94a632a
RS
762 "Description of problems in CPerl mode.
763Some faces will not be shown on some versions of Emacs unless you
bab27c0c 764install choose-color.el, available from
4ab89e7b 765 http://ilyaz.org/software/emacs
bab27c0c 766
6c389151 767`fill-paragraph' on a comment may leave the point behind the
4ab89e7b
SM
768paragraph. It also triggers a bug in some versions of Emacs (CPerl tries
769to detect it and bulk out).
770
771See documentation of a variable `cperl-problems-old-emaxen' for the
772problems which disappear if you upgrade Emacs to a reasonably new
773version (20.3 for Emacs, and those of 2004 for XEmacs).")
774
775(defvar cperl-problems-old-emaxen 'please-ignore-this-line
776 "Description of problems in CPerl mode specific for older Emacs versions.
6c389151 777
8e3acc66 778Emacs had a _very_ restricted syntax parsing engine until version
5bd52f0e 77920.1. Most problems below are corrected starting from this version of
8e3acc66 780Emacs, and all of them should be fixed in version 20.3. (Or apply
83261a2f
SM
781patches to Emacs 19.33/34 - see tips.) XEmacs was very backward in
782this respect (until 2003).
5bd52f0e 783
6c389151
SM
784Note that even with newer Emacsen in some very rare cases the details
785of interaction of `font-lock' and syntaxification may be not cleaned
786up yet. You may get slightly different colors basing on the order of
787fontification and syntaxification. Say, the initial faces is correct,
788but editing the buffer breaks this.
f83d2997 789
db133cb6
RS
790Even with older Emacsen CPerl mode tries to corrects some Emacs
791misunderstandings, however, for efficiency reasons the degree of
792correction is different for different operations. The partially
793corrected problems are: POD sections, here-documents, regexps. The
794operations are: highlighting, indentation, electric keywords, electric
795braces.
f83d2997
KH
796
797This may be confusing, since the regexp s#//#/#\; may be highlighted
798as a comment, but it will be recognized as a regexp by the indentation
83261a2f 799code. Or the opposite case, when a POD section is highlighted, but
f83d2997
KH
800may break the indentation of the following code (though indentation
801should work if the balance of delimiters is not broken by POD).
802
803The main trick (to make $ a \"backslash\") makes constructions like
804${aaa} look like unbalanced braces. The only trick I can think of is
2e8b9c7d 805to insert it as $ {aaa} (valid in perl5, not in perl4).
f83d2997
KH
806
807Similar problems arise in regexps, when /(\\s|$)/ should be rewritten
db133cb6
RS
808as /($|\\s)/. Note that such a transposition is not always possible.
809
5bd52f0e 810The solution is to upgrade your Emacs or patch an older one. Note
8e3acc66 811that Emacs 20.2 has some bugs related to `syntax-table' text
5bd52f0e
RS
812properties. Patches are available on the main CPerl download site,
813and on CPAN.
db133cb6
RS
814
815If these bugs cannot be fixed on your machine (say, you have an inferior
816environment and cannot recompile), you may still disable all the fancy stuff
83261a2f 817via `cperl-use-syntax-table-text-property'.")
f83d2997 818
f83d2997 819(defvar cperl-praise 'please-ignore-this-line
8e3acc66 820 "Advantages of CPerl mode.
f83d2997
KH
821
8220) It uses the newest `syntax-table' property ;-);
823
8241) It does 99% of Perl syntax correct (as opposed to 80-90% in Perl
5c8b7eaf 825mode - but the latter number may have improved too in last years) even
5bd52f0e
RS
826with old Emaxen which do not support `syntax-table' property.
827
828When using `syntax-table' property for syntax assist hints, it should
829handle 99.995% of lines correct - or somesuch. It automatically
830updates syntax assist hints when you edit your script.
f83d2997 831
bab27c0c 8322) It is generally believed to be \"the most user-friendly Emacs
f83d2997
KH
833package\" whatever it may mean (I doubt that the people who say similar
834things tried _all_ the rest of Emacs ;-), but this was not a lonely
835voice);
836
8373) Everything is customizable, one-by-one or in a big sweep;
838
8394) It has many easily-accessable \"tools\":
840 a) Can run program, check syntax, start debugger;
841 b) Can lineup vertically \"middles\" of rows, like `=' in
842 a = b;
843 cc = d;
844 c) Can insert spaces where this impoves readability (in one
845 interactive sweep over the buffer);
846 d) Has support for imenu, including:
847 1) Separate unordered list of \"interesting places\";
848 2) Separate TOC of POD sections;
849 3) Separate list of packages;
850 4) Hierarchical view of methods in (sub)packages;
851 5) and functions (by the full name - with package);
852 e) Has an interface to INFO docs for Perl; The interface is
853 very flexible, including shrink-wrapping of
854 documentation buffer/frame;
855 f) Has a builtin list of one-line explanations for perl constructs.
856 g) Can show these explanations if you stay long enough at the
857 corresponding place (or on demand);
858 h) Has an enhanced fontification (using 3 or 4 additional faces
859 comparing to font-lock - basically, different
860 namespaces in Perl have different colors);
861 i) Can construct TAGS basing on its knowledge of Perl syntax,
862 the standard menu has 6 different way to generate
db133cb6 863 TAGS (if \"by directory\", .xs files - with C-language
f83d2997
KH
864 bindings - are included in the scan);
865 j) Can build a hierarchical view of classes (via imenu) basing
866 on generated TAGS file;
867 k) Has electric parentheses, electric newlines, uses Abbrev
868 for electric logical constructs
869 while () {}
870 with different styles of expansion (context sensitive
871 to be not so bothering). Electric parentheses behave
872 \"as they should\" in a presence of a visible region.
873 l) Changes msb.el \"on the fly\" to insert a group \"Perl files\";
db133cb6
RS
874 m) Can convert from
875 if (A) { B }
876 to
877 B if A;
f83d2997 878
5bd52f0e 879 n) Highlights (by user-choice) either 3-delimiters constructs
6c389151
SM
880 (such as tr/a/b/), or regular expressions and `y/tr';
881 o) Highlights trailing whitespace;
882 p) Is able to manipulate Perl Regular Expressions to ease
883 conversion to a more readable form.
4ab89e7b
SM
884 q) Can ispell POD sections and HERE-DOCs.
885 r) Understands comments and character classes inside regular
886 expressions; can find matching () and [] in a regular expression.
887 s) Allows indentation of //x-style regular expressions;
888 t) Highlights different symbols in regular expressions according
889 to their function; much less problems with backslashitis;
890 u) Allows to find regular expressions which contain interpolated parts.
5bd52f0e 891
f83d2997
KH
8925) The indentation engine was very smart, but most of tricks may be
893not needed anymore with the support for `syntax-table' property. Has
894progress indicator for indentation (with `imenu' loaded).
895
5c8b7eaf 8966) Indent-region improves inline-comments as well; also corrects
db133cb6 897whitespace *inside* the conditional/loop constructs.
f83d2997
KH
898
8997) Fill-paragraph correctly handles multi-line comments;
db133cb6
RS
900
9018) Can switch to different indentation styles by one command, and restore
902the settings present before the switch.
903
5c8b7eaf 9049) When doing indentation of control constructs, may correct
db133cb6 905line-breaks/spacing between elements of the construct.
029cb4d5
SM
906
90710) Uses a linear-time algorith for indentation of regions (on Emaxen with
4ab89e7b
SM
908capable syntax engines).
909
91011) Syntax-highlight, indentation, sexp-recognition inside regular expressions.
911")
db133cb6
RS
912
913(defvar cperl-speed 'please-ignore-this-line
914 "This is an incomplete compendium of what is available in other parts
915of CPerl documentation. (Please inform me if I skept anything.)
916
917There is a perception that CPerl is slower than alternatives. This part
918of documentation is designed to overcome this misconception.
919
920*By default* CPerl tries to enable the most comfortable settings.
921From most points of view, correctly working package is infinitely more
922comfortable than a non-correctly working one, thus by default CPerl
923prefers correctness over speed. Below is the guide how to change
924settings if your preferences are different.
925
926A) Speed of loading the file. When loading file, CPerl may perform a
927scan which indicates places which cannot be parsed by primitive Emacs
928syntax-parsing routines, and marks them up so that either
929
930 A1) CPerl may work around these deficiencies (for big chunks, mostly
931 PODs and HERE-documents), or
932 A2) On capable Emaxen CPerl will use improved syntax-handlings
933 which reads mark-up hints directly.
934
935 The scan in case A2 is much more comprehensive, thus may be slower.
936
937 User can disable syntax-engine-helping scan of A2 by setting
938 `cperl-use-syntax-table-text-property'
939 variable to nil (if it is set to t).
940
941 One can disable the scan altogether (both A1 and A2) by setting
942 `cperl-pod-here-scan'
943 to nil.
944
5c8b7eaf 945B) Speed of editing operations.
db133cb6
RS
946
947 One can add a (minor) speedup to editing operations by setting
948 `cperl-use-syntax-table-text-property'
949 variable to nil (if it is set to t). This will disable
950 syntax-engine-helping scan, thus will make many more Perl
951 constructs be wrongly recognized by CPerl, thus may lead to
952 wrongly matched parentheses, wrong indentation, etc.
5bd52f0e
RS
953
954 One can unset `cperl-syntaxify-unwind'. This might speed up editing
83261a2f 955 of, say, long POD sections.")
f83d2997 956
5bd52f0e
RS
957(defvar cperl-tips-faces 'please-ignore-this-line
958 "CPerl mode uses following faces for highlighting:
959
4ab89e7b
SM
960 `cperl-array-face' Array names
961 `cperl-hash-face' Hash names
8661c643 962 `font-lock-comment-face' Comments, PODs and whatever is considered
5bd52f0e 963 syntaxically to be not code
8661c643 964 `font-lock-constant-face' HERE-doc delimiters, labels, delimiters of
5bd52f0e 965 2-arg operators s/y/tr/ or of RExen,
4ab89e7b
SM
966 `font-lock-warning-face' Special-cased m// and s//foo/,
967 `font-lock-function-name-face' _ as a target of a file tests, file tests,
5bd52f0e
RS
968 subroutine names at the moment of definition
969 (except those conflicting with Perl operators),
970 package names (when recognized), format names
8661c643 971 `font-lock-keyword-face' Control flow switch constructs, declarators
4ab89e7b 972 `cperl-nonoverridable-face' Non-overridable keywords, modifiers of RExen
8661c643 973 `font-lock-string-face' Strings, qw() constructs, RExen, POD sections,
5bd52f0e
RS
974 literal parts and the terminator of formats
975 and whatever is syntaxically considered
976 as string literals
8661c643
DL
977 `font-lock-type-face' Overridable keywords
978 `font-lock-variable-name-face' Variable declarations, indirect array and
5bd52f0e 979 hash names, POD headers/item names
e4c067b5 980 `cperl-invalid' Trailing whitespace
5bd52f0e
RS
981
982Note that in several situations the highlighting tries to inform about
983possible confusion, such as different colors for function names in
984declarations depending on what they (do not) override, or special cases
985m// and s/// which do not do what one would expect them to do.
986
5c8b7eaf 987Help with best setup of these faces for printout requested (for each of
5bd52f0e
RS
988the faces: please specify bold, italic, underline, shadow and box.)
989
4ab89e7b
SM
990In regular expressions (except character classes):
991 `font-lock-string-face' \"Normal\" stuff and non-0-length constructs
992 `font-lock-constant-face': Delimiters
993 `font-lock-warning-face' Special-cased m// and s//foo/,
994 Mismatched closing delimiters, parens
995 we couldn't match, misplaced quantifiers,
996 unrecognized escape sequences
997 `cperl-nonoverridable-face' Modifiers, as gism in m/REx/gism
998 `font-lock-type-face' POSIX classes inside charclasses,
999 escape sequences with arguments (\x \23 \p \N)
1000 and others match-a-char escape sequences
1001 `font-lock-keyword-face' Capturing parens, and |
1002 `font-lock-function-name-face' Special symbols: $ ^ . [ ] [^ ] (?{ }) (??{ })
1003 `font-lock-builtin-face' \"Remaining\" 0-length constructs, executable
1004 parts of a REx, not-capturing parens
1005 `font-lock-variable-name-face' Interpolated constructs, embedded code
1006 `font-lock-comment-face' Embedded comments
1007
1008")
5bd52f0e 1009
f83d2997
KH
1010\f
1011
1012;;; Portability stuff:
1013
1014(defmacro cperl-define-key (emacs-key definition &optional xemacs-key)
b787fc05
GM
1015 `(define-key cperl-mode-map
1016 ,(if xemacs-key
6546555e 1017 `(if (featurep 'xemacs) ,xemacs-key ,emacs-key)
b787fc05
GM
1018 emacs-key)
1019 ,definition))
f83d2997
KH
1020
1021(defvar cperl-del-back-ch
1022 (car (append (where-is-internal 'delete-backward-char)
1023 (where-is-internal 'backward-delete-char-untabify)))
029cb4d5 1024 "Character generated by key bound to `delete-backward-char'.")
f83d2997 1025
5c8b7eaf 1026(and (vectorp cperl-del-back-ch) (= (length cperl-del-back-ch) 1)
f83d2997
KH
1027 (setq cperl-del-back-ch (aref cperl-del-back-ch 0)))
1028
db133cb6 1029(defun cperl-mark-active () (mark)) ; Avoid undefined warning
6546555e 1030(if (featurep 'xemacs)
f83d2997
KH
1031 (progn
1032 ;; "Active regions" are on: use region only if active
1033 ;; "Active regions" are off: use region unconditionally
1034 (defun cperl-use-region-p ()
db133cb6 1035 (if zmacs-regions (mark) t)))
f83d2997
KH
1036 (defun cperl-use-region-p ()
1037 (if transient-mark-mode mark-active t))
1038 (defun cperl-mark-active () mark-active))
1039
1040(defsubst cperl-enable-font-lock ()
83261a2f 1041 cperl-can-font-lock)
f83d2997 1042
83261a2f 1043(defun cperl-putback-char (c) ; Emacs 19
db133cb6
RS
1044 (set 'unread-command-events (list c))) ; Avoid undefined warning
1045
6546555e 1046(if (featurep 'xemacs)
0ce7de92
RS
1047 (defun cperl-putback-char (c) ; XEmacs >= 19.12
1048 (setq unread-command-events (list (eval '(character-to-event c))))))
f83d2997
KH
1049
1050(or (fboundp 'uncomment-region)
1051 (defun uncomment-region (beg end)
1052 (interactive "r")
1053 (comment-region beg end -1)))
1054
1055(defvar cperl-do-not-fontify
1056 (if (string< emacs-version "19.30")
1057 'fontified
1058 'lazy-lock)
1059 "Text property which inhibits refontification.")
1060
5bd52f0e
RS
1061(defsubst cperl-put-do-not-fontify (from to &optional post)
1062 ;; If POST, do not do it with postponed fontification
1063 (if (and post cperl-syntaxify-by-font-lock)
1064 nil
f83d2997 1065 (put-text-property (max (point-min) (1- from))
5bd52f0e 1066 to cperl-do-not-fontify t)))
f83d2997 1067
ccc3ce39 1068(defcustom cperl-mode-hook nil
f94a632a 1069 "Hook run by CPerl mode."
ccc3ce39
SE
1070 :type 'hook
1071 :group 'cperl)
f83d2997 1072
db133cb6
RS
1073(defvar cperl-syntax-state nil)
1074(defvar cperl-syntax-done-to nil)
5bd52f0e 1075(defvar cperl-emacs-can-parse (> (length (save-excursion
ce22dd53 1076 (parse-partial-sexp (point) (point)))) 9))
db133cb6
RS
1077\f
1078;; Make customization possible "in reverse"
1079(defsubst cperl-val (symbol &optional default hairy)
1080 (cond
1081 ((eq (symbol-value symbol) 'null) default)
1082 (cperl-hairy (or hairy t))
1083 (t (symbol-value symbol))))
f83d2997 1084\f
4ab89e7b
SM
1085
1086(defun cperl-make-indent (column &optional minimum keep)
1087 "Makes indent of the current line the requested amount.
1088Unless KEEP, removes the old indentation. Works around a bug in ancient
1089versions of Emacs."
1090 (let ((prop (get-text-property (point) 'syntax-type)))
1091 (or keep
1092 (delete-horizontal-space))
1093 (indent-to column minimum)
1094 ;; In old versions (e.g., 19.33) `indent-to' would not inherit properties
1095 (and prop
1096 (> (current-column) 0)
1097 (save-excursion
1098 (beginning-of-line)
1099 (or (get-text-property (point) 'syntax-type)
1100 (and (looking-at "\\=[ \t]")
1101 (put-text-property (point) (match-end 0)
1102 'syntax-type prop)))))))
1103
f83d2997
KH
1104;;; Probably it is too late to set these guys already, but it can help later:
1105
5bd52f0e 1106;;;(and cperl-clobber-mode-lists
f83d2997
KH
1107;;;(setq auto-mode-alist
1108;;; (append '(("\\.\\([pP][Llm]\\|al\\)$" . perl-mode)) auto-mode-alist ))
1109;;;(and (boundp 'interpreter-mode-alist)
1110;;; (setq interpreter-mode-alist (append interpreter-mode-alist
5bd52f0e 1111;;; '(("miniperl" . perl-mode))))))
80585273 1112(eval-when-compile
dba01120
GM
1113 (mapc (lambda (p)
1114 (condition-case nil
1115 (require p)
1116 (error nil)))
1117 '(imenu easymenu etags timer man info))
80585273
DL
1118 (if (fboundp 'ps-extend-face-list)
1119 (defmacro cperl-ps-extend-face-list (arg)
1120 `(ps-extend-face-list ,arg))
1121 (defmacro cperl-ps-extend-face-list (arg)
e8af40ee 1122 `(error "This version of Emacs has no `ps-extend-face-list'")))
80585273
DL
1123 ;; Calling `cperl-enable-font-lock' below doesn't compile on XEmacs,
1124 ;; macros instead of defsubsts don't work on Emacs, so we do the
1125 ;; expansion manually. Any other suggestions?
1126 (require 'cl))
f83d2997
KH
1127
1128(defvar cperl-mode-abbrev-table nil
f94a632a 1129 "Abbrev table in use in CPerl mode buffers.")
f83d2997
KH
1130
1131(add-hook 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-")))
1132
1133(defvar cperl-mode-map () "Keymap used in CPerl mode.")
1134
1135(if cperl-mode-map nil
1136 (setq cperl-mode-map (make-sparse-keymap))
1137 (cperl-define-key "{" 'cperl-electric-lbrace)
1138 (cperl-define-key "[" 'cperl-electric-paren)
1139 (cperl-define-key "(" 'cperl-electric-paren)
1140 (cperl-define-key "<" 'cperl-electric-paren)
1141 (cperl-define-key "}" 'cperl-electric-brace)
1142 (cperl-define-key "]" 'cperl-electric-rparen)
1143 (cperl-define-key ")" 'cperl-electric-rparen)
1144 (cperl-define-key ";" 'cperl-electric-semi)
1145 (cperl-define-key ":" 'cperl-electric-terminator)
1146 (cperl-define-key "\C-j" 'newline-and-indent)
1147 (cperl-define-key "\C-c\C-j" 'cperl-linefeed)
db133cb6 1148 (cperl-define-key "\C-c\C-t" 'cperl-invert-if-unless)
f83d2997
KH
1149 (cperl-define-key "\C-c\C-a" 'cperl-toggle-auto-newline)
1150 (cperl-define-key "\C-c\C-k" 'cperl-toggle-abbrev)
db133cb6
RS
1151 (cperl-define-key "\C-c\C-w" 'cperl-toggle-construct-fix)
1152 (cperl-define-key "\C-c\C-f" 'auto-fill-mode)
f83d2997 1153 (cperl-define-key "\C-c\C-e" 'cperl-toggle-electric)
4ab89e7b
SM
1154 (cperl-define-key "\C-c\C-b" 'cperl-find-bad-style)
1155 (cperl-define-key "\C-c\C-p" 'cperl-pod-spell)
1156 (cperl-define-key "\C-c\C-d" 'cperl-here-doc-spell)
1157 (cperl-define-key "\C-c\C-n" 'cperl-narrow-to-here-doc)
1158 (cperl-define-key "\C-c\C-v" 'cperl-next-interpolated-REx)
1159 (cperl-define-key "\C-c\C-x" 'cperl-next-interpolated-REx-0)
1160 (cperl-define-key "\C-c\C-y" 'cperl-next-interpolated-REx-1)
db133cb6 1161 (cperl-define-key "\C-c\C-ha" 'cperl-toggle-autohelp)
4ab89e7b
SM
1162 (cperl-define-key "\C-c\C-hp" 'cperl-perldoc)
1163 (cperl-define-key "\C-c\C-hP" 'cperl-perldoc-at-point)
f83d2997
KH
1164 (cperl-define-key "\e\C-q" 'cperl-indent-exp) ; Usually not bound
1165 (cperl-define-key [?\C-\M-\|] 'cperl-lineup
1166 [(control meta |)])
1167 ;;(cperl-define-key "\M-q" 'cperl-fill-paragraph)
1168 ;;(cperl-define-key "\e;" 'cperl-indent-for-comment)
1169 (cperl-define-key "\177" 'cperl-electric-backspace)
1170 (cperl-define-key "\t" 'cperl-indent-command)
1171 ;; don't clobber the backspace binding:
db133cb6
RS
1172 (cperl-define-key "\C-c\C-hF" 'cperl-info-on-command
1173 [(control c) (control h) F])
db133cb6
RS
1174 (if (cperl-val 'cperl-clobber-lisp-bindings)
1175 (progn
1176 (cperl-define-key "\C-hf"
1177 ;;(concat (char-to-string help-char) "f") ; does not work
1178 'cperl-info-on-command
1179 [(control h) f])
1180 (cperl-define-key "\C-hv"
1181 ;;(concat (char-to-string help-char) "v") ; does not work
1182 'cperl-get-help
5bd52f0e
RS
1183 [(control h) v])
1184 (cperl-define-key "\C-c\C-hf"
1185 ;;(concat (char-to-string help-char) "f") ; does not work
1186 (key-binding "\C-hf")
1187 [(control c) (control h) f])
1188 (cperl-define-key "\C-c\C-hv"
1189 ;;(concat (char-to-string help-char) "v") ; does not work
1190 (key-binding "\C-hv")
1191 [(control c) (control h) v]))
1192 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-current-command
1193 [(control c) (control h) f])
1194 (cperl-define-key "\C-c\C-hv"
1195 ;;(concat (char-to-string help-char) "v") ; does not work
1196 'cperl-get-help
1197 [(control c) (control h) v]))
6546555e 1198 (if (and (featurep 'xemacs)
f83d2997
KH
1199 (<= emacs-minor-version 11) (<= emacs-major-version 19))
1200 (progn
1201 ;; substitute-key-definition is usefulness-deenhanced...
4ab89e7b 1202 ;;;;;(cperl-define-key "\M-q" 'cperl-fill-paragraph)
f83d2997
KH
1203 (cperl-define-key "\e;" 'cperl-indent-for-comment)
1204 (cperl-define-key "\e\C-\\" 'cperl-indent-region))
4ab89e7b
SM
1205 (or (boundp 'fill-paragraph-function)
1206 (substitute-key-definition
1207 'fill-paragraph 'cperl-fill-paragraph
1208 cperl-mode-map global-map))
f83d2997
KH
1209 (substitute-key-definition
1210 'indent-sexp 'cperl-indent-exp
1211 cperl-mode-map global-map)
f83d2997
KH
1212 (substitute-key-definition
1213 'indent-region 'cperl-indent-region
1214 cperl-mode-map global-map)
1215 (substitute-key-definition
1216 'indent-for-comment 'cperl-indent-for-comment
1217 cperl-mode-map global-map)))
1218
1219(defvar cperl-menu)
db133cb6
RS
1220(defvar cperl-lazy-installed)
1221(defvar cperl-old-style nil)
f83d2997
KH
1222(condition-case nil
1223 (progn
1224 (require 'easymenu)
83261a2f 1225 (easy-menu-define
4ab89e7b
SM
1226 cperl-menu cperl-mode-map "Menu for CPerl mode"
1227 '("Perl"
1228 ["Beginning of function" beginning-of-defun t]
1229 ["End of function" end-of-defun t]
1230 ["Mark function" mark-defun t]
1231 ["Indent expression" cperl-indent-exp t]
82eb0dae 1232 ["Fill paragraph/comment" fill-paragraph t]
4ab89e7b
SM
1233 "----"
1234 ["Line up a construction" cperl-lineup (cperl-use-region-p)]
1235 ["Invert if/unless/while etc" cperl-invert-if-unless t]
1236 ("Regexp"
1237 ["Beautify" cperl-beautify-regexp
1238 cperl-use-syntax-table-text-property]
1239 ["Beautify one level deep" (cperl-beautify-regexp 1)
1240 cperl-use-syntax-table-text-property]
1241 ["Beautify a group" cperl-beautify-level
1242 cperl-use-syntax-table-text-property]
1243 ["Beautify a group one level deep" (cperl-beautify-level 1)
1244 cperl-use-syntax-table-text-property]
1245 ["Contract a group" cperl-contract-level
1246 cperl-use-syntax-table-text-property]
1247 ["Contract groups" cperl-contract-levels
1248 cperl-use-syntax-table-text-property]
83261a2f 1249 "----"
cb5bf6ba 1250 ["Find next interpolated" cperl-next-interpolated-REx
4ab89e7b
SM
1251 (next-single-property-change (point-min) 'REx-interpolated)]
1252 ["Find next interpolated (no //o)"
1253 cperl-next-interpolated-REx-0
1254 (or (text-property-any (point-min) (point-max) 'REx-interpolated t)
1255 (text-property-any (point-min) (point-max) 'REx-interpolated 1))]
1256 ["Find next interpolated (neither //o nor whole-REx)"
1257 cperl-next-interpolated-REx-1
1258 (text-property-any (point-min) (point-max) 'REx-interpolated t)])
1259 ["Insert spaces if needed to fix style" cperl-find-bad-style t]
1260 ["Refresh \"hard\" constructions" cperl-find-pods-heres t]
1261 "----"
1262 ["Indent region" cperl-indent-region (cperl-use-region-p)]
1263 ["Comment region" cperl-comment-region (cperl-use-region-p)]
1264 ["Uncomment region" cperl-uncomment-region (cperl-use-region-p)]
1265 "----"
1266 ["Run" mode-compile (fboundp 'mode-compile)]
1267 ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
1268 (get-buffer "*compilation*"))]
1269 ["Next error" next-error (get-buffer "*compilation*")]
1270 ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
1271 "----"
1272 ["Debugger" cperl-db t]
1273 "----"
1274 ("Tools"
1275 ["Imenu" imenu (fboundp 'imenu)]
1276 ["Imenu on Perl Info" cperl-imenu-on-info (featurep 'imenu)]
83261a2f 1277 "----"
4ab89e7b
SM
1278 ["Ispell PODs" cperl-pod-spell
1279 ;; Better not to update syntaxification here:
1280 ;; debugging syntaxificatio can be broken by this???
1281 (or
1282 (get-text-property (point-min) 'in-pod)
1283 (< (progn
1284 (and cperl-syntaxify-for-menu
1285 (cperl-update-syntaxification (point-max) (point-max)))
1286 (next-single-property-change (point-min) 'in-pod nil (point-max)))
1287 (point-max)))]
1288 ["Ispell HERE-DOCs" cperl-here-doc-spell
1289 (< (progn
1290 (and cperl-syntaxify-for-menu
1291 (cperl-update-syntaxification (point-max) (point-max)))
1292 (next-single-property-change (point-min) 'here-doc-group nil (point-max)))
1293 (point-max))]
1294 ["Narrow to this HERE-DOC" cperl-narrow-to-here-doc
1295 (eq 'here-doc (progn
1296 (and cperl-syntaxify-for-menu
1297 (cperl-update-syntaxification (point) (point)))
1298 (get-text-property (point) 'syntax-type)))]
1299 ["Select this HERE-DOC or POD section"
1300 cperl-select-this-pod-or-here-doc
1301 (memq (progn
1302 (and cperl-syntaxify-for-menu
1303 (cperl-update-syntaxification (point) (point)))
1304 (get-text-property (point) 'syntax-type))
1305 '(here-doc pod))]
83261a2f 1306 "----"
4ab89e7b
SM
1307 ["CPerl pretty print (exprmntl)" cperl-ps-print
1308 (fboundp 'ps-extend-face-list)]
83261a2f 1309 "----"
4ab89e7b
SM
1310 ["Syntaxify region" cperl-find-pods-heres-region
1311 (cperl-use-region-p)]
1312 ["Profile syntaxification" cperl-time-fontification t]
1313 ["Debug errors in delayed fontification" cperl-emulate-lazy-lock t]
1314 ["Debug unwind for syntactic scan" cperl-toggle-set-debug-unwind t]
1315 ["Debug backtrace on syntactic scan (BEWARE!!!)"
1316 (cperl-toggle-set-debug-unwind nil t) t]
83261a2f 1317 "----"
4ab89e7b
SM
1318 ["Class Hierarchy from TAGS" cperl-tags-hier-init t]
1319 ;;["Update classes" (cperl-tags-hier-init t) tags-table-list]
1320 ("Tags"
f83d2997
KH
1321;;; ["Create tags for current file" cperl-etags t]
1322;;; ["Add tags for current file" (cperl-etags t) t]
1323;;; ["Create tags for Perl files in directory" (cperl-etags nil t) t]
1324;;; ["Add tags for Perl files in directory" (cperl-etags t t) t]
5c8b7eaf 1325;;; ["Create tags for Perl files in (sub)directories"
f83d2997
KH
1326;;; (cperl-etags nil 'recursive) t]
1327;;; ["Add tags for Perl files in (sub)directories"
5c8b7eaf 1328;;; (cperl-etags t 'recursive) t])
f83d2997 1329;;;; cperl-write-tags (&optional file erase recurse dir inbuffer)
f739b53b
SM
1330 ["Create tags for current file" (cperl-write-tags nil t) t]
1331 ["Add tags for current file" (cperl-write-tags) t]
1332 ["Create tags for Perl files in directory"
1333 (cperl-write-tags nil t nil t) t]
1334 ["Add tags for Perl files in directory"
1335 (cperl-write-tags nil nil nil t) t]
1336 ["Create tags for Perl files in (sub)directories"
1337 (cperl-write-tags nil t t t) t]
1338 ["Add tags for Perl files in (sub)directories"
1339 (cperl-write-tags nil nil t t) t]))
1340 ("Perl docs"
15ca5699 1341 ["Define word at point" imenu-go-find-at-position
f739b53b
SM
1342 (fboundp 'imenu-go-find-at-position)]
1343 ["Help on function" cperl-info-on-command t]
1344 ["Help on function at point" cperl-info-on-current-command t]
1345 ["Help on symbol at point" cperl-get-help t]
1346 ["Perldoc" cperl-perldoc t]
1347 ["Perldoc on word at point" cperl-perldoc-at-point t]
1348 ["View manpage of POD in this file" cperl-build-manpage t]
15ca5699 1349 ["Auto-help on" cperl-lazy-install
f739b53b
SM
1350 (and (fboundp 'run-with-idle-timer)
1351 (not cperl-lazy-installed))]
1352 ["Auto-help off" cperl-lazy-unstall
1353 (and (fboundp 'run-with-idle-timer)
1354 cperl-lazy-installed)])
1355 ("Toggle..."
1356 ["Auto newline" cperl-toggle-auto-newline t]
1357 ["Electric parens" cperl-toggle-electric t]
1358 ["Electric keywords" cperl-toggle-abbrev t]
1359 ["Fix whitespace on indent" cperl-toggle-construct-fix t]
1360 ["Auto-help on Perl constructs" cperl-toggle-autohelp t]
15ca5699 1361 ["Auto fill" auto-fill-mode t])
f739b53b
SM
1362 ("Indent styles..."
1363 ["CPerl" (cperl-set-style "CPerl") t]
1364 ["PerlStyle" (cperl-set-style "PerlStyle") t]
1365 ["GNU" (cperl-set-style "GNU") t]
1366 ["C++" (cperl-set-style "C++") t]
4ab89e7b 1367 ["K&R" (cperl-set-style "K&R") t]
f739b53b
SM
1368 ["BSD" (cperl-set-style "BSD") t]
1369 ["Whitesmith" (cperl-set-style "Whitesmith") t]
4ab89e7b 1370 ["Memorize Current" (cperl-set-style "Current") t]
f739b53b
SM
1371 ["Memorized" (cperl-set-style-back) cperl-old-style])
1372 ("Micro-docs"
1373 ["Tips" (describe-variable 'cperl-tips) t]
1374 ["Problems" (describe-variable 'cperl-problems) t]
1375 ["Speed" (describe-variable 'cperl-speed) t]
1376 ["Praise" (describe-variable 'cperl-praise) t]
1377 ["Faces" (describe-variable 'cperl-tips-faces) t]
1378 ["CPerl mode" (describe-function 'cperl-mode) t]
1379 ["CPerl version"
1380 (message "The version of master-file for this CPerl is %s-Emacs"
1381 cperl-version) t]))))
f83d2997
KH
1382 (error nil))
1383
1384(autoload 'c-macro-expand "cmacexp"
1385 "Display the result of expanding all C macros occurring in the region.
1386The expansion is entirely correct because it uses the C preprocessor."
1387 t)
1388
4ab89e7b
SM
1389;;; These two must be unwound, otherwise take exponential time
1390(defconst cperl-maybe-white-and-comment-rex "[ \t\n]*\\(#[^\n]*\n[ \t\n]*\\)*"
1391"Regular expression to match optional whitespace with interpspersed comments.
1392Should contain exactly one group.")
1393
1394;;; This one is tricky to unwind; still very inefficient...
1395(defconst cperl-white-and-comment-rex "\\([ \t\n]\\|#[^\n]*\n\\)+"
1396"Regular expression to match whitespace with interpspersed comments.
1397Should contain exactly one group.")
1398
1399
1400;;; Is incorporated in `cperl-imenu--function-name-regexp-perl'
1401;;; `cperl-outline-regexp', `defun-prompt-regexp'.
1402;;; Details of groups in this may be used in several functions; see comments
1403;;; near mentioned above variable(s)...
1404;;; sub($$):lvalue{} sub:lvalue{} Both allowed...
1405(defsubst cperl-after-sub-regexp (named attr) ; 9 groups without attr...
1406 "Match the text after `sub' in a subroutine declaration.
1407If NAMED is nil, allows anonymous subroutines. Matches up to the first \":\"
1408of attributes (if present), or end of the name or prototype (whatever is
1409the last)."
1410 (concat ; Assume n groups before this...
1411 "\\(" ; n+1=name-group
1412 cperl-white-and-comment-rex ; n+2=pre-name
1413 "\\(::[a-zA-Z_0-9:']+\\|[a-zA-Z_'][a-zA-Z_0-9:']*\\)" ; n+3=name
1414 "\\)" ; END n+1=name-group
1415 (if named "" "?")
1416 "\\(" ; n+4=proto-group
1417 cperl-maybe-white-and-comment-rex ; n+5=pre-proto
1418 "\\(([^()]*)\\)" ; n+6=prototype
1419 "\\)?" ; END n+4=proto-group
1420 "\\(" ; n+7=attr-group
1421 cperl-maybe-white-and-comment-rex ; n+8=pre-attr
1422 "\\(" ; n+9=start-attr
1423 ":"
1424 (if attr (concat
1425 "\\("
1426 cperl-maybe-white-and-comment-rex ; whitespace-comments
1427 "\\(\\sw\\|_\\)+" ; attr-name
1428 ;; attr-arg (1 level of internal parens allowed!)
1429 "\\((\\(\\\\.\\|[^\\\\()]\\|([^\\\\()]*)\\)*)\\)?"
1430 "\\(" ; optional : (XXX allows trailing???)
1431 cperl-maybe-white-and-comment-rex ; whitespace-comments
1432 ":\\)?"
1433 "\\)+")
1434 "[^:]")
1435 "\\)"
1436 "\\)?" ; END n+6=proto-group
1437 ))
1438
1439;;; Details of groups in this are used in `cperl-imenu--create-perl-index'
1440;;; and `cperl-outline-level'.
1441;;;; Was: 2=sub|package; now 2=package-group, 5=package-name 8=sub-name (+3)
95f433f4
RS
1442(defvar cperl-imenu--function-name-regexp-perl
1443 (concat
4ab89e7b
SM
1444 "^\\(" ; 1 = all
1445 "\\([ \t]*package" ; 2 = package-group
1446 "\\(" ; 3 = package-name-group
1447 cperl-white-and-comment-rex ; 4 = pre-package-name
1448 "\\([a-zA-Z_0-9:']+\\)\\)?\\)" ; 5 = package-name
1449 "\\|"
1450 "[ \t]*sub"
1451 (cperl-after-sub-regexp 'named nil) ; 8=name 11=proto 14=attr-start
1452 cperl-maybe-white-and-comment-rex ; 15=pre-block
1453 "\\|"
1454 "=head\\([1-4]\\)[ \t]+" ; 16=level
1455 "\\([^\n]+\\)$" ; 17=text
95f433f4
RS
1456 "\\)"))
1457
8dd511f6
RS
1458(defvar cperl-outline-regexp
1459 (concat cperl-imenu--function-name-regexp-perl "\\|" "\\`"))
1460
f83d2997 1461(defvar cperl-mode-syntax-table nil
f94a632a 1462 "Syntax table in use in CPerl mode buffers.")
f83d2997
KH
1463
1464(defvar cperl-string-syntax-table nil
f94a632a 1465 "Syntax table in use in CPerl mode string-like chunks.")
f83d2997 1466
4ab89e7b
SM
1467(defsubst cperl-1- (p)
1468 (max (point-min) (1- p)))
1469
1470(defsubst cperl-1+ (p)
1471 (min (point-max) (1+ p)))
1472
f83d2997
KH
1473(if cperl-mode-syntax-table
1474 ()
1475 (setq cperl-mode-syntax-table (make-syntax-table))
1476 (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table)
1477 (modify-syntax-entry ?/ "." cperl-mode-syntax-table)
1478 (modify-syntax-entry ?* "." cperl-mode-syntax-table)
1479 (modify-syntax-entry ?+ "." cperl-mode-syntax-table)
1480 (modify-syntax-entry ?- "." cperl-mode-syntax-table)
1481 (modify-syntax-entry ?= "." cperl-mode-syntax-table)
1482 (modify-syntax-entry ?% "." cperl-mode-syntax-table)
1483 (modify-syntax-entry ?< "." cperl-mode-syntax-table)
1484 (modify-syntax-entry ?> "." cperl-mode-syntax-table)
1485 (modify-syntax-entry ?& "." cperl-mode-syntax-table)
1486 (modify-syntax-entry ?$ "\\" cperl-mode-syntax-table)
1487 (modify-syntax-entry ?\n ">" cperl-mode-syntax-table)
1488 (modify-syntax-entry ?# "<" cperl-mode-syntax-table)
1489 (modify-syntax-entry ?' "\"" cperl-mode-syntax-table)
1490 (modify-syntax-entry ?` "\"" cperl-mode-syntax-table)
1491 (if cperl-under-as-char
1492 (modify-syntax-entry ?_ "w" cperl-mode-syntax-table))
1493 (modify-syntax-entry ?: "_" cperl-mode-syntax-table)
1494 (modify-syntax-entry ?| "." cperl-mode-syntax-table)
1495 (setq cperl-string-syntax-table (copy-syntax-table cperl-mode-syntax-table))
1496 (modify-syntax-entry ?$ "." cperl-string-syntax-table)
4ab89e7b
SM
1497 (modify-syntax-entry ?\{ "." cperl-string-syntax-table)
1498 (modify-syntax-entry ?\} "." cperl-string-syntax-table)
83261a2f 1499 (modify-syntax-entry ?# "." cperl-string-syntax-table)) ; (?# comment )
f83d2997
KH
1500
1501
1502\f
db133cb6 1503(defvar cperl-faces-init nil)
f83d2997
KH
1504;; Fix for msb.el
1505(defvar cperl-msb-fixed nil)
83261a2f 1506(defvar cperl-use-major-mode 'cperl-mode)
4ab89e7b
SM
1507(defvar cperl-font-lock-multiline-start nil)
1508(defvar cperl-font-lock-multiline nil)
4ab89e7b 1509(defvar cperl-font-locking nil)
83261a2f 1510
e9bfd3a3
GM
1511;; NB as it stands the code in cperl-mode assumes this only has one
1512;; element. If Xemacs 19 support were dropped, this could all be simplified.
1513(defvar cperl-compilation-error-regexp-alist
1514 ;; This look like a paranoiac regexp: could anybody find a better one? (which WORKS).
1515 '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
1516 2 3))
1517 "Alist that specifies how to match errors in perl output.")
1518
73e72da4
DN
1519(defvar compilation-error-regexp-alist)
1520
f83d2997
KH
1521;;;###autoload
1522(defun cperl-mode ()
1523 "Major mode for editing Perl code.
1524Expression and list commands understand all C brackets.
1525Tab indents for Perl code.
1526Paragraphs are separated by blank lines only.
1527Delete converts tabs to spaces as it moves back.
1528
1529Various characters in Perl almost always come in pairs: {}, (), [],
1530sometimes <>. When the user types the first, she gets the second as
1531well, with optional special formatting done on {}. (Disabled by
1532default.) You can always quote (with \\[quoted-insert]) the left
1533\"paren\" to avoid the expansion. The processing of < is special,
f94a632a 1534since most the time you mean \"less\". CPerl mode tries to guess
f83d2997
KH
1535whether you want to type pair <>, and inserts is if it
1536appropriate. You can set `cperl-electric-parens-string' to the string that
1537contains the parenths from the above list you want to be electrical.
1538Electricity of parenths is controlled by `cperl-electric-parens'.
1539You may also set `cperl-electric-parens-mark' to have electric parens
1540look for active mark and \"embrace\" a region if possible.'
1541
1542CPerl mode provides expansion of the Perl control constructs:
db133cb6 1543
5c8b7eaf 1544 if, else, elsif, unless, while, until, continue, do,
db133cb6
RS
1545 for, foreach, formy and foreachmy.
1546
1547and POD directives (Disabled by default, see `cperl-electric-keywords'.)
1548
1549The user types the keyword immediately followed by a space, which
1550causes the construct to be expanded, and the point is positioned where
1551she is most likely to want to be. eg. when the user types a space
1552following \"if\" the following appears in the buffer: if () { or if ()
1553} { } and the cursor is between the parentheses. The user can then
1554type some boolean expression within the parens. Having done that,
1555typing \\[cperl-linefeed] places you - appropriately indented - on a
1556new line between the braces (if you typed \\[cperl-linefeed] in a POD
5c8b7eaf 1557directive line, then appropriate number of new lines is inserted).
db133cb6
RS
1558
1559If CPerl decides that you want to insert \"English\" style construct like
1560
f83d2997 1561 bite if angry;
db133cb6
RS
1562
1563it will not do any expansion. See also help on variable
1564`cperl-extra-newline-before-brace'. (Note that one can switch the
1565help message on expansion by setting `cperl-message-electric-keyword'
1566to nil.)
f83d2997
KH
1567
1568\\[cperl-linefeed] is a convenience replacement for typing carriage
1569return. It places you in the next line with proper indentation, or if
1570you type it inside the inline block of control construct, like
db133cb6 1571
f83d2997 1572 foreach (@lines) {print; print}
db133cb6 1573
f83d2997
KH
1574and you are on a boundary of a statement inside braces, it will
1575transform the construct into a multiline and will place you into an
5c8b7eaf 1576appropriately indented blank line. If you need a usual
6292d528 1577`newline-and-indent' behavior, it is on \\[newline-and-indent],
f83d2997
KH
1578see documentation on `cperl-electric-linefeed'.
1579
db133cb6
RS
1580Use \\[cperl-invert-if-unless] to change a construction of the form
1581
1582 if (A) { B }
1583
1584into
1585
1586 B if A;
1587
f83d2997
KH
1588\\{cperl-mode-map}
1589
db133cb6
RS
1590Setting the variable `cperl-font-lock' to t switches on font-lock-mode
1591\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
1592on electric space between $ and {, `cperl-electric-parens-string' is
1593the string that contains parentheses that should be electric in CPerl
1594\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
f83d2997
KH
1595setting `cperl-electric-keywords' enables electric expansion of
1596control structures in CPerl. `cperl-electric-linefeed' governs which
1597one of two linefeed behavior is preferable. You can enable all these
1598options simultaneously (recommended mode of use) by setting
1599`cperl-hairy' to t. In this case you can switch separate options off
db133cb6
RS
1600by setting them to `null'. Note that one may undo the extra
1601whitespace inserted by semis and braces in `auto-newline'-mode by
1602consequent \\[cperl-electric-backspace].
f83d2997
KH
1603
1604If your site has perl5 documentation in info format, you can use commands
1605\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
1606These keys run commands `cperl-info-on-current-command' and
1607`cperl-info-on-command', which one is which is controlled by variable
5c8b7eaf 1608`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
db133cb6 1609\(in turn affected by `cperl-hairy').
f83d2997
KH
1610
1611Even if you have no info-format documentation, short one-liner-style
db133cb6
RS
1612help is available on \\[cperl-get-help], and one can run perldoc or
1613man via menu.
f83d2997 1614
db133cb6
RS
1615It is possible to show this help automatically after some idle time.
1616This is regulated by variable `cperl-lazy-help-time'. Default with
1617`cperl-hairy' (if the value of `cperl-lazy-help-time' is nil) is 5
1618secs idle time . It is also possible to switch this on/off from the
1619menu, or via \\[cperl-toggle-autohelp]. Requires `run-with-idle-timer'.
f83d2997
KH
1620
1621Use \\[cperl-lineup] to vertically lineup some construction - put the
1622beginning of the region at the start of construction, and make region
1623span the needed amount of lines.
1624
1625Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
83261a2f 1626`cperl-pod-face', `cperl-pod-head-face' control processing of POD and
db133cb6
RS
1627here-docs sections. With capable Emaxen results of scan are used
1628for indentation too, otherwise they are used for highlighting only.
f83d2997
KH
1629
1630Variables controlling indentation style:
1631 `cperl-tab-always-indent'
1632 Non-nil means TAB in CPerl mode should always reindent the current line,
1633 regardless of where in the line point is when the TAB command is used.
db133cb6
RS
1634 `cperl-indent-left-aligned-comments'
1635 Non-nil means that the comment starting in leftmost column should indent.
f83d2997
KH
1636 `cperl-auto-newline'
1637 Non-nil means automatically newline before and after braces,
1638 and after colons and semicolons, inserted in Perl code. The following
1639 \\[cperl-electric-backspace] will remove the inserted whitespace.
5c8b7eaf
SS
1640 Insertion after colons requires both this variable and
1641 `cperl-auto-newline-after-colon' set.
f83d2997
KH
1642 `cperl-auto-newline-after-colon'
1643 Non-nil means automatically newline even after colons.
1644 Subject to `cperl-auto-newline' setting.
1645 `cperl-indent-level'
1646 Indentation of Perl statements within surrounding block.
1647 The surrounding block's indentation is the indentation
1648 of the line on which the open-brace appears.
1649 `cperl-continued-statement-offset'
1650 Extra indentation given to a substatement, such as the
1651 then-clause of an if, or body of a while, or just a statement continuation.
1652 `cperl-continued-brace-offset'
1653 Extra indentation given to a brace that starts a substatement.
1654 This is in addition to `cperl-continued-statement-offset'.
1655 `cperl-brace-offset'
1656 Extra indentation for line if it starts with an open brace.
1657 `cperl-brace-imaginary-offset'
1658 An open brace following other text is treated as if it the line started
1659 this far to the right of the actual line indentation.
1660 `cperl-label-offset'
1661 Extra indentation for line that is a label.
1662 `cperl-min-label-indent'
1663 Minimal indentation for line that is a label.
1664
4ab89e7b
SM
1665Settings for classic indent-styles: K&R BSD=C++ GNU PerlStyle=Whitesmith
1666 `cperl-indent-level' 5 4 2 4
1667 `cperl-brace-offset' 0 0 0 0
1668 `cperl-continued-brace-offset' -5 -4 0 0
1669 `cperl-label-offset' -5 -4 -2 -4
1670 `cperl-continued-statement-offset' 5 4 2 4
f83d2997 1671
db133cb6
RS
1672CPerl knows several indentation styles, and may bulk set the
1673corresponding variables. Use \\[cperl-set-style] to do this. Use
1674\\[cperl-set-style-back] to restore the memorized preexisting values
4ab89e7b
SM
1675\(both available from menu). See examples in `cperl-style-examples'.
1676
1677Part of the indentation style is how different parts of if/elsif/else
1678statements are broken into lines; in CPerl, this is reflected on how
1679templates for these constructs are created (controlled by
1680`cperl-extra-newline-before-brace'), and how reflow-logic should treat \"continuation\" blocks of else/elsif/continue, controlled by the same variable,
1681and by `cperl-extra-newline-before-brace-multiline',
1682`cperl-merge-trailing-else', `cperl-indent-region-fix-constructs'.
db133cb6
RS
1683
1684If `cperl-indent-level' is 0, the statement after opening brace in
5c8b7eaf 1685column 0 is indented on
db133cb6 1686`cperl-brace-offset'+`cperl-continued-statement-offset'.
f83d2997
KH
1687
1688Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook'
db133cb6
RS
1689with no args.
1690
1691DO NOT FORGET to read micro-docs (available from `Perl' menu)
1692or as help on variables `cperl-tips', `cperl-problems',
f94a632a 1693`cperl-praise', `cperl-speed'."
f83d2997
KH
1694 (interactive)
1695 (kill-all-local-variables)
f83d2997
KH
1696 (use-local-map cperl-mode-map)
1697 (if (cperl-val 'cperl-electric-linefeed)
1698 (progn
1699 (local-set-key "\C-J" 'cperl-linefeed)
1700 (local-set-key "\C-C\C-J" 'newline-and-indent)))
db133cb6
RS
1701 (if (and
1702 (cperl-val 'cperl-clobber-lisp-bindings)
1703 (cperl-val 'cperl-info-on-command-no-prompt))
f83d2997
KH
1704 (progn
1705 ;; don't clobber the backspace binding:
1706 (cperl-define-key "\C-hf" 'cperl-info-on-current-command [(control h) f])
1707 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-command
1708 [(control c) (control h) f])))
83261a2f 1709 (setq major-mode cperl-use-major-mode)
f83d2997 1710 (setq mode-name "CPerl")
449657e8
GM
1711 (let ((prev-a-c abbrevs-changed))
1712 (define-abbrev-table 'cperl-mode-abbrev-table '(
f83d2997
KH
1713 ("if" "if" cperl-electric-keyword 0)
1714 ("elsif" "elsif" cperl-electric-keyword 0)
1715 ("while" "while" cperl-electric-keyword 0)
1716 ("until" "until" cperl-electric-keyword 0)
1717 ("unless" "unless" cperl-electric-keyword 0)
1718 ("else" "else" cperl-electric-else 0)
db133cb6 1719 ("continue" "continue" cperl-electric-else 0)
f83d2997
KH
1720 ("for" "for" cperl-electric-keyword 0)
1721 ("foreach" "foreach" cperl-electric-keyword 0)
db133cb6
RS
1722 ("formy" "formy" cperl-electric-keyword 0)
1723 ("foreachmy" "foreachmy" cperl-electric-keyword 0)
1724 ("do" "do" cperl-electric-keyword 0)
6c389151
SM
1725 ("=pod" "=pod" cperl-electric-pod 0)
1726 ("=over" "=over" cperl-electric-pod 0)
1727 ("=head1" "=head1" cperl-electric-pod 0)
1728 ("=head2" "=head2" cperl-electric-pod 0)
db133cb6
RS
1729 ("pod" "pod" cperl-electric-pod 0)
1730 ("over" "over" cperl-electric-pod 0)
1731 ("head1" "head1" cperl-electric-pod 0)
1732 ("head2" "head2" cperl-electric-pod 0)))
449657e8 1733 (setq abbrevs-changed prev-a-c))
f83d2997 1734 (setq local-abbrev-table cperl-mode-abbrev-table)
4ab89e7b
SM
1735 (if (cperl-val 'cperl-electric-keywords)
1736 (abbrev-mode 1))
f83d2997 1737 (set-syntax-table cperl-mode-syntax-table)
4ab89e7b
SM
1738 ;; Until Emacs is multi-threaded, we do not actually need it local:
1739 (make-local-variable 'cperl-font-lock-multiline-start)
1740 (make-local-variable 'cperl-font-locking)
6c389151
SM
1741 (make-local-variable 'outline-regexp)
1742 ;; (setq outline-regexp imenu-example--function-name-regexp-perl)
1743 (setq outline-regexp cperl-outline-regexp)
1744 (make-local-variable 'outline-level)
1745 (setq outline-level 'cperl-outline-level)
f83d2997
KH
1746 (make-local-variable 'paragraph-start)
1747 (setq paragraph-start (concat "^$\\|" page-delimiter))
1748 (make-local-variable 'paragraph-separate)
1749 (setq paragraph-separate paragraph-start)
1750 (make-local-variable 'paragraph-ignore-fill-prefix)
1751 (setq paragraph-ignore-fill-prefix t)
6546555e 1752 (if (featurep 'xemacs)
4ab89e7b
SM
1753 (progn
1754 (make-local-variable 'paren-backwards-message)
1755 (set 'paren-backwards-message t)))
f83d2997
KH
1756 (make-local-variable 'indent-line-function)
1757 (setq indent-line-function 'cperl-indent-line)
1758 (make-local-variable 'require-final-newline)
7d441781 1759 (setq require-final-newline mode-require-final-newline)
f83d2997
KH
1760 (make-local-variable 'comment-start)
1761 (setq comment-start "# ")
1762 (make-local-variable 'comment-end)
1763 (setq comment-end "")
1764 (make-local-variable 'comment-column)
1765 (setq comment-column cperl-comment-column)
1766 (make-local-variable 'comment-start-skip)
1767 (setq comment-start-skip "#+ *")
1768 (make-local-variable 'defun-prompt-regexp)
4ab89e7b
SM
1769;;; "[ \t]*sub"
1770;;; (cperl-after-sub-regexp 'named nil) ; 8=name 11=proto 14=attr-start
1771;;; cperl-maybe-white-and-comment-rex ; 15=pre-block
1772 (setq defun-prompt-regexp
1773 (concat "^[ \t]*\\(sub"
1774 (cperl-after-sub-regexp 'named 'attr-groups)
1775 "\\|" ; per toke.c
1776 "\\(BEGIN\\|CHECK\\|INIT\\|END\\|AUTOLOAD\\|DESTROY\\)"
1777 "\\)"
1778 cperl-maybe-white-and-comment-rex))
f83d2997
KH
1779 (make-local-variable 'comment-indent-function)
1780 (setq comment-indent-function 'cperl-comment-indent)
4ab89e7b
SM
1781 (and (boundp 'fill-paragraph-function)
1782 (progn
1783 (make-local-variable 'fill-paragraph-function)
1784 (set 'fill-paragraph-function 'cperl-fill-paragraph)))
f83d2997
KH
1785 (make-local-variable 'parse-sexp-ignore-comments)
1786 (setq parse-sexp-ignore-comments t)
1787 (make-local-variable 'indent-region-function)
1788 (setq indent-region-function 'cperl-indent-region)
1789 ;;(setq auto-fill-function 'cperl-do-auto-fill) ; Need to switch on and off!
1790 (make-local-variable 'imenu-create-index-function)
1791 (setq imenu-create-index-function
80585273 1792 (function cperl-imenu--create-perl-index))
f83d2997
KH
1793 (make-local-variable 'imenu-sort-function)
1794 (setq imenu-sort-function nil)
e1a5828f
AS
1795 (make-local-variable 'vc-rcs-header)
1796 (set 'vc-rcs-header cperl-vc-rcs-header)
1797 (make-local-variable 'vc-sccs-header)
1798 (set 'vc-sccs-header cperl-vc-sccs-header)
4ab89e7b
SM
1799 ;; This one is obsolete...
1800 (make-local-variable 'vc-header-alist)
73e72da4
DN
1801 (with-no-warnings
1802 (set 'vc-header-alist (or cperl-vc-header-alist ; Avoid warning
1803 `((SCCS ,(car cperl-vc-sccs-header))
1804 (RCS ,(car cperl-vc-rcs-header)))))
1805 )
4ab89e7b
SM
1806 (cond ((boundp 'compilation-error-regexp-alist-alist);; xemacs 20.x
1807 (make-local-variable 'compilation-error-regexp-alist-alist)
1808 (set 'compilation-error-regexp-alist-alist
e9bfd3a3 1809 (cons (cons 'cperl (car cperl-compilation-error-regexp-alist))
4ab89e7b
SM
1810 (symbol-value 'compilation-error-regexp-alist-alist)))
1811 (if (fboundp 'compilation-build-compilation-error-regexp-alist)
1812 (let ((f 'compilation-build-compilation-error-regexp-alist))
1813 (funcall f))
28a62ecb 1814 (make-local-variable 'compilation-error-regexp-alist)
4ab89e7b
SM
1815 (push 'cperl compilation-error-regexp-alist)))
1816 ((boundp 'compilation-error-regexp-alist);; xmeacs 19.x
1817 (make-local-variable 'compilation-error-regexp-alist)
1818 (set 'compilation-error-regexp-alist
10715960
RS
1819 (append cperl-compilation-error-regexp-alist
1820 (symbol-value 'compilation-error-regexp-alist)))))
f83d2997
KH
1821 (make-local-variable 'font-lock-defaults)
1822 (setq font-lock-defaults
db133cb6
RS
1823 (cond
1824 ((string< emacs-version "19.30")
4ab89e7b 1825 '(cperl-font-lock-keywords-2 nil nil ((?_ . "w"))))
db133cb6 1826 ((string< emacs-version "19.33") ; Which one to use?
5efe6a56
SM
1827 '((cperl-font-lock-keywords
1828 cperl-font-lock-keywords-1
4ab89e7b 1829 cperl-font-lock-keywords-2) nil nil ((?_ . "w"))))
db133cb6
RS
1830 (t
1831 '((cperl-load-font-lock-keywords
1832 cperl-load-font-lock-keywords-1
4ab89e7b 1833 cperl-load-font-lock-keywords-2) nil nil ((?_ . "w"))))))
db133cb6 1834 (make-local-variable 'cperl-syntax-state)
4ab89e7b 1835 (setq cperl-syntax-state nil) ; reset syntaxification cache
f83d2997
KH
1836 (if cperl-use-syntax-table-text-property
1837 (progn
029cb4d5 1838 (make-local-variable 'parse-sexp-lookup-properties)
f83d2997 1839 ;; Do not introduce variable if not needed, we check it!
db133cb6
RS
1840 (set 'parse-sexp-lookup-properties t)
1841 ;; Fix broken font-lock:
1842 (or (boundp 'font-lock-unfontify-region-function)
1843 (set 'font-lock-unfontify-region-function
83261a2f 1844 'font-lock-default-unfontify-region))
6546555e 1845 (unless (featurep 'xemacs) ; Our: just a plug for wrong font-lock
4ab89e7b
SM
1846 (make-local-variable 'font-lock-unfontify-region-function)
1847 (set 'font-lock-unfontify-region-function ; not present with old Emacs
1848 'cperl-font-lock-unfontify-region-function))
029cb4d5 1849 (make-local-variable 'cperl-syntax-done-to)
4ab89e7b 1850 (setq cperl-syntax-done-to nil) ; reset syntaxification cache
029cb4d5 1851 (make-local-variable 'font-lock-syntactic-keywords)
5c8b7eaf 1852 (setq font-lock-syntactic-keywords
db133cb6 1853 (if cperl-syntaxify-by-font-lock
11b41e6f
SM
1854 '((cperl-fontify-syntaxically))
1855 ;; unless font-lock-syntactic-keywords, font-lock (pre-22.1)
1856 ;; used to ignore syntax-table text-properties. (t) is a hack
1857 ;; to make font-lock think that font-lock-syntactic-keywords
1858 ;; are defined.
db133cb6 1859 '(t)))))
4ab89e7b
SM
1860 (if (boundp 'font-lock-multiline) ; Newer font-lock; use its facilities
1861 (progn
1862 (setq cperl-font-lock-multiline t) ; Not localized...
f453f5a8 1863 (set (make-local-variable 'font-lock-multiline) t))
4ab89e7b
SM
1864 (make-local-variable 'font-lock-fontify-region-function)
1865 (set 'font-lock-fontify-region-function ; not present with old Emacs
1866 'cperl-font-lock-fontify-region-function))
1867 (make-local-variable 'font-lock-fontify-region-function)
1868 (set 'font-lock-fontify-region-function ; not present with old Emacs
1869 'cperl-font-lock-fontify-region-function)
db133cb6 1870 (make-local-variable 'cperl-old-style)
83261a2f
SM
1871 (if (boundp 'normal-auto-fill-function) ; 19.33 and later
1872 (set (make-local-variable 'normal-auto-fill-function)
4ab89e7b 1873 'cperl-do-auto-fill)
83261a2f
SM
1874 (or (fboundp 'cperl-old-auto-fill-mode)
1875 (progn
1876 (fset 'cperl-old-auto-fill-mode (symbol-function 'auto-fill-mode))
1877 (defun auto-fill-mode (&optional arg)
1878 (interactive "P")
1879 (eval '(cperl-old-auto-fill-mode arg)) ; Avoid a warning
1880 (and auto-fill-function (memq major-mode '(perl-mode cperl-mode))
1881 (setq auto-fill-function 'cperl-do-auto-fill))))))
f83d2997 1882 (if (cperl-enable-font-lock)
5c8b7eaf 1883 (if (cperl-val 'cperl-font-lock)
f83d2997
KH
1884 (progn (or cperl-faces-init (cperl-init-faces))
1885 (font-lock-mode 1))))
4ab89e7b
SM
1886 (set (make-local-variable 'facemenu-add-face-function)
1887 'cperl-facemenu-add-face-function) ; XXXX What this guy is for???
f83d2997
KH
1888 (and (boundp 'msb-menu-cond)
1889 (not cperl-msb-fixed)
1890 (cperl-msb-fix))
1891 (if (featurep 'easymenu)
46c72468 1892 (easy-menu-add cperl-menu)) ; A NOP in Emacs.
a3c328ee 1893 (run-mode-hooks 'cperl-mode-hook)
4ab89e7b 1894 (if cperl-hook-after-change
39234e39 1895 (add-hook 'after-change-functions 'cperl-after-change-function nil t))
f83d2997 1896 ;; After hooks since fontification will break this
5c8b7eaf 1897 (if cperl-pod-here-scan
83261a2f 1898 (or cperl-syntaxify-by-font-lock
5bd52f0e
RS
1899 (progn (or cperl-faces-init (cperl-init-faces-weak))
1900 (cperl-find-pods-heres)))))
f83d2997
KH
1901\f
1902;; Fix for perldb - make default reasonable
1903(defun cperl-db ()
1904 (interactive)
1905 (require 'gud)
1906 (perldb (read-from-minibuffer "Run perldb (like this): "
1907 (if (consp gud-perldb-history)
1908 (car gud-perldb-history)
1909 (concat "perl " ;;(file-name-nondirectory
83261a2f
SM
1910 ;; I have problems
1911 ;; in OS/2
1912 ;; otherwise
1913 (buffer-file-name)))
f83d2997
KH
1914 nil nil
1915 '(gud-perldb-history . 1))))
1916\f
f83d2997
KH
1917(defun cperl-msb-fix ()
1918 ;; Adds perl files to msb menu, supposes that msb is already loaded
1919 (setq cperl-msb-fixed t)
1920 (let* ((l (length msb-menu-cond))
1921 (last (nth (1- l) msb-menu-cond))
1922 (precdr (nthcdr (- l 2) msb-menu-cond)) ; cdr of this is last
1923 (handle (1- (nth 1 last))))
1924 (setcdr precdr (list
1925 (list
996e2616 1926 '(memq major-mode '(cperl-mode perl-mode))
f83d2997
KH
1927 handle
1928 "Perl Files (%d)")
1929 last))))
1930\f
1931;; This is used by indent-for-comment
1932;; to decide how much to indent a comment in CPerl code
1933;; based on its context. Do fallback if comment is found wrong.
1934
1935(defvar cperl-wrong-comment)
5bd52f0e
RS
1936(defvar cperl-st-cfence '(14)) ; Comment-fence
1937(defvar cperl-st-sfence '(15)) ; String-fence
1938(defvar cperl-st-punct '(1))
1939(defvar cperl-st-word '(2))
1940(defvar cperl-st-bra '(4 . ?\>))
1941(defvar cperl-st-ket '(5 . ?\<))
1942
f83d2997 1943
4ab89e7b 1944(defun cperl-comment-indent () ; called at point at supposed comment
5bd52f0e 1945 (let ((p (point)) (c (current-column)) was phony)
4ab89e7b
SM
1946 (if (and (not cperl-indent-comment-at-column-0)
1947 (looking-at "^#"))
1948 0 ; Existing comment at bol stays there.
f83d2997
KH
1949 ;; Wrong comment found
1950 (save-excursion
5bd52f0e
RS
1951 (setq was (cperl-to-comment-or-eol)
1952 phony (eq (get-text-property (point) 'syntax-table)
1953 cperl-st-cfence))
1954 (if phony
4ab89e7b 1955 (progn ; Too naive???
5bd52f0e
RS
1956 (re-search-forward "#\\|$") ; Hmm, what about embedded #?
1957 (if (eq (preceding-char) ?\#)
1958 (forward-char -1))
1959 (setq was nil)))
4ab89e7b 1960 (if (= (point) p) ; Our caller found a correct place
f83d2997
KH
1961 (progn
1962 (skip-chars-backward " \t")
4ab89e7b
SM
1963 (setq was (current-column))
1964 (if (eq was 0)
1965 comment-column
1966 (max (1+ was) ; Else indent at comment column
1967 comment-column)))
1968 ;; No, the caller found a random place; we need to edit ourselves
f83d2997
KH
1969 (if was nil
1970 (insert comment-start)
1971 (backward-char (length comment-start)))
1972 (setq cperl-wrong-comment t)
4ab89e7b
SM
1973 (cperl-make-indent comment-column 1) ; Indent min 1
1974 c)))))
f83d2997
KH
1975
1976;;;(defun cperl-comment-indent-fallback ()
1977;;; "Is called if the standard comment-search procedure fails.
1978;;;Point is at start of real comment."
1979;;; (let ((c (current-column)) target cnt prevc)
1980;;; (if (= c comment-column) nil
1981;;; (setq cnt (skip-chars-backward "[ \t]"))
5c8b7eaf 1982;;; (setq target (max (1+ (setq prevc
f83d2997
KH
1983;;; (current-column))) ; Else indent at comment column
1984;;; comment-column))
1985;;; (if (= c comment-column) nil
1986;;; (delete-backward-char cnt)
1987;;; (while (< prevc target)
1988;;; (insert "\t")
1989;;; (setq prevc (current-column)))
1990;;; (if (> prevc target) (progn (delete-char -1) (setq prevc (current-column))))
1991;;; (while (< prevc target)
1992;;; (insert " ")
1993;;; (setq prevc (current-column)))))))
1994
1995(defun cperl-indent-for-comment ()
1996 "Substitute for `indent-for-comment' in CPerl."
1997 (interactive)
1998 (let (cperl-wrong-comment)
1999 (indent-for-comment)
4ab89e7b 2000 (if cperl-wrong-comment ; set by `cperl-comment-indent'
f83d2997
KH
2001 (progn (cperl-to-comment-or-eol)
2002 (forward-char (length comment-start))))))
2003
2004(defun cperl-comment-region (b e arg)
2005 "Comment or uncomment each line in the region in CPerl mode.
2006See `comment-region'."
2007 (interactive "r\np")
2008 (let ((comment-start "#"))
2009 (comment-region b e arg)))
2010
2011(defun cperl-uncomment-region (b e arg)
2012 "Uncomment or comment each line in the region in CPerl mode.
2013See `comment-region'."
2014 (interactive "r\np")
2015 (let ((comment-start "#"))
2016 (comment-region b e (- arg))))
2017
2018(defvar cperl-brace-recursing nil)
2019
2020(defun cperl-electric-brace (arg &optional only-before)
2021 "Insert character and correct line's indentation.
2022If ONLY-BEFORE and `cperl-auto-newline', will insert newline before the
2023place (even in empty line), but not after. If after \")\" and the inserted
5c8b7eaf 2024char is \"{\", insert extra newline before only if
f83d2997
KH
2025`cperl-extra-newline-before-brace'."
2026 (interactive "P")
2027 (let (insertpos
2028 (other-end (if (and cperl-electric-parens-mark
5c8b7eaf 2029 (cperl-mark-active)
f83d2997 2030 (< (mark) (point)))
5c8b7eaf 2031 (mark)
f83d2997
KH
2032 nil)))
2033 (if (and other-end
2034 (not cperl-brace-recursing)
2035 (cperl-val 'cperl-electric-parens)
2036 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point)))
2037 ;; Need to insert a matching pair
2038 (progn
2039 (save-excursion
2040 (setq insertpos (point-marker))
2041 (goto-char other-end)
2042 (setq last-command-char ?\{)
2043 (cperl-electric-lbrace arg insertpos))
2044 (forward-char 1))
83261a2f 2045 ;; Check whether we close something "usual" with `}'
db133cb6 2046 (if (and (eq last-command-char ?\})
5c8b7eaf 2047 (not
db133cb6
RS
2048 (condition-case nil
2049 (save-excursion
2050 (up-list (- (prefix-numeric-value arg)))
2051 ;;(cperl-after-block-p (point-min))
f739b53b
SM
2052 (or (cperl-after-expr-p nil "{;)")
2053 ;; after sub, else, continue
2054 (cperl-after-block-p nil 'pre)))
db133cb6
RS
2055 (error nil))))
2056 ;; Just insert the guy
2057 (self-insert-command (prefix-numeric-value arg))
2058 (if (and (not arg) ; No args, end (of empty line or auto)
2059 (eolp)
2060 (or (and (null only-before)
2061 (save-excursion
2062 (skip-chars-backward " \t")
2063 (bolp)))
2064 (and (eq last-command-char ?\{) ; Do not insert newline
2065 ;; if after ")" and `cperl-extra-newline-before-brace'
2066 ;; is nil, do not insert extra newline.
2067 (not cperl-extra-newline-before-brace)
2068 (save-excursion
2069 (skip-chars-backward " \t")
2070 (eq (preceding-char) ?\))))
5c8b7eaf 2071 (if cperl-auto-newline
db133cb6
RS
2072 (progn (cperl-indent-line) (newline) t) nil)))
2073 (progn
2074 (self-insert-command (prefix-numeric-value arg))
2075 (cperl-indent-line)
2076 (if cperl-auto-newline
2077 (setq insertpos (1- (point))))
2078 (if (and cperl-auto-newline (null only-before))
2079 (progn
2080 (newline)
2081 (cperl-indent-line)))
2082 (save-excursion
2083 (if insertpos (progn (goto-char insertpos)
5c8b7eaf 2084 (search-forward (make-string
db133cb6
RS
2085 1 last-command-char))
2086 (setq insertpos (1- (point)))))
2087 (delete-char -1))))
2088 (if insertpos
f83d2997 2089 (save-excursion
db133cb6
RS
2090 (goto-char insertpos)
2091 (self-insert-command (prefix-numeric-value arg)))
2092 (self-insert-command (prefix-numeric-value arg)))))))
f83d2997
KH
2093
2094(defun cperl-electric-lbrace (arg &optional end)
2095 "Insert character, correct line's indentation, correct quoting by space."
2096 (interactive "P")
83261a2f
SM
2097 (let ((cperl-brace-recursing t)
2098 (cperl-auto-newline cperl-auto-newline)
2099 (other-end (or end
2100 (if (and cperl-electric-parens-mark
2101 (cperl-mark-active)
2102 (> (mark) (point)))
2103 (save-excursion
2104 (goto-char (mark))
2105 (point-marker))
2106 nil)))
2107 pos after)
f83d2997
KH
2108 (and (cperl-val 'cperl-electric-lbrace-space)
2109 (eq (preceding-char) ?$)
2110 (save-excursion
2111 (skip-chars-backward "$")
2112 (looking-at "\\(\\$\\$\\)*\\$\\([^\\$]\\|$\\)"))
b5b0cb34 2113 (insert ?\s))
bab27c0c 2114 ;; Check whether we are in comment
5c8b7eaf 2115 (if (and
bab27c0c
RS
2116 (save-excursion
2117 (beginning-of-line)
2118 (not (looking-at "[ \t]*#")))
2119 (cperl-after-expr-p nil "{;)"))
2120 nil
2121 (setq cperl-auto-newline nil))
f83d2997
KH
2122 (cperl-electric-brace arg)
2123 (and (cperl-val 'cperl-electric-parens)
2124 (eq last-command-char ?{)
5c8b7eaf 2125 (memq last-command-char
f83d2997
KH
2126 (append cperl-electric-parens-string nil))
2127 (or (if other-end (goto-char (marker-position other-end)))
2128 t)
2129 (setq last-command-char ?} pos (point))
2130 (progn (cperl-electric-brace arg t)
2131 (goto-char pos)))))
2132
2133(defun cperl-electric-paren (arg)
f739b53b
SM
2134 "Insert an opening parenthesis or a matching pair of parentheses.
2135See `cperl-electric-parens'."
f83d2997
KH
2136 (interactive "P")
2137 (let ((beg (save-excursion (beginning-of-line) (point)))
2138 (other-end (if (and cperl-electric-parens-mark
5c8b7eaf 2139 (cperl-mark-active)
f83d2997 2140 (> (mark) (point)))
83261a2f
SM
2141 (save-excursion
2142 (goto-char (mark))
2143 (point-marker))
f83d2997
KH
2144 nil)))
2145 (if (and (cperl-val 'cperl-electric-parens)
2146 (memq last-command-char
2147 (append cperl-electric-parens-string nil))
2148 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
2149 ;;(not (save-excursion (search-backward "#" beg t)))
2150 (if (eq last-command-char ?<)
2151 (progn
2152 (and abbrev-mode ; later it is too late, may be after `for'
2153 (expand-abbrev))
2154 (cperl-after-expr-p nil "{;(,:="))
2155 1))
2156 (progn
2157 (self-insert-command (prefix-numeric-value arg))
2158 (if other-end (goto-char (marker-position other-end)))
5c8b7eaf 2159 (insert (make-string
f83d2997
KH
2160 (prefix-numeric-value arg)
2161 (cdr (assoc last-command-char '((?{ .?})
2162 (?[ . ?])
2163 (?( . ?))
2164 (?< . ?>))))))
2165 (forward-char (- (prefix-numeric-value arg))))
2166 (self-insert-command (prefix-numeric-value arg)))))
2167
2168(defun cperl-electric-rparen (arg)
2169 "Insert a matching pair of parentheses if marking is active.
f739b53b
SM
2170If not, or if we are not at the end of marking range, would self-insert.
2171Affected by `cperl-electric-parens'."
f83d2997
KH
2172 (interactive "P")
2173 (let ((beg (save-excursion (beginning-of-line) (point)))
2174 (other-end (if (and cperl-electric-parens-mark
2175 (cperl-val 'cperl-electric-parens)
2176 (memq last-command-char
2177 (append cperl-electric-parens-string nil))
5c8b7eaf 2178 (cperl-mark-active)
f83d2997 2179 (< (mark) (point)))
5c8b7eaf 2180 (mark)
f83d2997
KH
2181 nil))
2182 p)
2183 (if (and other-end
2184 (cperl-val 'cperl-electric-parens)
2185 (memq last-command-char '( ?\) ?\] ?\} ?\> ))
2186 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
2187 ;;(not (save-excursion (search-backward "#" beg t)))
2188 )
2189 (progn
2190 (self-insert-command (prefix-numeric-value arg))
2191 (setq p (point))
2192 (if other-end (goto-char other-end))
2193 (insert (make-string
2194 (prefix-numeric-value arg)
2195 (cdr (assoc last-command-char '((?\} . ?\{)
83261a2f
SM
2196 (?\] . ?\[)
2197 (?\) . ?\()
2198 (?\> . ?\<))))))
f83d2997
KH
2199 (goto-char (1+ p)))
2200 (self-insert-command (prefix-numeric-value arg)))))
2201
2202(defun cperl-electric-keyword ()
db133cb6
RS
2203 "Insert a construction appropriate after a keyword.
2204Help message may be switched off by setting `cperl-message-electric-keyword'
2205to nil."
5c8b7eaf 2206 (let ((beg (save-excursion (beginning-of-line) (point)))
f83d2997
KH
2207 (dollar (and (eq last-command-char ?$)
2208 (eq this-command 'self-insert-command)))
b5b0cb34 2209 (delete (and (memq last-command-char '(?\s ?\n ?\t ?\f))
db133cb6
RS
2210 (memq this-command '(self-insert-command newline))))
2211 my do)
f83d2997 2212 (and (save-excursion
db133cb6
RS
2213 (condition-case nil
2214 (progn
2215 (backward-sexp 1)
2216 (setq do (looking-at "do\\>")))
2217 (error nil))
f83d2997 2218 (cperl-after-expr-p nil "{;:"))
5c8b7eaf
SS
2219 (save-excursion
2220 (not
f83d2997 2221 (re-search-backward
5bd52f0e 2222 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
f83d2997
KH
2223 beg t)))
2224 (save-excursion (or (not (re-search-backward "^=" nil t))
db133cb6
RS
2225 (or
2226 (looking-at "=cut")
2227 (and cperl-use-syntax-table-text-property
2228 (not (eq (get-text-property (point)
2229 'syntax-type)
2230 'pod))))))
f739b53b
SM
2231 (save-excursion (forward-sexp -1)
2232 (not (memq (following-char) (append "$@%&*" nil))))
f83d2997 2233 (progn
db133cb6
RS
2234 (and (eq (preceding-char) ?y)
2235 (progn ; "foreachmy"
2236 (forward-char -2)
2237 (insert " ")
2238 (forward-char 2)
5c8b7eaf
SS
2239 (setq my t dollar t
2240 delete
db133cb6 2241 (memq this-command '(self-insert-command newline)))))
f83d2997
KH
2242 (and dollar (insert " $"))
2243 (cperl-indent-line)
2244 ;;(insert " () {\n}")
2245 (cond
2246 (cperl-extra-newline-before-brace
db133cb6 2247 (insert (if do "\n" " ()\n"))
f83d2997
KH
2248 (insert "{")
2249 (cperl-indent-line)
2250 (insert "\n")
2251 (cperl-indent-line)
db133cb6
RS
2252 (insert "\n}")
2253 (and do (insert " while ();")))
f83d2997 2254 (t
83261a2f 2255 (insert (if do " {\n} while ();" " () {\n}"))))
f83d2997
KH
2256 (or (looking-at "[ \t]\\|$") (insert " "))
2257 (cperl-indent-line)
2258 (if dollar (progn (search-backward "$")
5c8b7eaf 2259 (if my
db133cb6
RS
2260 (forward-char 1)
2261 (delete-char 1)))
f739b53b
SM
2262 (search-backward ")")
2263 (if (eq last-command-char ?\()
2264 (progn ; Avoid "if (())"
2265 (delete-backward-char 1)
2266 (delete-backward-char -1))))
f83d2997 2267 (if delete
db133cb6
RS
2268 (cperl-putback-char cperl-del-back-ch))
2269 (if cperl-message-electric-keyword
2270 (message "Precede char by C-q to avoid expansion"))))))
2271
2272(defun cperl-ensure-newlines (n &optional pos)
2273 "Make sure there are N newlines after the point."
2274 (or pos (setq pos (point)))
2275 (if (looking-at "\n")
2276 (forward-char 1)
2277 (insert "\n"))
2278 (if (> n 1)
2279 (cperl-ensure-newlines (1- n) pos)
2280 (goto-char pos)))
2281
2282(defun cperl-electric-pod ()
2283 "Insert a POD chunk appropriate after a =POD directive."
b5b0cb34 2284 (let ((delete (and (memq last-command-char '(?\s ?\n ?\t ?\f))
db133cb6
RS
2285 (memq this-command '(self-insert-command newline))))
2286 head1 notlast name p really-delete over)
2287 (and (save-excursion
6c389151 2288 (forward-word -1)
a1506d29 2289 (and
db133cb6
RS
2290 (eq (preceding-char) ?=)
2291 (progn
6c389151
SM
2292 (setq head1 (looking-at "head1\\>[ \t]*$"))
2293 (setq over (and (looking-at "over\\>[ \t]*$")
2294 (not (looking-at "over[ \t]*\n\n\n*=item\\>"))))
db133cb6
RS
2295 (forward-char -1)
2296 (bolp))
5c8b7eaf 2297 (or
5bd52f0e 2298 (get-text-property (point) 'in-pod)
db133cb6 2299 (cperl-after-expr-p nil "{;:")
4ab89e7b
SM
2300 (and (re-search-backward "\\(\\`\n?\\|^\n\\)=\\sw+" (point-min) t)
2301 (not (looking-at "\n*=cut"))
2302 (or (not cperl-use-syntax-table-text-property)
2303 (eq (get-text-property (point) 'syntax-type) 'pod))))))
db133cb6
RS
2304 (progn
2305 (save-excursion
6c389151 2306 (setq notlast (re-search-forward "^\n=" nil t)))
db133cb6
RS
2307 (or notlast
2308 (progn
2309 (insert "\n\n=cut")
2310 (cperl-ensure-newlines 2)
6c389151 2311 (forward-word -2)
a1506d29
JB
2312 (if (and head1
2313 (not
db133cb6
RS
2314 (save-excursion
2315 (forward-char -1)
2316 (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\>"
83261a2f 2317 nil t)))) ; Only one
a1506d29 2318 (progn
6c389151 2319 (forward-word 1)
db133cb6
RS
2320 (setq name (file-name-sans-extension
2321 (file-name-nondirectory (buffer-file-name)))
2322 p (point))
5c8b7eaf 2323 (insert " NAME\n\n" name
029cb4d5 2324 " - \n\n=head1 SYNOPSIS\n\n\n\n"
db133cb6
RS
2325 "=head1 DESCRIPTION")
2326 (cperl-ensure-newlines 4)
2327 (goto-char p)
6c389151 2328 (forward-word 2)
db133cb6
RS
2329 (end-of-line)
2330 (setq really-delete t))
6c389151 2331 (forward-word 1))))
db133cb6
RS
2332 (if over
2333 (progn
2334 (setq p (point))
2335 (insert "\n\n=item \n\n\n\n"
2336 "=back")
2337 (cperl-ensure-newlines 2)
2338 (goto-char p)
6c389151 2339 (forward-word 1)
db133cb6
RS
2340 (end-of-line)
2341 (setq really-delete t)))
2342 (if (and delete really-delete)
f83d2997
KH
2343 (cperl-putback-char cperl-del-back-ch))))))
2344
2345(defun cperl-electric-else ()
db133cb6
RS
2346 "Insert a construction appropriate after a keyword.
2347Help message may be switched off by setting `cperl-message-electric-keyword'
2348to nil."
f83d2997
KH
2349 (let ((beg (save-excursion (beginning-of-line) (point))))
2350 (and (save-excursion
2351 (backward-sexp 1)
2352 (cperl-after-expr-p nil "{;:"))
5c8b7eaf
SS
2353 (save-excursion
2354 (not
f83d2997 2355 (re-search-backward
5bd52f0e 2356 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
f83d2997
KH
2357 beg t)))
2358 (save-excursion (or (not (re-search-backward "^=" nil t))
db133cb6
RS
2359 (looking-at "=cut")
2360 (and cperl-use-syntax-table-text-property
2361 (not (eq (get-text-property (point)
2362 'syntax-type)
2363 'pod)))))
f83d2997
KH
2364 (progn
2365 (cperl-indent-line)
2366 ;;(insert " {\n\n}")
2367 (cond
2368 (cperl-extra-newline-before-brace
2369 (insert "\n")
2370 (insert "{")
2371 (cperl-indent-line)
2372 (insert "\n\n}"))
2373 (t
83261a2f 2374 (insert " {\n\n}")))
f83d2997
KH
2375 (or (looking-at "[ \t]\\|$") (insert " "))
2376 (cperl-indent-line)
2377 (forward-line -1)
2378 (cperl-indent-line)
db133cb6
RS
2379 (cperl-putback-char cperl-del-back-ch)
2380 (setq this-command 'cperl-electric-else)
2381 (if cperl-message-electric-keyword
2382 (message "Precede char by C-q to avoid expansion"))))))
f83d2997
KH
2383
2384(defun cperl-linefeed ()
db133cb6
RS
2385 "Go to end of line, open a new line and indent appropriately.
2386If in POD, insert appropriate lines."
f83d2997
KH
2387 (interactive)
2388 (let ((beg (save-excursion (beginning-of-line) (point)))
2389 (end (save-excursion (end-of-line) (point)))
db133cb6 2390 (pos (point)) start over cut res)
f83d2997 2391 (if (and ; Check if we need to split:
5c8b7eaf 2392 ; i.e., on a boundary and inside "{...}"
f83d2997 2393 (save-excursion (cperl-to-comment-or-eol)
83261a2f 2394 (>= (point) pos)) ; Not in a comment
f83d2997
KH
2395 (or (save-excursion
2396 (skip-chars-backward " \t" beg)
2397 (forward-char -1)
2398 (looking-at "[;{]")) ; After { or ; + spaces
2399 (looking-at "[ \t]*}") ; Before }
2400 (re-search-forward "\\=[ \t]*;" end t)) ; Before spaces + ;
2401 (save-excursion
2402 (and
5c8b7eaf 2403 (eq (car (parse-partial-sexp pos end -1)) -1)
f83d2997
KH
2404 ; Leave the level of parens
2405 (looking-at "[,; \t]*\\($\\|#\\)") ; Comma to allow anon subr
2406 ; Are at end
6c389151 2407 (cperl-after-block-p (point-min))
f83d2997
KH
2408 (progn
2409 (backward-sexp 1)
2410 (setq start (point-marker))
db133cb6 2411 (<= start pos))))) ; Redundant? Are after the
f83d2997
KH
2412 ; start of parens group.
2413 (progn
2414 (skip-chars-backward " \t")
2415 (or (memq (preceding-char) (append ";{" nil))
2416 (insert ";"))
2417 (insert "\n")
2418 (forward-line -1)
2419 (cperl-indent-line)
2420 (goto-char start)
2421 (or (looking-at "{[ \t]*$") ; If there is a statement
2422 ; before, move it to separate line
2423 (progn
2424 (forward-char 1)
2425 (insert "\n")
2426 (cperl-indent-line)))
2427 (forward-line 1) ; We are on the target line
2428 (cperl-indent-line)
2429 (beginning-of-line)
2430 (or (looking-at "[ \t]*}[,; \t]*$") ; If there is a statement
83261a2f 2431 ; after, move it to separate line
f83d2997
KH
2432 (progn
2433 (end-of-line)
2434 (search-backward "}" beg)
2435 (skip-chars-backward " \t")
2436 (or (memq (preceding-char) (append ";{" nil))
2437 (insert ";"))
2438 (insert "\n")
2439 (cperl-indent-line)
2440 (forward-line -1)))
5c8b7eaf 2441 (forward-line -1) ; We are on the line before target
f83d2997
KH
2442 (end-of-line)
2443 (newline-and-indent))
db133cb6 2444 (end-of-line) ; else - no splitting
f83d2997
KH
2445 (cond
2446 ((and (looking-at "\n[ \t]*{$")
2447 (save-excursion
2448 (skip-chars-backward " \t")
2449 (eq (preceding-char) ?\)))) ; Probably if () {} group
83261a2f 2450 ; with an extra newline.
f83d2997
KH
2451 (forward-line 2)
2452 (cperl-indent-line))
db133cb6
RS
2453 ((save-excursion ; In POD header
2454 (forward-paragraph -1)
2455 ;; (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\b")
2456 ;; We are after \n now, so look for the rest
2457 (if (looking-at "\\(\\`\n?\\|\n\\)=\\sw+")
5c8b7eaf 2458 (progn
db133cb6
RS
2459 (setq cut (looking-at "\\(\\`\n?\\|\n\\)=cut\\>"))
2460 (setq over (looking-at "\\(\\`\n?\\|\n\\)=over\\>"))
2461 t)))
2462 (if (and over
2463 (progn
2464 (forward-paragraph -1)
2465 (forward-word 1)
2466 (setq pos (point))
2467 (setq cut (buffer-substring (point)
2468 (save-excursion
2469 (end-of-line)
2470 (point))))
2471 (delete-char (- (save-excursion (end-of-line) (point))
2472 (point)))
2473 (setq res (expand-abbrev))
2474 (save-excursion
2475 (goto-char pos)
2476 (insert cut))
2477 res))
2478 nil
2479 (cperl-ensure-newlines (if cut 2 4))
2480 (forward-line 2)))
2481 ((get-text-property (point) 'in-pod) ; In POD section
2482 (cperl-ensure-newlines 4)
2483 (forward-line 2))
f83d2997
KH
2484 ((looking-at "\n[ \t]*$") ; Next line is empty - use it.
2485 (forward-line 1)
2486 (cperl-indent-line))
2487 (t
2488 (newline-and-indent))))))
2489
2490(defun cperl-electric-semi (arg)
2491 "Insert character and correct line's indentation."
2492 (interactive "P")
2493 (if cperl-auto-newline
2494 (cperl-electric-terminator arg)
6c389151
SM
2495 (self-insert-command (prefix-numeric-value arg))
2496 (if cperl-autoindent-on-semi
2497 (cperl-indent-line))))
f83d2997
KH
2498
2499(defun cperl-electric-terminator (arg)
2500 "Insert character and correct line's indentation."
2501 (interactive "P")
83261a2f
SM
2502 (let ((end (point))
2503 (auto (and cperl-auto-newline
2504 (or (not (eq last-command-char ?:))
2505 cperl-auto-newline-after-colon)))
2506 insertpos)
5c8b7eaf 2507 (if (and ;;(not arg)
f83d2997
KH
2508 (eolp)
2509 (not (save-excursion
2510 (beginning-of-line)
2511 (skip-chars-forward " \t")
2512 (or
2513 ;; Ignore in comment lines
2514 (= (following-char) ?#)
2515 ;; Colon is special only after a label
2516 ;; So quickly rule out most other uses of colon
2517 ;; and do no indentation for them.
2518 (and (eq last-command-char ?:)
2519 (save-excursion
2520 (forward-word 1)
2521 (skip-chars-forward " \t")
2522 (and (< (point) end)
2523 (progn (goto-char (- end 1))
2524 (not (looking-at ":"))))))
2525 (progn
2526 (beginning-of-defun)
2527 (let ((pps (parse-partial-sexp (point) end)))
2528 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
2529 (progn
2530 (self-insert-command (prefix-numeric-value arg))
2531 ;;(forward-char -1)
2532 (if auto (setq insertpos (point-marker)))
2533 ;;(forward-char 1)
2534 (cperl-indent-line)
2535 (if auto
2536 (progn
2537 (newline)
2538 (cperl-indent-line)))
f83d2997
KH
2539 (save-excursion
2540 (if insertpos (goto-char (1- (marker-position insertpos)))
2541 (forward-char -1))
2542 (delete-char 1))))
2543 (if insertpos
2544 (save-excursion
2545 (goto-char insertpos)
2546 (self-insert-command (prefix-numeric-value arg)))
2547 (self-insert-command (prefix-numeric-value arg)))))
2548
2549(defun cperl-electric-backspace (arg)
f739b53b
SM
2550 "Backspace, or remove the whitespace around the point inserted by an electric
2551key. Will untabify if `cperl-electric-backspace-untabify' is non-nil."
f83d2997 2552 (interactive "p")
5c8b7eaf
SS
2553 (if (and cperl-auto-newline
2554 (memq last-command '(cperl-electric-semi
f83d2997
KH
2555 cperl-electric-terminator
2556 cperl-electric-lbrace))
b5b0cb34 2557 (memq (preceding-char) '(?\s ?\t ?\n)))
f83d2997 2558 (let (p)
5c8b7eaf 2559 (if (eq last-command 'cperl-electric-lbrace)
f83d2997
KH
2560 (skip-chars-forward " \t\n"))
2561 (setq p (point))
2562 (skip-chars-backward " \t\n")
2563 (delete-region (point) p))
db133cb6
RS
2564 (and (eq last-command 'cperl-electric-else)
2565 ;; We are removing the whitespace *inside* cperl-electric-else
2566 (setq this-command 'cperl-electric-else-really))
5c8b7eaf 2567 (if (and cperl-auto-newline
db133cb6 2568 (eq last-command 'cperl-electric-else-really)
b5b0cb34 2569 (memq (preceding-char) '(?\s ?\t ?\n)))
db133cb6
RS
2570 (let (p)
2571 (skip-chars-forward " \t\n")
2572 (setq p (point))
2573 (skip-chars-backward " \t\n")
2574 (delete-region (point) p))
f739b53b
SM
2575 (if cperl-electric-backspace-untabify
2576 (backward-delete-char-untabify arg)
2577 (delete-backward-char arg)))))
f83d2997 2578
d6156ce8
KS
2579(put 'cperl-electric-backspace 'delete-selection 'supersede)
2580
4ab89e7b 2581(defun cperl-inside-parens-p () ;; NOT USED????
f83d2997
KH
2582 (condition-case ()
2583 (save-excursion
2584 (save-restriction
2585 (narrow-to-region (point)
2586 (progn (beginning-of-defun) (point)))
2587 (goto-char (point-max))
2588 (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
2589 (error nil)))
2590\f
2591(defun cperl-indent-command (&optional whole-exp)
2592 "Indent current line as Perl code, or in some cases insert a tab character.
5c8b7eaf 2593If `cperl-tab-always-indent' is non-nil (the default), always indent current
db133cb6 2594line. Otherwise, indent the current line only if point is at the left margin
f83d2997
KH
2595or in the line's indentation; otherwise insert a tab.
2596
2597A numeric argument, regardless of its value,
2598means indent rigidly all the lines of the expression starting after point
2599so that this line becomes properly indented.
2600The relative indentation among the lines of the expression are preserved."
2601 (interactive "P")
5bd52f0e 2602 (cperl-update-syntaxification (point) (point))
f83d2997
KH
2603 (if whole-exp
2604 ;; If arg, always indent this line as Perl
2605 ;; and shift remaining lines of expression the same amount.
2606 (let ((shift-amt (cperl-indent-line))
2607 beg end)
2608 (save-excursion
2609 (if cperl-tab-always-indent
2610 (beginning-of-line))
2611 (setq beg (point))
2612 (forward-sexp 1)
2613 (setq end (point))
2614 (goto-char beg)
2615 (forward-line 1)
2616 (setq beg (point)))
db133cb6 2617 (if (and shift-amt (> end beg))
f83d2997
KH
2618 (indent-code-rigidly beg end shift-amt "#")))
2619 (if (and (not cperl-tab-always-indent)
2620 (save-excursion
2621 (skip-chars-backward " \t")
2622 (not (bolp))))
2623 (insert-tab)
2624 (cperl-indent-line))))
2625
5bd52f0e 2626(defun cperl-indent-line (&optional parse-data)
f83d2997
KH
2627 "Indent current line as Perl code.
2628Return the amount the indentation changed by."
83261a2f
SM
2629 (let ((case-fold-search nil)
2630 (pos (- (point-max) (point)))
2631 indent i beg shift-amt)
5bd52f0e 2632 (setq indent (cperl-calculate-indent parse-data)
db133cb6 2633 i indent)
f83d2997
KH
2634 (beginning-of-line)
2635 (setq beg (point))
2636 (cond ((or (eq indent nil) (eq indent t))
db133cb6 2637 (setq indent (current-indentation) i nil))
f83d2997
KH
2638 ;;((eq indent t) ; Never?
2639 ;; (setq indent (cperl-calculate-indent-within-comment)))
2640 ;;((looking-at "[ \t]*#")
2641 ;; (setq indent 0))
2642 (t
2643 (skip-chars-forward " \t")
2644 (if (listp indent) (setq indent (car indent)))
82d9a08d
SM
2645 (cond ((and (looking-at "[A-Za-z_][A-Za-z_0-9]*:[^:]")
2646 (not (looking-at "[smy]:\\|tr:")))
f83d2997
KH
2647 (and (> indent 0)
2648 (setq indent (max cperl-min-label-indent
2649 (+ indent cperl-label-offset)))))
2650 ((= (following-char) ?})
2651 (setq indent (- indent cperl-indent-level)))
2652 ((memq (following-char) '(?\) ?\])) ; To line up with opening paren.
2653 (setq indent (+ indent cperl-close-paren-offset)))
2654 ((= (following-char) ?{)
2655 (setq indent (+ indent cperl-brace-offset))))))
2656 (skip-chars-forward " \t")
db133cb6
RS
2657 (setq shift-amt (and i (- indent (current-column))))
2658 (if (or (not shift-amt)
2659 (zerop shift-amt))
f83d2997
KH
2660 (if (> (- (point-max) pos) (point))
2661 (goto-char (- (point-max) pos)))
4ab89e7b
SM
2662 ;;;(delete-region beg (point))
2663 ;;;(indent-to indent)
2664 (cperl-make-indent indent)
f83d2997
KH
2665 ;; If initial point was within line's indentation,
2666 ;; position after the indentation. Else stay at same point in text.
2667 (if (> (- (point-max) pos) (point))
2668 (goto-char (- (point-max) pos))))
2669 shift-amt))
2670
2671(defun cperl-after-label ()
2672 ;; Returns true if the point is after label. Does not do save-excursion.
2673 (and (eq (preceding-char) ?:)
2674 (memq (char-syntax (char-after (- (point) 2)))
2675 '(?w ?_))
2676 (progn
2677 (backward-sexp)
2678 (looking-at "[a-zA-Z_][a-zA-Z0-9_]*:[^:]"))))
2679
2680(defun cperl-get-state (&optional parse-start start-state)
5bd52f0e
RS
2681 ;; returns list (START STATE DEPTH PRESTART),
2682 ;; START is a good place to start parsing, or equal to
5c8b7eaf 2683 ;; PARSE-START if preset,
5bd52f0e
RS
2684 ;; STATE is what is returned by `parse-partial-sexp'.
2685 ;; DEPTH is true is we are immediately after end of block
2686 ;; which contains START.
2687 ;; PRESTART is the position basing on which START was found.
f83d2997
KH
2688 (save-excursion
2689 (let ((start-point (point)) depth state start prestart)
5bd52f0e
RS
2690 (if (and parse-start
2691 (<= parse-start start-point))
f83d2997 2692 (goto-char parse-start)
5bd52f0e
RS
2693 (beginning-of-defun)
2694 (setq start-state nil))
f83d2997
KH
2695 (setq prestart (point))
2696 (if start-state nil
2697 ;; Try to go out, if sub is not on the outermost level
2698 (while (< (point) start-point)
2699 (setq start (point) parse-start start depth nil
2700 state (parse-partial-sexp start start-point -1))
2701 (if (> (car state) -1) nil
2702 ;; The current line could start like }}}, so the indentation
2703 ;; corresponds to a different level than what we reached
2704 (setq depth t)
2705 (beginning-of-line 2))) ; Go to the next line.
2706 (if start (goto-char start))) ; Not at the start of file
2707 (setq start (point))
f83d2997
KH
2708 (or state (setq state (parse-partial-sexp start start-point -1 nil start-state)))
2709 (list start state depth prestart))))
2710
f83d2997
KH
2711(defvar cperl-look-for-prop '((pod in-pod) (here-doc-delim here-doc-group)))
2712
4ab89e7b
SM
2713(defun cperl-beginning-of-property (p prop &optional lim)
2714 "Given that P has a property PROP, find where the property starts.
2715Will not look before LIM."
2716 ;;; XXXX What to do at point-max???
2717 (or (previous-single-property-change (cperl-1+ p) prop lim)
2718 (point-min))
2719;;; (cond ((eq p (point-min))
2720;;; p)
2721;;; ((and lim (<= p lim))
2722;;; p)
2723;;; ((not (get-text-property (1- p) prop))
2724;;; p)
2725;;; (t (or (previous-single-property-change p look-prop lim)
2726;;; (point-min))))
2727 )
2728
2729(defun cperl-sniff-for-indent (&optional parse-data) ; was parse-start
2730 ;; Old workhorse for calculation of indentation; the major problem
2731 ;; is that it mixes the sniffer logic to understand what the current line
2732 ;; MEANS with the logic to actually calculate where to indent it.
2733 ;; The latter part should be eventually moved to `cperl-calculate-indent';
2734 ;; actually, this is mostly done now...
f739b53b 2735 (cperl-update-syntaxification (point) (point))
4ab89e7b
SM
2736 (let ((res (get-text-property (point) 'syntax-type)))
2737 (save-excursion
2738 (cond
2739 ((and (memq res '(pod here-doc here-doc-delim format))
2740 (not (get-text-property (point) 'indentable)))
2741 (vector res))
2742 ;; before start of POD - whitespace found since do not have 'pod!
2743 ((looking-at "[ \t]*\n=")
2744 (error "Spaces before POD section!"))
2745 ((and (not cperl-indent-left-aligned-comments)
2746 (looking-at "^#"))
2747 [comment-special:at-beginning-of-line])
2748 ((get-text-property (point) 'in-pod)
2749 [in-pod])
2750 (t
2751 (beginning-of-line)
2752 (let* ((indent-point (point))
2753 (char-after-pos (save-excursion
2754 (skip-chars-forward " \t")
2755 (point)))
2756 (char-after (char-after char-after-pos))
2757 (pre-indent-point (point))
2758 p prop look-prop is-block delim)
2759 (save-excursion ; Know we are not in POD, find appropriate pos before
83261a2f
SM
2760 (cperl-backward-to-noncomment nil)
2761 (setq p (max (point-min) (1- (point)))
2762 prop (get-text-property p 'syntax-type)
2763 look-prop (or (nth 1 (assoc prop cperl-look-for-prop))
2764 'syntax-type))
2765 (if (memq prop '(pod here-doc format here-doc-delim))
2766 (progn
4ab89e7b 2767 (goto-char (cperl-beginning-of-property p look-prop))
83261a2f 2768 (beginning-of-line)
4ab89e7b
SM
2769 (setq pre-indent-point (point)))))
2770 (goto-char pre-indent-point) ; Orig line skipping preceeding pod/etc
2771 (let* ((case-fold-search nil)
2772 (s-s (cperl-get-state (car parse-data) (nth 1 parse-data)))
2773 (start (or (nth 2 parse-data) ; last complete sexp terminated
2774 (nth 0 s-s))) ; Good place to start parsing
2775 (state (nth 1 s-s))
2776 (containing-sexp (car (cdr state)))
2777 old-indent)
2778 (if (and
2779 ;;containing-sexp ;; We are buggy at toplevel :-(
2780 parse-data)
2781 (progn
2782 (setcar parse-data pre-indent-point)
2783 (setcar (cdr parse-data) state)
2784 (or (nth 2 parse-data)
2785 (setcar (cddr parse-data) start))
2786 ;; Before this point: end of statement
2787 (setq old-indent (nth 3 parse-data))))
2788 (cond ((get-text-property (point) 'indentable)
2789 ;; indent to "after" the surrounding open
2790 ;; (same offset as `cperl-beautify-regexp-piece'),
2791 ;; skip blanks if we do not close the expression.
2792 (setq delim ; We do not close the expression
2793 (get-text-property
2794 (cperl-1+ char-after-pos) 'indentable)
2795 p (1+ (cperl-beginning-of-property
2796 (point) 'indentable))
2797 is-block ; misused for: preceeding line in REx
2798 (save-excursion ; Find preceeding line
2799 (cperl-backward-to-noncomment p)
2800 (beginning-of-line)
2801 (if (<= (point) p)
2802 (progn ; get indent from the first line
2803 (goto-char p)
2804 (skip-chars-forward " \t")
2805 (if (memq (char-after (point))
2806 (append "#\n" nil))
2807 nil ; Can't use intentation of this line...
2808 (point)))
2809 (skip-chars-forward " \t")
2810 (point)))
2811 prop (parse-partial-sexp p char-after-pos))
2812 (cond ((not delim) ; End the REx, ignore is-block
2813 (vector 'indentable 'terminator p is-block))
2814 (is-block ; Indent w.r.t. preceeding line
2815 (vector 'indentable 'cont-line char-after-pos
2816 is-block char-after p))
2817 (t ; No preceeding line...
2818 (vector 'indentable 'first-line p))))
2819 ((get-text-property char-after-pos 'REx-part2)
2820 (vector 'REx-part2 (point)))
4ab89e7b 2821 ((nth 4 state)
82d9a08d
SM
2822 [comment])
2823 ((nth 3 state)
4ab89e7b
SM
2824 [string])
2825 ;; XXXX Do we need to special-case this?
2826 ((null containing-sexp)
2827 ;; Line is at top level. May be data or function definition,
2828 ;; or may be function argument declaration.
2829 ;; Indent like the previous top level line
2830 ;; unless that ends in a closeparen without semicolon,
2831 ;; in which case this line is the first argument decl.
2832 (skip-chars-forward " \t")
2833 (cperl-backward-to-noncomment (or old-indent (point-min)))
2834 (setq state
2835 (or (bobp)
2836 (eq (point) old-indent) ; old-indent was at comment
2837 (eq (preceding-char) ?\;)
2838 ;; Had ?\) too
2839 (and (eq (preceding-char) ?\})
2840 (cperl-after-block-and-statement-beg
2841 (point-min))) ; Was start - too close
2842 (memq char-after (append ")]}" nil))
2843 (and (eq (preceding-char) ?\:) ; label
83261a2f
SM
2844 (progn
2845 (forward-sexp -1)
4ab89e7b
SM
2846 (skip-chars-backward " \t")
2847 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*[ \t]*:")))
2848 (get-text-property (point) 'first-format-line)))
cb5bf6ba 2849
4ab89e7b
SM
2850 ;; Look at previous line that's at column 0
2851 ;; to determine whether we are in top-level decls
2852 ;; or function's arg decls. Set basic-indent accordingly.
2853 ;; Now add a little if this is a continuation line.
2854 (and state
2855 parse-data
2856 (not (eq char-after ?\C-j))
2857 (setcdr (cddr parse-data)
2858 (list pre-indent-point)))
2859 (vector 'toplevel start char-after state (nth 2 s-s)))
2860 ((not
2861 (or (setq is-block
2862 (and (setq delim (= (char-after containing-sexp) ?{))
2863 (save-excursion ; Is it a hash?
2864 (goto-char containing-sexp)
2865 (cperl-block-p))))
2866 cperl-indent-parens-as-block))
2867 ;; group is an expression, not a block:
2868 ;; indent to just after the surrounding open parens,
2869 ;; skip blanks if we do not close the expression.
2870 (goto-char (1+ containing-sexp))
2871 (or (memq char-after
2872 (append (if delim "}" ")]}") nil))
2873 (looking-at "[ \t]*\\(#\\|$\\)")
2874 (skip-chars-forward " \t"))
2875 (setq old-indent (point)) ; delim=is-brace
2876 (vector 'in-parens char-after (point) delim containing-sexp))
2877 (t
2878 ;; Statement level. Is it a continuation or a new statement?
2879 ;; Find previous non-comment character.
2880 (goto-char pre-indent-point) ; Skip one level of POD/etc
2881 (cperl-backward-to-noncomment containing-sexp)
2882 ;; Back up over label lines, since they don't
2883 ;; affect whether our line is a continuation.
2884 ;; (Had \, too)
2885 (while;;(or (eq (preceding-char) ?\,)
2886 (and (eq (preceding-char) ?:)
2887 (or;;(eq (char-after (- (point) 2)) ?\') ; ????
2888 (memq (char-syntax (char-after (- (point) 2)))
2889 '(?w ?_))))
2890 ;;)
2891 ;; This is always FALSE?
2892 (if (eq (preceding-char) ?\,)
2893 ;; Will go to beginning of line, essentially.
2894 ;; Will ignore embedded sexpr XXXX.
2895 (cperl-backward-to-start-of-continued-exp containing-sexp))
2896 (beginning-of-line)
2897 (cperl-backward-to-noncomment containing-sexp))
2898 ;; Now we get non-label preceeding the indent point
2899 (if (not (or (eq (1- (point)) containing-sexp)
2900 (memq (preceding-char)
2901 (append (if is-block " ;{" " ,;{") '(nil)))
2902 (and (eq (preceding-char) ?\})
2903 (cperl-after-block-and-statement-beg
2904 containing-sexp))
2905 (get-text-property (point) 'first-format-line)))
2906 ;; This line is continuation of preceding line's statement;
2907 ;; indent `cperl-continued-statement-offset' more than the
2908 ;; previous line of the statement.
2909 ;;
2910 ;; There might be a label on this line, just
2911 ;; consider it bad style and ignore it.
2912 (progn
2913 (cperl-backward-to-start-of-continued-exp containing-sexp)
2914 (vector 'continuation (point) char-after is-block delim))
2915 ;; This line starts a new statement.
2916 ;; Position following last unclosed open brace
2917 (goto-char containing-sexp)
2918 ;; Is line first statement after an open-brace?
2919 (or
2920 ;; If no, find that first statement and indent like
2921 ;; it. If the first statement begins with label, do
2922 ;; not believe when the indentation of the label is too
2923 ;; small.
2924 (save-excursion
2925 (forward-char 1)
2926 (let ((colon-line-end 0))
2927 (while
2928 (progn (skip-chars-forward " \t\n")
82d9a08d
SM
2929 ;; s: foo : bar :x is NOT label
2930 (and (looking-at "#\\|\\([a-zA-Z0-9_$]+\\):[^:]\\|=[a-zA-Z]")
2931 (not (looking-at "[sym]:\\|tr:"))))
4ab89e7b
SM
2932 ;; Skip over comments and labels following openbrace.
2933 (cond ((= (following-char) ?\#)
2934 (forward-line 1))
2935 ((= (following-char) ?\=)
2936 (goto-char
2937 (or (next-single-property-change (point) 'in-pod)
2938 (point-max)))) ; do not loop if no syntaxification
2939 ;; label:
2940 (t
2941 (save-excursion (end-of-line)
2942 (setq colon-line-end (point)))
2943 (search-forward ":"))))
2944 ;; We are at beginning of code (NOT label or comment)
2945 ;; First, the following code counts
2946 ;; if it is before the line we want to indent.
2947 (and (< (point) indent-point)
2948 (vector 'have-prev-sibling (point) colon-line-end
2949 containing-sexp))))
2950 (progn
2951 ;; If no previous statement,
2952 ;; indent it relative to line brace is on.
2953
2954 ;; For open-braces not the first thing in a line,
2955 ;; add in cperl-brace-imaginary-offset.
2956
2957 ;; If first thing on a line: ?????
2958 ;; Move back over whitespace before the openbrace.
2959 (setq ; brace first thing on a line
2960 old-indent (progn (skip-chars-backward " \t") (bolp)))
2961 ;; Should we indent w.r.t. earlier than start?
2962 ;; Move to start of control group, possibly on a different line
2963 (or cperl-indent-wrt-brace
2964 (cperl-backward-to-noncomment (point-min)))
2965 ;; If the openbrace is preceded by a parenthesized exp,
2966 ;; move to the beginning of that;
2967 (if (eq (preceding-char) ?\))
2968 (progn
2969 (forward-sexp -1)
2970 (cperl-backward-to-noncomment (point-min))))
2971 ;; In the case it starts a subroutine, indent with
2972 ;; respect to `sub', not with respect to the
2973 ;; first thing on the line, say in the case of
2974 ;; anonymous sub in a hash.
2975 (if (and;; Is it a sub in group starting on this line?
2976 (cond ((get-text-property (point) 'attrib-group)
2977 (goto-char (cperl-beginning-of-property
2978 (point) 'attrib-group)))
2979 ((eq (preceding-char) ?b)
2980 (forward-sexp -1)
2981 (looking-at "sub\\>")))
2982 (setq p (nth 1 ; start of innermost containing list
2983 (parse-partial-sexp
2984 (save-excursion (beginning-of-line)
2985 (point))
2986 (point)))))
2987 (progn
2988 (goto-char (1+ p)) ; enclosing block on the same line
2989 (skip-chars-forward " \t")
2990 (vector 'code-start-in-block containing-sexp char-after
2991 (and delim (not is-block)) ; is a HASH
2992 old-indent ; brace first thing on a line
2993 t (point) ; have something before...
2994 )
2995 ;;(current-column)
2996 )
2997 ;; Get initial indentation of the line we are on.
2998 ;; If line starts with label, calculate label indentation
2999 (vector 'code-start-in-block containing-sexp char-after
3000 (and delim (not is-block)) ; is a HASH
3001 old-indent ; brace first thing on a line
82d9a08d 3002 nil (point))))))))))))))) ; nothing interesting before
4ab89e7b
SM
3003
3004(defvar cperl-indent-rules-alist
3005 '((pod nil) ; via `syntax-type' property
3006 (here-doc nil) ; via `syntax-type' property
3007 (here-doc-delim nil) ; via `syntax-type' property
3008 (format nil) ; via `syntax-type' property
3009 (in-pod nil) ; via `in-pod' property
3010 (comment-special:at-beginning-of-line nil)
3011 (string t)
3012 (comment nil))
3013 "Alist of indentation rules for CPerl mode.
3014The values mean:
3015 nil: do not indent;
82d9a08d 3016 number: add this amount of indentation.")
4ab89e7b
SM
3017
3018(defun cperl-calculate-indent (&optional parse-data) ; was parse-start
3019 "Return appropriate indentation for current line as Perl code.
3020In usual case returns an integer: the column to indent to.
3021Returns nil if line starts inside a string, t if in a comment.
3022
3023Will not correct the indentation for labels, but will correct it for braces
3024and closing parentheses and brackets."
3025 ;; This code is still a broken architecture: in some cases we need to
3026 ;; compensate for some modifications which `cperl-indent-line' will add later
3027 (save-excursion
3028 (let ((i (cperl-sniff-for-indent parse-data)) what p)
3029 (cond
3030 ;;((or (null i) (eq i t) (numberp i))
3031 ;; i)
3032 ((vectorp i)
3033 (setq what (assoc (elt i 0) cperl-indent-rules-alist))
3034 (cond
3035 (what (cadr what)) ; Load from table
3036 ;;
3037 ;; Indenters for regular expressions with //x and qw()
3038 ;;
3039 ((eq 'REx-part2 (elt i 0)) ;; [self start] start of /REP in s//REP/x
3040 (goto-char (elt i 1))
3041 (condition-case nil ; Use indentation of the 1st part
3042 (forward-sexp -1))
3043 (current-column))
3044 ((eq 'indentable (elt i 0)) ; Indenter for REGEXP qw() etc
3045 (cond ;;; [indentable terminator start-pos is-block]
3046 ((eq 'terminator (elt i 1)) ; Lone terminator of "indentable string"
3047 (goto-char (elt i 2)) ; After opening parens
3048 (1- (current-column)))
3049 ((eq 'first-line (elt i 1)); [indentable first-line start-pos]
3050 (goto-char (elt i 2))
3051 (+ (or cperl-regexp-indent-step cperl-indent-level)
3052 -1
3053 (current-column)))
3054 ((eq 'cont-line (elt i 1)); [indentable cont-line pos prev-pos first-char start-pos]
3055 ;; Indent as the level after closing parens
3056 (goto-char (elt i 2)) ; indent line
3057 (skip-chars-forward " \t)") ; Skip closing parens
3058 (setq p (point))
3059 (goto-char (elt i 3)) ; previous line
3060 (skip-chars-forward " \t)") ; Skip closing parens
3061 ;; Number of parens in between:
3062 (setq p (nth 0 (parse-partial-sexp (point) p))
3063 what (elt i 4)) ; First char on current line
3064 (goto-char (elt i 3)) ; previous line
3065 (+ (* p (or cperl-regexp-indent-step cperl-indent-level))
3066 (cond ((eq what ?\) )
3067 (- cperl-close-paren-offset)) ; compensate
3068 ((eq what ?\| )
3069 (- (or cperl-regexp-indent-step cperl-indent-level)))
3070 (t 0))
3071 (if (eq (following-char) ?\| )
3072 (or cperl-regexp-indent-step cperl-indent-level)
3073 0)
3074 (current-column)))
3075 (t
3076 (error "Unrecognized value of indent: %s" i))))
3077 ;;
3078 ;; Indenter for stuff at toplevel
3079 ;;
3080 ((eq 'toplevel (elt i 0)) ;; [toplevel start char-after state immed-after-block]
3081 (+ (save-excursion ; To beg-of-defun, or end of last sexp
3082 (goto-char (elt i 1)) ; start = Good place to start parsing
cb5bf6ba 3083 (- (current-indentation) ;
4ab89e7b
SM
3084 (if (elt i 4) cperl-indent-level 0))) ; immed-after-block
3085 (if (eq (elt i 2) ?{) cperl-continued-brace-offset 0) ; char-after
3086 ;; Look at previous line that's at column 0
3087 ;; to determine whether we are in top-level decls
3088 ;; or function's arg decls. Set basic-indent accordingly.
3089 ;; Now add a little if this is a continuation line.
3090 (if (elt i 3) ; state (XXX What is the semantic???)
3091 0
3092 cperl-continued-statement-offset)))
3093 ;;
3094 ;; Indenter for stuff in "parentheses" (or brackets, braces-as-hash)
3095 ;;
3096 ((eq 'in-parens (elt i 0))
3097 ;; in-parens char-after old-indent-point is-brace containing-sexp
3098
3099 ;; group is an expression, not a block:
3100 ;; indent to just after the surrounding open parens,
3101 ;; skip blanks if we do not close the expression.
3102 (+ (progn
3103 (goto-char (elt i 2)) ; old-indent-point
3104 (current-column))
3105 (if (and (elt i 3) ; is-brace
3106 (eq (elt i 1) ?\})) ; char-after
3107 ;; Correct indentation of trailing ?\}
3108 (+ cperl-indent-level cperl-close-paren-offset)
3109 0)))
3110 ;;
3111 ;; Indenter for continuation lines
3112 ;;
3113 ((eq 'continuation (elt i 0))
3114 ;; [continuation statement-start char-after is-block is-brace]
3115 (goto-char (elt i 1)) ; statement-start
3116 (+ (if (memq (elt i 2) (append "}])" nil)) ; char-after
3117 0 ; Closing parenth
3118 cperl-continued-statement-offset)
3119 (if (or (elt i 3) ; is-block
3120 (not (elt i 4)) ; is-brace
3121 (not (eq (elt i 2) ?\}))) ; char-after
3122 0
3123 ;; Now it is a hash reference
3124 (+ cperl-indent-level cperl-close-paren-offset))
3125 ;; Labels do not take :: ...
3126 (if (looking-at "\\(\\w\\|_\\)+[ \t]*:")
3127 (if (> (current-indentation) cperl-min-label-indent)
3128 (- (current-indentation) cperl-label-offset)
3129 ;; Do not move `parse-data', this should
3130 ;; be quick anyway (this comment comes
3131 ;; from different location):
3132 (cperl-calculate-indent))
3133 (current-column))
3134 (if (eq (elt i 2) ?\{) ; char-after
3135 cperl-continued-brace-offset 0)))
3136 ;;
3137 ;; Indenter for lines in a block which are not leading lines
3138 ;;
3139 ((eq 'have-prev-sibling (elt i 0))
3140 ;; [have-prev-sibling sibling-beg colon-line-end block-start]
82d9a08d
SM
3141 (goto-char (elt i 1)) ; sibling-beg
3142 (if (> (elt i 2) (point)) ; colon-line-end; have label before point
4ab89e7b
SM
3143 (if (> (current-indentation)
3144 cperl-min-label-indent)
3145 (- (current-indentation) cperl-label-offset)
3146 ;; Do not believe: `max' was involved in calculation of indent
3147 (+ cperl-indent-level
3148 (save-excursion
3149 (goto-char (elt i 3)) ; block-start
3150 (current-indentation))))
3151 (current-column)))
3152 ;;
3153 ;; Indenter for the first line in a block
3154 ;;
3155 ((eq 'code-start-in-block (elt i 0))
3156 ;;[code-start-in-block before-brace char-after
3157 ;; is-a-HASH-ref brace-is-first-thing-on-a-line
3158 ;; group-starts-before-start-of-sub start-of-control-group]
3159 (goto-char (elt i 1))
3160 ;; For open brace in column zero, don't let statement
3161 ;; start there too. If cperl-indent-level=0,
3162 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
3163 (+ (if (and (bolp) (zerop cperl-indent-level))
3164 (+ cperl-brace-offset cperl-continued-statement-offset)
3165 cperl-indent-level)
3166 (if (and (elt i 3) ; is-a-HASH-ref
3167 (eq (elt i 2) ?\})) ; char-after: End of a hash reference
3168 (+ cperl-indent-level cperl-close-paren-offset)
3169 0)
3170 ;; Unless openbrace is the first nonwhite thing on the line,
3171 ;; add the cperl-brace-imaginary-offset.
3172 (if (elt i 4) 0 ; brace-is-first-thing-on-a-line
3173 cperl-brace-imaginary-offset)
3174 (progn
3175 (goto-char (elt i 6)) ; start-of-control-group
3176 (if (elt i 5) ; group-starts-before-start-of-sub
3177 (current-column)
3178 ;; Get initial indentation of the line we are on.
3179 ;; If line starts with label, calculate label indentation
3180 (if (save-excursion
3181 (beginning-of-line)
3182 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
3183 (if (> (current-indentation) cperl-min-label-indent)
3184 (- (current-indentation) cperl-label-offset)
3185 ;; Do not move `parse-data', this should
3186 ;; be quick anyway:
3187 (cperl-calculate-indent))
3188 (current-indentation))))))
3189 (t
3190 (error "Unrecognized value of indent: %s" i))))
3191 (t
3192 (error "Got strange value of indent: %s" i))))))
3193
f83d2997
KH
3194(defun cperl-calculate-indent-within-comment ()
3195 "Return the indentation amount for line, assuming that
3196the current line is to be regarded as part of a block comment."
3197 (let (end star-start)
3198 (save-excursion
3199 (beginning-of-line)
3200 (skip-chars-forward " \t")
3201 (setq end (point))
3202 (and (= (following-char) ?#)
3203 (forward-line -1)
3204 (cperl-to-comment-or-eol)
3205 (setq end (point)))
3206 (goto-char end)
3207 (current-column))))
3208
3209
3210(defun cperl-to-comment-or-eol ()
029cb4d5 3211 "Go to position before comment on the current line, or to end of line.
4ab89e7b
SM
3212Returns true if comment is found. In POD will not move the point."
3213 ;; If the line is inside other syntax groups (qq-style strings, HERE-docs)
3214 ;; then looks for literal # or end-of-line.
3215 (let (state stop-in cpoint (lim (progn (end-of-line) (point))) pr e)
3216 (or cperl-font-locking
3217 (cperl-update-syntaxification lim lim))
83261a2f 3218 (beginning-of-line)
4ab89e7b
SM
3219 (if (setq pr (get-text-property (point) 'syntax-type))
3220 (setq e (next-single-property-change (point) 'syntax-type nil (point-max))))
3221 (if (or (eq pr 'pod)
3222 (if (or (not e) (> e lim)) ; deep inside a group
3223 (re-search-forward "\\=[ \t]*\\(#\\|$\\)" lim t)))
83261a2f 3224 (if (eq (preceding-char) ?\#) (progn (backward-char 1) t))
4ab89e7b
SM
3225 ;; Else - need to do it the hard way
3226 (and (and e (<= e lim))
3227 (goto-char e))
83261a2f
SM
3228 (while (not stop-in)
3229 (setq state (parse-partial-sexp (point) lim nil nil nil t))
f83d2997 3230 ; stop at comment
83261a2f
SM
3231 ;; If fails (beginning-of-line inside sexp), then contains not-comment
3232 (if (nth 4 state) ; After `#';
f83d2997
KH
3233 ; (nth 2 state) can be
3234 ; beginning of m,s,qq and so
3235 ; on
83261a2f
SM
3236 (if (nth 2 state)
3237 (progn
3238 (setq cpoint (point))
3239 (goto-char (nth 2 state))
3240 (cond
3241 ((looking-at "\\(s\\|tr\\)\\>")
3242 (or (re-search-forward
3243 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*"
3244 lim 'move)
3245 (setq stop-in t)))
3246 ((looking-at "\\(m\\|q\\([qxwr]\\)?\\)\\>")
3247 (or (re-search-forward
3248 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#"
3249 lim 'move)
3250 (setq stop-in t)))
3251 (t ; It was fair comment
3252 (setq stop-in t) ; Finish
3253 (goto-char (1- cpoint)))))
3254 (setq stop-in t) ; Finish
3255 (forward-char -1))
15ca5699 3256 (setq stop-in t))) ; Finish
83261a2f 3257 (nth 4 state))))
f83d2997 3258
f83d2997
KH
3259(defsubst cperl-modify-syntax-type (at how)
3260 (if (< at (point-max))
3261 (progn
3262 (put-text-property at (1+ at) 'syntax-table how)
4ab89e7b 3263 (put-text-property at (1+ at) 'rear-nonsticky '(syntax-table)))))
f83d2997
KH
3264
3265(defun cperl-protect-defun-start (s e)
3266 ;; C code looks for "^\\s(" to skip comment backward in "hard" situations
3267 (save-excursion
3268 (goto-char s)
3269 (while (re-search-forward "^\\s(" e 'to-end)
3270 (put-text-property (1- (point)) (point) 'syntax-table cperl-st-punct))))
3271
5bd52f0e 3272(defun cperl-commentify (bb e string &optional noface)
5c8b7eaf 3273 (if cperl-use-syntax-table-text-property
5bd52f0e
RS
3274 (if (eq noface 'n) ; Only immediate
3275 nil
f83d2997
KH
3276 ;; We suppose that e is _after_ the end of construction, as after eol.
3277 (setq string (if string cperl-st-sfence cperl-st-cfence))
6c389151
SM
3278 (if (> bb (- e 2))
3279 ;; one-char string/comment?!
3280 (cperl-modify-syntax-type bb cperl-st-punct)
3281 (cperl-modify-syntax-type bb string)
3282 (cperl-modify-syntax-type (1- e) string))
f83d2997 3283 (if (and (eq string cperl-st-sfence) (> (- e 2) bb))
5c8b7eaf 3284 (put-text-property (1+ bb) (1- e)
f83d2997 3285 'syntax-table cperl-string-syntax-table))
5bd52f0e
RS
3286 (cperl-protect-defun-start bb e))
3287 ;; Fontify
3288 (or noface
3289 (not cperl-pod-here-fontify)
3290 (put-text-property bb e 'face (if string 'font-lock-string-face
3291 'font-lock-comment-face)))))
6c389151 3292
5bd52f0e
RS
3293(defvar cperl-starters '(( ?\( . ?\) )
3294 ( ?\[ . ?\] )
3295 ( ?\{ . ?\} )
3296 ( ?\< . ?\> )))
f83d2997 3297
4ab89e7b
SM
3298(defun cperl-cached-syntax-table (st)
3299 "Get a syntax table cached in ST, or create and cache into ST a syntax table.
3300All the entries of the syntax table are \".\", except for a backslash, which
3301is quoting."
3302 (if (car-safe st)
3303 (car st)
3304 (setcar st (make-syntax-table))
3305 (setq st (car st))
3306 (let ((i 0))
3307 (while (< i 256)
3308 (modify-syntax-entry i "." st)
3309 (setq i (1+ i))))
3310 (modify-syntax-entry ?\\ "\\" st)
3311 st))
3312
3313(defun cperl-forward-re (lim end is-2arg st-l err-l argument
f83d2997 3314 &optional ostart oend)
4ab89e7b
SM
3315"Find the end of a regular expression or a stringish construct (q[] etc).
3316The point should be before the starting delimiter.
3317
3318Goes to LIM if none is found. If IS-2ARG is non-nil, assumes that it
3319is s/// or tr/// like expression. If END is nil, generates an error
3320message if needed. If SET-ST is non-nil, will use (or generate) a
3321cached syntax table in ST-L. If ERR-L is non-nil, will store the
3322error message in its CAR (unless it already contains some error
3323message). ARGUMENT should be the name of the construct (used in error
3324messages). OSTART, OEND may be set in recursive calls when processing
3325the second argument of 2ARG construct.
3326
3327Works *before* syntax recognition is done. In IS-2ARG situation may
3328modify syntax-type text property if the situation is too hard."
3329 (let (b starter ender st i i2 go-forward reset-st set-st)
f83d2997
KH
3330 (skip-chars-forward " \t")
3331 ;; ender means matching-char matcher.
5c8b7eaf 3332 (setq b (point)
5bd52f0e
RS
3333 starter (if (eobp) 0 (char-after b))
3334 ender (cdr (assoc starter cperl-starters)))
f83d2997 3335 ;; What if starter == ?\\ ????
4ab89e7b 3336 (setq st (cperl-cached-syntax-table st-l))
f83d2997
KH
3337 (setq set-st t)
3338 ;; Whether we have an intermediate point
3339 (setq i nil)
3340 ;; Prepare the syntax table:
4ab89e7b
SM
3341 (if (not ender) ; m/blah/, s/x//, s/x/y/
3342 (modify-syntax-entry starter "$" st)
3343 (modify-syntax-entry starter (concat "(" (list ender)) st)
3344 (modify-syntax-entry ender (concat ")" (list starter)) st))
f83d2997
KH
3345 (condition-case bb
3346 (progn
5bd52f0e
RS
3347 ;; We use `$' syntax class to find matching stuff, but $$
3348 ;; is recognized the same as $, so we need to check this manually.
f83d2997
KH
3349 (if (and (eq starter (char-after (cperl-1+ b)))
3350 (not ender))
3351 ;; $ has TeXish matching rules, so $$ equiv $...
3352 (forward-char 2)
6c389151 3353 (setq reset-st (syntax-table))
f83d2997
KH
3354 (set-syntax-table st)
3355 (forward-sexp 1)
6c389151
SM
3356 (if (<= (point) (1+ b))
3357 (error "Unfinished regular expression"))
3358 (set-syntax-table reset-st)
3359 (setq reset-st nil)
f83d2997
KH
3360 ;; Now the problem is with m;blah;;
3361 (and (not ender)
3362 (eq (preceding-char)
3363 (char-after (- (point) 2)))
3364 (save-excursion
3365 (forward-char -2)
3366 (= 0 (% (skip-chars-backward "\\\\") 2)))
3367 (forward-char -1)))
5bd52f0e 3368 ;; Now we are after the first part.
f83d2997
KH
3369 (and is-2arg ; Have trailing part
3370 (not ender)
3371 (eq (following-char) starter) ; Empty trailing part
3372 (progn
3373 (or (eq (char-syntax (following-char)) ?.)
3374 ;; Make trailing letter into punctuation
3375 (cperl-modify-syntax-type (point) cperl-st-punct))
3376 (setq is-2arg nil go-forward t))) ; Ignore the tail
3377 (if is-2arg ; Not number => have second part
3378 (progn
3379 (setq i (point) i2 i)
3380 (if ender
b5b0cb34 3381 (if (memq (following-char) '(?\s ?\t ?\n ?\f))
f83d2997
KH
3382 (progn
3383 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
3384 (goto-char (match-end 0))
3385 (skip-chars-forward " \t\n\f"))
3386 (setq i2 (point))))
3387 (forward-char -1))
3388 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
5c8b7eaf 3389 (if ender (modify-syntax-entry ender "." st))
f83d2997 3390 (setq set-st nil)
4ab89e7b 3391 (setq ender (cperl-forward-re lim end nil st-l err-l
5bd52f0e 3392 argument starter ender)
f83d2997
KH
3393 ender (nth 2 ender)))))
3394 (error (goto-char lim)
3395 (setq set-st nil)
6c389151
SM
3396 (if reset-st
3397 (set-syntax-table reset-st))
f83d2997
KH
3398 (or end
3399 (message
5bd52f0e 3400 "End of `%s%s%c ... %c' string/RE not found: %s"
f83d2997
KH
3401 argument
3402 (if ostart (format "%c ... %c" ostart (or oend ostart)) "")
3403 starter (or ender starter) bb)
3404 (or (car err-l) (setcar err-l b)))))
3405 (if set-st
3406 (progn
3407 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
3408 (if ender (modify-syntax-entry ender "." st))))
5bd52f0e 3409 ;; i: have 2 args, after end of the first arg
e7f767c2 3410 ;; i2: start of the second arg, if any (before delim if `ender').
5bd52f0e
RS
3411 ;; ender: the last arg bounded by parens-like chars, the second one of them
3412 ;; starter: the starting delimiter of the first arg
5efe6a56 3413 ;; go-forward: has 2 args, and the second part is empty
f83d2997
KH
3414 (list i i2 ender starter go-forward)))
3415
4ab89e7b
SM
3416(defun cperl-forward-group-in-re (&optional st-l)
3417 "Find the end of a group in a REx.
3418Return the error message (if any). Does not work if delimiter is `)'.
3419Works before syntax recognition is done."
3420 ;; Works *before* syntax recognition is done
3421 (or st-l (setq st-l (list nil))) ; Avoid overwriting '()
3422 (let (st b reset-st)
3423 (condition-case b
3424 (progn
3425 (setq st (cperl-cached-syntax-table st-l))
3426 (modify-syntax-entry ?\( "()" st)
3427 (modify-syntax-entry ?\) ")(" st)
3428 (setq reset-st (syntax-table))
3429 (set-syntax-table st)
3430 (forward-sexp 1))
3431 (error (message
3432 "cperl-forward-group-in-re: error %s" b)))
3433 ;; now restore the initial state
3434 (if st
3435 (progn
3436 (modify-syntax-entry ?\( "." st)
3437 (modify-syntax-entry ?\) "." st)))
3438 (if reset-st
3439 (set-syntax-table reset-st))
3440 b))
3441
3442
83261a2f
SM
3443(defvar font-lock-string-face)
3444;;(defvar font-lock-reference-face)
3445(defvar font-lock-constant-face)
5c8b7eaf 3446(defsubst cperl-postpone-fontification (b e type val &optional now)
5bd52f0e
RS
3447 ;; Do after syntactic fontification?
3448 (if cperl-syntaxify-by-font-lock
3449 (or now (put-text-property b e 'cperl-postpone (cons type val)))
83261a2f 3450 (put-text-property b e type val)))
5bd52f0e
RS
3451
3452;;; Here is how the global structures (those which cannot be
3453;;; recognized locally) are marked:
5c8b7eaf 3454;; a) PODs:
5bd52f0e
RS
3455;; Start-to-end is marked `in-pod' ==> t
3456;; Each non-literal part is marked `syntax-type' ==> `pod'
3457;; Each literal part is marked `syntax-type' ==> `in-pod'
5c8b7eaf 3458;; b) HEREs:
5bd52f0e
RS
3459;; Start-to-end is marked `here-doc-group' ==> t
3460;; The body is marked `syntax-type' ==> `here-doc'
3461;; The delimiter is marked `syntax-type' ==> `here-doc-delim'
5c8b7eaf 3462;; c) FORMATs:
f739b53b
SM
3463;; First line (to =) marked `first-format-line' ==> t
3464;; After-this--to-end is marked `syntax-type' ==> `format'
5c8b7eaf 3465;; d) 'Q'uoted string:
5bd52f0e 3466;; part between markers inclusive is marked `syntax-type' ==> `string'
6c389151 3467;; part between `q' and the first marker is marked `syntax-type' ==> `prestring'
4ab89e7b
SM
3468;; second part of s///e is marked `syntax-type' ==> `multiline'
3469;; e) Attributes of subroutines: `attrib-group' ==> t
3470;; (or 0 if declaration); up to `{' or ';': `syntax-type' => `sub-decl'.
3471;; f) Multiline my/our declaration lists etc: `syntax-type' => `multiline'
3472
3473;;; In addition, some parts of RExes may be marked as `REx-interpolated'
3474;;; (value: 0 in //o, 1 if "interpolated variable" is whole-REx, t otherwise).
5bd52f0e
RS
3475
3476(defun cperl-unwind-to-safe (before &optional end)
3477 ;; if BEFORE, go to the previous start-of-line on each step of unwinding
3478 (let ((pos (point)) opos)
4ab89e7b
SM
3479 (while (and pos (progn
3480 (beginning-of-line)
3481 (get-text-property (setq pos (point)) 'syntax-type)))
3482 (setq opos pos
3483 pos (cperl-beginning-of-property pos 'syntax-type))
3484 (if (eq pos (point-min))
3485 (setq pos nil))
5bd52f0e
RS
3486 (if pos
3487 (if before
3488 (progn
3489 (goto-char (cperl-1- pos))
3490 (beginning-of-line)
3491 (setq pos (point)))
3492 (goto-char (setq pos (cperl-1- pos))))
3493 ;; Up to the start
3494 (goto-char (point-min))))
6c389151
SM
3495 ;; Skip empty lines
3496 (and (looking-at "\n*=")
3497 (/= 0 (skip-chars-backward "\n"))
3498 (forward-char))
3499 (setq pos (point))
5bd52f0e
RS
3500 (if end
3501 ;; Do the same for end, going small steps
4ab89e7b 3502 (save-excursion
5bd52f0e
RS
3503 (while (and end (get-text-property end 'syntax-type))
3504 (setq pos end
4ab89e7b
SM
3505 end (next-single-property-change end 'syntax-type nil (point-max)))
3506 (if end (progn (goto-char end)
3507 (or (bolp) (forward-line 1))
3508 (setq end (point)))))
5bd52f0e
RS
3509 (or end pos)))))
3510
4ab89e7b 3511;;; These are needed for byte-compile (at least with v19)
6c389151 3512(defvar cperl-nonoverridable-face)
4ab89e7b 3513(defvar font-lock-variable-name-face)
6c389151 3514(defvar font-lock-function-name-face)
4ab89e7b
SM
3515(defvar font-lock-keyword-face)
3516(defvar font-lock-builtin-face)
3517(defvar font-lock-type-face)
6c389151 3518(defvar font-lock-comment-face)
4ab89e7b 3519(defvar font-lock-warning-face)
6c389151 3520
4ab89e7b
SM
3521(defun cperl-find-sub-attrs (&optional st-l b-fname e-fname pos)
3522 "Syntaxically mark (and fontify) attributes of a subroutine.
3523Should be called with the point before leading colon of an attribute."
3524 ;; Works *before* syntax recognition is done
3525 (or st-l (setq st-l (list nil))) ; Avoid overwriting '()
3526 (let (st b p reset-st after-first (start (point)) start1 end1)
3527 (condition-case b
3528 (while (looking-at
3529 (concat
3530 "\\(" ; 1=optional? colon
3531 ":" cperl-maybe-white-and-comment-rex ; 2=whitespace/comment?
3532 "\\)"
3533 (if after-first "?" "")
3534 ;; No space between name and paren allowed...
3535 "\\(\\sw+\\)" ; 3=name
3536 "\\((\\)?")) ; 4=optional paren
3537 (and (match-beginning 1)
3538 (cperl-postpone-fontification
3539 (match-beginning 0) (cperl-1+ (match-beginning 0))
3540 'face font-lock-constant-face))
3541 (setq start1 (match-beginning 3) end1 (match-end 3))
3542 (cperl-postpone-fontification start1 end1
3543 'face font-lock-constant-face)
3544 (goto-char end1) ; end or before `('
3545 (if (match-end 4) ; Have attribute arguments...
3546 (progn
3547 (if st nil
3548 (setq st (cperl-cached-syntax-table st-l))
3549 (modify-syntax-entry ?\( "()" st)
3550 (modify-syntax-entry ?\) ")(" st))
3551 (setq reset-st (syntax-table) p (point))
3552 (set-syntax-table st)
3553 (forward-sexp 1)
3554 (set-syntax-table reset-st)
3555 (setq reset-st nil)
3556 (cperl-commentify p (point) t))) ; mark as string
3557 (forward-comment (buffer-size))
3558 (setq after-first t))
3559 (error (message
3560 "L%d: attribute `%s': %s"
3561 (count-lines (point-min) (point))
3562 (and start1 end1 (buffer-substring start1 end1)) b)
3563 (setq start nil)))
3564 (and start
3565 (progn
3566 (put-text-property start (point)
3567 'attrib-group (if (looking-at "{") t 0))
3568 (and pos
3569 (< 1 (count-lines (+ 3 pos) (point))) ; end of `sub'
3570 ;; Apparently, we do not need `multiline': faces added now
3571 (put-text-property (+ 3 pos) (cperl-1+ (point))
3572 'syntax-type 'sub-decl))
3573 (and b-fname ; Fontify here: the following condition
3574 (cperl-postpone-fontification ; is too hard to determine by
3575 b-fname e-fname 'face ; a REx, so do it here
3576 (if (looking-at "{")
3577 font-lock-function-name-face
3578 font-lock-variable-name-face)))))
3579 ;; now restore the initial state
3580 (if st
3581 (progn
3582 (modify-syntax-entry ?\( "." st)
3583 (modify-syntax-entry ?\) "." st)))
3584 (if reset-st
3585 (set-syntax-table reset-st))))
3586
3587(defsubst cperl-look-at-leading-count (is-x-REx e)
82d9a08d
SM
3588 (if (and
3589 (< (point) e)
3590 (re-search-forward (concat "\\=" (if is-x-REx "[ \t\n]*" "") "[{?+*]")
3591 (1- e) t)) ; return nil on failure, no moving
4ab89e7b
SM
3592 (if (eq ?\{ (preceding-char)) nil
3593 (cperl-postpone-fontification
3594 (1- (point)) (point)
3595 'face font-lock-warning-face))))
3596
3597;;; Debugging this may require (setq max-specpdl-size 2000)...
3598(defun cperl-find-pods-heres (&optional min max non-inter end ignore-max end-of-here-doc)
f83d2997 3599 "Scans the buffer for hard-to-parse Perl constructions.
5c8b7eaf
SS
3600If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify
3601the sections using `cperl-pod-head-face', `cperl-pod-face',
f83d2997
KH
3602`cperl-here-face'."
3603 (interactive)
05927f8c 3604 (or min (setq min (point-min)
db133cb6
RS
3605 cperl-syntax-state nil
3606 cperl-syntax-done-to min))
f83d2997 3607 (or max (setq max (point-max)))
83261a2f
SM
3608 (let* ((cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend
3609 face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb
4ab89e7b 3610 is-REx is-x-REx REx-subgr-start REx-subgr-end was-subgr i2 hairy-RE
83261a2f 3611 (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
4ab89e7b 3612 (modified (buffer-modified-p)) overshoot is-o-REx
83261a2f 3613 (after-change-functions nil)
4ab89e7b 3614 (cperl-font-locking t)
83261a2f
SM
3615 (use-syntax-state (and cperl-syntax-state
3616 (>= min (car cperl-syntax-state))))
3617 (state-point (if use-syntax-state
3618 (car cperl-syntax-state)
3619 (point-min)))
3620 (state (if use-syntax-state
3621 (cdr cperl-syntax-state)))
3622 ;; (st-l '(nil)) (err-l '(nil)) ; Would overwrite - propagates from a function call to a function call!
3623 (st-l (list nil)) (err-l (list nil))
3624 ;; Somehow font-lock may be not loaded yet...
4ab89e7b 3625 ;; (e.g., when building TAGS via command-line call)
83261a2f
SM
3626 (font-lock-string-face (if (boundp 'font-lock-string-face)
3627 font-lock-string-face
3628 'font-lock-string-face))
4ab89e7b 3629 (my-cperl-delimiters-face (if (boundp 'font-lock-constant-face)
83261a2f
SM
3630 font-lock-constant-face
3631 'font-lock-constant-face))
4ab89e7b 3632 (my-cperl-REx-spec-char-face ; [] ^.$ and wrapper-of ({})
83261a2f
SM
3633 (if (boundp 'font-lock-function-name-face)
3634 font-lock-function-name-face
3635 'font-lock-function-name-face))
4ab89e7b
SM
3636 (font-lock-variable-name-face ; interpolated vars and ({})-code
3637 (if (boundp 'font-lock-variable-name-face)
3638 font-lock-variable-name-face
3639 'font-lock-variable-name-face))
3640 (font-lock-function-name-face ; used in `cperl-find-sub-attrs'
3641 (if (boundp 'font-lock-function-name-face)
3642 font-lock-function-name-face
3643 'font-lock-function-name-face))
3644 (font-lock-constant-face ; used in `cperl-find-sub-attrs'
3645 (if (boundp 'font-lock-constant-face)
3646 font-lock-constant-face
3647 'font-lock-constant-face))
3648 (my-cperl-REx-0length-face ; 0-length, (?:)etc, non-literal \
3649 (if (boundp 'font-lock-builtin-face)
3650 font-lock-builtin-face
3651 'font-lock-builtin-face))
83261a2f
SM
3652 (font-lock-comment-face
3653 (if (boundp 'font-lock-comment-face)
3654 font-lock-comment-face
3655 'font-lock-comment-face))
4ab89e7b
SM
3656 (font-lock-warning-face
3657 (if (boundp 'font-lock-warning-face)
3658 font-lock-warning-face
3659 'font-lock-warning-face))
3660 (my-cperl-REx-ctl-face ; (|)
3661 (if (boundp 'font-lock-keyword-face)
3662 font-lock-keyword-face
3663 'font-lock-keyword-face))
3664 (my-cperl-REx-modifiers-face ; //gims
83261a2f
SM
3665 (if (boundp 'cperl-nonoverridable-face)
3666 cperl-nonoverridable-face
4ab89e7b
SM
3667 'cperl-nonoverridable-face))
3668 (my-cperl-REx-length1-face ; length=1 escaped chars, POSIX classes
3669 (if (boundp 'font-lock-type-face)
3670 font-lock-type-face
3671 'font-lock-type-face))
83261a2f
SM
3672 (stop-point (if ignore-max
3673 (point-max)
3674 max))
3675 (search
3676 (concat
4ab89e7b 3677 "\\(\\`\n?\\|^\n\\)=" ; POD
83261a2f
SM
3678 "\\|"
3679 ;; One extra () before this:
4ab89e7b 3680 "<<" ; HERE-DOC
83261a2f
SM
3681 "\\(" ; 1 + 1
3682 ;; First variant "BLAH" or just ``.
3683 "[ \t]*" ; Yes, whitespace is allowed!
3684 "\\([\"'`]\\)" ; 2 + 1 = 3
3685 "\\([^\"'`\n]*\\)" ; 3 + 1
3686 "\\3"
3687 "\\|"
f739b53b 3688 ;; Second variant: Identifier or \ID (same as 'ID') or empty
83261a2f
SM
3689 "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
3690 ;; Do not have <<= or << 30 or <<30 or << $blah.
3691 ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
3692 "\\(\\)" ; To preserve count of pars :-( 6 + 1
3693 "\\)"
3694 "\\|"
3695 ;; 1+6 extra () before this:
4ab89e7b 3696 "^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$" ;FRMAT
83261a2f 3697 (if cperl-use-syntax-table-text-property
db133cb6 3698 (concat
db133cb6 3699 "\\|"
83261a2f 3700 ;; 1+6+2=9 extra () before this:
4ab89e7b 3701 "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>" ; QUOTED CONSTRUCT
83261a2f
SM
3702 "\\|"
3703 ;; 1+6+2+1=10 extra () before this:
3704 "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
3705 "\\|"
4ab89e7b
SM
3706 ;; 1+6+2+1+1=11 extra () before this
3707 "\\<sub\\>" ; sub with proto/attr
3708 "\\("
3709 cperl-white-and-comment-rex
3710 "\\(::[a-zA-Z_:'0-9]*\\|[a-zA-Z_'][a-zA-Z_:'0-9]*\\)\\)?" ; name
3711 "\\("
3712 cperl-maybe-white-and-comment-rex
3713 "\\(([^()]*)\\|:[^:]\\)\\)" ; prototype or attribute start
83261a2f 3714 "\\|"
4ab89e7b
SM
3715 ;; 1+6+2+1+1+6=17 extra () before this:
3716 "\\$\\(['{]\\)" ; $' or ${foo}
83261a2f 3717 "\\|"
4ab89e7b
SM
3718 ;; 1+6+2+1+1+6+1=18 extra () before this (old pack'var syntax;
3719 ;; we do not support intervening comments...):
83261a2f 3720 "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'"
4ab89e7b 3721 ;; 1+6+2+1+1+6+1+1=19 extra () before this:
83261a2f 3722 "\\|"
4ab89e7b
SM
3723 "__\\(END\\|DATA\\)__" ; __END__ or __DATA__
3724 ;; 1+6+2+1+1+6+1+1+1=20 extra () before this:
db133cb6 3725 "\\|"
4ab89e7b 3726 "\\\\\\(['`\"($]\\)") ; BACKWACKED something-hairy
83261a2f 3727 ""))))
f83d2997
KH
3728 (unwind-protect
3729 (progn
3730 (save-excursion
3731 (or non-inter
3732 (message "Scanning for \"hard\" Perl constructions..."))
4ab89e7b 3733 ;;(message "find: %s --> %s" min max)
db133cb6 3734 (and cperl-pod-here-fontify
83261a2f
SM
3735 ;; We had evals here, do not know why...
3736 (setq face cperl-pod-face
3737 head-face cperl-pod-head-face
3738 here-face cperl-here-face))
5c8b7eaf 3739 (remove-text-properties min max
5bd52f0e 3740 '(syntax-type t in-pod t syntax-table t
4ab89e7b
SM
3741 attrib-group t
3742 REx-interpolated t
6c389151
SM
3743 cperl-postpone t
3744 syntax-subtype t
3745 rear-nonsticky t
4ab89e7b 3746 front-sticky t
f739b53b
SM
3747 here-doc-group t
3748 first-format-line t
4ab89e7b 3749 REx-part2 t
6c389151 3750 indentable t))
f83d2997
KH
3751 ;; Need to remove face as well...
3752 (goto-char min)
db133cb6 3753 (and (eq system-type 'emx)
4ab89e7b
SM
3754 (eq (point) 1)
3755 (let ((case-fold-search t))
3756 (looking-at "extproc[ \t]")) ; Analogue of #!
5c8b7eaf 3757 (cperl-commentify min
db133cb6
RS
3758 (save-excursion (end-of-line) (point))
3759 nil))
3760 (while (and
3761 (< (point) max)
3762 (re-search-forward search max t))
5bd52f0e 3763 (setq tmpend nil) ; Valid for most cases
4ab89e7b
SM
3764 (setq b (match-beginning 0)
3765 state (save-excursion (parse-partial-sexp
3766 state-point b nil nil state))
3767 state-point b)
5c8b7eaf 3768 (cond
4ab89e7b
SM
3769 ;; 1+6+2+1+1+6=17 extra () before this:
3770 ;; "\\$\\(['{]\\)"
3771 ((match-beginning 18) ; $' or ${foo}
3772 (if (eq (preceding-char) ?\') ; $'
3773 (progn
3774 (setq b (1- (point))
3775 state (parse-partial-sexp
3776 state-point (1- b) nil nil state)
3777 state-point (1- b))
3778 (if (nth 3 state) ; in string
3779 (cperl-modify-syntax-type (1- b) cperl-st-punct))
3780 (goto-char (1+ b)))
3781 ;; else: ${
3782 (setq bb (match-beginning 0))
3783 (cperl-modify-syntax-type bb cperl-st-punct)))
3784 ;; No processing in strings/comments beyond this point:
3785 ((or (nth 3 state) (nth 4 state))
3786 t) ; Do nothing in comment/string
f83d2997 3787 ((match-beginning 1) ; POD section
a1506d29 3788 ;; "\\(\\`\n?\\|^\n\\)="
4ab89e7b
SM
3789 (setq b (match-beginning 0)
3790 state (parse-partial-sexp
3791 state-point b nil nil state)
3792 state-point b)
3793 (if (or (nth 3 state) (nth 4 state)
3794 (looking-at "cut\\>"))
3795 (if (or (nth 3 state) (nth 4 state) ignore-max)
5bd52f0e 3796 nil ; Doing a chunk only
f83d2997
KH
3797 (message "=cut is not preceded by a POD section")
3798 (or (car err-l) (setcar err-l (point))))
3799 (beginning-of-line)
5c8b7eaf
SS
3800
3801 (setq b (point)
5bd52f0e
RS
3802 bb b
3803 tb (match-beginning 0)
3804 b1 nil) ; error condition
db133cb6
RS
3805 ;; We do not search to max, since we may be called from
3806 ;; some hook of fontification, and max is random
6c389151 3807 (or (re-search-forward "^\n=cut\\>" stop-point 'toend)
f83d2997 3808 (progn
6c389151
SM
3809 (goto-char b)
3810 (if (re-search-forward "\n=cut\\>" stop-point 'toend)
3811 (progn
3812 (message "=cut is not preceded by an empty line")
3813 (setq b1 t)
3814 (or (car err-l) (setcar err-l b))))))
f83d2997
KH
3815 (beginning-of-line 2) ; An empty line after =cut is not POD!
3816 (setq e (point))
db133cb6 3817 (and (> e max)
6c389151 3818 (progn
a1506d29 3819 (remove-text-properties
6c389151 3820 max e '(syntax-type t in-pod t syntax-table t
4ab89e7b
SM
3821 attrib-group t
3822 REx-interpolated t
6c389151
SM
3823 cperl-postpone t
3824 syntax-subtype t
f739b53b 3825 here-doc-group t
6c389151 3826 rear-nonsticky t
4ab89e7b 3827 front-sticky t
f739b53b 3828 first-format-line t
4ab89e7b 3829 REx-part2 t
6c389151
SM
3830 indentable t))
3831 (setq tmpend tb)))
f83d2997 3832 (put-text-property b e 'in-pod t)
6c389151 3833 (put-text-property b e 'syntax-type 'in-pod)
f83d2997
KH
3834 (goto-char b)
3835 (while (re-search-forward "\n\n[ \t]" e t)
3836 ;; We start 'pod 1 char earlier to include the preceding line
3837 (beginning-of-line)
3838 (put-text-property (cperl-1- b) (point) 'syntax-type 'pod)
5efe6a56
SM
3839 (cperl-put-do-not-fontify b (point) t)
3840 ;; mark the non-literal parts as PODs
a1506d29 3841 (if cperl-pod-here-fontify
5efe6a56 3842 (cperl-postpone-fontification b (point) 'face face t))
f83d2997
KH
3843 (re-search-forward "\n\n[^ \t\f\n]" e 'toend)
3844 (beginning-of-line)
3845 (setq b (point)))
3846 (put-text-property (cperl-1- (point)) e 'syntax-type 'pod)
5efe6a56 3847 (cperl-put-do-not-fontify (point) e t)
a1506d29
JB
3848 (if cperl-pod-here-fontify
3849 (progn
5efe6a56
SM
3850 ;; mark the non-literal parts as PODs
3851 (cperl-postpone-fontification (point) e 'face face t)
3852 (goto-char bb)
a1506d29 3853 (if (looking-at
5efe6a56
SM
3854 "=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$")
3855 ;; mark the headers
a1506d29 3856 (cperl-postpone-fontification
5efe6a56 3857 (match-beginning 1) (match-end 1)
6c389151
SM
3858 'face head-face))
3859 (while (re-search-forward
3860 ;; One paragraph
3861 "^\n=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$"
3862 e 'toend)
3863 ;; mark the headers
a1506d29 3864 (cperl-postpone-fontification
5efe6a56
SM
3865 (match-beginning 1) (match-end 1)
3866 'face head-face))))
f83d2997
KH
3867 (cperl-commentify bb e nil)
3868 (goto-char e)
3869 (or (eq e (point-max))
83261a2f 3870 (forward-char -1)))) ; Prepare for immediate POD start.
f83d2997 3871 ;; Here document
4ab89e7b
SM
3872 ;; We can do many here-per-line;
3873 ;; but multiline quote on the same line as <<HERE confuses us...
5bd52f0e 3874 ;; ;; One extra () before this:
5c8b7eaf 3875 ;;"<<"
5bd52f0e
RS
3876 ;; "\\(" ; 1 + 1
3877 ;; ;; First variant "BLAH" or just ``.
f739b53b 3878 ;; "[ \t]*" ; Yes, whitespace is allowed!
5bd52f0e
RS
3879 ;; "\\([\"'`]\\)" ; 2 + 1
3880 ;; "\\([^\"'`\n]*\\)" ; 3 + 1
3881 ;; "\\3"
3882 ;; "\\|"
3883 ;; ;; Second variant: Identifier or \ID or empty
3884 ;; "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
3885 ;; ;; Do not have <<= or << 30 or <<30 or << $blah.
3886 ;; ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
3887 ;; "\\(\\)" ; To preserve count of pars :-( 6 + 1
3888 ;; "\\)"
f83d2997 3889 ((match-beginning 2) ; 1 + 1
4ab89e7b 3890 (setq b (point)
5bd52f0e 3891 tb (match-beginning 0)
4ab89e7b
SM
3892 c (and ; not HERE-DOC
3893 (match-beginning 5)
3894 (save-match-data
3895 (or (looking-at "[ \t]*(") ; << function_call()
3896 (save-excursion ; 1 << func_name, or $foo << 10
3897 (condition-case nil
3898 (progn
3899 (goto-char tb)
3900 ;;; XXX What to do: foo <<bar ???
3901 ;;; XXX Need to support print {a} <<B ???
3902 (forward-sexp -1)
cb5bf6ba 3903 (save-match-data
4ab89e7b
SM
3904 ; $foo << b; $f .= <<B;
3905 ; ($f+1) << b; a($f) . <<B;
3906 ; foo 1, <<B; $x{a} <<b;
3907 (cond
3908 ((looking-at "[0-9$({]")
3909 (forward-sexp 1)
3910 (and
3911 (looking-at "[ \t]*<<")
3912 (condition-case nil
3913 ;; print $foo <<EOF
3914 (progn
3915 (forward-sexp -2)
3916 (not
3917 (looking-at "\\(printf?\\|system\\|exec\\|sort\\)\\>")))
3918 (error t)))))))
3919 (error nil))) ; func(<<EOF)
3920 (and (not (match-beginning 6)) ; Empty
3921 (looking-at
3922 "[ \t]*[=0-9$@%&(]"))))))
5bd52f0e
RS
3923 (if c ; Not here-doc
3924 nil ; Skip it.
4ab89e7b 3925 (setq c (match-end 2)) ; 1 + 1
f83d2997
KH
3926 (if (match-beginning 5) ;4 + 1
3927 (setq b1 (match-beginning 5) ; 4 + 1
3928 e1 (match-end 5)) ; 4 + 1
3929 (setq b1 (match-beginning 4) ; 3 + 1
3930 e1 (match-end 4))) ; 3 + 1
3931 (setq tag (buffer-substring b1 e1)
3932 qtag (regexp-quote tag))
5c8b7eaf 3933 (cond (cperl-pod-here-fontify
5bd52f0e 3934 ;; Highlight the starting delimiter
cb5bf6ba 3935 (cperl-postpone-fontification
4ab89e7b 3936 b1 e1 'face my-cperl-delimiters-face)
5bd52f0e 3937 (cperl-put-do-not-fontify b1 e1 t)))
f83d2997 3938 (forward-line)
4ab89e7b
SM
3939 (setq i (point))
3940 (if end-of-here-doc
3941 (goto-char end-of-here-doc))
f83d2997 3942 (setq b (point))
db133cb6
RS
3943 ;; We do not search to max, since we may be called from
3944 ;; some hook of fontification, and max is random
f739b53b
SM
3945 (or (and (re-search-forward (concat "^" qtag "$")
3946 stop-point 'toend)
4ab89e7b
SM
3947 ;;;(eq (following-char) ?\n) ; XXXX WHY???
3948 )
f739b53b
SM
3949 (progn ; Pretend we matched at the end
3950 (goto-char (point-max))
3951 (re-search-forward "\\'")
3952 (message "End of here-document `%s' not found." tag)
3953 (or (car err-l) (setcar err-l b))))
3954 (if cperl-pod-here-fontify
3955 (progn
3956 ;; Highlight the ending delimiter
4ab89e7b
SM
3957 (cperl-postpone-fontification
3958 (match-beginning 0) (match-end 0)
3959 'face my-cperl-delimiters-face)
f739b53b
SM
3960 (cperl-put-do-not-fontify b (match-end 0) t)
3961 ;; Highlight the HERE-DOC
3962 (cperl-postpone-fontification b (match-beginning 0)
3963 'face here-face)))
3964 (setq e1 (cperl-1+ (match-end 0)))
3965 (put-text-property b (match-beginning 0)
3966 'syntax-type 'here-doc)
3967 (put-text-property (match-beginning 0) e1
3968 'syntax-type 'here-doc-delim)
4ab89e7b
SM
3969 (put-text-property b e1 'here-doc-group t)
3970 ;; This makes insertion at the start of HERE-DOC update
3971 ;; the whole construct:
3972 (put-text-property b (cperl-1+ b) 'front-sticky '(syntax-type))
f739b53b
SM
3973 (cperl-commentify b e1 nil)
3974 (cperl-put-do-not-fontify b (match-end 0) t)
4ab89e7b
SM
3975 ;; Cache the syntax info...
3976 (setq cperl-syntax-state (cons state-point state))
3977 ;; ... and process the rest of the line...
3978 (setq overshoot
3979 (elt ; non-inter ignore-max
3980 (cperl-find-pods-heres c i t end t e1) 1))
3981 (if (and overshoot (> overshoot (point)))
3982 (goto-char overshoot)
3983 (setq overshoot e1))
f739b53b
SM
3984 (if (> e1 max)
3985 (setq tmpend tb))))
f83d2997
KH
3986 ;; format
3987 ((match-beginning 8)
3988 ;; 1+6=7 extra () before this:
3989 ;;"^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
3990 (setq b (point)
3991 name (if (match-beginning 8) ; 7 + 1
3992 (buffer-substring (match-beginning 8) ; 7 + 1
3993 (match-end 8)) ; 7 + 1
5bd52f0e
RS
3994 "")
3995 tb (match-beginning 0))
f83d2997 3996 (setq argument nil)
f739b53b
SM
3997 (put-text-property (save-excursion
3998 (beginning-of-line)
3999 (point))
4000 b 'first-format-line 't)
5c8b7eaf 4001 (if cperl-pod-here-fontify
f83d2997
KH
4002 (while (and (eq (forward-line) 0)
4003 (not (looking-at "^[.;]$")))
4004 (cond
4005 ((looking-at "^#")) ; Skip comments
4006 ((and argument ; Skip argument multi-lines
5c8b7eaf 4007 (looking-at "^[ \t]*{"))
f83d2997
KH
4008 (forward-sexp 1)
4009 (setq argument nil))
4010 (argument ; Skip argument lines
4011 (setq argument nil))
4012 (t ; Format line
4013 (setq b1 (point))
4014 (setq argument (looking-at "^[^\n]*[@^]"))
4015 (end-of-line)
5bd52f0e 4016 ;; Highlight the format line
5c8b7eaf 4017 (cperl-postpone-fontification b1 (point)
83261a2f 4018 'face font-lock-string-face)
f83d2997 4019 (cperl-commentify b1 (point) nil)
5bd52f0e 4020 (cperl-put-do-not-fontify b1 (point) t))))
db133cb6
RS
4021 ;; We do not search to max, since we may be called from
4022 ;; some hook of fontification, and max is random
4023 (re-search-forward "^[.;]$" stop-point 'toend))
f83d2997 4024 (beginning-of-line)
83261a2f 4025 (if (looking-at "^\\.$") ; ";" is not supported yet
f83d2997 4026 (progn
5bd52f0e
RS
4027 ;; Highlight the ending delimiter
4028 (cperl-postpone-fontification (point) (+ (point) 2)
83261a2f 4029 'face font-lock-string-face)
f83d2997 4030 (cperl-commentify (point) (+ (point) 2) nil)
5bd52f0e 4031 (cperl-put-do-not-fontify (point) (+ (point) 2) t))
f83d2997
KH
4032 (message "End of format `%s' not found." name)
4033 (or (car err-l) (setcar err-l b)))
4034 (forward-line)
5bd52f0e
RS
4035 (if (> (point) max)
4036 (setq tmpend tb))
db133cb6 4037 (put-text-property b (point) 'syntax-type 'format))
4ab89e7b 4038 ;; qq-like String or Regexp:
f83d2997
KH
4039 ((or (match-beginning 10) (match-beginning 11))
4040 ;; 1+6+2=9 extra () before this:
5bd52f0e 4041 ;; "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
f83d2997 4042 ;; "\\|"
5bd52f0e 4043 ;; "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
f83d2997
KH
4044 (setq b1 (if (match-beginning 10) 10 11)
4045 argument (buffer-substring
4046 (match-beginning b1) (match-end b1))
4ab89e7b 4047 b (point) ; end of qq etc
f83d2997
KH
4048 i b
4049 c (char-after (match-beginning b1))
4ab89e7b 4050 bb (char-after (1- (match-beginning b1))) ; tmp holder
5bd52f0e
RS
4051 ;; bb == "Not a stringy"
4052 bb (if (eq b1 10) ; user variables/whatever
f739b53b
SM
4053 (and (memq bb (append "$@%*#_:-&>" nil)) ; $#y)
4054 (cond ((eq bb ?-) (eq c ?s)) ; -s file test
4055 ((eq bb ?\:) ; $opt::s
4056 (eq (char-after
4057 (- (match-beginning b1) 2))
4058 ?\:))
4059 ((eq bb ?\>) ; $foo->s
4060 (eq (char-after
4061 (- (match-beginning b1) 2))
4062 ?\-))
4063 ((eq bb ?\&)
4ab89e7b 4064 (not (eq (char-after ; &&m/blah/
f739b53b
SM
4065 (- (match-beginning b1) 2))
4066 ?\&)))
4067 (t t)))
5bd52f0e
RS
4068 ;; <file> or <$file>
4069 (and (eq c ?\<)
6c389151 4070 ;; Do not stringify <FH>, <$fh> :
5bd52f0e 4071 (save-match-data
5c8b7eaf 4072 (looking-at
6c389151 4073 "\\$?\\([_a-zA-Z:][_a-zA-Z0-9:]*\\)?>"))))
5bd52f0e 4074 tb (match-beginning 0))
db133cb6
RS
4075 (goto-char (match-beginning b1))
4076 (cperl-backward-to-noncomment (point-min))
f83d2997 4077 (or bb
5bd52f0e 4078 (if (eq b1 11) ; bare /blah/ or ?blah? or <foo>
f83d2997 4079 (setq argument ""
f739b53b 4080 b1 nil
db133cb6 4081 bb ; Not a regexp?
4ab89e7b
SM
4082 (not
4083 ;; What is below: regexp-p?
4084 (and
4085 (or (memq (preceding-char)
4086 (append (if (memq c '(?\? ?\<))
4087 ;; $a++ ? 1 : 2
4088 "~{(=|&*!,;:["
4089 "~{(=|&+-*!,;:[") nil))
4090 (and (eq (preceding-char) ?\})
4091 (cperl-after-block-p (point-min)))
4092 (and (eq (char-syntax (preceding-char)) ?w)
4093 (progn
4094 (forward-sexp -1)
6c389151
SM
4095;; After these keywords `/' starts a RE. One should add all the
4096;; functions/builtins which expect an argument, but ...
4ab89e7b
SM
4097 (if (eq (preceding-char) ?-)
4098 ;; -d ?foo? is a RE
4099 (looking-at "[a-zA-Z]\\>")
4100 (and
4101 (not (memq (preceding-char)
4102 '(?$ ?@ ?& ?%)))
4103 (looking-at
4104 "\\(while\\|if\\|unless\\|until\\|and\\|or\\|not\\|xor\\|split\\|grep\\|map\\|print\\)\\>")))))
4105 (and (eq (preceding-char) ?.)
4106 (eq (char-after (- (point) 2)) ?.))
4107 (bobp))
4108 ;; m|blah| ? foo : bar;
4109 (not
4110 (and (eq c ?\?)
4111 cperl-use-syntax-table-text-property
4112 (not (bobp))
4113 (progn
4114 (forward-char -1)
4115 (looking-at "\\s|"))))))
db133cb6
RS
4116 b (1- b))
4117 ;; s y tr m
f739b53b
SM
4118 ;; Check for $a -> y
4119 (setq b1 (preceding-char)
4120 go (point))
4121 (if (and (eq b1 ?>)
4122 (eq (char-after (- go 2)) ?-))
db133cb6
RS
4123 ;; Not a regexp
4124 (setq bb t))))
f739b53b
SM
4125 (or bb
4126 (progn
4ab89e7b 4127 (goto-char b)
f739b53b
SM
4128 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
4129 (goto-char (match-end 0))
4130 (skip-chars-forward " \t\n\f"))
4131 (cond ((and (eq (following-char) ?\})
4132 (eq b1 ?\{))
4133 ;; Check for $a[23]->{ s }, @{s} and *{s::foo}
4134 (goto-char (1- go))
4135 (skip-chars-backward " \t\n\f")
4136 (if (memq (preceding-char) (append "$@%&*" nil))
4137 (setq bb t) ; @{y}
4138 (condition-case nil
4139 (forward-sexp -1)
4140 (error nil)))
4141 (if (or bb
4142 (looking-at ; $foo -> {s}
4143 "[$@]\\$*\\([a-zA-Z0-9_:]+\\|[^{]\\)\\([ \t\n]*->\\)?[ \t\n]*{")
4144 (and ; $foo[12] -> {s}
4145 (memq (following-char) '(?\{ ?\[))
4146 (progn
4147 (forward-sexp 1)
4148 (looking-at "\\([ \t\n]*->\\)?[ \t\n]*{"))))
4149 (setq bb t)
4150 (goto-char b)))
4151 ((and (eq (following-char) ?=)
4152 (eq (char-after (1+ (point))) ?\>))
4153 ;; Check for { foo => 1, s => 2 }
4154 ;; Apparently s=> is never a substitution...
4155 (setq bb t))
4156 ((and (eq (following-char) ?:)
4157 (eq b1 ?\{) ; Check for $ { s::bar }
4158 (looking-at "::[a-zA-Z0-9_:]*[ \t\n\f]*}")
15ca5699 4159 (progn
f739b53b
SM
4160 (goto-char (1- go))
4161 (skip-chars-backward " \t\n\f")
4162 (memq (preceding-char)
4163 (append "$@%&*" nil))))
4ab89e7b
SM
4164 (setq bb t))
4165 ((eobp)
f739b53b
SM
4166 (setq bb t)))))
4167 (if bb
f83d2997 4168 (goto-char i)
6c389151 4169 ;; Skip whitespace and comments...
f83d2997
KH
4170 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
4171 (goto-char (match-end 0))
4172 (skip-chars-forward " \t\n\f"))
6c389151
SM
4173 (if (> (point) b)
4174 (put-text-property b (point) 'syntax-type 'prestring))
f83d2997
KH
4175 ;; qtag means two-arg matcher, may be reset to
4176 ;; 2 or 3 later if some special quoting is needed.
4177 ;; e1 means matching-char matcher.
4ab89e7b 4178 (setq b (point) ; before the first delimiter
5bd52f0e
RS
4179 ;; has 2 args
4180 i2 (string-match "^\\([sy]\\|tr\\)$" argument)
db133cb6
RS
4181 ;; We do not search to max, since we may be called from
4182 ;; some hook of fontification, and max is random
4183 i (cperl-forward-re stop-point end
5bd52f0e 4184 i2
4ab89e7b
SM
4185 st-l err-l argument)
4186 ;; If `go', then it is considered as 1-arg, `b1' is nil
4187 ;; as in s/foo//x; the point is before final "slash"
5bd52f0e 4188 b1 (nth 1 i) ; start of the second part
5c8b7eaf 4189 tag (nth 2 i) ; ender-char, true if second part
5bd52f0e 4190 ; is with matching chars []
f83d2997
KH
4191 go (nth 4 i) ; There is a 1-char part after the end
4192 i (car i) ; intermediate point
5c8b7eaf 4193 e1 (point) ; end
5bd52f0e 4194 ;; Before end of the second part if non-matching: ///
5c8b7eaf 4195 tail (if (and i (not tag))
5bd52f0e
RS
4196 (1- e1))
4197 e (if i i e1) ; end of the first part
6c389151 4198 qtag nil ; need to preserve backslashitis
4ab89e7b
SM
4199 is-x-REx nil is-o-REx nil); REx has //x //o modifiers
4200 ;; If s{} (), then b/b1 are at "{", "(", e1/i after ")", "}"
f83d2997
KH
4201 ;; Commenting \\ is dangerous, what about ( ?
4202 (and i tail
4203 (eq (char-after i) ?\\)
5bd52f0e 4204 (setq qtag t))
4ab89e7b
SM
4205 (and (if go (looking-at ".\\sw*x")
4206 (looking-at "\\sw*x")) ; qr//x
4207 (setq is-x-REx t))
4208 (and (if go (looking-at ".\\sw*o")
4209 (looking-at "\\sw*o")) ; //o
4210 (setq is-o-REx t))
f83d2997 4211 (if (null i)
5bd52f0e 4212 ;; Considered as 1arg form
f83d2997
KH
4213 (progn
4214 (cperl-commentify b (point) t)
5bd52f0e 4215 (put-text-property b (point) 'syntax-type 'string)
6c389151
SM
4216 (if (or is-x-REx
4217 ;; ignore other text properties:
4218 (string-match "^qw$" argument))
4219 (put-text-property b (point) 'indentable t))
5bd52f0e
RS
4220 (and go
4221 (setq e1 (cperl-1+ e1))
4222 (or (eobp)
4223 (forward-char 1))))
f83d2997
KH
4224 (cperl-commentify b i t)
4225 (if (looking-at "\\sw*e") ; s///e
4226 (progn
4ab89e7b
SM
4227 ;; Cache the syntax info...
4228 (setq cperl-syntax-state (cons state-point state))
f83d2997
KH
4229 (and
4230 ;; silent:
4ab89e7b 4231 (car (cperl-find-pods-heres b1 (1- (point)) t end))
f83d2997
KH
4232 ;; Error
4233 (goto-char (1+ max)))
5bd52f0e 4234 (if (and tag (eq (preceding-char) ?\>))
f83d2997
KH
4235 (progn
4236 (cperl-modify-syntax-type (1- (point)) cperl-st-ket)
5bd52f0e 4237 (cperl-modify-syntax-type i cperl-st-bra)))
6c389151 4238 (put-text-property b i 'syntax-type 'string)
4ab89e7b 4239 (put-text-property i (point) 'syntax-type 'multiline)
6c389151
SM
4240 (if is-x-REx
4241 (put-text-property b i 'indentable t)))
5bd52f0e
RS
4242 (cperl-commentify b1 (point) t)
4243 (put-text-property b (point) 'syntax-type 'string)
6c389151
SM
4244 (if is-x-REx
4245 (put-text-property b i 'indentable t))
5bd52f0e 4246 (if qtag
db133cb6 4247 (cperl-modify-syntax-type (1+ i) cperl-st-punct))
f83d2997 4248 (setq tail nil)))
5bd52f0e 4249 ;; Now: tail: if the second part is non-matching without ///e
f83d2997
KH
4250 (if (eq (char-syntax (following-char)) ?w)
4251 (progn
4252 (forward-word 1) ; skip modifiers s///s
5bd52f0e 4253 (if tail (cperl-commentify tail (point) t))
a1506d29 4254 (cperl-postpone-fontification
4ab89e7b 4255 e1 (point) 'face my-cperl-REx-modifiers-face)))
5bd52f0e
RS
4256 ;; Check whether it is m// which means "previous match"
4257 ;; and highlight differently
a1506d29 4258 (setq is-REx
6c389151
SM
4259 (and (string-match "^\\([sm]?\\|qr\\)$" argument)
4260 (or (not (= (length argument) 0))
4261 (not (eq c ?\<)))))
a1506d29 4262 (if (and is-REx
6c389151 4263 (eq e (+ 2 b))
5bd52f0e
RS
4264 ;; split // *is* using zero-pattern
4265 (save-excursion
4266 (condition-case nil
4267 (progn
4268 (goto-char tb)
4269 (forward-sexp -1)
4270 (not (looking-at "split\\>")))
4271 (error t))))
5c8b7eaf 4272 (cperl-postpone-fontification
4ab89e7b 4273 b e 'face font-lock-warning-face)
5bd52f0e
RS
4274 (if (or i2 ; Has 2 args
4275 (and cperl-fontify-m-as-s
4276 (or
4277 (string-match "^\\(m\\|qr\\)$" argument)
4278 (and (eq 0 (length argument))
4279 (not (eq ?\< (char-after b)))))))
4280 (progn
5c8b7eaf 4281 (cperl-postpone-fontification
4ab89e7b 4282 b (cperl-1+ b) 'face my-cperl-delimiters-face)
5c8b7eaf 4283 (cperl-postpone-fontification
4ab89e7b 4284 (1- e) e 'face my-cperl-delimiters-face)))
6c389151 4285 (if (and is-REx cperl-regexp-scan)
4ab89e7b
SM
4286 ;; Process RExen: embedded comments, charclasses and ]
4287;;;/\3333\xFg\x{FFF}a\ppp\PPP\qqq\C\99f(?{ foo })(??{ foo })/;
4288;;;/a\.b[^a[:ff:]b]x$ab->$[|$,$ab->[cd]->[ef]|$ab[xy].|^${a,b}{c,d}/;
4289;;;/(?<=foo)(?<!bar)(x)(?:$ab|\$\/)$|\\\b\x888\776\[\:$/xxx;
4290;;;m?(\?\?{b,a})? + m/(??{aa})(?(?=xx)aa|bb)(?#aac)/;
4291;;;m$(^ab[c]\$)$ + m+(^ab[c]\$\+)+ + m](^ab[c\]$|.+)] + m)(^ab[c]$|.+\));
4292;;;m^a[\^b]c^ + m.a[^b]\.c.;
6c389151
SM
4293 (save-excursion
4294 (goto-char (1+ b))
cb5bf6ba 4295 ;; First
4ab89e7b
SM
4296 (cperl-look-at-leading-count is-x-REx e)
4297 (setq hairy-RE
4298 (concat
4299 (if is-x-REx
4300 (if (eq (char-after b) ?\#)
4301 "\\((\\?\\\\#\\)\\|\\(\\\\#\\)"
4302 "\\((\\?#\\)\\|\\(#\\)")
4303 ;; keep the same count: add a fake group
4304 (if (eq (char-after b) ?\#)
4305 "\\((\\?\\\\#\\)\\(\\)"
4306 "\\((\\?#\\)\\(\\)"))
4307 "\\|"
4308 "\\(\\[\\)" ; 3=[
4309 "\\|"
4310 "\\(]\\)" ; 4=]
4311 "\\|"
4312 ;; XXXX Will not be able to use it in s)))
4313 (if (eq (char-after b) ?\) )
4314 "\\())))\\)" ; Will never match
4315 (if (eq (char-after b) ?? )
4316 ;;"\\((\\\\\\?\\(\\\\\\?\\)?{\\)"
4317 "\\((\\\\\\?\\\\\\?{\\|()\\\\\\?{\\)"
4318 "\\((\\?\\??{\\)")) ; 5= (??{ (?{
4319 "\\|" ; 6= 0-length, 7: name, 8,9:code, 10:group
4320 "\\(" ;; XXXX 1-char variables, exc. |()\s
4321 "[$@]"
4322 "\\("
4323 "[_a-zA-Z:][_a-zA-Z0-9:]*"
4324 "\\|"
4325 "{[^{}]*}" ; only one-level allowed
4326 "\\|"
4327 "[^{(|) \t\r\n\f]"
4328 "\\)"
4329 "\\(" ;;8,9:code part of array/hash elt
4330 "\\(" "->" "\\)?"
4331 "\\[[^][]*\\]"
4332 "\\|"
4333 "{[^{}]*}"
4334 "\\)*"
4335 ;; XXXX: what if u is delim?
4336 "\\|"
4337 "[)^|$.*?+]"
4338 "\\|"
4339 "{[0-9]+}"
4340 "\\|"
4341 "{[0-9]+,[0-9]*}"
4342 "\\|"
4343 "\\\\[luLUEQbBAzZG]"
4344 "\\|"
4345 "(" ; Group opener
4346 "\\(" ; 10 group opener follower
4347 "\\?\\((\\?\\)" ; 11: in (?(?=C)A|B)
4348 "\\|"
4349 "\\?[:=!>?{]" ; "?" something
4350 "\\|"
4351 "\\?[-imsx]+[:)]" ; (?i) (?-s:.)
4352 "\\|"
4353 "\\?([0-9]+)" ; (?(1)foo|bar)
4354 "\\|"
4355 "\\?<[=!]"
4356 ;;;"\\|"
4357 ;;; "\\?"
4358 "\\)?"
4359 "\\)"
4360 "\\|"
4361 "\\\\\\(.\\)" ; 12=\SYMBOL
4362 ))
6c389151 4363 (while
4ab89e7b
SM
4364 (and (< (point) (1- e))
4365 (re-search-forward hairy-RE (1- e) 'to-end))
6c389151 4366 (goto-char (match-beginning 0))
4ab89e7b
SM
4367 (setq REx-subgr-start (point)
4368 was-subgr (following-char))
4369 (cond
4370 ((match-beginning 6) ; 0-length builtins, groups
4371 (goto-char (match-end 0))
4372 (if (match-beginning 11)
4373 (goto-char (match-beginning 11)))
4374 (if (>= (point) e)
4375 (goto-char (1- e)))
4376 (cperl-postpone-fontification
4377 (match-beginning 0) (point)
4378 'face
4379 (cond
4380 ((eq was-subgr ?\) )
4381 (condition-case nil
4382 (save-excursion
4383 (forward-sexp -1)
4384 (if (> (point) b)
4385 (if (if (eq (char-after b) ?? )
4386 (looking-at "(\\\\\\?")
4387 (eq (char-after (1+ (point))) ?\?))
4388 my-cperl-REx-0length-face
4389 my-cperl-REx-ctl-face)
4390 font-lock-warning-face))
4391 (error font-lock-warning-face)))
4392 ((eq was-subgr ?\| )
4393 my-cperl-REx-ctl-face)
4394 ((eq was-subgr ?\$ )
4395 (if (> (point) (1+ REx-subgr-start))
4396 (progn
4397 (put-text-property
4398 (match-beginning 0) (point)
4399 'REx-interpolated
4400 (if is-o-REx 0
4401 (if (and (eq (match-beginning 0)
4402 (1+ b))
4403 (eq (point)
4404 (1- e))) 1 t)))
4405 font-lock-variable-name-face)
4406 my-cperl-REx-spec-char-face))
4407 ((memq was-subgr (append "^." nil) )
4408 my-cperl-REx-spec-char-face)
4409 ((eq was-subgr ?\( )
4410 (if (not (match-beginning 10))
4411 my-cperl-REx-ctl-face
4412 my-cperl-REx-0length-face))
4413 (t my-cperl-REx-0length-face)))
4414 (if (and (memq was-subgr (append "(|" nil))
4415 (not (string-match "(\\?[-imsx]+)"
4416 (match-string 0))))
4417 (cperl-look-at-leading-count is-x-REx e))
4418 (setq was-subgr nil)) ; We do stuff here
4419 ((match-beginning 12) ; \SYMBOL
4420 (forward-char 2)
4421 (if (>= (point) e)
4422 (goto-char (1- e))
4423 ;; How many chars to not highlight:
4424 ;; 0-len special-alnums in other branch =>
4425 ;; Generic: \non-alnum (1), \alnum (1+face)
4426 ;; Is-delim: \non-alnum (1/spec-2) alnum-1 (=what hai)
4427 (setq REx-subgr-start (point)
4428 qtag (preceding-char))
4429 (cperl-postpone-fontification
4430 (- (point) 2) (- (point) 1) 'face
4431 (if (memq qtag
4432 (append "ghijkmoqvFHIJKMORTVY" nil))
4433 font-lock-warning-face
4434 my-cperl-REx-0length-face))
4435 (if (and (eq (char-after b) qtag)
4436 (memq qtag (append ".])^$|*?+" nil)))
4437 (progn
4438 (if (and cperl-use-syntax-table-text-property
4439 (eq qtag ?\) ))
4440 (put-text-property
4441 REx-subgr-start (1- (point))
4442 'syntax-table cperl-st-punct))
4443 (cperl-postpone-fontification
4444 (1- (point)) (point) 'face
4445 ; \] can't appear below
4446 (if (memq qtag (append ".]^$" nil))
4447 'my-cperl-REx-spec-char-face
4448 (if (memq qtag (append "*?+" nil))
4449 'my-cperl-REx-0length-face
4450 'my-cperl-REx-ctl-face))))) ; )|
4451 ;; Test for arguments:
4452 (cond
4453 ;; This is not pretty: the 5.8.7 logic:
4454 ;; \0numx -> octal (up to total 3 dig)
4455 ;; \DIGIT -> backref unless \0
cb5bf6ba 4456 ;; \DIGITs -> backref if valid
4ab89e7b
SM
4457 ;; otherwise up to 3 -> octal
4458 ;; Do not try to distinguish, we guess
4459 ((or (and (memq qtag (append "01234567" nil))
4460 (re-search-forward
4461 "\\=[01234567]?[01234567]?"
4462 (1- e) 'to-end))
4463 (and (memq qtag (append "89" nil))
cb5bf6ba 4464 (re-search-forward
4ab89e7b
SM
4465 "\\=[0123456789]*" (1- e) 'to-end))
4466 (and (eq qtag ?x)
4467 (re-search-forward
4468 "\\=[0-9a-fA-F][0-9a-fA-F]?\\|\\={[0-9a-fA-F]+}"
4469 (1- e) 'to-end))
4470 (and (memq qtag (append "pPN" nil))
4471 (re-search-forward "\\={[^{}]+}\\|."
4472 (1- e) 'to-end))
4473 (eq (char-syntax qtag) ?w))
4474 (cperl-postpone-fontification
4475 (1- REx-subgr-start) (point)
4476 'face my-cperl-REx-length1-face))))
4477 (setq was-subgr nil)) ; We do stuff here
4478 ((match-beginning 3) ; [charclass]
4479 (forward-char 1)
4480 (if (eq (char-after b) ?^ )
4481 (and (eq (following-char) ?\\ )
4482 (eq (char-after (cperl-1+ (point)))
4483 ?^ )
4484 (forward-char 2))
4485 (and (eq (following-char) ?^ )
4486 (forward-char 1)))
4487 (setq argument b ; continue?
4488 tag nil ; list of POSIX classes
4489 qtag (point))
4490 (if (eq (char-after b) ?\] )
4491 (and (eq (following-char) ?\\ )
4492 (eq (char-after (cperl-1+ (point)))
4493 ?\] )
4494 (setq qtag (1+ qtag))
4495 (forward-char 2))
4496 (and (eq (following-char) ?\] )
4497 (forward-char 1)))
4498 ;; Apparently, I can't put \] into a charclass
4499 ;; in m]]: m][\\\]\]] produces [\\]]
4500;;; POSIX? [:word:] [:^word:] only inside []
4501;;; "\\=\\(\\\\.\\|[^][\\\\]\\|\\[:\\^?\sw+:]\\|\\[[^:]\\)*]")
cb5bf6ba 4502 (while
4ab89e7b
SM
4503 (and argument
4504 (re-search-forward
4505 (if (eq (char-after b) ?\] )
4506 "\\=\\(\\\\[^]]\\|[^]\\\\]\\)*\\\\]"
4507 "\\=\\(\\\\.\\|[^]\\\\]\\)*]")
4508 (1- e) 'toend))
4509 ;; Is this ] an end of POSIX class?
4510 (if (save-excursion
4511 (and
4512 (search-backward "[" argument t)
4513 (< REx-subgr-start (point))
4514 (not
4515 (and ; Should work with delim = \
4516 (eq (preceding-char) ?\\ )
4517 (= (% (skip-chars-backward
4518 "\\\\") 2) 0)))
4519 (looking-at
4520 (cond
4521 ((eq (char-after b) ?\] )
4522 "\\\\*\\[:\\^?\\sw+:\\\\\\]")
4523 ((eq (char-after b) ?\: )
4524 "\\\\*\\[\\\\:\\^?\\sw+\\\\:]")
4525 ((eq (char-after b) ?^ )
4526 "\\\\*\\[:\\(\\\\\\^\\)?\\sw+:\]")
4527 ((eq (char-syntax (char-after b))
4528 ?w)
4529 (concat
4530 "\\\\*\\[:\\(\\\\\\^\\)?\\(\\\\"
4531 (char-to-string (char-after b))
4532 "\\|\\sw\\)+:\]"))
4533 (t "\\\\*\\[:\\^?\\sw*:]")))
4534 (setq argument (point))))
4535 (setq tag (cons (cons argument (point))
4536 tag)
4537 argument (point)) ; continue
4538 (setq argument nil)))
4539 (and argument
4540 (message "Couldn't find end of charclass in a REx, pos=%s"
4541 REx-subgr-start))
4542 (if (and cperl-use-syntax-table-text-property
4543 (> (- (point) 2) REx-subgr-start))
4544 (put-text-property
4545 (1+ REx-subgr-start) (1- (point))
4546 'syntax-table cperl-st-punct))
4547 (cperl-postpone-fontification
4548 REx-subgr-start qtag
4549 'face my-cperl-REx-spec-char-face)
4550 (cperl-postpone-fontification
4551 (1- (point)) (point) 'face
4552 my-cperl-REx-spec-char-face)
4553 (if (eq (char-after b) ?\] )
4554 (cperl-postpone-fontification
4555 (- (point) 2) (1- (point))
4556 'face my-cperl-REx-0length-face))
4557 (while tag
4558 (cperl-postpone-fontification
4559 (car (car tag)) (cdr (car tag))
4560 'face my-cperl-REx-length1-face)
4561 (setq tag (cdr tag)))
4562 (setq was-subgr nil)) ; did facing already
4563 ;; Now rare stuff:
4564 ((and (match-beginning 2) ; #-comment
4565 (/= (match-beginning 2) (match-end 2)))
4566 (beginning-of-line 2)
4567 (if (> (point) e)
4568 (goto-char (1- e))))
4569 ((match-beginning 4) ; character "]"
4570 (setq was-subgr nil) ; We do stuff here
4571 (goto-char (match-end 0))
4572 (if cperl-use-syntax-table-text-property
4573 (put-text-property
4574 (1- (point)) (point)
4575 'syntax-table cperl-st-punct))
4576 (cperl-postpone-fontification
4577 (1- (point)) (point)
4578 'face font-lock-warning-face))
4579 ((match-beginning 5) ; before (?{}) (??{})
4580 (setq tag (match-end 0))
4581 (if (or (setq qtag
4582 (cperl-forward-group-in-re st-l))
4583 (and (>= (point) e)
4584 (setq qtag "no matching `)' found"))
4585 (and (not (eq (char-after (- (point) 2))
4586 ?\} ))
4587 (setq qtag "Can't find })")))
a1506d29 4588 (progn
4ab89e7b 4589 (goto-char (1- e))
274f1353 4590 (message "%s" qtag))
4ab89e7b
SM
4591 (cperl-postpone-fontification
4592 (1- tag) (1- (point))
4593 'face font-lock-variable-name-face)
4594 (cperl-postpone-fontification
4595 REx-subgr-start (1- tag)
4596 'face my-cperl-REx-spec-char-face)
4597 (cperl-postpone-fontification
4598 (1- (point)) (point)
4599 'face my-cperl-REx-spec-char-face)
4600 (if cperl-use-syntax-table-text-property
4601 (progn
4602 (put-text-property
4603 (- (point) 2) (1- (point))
4604 'syntax-table cperl-st-cfence)
4605 (put-text-property
4606 (+ REx-subgr-start 2)
4607 (+ REx-subgr-start 3)
4608 'syntax-table cperl-st-cfence))))
4609 (setq was-subgr nil))
4610 (t ; (?#)-comment
4611 ;; Inside "(" and "\" arn't special in any way
4612 ;; Works also if the outside delimiters are ().
4613 (or;;(if (eq (char-after b) ?\) )
4614 ;;(re-search-forward
4615 ;; "[^\\\\]\\(\\\\\\\\\\)*\\\\)"
4616 ;; (1- e) 'toend)
4617 (search-forward ")" (1- e) 'toend)
4618 ;;)
4619 (message
4620 "Couldn't find end of (?#...)-comment in a REx, pos=%s"
4621 REx-subgr-start))))
6c389151
SM
4622 (if (>= (point) e)
4623 (goto-char (1- e)))
4ab89e7b
SM
4624 (cond
4625 (was-subgr
4626 (setq REx-subgr-end (point))
4627 (cperl-commentify
4628 REx-subgr-start REx-subgr-end nil)
4629 (cperl-postpone-fontification
4630 REx-subgr-start REx-subgr-end
4631 'face font-lock-comment-face))))))
6c389151 4632 (if (and is-REx is-x-REx)
a1506d29 4633 (put-text-property (1+ b) (1- e)
6c389151 4634 'syntax-subtype 'x-REx)))
82d9a08d
SM
4635 (if (and i2 e1 b1 (> e1 b1))
4636 (progn ; No errors finding the second part...
5c8b7eaf 4637 (cperl-postpone-fontification
4ab89e7b 4638 (1- e1) e1 'face my-cperl-delimiters-face)
05927f8c
VJL
4639 (if (and (not (eobp))
4640 (assoc (char-after b) cperl-starters))
4ab89e7b
SM
4641 (progn
4642 (cperl-postpone-fontification
4643 b1 (1+ b1) 'face my-cperl-delimiters-face)
4644 (put-text-property b1 (1+ b1)
4645 'REx-part2 t)))))
5bd52f0e
RS
4646 (if (> (point) max)
4647 (setq tmpend tb))))
4ab89e7b
SM
4648 ((match-beginning 17) ; sub with prototype or attribute
4649 ;; 1+6+2+1+1=11 extra () before this (sub with proto/attr):
4650 ;;"\\<sub\\>\\(" ;12
4651 ;; cperl-white-and-comment-rex ;13
4652 ;; "\\([a-zA-Z_:'0-9]+\\)\\)?" ; name ;14
4653 ;;"\\(" cperl-maybe-white-and-comment-rex ;15,16
4654 ;; "\\(([^()]*)\\|:[^:]\\)\\)" ; 17:proto or attribute start
4655 (setq b1 (match-beginning 14) e1 (match-end 14))
f83d2997
KH
4656 (if (memq (char-after (1- b))
4657 '(?\$ ?\@ ?\% ?\& ?\*))
4658 nil
4ab89e7b
SM
4659 (goto-char b)
4660 (if (eq (char-after (match-beginning 17)) ?\( )
4661 (progn
4662 (cperl-commentify ; Prototypes; mark as string
4663 (match-beginning 17) (match-end 17) t)
4664 (goto-char (match-end 0))
4665 ;; Now look for attributes after prototype:
4666 (forward-comment (buffer-size))
4667 (and (looking-at ":[^:]")
4668 (cperl-find-sub-attrs st-l b1 e1 b)))
4669 ;; treat attributes without prototype
4670 (goto-char (match-beginning 17))
4671 (cperl-find-sub-attrs st-l b1 e1 b))))
4672 ;; 1+6+2+1+1+6+1=18 extra () before this:
f83d2997 4673 ;; "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'")
4ab89e7b
SM
4674 ((match-beginning 19) ; old $abc'efg syntax
4675 (setq bb (match-end 0))
4676 ;;;(if (nth 3 state) nil ; in string
4677 (put-text-property (1- bb) bb 'syntax-table cperl-st-word)
f83d2997 4678 (goto-char bb))
4ab89e7b 4679 ;; 1+6+2+1+1+6+1+1=19 extra () before this:
f83d2997 4680 ;; "__\\(END\\|DATA\\)__"
4ab89e7b
SM
4681 ((match-beginning 20) ; __END__, __DATA__
4682 (setq bb (match-end 0))
4683 ;; (put-text-property b (1+ bb) 'syntax-type 'pod) ; Cheat
4684 (cperl-commentify b bb nil)
4685 (setq end t))
4686 ;; "\\\\\\(['`\"($]\\)"
4687 ((match-beginning 21)
4688 ;; Trailing backslash; make non-quoting outside string/comment
4689 (setq bb (match-end 0))
6c389151
SM
4690 (goto-char b)
4691 (skip-chars-backward "\\\\")
4692 ;;;(setq i2 (= (% (skip-chars-backward "\\\\") 2) -1))
4ab89e7b 4693 (cperl-modify-syntax-type b cperl-st-punct)
6c389151
SM
4694 (goto-char bb))
4695 (t (error "Error in regexp of the sniffer")))
db133cb6 4696 (if (> (point) stop-point)
f83d2997 4697 (progn
5c8b7eaf 4698 (if end
f83d2997
KH
4699 (message "Garbage after __END__/__DATA__ ignored")
4700 (message "Unbalanced syntax found while scanning")
4701 (or (car err-l) (setcar err-l b)))
db133cb6
RS
4702 (goto-char stop-point))))
4703 (setq cperl-syntax-state (cons state-point state)
4ab89e7b
SM
4704 ;; Do not mark syntax as done past tmpend???
4705 cperl-syntax-done-to (or tmpend (max (point) max)))
4706 ;;(message "state-at=%s, done-to=%s" state-point cperl-syntax-done-to)
4707 )
f83d2997 4708 (if (car err-l) (goto-char (car err-l))
db133cb6
RS
4709 (or non-inter
4710 (message "Scanning for \"hard\" Perl constructions... done"))))
f83d2997
KH
4711 (and (buffer-modified-p)
4712 (not modified)
4713 (set-buffer-modified-p nil))
00424a9e
SM
4714 ;; I do not understand what this is doing here. It breaks font-locking
4715 ;; because it resets the syntax-table from font-lock-syntax-table to
4716 ;; cperl-mode-syntax-table.
4717 ;; (set-syntax-table cperl-mode-syntax-table)
4718 )
4ab89e7b
SM
4719 (list (car err-l) overshoot)))
4720
4721(defun cperl-find-pods-heres-region (min max)
4722 (interactive "r")
4723 (cperl-find-pods-heres min max))
f83d2997
KH
4724
4725(defun cperl-backward-to-noncomment (lim)
4726 ;; Stops at lim or after non-whitespace that is not in comment
4ab89e7b 4727 ;; XXXX Wrongly understands end-of-multiline strings with # as comment
5bd52f0e 4728 (let (stop p pr)
4ab89e7b 4729 (while (and (not stop) (> (point) (or lim (point-min))))
f83d2997
KH
4730 (skip-chars-backward " \t\n\f" lim)
4731 (setq p (point))
4732 (beginning-of-line)
5bd52f0e
RS
4733 (if (memq (setq pr (get-text-property (point) 'syntax-type))
4734 '(pod here-doc here-doc-delim))
82d9a08d
SM
4735 (progn
4736 (cperl-unwind-to-safe nil)
4737 (setq pr (get-text-property (point) 'syntax-type))))
4738 (or (and (looking-at "^[ \t]*\\(#\\|$\\)")
4739 (not (memq pr '(string prestring))))
4740 (progn (cperl-to-comment-or-eol) (bolp))
4741 (progn
4742 (skip-chars-backward " \t")
4743 (if (< p (point)) (goto-char p))
4744 (setq stop t))))))
f83d2997 4745
4ab89e7b
SM
4746;; Used only in `cperl-calculate-indent'...
4747(defun cperl-block-p () ; Do not C-M-q ! One string contains ";" !
4748 ;; Positions is before ?\{. Checks whether it starts a block.
4749 ;; No save-excursion! This is more a distinguisher of a block/hash ref...
4750 (cperl-backward-to-noncomment (point-min))
4751 (or (memq (preceding-char) (append ";){}$@&%\C-@" nil)) ; Or label! \C-@ at bobp
4752 ; Label may be mixed up with `$blah :'
4753 (save-excursion (cperl-after-label))
4754 (get-text-property (cperl-1- (point)) 'attrib-group)
4755 (and (memq (char-syntax (preceding-char)) '(?w ?_))
4756 (progn
4757 (backward-sexp)
4758 ;; sub {BLK}, print {BLK} $data, but NOT `bless', `return', `tr'
4759 (or (and (looking-at "[a-zA-Z0-9_:]+[ \t\n\f]*[{#]") ; Method call syntax
4760 (not (looking-at "\\(bless\\|return\\|q[wqrx]?\\|tr\\|[smy]\\)\\>")))
4761 ;; sub bless::foo {}
4762 (progn
4763 (cperl-backward-to-noncomment (point-min))
4764 (and (eq (preceding-char) ?b)
4765 (progn
4766 (forward-sexp -1)
4767 (looking-at "sub[ \t\n\f#]")))))))))
4768
4769;;; What is the difference of (cperl-after-block-p lim t) and (cperl-block-p)?
4770;;; No save-excursion; condition-case ... In (cperl-block-p) the block
4771;;; may be a part of an in-statement construct, such as
4772;;; ${something()}, print {FH} $data.
4773;;; Moreover, one takes positive approach (looks for else,grep etc)
4774;;; another negative (looks for bless,tr etc)
f739b53b 4775(defun cperl-after-block-p (lim &optional pre-block)
4ab89e7b
SM
4776 "Return true if the preceeding } (if PRE-BLOCK, following {) delimits a block.
4777Would not look before LIM. Assumes that LIM is a good place to begin a
4778statement. The kind of block we treat here is one after which a new
4779statement would start; thus the block in ${func()} does not count."
f83d2997
KH
4780 (save-excursion
4781 (condition-case nil
4782 (progn
f739b53b 4783 (or pre-block (forward-sexp -1))
f83d2997 4784 (cperl-backward-to-noncomment lim)
bab27c0c 4785 (or (eq (point) lim)
4ab89e7b
SM
4786 ;; if () {} // sub f () {} // sub f :a(') {}
4787 (eq (preceding-char) ?\) )
4788 ;; label: {}
4789 (save-excursion (cperl-after-label))
4790 ;; sub :attr {}
4791 (get-text-property (cperl-1- (point)) 'attrib-group)
4792 (if (memq (char-syntax (preceding-char)) '(?w ?_)) ; else {}
db133cb6
RS
4793 (save-excursion
4794 (forward-sexp -1)
4ab89e7b
SM
4795 ;; else {} but not else::func {}
4796 (or (and (looking-at "\\(else\\|continue\\|grep\\|map\\|BEGIN\\|END\\|CHECK\\|INIT\\)\\>")
4797 (not (looking-at "\\(\\sw\\|_\\)+::")))
db133cb6
RS
4798 ;; sub f {}
4799 (progn
4800 (cperl-backward-to-noncomment lim)
4ab89e7b 4801 (and (eq (preceding-char) ?b)
db133cb6
RS
4802 (progn
4803 (forward-sexp -1)
4ab89e7b
SM
4804 (looking-at "sub[ \t\n\f#]"))))))
4805 ;; What preceeds is not word... XXXX Last statement in sub???
db133cb6 4806 (cperl-after-expr-p lim))))
f83d2997
KH
4807 (error nil))))
4808
4809(defun cperl-after-expr-p (&optional lim chars test)
029cb4d5 4810 "Return true if the position is good for start of expression.
f83d2997
KH
4811TEST is the expression to evaluate at the found position. If absent,
4812CHARS is a string that contains good characters to have before us (however,
4813`}' is treated \"smartly\" if it is not in the list)."
83261a2f 4814 (let ((lim (or lim (point-min)))
f739b53b
SM
4815 stop p pr)
4816 (cperl-update-syntaxification (point) (point))
f83d2997
KH
4817 (save-excursion
4818 (while (and (not stop) (> (point) lim))
4819 (skip-chars-backward " \t\n\f" lim)
4820 (setq p (point))
4821 (beginning-of-line)
f739b53b
SM
4822 ;;(memq (setq pr (get-text-property (point) 'syntax-type))
4823 ;; '(pod here-doc here-doc-delim))
4824 (if (get-text-property (point) 'here-doc-group)
4825 (progn
4826 (goto-char
4ab89e7b 4827 (cperl-beginning-of-property (point) 'here-doc-group))
f739b53b
SM
4828 (beginning-of-line 0)))
4829 (if (get-text-property (point) 'in-pod)
4830 (progn
4831 (goto-char
4ab89e7b 4832 (cperl-beginning-of-property (point) 'in-pod))
f739b53b 4833 (beginning-of-line 0)))
f83d2997 4834 (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip
5bd52f0e 4835 ;; Else: last iteration, or a label
f739b53b 4836 (cperl-to-comment-or-eol) ; Will not move past "." after a format
f83d2997
KH
4837 (skip-chars-backward " \t")
4838 (if (< p (point)) (goto-char p))
5bd52f0e
RS
4839 (setq p (point))
4840 (if (and (eq (preceding-char) ?:)
4841 (progn
4842 (forward-char -1)
4843 (skip-chars-backward " \t\n\f" lim)
4ab89e7b 4844 (memq (char-syntax (preceding-char)) '(?w ?_))))
5bd52f0e
RS
4845 (forward-sexp -1) ; Possibly label. Skip it
4846 (goto-char p)
4847 (setq stop t))))
bab27c0c
RS
4848 (or (bobp) ; ???? Needed
4849 (eq (point) lim)
029cb4d5 4850 (looking-at "[ \t]*__\\(END\\|DATA\\)__") ; After this anything goes
f83d2997
KH
4851 (progn
4852 (if test (eval test)
4853 (or (memq (preceding-char) (append (or chars "{;") nil))
4854 (and (eq (preceding-char) ?\})
f739b53b
SM
4855 (cperl-after-block-p lim))
4856 (and (eq (following-char) ?.) ; in format: see comment above
4857 (eq (get-text-property (point) 'syntax-type)
4858 'format)))))))))
f83d2997 4859
4ab89e7b
SM
4860(defun cperl-backward-to-start-of-expr (&optional lim)
4861 (condition-case nil
4862 (progn
4863 (while (and (or (not lim)
4864 (> (point) lim))
4865 (not (cperl-after-expr-p lim)))
4866 (forward-sexp -1)
4867 ;; May be after $, @, $# etc of a variable
4868 (skip-chars-backward "$@%#")))
4869 (error nil)))
4870
4871(defun cperl-at-end-of-expr (&optional lim)
4872 ;; Since the SEXP approach below is very fragile, do some overengineering
4873 (or (looking-at (concat cperl-maybe-white-and-comment-rex "[;}]"))
4874 (condition-case nil
4875 (save-excursion
4876 ;; If nothing interesting after, does as (forward-sexp -1);
4877 ;; otherwise fails, or ends at a start of following sexp.
4878 ;; XXXX PROBLEMS: if what follows (after ";") @FOO, or ${bar}
4879 ;; may be stuck after @ or $; just put some stupid workaround now:
4880 (let ((p (point)))
4881 (forward-sexp 1)
4882 (forward-sexp -1)
4883 (while (memq (preceding-char) (append "%&@$*" nil))
4884 (forward-char -1))
4885 (or (< (point) p)
4886 (cperl-after-expr-p lim))))
4887 (error t))))
4888
4889(defun cperl-forward-to-end-of-expr (&optional lim)
4890 (let ((p (point))))
4891 (condition-case nil
4892 (progn
4893 (while (and (< (point) (or lim (point-max)))
4894 (not (cperl-at-end-of-expr)))
4895 (forward-sexp 1)))
4896 (error nil)))
4897
f83d2997
KH
4898(defun cperl-backward-to-start-of-continued-exp (lim)
4899 (if (memq (preceding-char) (append ")]}\"'`" nil))
4900 (forward-sexp -1))
4901 (beginning-of-line)
4902 (if (<= (point) lim)
4903 (goto-char (1+ lim)))
4904 (skip-chars-forward " \t"))
4905
db133cb6
RS
4906(defun cperl-after-block-and-statement-beg (lim)
4907 ;; We assume that we are after ?\}
5c8b7eaf 4908 (and
db133cb6
RS
4909 (cperl-after-block-p lim)
4910 (save-excursion
4911 (forward-sexp -1)
4912 (cperl-backward-to-noncomment (point-min))
4913 (or (bobp)
bab27c0c 4914 (eq (point) lim)
db133cb6
RS
4915 (not (= (char-syntax (preceding-char)) ?w))
4916 (progn
4917 (forward-sexp -1)
5c8b7eaf 4918 (not
db133cb6
RS
4919 (looking-at
4920 "\\(map\\|grep\\|printf?\\|system\\|exec\\|tr\\|s\\)\\>")))))))
4921
f83d2997 4922\f
f83d2997
KH
4923(defun cperl-indent-exp ()
4924 "Simple variant of indentation of continued-sexp.
5bd52f0e
RS
4925
4926Will not indent comment if it starts at `comment-indent' or looks like
4927continuation of the comment on the previous line.
db133cb6 4928
5c8b7eaf 4929If `cperl-indent-region-fix-constructs', will improve spacing on
db133cb6 4930conditional/loop constructs."
f83d2997
KH
4931 (interactive)
4932 (save-excursion
4933 (let ((tmp-end (progn (end-of-line) (point))) top done)
4934 (save-excursion
4935 (beginning-of-line)
4936 (while (null done)
4937 (setq top (point))
4ab89e7b
SM
4938 ;; Plan A: if line has an unfinished paren-group, go to end-of-group
4939 (while (= -1 (nth 0 (parse-partial-sexp (point) tmp-end -1)))
f83d2997
KH
4940 (setq top (point))) ; Get the outermost parenths in line
4941 (goto-char top)
4942 (while (< (point) tmp-end)
4943 (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol
4944 (or (eolp) (forward-sexp 1)))
4ab89e7b
SM
4945 (if (> (point) tmp-end) ; Yes, there an unfinished block
4946 nil
4947 (if (eq ?\) (preceding-char))
4948 (progn ;; Plan B: find by REGEXP block followup this line
4949 (setq top (point))
4950 (condition-case nil
4951 (progn
4952 (forward-sexp -2)
4953 (if (eq (following-char) ?$ ) ; for my $var (list)
4954 (progn
4955 (forward-sexp -1)
4956 (if (looking-at "\\(my\\|local\\|our\\)\\>")
4957 (forward-sexp -1))))
4958 (if (looking-at
4959 (concat "\\(\\elsif\\|if\\|unless\\|while\\|until"
4960 "\\|for\\(each\\)?\\>\\(\\("
4961 cperl-maybe-white-and-comment-rex
4962 "\\(my\\|local\\|our\\)\\)?"
4963 cperl-maybe-white-and-comment-rex
4964 "\\$[_a-zA-Z0-9]+\\)?\\)\\>"))
4965 (progn
4966 (goto-char top)
4967 (forward-sexp 1)
4968 (setq top (point)))))
4969 (error (setq done t)))
4970 (goto-char top))
4971 (if (looking-at ; Try Plan C: continuation block
4972 (concat cperl-maybe-white-and-comment-rex
4973 "\\<\\(else\\|elsif\|continue\\)\\>"))
4974 (progn
4975 (goto-char (match-end 0))
4976 (save-excursion
4977 (end-of-line)
4978 (setq tmp-end (point))))
4979 (setq done t))))
4980 (save-excursion
4981 (end-of-line)
4982 (setq tmp-end (point))))
f83d2997
KH
4983 (goto-char tmp-end)
4984 (setq tmp-end (point-marker)))
db133cb6
RS
4985 (if cperl-indent-region-fix-constructs
4986 (cperl-fix-line-spacing tmp-end))
f83d2997
KH
4987 (cperl-indent-region (point) tmp-end))))
4988
5bd52f0e
RS
4989(defun cperl-fix-line-spacing (&optional end parse-data)
4990 "Improve whitespace in a conditional/loop construct.
4991Returns some position at the last line."
db133cb6
RS
4992 (interactive)
4993 (or end
4994 (setq end (point-max)))
83261a2f
SM
4995 (let ((ee (save-excursion (end-of-line) (point)))
4996 (cperl-indent-region-fix-constructs
4997 (or cperl-indent-region-fix-constructs 1))
4998 p pp ml have-brace ret)
db133cb6
RS
4999 (save-excursion
5000 (beginning-of-line)
5bd52f0e 5001 (setq ret (point))
5c8b7eaf 5002 ;; }? continue
5bd52f0e 5003 ;; blah; }
5c8b7eaf 5004 (if (not
5bd52f0e
RS
5005 (or (looking-at "[ \t]*\\(els\\(e\\|if\\)\\|continue\\|if\\|while\\|for\\(each\\)?\\|until\\)")
5006 (setq have-brace (save-excursion (search-forward "}" ee t)))))
5007 nil ; Do not need to do anything
83261a2f
SM
5008 ;; Looking at:
5009 ;; }
5010 ;; else
4ab89e7b
SM
5011 (if cperl-merge-trailing-else
5012 (if (looking-at
5013 "[ \t]*}[ \t]*\n[ \t\n]*\\(els\\(e\\|if\\)\\|continue\\)\\>")
5014 (progn
5015 (search-forward "}")
5016 (setq p (point))
5017 (skip-chars-forward " \t\n")
5018 (delete-region p (point))
b5b0cb34 5019 (insert (make-string cperl-indent-region-fix-constructs ?\s))
4ab89e7b
SM
5020 (beginning-of-line)))
5021 (if (looking-at "[ \t]*}[ \t]*\\(els\\(e\\|if\\)\\|continue\\)\\>")
5022 (save-excursion
5023 (search-forward "}")
5024 (delete-horizontal-space)
5025 (insert "\n")
5026 (setq ret (point))
5027 (if (cperl-indent-line parse-data)
5028 (progn
5029 (cperl-fix-line-spacing end parse-data)
5030 (setq ret (point)))))))
83261a2f
SM
5031 ;; Looking at:
5032 ;; } else
5033 (if (looking-at "[ \t]*}\\(\t*\\|[ \t][ \t]+\\)\\<\\(els\\(e\\|if\\)\\|continue\\)\\>")
5034 (progn
5035 (search-forward "}")
5036 (delete-horizontal-space)
b5b0cb34 5037 (insert (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f
SM
5038 (beginning-of-line)))
5039 ;; Looking at:
5040 ;; else {
5041 (if (looking-at
5042 "[ \t]*}?[ \t]*\\<\\(\\els\\(e\\|if\\)\\|continue\\|unless\\|if\\|while\\|for\\(each\\)?\\|until\\)\\>\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
5043 (progn
5044 (forward-word 1)
5045 (delete-horizontal-space)
b5b0cb34 5046 (insert (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f
SM
5047 (beginning-of-line)))
5048 ;; Looking at:
5049 ;; foreach my $var
5050 (if (looking-at
5051 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)\\(\t*\\|[ \t][ \t]+\\)[^ \t\n]")
5052 (progn
5053 (forward-word 2)
5054 (delete-horizontal-space)
b5b0cb34 5055 (insert (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f
SM
5056 (beginning-of-line)))
5057 ;; Looking at:
5058 ;; foreach my $var (
5059 (if (looking-at
6c389151 5060 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)[ \t]*\\$[_a-zA-Z0-9]+\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
83261a2f 5061 (progn
f739b53b 5062 (forward-sexp 3)
83261a2f
SM
5063 (delete-horizontal-space)
5064 (insert
b5b0cb34 5065 (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f 5066 (beginning-of-line)))
4ab89e7b
SM
5067 ;; Looking at (with or without "}" at start, ending after "({"):
5068 ;; } foreach my $var () OR {
83261a2f 5069 (if (looking-at
ce22dd53 5070 "[ \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]*{")
83261a2f 5071 (progn
4ab89e7b 5072 (setq ml (match-beginning 8)) ; "(" or "{" after control word
83261a2f
SM
5073 (re-search-forward "[({]")
5074 (forward-char -1)
5075 (setq p (point))
5076 (if (eq (following-char) ?\( )
5077 (progn
5078 (forward-sexp 1)
4ab89e7b 5079 (setq pp (point))) ; past parenth-group
83261a2f
SM
5080 ;; after `else' or nothing
5081 (if ml ; after `else'
5082 (skip-chars-backward " \t\n")
5083 (beginning-of-line))
5084 (setq pp nil))
5085 ;; Now after the sexp before the brace
5086 ;; Multiline expr should be special
5087 (setq ml (and pp (save-excursion (goto-char p)
5088 (search-forward "\n" pp t))))
4ab89e7b 5089 (if (and (or (not pp) (< pp end)) ; Do not go too far...
83261a2f
SM
5090 (looking-at "[ \t\n]*{"))
5091 (progn
5092 (cond
5093 ((bolp) ; Were before `{', no if/else/etc
5094 nil)
4ab89e7b 5095 ((looking-at "\\(\t*\\| [ \t]+\\){") ; Not exactly 1 SPACE
83261a2f
SM
5096 (delete-horizontal-space)
5097 (if (if ml
5098 cperl-extra-newline-before-brace-multiline
5099 cperl-extra-newline-before-brace)
5100 (progn
5101 (delete-horizontal-space)
5102 (insert "\n")
5103 (setq ret (point))
5104 (if (cperl-indent-line parse-data)
5105 (progn
5106 (cperl-fix-line-spacing end parse-data)
5107 (setq ret (point)))))
5108 (insert
b5b0cb34 5109 (make-string cperl-indent-region-fix-constructs ?\s))))
83261a2f
SM
5110 ((and (looking-at "[ \t]*\n")
5111 (not (if ml
5112 cperl-extra-newline-before-brace-multiline
5113 cperl-extra-newline-before-brace)))
5114 (setq pp (point))
5115 (skip-chars-forward " \t\n")
5116 (delete-region pp (point))
db133cb6 5117 (insert
4ab89e7b
SM
5118 (make-string cperl-indent-region-fix-constructs ?\ )))
5119 ((and (looking-at "[\t ]*{")
5120 (if ml cperl-extra-newline-before-brace-multiline
5121 cperl-extra-newline-before-brace))
5122 (delete-horizontal-space)
5123 (insert "\n")
5124 (setq ret (point))
5125 (if (cperl-indent-line parse-data)
5126 (progn
5127 (cperl-fix-line-spacing end parse-data)
5128 (setq ret (point))))))
83261a2f
SM
5129 ;; Now we are before `{'
5130 (if (looking-at "[ \t\n]*{[ \t]*[^ \t\n#]")
5131 (progn
5132 (skip-chars-forward " \t\n")
5133 (setq pp (point))
5134 (forward-sexp 1)
5135 (setq p (point))
5136 (goto-char pp)
5137 (setq ml (search-forward "\n" p t))
5138 (if (or cperl-break-one-line-blocks-when-indent ml)
5139 ;; not good: multi-line BLOCK
5140 (progn
5141 (goto-char (1+ pp))
5142 (delete-horizontal-space)
5143 (insert "\n")
5144 (setq ret (point))
5145 (if (cperl-indent-line parse-data)
5146 (setq ret (cperl-fix-line-spacing end parse-data)))))))))))
5147 (beginning-of-line)
5148 (setq p (point) pp (save-excursion (end-of-line) (point))) ; May be different from ee.
5149 ;; Now check whether there is a hanging `}'
5150 ;; Looking at:
5151 ;; } blah
5152 (if (and
5153 cperl-fix-hanging-brace-when-indent
5154 have-brace
5155 (not (looking-at "[ \t]*}[ \t]*\\(\\<\\(els\\(if\\|e\\)\\|continue\\|while\\|until\\)\\>\\|$\\|#\\)"))
5156 (condition-case nil
5157 (progn
5158 (up-list 1)
5159 (if (and (<= (point) pp)
5160 (eq (preceding-char) ?\} )
5161 (cperl-after-block-and-statement-beg (point-min)))
5162 t
5163 (goto-char p)
5164 nil))
5165 (error nil)))
5166 (progn
5167 (forward-char -1)
5168 (skip-chars-backward " \t")
5169 (if (bolp)
5170 ;; `}' was the first thing on the line, insert NL *after* it.
5171 (progn
5172 (cperl-indent-line parse-data)
5173 (search-forward "}")
5174 (delete-horizontal-space)
5175 (insert "\n"))
5176 (delete-horizontal-space)
5177 (or (eq (preceding-char) ?\;)
5178 (bolp)
5179 (and (eq (preceding-char) ?\} )
5180 (cperl-after-block-p (point-min)))
5181 (insert ";"))
5182 (insert "\n")
5183 (setq ret (point)))
5184 (if (cperl-indent-line parse-data)
5185 (setq ret (cperl-fix-line-spacing end parse-data)))
5186 (beginning-of-line)))))
5bd52f0e
RS
5187 ret))
5188
5189(defvar cperl-update-start) ; Do not need to make them local
5190(defvar cperl-update-end)
5191(defun cperl-delay-update-hook (beg end old-len)
5192 (setq cperl-update-start (min beg (or cperl-update-start (point-max))))
5193 (setq cperl-update-end (max end (or cperl-update-end (point-min)))))
db133cb6 5194
f83d2997
KH
5195(defun cperl-indent-region (start end)
5196 "Simple variant of indentation of region in CPerl mode.
5c8b7eaf 5197Should be slow. Will not indent comment if it starts at `comment-indent'
f83d2997 5198or looks like continuation of the comment on the previous line.
5c8b7eaf
SS
5199Indents all the lines whose first character is between START and END
5200inclusive.
db133cb6 5201
5c8b7eaf 5202If `cperl-indent-region-fix-constructs', will improve spacing on
db133cb6 5203conditional/loop constructs."
f83d2997 5204 (interactive "r")
5bd52f0e 5205 (cperl-update-syntaxification end end)
f83d2997 5206 (save-excursion
5bd52f0e 5207 (let (cperl-update-start cperl-update-end (h-a-c after-change-functions))
83261a2f
SM
5208 (let ((indent-info (if cperl-emacs-can-parse
5209 (list nil nil nil) ; Cannot use '(), since will modify
5210 nil))
c326ddd1 5211 (pm 0)
83261a2f
SM
5212 after-change-functions ; Speed it up!
5213 st comm old-comm-indent new-comm-indent p pp i empty)
5bd52f0e 5214 (if h-a-c (add-hook 'after-change-functions 'cperl-delay-update-hook))
83261a2f
SM
5215 (goto-char start)
5216 (setq old-comm-indent (and (cperl-to-comment-or-eol)
5217 (current-column))
5218 new-comm-indent old-comm-indent)
5219 (goto-char start)
5220 (setq end (set-marker (make-marker) end)) ; indentation changes pos
5221 (or (bolp) (beginning-of-line 2))
83261a2f 5222 (while (and (<= (point) end) (not (eobp))) ; bol to check start
5bd52f0e
RS
5223 (setq st (point))
5224 (if (or
5225 (setq empty (looking-at "[ \t]*\n"))
5226 (and (setq comm (looking-at "[ \t]*#"))
83261a2f
SM
5227 (or (eq (current-indentation) (or old-comm-indent
5228 comment-column))
5bd52f0e 5229 (setq old-comm-indent nil))))
f83d2997 5230 (if (and old-comm-indent
5bd52f0e 5231 (not empty)
f83d2997 5232 (= (current-indentation) old-comm-indent)
5bd52f0e
RS
5233 (not (eq (get-text-property (point) 'syntax-type) 'pod))
5234 (not (eq (get-text-property (point) 'syntax-table)
5235 cperl-st-cfence)))
83261a2f
SM
5236 (let ((comment-column new-comm-indent))
5237 (indent-for-comment)))
5238 (progn
5bd52f0e 5239 (setq i (cperl-indent-line indent-info))
f83d2997 5240 (or comm
db133cb6 5241 (not i)
f83d2997 5242 (progn
db133cb6 5243 (if cperl-indent-region-fix-constructs
5bd52f0e 5244 (goto-char (cperl-fix-line-spacing end indent-info)))
83261a2f
SM
5245 (if (setq old-comm-indent
5246 (and (cperl-to-comment-or-eol)
5247 (not (memq (get-text-property (point)
5248 'syntax-type)
5249 '(pod here-doc)))
5c8b7eaf 5250 (not (eq (get-text-property (point)
5bd52f0e
RS
5251 'syntax-table)
5252 cperl-st-cfence))
f83d2997
KH
5253 (current-column)))
5254 (progn (indent-for-comment)
5255 (skip-chars-backward " \t")
5256 (skip-chars-backward "#")
5257 (setq new-comm-indent (current-column))))))))
335dd1f1 5258 (beginning-of-line 2)))
5bd52f0e 5259 ;; Now run the update hooks
83261a2f
SM
5260 (and after-change-functions
5261 cperl-update-end
5262 (save-excursion
5263 (goto-char cperl-update-end)
5264 (insert " ")
5265 (delete-char -1)
5266 (goto-char cperl-update-start)
5267 (insert " ")
5268 (delete-char -1))))))
f83d2997 5269
f83d2997
KH
5270;; Stolen from lisp-mode with a lot of improvements
5271
5272(defun cperl-fill-paragraph (&optional justify iteration)
82eb0dae 5273 "Like `fill-paragraph', but handle CPerl comments.
f83d2997
KH
5274If any of the current line is a comment, fill the comment or the
5275block of it that point is in, preserving the comment's initial
5276indentation and initial hashes. Behaves usually outside of comment."
82eb0dae 5277 ;; (interactive "P") ; Only works when called from fill-paragraph. -stef
83261a2f 5278 (let (;; Non-nil if the current line contains a comment.
f83d2997 5279 has-comment
4ab89e7b 5280 fill-paragraph-function ; do not recurse
f83d2997
KH
5281 ;; If has-comment, the appropriate fill-prefix for the comment.
5282 comment-fill-prefix
5283 ;; Line that contains code and comment (or nil)
5284 start
5285 c spaces len dc (comment-column comment-column))
5286 ;; Figure out what kind of comment we are looking at.
5287 (save-excursion
5288 (beginning-of-line)
5289 (cond
5290
5291 ;; A line with nothing but a comment on it?
5292 ((looking-at "[ \t]*#[# \t]*")
5293 (setq has-comment t
5294 comment-fill-prefix (buffer-substring (match-beginning 0)
5295 (match-end 0))))
5296
5297 ;; A line with some code, followed by a comment? Remember that the
5298 ;; semi which starts the comment shouldn't be part of a string or
5299 ;; character.
5300 ((cperl-to-comment-or-eol)
5301 (setq has-comment t)
5302 (looking-at "#+[ \t]*")
5c8b7eaf 5303 (setq start (point) c (current-column)
f83d2997 5304 comment-fill-prefix
b5b0cb34 5305 (concat (make-string (current-column) ?\s)
f83d2997 5306 (buffer-substring (match-beginning 0) (match-end 0)))
5c8b7eaf 5307 spaces (progn (skip-chars-backward " \t")
f83d2997 5308 (buffer-substring (point) start))
5c8b7eaf 5309 dc (- c (current-column)) len (- start (point))
f83d2997
KH
5310 start (point-marker))
5311 (delete-char len)
4ab89e7b 5312 (insert (make-string dc ?-))))) ; Placeholder (to avoid splitting???)
f83d2997 5313 (if (not has-comment)
83261a2f 5314 (fill-paragraph justify) ; Do the usual thing outside of comment
f83d2997
KH
5315 ;; Narrow to include only the comment, and then fill the region.
5316 (save-restriction
5317 (narrow-to-region
5318 ;; Find the first line we should include in the region to fill.
5319 (if start (progn (beginning-of-line) (point))
5320 (save-excursion
5321 (while (and (zerop (forward-line -1))
5322 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
5323 ;; We may have gone to far. Go forward again.
5324 (or (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")
5325 (forward-line 1))
5326 (point)))
5327 ;; Find the beginning of the first line past the region to fill.
5328 (save-excursion
5329 (while (progn (forward-line 1)
5330 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
5331 (point)))
5332 ;; Remove existing hashes
cff301be 5333 (save-excursion
4ab89e7b
SM
5334 (goto-char (point-min))
5335 (while (progn (forward-line 1) (< (point) (point-max)))
5336 (skip-chars-forward " \t")
5337 (if (looking-at "#+")
5338 (progn
5339 (if (and (eq (point) (match-beginning 0))
5340 (not (eq (point) (match-end 0)))) nil
5341 (error
5342 "Bug in Emacs: `looking-at' in `narrow-to-region': match-data is garbage"))
5343 (delete-char (- (match-end 0) (match-beginning 0)))))))
f83d2997
KH
5344
5345 ;; Lines with only hashes on them can be paragraph boundaries.
5346 (let ((paragraph-start (concat paragraph-start "\\|^[ \t#]*$"))
5347 (paragraph-separate (concat paragraph-start "\\|^[ \t#]*$"))
5348 (fill-prefix comment-fill-prefix))
5349 (fill-paragraph justify)))
5350 (if (and start)
5c8b7eaf 5351 (progn
f83d2997
KH
5352 (goto-char start)
5353 (if (> dc 0)
83261a2f 5354 (progn (delete-char dc) (insert spaces)))
f83d2997
KH
5355 (if (or (= (current-column) c) iteration) nil
5356 (setq comment-column c)
5357 (indent-for-comment)
5358 ;; Repeat once more, flagging as iteration
4ab89e7b
SM
5359 (cperl-fill-paragraph justify t))))))
5360 t)
f83d2997
KH
5361
5362(defun cperl-do-auto-fill ()
5363 ;; Break out if the line is short enough
5364 (if (> (save-excursion
5365 (end-of-line)
5366 (current-column))
5367 fill-column)
83261a2f
SM
5368 (let ((c (save-excursion (beginning-of-line)
5369 (cperl-to-comment-or-eol) (point)))
8038e2cf 5370 (s (memq (following-char) '(?\s ?\t))) marker)
82eb0dae
SM
5371 (if (>= c (point))
5372 ;; Don't break line inside code: only inside comment.
5373 nil
83261a2f 5374 (setq marker (point-marker))
82eb0dae 5375 (fill-paragraph nil)
83261a2f
SM
5376 (goto-char marker)
5377 ;; Is not enough, sometimes marker is a start of line
5378 (if (bolp) (progn (re-search-forward "#+[ \t]*")
5379 (goto-char (match-end 0))))
5380 ;; Following space could have gone:
8038e2cf 5381 (if (or (not s) (memq (following-char) '(?\s ?\t))) nil
83261a2f
SM
5382 (insert " ")
5383 (backward-char 1))
5384 ;; Previous space could have gone:
8038e2cf 5385 (or (memq (preceding-char) '(?\s ?\t)) (insert " "))))))
f83d2997 5386
f83d2997
KH
5387(defun cperl-imenu-addback (lst &optional isback name)
5388 ;; We suppose that the lst is a DAG, unless the first element only
5389 ;; loops back, and ISBACK is set. Thus this function cannot be
5390 ;; applied twice without ISBACK set.
5391 (cond ((not cperl-imenu-addback) lst)
5392 (t
5c8b7eaf 5393 (or name
f83d2997 5394 (setq name "+++BACK+++"))
dba01120
GM
5395 (mapc (lambda (elt)
5396 (if (and (listp elt) (listp (cdr elt)))
5397 (progn
5398 ;; In the other order it goes up
5399 ;; one level only ;-(
5400 (setcdr elt (cons (cons name lst)
5401 (cdr elt)))
5402 (cperl-imenu-addback (cdr elt) t name))))
5403 (if isback (cdr lst) lst))
f83d2997
KH
5404 lst)))
5405
80585273 5406(defun cperl-imenu--create-perl-index (&optional regexp)
f83d2997 5407 (require 'imenu) ; May be called from TAGS creator
5c8b7eaf 5408 (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '())
f83d2997
KH
5409 (index-unsorted-alist '()) (i-s-f (default-value 'imenu-sort-function))
5410 (index-meth-alist '()) meth
4ab89e7b
SM
5411 packages ends-ranges p marker is-proto
5412 (prev-pos 0) is-pack index index1 name (end-range 0) package)
f83d2997 5413 (goto-char (point-min))
6c389151 5414 (cperl-update-syntaxification (point-max) (point-max))
f83d2997
KH
5415 ;; Search for the function
5416 (progn ;;save-match-data
5417 (while (re-search-forward
80585273 5418 (or regexp cperl-imenu--function-name-regexp-perl)
f83d2997 5419 nil t)
4ab89e7b 5420 ;; 2=package-group, 5=package-name 8=sub-name
f83d2997
KH
5421 (cond
5422 ((and ; Skip some noise if building tags
4ab89e7b
SM
5423 (match-beginning 5) ; package name
5424 ;;(eq (char-after (match-beginning 2)) ?p) ; package
f83d2997 5425 (not (save-match-data
83261a2f 5426 (looking-at "[ \t\n]*;")))) ; Plain text word 'package'
f83d2997
KH
5427 nil)
5428 ((and
4ab89e7b
SM
5429 (or (match-beginning 2)
5430 (match-beginning 8)) ; package or sub
6c389151 5431 ;; Skip if quoted (will not skip multi-line ''-strings :-():
f83d2997
KH
5432 (null (get-text-property (match-beginning 1) 'syntax-table))
5433 (null (get-text-property (match-beginning 1) 'syntax-type))
5434 (null (get-text-property (match-beginning 1) 'in-pod)))
4ab89e7b 5435 (setq is-pack (match-beginning 2))
f83d2997
KH
5436 ;; (if (looking-at "([^()]*)[ \t\n\f]*")
5437 ;; (goto-char (match-end 0))) ; Messes what follows
4ab89e7b 5438 (setq meth nil
f83d2997
KH
5439 p (point))
5440 (while (and ends-ranges (>= p (car ends-ranges)))
5441 ;; delete obsolete entries
5442 (setq ends-ranges (cdr ends-ranges) packages (cdr packages)))
5443 (setq package (or (car packages) "")
5444 end-range (or (car ends-ranges) 0))
4ab89e7b
SM
5445 (if is-pack ; doing "package"
5446 (progn
5447 (if (match-beginning 5) ; named package
5448 (setq name (buffer-substring (match-beginning 5)
5449 (match-end 5))
5450 name (progn
5451 (set-text-properties 0 (length name) nil name)
5452 name)
5453 package (concat name "::")
5454 name (concat "package " name))
5455 ;; Support nameless packages
5456 (setq name "package;" package ""))
5457 (setq end-range
5458 (save-excursion
5459 (parse-partial-sexp (point) (point-max) -1) (point))
5460 ends-ranges (cons end-range ends-ranges)
5461 packages (cons package packages)))
5462 (setq is-proto
5463 (or (eq (following-char) ?\;)
5464 (eq 0 (get-text-property (point) 'attrib-group)))))
f83d2997 5465 ;; Skip this function name if it is a prototype declaration.
4ab89e7b
SM
5466 (if (and is-proto (not is-pack)) nil
5467 (or is-pack
5468 (setq name
5469 (buffer-substring (match-beginning 8) (match-end 8)))
5470 (set-text-properties 0 (length name) nil name))
5471 (setq marker (make-marker))
5472 (set-marker marker (match-end (if is-pack 2 8)))
5473 (cond (is-pack nil)
5474 ((string-match "[:']" name)
5475 (setq meth t))
5476 ((> p end-range) nil)
5477 (t
5478 (setq name (concat package name) meth t)))
6c389151 5479 (setq index (cons name marker))
4ab89e7b 5480 (if is-pack
f83d2997
KH
5481 (push index index-pack-alist)
5482 (push index index-alist))
5483 (if meth (push index index-meth-alist))
5484 (push index index-unsorted-alist)))
4ab89e7b
SM
5485 ((match-beginning 16) ; POD section
5486 (setq name (buffer-substring (match-beginning 17) (match-end 17))
5487 marker (make-marker))
5488 (set-marker marker (match-beginning 17))
f83d2997 5489 (set-text-properties 0 (length name) nil name)
4ab89e7b
SM
5490 (setq name (concat (make-string
5491 (* 3 (- (char-after (match-beginning 16)) ?1))
5492 ?\ )
5493 name)
5494 index (cons name marker))
f83d2997
KH
5495 (setq index1 (cons (concat "=" name) (cdr index)))
5496 (push index index-pod-alist)
5497 (push index1 index-unsorted-alist)))))
5c8b7eaf 5498 (setq index-alist
f83d2997
KH
5499 (if (default-value 'imenu-sort-function)
5500 (sort index-alist (default-value 'imenu-sort-function))
83261a2f 5501 (nreverse index-alist)))
f83d2997
KH
5502 (and index-pod-alist
5503 (push (cons "+POD headers+..."
5504 (nreverse index-pod-alist))
5505 index-alist))
5506 (and (or index-pack-alist index-meth-alist)
5507 (let ((lst index-pack-alist) hier-list pack elt group name)
5508 ;; Remove "package ", reverse and uniquify.
5509 (while lst
5510 (setq elt (car lst) lst (cdr lst) name (substring (car elt) 8))
5511 (if (assoc name hier-list) nil
5512 (setq hier-list (cons (cons name (cdr elt)) hier-list))))
5513 (setq lst index-meth-alist)
5514 (while lst
5515 (setq elt (car lst) lst (cdr lst))
5516 (cond ((string-match "\\(::\\|'\\)[_a-zA-Z0-9]+$" (car elt))
5517 (setq pack (substring (car elt) 0 (match-beginning 0)))
5c8b7eaf 5518 (if (setq group (assoc pack hier-list))
f83d2997
KH
5519 (if (listp (cdr group))
5520 ;; Have some functions already
5c8b7eaf
SS
5521 (setcdr group
5522 (cons (cons (substring
f83d2997
KH
5523 (car elt)
5524 (+ 2 (match-beginning 0)))
5525 (cdr elt))
5526 (cdr group)))
5c8b7eaf 5527 (setcdr group (list (cons (substring
f83d2997
KH
5528 (car elt)
5529 (+ 2 (match-beginning 0)))
5530 (cdr elt)))))
5c8b7eaf
SS
5531 (setq hier-list
5532 (cons (cons pack
5533 (list (cons (substring
f83d2997
KH
5534 (car elt)
5535 (+ 2 (match-beginning 0)))
5536 (cdr elt))))
5537 hier-list))))))
5538 (push (cons "+Hierarchy+..."
5539 hier-list)
5540 index-alist)))
5541 (and index-pack-alist
5542 (push (cons "+Packages+..."
5543 (nreverse index-pack-alist))
5544 index-alist))
5c8b7eaf 5545 (and (or index-pack-alist index-pod-alist
f83d2997
KH
5546 (default-value 'imenu-sort-function))
5547 index-unsorted-alist
5548 (push (cons "+Unsorted List+..."
5549 (nreverse index-unsorted-alist))
5550 index-alist))
5551 (cperl-imenu-addback index-alist)))
5552
6c389151 5553\f
6c389151
SM
5554;; Suggested by Mark A. Hershberger
5555(defun cperl-outline-level ()
5556 (looking-at outline-regexp)
5557 (cond ((not (match-beginning 1)) 0) ; beginning-of-file
4ab89e7b
SM
5558;;;; 2=package-group, 5=package-name 8=sub-name 16=head-level
5559 ((match-beginning 2) 0) ; package
5560 ((match-beginning 8) 1) ; sub
5561 ((match-beginning 16)
5562 (- (char-after (match-beginning 16)) ?0)) ; headN ==> N
5563 (t 5))) ; should not happen
6c389151
SM
5564
5565\f
f83d2997
KH
5566(defun cperl-windowed-init ()
5567 "Initialization under windowed version."
f453f5a8 5568 (cond ((featurep 'ps-print)
82d9a08d
SM
5569 (or cperl-faces-init
5570 (progn
5571 (and (boundp 'font-lock-multiline)
5572 (setq cperl-font-lock-multiline t))
5573 (cperl-init-faces))))
f453f5a8
CY
5574 ((not cperl-faces-init)
5575 (add-hook 'font-lock-mode-hook
5576 (function
5577 (lambda ()
5578 (if (memq major-mode '(perl-mode cperl-mode))
5579 (progn
5580 (or cperl-faces-init (cperl-init-faces)))))))
5581 (if (fboundp 'eval-after-load)
5582 (eval-after-load
5583 "ps-print"
5584 '(or cperl-faces-init (cperl-init-faces)))))))
db133cb6 5585
5efe6a56 5586(defvar cperl-font-lock-keywords-1 nil
80585273 5587 "Additional expressions to highlight in Perl mode. Minimal set.")
5efe6a56 5588(defvar cperl-font-lock-keywords nil
80585273 5589 "Additional expressions to highlight in Perl mode. Default set.")
5efe6a56 5590(defvar cperl-font-lock-keywords-2 nil
80585273
DL
5591 "Additional expressions to highlight in Perl mode. Maximal set")
5592
db133cb6
RS
5593(defun cperl-load-font-lock-keywords ()
5594 (or cperl-faces-init (cperl-init-faces))
5efe6a56 5595 cperl-font-lock-keywords)
db133cb6
RS
5596
5597(defun cperl-load-font-lock-keywords-1 ()
5598 (or cperl-faces-init (cperl-init-faces))
5efe6a56 5599 cperl-font-lock-keywords-1)
db133cb6
RS
5600
5601(defun cperl-load-font-lock-keywords-2 ()
5602 (or cperl-faces-init (cperl-init-faces))
5efe6a56 5603 cperl-font-lock-keywords-2)
f83d2997 5604
5bd52f0e
RS
5605(defun cperl-init-faces-weak ()
5606 ;; Allow `cperl-find-pods-heres' to run.
5607 (or (boundp 'font-lock-constant-face)
5608 (cperl-force-face font-lock-constant-face
4ab89e7b
SM
5609 "Face for constant and label names"))
5610 (or (boundp 'font-lock-warning-face)
5611 (cperl-force-face font-lock-warning-face
5612 "Face for things which should stand out"))
5613 ;;(setq font-lock-constant-face 'font-lock-constant-face)
5614 )
5bd52f0e 5615
f83d2997 5616(defun cperl-init-faces ()
5bd52f0e 5617 (condition-case errs
f83d2997
KH
5618 (progn
5619 (require 'font-lock)
5620 (and (fboundp 'font-lock-fontify-anchored-keywords)
5621 (featurep 'font-lock-extra)
5622 (message "You have an obsolete package `font-lock-extra'. Install `choose-color'."))
5623 (let (t-font-lock-keywords t-font-lock-keywords-1 font-lock-anchored)
f83d2997
KH
5624 (if (fboundp 'font-lock-fontify-anchored-keywords)
5625 (setq font-lock-anchored t))
5c8b7eaf 5626 (setq
f83d2997
KH
5627 t-font-lock-keywords
5628 (list
ac6857fb 5629 `("[ \t]+$" 0 ',cperl-invalid-face t)
f83d2997
KH
5630 (cons
5631 (concat
5632 "\\(^\\|[^$@%&\\]\\)\\<\\("
5633 (mapconcat
5634 'identity
5635 '("if" "until" "while" "elsif" "else" "unless" "for"
5636 "foreach" "continue" "exit" "die" "last" "goto" "next"
4ab89e7b 5637 "redo" "return" "local" "exec" "sub" "do" "dump" "use" "our"
6c389151 5638 "require" "package" "eval" "my" "BEGIN" "END" "CHECK" "INIT")
f83d2997
KH
5639 "\\|") ; Flow control
5640 "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]"
5641 ; In what follows we use `type' style
5642 ; for overwritable builtins
5643 (list
5644 (concat
5645 "\\(^\\|[^$@%&\\]\\)\\<\\("
5646 ;; "CORE" "__FILE__" "__LINE__" "abs" "accept" "alarm"
5647 ;; "and" "atan2" "bind" "binmode" "bless" "caller"
5648 ;; "chdir" "chmod" "chown" "chr" "chroot" "close"
5649 ;; "closedir" "cmp" "connect" "continue" "cos" "crypt"
5650 ;; "dbmclose" "dbmopen" "die" "dump" "endgrent"
5651 ;; "endhostent" "endnetent" "endprotoent" "endpwent"
5652 ;; "endservent" "eof" "eq" "exec" "exit" "exp" "fcntl"
5653 ;; "fileno" "flock" "fork" "formline" "ge" "getc"
5654 ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
5655 ;; "gethostbyname" "gethostent" "getlogin"
5656 ;; "getnetbyaddr" "getnetbyname" "getnetent"
5657 ;; "getpeername" "getpgrp" "getppid" "getpriority"
5658 ;; "getprotobyname" "getprotobynumber" "getprotoent"
5659 ;; "getpwent" "getpwnam" "getpwuid" "getservbyname"
5660 ;; "getservbyport" "getservent" "getsockname"
5661 ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int"
5662 ;; "ioctl" "join" "kill" "lc" "lcfirst" "le" "length"
5bd52f0e 5663 ;; "link" "listen" "localtime" "lock" "log" "lstat" "lt"
f83d2997
KH
5664 ;; "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "ne"
5665 ;; "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
5666 ;; "quotemeta" "rand" "read" "readdir" "readline"
5667 ;; "readlink" "readpipe" "recv" "ref" "rename" "require"
5668 ;; "reset" "reverse" "rewinddir" "rindex" "rmdir" "seek"
5669 ;; "seekdir" "select" "semctl" "semget" "semop" "send"
5670 ;; "setgrent" "sethostent" "setnetent" "setpgrp"
5671 ;; "setpriority" "setprotoent" "setpwent" "setservent"
5672 ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite"
5673 ;; "shutdown" "sin" "sleep" "socket" "socketpair"
5674 ;; "sprintf" "sqrt" "srand" "stat" "substr" "symlink"
6c389151 5675 ;; "syscall" "sysopen" "sysread" "system" "syswrite" "tell"
f83d2997
KH
5676 ;; "telldir" "time" "times" "truncate" "uc" "ucfirst"
5677 ;; "umask" "unlink" "unpack" "utime" "values" "vec"
5678 ;; "wait" "waitpid" "wantarray" "warn" "write" "x" "xor"
5c8b7eaf 5679 "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|"
f83d2997
KH
5680 "b\\(in\\(d\\|mode\\)\\|less\\)\\|"
5681 "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|"
5682 "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|"
5683 "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|"
5684 "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|"
5685 "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|"
5686 "f\\(ileno\\|cntl\\|lock\\|or\\(k\\|mline\\)\\)\\|"
5687 "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|"
5688 "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w"
5689 "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|"
5690 "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|"
5691 "ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|"
5692 "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|"
5693 "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|"
5694 "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e"
5bd52f0e 5695 "\\(\\|ngth\\)\\|o\\(c\\(altime\\|k\\)\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|"
f83d2997
KH
5696 "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|"
5697 "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|"
5698 "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin"
5699 "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name"
5700 "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r"
5701 "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|"
5702 "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|"
5703 "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|"
6c389151 5704 "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|open\\|tem\\|write\\)\\|"
f83d2997
KH
5705 "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|"
5706 "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|"
5707 "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|"
5708 "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|"
5709 "x\\(\\|or\\)\\|__\\(FILE__\\|LINE__\\|PACKAGE__\\)"
5710 "\\)\\>") 2 'font-lock-type-face)
5711 ;; In what follows we use `other' style
5712 ;; for nonoverwritable builtins
5713 ;; Somehow 's', 'm' are not auto-generated???
5714 (list
5715 (concat
5716 "\\(^\\|[^$@%&\\]\\)\\<\\("
6c389151 5717 ;; "AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "__END__" "chomp"
f83d2997
KH
5718 ;; "chop" "defined" "delete" "do" "each" "else" "elsif"
5719 ;; "eval" "exists" "for" "foreach" "format" "goto"
5720 ;; "grep" "if" "keys" "last" "local" "map" "my" "next"
4ab89e7b 5721 ;; "no" "our" "package" "pop" "pos" "print" "printf" "push"
f83d2997
KH
5722 ;; "q" "qq" "qw" "qx" "redo" "return" "scalar" "shift"
5723 ;; "sort" "splice" "split" "study" "sub" "tie" "tr"
5724 ;; "undef" "unless" "unshift" "untie" "until" "use"
5725 ;; "while" "y"
6c389151 5726 "AUTOLOAD\\|BEGIN\\|CHECK\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|"
f83d2997 5727 "o\\)\\|DESTROY\\|e\\(ach\\|val\\|xists\\|ls\\(e\\|if\\)\\)\\|"
6c389151
SM
5728 "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|INIT\\|if\\|keys\\|"
5729 "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|our\\|"
f83d2997 5730 "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|"
5bd52f0e 5731 "q\\(\\|q\\|w\\|x\\|r\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|"
f83d2997
KH
5732 "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|"
5733 "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|"
5734 "while\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added manually
5735 "\\|[sm]" ; Added manually
4ab89e7b 5736 "\\)\\>") 2 'cperl-nonoverridable-face)
f83d2997
KH
5737 ;; (mapconcat 'identity
5738 ;; '("#endif" "#else" "#ifdef" "#ifndef" "#if"
5739 ;; "#include" "#define" "#undef")
5740 ;; "\\|")
5741 '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0
5742 font-lock-function-name-face keep) ; Not very good, triggers at "[a-z]"
4ab89e7b
SM
5743 ;; This highlights declarations and definitions differenty.
5744 ;; We do not try to highlight in the case of attributes:
5745 ;; it is already done by `cperl-find-pods-heres'
5746 (list (concat "\\<sub"
5747 cperl-white-and-comment-rex ; whitespace/comments
5748 "\\([^ \n\t{;()]+\\)" ; 2=name (assume non-anonymous)
5749 "\\("
5750 cperl-maybe-white-and-comment-rex ;whitespace/comments?
5751 "([^()]*)\\)?" ; prototype
5752 cperl-maybe-white-and-comment-rex ; whitespace/comments?
5753 "[{;]")
5754 2 (if cperl-font-lock-multiline
5755 '(if (eq (char-after (cperl-1- (match-end 0))) ?\{ )
5756 'font-lock-function-name-face
5757 'font-lock-variable-name-face)
5758 ;; need to manually set 'multiline' for older font-locks
5759 '(progn
5760 (if (< 1 (count-lines (match-beginning 0)
5761 (match-end 0)))
5762 (put-text-property
5763 (+ 3 (match-beginning 0)) (match-end 0)
5764 'syntax-type 'multiline))
5765 (if (eq (char-after (cperl-1- (match-end 0))) ?\{ )
5766 'font-lock-function-name-face
5767 'font-lock-variable-name-face))))
f83d2997
KH
5768 '("\\<\\(package\\|require\\|use\\|import\\|no\\|bootstrap\\)[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t;]" ; require A if B;
5769 2 font-lock-function-name-face)
5770 '("^[ \t]*format[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t]*=[ \t]*$"
5771 1 font-lock-function-name-face)
5772 (cond ((featurep 'font-lock-extra)
5c8b7eaf 5773 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
f83d2997
KH
5774 (2 font-lock-string-face t)
5775 (0 '(restart 2 t)))) ; To highlight $a{bc}{ef}
5776 (font-lock-anchored
5777 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
5778 (2 font-lock-string-face t)
5779 ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
5780 nil nil
5781 (1 font-lock-string-face t))))
5782 (t '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
5783 2 font-lock-string-face t)))
db133cb6 5784 '("[\[ \t{,(]\\(-?[a-zA-Z0-9_:]+\\)[ \t]*=>" 1
f83d2997 5785 font-lock-string-face t)
5c8b7eaf 5786 '("^[ \t]*\\([a-zA-Z0-9_]+[ \t]*:\\)[ \t]*\\($\\|{\\|\\<\\(until\\|while\\|for\\(each\\)?\\|do\\)\\>\\)" 1
83261a2f 5787 font-lock-constant-face) ; labels
f83d2997 5788 '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets
883212ce 5789 2 font-lock-constant-face)
6c389151
SM
5790 ;; Uncomment to get perl-mode-like vars
5791 ;;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
5792 ;;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
5793 ;;; (2 (cons font-lock-variable-name-face '(underline))))
f83d2997 5794 (cond ((featurep 'font-lock-extra)
6c389151 5795 '("^[ \t]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
f83d2997
KH
5796 (3 font-lock-variable-name-face)
5797 (4 '(another 4 nil
5798 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
5799 (1 font-lock-variable-name-face)
5c8b7eaf 5800 (2 '(restart 2 nil) nil t)))
f83d2997
KH
5801 nil t))) ; local variables, multiple
5802 (font-lock-anchored
4ab89e7b 5803 ;; 1=my_etc, 2=white? 3=(+white? 4=white? 5=var
9edd6ee6 5804 `(,(concat "\\<\\(my\\|local\\|our\\)"
4ab89e7b
SM
5805 cperl-maybe-white-and-comment-rex
5806 "\\(("
5807 cperl-maybe-white-and-comment-rex
9edd6ee6
SM
5808 "\\)?\\([$@%*]\\([a-zA-Z0-9_:]+\\|[^a-zA-Z0-9_]\\)\\)")
5809 (5 ,(if cperl-font-lock-multiline
4ab89e7b
SM
5810 'font-lock-variable-name-face
5811 '(progn (setq cperl-font-lock-multiline-start
5812 (match-beginning 0))
9edd6ee6
SM
5813 'font-lock-variable-name-face)))
5814 (,(concat "\\="
4ab89e7b
SM
5815 cperl-maybe-white-and-comment-rex
5816 ","
5817 cperl-maybe-white-and-comment-rex
9edd6ee6 5818 "\\([$@%*]\\([a-zA-Z0-9_:]+\\|[^a-zA-Z0-9_]\\)\\)")
cb5bf6ba 5819 ;; Bug in font-lock: limit is used not only to limit
4ab89e7b
SM
5820 ;; searches, but to set the "extend window for
5821 ;; facification" property. Thus we need to minimize.
9edd6ee6 5822 ,(if cperl-font-lock-multiline
4ab89e7b
SM
5823 '(if (match-beginning 3)
5824 (save-excursion
5825 (goto-char (match-beginning 3))
5826 (condition-case nil
5827 (forward-sexp 1)
5828 (error
5829 (condition-case nil
5830 (forward-char 200)
5831 (error nil)))) ; typeahead
5832 (1- (point))) ; report limit
5833 (forward-char -2)) ; disable continued expr
5834 '(if (match-beginning 3)
5835 (point-max) ; No limit for continuation
9edd6ee6
SM
5836 (forward-char -2))) ; disable continued expr
5837 ,(if cperl-font-lock-multiline
4ab89e7b
SM
5838 nil
5839 '(progn ; Do at end
5840 ;; "my" may be already fontified (POD),
5841 ;; so cperl-font-lock-multiline-start is nil
5842 (if (or (not cperl-font-lock-multiline-start)
5843 (> 2 (count-lines
5844 cperl-font-lock-multiline-start
5845 (point))))
5846 nil
5847 (put-text-property
5848 (1+ cperl-font-lock-multiline-start) (point)
5849 'syntax-type 'multiline))
9edd6ee6
SM
5850 (setq cperl-font-lock-multiline-start nil)))
5851 (3 font-lock-variable-name-face))))
4ab89e7b 5852 (t '("^[ \t{}]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
f83d2997 5853 3 font-lock-variable-name-face)))
6c389151 5854 '("\\<for\\(each\\)?\\([ \t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*("
eb6121fc 5855 4 font-lock-variable-name-face)
9ed9fd35
DP
5856 ;; Avoid $!, and s!!, qq!! etc. when not fontifying syntaxically
5857 '("\\(?:^\\|[^smywqrx$]\\)\\(!\\)" 1 font-lock-negation-char-face)
eb6121fc 5858 '("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend)))
a1506d29 5859 (setq
f83d2997
KH
5860 t-font-lock-keywords-1
5861 (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock
4ab89e7b
SM
5862 ;; not yet as of XEmacs 19.12, works with 21.1.11
5863 (or
6546555e 5864 (not (featurep 'xemacs))
4ab89e7b
SM
5865 (string< "21.1.9" emacs-version)
5866 (and (string< "21.1.10" emacs-version)
5867 (string< emacs-version "21.1.2")))
f83d2997
KH
5868 '(
5869 ("\\(\\([@%]\\|\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
5870 (if (eq (char-after (match-beginning 2)) ?%)
4ab89e7b
SM
5871 'cperl-hash-face
5872 'cperl-array-face)
f83d2997
KH
5873 t) ; arrays and hashes
5874 ("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
5875 1
5c8b7eaf 5876 (if (= (- (match-end 2) (match-beginning 2)) 1)
f83d2997 5877 (if (eq (char-after (match-beginning 3)) ?{)
4ab89e7b
SM
5878 'cperl-hash-face
5879 'cperl-array-face) ; arrays and hashes
f83d2997
KH
5880 font-lock-variable-name-face) ; Just to put something
5881 t)
4ab89e7b
SM
5882 ("\\(@\\|\\$#\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
5883 (1 cperl-array-face)
5884 (2 font-lock-variable-name-face))
5885 ("\\(%\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
5886 (1 cperl-hash-face)
5887 (2 font-lock-variable-name-face))
f83d2997
KH
5888 ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
5889 ;;; Too much noise from \s* @s[ and friends
5c8b7eaf 5890 ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
f83d2997
KH
5891 ;;(3 font-lock-function-name-face t t)
5892 ;;(4
5893 ;; (if (cperl-slash-is-regexp)
5894 ;; font-lock-function-name-face 'default) nil t))
5895 )))
6c389151
SM
5896 (if cperl-highlight-variables-indiscriminately
5897 (setq t-font-lock-keywords-1
5898 (append t-font-lock-keywords-1
4ab89e7b 5899 (list '("\\([$*]{?\\sw+\\)" 1
6c389151 5900 font-lock-variable-name-face)))))
a1506d29 5901 (setq cperl-font-lock-keywords-1
5bd52f0e
RS
5902 (if cperl-syntaxify-by-font-lock
5903 (cons 'cperl-fontify-update
5904 t-font-lock-keywords)
5905 t-font-lock-keywords)
5efe6a56
SM
5906 cperl-font-lock-keywords cperl-font-lock-keywords-1
5907 cperl-font-lock-keywords-2 (append
6c389151
SM
5908 cperl-font-lock-keywords-1
5909 t-font-lock-keywords-1)))
f83d2997
KH
5910 (if (fboundp 'ps-print-buffer) (cperl-ps-print-init))
5911 (if (or (featurep 'choose-color) (featurep 'font-lock-extra))
db133cb6 5912 (eval ; Avoid a warning
83261a2f
SM
5913 '(font-lock-require-faces
5914 (list
5915 ;; Color-light Color-dark Gray-light Gray-dark Mono
5916 (list 'font-lock-comment-face
5917 ["Firebrick" "OrangeRed" "DimGray" "Gray80"]
5918 nil
5919 [nil nil t t t]
5920 [nil nil t t t]
5921 nil)
5922 (list 'font-lock-string-face
5923 ["RosyBrown" "LightSalmon" "Gray50" "LightGray"]
5924 nil
5925 nil
5926 [nil nil t t t]
5927 nil)
5928 (list 'font-lock-function-name-face
5929 (vector
5930 "Blue" "LightSkyBlue" "Gray50" "LightGray"
5931 (cdr (assq 'background-color ; if mono
5932 (frame-parameters))))
5933 (vector
5934 nil nil nil nil
5935 (cdr (assq 'foreground-color ; if mono
5936 (frame-parameters))))
5937 [nil nil t t t]
5938 nil
5939 nil)
5940 (list 'font-lock-variable-name-face
5941 ["DarkGoldenrod" "LightGoldenrod" "DimGray" "Gray90"]
5942 nil
5943 [nil nil t t t]
5944 [nil nil t t t]
5945 nil)
5946 (list 'font-lock-type-face
5947 ["DarkOliveGreen" "PaleGreen" "DimGray" "Gray80"]
5948 nil
5949 [nil nil t t t]
5950 nil
5951 [nil nil t t t])
4ab89e7b
SM
5952 (list 'font-lock-warning-face
5953 ["Pink" "Red" "Gray50" "LightGray"]
5954 ["gray20" "gray90"
5955 "gray80" "gray20"]
5956 [nil nil t t t]
5957 nil
5958 [nil nil t t t]
5959 )
83261a2f
SM
5960 (list 'font-lock-constant-face
5961 ["CadetBlue" "Aquamarine" "Gray50" "LightGray"]
5962 nil
5963 [nil nil t t t]
5964 nil
5965 [nil nil t t t])
4ab89e7b 5966 (list 'cperl-nonoverridable-face
83261a2f
SM
5967 ["chartreuse3" ("orchid1" "orange")
5968 nil "Gray80"]
5969 [nil nil "gray90"]
5970 [nil nil nil t t]
5971 [nil nil t t]
5972 [nil nil t t t])
4ab89e7b 5973 (list 'cperl-array-face
83261a2f
SM
5974 ["blue" "yellow" nil "Gray80"]
5975 ["lightyellow2" ("navy" "os2blue" "darkgreen")
5976 "gray90"]
5977 t
5978 nil
5979 nil)
4ab89e7b 5980 (list 'cperl-hash-face
83261a2f
SM
5981 ["red" "red" nil "Gray80"]
5982 ["lightyellow2" ("navy" "os2blue" "darkgreen")
5983 "gray90"]
5984 t
5985 t
5986 nil))))
5bd52f0e 5987 ;; Do it the dull way, without choose-color
f83d2997
KH
5988 (defvar cperl-guessed-background nil
5989 "Display characteristics as guessed by cperl.")
83261a2f 5990 ;; (or (fboundp 'x-color-defined-p)
15ca5699 5991 ;; (defalias 'x-color-defined-p
83261a2f
SM
5992 ;; (cond ((fboundp 'color-defined-p) 'color-defined-p)
5993 ;; ;; XEmacs >= 19.12
5994 ;; ((fboundp 'valid-color-name-p) 'valid-color-name-p)
5995 ;; ;; XEmacs 19.11
5996 ;; (t 'x-valid-color-name-p))))
5c8b7eaf 5997 (cperl-force-face font-lock-constant-face
5bd52f0e
RS
5998 "Face for constant and label names")
5999 (cperl-force-face font-lock-variable-name-face
6000 "Face for variable names")
6001 (cperl-force-face font-lock-type-face
6002 "Face for data types")
4ab89e7b 6003 (cperl-force-face cperl-nonoverridable-face
5bd52f0e 6004 "Face for data types from another group")
4ab89e7b
SM
6005 (cperl-force-face font-lock-warning-face
6006 "Face for things which should stand out")
5bd52f0e
RS
6007 (cperl-force-face font-lock-comment-face
6008 "Face for comments")
6009 (cperl-force-face font-lock-function-name-face
6010 "Face for function names")
4ab89e7b 6011 (cperl-force-face cperl-hash-face
5bd52f0e 6012 "Face for hashes")
4ab89e7b 6013 (cperl-force-face cperl-array-face
5bd52f0e
RS
6014 "Face for arrays")
6015 ;;(defvar font-lock-constant-face 'font-lock-constant-face)
6016 ;;(defvar font-lock-variable-name-face 'font-lock-variable-name-face)
6017 ;;(or (boundp 'font-lock-type-face)
6018 ;; (defconst font-lock-type-face
6019 ;; 'font-lock-type-face
6020 ;; "Face to use for data types."))
6021 ;;(or (boundp 'cperl-nonoverridable-face)
6022 ;; (defconst cperl-nonoverridable-face
4ab89e7b 6023 ;; 'cperl-nonoverridable-face
5bd52f0e 6024 ;; "Face to use for data types from another group."))
6546555e 6025 ;;(if (not (featurep 'xemacs)) nil
5bd52f0e
RS
6026 ;; (or (boundp 'font-lock-comment-face)
6027 ;; (defconst font-lock-comment-face
6028 ;; 'font-lock-comment-face
6029 ;; "Face to use for comments."))
6030 ;; (or (boundp 'font-lock-keyword-face)
6031 ;; (defconst font-lock-keyword-face
6032 ;; 'font-lock-keyword-face
6033 ;; "Face to use for keywords."))
6034 ;; (or (boundp 'font-lock-function-name-face)
6035 ;; (defconst font-lock-function-name-face
6036 ;; 'font-lock-function-name-face
6037 ;; "Face to use for function names.")))
6038 (if (and
4ab89e7b 6039 (not (cperl-is-face 'cperl-array-face))
5c8b7eaf 6040 (cperl-is-face 'font-lock-emphasized-face))
4ab89e7b 6041 (copy-face 'font-lock-emphasized-face 'cperl-array-face))
5bd52f0e 6042 (if (and
4ab89e7b 6043 (not (cperl-is-face 'cperl-hash-face))
5c8b7eaf 6044 (cperl-is-face 'font-lock-other-emphasized-face))
4ab89e7b 6045 (copy-face 'font-lock-other-emphasized-face 'cperl-hash-face))
5bd52f0e 6046 (if (and
4ab89e7b 6047 (not (cperl-is-face 'cperl-nonoverridable-face))
5c8b7eaf 6048 (cperl-is-face 'font-lock-other-type-face))
4ab89e7b 6049 (copy-face 'font-lock-other-type-face 'cperl-nonoverridable-face))
5bd52f0e
RS
6050 ;;(or (boundp 'cperl-hash-face)
6051 ;; (defconst cperl-hash-face
4ab89e7b 6052 ;; 'cperl-hash-face
5bd52f0e
RS
6053 ;; "Face to use for hashes."))
6054 ;;(or (boundp 'cperl-array-face)
6055 ;; (defconst cperl-array-face
4ab89e7b 6056 ;; 'cperl-array-face
5bd52f0e 6057 ;; "Face to use for arrays."))
f83d2997
KH
6058 ;; Here we try to guess background
6059 (let ((background
6060 (if (boundp 'font-lock-background-mode)
6061 font-lock-background-mode
5c8b7eaf 6062 'light))
83261a2f 6063 (face-list (and (fboundp 'face-list) (face-list))))
5bd52f0e
RS
6064;;;; (fset 'cperl-is-face
6065;;;; (cond ((fboundp 'find-face)
6066;;;; (symbol-function 'find-face))
6067;;;; (face-list
6068;;;; (function (lambda (face) (member face face-list))))
6069;;;; (t
6070;;;; (function (lambda (face) (boundp face))))))
f83d2997
KH
6071 (defvar cperl-guessed-background
6072 (if (and (boundp 'font-lock-display-type)
6073 (eq font-lock-display-type 'grayscale))
6074 'gray
6075 background)
6076 "Background as guessed by CPerl mode")
83261a2f
SM
6077 (and (not (cperl-is-face 'font-lock-constant-face))
6078 (cperl-is-face 'font-lock-reference-face)
6079 (copy-face 'font-lock-reference-face 'font-lock-constant-face))
db133cb6 6080 (if (cperl-is-face 'font-lock-type-face) nil
f83d2997
KH
6081 (copy-face 'default 'font-lock-type-face)
6082 (cond
6083 ((eq background 'light)
6084 (set-face-foreground 'font-lock-type-face
6085 (if (x-color-defined-p "seagreen")
6086 "seagreen"
6087 "sea green")))
6088 ((eq background 'dark)
6089 (set-face-foreground 'font-lock-type-face
6090 (if (x-color-defined-p "os2pink")
6091 "os2pink"
6092 "pink")))
6093 (t
6094 (set-face-background 'font-lock-type-face "gray90"))))
4ab89e7b 6095 (if (cperl-is-face 'cperl-nonoverridable-face)
f83d2997 6096 nil
4ab89e7b 6097 (copy-face 'font-lock-type-face 'cperl-nonoverridable-face)
f83d2997
KH
6098 (cond
6099 ((eq background 'light)
4ab89e7b 6100 (set-face-foreground 'cperl-nonoverridable-face
f83d2997
KH
6101 (if (x-color-defined-p "chartreuse3")
6102 "chartreuse3"
6103 "chartreuse")))
6104 ((eq background 'dark)
4ab89e7b 6105 (set-face-foreground 'cperl-nonoverridable-face
f83d2997
KH
6106 (if (x-color-defined-p "orchid1")
6107 "orchid1"
6108 "orange")))))
5bd52f0e
RS
6109;;; (if (cperl-is-face 'font-lock-other-emphasized-face) nil
6110;;; (copy-face 'bold-italic 'font-lock-other-emphasized-face)
6111;;; (cond
6112;;; ((eq background 'light)
6113;;; (set-face-background 'font-lock-other-emphasized-face
6114;;; (if (x-color-defined-p "lightyellow2")
6115;;; "lightyellow2"
6116;;; (if (x-color-defined-p "lightyellow")
6117;;; "lightyellow"
6118;;; "light yellow"))))
6119;;; ((eq background 'dark)
6120;;; (set-face-background 'font-lock-other-emphasized-face
6121;;; (if (x-color-defined-p "navy")
6122;;; "navy"
6123;;; (if (x-color-defined-p "darkgreen")
6124;;; "darkgreen"
6125;;; "dark green"))))
6126;;; (t (set-face-background 'font-lock-other-emphasized-face "gray90"))))
6127;;; (if (cperl-is-face 'font-lock-emphasized-face) nil
6128;;; (copy-face 'bold 'font-lock-emphasized-face)
6129;;; (cond
6130;;; ((eq background 'light)
6131;;; (set-face-background 'font-lock-emphasized-face
6132;;; (if (x-color-defined-p "lightyellow2")
6133;;; "lightyellow2"
6134;;; "lightyellow")))
6135;;; ((eq background 'dark)
6136;;; (set-face-background 'font-lock-emphasized-face
6137;;; (if (x-color-defined-p "navy")
6138;;; "navy"
6139;;; (if (x-color-defined-p "darkgreen")
6140;;; "darkgreen"
6141;;; "dark green"))))
6142;;; (t (set-face-background 'font-lock-emphasized-face "gray90"))))
db133cb6 6143 (if (cperl-is-face 'font-lock-variable-name-face) nil
f83d2997 6144 (copy-face 'italic 'font-lock-variable-name-face))
db133cb6 6145 (if (cperl-is-face 'font-lock-constant-face) nil
883212ce 6146 (copy-face 'italic 'font-lock-constant-face))))
f83d2997 6147 (setq cperl-faces-init t))
5bd52f0e 6148 (error (message "cperl-init-faces (ignored): %s" errs))))
f83d2997
KH
6149
6150
6151(defun cperl-ps-print-init ()
6152 "Initialization of `ps-print' components for faces used in CPerl."
5bd52f0e
RS
6153 (eval-after-load "ps-print"
6154 '(setq ps-bold-faces
5c8b7eaf 6155 ;; font-lock-variable-name-face
5bd52f0e 6156 ;; font-lock-constant-face
4ab89e7b 6157 (append '(cperl-array-face cperl-hash-face)
5bd52f0e
RS
6158 ps-bold-faces)
6159 ps-italic-faces
6160 ;; font-lock-constant-face
4ab89e7b 6161 (append '(cperl-nonoverridable-face cperl-hash-face)
5bd52f0e
RS
6162 ps-italic-faces)
6163 ps-underlined-faces
6164 ;; font-lock-type-face
4ab89e7b 6165 (append '(cperl-array-face cperl-hash-face underline cperl-nonoverridable-face)
5bd52f0e
RS
6166 ps-underlined-faces))))
6167
6168(defvar ps-print-face-extension-alist)
6169
6170(defun cperl-ps-print (&optional file)
6171 "Pretty-print in CPerl style.
6172If optional argument FILE is an empty string, prints to printer, otherwise
6173to the file FILE. If FILE is nil, prompts for a file name.
6174
6175Style of printout regulated by the variable `cperl-ps-print-face-properties'."
6176 (interactive)
5c8b7eaf
SS
6177 (or file
6178 (setq file (read-from-minibuffer
5bd52f0e
RS
6179 "Print to file (if empty - to printer): "
6180 (concat (buffer-file-name) ".ps")
6181 nil nil 'file-name-history)))
6182 (or (> (length file) 0)
6183 (setq file nil))
6184 (require 'ps-print) ; To get ps-print-face-extension-alist
6185 (let ((ps-print-color-p t)
6186 (ps-print-face-extension-alist ps-print-face-extension-alist))
6187 (cperl-ps-extend-face-list cperl-ps-print-face-properties)
6188 (ps-print-buffer-with-faces file)))
6189
6190;;; (defun cperl-ps-print-init ()
6191;;; "Initialization of `ps-print' components for faces used in CPerl."
6192;;; ;; Guard against old versions
6193;;; (defvar ps-underlined-faces nil)
6194;;; (defvar ps-bold-faces nil)
6195;;; (defvar ps-italic-faces nil)
6196;;; (setq ps-bold-faces
6197;;; (append '(font-lock-emphasized-face
4ab89e7b 6198;;; cperl-array-face
5c8b7eaf
SS
6199;;; font-lock-keyword-face
6200;;; font-lock-variable-name-face
6201;;; font-lock-constant-face
6202;;; font-lock-reference-face
5bd52f0e 6203;;; font-lock-other-emphasized-face
4ab89e7b 6204;;; cperl-hash-face)
5bd52f0e
RS
6205;;; ps-bold-faces))
6206;;; (setq ps-italic-faces
4ab89e7b 6207;;; (append '(cperl-nonoverridable-face
5c8b7eaf
SS
6208;;; font-lock-constant-face
6209;;; font-lock-reference-face
5bd52f0e 6210;;; font-lock-other-emphasized-face
4ab89e7b 6211;;; cperl-hash-face)
5bd52f0e
RS
6212;;; ps-italic-faces))
6213;;; (setq ps-underlined-faces
6214;;; (append '(font-lock-emphasized-face
4ab89e7b 6215;;; cperl-array-face
5bd52f0e 6216;;; font-lock-other-emphasized-face
4ab89e7b
SM
6217;;; cperl-hash-face
6218;;; cperl-nonoverridable-face font-lock-type-face)
5bd52f0e
RS
6219;;; ps-underlined-faces))
6220;;; (cons 'font-lock-type-face ps-underlined-faces))
f83d2997
KH
6221
6222
6223(if (cperl-enable-font-lock) (cperl-windowed-init))
6224
db133cb6 6225(defconst cperl-styles-entries
5c8b7eaf
SS
6226 '(cperl-indent-level cperl-brace-offset cperl-continued-brace-offset
6227 cperl-label-offset cperl-extra-newline-before-brace
4ab89e7b 6228 cperl-extra-newline-before-brace-multiline
bab27c0c 6229 cperl-merge-trailing-else
db133cb6
RS
6230 cperl-continued-statement-offset))
6231
4ab89e7b
SM
6232(defconst cperl-style-examples
6233"##### Numbers etc are: cperl-indent-level cperl-brace-offset
6234##### cperl-continued-brace-offset cperl-label-offset
6235##### cperl-continued-statement-offset
6236##### cperl-merge-trailing-else cperl-extra-newline-before-brace
6237
6238########### (Do not forget cperl-extra-newline-before-brace-multiline)
6239
6240### CPerl (=GNU - extra-newline-before-brace + merge-trailing-else) 2/0/0/-2/2/t/nil
6241if (foo) {
6242 bar
6243 baz;
6244 label:
6245 {
6246 boon;
6247 }
6248} else {
6249 stop;
6250}
6251
6252### PerlStyle (=CPerl with 4 as indent) 4/0/0/-4/4/t/nil
6253if (foo) {
6254 bar
6255 baz;
6256 label:
6257 {
6258 boon;
6259 }
6260} else {
6261 stop;
6262}
6263
6264### GNU 2/0/0/-2/2/nil/t
6265if (foo)
6266 {
6267 bar
6268 baz;
6269 label:
6270 {
6271 boon;
6272 }
6273 }
6274else
6275 {
6276 stop;
6277 }
6278
6279### C++ (=PerlStyle with braces aligned with control words) 4/0/-4/-4/4/nil/t
6280if (foo)
6281{
6282 bar
6283 baz;
6284 label:
6285 {
6286 boon;
6287 }
6288}
6289else
6290{
6291 stop;
6292}
6293
6294### BSD (=C++, but will not change preexisting merge-trailing-else
6295### and extra-newline-before-brace ) 4/0/-4/-4/4
6296if (foo)
6297{
6298 bar
6299 baz;
6300 label:
6301 {
6302 boon;
6303 }
6304}
6305else
6306{
6307 stop;
6308}
6309
6310### K&R (=C++ with indent 5 - merge-trailing-else, but will not
6311### change preexisting extra-newline-before-brace) 5/0/-5/-5/5/nil
6312if (foo)
6313{
6314 bar
6315 baz;
6316 label:
6317 {
6318 boon;
6319 }
6320}
6321else
6322{
6323 stop;
6324}
6325
6326### Whitesmith (=PerlStyle, but will not change preexisting
6327### extra-newline-before-brace and merge-trailing-else) 4/0/0/-4/4
6328if (foo)
6329 {
6330 bar
6331 baz;
6332 label:
6333 {
6334 boon;
6335 }
6336 }
6337else
6338 {
6339 stop;
6340 }
6341"
6342"Examples of if/else with different indent styles (with v4.23).")
6343
db133cb6 6344(defconst cperl-style-alist
4ab89e7b 6345 '(("CPerl" ;; =GNU - extra-newline-before-brace + cperl-merge-trailing-else
db133cb6
RS
6346 (cperl-indent-level . 2)
6347 (cperl-brace-offset . 0)
6348 (cperl-continued-brace-offset . 0)
6349 (cperl-label-offset . -2)
4ab89e7b 6350 (cperl-continued-statement-offset . 2)
db133cb6 6351 (cperl-extra-newline-before-brace . nil)
4ab89e7b
SM
6352 (cperl-extra-newline-before-brace-multiline . nil)
6353 (cperl-merge-trailing-else . t))
6354
83261a2f 6355 ("PerlStyle" ; CPerl with 4 as indent
db133cb6
RS
6356 (cperl-indent-level . 4)
6357 (cperl-brace-offset . 0)
6358 (cperl-continued-brace-offset . 0)
6359 (cperl-label-offset . -4)
4ab89e7b 6360 (cperl-continued-statement-offset . 4)
db133cb6 6361 (cperl-extra-newline-before-brace . nil)
4ab89e7b
SM
6362 (cperl-extra-newline-before-brace-multiline . nil)
6363 (cperl-merge-trailing-else . t))
6364
db133cb6
RS
6365 ("GNU"
6366 (cperl-indent-level . 2)
6367 (cperl-brace-offset . 0)
6368 (cperl-continued-brace-offset . 0)
6369 (cperl-label-offset . -2)
4ab89e7b 6370 (cperl-continued-statement-offset . 2)
db133cb6 6371 (cperl-extra-newline-before-brace . t)
4ab89e7b
SM
6372 (cperl-extra-newline-before-brace-multiline . t)
6373 (cperl-merge-trailing-else . nil))
6374
db133cb6
RS
6375 ("K&R"
6376 (cperl-indent-level . 5)
6377 (cperl-brace-offset . 0)
6378 (cperl-continued-brace-offset . -5)
6379 (cperl-label-offset . -5)
4ab89e7b 6380 (cperl-continued-statement-offset . 5)
db133cb6 6381 ;;(cperl-extra-newline-before-brace . nil) ; ???
4ab89e7b
SM
6382 ;;(cperl-extra-newline-before-brace-multiline . nil)
6383 (cperl-merge-trailing-else . nil))
6384
db133cb6
RS
6385 ("BSD"
6386 (cperl-indent-level . 4)
6387 (cperl-brace-offset . 0)
6388 (cperl-continued-brace-offset . -4)
6389 (cperl-label-offset . -4)
4ab89e7b 6390 (cperl-continued-statement-offset . 4)
db133cb6 6391 ;;(cperl-extra-newline-before-brace . nil) ; ???
4ab89e7b
SM
6392 ;;(cperl-extra-newline-before-brace-multiline . nil)
6393 ;;(cperl-merge-trailing-else . nil) ; ???
6394 )
6395
db133cb6
RS
6396 ("C++"
6397 (cperl-indent-level . 4)
6398 (cperl-brace-offset . 0)
6399 (cperl-continued-brace-offset . -4)
6400 (cperl-label-offset . -4)
6401 (cperl-continued-statement-offset . 4)
4ab89e7b
SM
6402 (cperl-extra-newline-before-brace . t)
6403 (cperl-extra-newline-before-brace-multiline . t)
6404 (cperl-merge-trailing-else . nil))
6405
db133cb6
RS
6406 ("Whitesmith"
6407 (cperl-indent-level . 4)
6408 (cperl-brace-offset . 0)
6409 (cperl-continued-brace-offset . 0)
6410 (cperl-label-offset . -4)
4ab89e7b 6411 (cperl-continued-statement-offset . 4)
db133cb6 6412 ;;(cperl-extra-newline-before-brace . nil) ; ???
4ab89e7b
SM
6413 ;;(cperl-extra-newline-before-brace-multiline . nil)
6414 ;;(cperl-merge-trailing-else . nil) ; ???
6415 )
6416 ("Current"))
6417 "List of variables to set to get a particular indentation style.
6418Should be used via `cperl-set-style' or via Perl menu.
6419
6420See examples in `cperl-style-examples'.")
db133cb6 6421
f83d2997 6422(defun cperl-set-style (style)
f94a632a 6423 "Set CPerl mode variables to use one of several different indentation styles.
f83d2997 6424The arguments are a string representing the desired style.
5c8b7eaf 6425The list of styles is in `cperl-style-alist', available styles
4ab89e7b 6426are CPerl, PerlStyle, GNU, K&R, BSD, C++ and Whitesmith.
db133cb6
RS
6427
6428The current value of style is memorized (unless there is a memorized
6429data already), may be restored by `cperl-set-style-back'.
6430
6431Chosing \"Current\" style will not change style, so this may be used for
4ab89e7b 6432side-effect of memorizing only. Examples in `cperl-style-examples'."
5c8b7eaf 6433 (interactive
15ca5699 6434 (let ((list (mapcar (function (lambda (elt) (list (car elt))))
db133cb6 6435 cperl-style-alist)))
f83d2997 6436 (list (completing-read "Enter style: " list nil 'insist))))
db133cb6
RS
6437 (or cperl-old-style
6438 (setq cperl-old-style
6439 (mapcar (function
6440 (lambda (name)
6441 (cons name (eval name))))
6442 cperl-styles-entries)))
6443 (let ((style (cdr (assoc style cperl-style-alist))) setting str sym)
f83d2997
KH
6444 (while style
6445 (setq setting (car style) style (cdr style))
db133cb6
RS
6446 (set (car setting) (cdr setting)))))
6447
6448(defun cperl-set-style-back ()
810fb442 6449 "Restore a style memorized by `cperl-set-style'."
db133cb6
RS
6450 (interactive)
6451 (or cperl-old-style (error "The style was not changed"))
6452 (let (setting)
6453 (while cperl-old-style
5c8b7eaf 6454 (setq setting (car cperl-old-style)
db133cb6
RS
6455 cperl-old-style (cdr cperl-old-style))
6456 (set (car setting) (cdr setting)))))
f83d2997
KH
6457
6458(defun cperl-check-syntax ()
6459 (interactive)
6460 (require 'mode-compile)
db133cb6
RS
6461 (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc")))
6462 (eval '(mode-compile)))) ; Avoid a warning
f83d2997
KH
6463
6464(defun cperl-info-buffer (type)
6465 ;; Returns buffer with documentation. Creates if missing.
6466 ;; If TYPE, this vars buffer.
6467 ;; Special care is taken to not stomp over an existing info buffer
6468 (let* ((bname (if type "*info-perl-var*" "*info-perl*"))
6469 (info (get-buffer bname))
6470 (oldbuf (get-buffer "*info*")))
6471 (if info info
6472 (save-window-excursion
6473 ;; Get Info running
6474 (require 'info)
6475 (cond (oldbuf
6476 (set-buffer oldbuf)
6477 (rename-buffer "*info-perl-tmp*")))
6478 (save-window-excursion
6479 (info))
6480 (Info-find-node cperl-info-page (if type "perlvar" "perlfunc"))
6481 (set-buffer "*info*")
6482 (rename-buffer bname)
6483 (cond (oldbuf
6484 (set-buffer "*info-perl-tmp*")
6485 (rename-buffer "*info*")
6486 (set-buffer bname)))
029cb4d5 6487 (make-local-variable 'window-min-height)
f83d2997
KH
6488 (setq window-min-height 2)
6489 (current-buffer)))))
6490
6491(defun cperl-word-at-point (&optional p)
f94a632a 6492 "Return the word at point or at P."
f83d2997
KH
6493 (save-excursion
6494 (if p (goto-char p))
6495 (or (cperl-word-at-point-hard)
6496 (progn
6497 (require 'etags)
6498 (funcall (or (and (boundp 'find-tag-default-function)
6499 find-tag-default-function)
6500 (get major-mode 'find-tag-default-function)
6501 ;; XEmacs 19.12 has `find-tag-default-hook'; it is
6502 ;; automatically used within `find-tag-default':
6503 'find-tag-default))))))
6504
6505(defun cperl-info-on-command (command)
f94a632a 6506 "Show documentation for Perl command COMMAND in other window.
f83d2997
KH
6507If perl-info buffer is shown in some frame, uses this frame.
6508Customized by setting variables `cperl-shrink-wrap-info-frame',
6509`cperl-max-help-size'."
5c8b7eaf 6510 (interactive
f83d2997 6511 (let* ((default (cperl-word-at-point))
5c8b7eaf 6512 (read (read-string
83261a2f
SM
6513 (format "Find doc for Perl function (default %s): "
6514 default))))
5c8b7eaf 6515 (list (if (equal read "")
83261a2f
SM
6516 default
6517 read))))
f83d2997
KH
6518
6519 (let ((buffer (current-buffer))
6520 (cmd-desc (concat "^" (regexp-quote command) "[^a-zA-Z_0-9]")) ; "tr///"
6521 pos isvar height iniheight frheight buf win fr1 fr2 iniwin not-loner
6522 max-height char-height buf-list)
6523 (if (string-match "^-[a-zA-Z]$" command)
6524 (setq cmd-desc "^-X[ \t\n]"))
6525 (setq isvar (string-match "^[$@%]" command)
6526 buf (cperl-info-buffer isvar)
6527 iniwin (selected-window)
6528 fr1 (window-frame iniwin))
6529 (set-buffer buf)
fc49c9c6 6530 (goto-char (point-min))
5c8b7eaf 6531 (or isvar
f83d2997
KH
6532 (progn (re-search-forward "^-X[ \t\n]")
6533 (forward-line -1)))
6534 (if (re-search-forward cmd-desc nil t)
6535 (progn
6536 ;; Go back to beginning of the group (ex, for qq)
6537 (if (re-search-backward "^[ \t\n\f]")
6538 (forward-line 1))
6539 (beginning-of-line)
5c8b7eaf 6540 ;; Get some of
f83d2997
KH
6541 (setq pos (point)
6542 buf-list (list buf "*info-perl-var*" "*info-perl*"))
6543 (while (and (not win) buf-list)
6544 (setq win (get-buffer-window (car buf-list) t))
6545 (setq buf-list (cdr buf-list)))
6546 (or (not win)
6547 (eq (window-buffer win) buf)
6548 (set-window-buffer win buf))
6549 (and win (setq fr2 (window-frame win)))
6550 (if (or (not fr2) (eq fr1 fr2))
6551 (pop-to-buffer buf)
6552 (special-display-popup-frame buf) ; Make it visible
6553 (select-window win))
6554 (goto-char pos) ; Needed (?!).
6555 ;; Resize
6556 (setq iniheight (window-height)
6557 frheight (frame-height)
6558 not-loner (< iniheight (1- frheight))) ; Are not alone
5c8b7eaf 6559 (cond ((if not-loner cperl-max-help-size
f83d2997 6560 cperl-shrink-wrap-info-frame)
5c8b7eaf
SS
6561 (setq height
6562 (+ 2
6563 (count-lines
6564 pos
f83d2997
KH
6565 (save-excursion
6566 (if (re-search-forward
6567 "^[ \t][^\n]*\n+\\([^ \t\n\f]\\|\\'\\)" nil t)
6568 (match-beginning 0) (point-max)))))
5c8b7eaf 6569 max-height
f83d2997
KH
6570 (if not-loner
6571 (/ (* (- frheight 3) cperl-max-help-size) 100)
6572 (setq char-height (frame-char-height))
6573 ;; Non-functioning under OS/2:
6574 (if (eq char-height 1) (setq char-height 18))
6575 ;; Title, menubar, + 2 for slack
83261a2f 6576 (- (/ (x-display-pixel-height) char-height) 4)))
f83d2997
KH
6577 (if (> height max-height) (setq height max-height))
6578 ;;(message "was %s doing %s" iniheight height)
6579 (if not-loner
6580 (enlarge-window (- height iniheight))
6581 (set-frame-height (window-frame win) (1+ height)))))
6582 (set-window-start (selected-window) pos))
6583 (message "No entry for %s found." command))
6584 ;;(pop-to-buffer buffer)
6585 (select-window iniwin)))
6586
6587(defun cperl-info-on-current-command ()
029cb4d5 6588 "Show documentation for Perl command at point in other window."
f83d2997
KH
6589 (interactive)
6590 (cperl-info-on-command (cperl-word-at-point)))
6591
6592(defun cperl-imenu-info-imenu-search ()
6593 (if (looking-at "^-X[ \t\n]") nil
6594 (re-search-backward
6595 "^\n\\([-a-zA-Z_]+\\)[ \t\n]")
6596 (forward-line 1)))
6597
5c8b7eaf 6598(defun cperl-imenu-info-imenu-name ()
f83d2997
KH
6599 (buffer-substring
6600 (match-beginning 1) (match-end 1)))
6601
6602(defun cperl-imenu-on-info ()
4ab89e7b
SM
6603 "Shows imenu for Perl Info Buffer.
6604Opens Perl Info buffer if needed."
f83d2997
KH
6605 (interactive)
6606 (let* ((buffer (current-buffer))
6607 imenu-create-index-function
5c8b7eaf
SS
6608 imenu-prev-index-position-function
6609 imenu-extract-index-name-function
f83d2997
KH
6610 (index-item (save-restriction
6611 (save-window-excursion
6612 (set-buffer (cperl-info-buffer nil))
5c8b7eaf 6613 (setq imenu-create-index-function
f83d2997
KH
6614 'imenu-default-create-index-function
6615 imenu-prev-index-position-function
6616 'cperl-imenu-info-imenu-search
6617 imenu-extract-index-name-function
6618 'cperl-imenu-info-imenu-name)
6619 (imenu-choose-buffer-index)))))
6620 (and index-item
6621 (progn
6622 (push-mark)
6623 (pop-to-buffer "*info-perl*")
6624 (cond
6625 ((markerp (cdr index-item))
6626 (goto-char (marker-position (cdr index-item))))
6627 (t
6628 (goto-char (cdr index-item))))
6629 (set-window-start (selected-window) (point))
6630 (pop-to-buffer buffer)))))
6631
6632(defun cperl-lineup (beg end &optional step minshift)
6633 "Lineup construction in a region.
6634Beginning of region should be at the start of a construction.
6635All first occurrences of this construction in the lines that are
6636partially contained in the region are lined up at the same column.
6637
6638MINSHIFT is the minimal amount of space to insert before the construction.
6639STEP is the tabwidth to position constructions.
029cb4d5 6640If STEP is nil, `cperl-lineup-step' will be used
15ca5699 6641\(or `cperl-indent-level', if `cperl-lineup-step' is nil).
f83d2997
KH
6642Will not move the position at the start to the left."
6643 (interactive "r")
4ab89e7b 6644 (let (search col tcol seen b)
f83d2997
KH
6645 (save-excursion
6646 (goto-char end)
6647 (end-of-line)
6648 (setq end (point-marker))
6649 (goto-char beg)
6650 (skip-chars-forward " \t\f")
6651 (setq beg (point-marker))
6652 (indent-region beg end nil)
6653 (goto-char beg)
6654 (setq col (current-column))
6655 (if (looking-at "[a-zA-Z0-9_]")
6656 (if (looking-at "\\<[a-zA-Z0-9_]+\\>")
6657 (setq search
5c8b7eaf
SS
6658 (concat "\\<"
6659 (regexp-quote
f83d2997
KH
6660 (buffer-substring (match-beginning 0)
6661 (match-end 0))) "\\>"))
6662 (error "Cannot line up in a middle of the word"))
6663 (if (looking-at "$")
6664 (error "Cannot line up end of line"))
6665 (setq search (regexp-quote (char-to-string (following-char)))))
6666 (setq step (or step cperl-lineup-step cperl-indent-level))
6667 (or minshift (setq minshift 1))
6668 (while (progn
6669 (beginning-of-line 2)
5c8b7eaf 6670 (and (< (point) end)
f83d2997
KH
6671 (re-search-forward search end t)
6672 (goto-char (match-beginning 0))))
6673 (setq tcol (current-column) seen t)
6674 (if (> tcol col) (setq col tcol)))
6675 (or seen
6676 (error "The construction to line up occurred only once"))
6677 (goto-char beg)
6678 (setq col (+ col minshift))
6679 (if (/= (% col step) 0) (setq step (* step (1+ (/ col step)))))
5c8b7eaf 6680 (while
f83d2997 6681 (progn
4ab89e7b 6682 (cperl-make-indent col)
5c8b7eaf
SS
6683 (beginning-of-line 2)
6684 (and (< (point) end)
f83d2997
KH
6685 (re-search-forward search end t)
6686 (goto-char (match-beginning 0)))))))) ; No body
6687
4ab89e7b 6688(defun cperl-etags (&optional add all files) ;; NOT USED???
f83d2997
KH
6689 "Run etags with appropriate options for Perl files.
6690If optional argument ALL is `recursive', will process Perl files
6691in subdirectories too."
6692 (interactive)
6693 (let ((cmd "etags")
4ab89e7b
SM
6694 (args '("-l" "none" "-r"
6695 ;; 1=fullname 2=package? 3=name 4=proto? 5=attrs? (VERY APPROX!)
6696 "/\\<sub[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)\\)[ \\t]*\\(([^()]*)[ \t]*\\)?\\([ \t]*:[^#{;]*\\)?\\([{#]\\|$\\)/\\3/"
6697 "-r"
6698 "/\\<package[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)\\)[ \\t]*\\([#;]\\|$\\)/\\1/"
6699 "-r"
6700 "/\\<\\(package\\)[ \\t]*;/\\1;/"))
f83d2997
KH
6701 res)
6702 (if add (setq args (cons "-a" args)))
6703 (or files (setq files (list buffer-file-name)))
6704 (cond
6705 ((eq all 'recursive)
6706 ;;(error "Not implemented: recursive")
5c8b7eaf 6707 (setq args (append (list "-e"
f83d2997
KH
6708 "sub wanted {push @ARGV, $File::Find::name if /\\.[pP][Llm]$/}
6709 use File::Find;
6710 find(\\&wanted, '.');
5c8b7eaf 6711 exec @ARGV;"
f83d2997
KH
6712 cmd) args)
6713 cmd "perl"))
5c8b7eaf 6714 (all
f83d2997 6715 ;;(error "Not implemented: all")
5c8b7eaf 6716 (setq args (append (list "-e"
f83d2997 6717 "push @ARGV, <*.PL *.pl *.pm>;
5c8b7eaf 6718 exec @ARGV;"
f83d2997
KH
6719 cmd) args)
6720 cmd "perl"))
6721 (t
6722 (setq args (append args files))))
6723 (setq res (apply 'call-process cmd nil nil nil args))
6724 (or (eq res 0)
6725 (message "etags returned \"%s\"" res))))
6726
6727(defun cperl-toggle-auto-newline ()
6728 "Toggle the state of `cperl-auto-newline'."
6729 (interactive)
6730 (setq cperl-auto-newline (not cperl-auto-newline))
5c8b7eaf 6731 (message "Newlines will %sbe auto-inserted now."
f83d2997
KH
6732 (if cperl-auto-newline "" "not ")))
6733
6734(defun cperl-toggle-abbrev ()
6735 "Toggle the state of automatic keyword expansion in CPerl mode."
6736 (interactive)
6737 (abbrev-mode (if abbrev-mode 0 1))
5c8b7eaf 6738 (message "Perl control structure will %sbe auto-inserted now."
f83d2997
KH
6739 (if abbrev-mode "" "not ")))
6740
6741
6742(defun cperl-toggle-electric ()
6743 "Toggle the state of parentheses doubling in CPerl mode."
6744 (interactive)
6745 (setq cperl-electric-parens (if (cperl-val 'cperl-electric-parens) 'null t))
5c8b7eaf 6746 (message "Parentheses will %sbe auto-doubled now."
f83d2997
KH
6747 (if (cperl-val 'cperl-electric-parens) "" "not ")))
6748
db133cb6 6749(defun cperl-toggle-autohelp ()
f739b53b
SM
6750 "Toggle the state of Auto-Help on Perl constructs (put in the message area).
6751Delay of auto-help controlled by `cperl-lazy-help-time'."
db133cb6
RS
6752 (interactive)
6753 (if (fboundp 'run-with-idle-timer)
6754 (progn
6755 (if cperl-lazy-installed
f739b53b 6756 (cperl-lazy-unstall)
db133cb6 6757 (cperl-lazy-install))
5c8b7eaf 6758 (message "Perl help messages will %sbe automatically shown now."
db133cb6
RS
6759 (if cperl-lazy-installed "" "not ")))
6760 (message "Cannot automatically show Perl help messages - run-with-idle-timer missing.")))
6761
6762(defun cperl-toggle-construct-fix ()
6763 "Toggle whether `indent-region'/`indent-sexp' fix whitespace too."
6764 (interactive)
5c8b7eaf 6765 (setq cperl-indent-region-fix-constructs
5bd52f0e
RS
6766 (if cperl-indent-region-fix-constructs
6767 nil
6768 1))
5c8b7eaf 6769 (message "indent-region/indent-sexp will %sbe automatically fix whitespace."
db133cb6
RS
6770 (if cperl-indent-region-fix-constructs "" "not ")))
6771
4ab89e7b
SM
6772(defun cperl-toggle-set-debug-unwind (arg &optional backtrace)
6773 "Toggle (or, with numeric argument, set) debugging state of syntaxification.
6774Nonpositive numeric argument disables debugging messages. The message
6775summarizes which regions it was decided to rescan for syntactic constructs.
6776
6777The message looks like this:
6778
6779 Syxify req=123..138 actual=101..146 done-to: 112=>146 statepos: 73=>117
6780
6781Numbers are character positions in the buffer. REQ provides the range to
6782rescan requested by `font-lock'. ACTUAL is the range actually resyntaxified;
6783for correct operation it should start and end outside any special syntactic
6784construct. DONE-TO and STATEPOS indicate changes to internal caches maintained
6785by CPerl."
6786 (interactive "P")
6787 (or arg
cb5bf6ba 6788 (setq arg (if (eq cperl-syntaxify-by-font-lock
4ab89e7b
SM
6789 (if backtrace 'backtrace 'message)) 0 1)))
6790 (setq arg (if (> arg 0) (if backtrace 'backtrace 'message) t))
6791 (setq cperl-syntaxify-by-font-lock arg)
6792 (message "Debugging messages of syntax unwind %sabled."
6793 (if (eq arg t) "dis" "en")))
6794
f83d2997
KH
6795;;;; Tags file creation.
6796
6797(defvar cperl-tmp-buffer " *cperl-tmp*")
6798
6799(defun cperl-setup-tmp-buf ()
6800 (set-buffer (get-buffer-create cperl-tmp-buffer))
6801 (set-syntax-table cperl-mode-syntax-table)
6802 (buffer-disable-undo)
6803 (auto-fill-mode 0)
6804 (if cperl-use-syntax-table-text-property-for-tags
6805 (progn
029cb4d5 6806 (make-local-variable 'parse-sexp-lookup-properties)
f83d2997
KH
6807 ;; Do not introduce variable if not needed, we check it!
6808 (set 'parse-sexp-lookup-properties t))))
6809
6810(defun cperl-xsub-scan ()
f83d2997 6811 (require 'imenu)
5c8b7eaf 6812 (let ((index-alist '())
f83d2997
KH
6813 (prev-pos 0) index index1 name package prefix)
6814 (goto-char (point-min))
f83d2997
KH
6815 ;; Search for the function
6816 (progn ;;save-match-data
6817 (while (re-search-forward
6818 "^\\([ \t]*MODULE\\>[^\n]*\\<PACKAGE[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9:]*\\)\\>\\|\\([a-zA-Z_][a-zA-Z_0-9]*\\)(\\|[ \t]*BOOT:\\)"
6819 nil t)
f83d2997 6820 (cond
83261a2f 6821 ((match-beginning 2) ; SECTION
f83d2997
KH
6822 (setq package (buffer-substring (match-beginning 2) (match-end 2)))
6823 (goto-char (match-beginning 0))
6824 (skip-chars-forward " \t")
6825 (forward-char 1)
6826 (if (looking-at "[^\n]*\\<PREFIX[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9]*\\)\\>")
6827 (setq prefix (buffer-substring (match-beginning 1) (match-end 1)))
6828 (setq prefix nil)))
6829 ((not package) nil) ; C language section
6830 ((match-beginning 3) ; XSUB
6831 (goto-char (1+ (match-beginning 3)))
6832 (setq index (imenu-example--name-and-position))
6833 (setq name (buffer-substring (match-beginning 3) (match-end 3)))
6834 (if (and prefix (string-match (concat "^" prefix) name))
6835 (setq name (substring name (length prefix))))
6836 (cond ((string-match "::" name) nil)
6837 (t
6838 (setq index1 (cons (concat package "::" name) (cdr index)))
6839 (push index1 index-alist)))
6840 (setcar index name)
6841 (push index index-alist))
6842 (t ; BOOT: section
6843 ;; (beginning-of-line)
6844 (setq index (imenu-example--name-and-position))
6845 (setcar index (concat package "::BOOT:"))
6846 (push index index-alist)))))
f83d2997
KH
6847 index-alist))
6848
6c389151
SM
6849(defvar cperl-unreadable-ok nil)
6850
6851(defun cperl-find-tags (ifile xs topdir)
83261a2f
SM
6852 (let ((b (get-buffer cperl-tmp-buffer)) ind lst elt pos ret rel
6853 (cperl-pod-here-fontify nil) f file)
f83d2997
KH
6854 (save-excursion
6855 (if b (set-buffer b)
83261a2f 6856 (cperl-setup-tmp-buf))
f83d2997 6857 (erase-buffer)
6c389151
SM
6858 (condition-case err
6859 (setq file (car (insert-file-contents ifile)))
6860 (error (if cperl-unreadable-ok nil
6861 (if (y-or-n-p
6862 (format "File %s unreadable. Continue? " ifile))
6863 (setq cperl-unreadable-ok t)
6864 (error "Aborting: unreadable file %s" ifile)))))
a1506d29 6865 (if (not file)
6c389151 6866 (message "Unreadable file %s" ifile)
83261a2f
SM
6867 (message "Scanning file %s ..." file)
6868 (if (and cperl-use-syntax-table-text-property-for-tags
6869 (not xs))
6870 (condition-case err ; after __END__ may have garbage
6871 (cperl-find-pods-heres nil nil noninteractive)
6872 (error (message "While scanning for syntax: %s" err))))
6873 (if xs
6874 (setq lst (cperl-xsub-scan))
6875 (setq ind (cperl-imenu--create-perl-index))
6876 (setq lst (cdr (assoc "+Unsorted List+..." ind))))
6877 (setq lst
6878 (mapcar
6879 (function
6880 (lambda (elt)
6881 (cond ((string-match "^[_a-zA-Z]" (car elt))
6882 (goto-char (cdr elt))
6883 (beginning-of-line) ; pos should be of the start of the line
6884 (list (car elt)
6885 (point)
6886 (1+ (count-lines 1 (point))) ; 1+ since at beg-o-l
6887 (buffer-substring (progn
6888 (goto-char (cdr elt))
6889 ;; After name now...
6890 (or (eolp) (forward-char 1))
6891 (point))
6892 (progn
6893 (beginning-of-line)
6894 (point))))))))
6895 lst))
6896 (erase-buffer)
6897 (while lst
6898 (setq elt (car lst) lst (cdr lst))
6899 (if elt
6900 (progn
6901 (insert (elt elt 3)
6902 127
6903 (if (string-match "^package " (car elt))
6904 (substring (car elt) 8)
6905 (car elt) )
6906 1
6907 (number-to-string (elt elt 2)) ; Line
6908 ","
6909 (number-to-string (1- (elt elt 1))) ; Char pos 0-based
6910 "\n")
6911 (if (and (string-match "^[_a-zA-Z]+::" (car elt))
6912 (string-match "^sub[ \t]+\\([_a-zA-Z]+\\)[^:_a-zA-Z]"
6913 (elt elt 3)))
6914 ;; Need to insert the name without package as well
15ca5699 6915 (setq lst (cons (cons (substring (elt elt 3)
83261a2f
SM
6916 (match-beginning 1)
6917 (match-end 1))
6918 (cdr elt))
6919 lst))))))
6920 (setq pos (point))
6921 (goto-char 1)
6922 (setq rel file)
6923 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
6924 (set-text-properties 0 (length rel) nil rel)
6925 (and (equal topdir (substring rel 0 (length topdir)))
6926 (setq rel (substring file (length topdir))))
6927 (insert "\f\n" rel "," (number-to-string (1- pos)) "\n")
6928 (setq ret (buffer-substring 1 (point-max)))
6929 (erase-buffer)
6930 (or noninteractive
6931 (message "Scanning file %s finished" file))
6932 ret))))
f83d2997
KH
6933
6934(defun cperl-add-tags-recurse-noxs ()
4ab89e7b 6935 "Add to TAGS data for \"pure\" Perl files in the current directory and kids.
f83d2997
KH
6936Use as
6937 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
4ab89e7b 6938 -f cperl-add-tags-recurse-noxs
f83d2997
KH
6939"
6940 (cperl-write-tags nil nil t t nil t))
6941
4ab89e7b
SM
6942(defun cperl-add-tags-recurse-noxs-fullpath ()
6943 "Add to TAGS data for \"pure\" Perl in the current directory and kids.
6944Writes down fullpath, so TAGS is relocatable (but if the build directory
6945is relocated, the file TAGS inside it breaks). Use as
6946 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
6947 -f cperl-add-tags-recurse-noxs-fullpath
6948"
6949 (cperl-write-tags nil nil t t nil t ""))
6950
f83d2997
KH
6951(defun cperl-add-tags-recurse ()
6952 "Add to TAGS file data for Perl files in the current directory and kids.
6953Use as
6954 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
5c8b7eaf 6955 -f cperl-add-tags-recurse
f83d2997
KH
6956"
6957 (cperl-write-tags nil nil t t))
6958
6959(defun cperl-write-tags (&optional file erase recurse dir inbuffer noxs topdir)
6960 ;; If INBUFFER, do not select buffer, and do not save
6961 ;; If ERASE is `ignore', do not erase, and do not try to delete old info.
6962 (require 'etags)
6963 (if file nil
6964 (setq file (if dir default-directory (buffer-file-name)))
6965 (if (and (not dir) (buffer-modified-p)) (error "Save buffer first!")))
6966 (or topdir
6967 (setq topdir default-directory))
6968 (let ((tags-file-name "TAGS")
6969 (case-fold-search (eq system-type 'emx))
6c389151 6970 xs rel tm)
f83d2997
KH
6971 (save-excursion
6972 (cond (inbuffer nil) ; Already there
6973 ((file-exists-p tags-file-name)
6546555e 6974 (if (featurep 'xemacs)
5bd52f0e 6975 (visit-tags-table-buffer)
83261a2f 6976 (visit-tags-table-buffer tags-file-name)))
f83d2997
KH
6977 (t (set-buffer (find-file-noselect tags-file-name))))
6978 (cond
6979 (dir
6980 (cond ((eq erase 'ignore))
6981 (erase
6982 (erase-buffer)
6983 (setq erase 'ignore)))
a1506d29 6984 (let ((files
6c389151 6985 (condition-case err
a1506d29 6986 (directory-files file t
6c389151
SM
6987 (if recurse nil cperl-scan-files-regexp)
6988 t)
6989 (error
6990 (if cperl-unreadable-ok nil
6991 (if (y-or-n-p
6992 (format "Directory %s unreadable. Continue? " file))
a1506d29 6993 (setq cperl-unreadable-ok t
83261a2f 6994 tm nil) ; Return empty list
6c389151 6995 (error "Aborting: unreadable directory %s" file)))))))
dba01120
GM
6996 (mapc (function
6997 (lambda (file)
6998 (cond
6999 ((string-match cperl-noscan-files-regexp file)
7000 nil)
7001 ((not (file-directory-p file))
7002 (if (string-match cperl-scan-files-regexp file)
7003 (cperl-write-tags file erase recurse nil t noxs topdir)))
7004 ((not recurse) nil)
7005 (t (cperl-write-tags file erase recurse t t noxs topdir)))))
7006 files)))
f83d2997
KH
7007 (t
7008 (setq xs (string-match "\\.xs$" file))
7009 (if (not (and xs noxs))
7010 (progn
7011 (cond ((eq erase 'ignore) (goto-char (point-max)))
83261a2f
SM
7012 (erase (erase-buffer))
7013 (t
7014 (goto-char 1)
7015 (setq rel file)
7016 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
7017 (set-text-properties 0 (length rel) nil rel)
7018 (and (equal topdir (substring rel 0 (length topdir)))
7019 (setq rel (substring file (length topdir))))
7020 (if (search-forward (concat "\f\n" rel ",") nil t)
7021 (progn
7022 (search-backward "\f\n")
7023 (delete-region (point)
7024 (save-excursion
7025 (forward-char 1)
7026 (if (search-forward "\f\n"
7027 nil 'toend)
7028 (- (point) 2)
7029 (point-max)))))
7030 (goto-char (point-max)))))
f83d2997 7031 (insert (cperl-find-tags file xs topdir))))))
83261a2f
SM
7032 (if inbuffer nil ; Delegate to the caller
7033 (save-buffer 0) ; No backup
f83d2997
KH
7034 (if (fboundp 'initialize-new-tags-table) ; Do we need something special in XEmacs?
7035 (initialize-new-tags-table))))))
7036
7037(defvar cperl-tags-hier-regexp-list
5c8b7eaf 7038 (concat
f83d2997
KH
7039 "^\\("
7040 "\\(package\\)\\>"
7041 "\\|"
7042 "sub\\>[^\n]+::"
7043 "\\|"
7044 "[a-zA-Z_][a-zA-Z_0-9:]*(\C-?[^\n]+::" ; XSUB?
7045 "\\|"
7046 "[ \t]*BOOT:\C-?[^\n]+::" ; BOOT section
7047 "\\)"))
7048
7049(defvar cperl-hierarchy '(() ())
f94a632a 7050 "Global hierarchy of classes.")
f83d2997
KH
7051
7052(defun cperl-tags-hier-fill ()
7053 ;; Suppose we are in a tag table cooked by cperl.
7054 (goto-char 1)
7055 (let (type pack name pos line chunk ord cons1 file str info fileind)
7056 (while (re-search-forward cperl-tags-hier-regexp-list nil t)
5c8b7eaf 7057 (setq pos (match-beginning 0)
f83d2997
KH
7058 pack (match-beginning 2))
7059 (beginning-of-line)
7060 (if (looking-at (concat
7061 "\\([^\n]+\\)"
7062 "\C-?"
7063 "\\([^\n]+\\)"
7064 "\C-a"
7065 "\\([0-9]+\\)"
7066 ","
7067 "\\([0-9]+\\)"))
7068 (progn
7069 (setq ;;str (buffer-substring (match-beginning 1) (match-end 1))
7070 name (buffer-substring (match-beginning 2) (match-end 2))
7071 ;;pos (buffer-substring (match-beginning 3) (match-end 3))
5bd52f0e 7072 line (buffer-substring (match-beginning 3) (match-end 3))
f83d2997 7073 ord (if pack 1 0)
f83d2997 7074 file (file-of-tag)
5bd52f0e
RS
7075 fileind (format "%s:%s" file line)
7076 ;; Moves to beginning of the next line:
7077 info (cperl-etags-snarf-tag file line))
f83d2997
KH
7078 ;; Move back
7079 (forward-char -1)
7080 ;; Make new member of hierarchy name ==> file ==> pos if needed
7081 (if (setq cons1 (assoc name (nth ord cperl-hierarchy)))
7082 ;; Name known
7083 (setcdr cons1 (cons (cons fileind (vector file info))
7084 (cdr cons1)))
7085 ;; First occurrence of the name, start alist
7086 (setq cons1 (cons name (list (cons fileind (vector file info)))))
5c8b7eaf 7087 (if pack
f83d2997
KH
7088 (setcar (cdr cperl-hierarchy)
7089 (cons cons1 (nth 1 cperl-hierarchy)))
7090 (setcar cperl-hierarchy
7091 (cons cons1 (car cperl-hierarchy)))))))
7092 (end-of-line))))
7093
7094(defun cperl-tags-hier-init (&optional update)
7095 "Show hierarchical menu of classes and methods.
7096Finds info about classes by a scan of loaded TAGS files.
7097Supposes that the TAGS files contain fully qualified function names.
7098One may build such TAGS files from CPerl mode menu."
7099 (interactive)
7100 (require 'etags)
7101 (require 'imenu)
7102 (if (or update (null (nth 2 cperl-hierarchy)))
83261a2f
SM
7103 (let ((remover (function (lambda (elt) ; (name (file1...) (file2..))
7104 (or (nthcdr 2 elt)
7105 ;; Only in one file
7106 (setcdr elt (cdr (nth 1 elt)))))))
7107 pack name cons1 to l1 l2 l3 l4 b)
f83d2997
KH
7108 ;; (setq cperl-hierarchy '(() () ())) ; Would write into '() later!
7109 (setq cperl-hierarchy (list l1 l2 l3))
6546555e 7110 (if (featurep 'xemacs) ; Not checked
5bd52f0e
RS
7111 (progn
7112 (or tags-file-name
7113 ;; Does this work in XEmacs?
f83d2997
KH
7114 (call-interactively 'visit-tags-table))
7115 (message "Updating list of classes...")
5bd52f0e
RS
7116 (set-buffer (get-file-buffer tags-file-name))
7117 (cperl-tags-hier-fill))
7118 (or tags-table-list
7119 (call-interactively 'visit-tags-table))
dba01120 7120 (mapc
4ab89e7b
SM
7121 (function
7122 (lambda (tagsfile)
5bd52f0e 7123 (message "Updating list of classes... %s" tagsfile)
f83d2997
KH
7124 (set-buffer (get-file-buffer tagsfile))
7125 (cperl-tags-hier-fill)))
dba01120 7126 tags-table-list)
5bd52f0e 7127 (message "Updating list of classes... postprocessing..."))
dba01120
GM
7128 (mapc remover (car cperl-hierarchy))
7129 (mapc remover (nth 1 cperl-hierarchy))
f83d2997
KH
7130 (setq to (list nil (cons "Packages: " (nth 1 cperl-hierarchy))
7131 (cons "Methods: " (car cperl-hierarchy))))
7132 (cperl-tags-treeify to 1)
7133 (setcar (nthcdr 2 cperl-hierarchy)
7134 (cperl-menu-to-keymap (cons '("+++UPDATE+++" . -999) (cdr to))))
7135 (message "Updating list of classes: done, requesting display...")
7136 ;;(cperl-imenu-addback (nth 2 cperl-hierarchy))
7137 ))
7138 (or (nth 2 cperl-hierarchy)
7139 (error "No items found"))
7140 (setq update
7141;;; (imenu-choose-buffer-index "Packages: " (nth 2 cperl-hierarchy))
83261a2f
SM
7142 (if (if (fboundp 'display-popup-menus-p)
7143 (let ((f 'display-popup-menus-p))
7144 (funcall f))
7145 window-system)
f83d2997
KH
7146 (x-popup-menu t (nth 2 cperl-hierarchy))
7147 (require 'tmm)
7148 (tmm-prompt (nth 2 cperl-hierarchy))))
7149 (if (and update (listp update))
7150 (progn (while (cdr update) (setq update (cdr update)))
7151 (setq update (car update)))) ; Get the last from the list
5c8b7eaf 7152 (if (vectorp update)
f83d2997
KH
7153 (progn
7154 (find-file (elt update 0))
5bd52f0e 7155 (cperl-etags-goto-tag-location (elt update 1))))
f83d2997
KH
7156 (if (eq update -999) (cperl-tags-hier-init t)))
7157
7158(defun cperl-tags-treeify (to level)
7159 ;; cadr of `to' is read-write. On start it is a cons
5c8b7eaf 7160 (let* ((regexp (concat "^\\(" (mapconcat
f83d2997
KH
7161 'identity
7162 (make-list level "[_a-zA-Z0-9]+")
7163 "::")
7164 "\\)\\(::\\)?"))
7165 (packages (cdr (nth 1 to)))
7166 (methods (cdr (nth 2 to)))
7167 l1 head tail cons1 cons2 ord writeto packs recurse
7168 root-packages root-functions ms many_ms same_name ps
7169 (move-deeper
5c8b7eaf 7170 (function
f83d2997
KH
7171 (lambda (elt)
7172 (cond ((and (string-match regexp (car elt))
7173 (or (eq ord 1) (match-end 2)))
7174 (setq head (substring (car elt) 0 (match-end 1))
5c8b7eaf 7175 tail (if (match-end 2) (substring (car elt)
f83d2997
KH
7176 (match-end 2)))
7177 recurse t)
7178 (if (setq cons1 (assoc head writeto)) nil
7179 ;; Need to init new head
7180 (setcdr writeto (cons (list head (list "Packages: ")
7181 (list "Methods: "))
7182 (cdr writeto)))
7183 (setq cons1 (nth 1 writeto)))
7184 (setq cons2 (nth ord cons1)) ; Either packs or meths
7185 (setcdr cons2 (cons elt (cdr cons2))))
7186 ((eq ord 2)
7187 (setq root-functions (cons elt root-functions)))
7188 (t
7189 (setq root-packages (cons elt root-packages))))))))
7190 (setcdr to l1) ; Init to dynamic space
7191 (setq writeto to)
7192 (setq ord 1)
dba01120 7193 (mapc move-deeper packages)
f83d2997 7194 (setq ord 2)
dba01120 7195 (mapc move-deeper methods)
f83d2997 7196 (if recurse
dba01120 7197 (mapc (function (lambda (elt)
f83d2997 7198 (cperl-tags-treeify elt (1+ level))))
dba01120 7199 (cdr to)))
f83d2997 7200 ;;Now clean up leaders with one child only
dba01120
GM
7201 (mapc (function (lambda (elt)
7202 (if (not (and (listp (cdr elt))
7203 (eq (length elt) 2))) nil
7204 (setcar elt (car (nth 1 elt)))
7205 (setcdr elt (cdr (nth 1 elt))))))
7206 (cdr to))
f83d2997
KH
7207 ;; Sort the roots of subtrees
7208 (if (default-value 'imenu-sort-function)
7209 (setcdr to
7210 (sort (cdr to) (default-value 'imenu-sort-function))))
7211 ;; Now add back functions removed from display
dba01120
GM
7212 (mapc (function (lambda (elt)
7213 (setcdr to (cons elt (cdr to)))))
7214 (if (default-value 'imenu-sort-function)
7215 (nreverse
7216 (sort root-functions (default-value 'imenu-sort-function)))
7217 root-functions))
f83d2997 7218 ;; Now add back packages removed from display
dba01120
GM
7219 (mapc (function (lambda (elt)
7220 (setcdr to (cons (cons (concat "package " (car elt))
7221 (cdr elt))
7222 (cdr to)))))
7223 (if (default-value 'imenu-sort-function)
7224 (nreverse
7225 (sort root-packages (default-value 'imenu-sort-function)))
7226 root-packages))))
f83d2997
KH
7227
7228;;;(x-popup-menu t
5c8b7eaf 7229;;; '(keymap "Name1"
f83d2997 7230;;; ("Ret1" "aa")
5c8b7eaf
SS
7231;;; ("Head1" "ab"
7232;;; keymap "Name2"
f83d2997
KH
7233;;; ("Tail1" "x") ("Tail2" "y"))))
7234
7235(defun cperl-list-fold (list name limit)
7236 (let (list1 list2 elt1 (num 0))
7237 (if (<= (length list) limit) list
7238 (setq list1 nil list2 nil)
7239 (while list
5c8b7eaf 7240 (setq num (1+ num)
f83d2997
KH
7241 elt1 (car list)
7242 list (cdr list))
7243 (if (<= num imenu-max-items)
7244 (setq list2 (cons elt1 list2))
7245 (setq list1 (cons (cons name
7246 (nreverse list2))
7247 list1)
7248 list2 (list elt1)
7249 num 1)))
7250 (nreverse (cons (cons name
7251 (nreverse list2))
7252 list1)))))
7253
7254(defun cperl-menu-to-keymap (menu &optional name)
7255 (let (list)
5c8b7eaf
SS
7256 (cons 'keymap
7257 (mapcar
7258 (function
f83d2997
KH
7259 (lambda (elt)
7260 (cond ((listp (cdr elt))
7261 (setq list (cperl-list-fold
7262 (cdr elt) (car elt) imenu-max-items))
7263 (cons nil
7264 (cons (car elt)
7265 (cperl-menu-to-keymap list))))
7266 (t
7267 (list (cdr elt) (car elt) t))))) ; t is needed in 19.34
7268 (cperl-list-fold menu "Root" imenu-max-items)))))
7269
7270\f
7271(defvar cperl-bad-style-regexp
7272 (mapconcat 'identity
83261a2f 7273 '("[^-\n\t <>=+!.&|(*/'`\"#^][-=+<>!|&^]" ; char sign
15ca5699 7274 "[-<>=+^&|]+[^- \t\n=+<>~]") ; sign+ char
83261a2f 7275 "\\|")
f83d2997
KH
7276 "Finds places such that insertion of a whitespace may help a lot.")
7277
5c8b7eaf 7278(defvar cperl-not-bad-style-regexp
15ca5699 7279 (mapconcat
83261a2f 7280 'identity
f83d2997
KH
7281 '("[^-\t <>=+]\\(--\\|\\+\\+\\)" ; var-- var++
7282 "[a-zA-Z0-9_][|&][a-zA-Z0-9_$]" ; abc|def abc&def are often used.
7283 "&[(a-zA-Z0-9_$]" ; &subroutine &(var->field)
4ab89e7b 7284 "<\\$?\\sw+\\(\\.\\(\\sw\\|_\\)+\\)?>" ; <IN> <stdin.h>
5bd52f0e 7285 "-[a-zA-Z][ \t]+[_$\"'`a-zA-Z]" ; -f file, -t STDIN
f83d2997
KH
7286 "-[0-9]" ; -5
7287 "\\+\\+" ; ++var
7288 "--" ; --var
7289 ".->" ; a->b
7290 "->" ; a SPACE ->b
7291 "\\[-" ; a[-1]
5bd52f0e 7292 "\\\\[&$@*\\\\]" ; \&func
f83d2997 7293 "^=" ; =head
5bd52f0e
RS
7294 "\\$." ; $|
7295 "<<[a-zA-Z_'\"`]" ; <<FOO, <<'FOO'
f83d2997
KH
7296 "||"
7297 "&&"
7298 "[CBIXSLFZ]<\\(\\sw\\|\\s \\|\\s_\\|[\n]\\)*>" ; C<code like text>
83261a2f 7299 "-[a-zA-Z_0-9]+[ \t]*=>" ; -option => value
f83d2997
KH
7300 ;; Unaddressed trouble spots: = -abc, f(56, -abc) --- specialcased below
7301 ;;"[*/+-|&<.]+="
7302 )
7303 "\\|")
7304 "If matches at the start of match found by `my-bad-c-style-regexp',
7305insertion of a whitespace will not help.")
7306
7307(defvar found-bad)
7308
7309(defun cperl-find-bad-style ()
7310 "Find places in the buffer where insertion of a whitespace may help.
7311Prompts user for insertion of spaces.
7312Currently it is tuned to C and Perl syntax."
7313 (interactive)
7314 (let (found-bad (p (point)))
7315 (setq last-nonmenu-event 13) ; To disable popup
4ab89e7b 7316 (goto-char (point-min))
f83d2997 7317 (map-y-or-n-p "Insert space here? "
83261a2f 7318 (lambda (arg) (insert " "))
f83d2997 7319 'cperl-next-bad-style
5c8b7eaf 7320 '("location" "locations" "insert a space into")
f83d2997
KH
7321 '((?\C-r (lambda (arg)
7322 (let ((buffer-quit-function
7323 'exit-recursive-edit))
7324 (message "Exit with Esc Esc")
7325 (recursive-edit)
7326 t)) ; Consider acted upon
5c8b7eaf 7327 "edit, exit with Esc Esc")
f83d2997
KH
7328 (?e (lambda (arg)
7329 (let ((buffer-quit-function
7330 'exit-recursive-edit))
7331 (message "Exit with Esc Esc")
7332 (recursive-edit)
7333 t)) ; Consider acted upon
7334 "edit, exit with Esc Esc"))
7335 t)
7336 (if found-bad (goto-char found-bad)
7337 (goto-char p)
7338 (message "No appropriate place found"))))
7339
7340(defun cperl-next-bad-style ()
7341 (let (p (not-found t) (point (point)) found)
7342 (while (and not-found
7343 (re-search-forward cperl-bad-style-regexp nil 'to-end))
7344 (setq p (point))
7345 (goto-char (match-beginning 0))
7346 (if (or
7347 (looking-at cperl-not-bad-style-regexp)
7348 ;; Check for a < -b and friends
7349 (and (eq (following-char) ?\-)
7350 (save-excursion
7351 (skip-chars-backward " \t\n")
07cb2aa3 7352 (memq (preceding-char) '(?\= ?\> ?\< ?\, ?\( ?\[ ?\{))))
f83d2997
KH
7353 ;; Now check for syntax type
7354 (save-match-data
7355 (setq found (point))
7356 (beginning-of-defun)
7357 (let ((pps (parse-partial-sexp (point) found)))
7358 (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))
7359 (goto-char (match-end 0))
7360 (goto-char (1- p))
7361 (setq not-found nil
7362 found-bad found)))
7363 (not not-found)))
7364
f1d851ae 7365\f
f83d2997 7366;;; Getting help
5c8b7eaf 7367(defvar cperl-have-help-regexp
f83d2997
KH
7368 ;;(concat "\\("
7369 (mapconcat
7370 'identity
83261a2f 7371 '("[$@%*&][0-9a-zA-Z_:]+\\([ \t]*[[{]\\)?" ; Usual variable
f83d2997
KH
7372 "[$@]\\^[a-zA-Z]" ; Special variable
7373 "[$@][^ \n\t]" ; Special variable
7374 "-[a-zA-Z]" ; File test
7375 "\\\\[a-zA-Z0]" ; Special chars
83261a2f 7376 "^=[a-z][a-zA-Z0-9_]*" ; POD sections
f83d2997
KH
7377 "[-!&*+,-./<=>?\\\\^|~]+" ; Operator
7378 "[a-zA-Z_0-9:]+" ; symbol or number
7379 "x="
83261a2f 7380 "#!")
f83d2997 7381 ;;"\\)\\|\\("
83261a2f
SM
7382 "\\|")
7383 ;;"\\)"
7384 ;;)
f83d2997
KH
7385 "Matches places in the buffer we can find help for.")
7386
7387(defvar cperl-message-on-help-error t)
7388(defvar cperl-help-from-timer nil)
7389
7390(defun cperl-word-at-point-hard ()
7391 ;; Does not save-excursion
7392 ;; Get to the something meaningful
7393 (or (eobp) (eolp) (forward-char 1))
5c8b7eaf 7394 (re-search-backward "[-a-zA-Z0-9_:!&*+,-./<=>?\\\\^|~$%@]"
f83d2997
KH
7395 (save-excursion (beginning-of-line) (point))
7396 'to-beg)
7397 ;; (cond
7398 ;; ((or (eobp) (looking-at "[][ \t\n{}();,]")) ; Not at a symbol
7399 ;; (skip-chars-backward " \n\t\r({[]});,")
7400 ;; (or (bobp) (backward-char 1))))
7401 ;; Try to backtrace
7402 (cond
7403 ((looking-at "[a-zA-Z0-9_:]") ; symbol
7404 (skip-chars-backward "a-zA-Z0-9_:")
5c8b7eaf 7405 (cond
f83d2997
KH
7406 ((and (eq (preceding-char) ?^) ; $^I
7407 (eq (char-after (- (point) 2)) ?\$))
7408 (forward-char -2))
7409 ((memq (preceding-char) (append "*$@%&\\" nil)) ; *glob
7410 (forward-char -1))
7411 ((and (eq (preceding-char) ?\=)
7412 (eq (current-column) 1))
7413 (forward-char -1))) ; =head1
7414 (if (and (eq (preceding-char) ?\<)
7415 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <FH>
7416 (forward-char -1)))
7417 ((and (looking-at "=") (eq (preceding-char) ?x)) ; x=
7418 (forward-char -1))
7419 ((and (looking-at "\\^") (eq (preceding-char) ?\$)) ; $^I
7420 (forward-char -1))
7421 ((looking-at "[-!&*+,-./<=>?\\\\^|~]")
7422 (skip-chars-backward "-!&*+,-./<=>?\\\\^|~")
7423 (cond
7424 ((and (eq (preceding-char) ?\$)
7425 (not (eq (char-after (- (point) 2)) ?\$))) ; $-
7426 (forward-char -1))
7427 ((and (eq (following-char) ?\>)
7428 (string-match "[a-zA-Z0-9_]" (char-to-string (preceding-char)))
7429 (save-excursion
7430 (forward-sexp -1)
7431 (and (eq (preceding-char) ?\<)
7432 (looking-at "\\$?[a-zA-Z0-9_:]+>")))) ; <FH>
7433 (search-backward "<"))))
7434 ((and (eq (following-char) ?\$)
7435 (eq (preceding-char) ?\<)
7436 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <$fh>
7437 (forward-char -1)))
7438 (if (looking-at cperl-have-help-regexp)
7439 (buffer-substring (match-beginning 0) (match-end 0))))
7440
7441(defun cperl-get-help ()
7442 "Get one-line docs on the symbol at the point.
7443The data for these docs is a little bit obsolete and may be in fact longer
7444than a line. Your contribution to update/shorten it is appreciated."
7445 (interactive)
7446 (save-match-data ; May be called "inside" query-replace
7447 (save-excursion
7448 (let ((word (cperl-word-at-point-hard)))
7449 (if word
7450 (if (and cperl-help-from-timer ; Bail out if not in mainland
7451 (not (string-match "^#!\\|\\\\\\|^=" word)) ; Show help even in comments/strings.
7452 (or (memq (get-text-property (point) 'face)
7453 '(font-lock-comment-face font-lock-string-face))
7454 (memq (get-text-property (point) 'syntax-type)
7455 '(pod here-doc format))))
7456 nil
7457 (cperl-describe-perl-symbol word))
7458 (if cperl-message-on-help-error
5c8b7eaf 7459 (message "Nothing found for %s..."
f83d2997
KH
7460 (buffer-substring (point) (min (+ 5 (point)) (point-max))))))))))
7461
7462;;; Stolen from perl-descr.el by Johan Vromans:
7463
7464(defvar cperl-doc-buffer " *perl-doc*"
7465 "Where the documentation can be found.")
7466
7467(defun cperl-describe-perl-symbol (val)
7468 "Display the documentation of symbol at point, a Perl operator."
7469 (let ((enable-recursive-minibuffers t)
7470 args-file regexp)
7471 (cond
83261a2f
SM
7472 ((string-match "^[&*][a-zA-Z_]" val)
7473 (setq val (concat (substring val 0 1) "NAME")))
7474 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*\\[" val)
7475 (setq val (concat "@" (substring val 1 (match-end 1)))))
7476 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*{" val)
7477 (setq val (concat "%" (substring val 1 (match-end 1)))))
7478 ((and (string= val "x") (string-match "^x=" val))
7479 (setq val "x="))
7480 ((string-match "^\\$[\C-a-\C-z]" val)
7481 (setq val (concat "$^" (char-to-string (+ ?A -1 (aref val 1))))))
7482 ((string-match "^CORE::" val)
7483 (setq val "CORE::"))
7484 ((string-match "^SUPER::" val)
7485 (setq val "SUPER::"))
7486 ((and (string= "<" val) (string-match "^<\\$?[a-zA-Z0-9_:]+>" val))
7487 (setq val "<NAME>")))
5c8b7eaf 7488 (setq regexp (concat "^"
f83d2997 7489 "\\([^a-zA-Z0-9_:]+[ \t]+\\)?"
5c8b7eaf 7490 (regexp-quote val)
f83d2997
KH
7491 "\\([ \t([/]\\|$\\)"))
7492
7493 ;; get the buffer with the documentation text
7494 (cperl-switch-to-doc-buffer)
7495
7496 ;; lookup in the doc
7497 (goto-char (point-min))
7498 (let ((case-fold-search nil))
5c8b7eaf 7499 (list
f83d2997
KH
7500 (if (re-search-forward regexp (point-max) t)
7501 (save-excursion
7502 (beginning-of-line 1)
7503 (let ((lnstart (point)))
7504 (end-of-line)
7505 (message "%s" (buffer-substring lnstart (point)))))
7506 (if cperl-message-on-help-error
7507 (message "No definition for %s" val)))))))
7508
83261a2f 7509(defvar cperl-short-docs 'please-ignore-this-line
f83d2997
KH
7510 ;; Perl4 version was written by Johan Vromans (jvromans@squirrel.nl)
7511 "# based on '@(#)@ perl-descr.el 1.9 - describe-perl-symbol' [Perl 5]
f739b53b 7512... Range (list context); flip/flop [no flop when flip] (scalar context).
5c8b7eaf 7513! ... Logical negation.
f83d2997
KH
7514... != ... Numeric inequality.
7515... !~ ... Search pattern, substitution, or translation (negated).
7516$! In numeric context: errno. In a string context: error string.
7517$\" The separator which joins elements of arrays interpolated in strings.
f739b53b 7518$# The output format for printed numbers. Default is %.15g or close.
f83d2997
KH
7519$$ Process number of this script. Changes in the fork()ed child process.
7520$% The current page number of the currently selected output channel.
7521
7522 The following variables are always local to the current block:
7523
7524$1 Match of the 1st set of parentheses in the last match (auto-local).
7525$2 Match of the 2nd set of parentheses in the last match (auto-local).
7526$3 Match of the 3rd set of parentheses in the last match (auto-local).
7527$4 Match of the 4th set of parentheses in the last match (auto-local).
7528$5 Match of the 5th set of parentheses in the last match (auto-local).
7529$6 Match of the 6th set of parentheses in the last match (auto-local).
7530$7 Match of the 7th set of parentheses in the last match (auto-local).
7531$8 Match of the 8th set of parentheses in the last match (auto-local).
7532$9 Match of the 9th set of parentheses in the last match (auto-local).
7533$& The string matched by the last pattern match (auto-local).
7534$' The string after what was matched by the last match (auto-local).
7535$` The string before what was matched by the last match (auto-local).
7536
7537$( The real gid of this process.
7538$) The effective gid of this process.
7539$* Deprecated: Set to 1 to do multiline matching within a string.
7540$+ The last bracket matched by the last search pattern.
7541$, The output field separator for the print operator.
7542$- The number of lines left on the page.
7543$. The current input line number of the last filehandle that was read.
7544$/ The input record separator, newline by default.
f739b53b 7545$0 Name of the file containing the current perl script (read/write).
f83d2997
KH
7546$: String may be broken after these characters to fill ^-lines in a format.
7547$; Subscript separator for multi-dim array emulation. Default \"\\034\".
7548$< The real uid of this process.
7549$= The page length of the current output channel. Default is 60 lines.
7550$> The effective uid of this process.
7551$? The status returned by the last ``, pipe close or `system'.
7552$@ The perl error message from the last eval or do @var{EXPR} command.
7553$ARGV The name of the current file used with <> .
7554$[ Deprecated: The index of the first element/char in an array/string.
7555$\\ The output record separator for the print operator.
7556$] The perl version string as displayed with perl -v.
7557$^ The name of the current top-of-page format.
7558$^A The current value of the write() accumulator for format() lines.
7559$^D The value of the perl debug (-D) flags.
7560$^E Information about the last system error other than that provided by $!.
7561$^F The highest system file descriptor, ordinarily 2.
7562$^H The current set of syntax checks enabled by `use strict'.
7563$^I The value of the in-place edit extension (perl -i option).
d7584f0f 7564$^L What formats output to perform a formfeed. Default is \\f.
5bd52f0e 7565$^M A buffer for emergency memory allocation when running out of memory.
f83d2997
KH
7566$^O The operating system name under which this copy of Perl was built.
7567$^P Internal debugging flag.
7568$^T The time the script was started. Used by -A/-M/-C file tests.
7569$^W True if warnings are requested (perl -w flag).
7570$^X The name under which perl was invoked (argv[0] in C-speech).
7571$_ The default input and pattern-searching space.
5c8b7eaf 7572$| Auto-flush after write/print on current output channel? Default 0.
f83d2997
KH
7573$~ The name of the current report format.
7574... % ... Modulo division.
7575... %= ... Modulo division assignment.
7576%ENV Contains the current environment.
7577%INC List of files that have been require-d or do-ne.
7578%SIG Used to set signal handlers for various signals.
7579... & ... Bitwise and.
7580... && ... Logical and.
7581... &&= ... Logical and assignment.
7582... &= ... Bitwise and assignment.
7583... * ... Multiplication.
7584... ** ... Exponentiation.
7585*NAME Glob: all objects refered by NAME. *NAM1 = *NAM2 aliases NAM1 to NAM2.
7586&NAME(arg0, ...) Subroutine call. Arguments go to @_.
7587... + ... Addition. +EXPR Makes EXPR into scalar context.
7588++ Auto-increment (magical on strings). ++EXPR EXPR++
7589... += ... Addition assignment.
7590, Comma operator.
7591... - ... Subtraction.
7592-- Auto-decrement (NOT magical on strings). --EXPR EXPR--
7593... -= ... Subtraction assignment.
7594-A Access time in days since script started.
7595-B File is a non-text (binary) file.
7596-C Inode change time in days since script started.
7597-M Age in days since script started.
7598-O File is owned by real uid.
7599-R File is readable by real uid.
7600-S File is a socket .
7601-T File is a text file.
7602-W File is writable by real uid.
7603-X File is executable by real uid.
7604-b File is a block special file.
7605-c File is a character special file.
7606-d File is a directory.
7607-e File exists .
7608-f File is a plain file.
7609-g File has setgid bit set.
7610-k File has sticky bit set.
7611-l File is a symbolic link.
7612-o File is owned by effective uid.
7613-p File is a named pipe (FIFO).
7614-r File is readable by effective uid.
7615-s File has non-zero size.
7616-t Tests if filehandle (STDIN by default) is opened to a tty.
7617-u File has setuid bit set.
7618-w File is writable by effective uid.
7619-x File is executable by effective uid.
7620-z File has zero size.
7621. Concatenate strings.
f739b53b 7622.. Range (list context); flip/flop (scalar context) operator.
f83d2997
KH
7623.= Concatenate assignment strings
7624... / ... Division. /PATTERN/ioxsmg Pattern match
7625... /= ... Division assignment.
7626/PATTERN/ioxsmg Pattern match.
f739b53b 7627... < ... Numeric less than. <pattern> Glob. See <NAME>, <> as well.
f83d2997
KH
7628<NAME> Reads line from filehandle NAME (a bareword or dollar-bareword).
7629<pattern> Glob (Unless pattern is bareword/dollar-bareword - see <NAME>).
7630<> Reads line from union of files in @ARGV (= command line) and STDIN.
7631... << ... Bitwise shift left. << start of HERE-DOCUMENT.
7632... <= ... Numeric less than or equal to.
7633... <=> ... Numeric compare.
7634... = ... Assignment.
7635... == ... Numeric equality.
7636... =~ ... Search pattern, substitution, or translation
7637... > ... Numeric greater than.
7638... >= ... Numeric greater than or equal to.
7639... >> ... Bitwise shift right.
7640... >>= ... Bitwise shift right assignment.
7641... ? ... : ... Condition=if-then-else operator. ?PAT? One-time pattern match.
7642?PATTERN? One-time pattern match.
7643@ARGV Command line arguments (not including the command name - see $0).
7644@INC List of places to look for perl scripts during do/include/use.
f739b53b 7645@_ Parameter array for subroutines; result of split() unless in list context.
d7584f0f 7646\\ Creates reference to what follows, like \\$var, or quotes non-\\w in strings.
f83d2997
KH
7647\\0 Octal char, e.g. \\033.
7648\\E Case modification terminator. See \\Q, \\L, and \\U.
d7584f0f
AS
7649\\L Lowercase until \\E . See also \\l, lc.
7650\\U Upcase until \\E . See also \\u, uc.
f83d2997
KH
7651\\Q Quote metacharacters until \\E . See also quotemeta.
7652\\a Alarm character (octal 007).
7653\\b Backspace character (octal 010).
7654\\c Control character, e.g. \\c[ .
7655\\e Escape character (octal 033).
7656\\f Formfeed character (octal 014).
7657\\l Lowercase the next character. See also \\L and \\u, lcfirst.
7658\\n Newline character (octal 012 on most systems).
7659\\r Return character (octal 015 on most systems).
7660\\t Tab character (octal 011).
7661\\u Upcase the next character. See also \\U and \\l, ucfirst.
7662\\x Hex character, e.g. \\x1b.
7663... ^ ... Bitwise exclusive or.
7664__END__ Ends program source.
7665__DATA__ Ends program source.
7666__FILE__ Current (source) filename.
7667__LINE__ Current line in current source.
7668__PACKAGE__ Current package.
7669ARGV Default multi-file input filehandle. <ARGV> is a synonym for <>.
7670ARGVOUT Output filehandle with -i flag.
7671BEGIN { ... } Immediately executed (during compilation) piece of code.
7672END { ... } Pseudo-subroutine executed after the script finishes.
6c389151
SM
7673CHECK { ... } Pseudo-subroutine executed after the script is compiled.
7674INIT { ... } Pseudo-subroutine executed before the script starts running.
f83d2997
KH
7675DATA Input filehandle for what follows after __END__ or __DATA__.
7676accept(NEWSOCKET,GENERICSOCKET)
7677alarm(SECONDS)
7678atan2(X,Y)
7679bind(SOCKET,NAME)
7680binmode(FILEHANDLE)
7681caller[(LEVEL)]
7682chdir(EXPR)
7683chmod(LIST)
7684chop[(LIST|VAR)]
7685chown(LIST)
7686chroot(FILENAME)
7687close(FILEHANDLE)
7688closedir(DIRHANDLE)
7689... cmp ... String compare.
7690connect(SOCKET,NAME)
7691continue of { block } continue { block }. Is executed after `next' or at end.
7692cos(EXPR)
7693crypt(PLAINTEXT,SALT)
7694dbmclose(%HASH)
7695dbmopen(%HASH,DBNAME,MODE)
7696defined(EXPR)
7697delete($HASH{KEY})
7698die(LIST)
7699do { ... }|SUBR while|until EXPR executes at least once
7700do(EXPR|SUBR([LIST])) (with while|until executes at least once)
7701dump LABEL
7702each(%HASH)
7703endgrent
7704endhostent
7705endnetent
7706endprotoent
7707endpwent
7708endservent
7709eof[([FILEHANDLE])]
7710... eq ... String equality.
7711eval(EXPR) or eval { BLOCK }
4ab89e7b 7712exec([TRUENAME] ARGV0, ARGVs) or exec(SHELL_COMMAND_LINE)
f83d2997
KH
7713exit(EXPR)
7714exp(EXPR)
7715fcntl(FILEHANDLE,FUNCTION,SCALAR)
7716fileno(FILEHANDLE)
7717flock(FILEHANDLE,OPERATION)
7718for (EXPR;EXPR;EXPR) { ... }
7719foreach [VAR] (@ARRAY) { ... }
7720fork
7721... ge ... String greater than or equal.
7722getc[(FILEHANDLE)]
7723getgrent
7724getgrgid(GID)
7725getgrnam(NAME)
7726gethostbyaddr(ADDR,ADDRTYPE)
7727gethostbyname(NAME)
7728gethostent
7729getlogin
7730getnetbyaddr(ADDR,ADDRTYPE)
7731getnetbyname(NAME)
7732getnetent
7733getpeername(SOCKET)
7734getpgrp(PID)
7735getppid
7736getpriority(WHICH,WHO)
7737getprotobyname(NAME)
7738getprotobynumber(NUMBER)
7739getprotoent
7740getpwent
7741getpwnam(NAME)
7742getpwuid(UID)
7743getservbyname(NAME,PROTO)
7744getservbyport(PORT,PROTO)
7745getservent
7746getsockname(SOCKET)
7747getsockopt(SOCKET,LEVEL,OPTNAME)
7748gmtime(EXPR)
7749goto LABEL
f83d2997
KH
7750... gt ... String greater than.
7751hex(EXPR)
7752if (EXPR) { ... } [ elsif (EXPR) { ... } ... ] [ else { ... } ] or EXPR if EXPR
7753index(STR,SUBSTR[,OFFSET])
7754int(EXPR)
7755ioctl(FILEHANDLE,FUNCTION,SCALAR)
7756join(EXPR,LIST)
7757keys(%HASH)
7758kill(LIST)
7759last [LABEL]
7760... le ... String less than or equal.
7761length(EXPR)
7762link(OLDFILE,NEWFILE)
7763listen(SOCKET,QUEUESIZE)
7764local(LIST)
7765localtime(EXPR)
7766log(EXPR)
7767lstat(EXPR|FILEHANDLE|VAR)
7768... lt ... String less than.
7769m/PATTERN/iogsmx
7770mkdir(FILENAME,MODE)
7771msgctl(ID,CMD,ARG)
7772msgget(KEY,FLAGS)
7773msgrcv(ID,VAR,SIZE,TYPE.FLAGS)
7774msgsnd(ID,MSG,FLAGS)
7775my VAR or my (VAR1,...) Introduces a lexical variable ($VAR, @ARR, or %HASH).
6c389151 7776our VAR or our (VAR1,...) Lexically enable a global variable ($V, @A, or %H).
f83d2997
KH
7777... ne ... String inequality.
7778next [LABEL]
7779oct(EXPR)
7780open(FILEHANDLE[,EXPR])
7781opendir(DIRHANDLE,EXPR)
7782ord(EXPR) ASCII value of the first char of the string.
7783pack(TEMPLATE,LIST)
7784package NAME Introduces package context.
7785pipe(READHANDLE,WRITEHANDLE) Create a pair of filehandles on ends of a pipe.
7786pop(ARRAY)
7787print [FILEHANDLE] [(LIST)]
7788printf [FILEHANDLE] (FORMAT,LIST)
7789push(ARRAY,LIST)
7790q/STRING/ Synonym for 'STRING'
7791qq/STRING/ Synonym for \"STRING\"
7792qx/STRING/ Synonym for `STRING`
7793rand[(EXPR)]
7794read(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7795readdir(DIRHANDLE)
7796readlink(EXPR)
7797recv(SOCKET,SCALAR,LEN,FLAGS)
7798redo [LABEL]
7799rename(OLDNAME,NEWNAME)
7800require [FILENAME | PERL_VERSION]
7801reset[(EXPR)]
7802return(LIST)
7803reverse(LIST)
7804rewinddir(DIRHANDLE)
7805rindex(STR,SUBSTR[,OFFSET])
7806rmdir(FILENAME)
7807s/PATTERN/REPLACEMENT/gieoxsm
7808scalar(EXPR)
7809seek(FILEHANDLE,POSITION,WHENCE)
7810seekdir(DIRHANDLE,POS)
7811select(FILEHANDLE | RBITS,WBITS,EBITS,TIMEOUT)
7812semctl(ID,SEMNUM,CMD,ARG)
7813semget(KEY,NSEMS,SIZE,FLAGS)
7814semop(KEY,...)
7815send(SOCKET,MSG,FLAGS[,TO])
7816setgrent
7817sethostent(STAYOPEN)
7818setnetent(STAYOPEN)
7819setpgrp(PID,PGRP)
7820setpriority(WHICH,WHO,PRIORITY)
7821setprotoent(STAYOPEN)
7822setpwent
7823setservent(STAYOPEN)
7824setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)
7825shift[(ARRAY)]
7826shmctl(ID,CMD,ARG)
7827shmget(KEY,SIZE,FLAGS)
7828shmread(ID,VAR,POS,SIZE)
7829shmwrite(ID,STRING,POS,SIZE)
7830shutdown(SOCKET,HOW)
7831sin(EXPR)
7832sleep[(EXPR)]
7833socket(SOCKET,DOMAIN,TYPE,PROTOCOL)
7834socketpair(SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL)
7835sort [SUBROUTINE] (LIST)
7836splice(ARRAY,OFFSET[,LENGTH[,LIST]])
7837split[(/PATTERN/[,EXPR[,LIMIT]])]
7838sprintf(FORMAT,LIST)
7839sqrt(EXPR)
7840srand(EXPR)
7841stat(EXPR|FILEHANDLE|VAR)
7842study[(SCALAR)]
7843sub [NAME [(format)]] { BODY } sub NAME [(format)]; sub [(format)] {...}
7844substr(EXPR,OFFSET[,LEN])
7845symlink(OLDFILE,NEWFILE)
7846syscall(LIST)
7847sysread(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
4ab89e7b 7848system([TRUENAME] ARGV0 [,ARGV]) or system(SHELL_COMMAND_LINE)
f83d2997
KH
7849syswrite(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7850tell[(FILEHANDLE)]
7851telldir(DIRHANDLE)
7852time
7853times
7854tr/SEARCHLIST/REPLACEMENTLIST/cds
7855truncate(FILE|EXPR,LENGTH)
7856umask[(EXPR)]
7857undef[(EXPR)]
7858unless (EXPR) { ... } [ else { ... } ] or EXPR unless EXPR
7859unlink(LIST)
7860unpack(TEMPLATE,EXPR)
7861unshift(ARRAY,LIST)
7862until (EXPR) { ... } EXPR until EXPR
7863utime(LIST)
7864values(%HASH)
7865vec(EXPR,OFFSET,BITS)
7866wait
7867waitpid(PID,FLAGS)
7868wantarray Returns true if the sub/eval is called in list context.
7869warn(LIST)
7870while (EXPR) { ... } EXPR while EXPR
7871write[(EXPR|FILEHANDLE)]
7872... x ... Repeat string or array.
7873x= ... Repetition assignment.
7874y/SEARCHLIST/REPLACEMENTLIST/
7875... | ... Bitwise or.
7876... || ... Logical or.
7877~ ... Unary bitwise complement.
db133cb6 7878#! OS interpreter indicator. If contains `perl', used for options, and -x.
f83d2997
KH
7879AUTOLOAD {...} Shorthand for `sub AUTOLOAD {...}'.
7880CORE:: Prefix to access builtin function if imported sub obscures it.
7881SUPER:: Prefix to lookup for a method in @ISA classes.
7882DESTROY Shorthand for `sub DESTROY {...}'.
7883... EQ ... Obsolete synonym of `eq'.
7884... GE ... Obsolete synonym of `ge'.
7885... GT ... Obsolete synonym of `gt'.
7886... LE ... Obsolete synonym of `le'.
7887... LT ... Obsolete synonym of `lt'.
7888... NE ... Obsolete synonym of `ne'.
7889abs [ EXPR ] absolute value
7890... and ... Low-precedence synonym for &&.
7891bless REFERENCE [, PACKAGE] Makes reference into an object of a package.
7892chomp [LIST] Strips $/ off LIST/$_. Returns count. Special if $/ eq ''!
7893chr Converts a number to char with the same ordinal.
7894else Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
7895elsif Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
83261a2f 7896exists $HASH{KEY} True if the key exists.
f83d2997
KH
7897format [NAME] = Start of output format. Ended by a single dot (.) on a line.
7898formline PICTURE, LIST Backdoor into \"format\" processing.
7899glob EXPR Synonym of <EXPR>.
7900lc [ EXPR ] Returns lowercased EXPR.
7901lcfirst [ EXPR ] Returns EXPR with lower-cased first letter.
db133cb6 7902grep EXPR,LIST or grep {BLOCK} LIST Filters LIST via EXPR/BLOCK.
f83d2997
KH
7903map EXPR, LIST or map {BLOCK} LIST Applies EXPR/BLOCK to elts of LIST.
7904no PACKAGE [SYMBOL1, ...] Partial reverse for `use'. Runs `unimport' method.
7905not ... Low-precedence synonym for ! - negation.
7906... or ... Low-precedence synonym for ||.
7907pos STRING Set/Get end-position of the last match over this string, see \\G.
7908quotemeta [ EXPR ] Quote regexp metacharacters.
7909qw/WORD1 .../ Synonym of split('', 'WORD1 ...')
7910readline FH Synonym of <FH>.
7911readpipe CMD Synonym of `CMD`.
7912ref [ EXPR ] Type of EXPR when dereferenced.
7913sysopen FH, FILENAME, MODE [, PERM] (MODE is numeric, see Fcntl.)
7914tie VAR, PACKAGE, LIST Hide an object behind a simple Perl variable.
7915tied Returns internal object for a tied data.
7916uc [ EXPR ] Returns upcased EXPR.
7917ucfirst [ EXPR ] Returns EXPR with upcased first letter.
7918untie VAR Unlink an object from a simple Perl variable.
7919use PACKAGE [SYMBOL1, ...] Compile-time `require' with consequent `import'.
7920... xor ... Low-precedence synonym for exclusive or.
d7584f0f 7921prototype \\&SUB Returns prototype of the function given a reference.
f83d2997
KH
7922=head1 Top-level heading.
7923=head2 Second-level heading.
7924=head3 Third-level heading (is there such?).
7925=over [ NUMBER ] Start list.
7926=item [ TITLE ] Start new item in the list.
7927=back End list.
7928=cut Switch from POD to Perl.
7929=pod Switch from Perl to POD.
7930")
7931
21df56d5 7932(defun cperl-switch-to-doc-buffer (&optional interactive)
f83d2997 7933 "Go to the perl documentation buffer and insert the documentation."
21df56d5 7934 (interactive "p")
f83d2997 7935 (let ((buf (get-buffer-create cperl-doc-buffer)))
21df56d5 7936 (if interactive
f83d2997
KH
7937 (switch-to-buffer-other-window buf)
7938 (set-buffer buf))
7939 (if (= (buffer-size) 0)
7940 (progn
7941 (insert (documentation-property 'cperl-short-docs
7942 'variable-documentation))
7943 (setq buffer-read-only t)))))
7944
6c389151 7945(defun cperl-beautify-regexp-piece (b e embed level)
f83d2997
KH
7946 ;; b is before the starting delimiter, e before the ending
7947 ;; e should be a marker, may be changed, but remains "correct".
e7f767c2 7948 ;; EMBED is nil if we process the whole REx.
4ab89e7b 7949 ;; The REx is guaranteed to have //x
6c389151
SM
7950 ;; LEVEL shows how many levels deep to go
7951 ;; position at enter and at leave is not defined
7952 (let (s c tmp (m (make-marker)) (m1 (make-marker)) c1 spaces inline code pos)
f83d2997
KH
7953 (if (not embed)
7954 (goto-char (1+ b))
7955 (goto-char b)
6c389151 7956 (cond ((looking-at "(\\?\\\\#") ; (?#) wrongly commented when //x-ing
f83d2997
KH
7957 (forward-char 2)
7958 (delete-char 1)
7959 (forward-char 1))
7960 ((looking-at "(\\?[^a-zA-Z]")
7961 (forward-char 3))
7962 ((looking-at "(\\?") ; (?i)
7963 (forward-char 2))
7964 (t
7965 (forward-char 1))))
7966 (setq c (if embed (current-indentation) (1- (current-column)))
7967 c1 (+ c (or cperl-regexp-indent-step cperl-indent-level)))
7968 (or (looking-at "[ \t]*[\n#]")
7969 (progn
7970 (insert "\n")))
7971 (goto-char e)
7972 (beginning-of-line)
7973 (if (re-search-forward "[^ \t]" e t)
83261a2f 7974 (progn ; Something before the ending delimiter
f83d2997 7975 (goto-char e)
6c389151 7976 (delete-horizontal-space)
f83d2997 7977 (insert "\n")
4ab89e7b 7978 (cperl-make-indent c)
f83d2997
KH
7979 (set-marker e (point))))
7980 (goto-char b)
7981 (end-of-line 2)
7982 (while (< (point) (marker-position e))
7983 (beginning-of-line)
7984 (setq s (point)
7985 inline t)
7986 (skip-chars-forward " \t")
7987 (delete-region s (point))
4ab89e7b 7988 (cperl-make-indent c1)
f83d2997
KH
7989 (while (and
7990 inline
5c8b7eaf 7991 (looking-at
f83d2997
KH
7992 (concat "\\([a-zA-Z0-9]+[^*+{?]\\)" ; 1 word
7993 "\\|" ; Embedded variable
7994 "\\$\\([a-zA-Z0-9_]+\\([[{]\\)?\\|[^\n \t)|]\\)" ; 2 3
7995 "\\|" ; $ ^
7996 "[$^]"
7997 "\\|" ; simple-code simple-code*?
7998 "\\(\\\\.\\|[^][()#|*+?\n]\\)\\([*+{?]\\??\\)?" ; 4 5
7999 "\\|" ; Class
8000 "\\(\\[\\)" ; 6
8001 "\\|" ; Grouping
8002 "\\((\\(\\?\\)?\\)" ; 7 8
8003 "\\|" ; |
83261a2f 8004 "\\(|\\)"))) ; 9
f83d2997
KH
8005 (goto-char (match-end 0))
8006 (setq spaces t)
8007 (cond ((match-beginning 1) ; Alphanum word + junk
8008 (forward-char -1))
8009 ((or (match-beginning 3) ; $ab[12]
8010 (and (match-beginning 5) ; X* X+ X{2,3}
8011 (eq (preceding-char) ?\{)))
8012 (forward-char -1)
8013 (forward-sexp 1))
4ab89e7b
SM
8014 ((and ; [], already syntaxified
8015 (match-beginning 6)
8016 cperl-regexp-scan
8017 cperl-use-syntax-table-text-property)
8018 (forward-char -1)
8019 (forward-sexp 1)
8020 (or (eq (preceding-char) ?\])
8021 (error "[]-group not terminated"))
8022 (re-search-forward
8023 "\\=\\([*+?]\\|{[0-9]+\\(,[0-9]*\\)?}\\)\\??" e t))
f83d2997
KH
8024 ((match-beginning 6) ; []
8025 (setq tmp (point))
8026 (if (looking-at "\\^?\\]")
8027 (goto-char (match-end 0)))
6c389151
SM
8028 ;; XXXX POSIX classes?!
8029 (while (and (not pos)
8030 (re-search-forward "\\[:\\|\\]" e t))
8031 (if (eq (preceding-char) ?:)
8032 (or (re-search-forward ":\\]" e t)
8033 (error "[:POSIX:]-group in []-group not terminated"))
8034 (setq pos t)))
8035 (or (eq (preceding-char) ?\])
8036 (error "[]-group not terminated"))
4ab89e7b
SM
8037 (re-search-forward
8038 "\\=\\([*+?]\\|{[0-9]+\\(,[0-9]*\\)?}\\)\\??" e t))
f83d2997
KH
8039 ((match-beginning 7) ; ()
8040 (goto-char (match-beginning 0))
6c389151
SM
8041 (setq pos (current-column))
8042 (or (eq pos c1)
f83d2997 8043 (progn
6c389151 8044 (delete-horizontal-space)
f83d2997 8045 (insert "\n")
4ab89e7b 8046 (cperl-make-indent c1)))
f83d2997
KH
8047 (setq tmp (point))
8048 (forward-sexp 1)
8049 ;; (or (forward-sexp 1)
8050 ;; (progn
8051 ;; (goto-char tmp)
8052 ;; (error "()-group not terminated")))
8053 (set-marker m (1- (point)))
8054 (set-marker m1 (point))
6c389151
SM
8055 (if (= level 1)
8056 (if (progn ; indent rigidly if multiline
a1506d29 8057 ;; In fact does not make a lot of sense, since
6c389151
SM
8058 ;; the starting position can be already lost due
8059 ;; to insertion of "\n" and " "
8060 (goto-char tmp)
8061 (search-forward "\n" m1 t))
8062 (indent-rigidly (point) m1 (- c1 pos)))
8063 (setq level (1- level))
8064 (cond
8065 ((not (match-beginning 8))
8066 (cperl-beautify-regexp-piece tmp m t level))
8067 ((eq (char-after (+ 2 tmp)) ?\{) ; Code
8068 t)
8069 ((eq (char-after (+ 2 tmp)) ?\() ; Conditional
8070 (goto-char (+ 2 tmp))
8071 (forward-sexp 1)
8072 (cperl-beautify-regexp-piece (point) m t level))
8073 ((eq (char-after (+ 2 tmp)) ?<) ; Lookbehind
8074 (goto-char (+ 3 tmp))
8075 (cperl-beautify-regexp-piece (point) m t level))
8076 (t
8077 (cperl-beautify-regexp-piece tmp m t level))))
f83d2997
KH
8078 (goto-char m1)
8079 (cond ((looking-at "[*+?]\\??")
8080 (goto-char (match-end 0)))
8081 ((eq (following-char) ?\{)
8082 (forward-sexp 1)
8083 (if (eq (following-char) ?\?)
8084 (forward-char))))
8085 (skip-chars-forward " \t")
8086 (setq spaces nil)
8087 (if (looking-at "[#\n]")
8088 (progn
8089 (or (eolp) (indent-for-comment))
8090 (beginning-of-line 2))
6c389151 8091 (delete-horizontal-space)
f83d2997
KH
8092 (insert "\n"))
8093 (end-of-line)
8094 (setq inline nil))
8095 ((match-beginning 9) ; |
8096 (forward-char -1)
8097 (setq tmp (point))
8098 (beginning-of-line)
8099 (if (re-search-forward "[^ \t]" tmp t)
8100 (progn
8101 (goto-char tmp)
6c389151 8102 (delete-horizontal-space)
f83d2997
KH
8103 (insert "\n"))
8104 ;; first at line
8105 (delete-region (point) tmp))
4ab89e7b 8106 (cperl-make-indent c)
f83d2997
KH
8107 (forward-char 1)
8108 (skip-chars-forward " \t")
8109 (setq spaces nil)
8110 (if (looking-at "[#\n]")
8111 (beginning-of-line 2)
6c389151 8112 (delete-horizontal-space)
f83d2997
KH
8113 (insert "\n"))
8114 (end-of-line)
8115 (setq inline nil)))
8116 (or (looking-at "[ \t\n]")
8117 (not spaces)
8118 (insert " "))
8119 (skip-chars-forward " \t"))
83261a2f
SM
8120 (or (looking-at "[#\n]")
8121 (error "Unknown code `%s' in a regexp"
8122 (buffer-substring (point) (1+ (point)))))
8123 (and inline (end-of-line 2)))
f83d2997
KH
8124 ;; Special-case the last line of group
8125 (if (and (>= (point) (marker-position e))
8126 (/= (current-indentation) c))
8127 (progn
83261a2f 8128 (beginning-of-line)
4ab89e7b 8129 (cperl-make-indent c)))))
f83d2997
KH
8130
8131(defun cperl-make-regexp-x ()
db133cb6 8132 ;; Returns position of the start
6c389151 8133 ;; XXX this is called too often! Need to cache the result!
f83d2997
KH
8134 (save-excursion
8135 (or cperl-use-syntax-table-text-property
5bd52f0e 8136 (error "I need to have a regexp marked!"))
f83d2997 8137 ;; Find the start
db133cb6
RS
8138 (if (looking-at "\\s|")
8139 nil ; good already
5bd52f0e 8140 (if (looking-at "\\([smy]\\|qr\\)\\s|")
db133cb6 8141 (forward-char 1)
83261a2f 8142 (re-search-backward "\\s|"))) ; Assume it is scanned already.
f83d2997
KH
8143 ;;(forward-char 1)
8144 (let ((b (point)) (e (make-marker)) have-x delim (c (current-column))
8145 (sub-p (eq (preceding-char) ?s)) s)
8146 (forward-sexp 1)
8147 (set-marker e (1- (point)))
8148 (setq delim (preceding-char))
8149 (if (and sub-p (eq delim (char-after (- (point) 2))))
8150 (error "Possible s/blah// - do not know how to deal with"))
8151 (if sub-p (forward-sexp 1))
5c8b7eaf 8152 (if (looking-at "\\sw*x")
f83d2997
KH
8153 (setq have-x t)
8154 (insert "x"))
8155 ;; Protect fragile " ", "#"
8156 (if have-x nil
8157 (goto-char (1+ b))
8158 (while (re-search-forward "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*[ \t\n#]" e t) ; Need to include (?#) too?
8159 (forward-char -1)
8160 (insert "\\")
8161 (forward-char 1)))
8162 b)))
8163
6c389151 8164(defun cperl-beautify-regexp (&optional deep)
f94a632a 8165 "Do it. (Experimental, may change semantics, recheck the result.)
f83d2997 8166We suppose that the regexp is scanned already."
6c389151 8167 (interactive "P")
0c602a0f 8168 (setq deep (if deep (prefix-numeric-value deep) -1))
6c389151
SM
8169 (save-excursion
8170 (goto-char (cperl-make-regexp-x))
8171 (let ((b (point)) (e (make-marker)))
8172 (forward-sexp 1)
8173 (set-marker e (1- (point)))
8174 (cperl-beautify-regexp-piece b e nil deep))))
f83d2997 8175
db133cb6
RS
8176(defun cperl-regext-to-level-start ()
8177 "Goto start of an enclosing group in regexp.
f83d2997
KH
8178We suppose that the regexp is scanned already."
8179 (interactive)
db133cb6 8180 (let ((limit (cperl-make-regexp-x)) done)
f83d2997
KH
8181 (while (not done)
8182 (or (eq (following-char) ?\()
db133cb6 8183 (search-backward "(" (1+ limit) t)
f83d2997
KH
8184 (error "Cannot find `(' which starts a group"))
8185 (setq done
8186 (save-excursion
8187 (skip-chars-backward "\\")
8188 (looking-at "\\(\\\\\\\\\\)*(")))
db133cb6
RS
8189 (or done (forward-char -1)))))
8190
8191(defun cperl-contract-level ()
5bd52f0e 8192 "Find an enclosing group in regexp and contract it.
db133cb6
RS
8193\(Experimental, may change semantics, recheck the result.)
8194We suppose that the regexp is scanned already."
8195 (interactive)
6c389151 8196 ;; (save-excursion ; Can't, breaks `cperl-contract-levels'
83261a2f 8197 (cperl-regext-to-level-start)
4ab89e7b 8198 (let ((b (point)) (e (make-marker)) c)
83261a2f
SM
8199 (forward-sexp 1)
8200 (set-marker e (1- (point)))
8201 (goto-char b)
8202 (while (re-search-forward "\\(#\\)\\|\n" e 'to-end)
8203 (cond
8204 ((match-beginning 1) ; #-comment
8205 (or c (setq c (current-indentation)))
8206 (beginning-of-line 2) ; Skip
4ab89e7b 8207 (cperl-make-indent c))
83261a2f
SM
8208 (t
8209 (delete-char -1)
8210 (just-one-space))))))
db133cb6
RS
8211
8212(defun cperl-contract-levels ()
5bd52f0e 8213 "Find an enclosing group in regexp and contract all the kids.
db133cb6
RS
8214\(Experimental, may change semantics, recheck the result.)
8215We suppose that the regexp is scanned already."
8216 (interactive)
6c389151
SM
8217 (save-excursion
8218 (condition-case nil
8219 (cperl-regext-to-level-start)
8220 (error ; We are outside outermost group
5efe6a56
SM
8221 (goto-char (cperl-make-regexp-x))))
8222 (let ((b (point)) (e (make-marker)) s c)
8223 (forward-sexp 1)
8224 (set-marker e (1- (point)))
8225 (goto-char (1+ b))
8226 (while (re-search-forward "\\(\\\\\\\\\\)\\|(" e t)
a1506d29 8227 (cond
6c389151
SM
8228 ((match-beginning 1) ; Skip
8229 nil)
8230 (t ; Group
8231 (cperl-contract-level)))))))
f83d2997 8232
6c389151 8233(defun cperl-beautify-level (&optional deep)
f83d2997
KH
8234 "Find an enclosing group in regexp and beautify it.
8235\(Experimental, may change semantics, recheck the result.)
8236We suppose that the regexp is scanned already."
6c389151 8237 (interactive "P")
0c602a0f 8238 (setq deep (if deep (prefix-numeric-value deep) -1))
6c389151
SM
8239 (save-excursion
8240 (cperl-regext-to-level-start)
8241 (let ((b (point)) (e (make-marker)))
8242 (forward-sexp 1)
8243 (set-marker e (1- (point)))
8244 (cperl-beautify-regexp-piece b e nil deep))))
db133cb6 8245
4ab89e7b
SM
8246(defun cperl-invert-if-unless-modifiers ()
8247 "Change `B if A;' into `if (A) {B}' etc if possible.
8248\(Unfinished.)"
cb5bf6ba 8249 (interactive) ;
4ab89e7b
SM
8250 (let (A B pre-B post-B pre-if post-if pre-A post-A if-string
8251 (w-rex "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>"))
8252 (and (= (char-syntax (preceding-char)) ?w)
8253 (forward-sexp -1))
8254 (setq pre-if (point))
8255 (cperl-backward-to-start-of-expr)
8256 (setq pre-B (point))
8257 (forward-sexp 1) ; otherwise forward-to-end-of-expr is NOP
8258 (cperl-forward-to-end-of-expr)
8259 (setq post-A (point))
8260 (goto-char pre-if)
8261 (or (looking-at w-rex)
8262 ;; Find the position
8263 (progn (goto-char post-A)
8264 (while (and
8265 (not (looking-at w-rex))
8266 (> (point) pre-B))
8267 (forward-sexp -1))
8268 (setq pre-if (point))))
8269 (or (looking-at w-rex)
8270 (error "Can't find `if', `unless', `while', `until', `for' or `foreach'"))
8271 ;; 1 B 2 ... 3 B-com ... 4 if 5 ... if-com 6 ... 7 A 8
8272 (setq if-string (buffer-substring (match-beginning 0) (match-end 0)))
8273 ;; First, simple part: find code boundaries
8274 (forward-sexp 1)
8275 (setq post-if (point))
8276 (forward-sexp -2)
8277 (forward-sexp 1)
8278 (setq post-B (point))
8279 (cperl-backward-to-start-of-expr)
8280 (setq pre-B (point))
8281 (setq B (buffer-substring pre-B post-B))
8282 (goto-char pre-if)
8283 (forward-sexp 2)
8284 (forward-sexp -1)
8285 ;; May be after $, @, $# etc of a variable
8286 (skip-chars-backward "$@%#")
8287 (setq pre-A (point))
8288 (cperl-forward-to-end-of-expr)
8289 (setq post-A (point))
8290 (setq A (buffer-substring pre-A post-A))
8291 ;; Now modify (from end, to not break the stuff)
8292 (skip-chars-forward " \t;")
8293 (delete-region pre-A (point)) ; we move to pre-A
8294 (insert "\n" B ";\n}")
8295 (and (looking-at "[ \t]*#") (cperl-indent-for-comment))
8296 (delete-region pre-if post-if)
8297 (delete-region pre-B post-B)
8298 (goto-char pre-B)
8299 (insert if-string " (" A ") {")
8300 (setq post-B (point))
8301 (if (looking-at "[ \t]+$")
8302 (delete-horizontal-space)
8303 (if (looking-at "[ \t]*#")
8304 (cperl-indent-for-comment)
8305 (just-one-space)))
8306 (forward-line 1)
8307 (if (looking-at "[ \t]*$")
8308 (progn ; delete line
8309 (delete-horizontal-space)
8310 (delete-region (point) (1+ (point)))))
8311 (cperl-indent-line)
8312 (goto-char (1- post-B))
8313 (forward-sexp 1)
8314 (cperl-indent-line)
8315 (goto-char pre-B)))
8316
db133cb6 8317(defun cperl-invert-if-unless ()
4ab89e7b
SM
8318 "Change `if (A) {B}' into `B if A;' etc (or visa versa) if possible.
8319If the cursor is not on the leading keyword of the BLOCK flavor of
8320construct, will assume it is the STATEMENT flavor, so will try to find
8321the appropriate statement modifier."
db133cb6 8322 (interactive)
4ab89e7b
SM
8323 (and (= (char-syntax (preceding-char)) ?w)
8324 (forward-sexp -1))
6c389151 8325 (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>")
4ab89e7b
SM
8326 (let ((pre-if (point))
8327 pre-A post-A pre-B post-B A B state p end-B-code is-block B-comment
8328 (if-string (buffer-substring (match-beginning 0) (match-end 0))))
db133cb6 8329 (forward-sexp 2)
4ab89e7b 8330 (setq post-A (point))
db133cb6 8331 (forward-sexp -1)
4ab89e7b
SM
8332 (setq pre-A (point))
8333 (setq is-block (and (eq (following-char) ?\( )
8334 (save-excursion
8335 (condition-case nil
8336 (progn
8337 (forward-sexp 2)
8338 (forward-sexp -1)
8339 (eq (following-char) ?\{ ))
8340 (error nil)))))
8341 (if is-block
db133cb6 8342 (progn
4ab89e7b 8343 (goto-char post-A)
db133cb6 8344 (forward-sexp 1)
4ab89e7b 8345 (setq post-B (point))
db133cb6 8346 (forward-sexp -1)
4ab89e7b 8347 (setq pre-B (point))
db133cb6
RS
8348 (if (and (eq (following-char) ?\{ )
8349 (progn
4ab89e7b 8350 (cperl-backward-to-noncomment post-A)
db133cb6
RS
8351 (eq (preceding-char) ?\) )))
8352 (if (condition-case nil
8353 (progn
4ab89e7b 8354 (goto-char post-B)
db133cb6
RS
8355 (forward-sexp 1)
8356 (forward-sexp -1)
8357 (looking-at "\\<els\\(e\\|if\\)\\>"))
8358 (error nil))
8359 (error
4ab89e7b
SM
8360 "`%s' (EXPR) {BLOCK} with `else'/`elsif'" if-string)
8361 (goto-char (1- post-B))
8362 (cperl-backward-to-noncomment pre-B)
db133cb6
RS
8363 (if (eq (preceding-char) ?\;)
8364 (forward-char -1))
4ab89e7b
SM
8365 (setq end-B-code (point))
8366 (goto-char pre-B)
8367 (while (re-search-forward "\\<\\(for\\|foreach\\|if\\|unless\\|while\\|until\\)\\>\\|;" end-B-code t)
db133cb6 8368 (setq p (match-beginning 0)
4ab89e7b
SM
8369 A (buffer-substring p (match-end 0))
8370 state (parse-partial-sexp pre-B p))
5c8b7eaf 8371 (or (nth 3 state)
db133cb6
RS
8372 (nth 4 state)
8373 (nth 5 state)
4ab89e7b 8374 (error "`%s' inside `%s' BLOCK" A if-string))
db133cb6
RS
8375 (goto-char (match-end 0)))
8376 ;; Finally got it
4ab89e7b 8377 (goto-char (1+ pre-B))
db133cb6 8378 (skip-chars-forward " \t\n")
4ab89e7b
SM
8379 (setq B (buffer-substring (point) end-B-code))
8380 (goto-char end-B-code)
db133cb6
RS
8381 (or (looking-at ";?[ \t\n]*}")
8382 (progn
8383 (skip-chars-forward "; \t\n")
4ab89e7b
SM
8384 (setq B-comment
8385 (buffer-substring (point) (1- post-B)))))
8386 (and (equal B "")
8387 (setq B "1"))
8388 (goto-char (1- post-A))
8389 (cperl-backward-to-noncomment pre-A)
db133cb6 8390 (or (looking-at "[ \t\n]*)")
4ab89e7b 8391 (goto-char (1- post-A)))
db133cb6 8392 (setq p (point))
4ab89e7b 8393 (goto-char (1+ pre-A))
db133cb6 8394 (skip-chars-forward " \t\n")
4ab89e7b
SM
8395 (setq A (buffer-substring (point) p))
8396 (delete-region pre-B post-B)
8397 (delete-region pre-A post-A)
8398 (goto-char pre-if)
8399 (insert B " ")
8400 (and B-comment (insert B-comment " "))
db133cb6
RS
8401 (just-one-space)
8402 (forward-word 1)
4ab89e7b
SM
8403 (setq pre-A (point))
8404 (insert " " A ";")
6c389151 8405 (delete-horizontal-space)
4ab89e7b
SM
8406 (setq post-B (point))
8407 (if (looking-at "#")
8408 (indent-for-comment))
8409 (goto-char post-B)
db133cb6
RS
8410 (forward-char -1)
8411 (delete-horizontal-space)
4ab89e7b 8412 (goto-char pre-A)
db133cb6 8413 (just-one-space)
4ab89e7b
SM
8414 (goto-char pre-if)
8415 (setq pre-A (set-marker (make-marker) pre-A))
8416 (while (<= (point) (marker-position pre-A))
8417 (cperl-indent-line)
8418 (forward-line 1))
8419 (goto-char (marker-position pre-A))
8420 (if B-comment
8421 (progn
8422 (forward-line -1)
8423 (indent-for-comment)
8424 (goto-char (marker-position pre-A)))))
8425 (error "`%s' (EXPR) not with an {BLOCK}" if-string)))
8426 ;; (error "`%s' not with an (EXPR)" if-string)
8427 (forward-sexp -1)
8428 (cperl-invert-if-unless-modifiers)))
8429 ;;(error "Not at `if', `unless', `while', `until', `for' or `foreach'")
8430 (cperl-invert-if-unless-modifiers)))
db133cb6 8431
5bd52f0e 8432;;; By Anthony Foiani <afoiani@uswest.com>
b7ec9e59
RS
8433;;; Getting help on modules in C-h f ?
8434;;; This is a modified version of `man'.
8435;;; Need to teach it how to lookup functions
4ab89e7b 8436;;;###autoload
b7ec9e59
RS
8437(defun cperl-perldoc (word)
8438 "Run `perldoc' on WORD."
8439 (interactive
8440 (list (let* ((default-entry (cperl-word-at-point))
8441 (input (read-string
8442 (format "perldoc entry%s: "
8443 (if (string= default-entry "")
8444 ""
8445 (format " (default %s)" default-entry))))))
8446 (if (string= input "")
8447 (if (string= default-entry "")
8448 (error "No perldoc args given")
8449 default-entry)
8450 input))))
a8e1e57f 8451 (require 'man)
f739b53b
SM
8452 (let* ((case-fold-search nil)
8453 (is-func (and
b7ec9e59
RS
8454 (string-match "^[a-z]+$" word)
8455 (string-match (concat "^" word "\\>")
8456 (documentation-property
8457 'cperl-short-docs
8458 'variable-documentation))))
8459 (manual-program (if is-func "perldoc -f" "perldoc")))
f739b53b 8460 (cond
6546555e 8461 ((featurep 'xemacs)
f739b53b
SM
8462 (let ((Manual-program "perldoc")
8463 (Manual-switches (if is-func (list "-f"))))
8464 (manual-entry word)))
8465 (t
8466 (Man-getpage-in-background word)))))
b7ec9e59 8467
4ab89e7b 8468;;;###autoload
b7ec9e59
RS
8469(defun cperl-perldoc-at-point ()
8470 "Run a `perldoc' on the word around point."
8471 (interactive)
8472 (cperl-perldoc (cperl-word-at-point)))
8473
8474(defcustom pod2man-program "pod2man"
8475 "*File name for `pod2man'."
8476 :type 'file
8477 :group 'cperl)
8478
5bd52f0e 8479;;; By Nick Roberts <Nick.Roberts@src.bae.co.uk> (with changes)
b7ec9e59
RS
8480(defun cperl-pod-to-manpage ()
8481 "Create a virtual manpage in Emacs from the Perl Online Documentation."
8482 (interactive)
8483 (require 'man)
8484 (let* ((pod2man-args (concat buffer-file-name " | nroff -man "))
8485 (bufname (concat "Man " buffer-file-name))
8486 (buffer (generate-new-buffer bufname)))
8487 (save-excursion
8488 (set-buffer buffer)
8489 (let ((process-environment (copy-sequence process-environment)))
8490 ;; Prevent any attempt to use display terminal fanciness.
8491 (setenv "TERM" "dumb")
8492 (set-process-sentinel
8493 (start-process pod2man-program buffer "sh" "-c"
8494 (format (cperl-pod2man-build-command) pod2man-args))
8495 'Man-bgproc-sentinel)))))
8496
f739b53b
SM
8497;;; Updated version by him too
8498(defun cperl-build-manpage ()
8499 "Create a virtual manpage in Emacs from the POD in the file."
8500 (interactive)
8501 (require 'man)
8502 (cond
6546555e 8503 ((featurep 'xemacs)
f739b53b
SM
8504 (let ((Manual-program "perldoc"))
8505 (manual-entry buffer-file-name)))
8506 (t
8507 (let* ((manual-program "perldoc"))
8508 (Man-getpage-in-background buffer-file-name)))))
8509
b7ec9e59
RS
8510(defun cperl-pod2man-build-command ()
8511 "Builds the entire background manpage and cleaning command."
8512 (let ((command (concat pod2man-program " %s 2>/dev/null"))
4ab89e7b 8513 (flist (and (boundp 'Man-filter-list) Man-filter-list)))
b7ec9e59
RS
8514 (while (and flist (car flist))
8515 (let ((pcom (car (car flist)))
8516 (pargs (cdr (car flist))))
8517 (setq command
8518 (concat command " | " pcom " "
8519 (mapconcat '(lambda (phrase)
8520 (if (not (stringp phrase))
8521 (error "Malformed Man-filter-list"))
8522 phrase)
8523 pargs " ")))
8524 (setq flist (cdr flist))))
8525 command))
db133cb6 8526
4ab89e7b
SM
8527
8528(defun cperl-next-interpolated-REx-1 ()
8529 "Move point to next REx which has interpolated parts without //o.
8530Skips RExes consisting of one interpolated variable.
8531
8532Note that skipped RExen are not performance hits."
8533 (interactive "")
8534 (cperl-next-interpolated-REx 1))
8535
8536(defun cperl-next-interpolated-REx-0 ()
8537 "Move point to next REx which has interpolated parts without //o."
8538 (interactive "")
8539 (cperl-next-interpolated-REx 0))
8540
8541(defun cperl-next-interpolated-REx (&optional skip beg limit)
8542 "Move point to next REx which has interpolated parts.
8543SKIP is a list of possible types to skip, BEG and LIMIT are the starting
8544point and the limit of search (default to point and end of buffer).
8545
8546SKIP may be a number, then it behaves as list of numbers up to SKIP; this
8547semantic may be used as a numeric argument.
8548
8549Types are 0 for / $rex /o (interpolated once), 1 for /$rex/ (if $rex is
8550a result of qr//, this is not a performance hit), t for the rest."
8551 (interactive "P")
8552 (if (numberp skip) (setq skip (list 0 skip)))
8553 (or beg (setq beg (point)))
8554 (or limit (setq limit (point-max))) ; needed for n-s-p-c
8555 (let (pp)
8556 (and (eq (get-text-property beg 'syntax-type) 'string)
8557 (setq beg (next-single-property-change beg 'syntax-type nil limit)))
8558 (cperl-map-pods-heres
8559 (function (lambda (s e p)
8560 (if (memq (get-text-property s 'REx-interpolated) skip)
8561 t
8562 (setq pp s)
8563 nil))) ; nil stops
8564 'REx-interpolated beg limit)
8565 (if pp (goto-char pp)
8566 (message "No more interpolated REx"))))
8567
8568;;; Initial version contributed by Trey Belew
8569(defun cperl-here-doc-spell (&optional beg end)
8570 "Spell-check HERE-documents in the Perl buffer.
8571If a region is highlighted, restricts to the region."
8572 (interactive "")
8573 (cperl-pod-spell t beg end))
8574
8575(defun cperl-pod-spell (&optional do-heres beg end)
8576 "Spell-check POD documentation.
8577If invoked with prefix argument, will do HERE-DOCs instead.
8578If a region is highlighted, restricts to the region."
8579 (interactive "P")
8580 (save-excursion
8581 (let (beg end)
8582 (if (cperl-mark-active)
8583 (setq beg (min (mark) (point))
8584 end (max (mark) (point)))
8585 (setq beg (point-min)
8586 end (point-max)))
8587 (cperl-map-pods-heres (function
8588 (lambda (s e p)
8589 (if do-heres
8590 (setq e (save-excursion
8591 (goto-char e)
8592 (forward-line -1)
8593 (point))))
8594 (ispell-region s e)
8595 t))
8596 (if do-heres 'here-doc-group 'in-pod)
8597 beg end))))
8598
8599(defun cperl-map-pods-heres (func &optional prop s end)
8600 "Executes a function over regions of pods or here-documents.
8601PROP is the text-property to search for; default to `in-pod'. Stop when
8602function returns nil."
8603 (let (pos posend has-prop (cont t))
8604 (or prop (setq prop 'in-pod))
8605 (or s (setq s (point-min)))
8606 (or end (setq end (point-max)))
8607 (cperl-update-syntaxification end end)
8608 (save-excursion
8609 (goto-char (setq pos s))
8610 (while (and cont (< pos end))
8611 (setq has-prop (get-text-property pos prop))
8612 (setq posend (next-single-property-change pos prop nil end))
8613 (and has-prop
8614 (setq cont (funcall func pos posend prop)))
8615 (setq pos posend)))))
8616
8617;;; Based on code by Masatake YAMATO:
8618(defun cperl-get-here-doc-region (&optional pos pod)
8619 "Return HERE document region around the point.
8620Return nil if the point is not in a HERE document region. If POD is non-nil,
8621will return a POD section if point is in a POD section."
8622 (or pos (setq pos (point)))
8623 (cperl-update-syntaxification pos pos)
8624 (if (or (eq 'here-doc (get-text-property pos 'syntax-type))
8625 (and pod
8626 (eq 'pod (get-text-property pos 'syntax-type))))
8627 (let ((b (cperl-beginning-of-property pos 'syntax-type))
8628 (e (next-single-property-change pos 'syntax-type)))
8629 (cons b (or e (point-max))))))
8630
8631(defun cperl-narrow-to-here-doc (&optional pos)
8632 "Narrows editing region to the HERE-DOC at POS.
8633POS defaults to the point."
8634 (interactive "d")
8635 (or pos (setq pos (point)))
8636 (let ((p (cperl-get-here-doc-region pos)))
8637 (or p (error "Not inside a HERE document"))
8638 (narrow-to-region (car p) (cdr p))
8639 (message
8640 "When you are finished with narrow editing, type C-x n w")))
8641
8642(defun cperl-select-this-pod-or-here-doc (&optional pos)
8643 "Select the HERE-DOC (or POD section) at POS.
8644POS defaults to the point."
8645 (interactive "d")
8646 (let ((p (cperl-get-here-doc-region pos t)))
8647 (if p
8648 (progn
8649 (goto-char (car p))
8650 (push-mark (cdr p) nil t)) ; Message, activate in transient-mode
8651 (message "I do not think POS is in POD or a HERE-doc..."))))
8652
8653(defun cperl-facemenu-add-face-function (face end)
8654 "A callback to process user-initiated font-change requests.
8655Translates `bold', `italic', and `bold-italic' requests to insertion of
8656corresponding POD directives, and `underline' to C<> POD directive.
8657
8658Such requests are usually bound to M-o LETTER."
8659 (or (get-text-property (point) 'in-pod)
8660 (error "Faces can only be set within POD"))
8661 (setq facemenu-end-add-face (if (eq face 'bold-italic) ">>" ">"))
8662 (cdr (or (assq face '((bold . "B<")
8663 (italic . "I<")
8664 (bold-italic . "B<I<")
8665 (underline . "C<")))
8666 (error "Face %s not configured for cperl-mode"
8667 face))))
8668\f
8669(defun cperl-time-fontification (&optional l step lim)
8670 "Times how long it takes to do incremental fontification in a region.
8671L is the line to start at, STEP is the number of lines to skip when
8672doing next incremental fontification, LIM is the maximal number of
8673incremental fontification to perform. Messages are accumulated in
8674*Messages* buffer.
8675
8676May be used for pinpointing which construct slows down buffer fontification:
8677start with default arguments, then refine the slowdown regions."
8678 (interactive "nLine to start at: \nnStep to do incremental fontification: ")
8679 (or l (setq l 1))
8680 (or step (setq step 500))
8681 (or lim (setq lim 40))
8682 (let* ((timems (function (lambda ()
8683 (let ((tt (current-time)))
8684 (+ (* 1000 (nth 1 tt)) (/ (nth 2 tt) 1000))))))
8685 (tt (funcall timems)) (c 0) delta tot)
8686 (goto-line l)
8687 (cperl-mode)
8688 (setq tot (- (- tt (setq tt (funcall timems)))))
8689 (message "cperl-mode at %s: %s" l tot)
8690 (while (and (< c lim) (not (eobp)))
8691 (forward-line step)
8692 (setq l (+ l step))
8693 (setq c (1+ c))
8694 (cperl-update-syntaxification (point) (point))
8695 (setq delta (- (- tt (setq tt (funcall timems)))) tot (+ tot delta))
8696 (message "to %s:%6s,%7s" l delta tot))
8697 tot))
8698
6546555e
DN
8699(defvar font-lock-cache-position)
8700
4ab89e7b
SM
8701(defun cperl-emulate-lazy-lock (&optional window-size)
8702 "Emulate `lazy-lock' without `condition-case', so `debug-on-error' works.
8703Start fontifying the buffer from the start (or end) using the given
8704WINDOW-SIZE (units is lines). Negative WINDOW-SIZE starts at end, and
8705goes backwards; default is -50. This function is not CPerl-specific; it
8706may be used to debug problems with delayed incremental fontification."
8707 (interactive
8708 "nSize of window for incremental fontification, negative goes backwards: ")
8709 (or window-size (setq window-size -50))
8710 (let ((pos (if (> window-size 0)
8711 (point-min)
8712 (point-max)))
8713 p)
8714 (goto-char pos)
8715 (normal-mode)
8716 ;; Why needed??? With older font-locks???
8717 (set (make-local-variable 'font-lock-cache-position) (make-marker))
8718 (while (if (> window-size 0)
8719 (< pos (point-max))
8720 (> pos (point-min)))
8721 (setq p (progn
8722 (forward-line window-size)
8723 (point)))
8724 (font-lock-fontify-region (min p pos) (max p pos))
8725 (setq pos p))))
8726
8727\f
db133cb6 8728(defun cperl-lazy-install ()) ; Avoid a warning
f739b53b 8729(defun cperl-lazy-unstall ()) ; Avoid a warning
f83d2997
KH
8730
8731(if (fboundp 'run-with-idle-timer)
8732 (progn
8733 (defvar cperl-help-shown nil
8734 "Non-nil means that the help was already shown now.")
8735
8736 (defvar cperl-lazy-installed nil
8737 "Non-nil means that the lazy-help handlers are installed now.")
8738
8739 (defun cperl-lazy-install ()
f739b53b
SM
8740 "Switches on Auto-Help on Perl constructs (put in the message area).
8741Delay of auto-help controlled by `cperl-lazy-help-time'."
f83d2997 8742 (interactive)
4ab89e7b 8743 (make-local-variable 'cperl-help-shown)
f83d2997
KH
8744 (if (and (cperl-val 'cperl-lazy-help-time)
8745 (not cperl-lazy-installed))
8746 (progn
8747 (add-hook 'post-command-hook 'cperl-lazy-hook)
5c8b7eaf
SS
8748 (run-with-idle-timer
8749 (cperl-val 'cperl-lazy-help-time 1000000 5)
8750 t
f83d2997
KH
8751 'cperl-get-help-defer)
8752 (setq cperl-lazy-installed t))))
8753
8754 (defun cperl-lazy-unstall ()
f739b53b
SM
8755 "Switches off Auto-Help on Perl constructs (put in the message area).
8756Delay of auto-help controlled by `cperl-lazy-help-time'."
f83d2997
KH
8757 (interactive)
8758 (remove-hook 'post-command-hook 'cperl-lazy-hook)
8759 (cancel-function-timers 'cperl-get-help-defer)
8760 (setq cperl-lazy-installed nil))
8761
8762 (defun cperl-lazy-hook ()
8763 (setq cperl-help-shown nil))
8764
8765 (defun cperl-get-help-defer ()
83261a2f 8766 (if (not (memq major-mode '(perl-mode cperl-mode))) nil
f83d2997
KH
8767 (let ((cperl-message-on-help-error nil) (cperl-help-from-timer t))
8768 (cperl-get-help)
8769 (setq cperl-help-shown t))))
8770 (cperl-lazy-install)))
8771
db133cb6
RS
8772
8773;;; Plug for wrong font-lock:
8774
8775(defun cperl-font-lock-unfontify-region-function (beg end)
4ab89e7b
SM
8776 (let* ((modified (buffer-modified-p)) (buffer-undo-list t)
8777 (inhibit-read-only t) (inhibit-point-motion-hooks t)
8778 before-change-functions after-change-functions
8779 deactivate-mark buffer-file-name buffer-file-truename)
8780 (remove-text-properties beg end '(face nil))
8781 (if (and (not modified) (buffer-modified-p))
8782 (set-buffer-modified-p nil))))
8783
8784(defun cperl-font-lock-fontify-region-function (beg end loudly)
8785 "Extends the region to safe positions, then calls the default function.
8786Newer `font-lock's can do it themselves.
8787We unwind only as far as needed for fontification. Syntaxification may
8788do extra unwind via `cperl-unwind-to-safe'."
8789 (save-excursion
8790 (goto-char beg)
8791 (while (and beg
8792 (progn
8793 (beginning-of-line)
8794 (eq (get-text-property (setq beg (point)) 'syntax-type)
8795 'multiline)))
8796 (if (setq beg (cperl-beginning-of-property beg 'syntax-type))
8797 (goto-char beg)))
8798 (setq beg (point))
8799 (goto-char end)
8800 (while (and end
8801 (progn
8802 (or (bolp) (condition-case nil
8803 (forward-line 1)
8804 (error nil)))
8805 (eq (get-text-property (setq end (point)) 'syntax-type)
8806 'multiline)))
8807 (setq end (next-single-property-change end 'syntax-type nil (point-max)))
8808 (goto-char end))
8809 (setq end (point)))
8810 (font-lock-default-fontify-region beg end loudly))
db133cb6
RS
8811
8812(defvar cperl-d-l nil)
8813(defun cperl-fontify-syntaxically (end)
5bd52f0e 8814 ;; Some vars for debugging only
6c389151 8815 ;; (message "Syntaxifying...")
4ab89e7b 8816 (let ((dbg (point)) (iend end) (idone cperl-syntax-done-to)
83261a2f 8817 (istate (car cperl-syntax-state))
4ab89e7b
SM
8818 start from-start edebug-backtrace-buffer)
8819 (if (eq cperl-syntaxify-by-font-lock 'backtrace)
8820 (progn
8821 (require 'edebug)
8822 (let ((f 'edebug-backtrace))
8823 (funcall f)))) ; Avoid compile-time warning
db133cb6 8824 (or cperl-syntax-done-to
4ab89e7b
SM
8825 (setq cperl-syntax-done-to (point-min)
8826 from-start t))
8827 (setq start (if (and cperl-hook-after-change
8828 (not from-start))
8829 cperl-syntax-done-to ; Fontify without change; ignore start
8830 ;; Need to forget what is after `start'
8831 (min cperl-syntax-done-to (point))))
8832 (goto-char start)
8833 (beginning-of-line)
8834 (setq start (point))
8835 (and cperl-syntaxify-unwind
8836 (setq end (cperl-unwind-to-safe t end)
8837 start (point)))
db133cb6
RS
8838 (and (> end start)
8839 (setq cperl-syntax-done-to start) ; In case what follows fails
8840 (cperl-find-pods-heres start end t nil t))
4ab89e7b
SM
8841 (if (memq cperl-syntaxify-by-font-lock '(backtrace message))
8842 (message "Syxify req=%s..%s actual=%s..%s done-to: %s=>%s statepos: %s=>%s"
8843 dbg iend start end idone cperl-syntax-done-to
5c8b7eaf 8844 istate (car cperl-syntax-state))) ; For debugging
83261a2f 8845 nil)) ; Do not iterate
db133cb6 8846
5bd52f0e 8847(defun cperl-fontify-update (end)
4ab89e7b
SM
8848 (let ((pos (point-min)) prop posend)
8849 (setq end (point-max))
5bd52f0e 8850 (while (< pos end)
4ab89e7b
SM
8851 (setq prop (get-text-property pos 'cperl-postpone)
8852 posend (next-single-property-change pos 'cperl-postpone nil end))
5bd52f0e
RS
8853 (and prop (put-text-property pos posend (car prop) (cdr prop)))
8854 (setq pos posend)))
83261a2f 8855 nil) ; Do not iterate
5bd52f0e 8856
4ab89e7b
SM
8857(defun cperl-fontify-update-bad (end)
8858 ;; Since fontification happens with different region than syntaxification,
8859 ;; do to the end of buffer, not to END;;; likewise, start earlier if needed
8860 (let* ((pos (point)) (prop (get-text-property pos 'cperl-postpone)) posend)
8861 (if prop
8862 (setq pos (or (cperl-beginning-of-property
8863 (cperl-1+ pos) 'cperl-postpone)
8864 (point-min))))
8865 (while (< pos end)
8866 (setq posend (next-single-property-change pos 'cperl-postpone))
8867 (and prop (put-text-property pos posend (car prop) (cdr prop)))
8868 (setq pos posend)
8869 (setq prop (get-text-property pos 'cperl-postpone))))
8870 nil) ; Do not iterate
8871
8872;; Called when any modification is made to buffer text.
8873(defun cperl-after-change-function (beg end old-len)
8874 ;; We should have been informed about changes by `font-lock'. Since it
8875 ;; does not inform as which calls are defered, do it ourselves
8876 (if cperl-syntax-done-to
8877 (setq cperl-syntax-done-to (min cperl-syntax-done-to beg))))
8878
5bd52f0e
RS
8879(defun cperl-update-syntaxification (from to)
8880 (if (and cperl-use-syntax-table-text-property
8881 cperl-syntaxify-by-font-lock
8882 (or (null cperl-syntax-done-to)
8883 (< cperl-syntax-done-to to)))
8884 (progn
8885 (save-excursion
8886 (goto-char from)
8887 (cperl-fontify-syntaxically to)))))
8888
5c8b7eaf 8889(defvar cperl-version
82d9a08d 8890 (let ((v "Revision: 5.23"))
5bd52f0e
RS
8891 (string-match ":\\s *\\([0-9.]+\\)" v)
8892 (substring v (match-beginning 1) (match-end 1)))
8893 "Version of IZ-supported CPerl package this file is based on.")
8894
f83d2997
KH
8895(provide 'cperl-mode)
8896
cbee283d 8897;; arch-tag: 42e5b19b-e187-4537-929f-1a7408980ce6
f83d2997 8898;;; cperl-mode.el ends here