Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / progmodes / cperl-mode.el
CommitLineData
f83d2997
KH
1;;; cperl-mode.el --- Perl code editing commands for Emacs
2
acaf905b 3;; Copyright (C) 1985-1987, 1991-2012 Free Software Foundation, Inc.
f83d2997 4
5858f68c
GM
5;; Author: Ilya Zakharevich
6;; Bob Olson
4ab89e7b 7;; Maintainer: Ilya Zakharevich <ilyaz@cpan.org>
f83d2997
KH
8;; Keywords: languages, Perl
9
10;; This file is part of GNU Emacs.
11
b1fc2b50 12;; GNU Emacs is free software: you can redistribute it and/or modify
f83d2997 13;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
f83d2997
KH
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
b1fc2b50 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
f83d2997 24
4ab89e7b 25;;; Corrections made by Ilya Zakharevich ilyaz@cpan.org
f83d2997
KH
26
27;;; Commentary:
28
83261a2f
SM
29;; You can either fine-tune the bells and whistles of this mode or
30;; bulk enable them by putting
f83d2997
KH
31
32;; (setq cperl-hairy t)
33
83261a2f
SM
34;; in your .emacs file. (Emacs rulers do not consider it politically
35;; correct to make whistles enabled by default.)
f83d2997 36
83261a2f
SM
37;; DO NOT FORGET to read micro-docs (available from `Perl' menu) <<<<<<
38;; or as help on variables `cperl-tips', `cperl-problems', <<<<<<
15ca5699 39;; `cperl-praise', `cperl-speed'. <<<<<<
f83d2997 40
83261a2f
SM
41;; The mode information (on C-h m) provides some customization help.
42;; If you use font-lock feature of this mode, it is advisable to use
43;; either lazy-lock-mode or fast-lock-mode. I prefer lazy-lock.
f83d2997 44
83261a2f
SM
45;; Faces used now: three faces for first-class and second-class keywords
46;; and control flow words, one for each: comments, string, labels,
47;; functions definitions and packages, arrays, hashes, and variable
48;; definitions. If you do not see all these faces, your font-lock does
49;; not define them, so you need to define them manually.
f83d2997 50
83261a2f
SM
51;; This mode supports font-lock, imenu and mode-compile. In the
52;; hairy version font-lock is on, but you should activate imenu
53;; yourself (note that mode-compile is not standard yet). Well, you
54;; can use imenu from keyboard anyway (M-x imenu), but it is better
55;; to bind it like that:
f83d2997
KH
56
57;; (define-key global-map [M-S-down-mouse-3] 'imenu)
58
83261a2f
SM
59;;; Font lock bugs as of v4.32:
60
61;; The following kinds of Perl code erroneously start strings:
62;; \$` \$' \$"
63;; $opt::s $opt_s $opt{s} (s => ...) /\s+.../
64;; likewise with m, tr, y, q, qX instead of s
65
f83d2997 66;;; Code:
4ab89e7b 67\f
b5b0cb34
JB
68(defvar vc-rcs-header)
69(defvar vc-sccs-header)
70
80585273 71(eval-when-compile
4ab89e7b
SM
72 (condition-case nil
73 (require 'custom)
74 (error nil))
75 (condition-case nil
76 (require 'man)
77 (error nil))
4ab89e7b 78 (defvar cperl-can-font-lock
6546555e 79 (or (featurep 'xemacs)
4ab89e7b
SM
80 (and (boundp 'emacs-major-version)
81 (or window-system
82 (> emacs-major-version 20)))))
83 (if cperl-can-font-lock
84 (require 'font-lock))
85 (defvar msb-menu-cond)
86 (defvar gud-perldb-history)
87 (defvar font-lock-background-mode) ; not in Emacs
88 (defvar font-lock-display-type) ; ditto
89 (defvar paren-backwards-message) ; Not in newer XEmacs?
90 (or (fboundp 'defgroup)
91 (defmacro defgroup (name val doc &rest arr)
92 nil))
93 (or (fboundp 'custom-declare-variable)
94 (defmacro defcustom (name val doc &rest arr)
9edd6ee6 95 `(defvar ,name ,val ,doc)))
4ab89e7b
SM
96 (or (and (fboundp 'custom-declare-variable)
97 (string< "19.31" emacs-version)) ; Checked with 19.30: defface does not work
98 (defmacro defface (&rest arr)
99 nil))
100 ;; Avoid warning (tmp definitions)
101 (or (fboundp 'x-color-defined-p)
102 (defmacro x-color-defined-p (col)
9edd6ee6 103 (cond ((fboundp 'color-defined-p) `(color-defined-p ,col))
4ab89e7b 104 ;; XEmacs >= 19.12
9edd6ee6 105 ((fboundp 'valid-color-name-p) `(valid-color-name-p ,col))
4ab89e7b 106 ;; XEmacs 19.11
9edd6ee6 107 ((fboundp 'x-valid-color-name-p) `(x-valid-color-name-p ,col))
4ab89e7b
SM
108 (t '(error "Cannot implement color-defined-p")))))
109 (defmacro cperl-is-face (arg) ; Takes quoted arg
110 (cond ((fboundp 'find-face)
9edd6ee6 111 `(find-face ,arg))
4ab89e7b
SM
112 (;;(and (fboundp 'face-list)
113 ;; (face-list))
114 (fboundp 'face-list)
9edd6ee6
SM
115 `(member ,arg (and (fboundp 'face-list)
116 (face-list))))
4ab89e7b 117 (t
9edd6ee6 118 `(boundp ,arg))))
4ab89e7b
SM
119 (defmacro cperl-make-face (arg descr) ; Takes unquoted arg
120 (cond ((fboundp 'make-face)
9edd6ee6 121 `(make-face (quote ,arg)))
4ab89e7b 122 (t
9edd6ee6 123 `(defvar ,arg (quote ,arg) ,descr))))
4ab89e7b 124 (defmacro cperl-force-face (arg descr) ; Takes unquoted arg
9edd6ee6
SM
125 `(progn
126 (or (cperl-is-face (quote ,arg))
127 (cperl-make-face ,arg ,descr))
128 (or (boundp (quote ,arg)) ; We use unquoted variants too
129 (defvar ,arg (quote ,arg) ,descr))))
6546555e 130 (if (featurep 'xemacs)
4ab89e7b 131 (defmacro cperl-etags-snarf-tag (file line)
9edd6ee6
SM
132 `(progn
133 (beginning-of-line 2)
134 (list ,file ,line)))
4ab89e7b 135 (defmacro cperl-etags-snarf-tag (file line)
9edd6ee6 136 `(etags-snarf-tag)))
6546555e 137 (if (featurep 'xemacs)
4ab89e7b 138 (defmacro cperl-etags-goto-tag-location (elt)
9edd6ee6
SM
139 ;;(progn
140 ;; (switch-to-buffer (get-file-buffer (elt ,elt 0)))
141 ;; (set-buffer (get-file-buffer (elt ,elt 0)))
142 ;; Probably will not work due to some save-excursion???
143 ;; Or save-file-position?
144 ;; (message "Did I get to line %s?" (elt ,elt 1))
145 `(goto-line (string-to-int (elt ,elt 1))))
4ab89e7b
SM
146 ;;)
147 (defmacro cperl-etags-goto-tag-location (elt)
9edd6ee6 148 `(etags-goto-tag-location ,elt))))
5bd52f0e 149
83261a2f 150(defvar cperl-can-font-lock
6546555e 151 (or (featurep 'xemacs)
83261a2f
SM
152 (and (boundp 'emacs-major-version)
153 (or window-system
154 (> emacs-major-version 20)))))
155
5bd52f0e
RS
156(defun cperl-choose-color (&rest list)
157 (let (answer)
158 (while list
159 (or answer
160 (if (or (x-color-defined-p (car list))
161 (null (cdr list)))
162 (setq answer (car list))))
163 (setq list (cdr list)))
164 answer))
165
ccc3ce39
SE
166(defgroup cperl nil
167 "Major mode for editing Perl code."
168 :prefix "cperl-"
db133cb6
RS
169 :group 'languages
170 :version "20.3")
171
172(defgroup cperl-indentation-details nil
173 "Indentation."
174 :prefix "cperl-"
175 :group 'cperl)
176
177(defgroup cperl-affected-by-hairy nil
178 "Variables affected by `cperl-hairy'."
179 :prefix "cperl-"
180 :group 'cperl)
181
182(defgroup cperl-autoinsert-details nil
183 "Auto-insert tuneup."
184 :prefix "cperl-"
185 :group 'cperl)
186
187(defgroup cperl-faces nil
188 "Fontification colors."
8ec3bce0 189 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
db133cb6
RS
190 :prefix "cperl-"
191 :group 'cperl)
192
193(defgroup cperl-speed nil
194 "Speed vs. validity tuneup."
195 :prefix "cperl-"
196 :group 'cperl)
197
198(defgroup cperl-help-system nil
199 "Help system tuneup."
200 :prefix "cperl-"
201 :group 'cperl)
ccc3ce39 202
f83d2997 203\f
ccc3ce39 204(defcustom cperl-extra-newline-before-brace nil
f83d2997
KH
205 "*Non-nil means that if, elsif, while, until, else, for, foreach
206and do constructs look like:
207
208 if ()
209 {
210 }
211
212instead of:
213
214 if () {
83261a2f 215 }"
ccc3ce39 216 :type 'boolean
db133cb6
RS
217 :group 'cperl-autoinsert-details)
218
5c8b7eaf 219(defcustom cperl-extra-newline-before-brace-multiline
db133cb6
RS
220 cperl-extra-newline-before-brace
221 "*Non-nil means the same as `cperl-extra-newline-before-brace', but
222for constructs with multiline if/unless/while/until/for/foreach condition."
223 :type 'boolean
224 :group 'cperl-autoinsert-details)
ccc3ce39
SE
225
226(defcustom cperl-indent-level 2
227 "*Indentation of CPerl statements with respect to containing block."
228 :type 'integer
db133cb6 229 :group 'cperl-indentation-details)
f152a898 230
2d5590e0 231;; Is is not unusual to put both things like perl-indent-level and
f152a898
DN
232;; cperl-indent-level in the local variable section of a file. If only
233;; one of perl-mode and cperl-mode is in use, a warning will be issued
2d5590e0 234;; about the variable. Autoload these here, so that no warning is
f152a898
DN
235;; issued when using either perl-mode or cperl-mode.
236;;;###autoload(put 'cperl-indent-level 'safe-local-variable 'integerp)
2d5590e0
DN
237;;;###autoload(put 'cperl-brace-offset 'safe-local-variable 'integerp)
238;;;###autoload(put 'cperl-continued-brace-offset 'safe-local-variable 'integerp)
239;;;###autoload(put 'cperl-label-offset 'safe-local-variable 'integerp)
240;;;###autoload(put 'cperl-continued-statement-offset 'safe-local-variable 'integerp)
241;;;###autoload(put 'cperl-extra-newline-before-brace 'safe-local-variable 'booleanp)
242;;;###autoload(put 'cperl-merge-trailing-else 'safe-local-variable 'booleanp)
f83d2997 243
ccc3ce39 244(defcustom cperl-lineup-step nil
f83d2997 245 "*`cperl-lineup' will always lineup at multiple of this number.
029cb4d5 246If nil, the value of `cperl-indent-level' will be used."
ccc3ce39 247 :type '(choice (const nil) integer)
db133cb6
RS
248 :group 'cperl-indentation-details)
249
ccc3ce39 250(defcustom cperl-brace-imaginary-offset 0
f83d2997
KH
251 "*Imagined indentation of a Perl open brace that actually follows a statement.
252An open brace following other text is treated as if it were this far
ccc3ce39
SE
253to the right of the start of its line."
254 :type 'integer
db133cb6 255 :group 'cperl-indentation-details)
ccc3ce39
SE
256
257(defcustom cperl-brace-offset 0
258 "*Extra indentation for braces, compared with other text in same context."
259 :type 'integer
db133cb6 260 :group 'cperl-indentation-details)
ccc3ce39
SE
261(defcustom cperl-label-offset -2
262 "*Offset of CPerl label lines relative to usual indentation."
263 :type 'integer
db133cb6 264 :group 'cperl-indentation-details)
ccc3ce39
SE
265(defcustom cperl-min-label-indent 1
266 "*Minimal offset of CPerl label lines."
267 :type 'integer
db133cb6 268 :group 'cperl-indentation-details)
ccc3ce39
SE
269(defcustom cperl-continued-statement-offset 2
270 "*Extra indent for lines not starting new statements."
271 :type 'integer
db133cb6 272 :group 'cperl-indentation-details)
ccc3ce39 273(defcustom cperl-continued-brace-offset 0
f83d2997 274 "*Extra indent for substatements that start with open-braces.
ccc3ce39
SE
275This is in addition to cperl-continued-statement-offset."
276 :type 'integer
db133cb6 277 :group 'cperl-indentation-details)
ccc3ce39
SE
278(defcustom cperl-close-paren-offset -1
279 "*Extra indent for substatements that start with close-parenthesis."
280 :type 'integer
db133cb6 281 :group 'cperl-indentation-details)
ccc3ce39 282
4ab89e7b
SM
283(defcustom cperl-indent-wrt-brace t
284 "*Non-nil means indent statements in if/etc block relative brace, not if/etc.
285Versions 5.2 ... 5.20 behaved as if this were `nil'."
286 :type 'boolean
287 :group 'cperl-indentation-details)
288
ccc3ce39 289(defcustom cperl-auto-newline nil
f83d2997
KH
290 "*Non-nil means automatically newline before and after braces,
291and after colons and semicolons, inserted in CPerl code. The following
292\\[cperl-electric-backspace] will remove the inserted whitespace.
5c8b7eaf 293Insertion after colons requires both this variable and
ccc3ce39
SE
294`cperl-auto-newline-after-colon' set."
295 :type 'boolean
db133cb6 296 :group 'cperl-autoinsert-details)
f83d2997 297
6c389151
SM
298(defcustom cperl-autoindent-on-semi nil
299 "*Non-nil means automatically indent after insertion of (semi)colon.
300Active if `cperl-auto-newline' is false."
301 :type 'boolean
302 :group 'cperl-autoinsert-details)
303
ccc3ce39 304(defcustom cperl-auto-newline-after-colon nil
f83d2997 305 "*Non-nil means automatically newline even after colons.
ccc3ce39
SE
306Subject to `cperl-auto-newline' setting."
307 :type 'boolean
db133cb6 308 :group 'cperl-autoinsert-details)
f83d2997 309
ccc3ce39 310(defcustom cperl-tab-always-indent t
f83d2997 311 "*Non-nil means TAB in CPerl mode should always reindent the current line,
ccc3ce39
SE
312regardless of where in the line point is when the TAB command is used."
313 :type 'boolean
db133cb6 314 :group 'cperl-indentation-details)
f83d2997 315
ccc3ce39 316(defcustom cperl-font-lock nil
029cb4d5 317 "*Non-nil (and non-null) means CPerl buffers will use `font-lock-mode'.
ccc3ce39 318Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
319 :type '(choice (const null) boolean)
320 :group 'cperl-affected-by-hairy)
f83d2997 321
ccc3ce39 322(defcustom cperl-electric-lbrace-space nil
029cb4d5 323 "*Non-nil (and non-null) means { after $ should be preceded by ` '.
ccc3ce39 324Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
325 :type '(choice (const null) boolean)
326 :group 'cperl-affected-by-hairy)
f83d2997 327
ccc3ce39 328(defcustom cperl-electric-parens-string "({[]})<"
f83d2997 329 "*String of parentheses that should be electric in CPerl.
ccc3ce39
SE
330Closing ones are electric only if the region is highlighted."
331 :type 'string
db133cb6 332 :group 'cperl-affected-by-hairy)
f83d2997 333
ccc3ce39 334(defcustom cperl-electric-parens nil
f83d2997 335 "*Non-nil (and non-null) means parentheses should be electric in CPerl.
ccc3ce39 336Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
337 :type '(choice (const null) boolean)
338 :group 'cperl-affected-by-hairy)
339
340(defvar zmacs-regions) ; Avoid warning
341
5c8b7eaf 342(defcustom cperl-electric-parens-mark
f83d2997
KH
343 (and window-system
344 (or (and (boundp 'transient-mark-mode) ; For Emacs
345 transient-mark-mode)
346 (and (boundp 'zmacs-regions) ; For XEmacs
347 zmacs-regions)))
348 "*Not-nil means that electric parens look for active mark.
ccc3ce39
SE
349Default is yes if there is visual feedback on mark."
350 :type 'boolean
db133cb6 351 :group 'cperl-autoinsert-details)
f83d2997 352
ccc3ce39 353(defcustom cperl-electric-linefeed nil
f83d2997
KH
354 "*If true, LFD should be hairy in CPerl, otherwise C-c LFD is hairy.
355In any case these two mean plain and hairy linefeeds together.
ccc3ce39 356Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
357 :type '(choice (const null) boolean)
358 :group 'cperl-affected-by-hairy)
f83d2997 359
ccc3ce39 360(defcustom cperl-electric-keywords nil
f83d2997 361 "*Not-nil (and non-null) means keywords are electric in CPerl.
350b4cb9
EZ
362Can be overwritten by `cperl-hairy' if nil.
363
364Uses `abbrev-mode' to do the expansion. If you want to use your
365own abbrevs in cperl-mode, but do not want keywords to be
366electric, you must redefine `cperl-mode-abbrev-table': do
367\\[edit-abbrevs], search for `cperl-mode-abbrev-table', and, in
368that paragraph, delete the words that appear at the ends of lines and
369that begin with \"cperl-electric\".
370"
db133cb6
RS
371 :type '(choice (const null) boolean)
372 :group 'cperl-affected-by-hairy)
ccc3ce39 373
f739b53b
SM
374(defcustom cperl-electric-backspace-untabify t
375 "*Not-nil means electric-backspace will untabify in CPerl."
376 :type 'boolean
377 :group 'cperl-autoinsert-details)
378
ccc3ce39 379(defcustom cperl-hairy nil
db133cb6 380 "*Not-nil means most of the bells and whistles are enabled in CPerl.
5c8b7eaf 381Affects: `cperl-font-lock', `cperl-electric-lbrace-space',
db133cb6
RS
382`cperl-electric-parens', `cperl-electric-linefeed', `cperl-electric-keywords',
383`cperl-info-on-command-no-prompt', `cperl-clobber-lisp-bindings',
384`cperl-lazy-help-time'."
ccc3ce39 385 :type 'boolean
db133cb6 386 :group 'cperl-affected-by-hairy)
ccc3ce39
SE
387
388(defcustom cperl-comment-column 32
389 "*Column to put comments in CPerl (use \\[cperl-indent] to lineup with code)."
390 :type 'integer
db133cb6 391 :group 'cperl-indentation-details)
ccc3ce39 392
4ab89e7b
SM
393(defcustom cperl-indent-comment-at-column-0 nil
394 "*Non-nil means that comment started at column 0 should be indentable."
395 :type 'boolean
396 :group 'cperl-indentation-details)
e1a5828f
AS
397
398(defcustom cperl-vc-sccs-header '("($sccs) = ('%W\%' =~ /(\\d+(\\.\\d+)+)/) ;")
399 "*Special version of `vc-sccs-header' that is used in CPerl mode buffers."
400 :type '(repeat string)
401 :group 'cperl)
402
4ab89e7b 403(defcustom cperl-vc-rcs-header '("($rcs) = (' $Id\$ ' =~ /(\\d+(\\.\\d+)+)/);")
e1a5828f
AS
404 "*Special version of `vc-rcs-header' that is used in CPerl mode buffers."
405 :type '(repeat string)
4ab89e7b
SM
406 :group 'cperl)
407
408;; This became obsolete...
409(defvar cperl-vc-header-alist nil)
410(make-obsolete-variable
411 'cperl-vc-header-alist
cb5b40ee
SM
412 "use cperl-vc-rcs-header or cperl-vc-sccs-header instead."
413 "22.1")
ccc3ce39 414
5c8b7eaf 415(defcustom cperl-clobber-mode-lists
5bd52f0e
RS
416 (not
417 (and
418 (boundp 'interpreter-mode-alist)
419 (assoc "miniperl" interpreter-mode-alist)
420 (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist)))
421 "*Whether to install us into `interpreter-' and `extension' mode lists."
422 :type 'boolean
423 :group 'cperl)
424
ccc3ce39 425(defcustom cperl-info-on-command-no-prompt nil
f83d2997 426 "*Not-nil (and non-null) means not to prompt on C-h f.
6292d528 427The opposite behavior is always available if prefixed with C-c.
ccc3ce39 428Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
429 :type '(choice (const null) boolean)
430 :group 'cperl-affected-by-hairy)
431
432(defcustom cperl-clobber-lisp-bindings nil
433 "*Not-nil (and non-null) means not overwrite C-h f.
434The function is available on \\[cperl-info-on-command], \\[cperl-get-help].
435Can be overwritten by `cperl-hairy' if nil."
436 :type '(choice (const null) boolean)
437 :group 'cperl-affected-by-hairy)
f83d2997 438
ccc3ce39 439(defcustom cperl-lazy-help-time nil
db133cb6
RS
440 "*Not-nil (and non-null) means to show lazy help after given idle time.
441Can be overwritten by `cperl-hairy' to be 5 sec if nil."
300f7bb3 442 :type '(choice (const null) (const nil) integer)
db133cb6 443 :group 'cperl-affected-by-hairy)
f83d2997 444
ccc3ce39 445(defcustom cperl-pod-face 'font-lock-comment-face
83261a2f 446 "*Face for POD highlighting."
ccc3ce39 447 :type 'face
db133cb6 448 :group 'cperl-faces)
f83d2997 449
ccc3ce39 450(defcustom cperl-pod-head-face 'font-lock-variable-name-face
83261a2f 451 "*Face for POD highlighting.
ccc3ce39
SE
452Font for POD headers."
453 :type 'face
db133cb6 454 :group 'cperl-faces)
f83d2997 455
ccc3ce39 456(defcustom cperl-here-face 'font-lock-string-face
80585273 457 "*Face for here-docs highlighting."
ccc3ce39 458 :type 'face
db133cb6 459 :group 'cperl-faces)
f83d2997 460
4ab89e7b 461;;; Some double-evaluation happened with font-locks... Needed with 21.2...
6546555e 462(defvar cperl-singly-quote-face (featurep 'xemacs))
4ab89e7b 463
224ca9c9
CY
464(defcustom cperl-invalid-face 'underline
465 "*Face for highlighting trailing whitespace."
80585273 466 :type 'face
ac6857fb 467 :version "21.1"
5bd52f0e
RS
468 :group 'cperl-faces)
469
ccc3ce39 470(defcustom cperl-pod-here-fontify '(featurep 'font-lock)
83261a2f 471 "*Not-nil after evaluation means to highlight POD and here-docs sections."
ccc3ce39 472 :type 'boolean
db133cb6 473 :group 'cperl-faces)
f83d2997 474
5bd52f0e
RS
475(defcustom cperl-fontify-m-as-s t
476 "*Not-nil means highlight 1arg regular expressions operators same as 2arg."
477 :type 'boolean
478 :group 'cperl-faces)
479
6c389151
SM
480(defcustom cperl-highlight-variables-indiscriminately nil
481 "*Non-nil means perform additional highlighting on variables.
482Currently only changes how scalar variables are highlighted.
483Note that that variable is only read at initialization time for
484the variable `cperl-font-lock-keywords-2', so changing it after you've
f94a632a 485entered CPerl mode the first time will have no effect."
6c389151
SM
486 :type 'boolean
487 :group 'cperl)
488
ccc3ce39 489(defcustom cperl-pod-here-scan t
83261a2f 490 "*Not-nil means look for POD and here-docs sections during startup.
ccc3ce39
SE
491You can always make lookup from menu or using \\[cperl-find-pods-heres]."
492 :type 'boolean
db133cb6 493 :group 'cperl-speed)
f83d2997 494
6c389151
SM
495(defcustom cperl-regexp-scan t
496 "*Not-nil means make marking of regular expression more thorough.
4ab89e7b
SM
497Effective only with `cperl-pod-here-scan'."
498 :type 'boolean
499 :group 'cperl-speed)
500
501(defcustom cperl-hook-after-change t
502 "*Not-nil means install hook to know which regions of buffer are changed.
503May significantly speed up delayed fontification. Changes take effect
504after reload."
6c389151
SM
505 :type 'boolean
506 :group 'cperl-speed)
507
ccc3ce39 508(defcustom cperl-imenu-addback nil
f83d2997 509 "*Not-nil means add backreferences to generated `imenu's.
db133cb6 510May require patched `imenu' and `imenu-go'. Obsolete."
ccc3ce39 511 :type 'boolean
db133cb6 512 :group 'cperl-help-system)
f83d2997 513
ccc3ce39
SE
514(defcustom cperl-max-help-size 66
515 "*Non-nil means shrink-wrapping of info-buffer allowed up to these percents."
516 :type '(choice integer (const nil))
db133cb6 517 :group 'cperl-help-system)
f83d2997 518
ccc3ce39
SE
519(defcustom cperl-shrink-wrap-info-frame t
520 "*Non-nil means shrink-wrapping of info-buffer-frame allowed."
521 :type 'boolean
db133cb6 522 :group 'cperl-help-system)
f83d2997 523
ccc3ce39 524(defcustom cperl-info-page "perl"
f83d2997 525 "*Name of the info page containing perl docs.
ccc3ce39
SE
526Older version of this page was called `perl5', newer `perl'."
527 :type 'string
db133cb6 528 :group 'cperl-help-system)
f83d2997 529
5c8b7eaf 530(defcustom cperl-use-syntax-table-text-property
f83d2997 531 (boundp 'parse-sexp-lookup-properties)
ccc3ce39
SE
532 "*Non-nil means CPerl sets up and uses `syntax-table' text property."
533 :type 'boolean
db133cb6 534 :group 'cperl-speed)
f83d2997 535
5c8b7eaf 536(defcustom cperl-use-syntax-table-text-property-for-tags
f83d2997 537 cperl-use-syntax-table-text-property
ccc3ce39
SE
538 "*Non-nil means: set up and use `syntax-table' text property generating TAGS."
539 :type 'boolean
db133cb6 540 :group 'cperl-speed)
ccc3ce39
SE
541
542(defcustom cperl-scan-files-regexp "\\.\\([pP][Llm]\\|xs\\)$"
543 "*Regexp to match files to scan when generating TAGS."
544 :type 'regexp
545 :group 'cperl)
546
8937f01b
RS
547(defcustom cperl-noscan-files-regexp
548 "/\\(\\.\\.?\\|SCCS\\|RCS\\|CVS\\|blib\\)$"
ccc3ce39
SE
549 "*Regexp to match files/dirs to skip when generating TAGS."
550 :type 'regexp
551 :group 'cperl)
552
553(defcustom cperl-regexp-indent-step nil
554 "*Indentation used when beautifying regexps.
029cb4d5 555If nil, the value of `cperl-indent-level' will be used."
ccc3ce39 556 :type '(choice integer (const nil))
db133cb6 557 :group 'cperl-indentation-details)
ccc3ce39
SE
558
559(defcustom cperl-indent-left-aligned-comments t
560 "*Non-nil means that the comment starting in leftmost column should indent."
561 :type 'boolean
db133cb6 562 :group 'cperl-indentation-details)
ccc3ce39 563
8f222248 564(defcustom cperl-under-as-char nil
ccc3ce39
SE
565 "*Non-nil means that the _ (underline) should be treated as word char."
566 :type 'boolean
567 :group 'cperl)
f83d2997 568
db133cb6
RS
569(defcustom cperl-extra-perl-args ""
570 "*Extra arguments to use when starting Perl.
571Currently used with `cperl-check-syntax' only."
572 :type 'string
573 :group 'cperl)
574
575(defcustom cperl-message-electric-keyword t
576 "*Non-nil means that the `cperl-electric-keyword' prints a help message."
577 :type 'boolean
578 :group 'cperl-help-system)
579
580(defcustom cperl-indent-region-fix-constructs 1
581 "*Amount of space to insert between `}' and `else' or `elsif'
582in `cperl-indent-region'. Set to nil to leave as is. Values other
583than 1 and nil will probably not work."
584 :type '(choice (const nil) (const 1))
585 :group 'cperl-indentation-details)
586
587(defcustom cperl-break-one-line-blocks-when-indent t
588 "*Non-nil means that one-line if/unless/while/until/for/foreach BLOCKs
2022c546 589need to be reformatted into multiline ones when indenting a region."
db133cb6
RS
590 :type 'boolean
591 :group 'cperl-indentation-details)
592
593(defcustom cperl-fix-hanging-brace-when-indent t
594 "*Non-nil means that BLOCK-end `}' may be put on a separate line
5c8b7eaf 595when indenting a region.
db133cb6
RS
596Braces followed by else/elsif/while/until are excepted."
597 :type 'boolean
598 :group 'cperl-indentation-details)
599
600(defcustom cperl-merge-trailing-else t
5c8b7eaf 601 "*Non-nil means that BLOCK-end `}' followed by else/elsif/continue
db133cb6
RS
602may be merged to be on the same line when indenting a region."
603 :type 'boolean
604 :group 'cperl-indentation-details)
605
6c389151
SM
606(defcustom cperl-indent-parens-as-block nil
607 "*Non-nil means that non-block ()-, {}- and []-groups are indented as blocks,
608but for trailing \",\" inside the group, which won't increase indentation.
609One should tune up `cperl-close-paren-offset' as well."
610 :type 'boolean
611 :group 'cperl-indentation-details)
612
a1506d29 613(defcustom cperl-syntaxify-by-font-lock
83261a2f 614 (and cperl-can-font-lock
5bd52f0e 615 (boundp 'parse-sexp-lookup-properties))
3af98a7b 616 "*Non-nil means that CPerl uses the `font-lock' routines for syntaxification."
5bd52f0e
RS
617 :type '(choice (const message) boolean)
618 :group 'cperl-speed)
619
620(defcustom cperl-syntaxify-unwind
621 t
f94a632a 622 "*Non-nil means that CPerl unwinds to a start of a long construction
5bd52f0e 623when syntaxifying a chunk of buffer."
db133cb6
RS
624 :type 'boolean
625 :group 'cperl-speed)
626
4ab89e7b
SM
627(defcustom cperl-syntaxify-for-menu
628 t
629 "*Non-nil means that CPerl syntaxifies up to the point before showing menu.
630This way enabling/disabling of menu items is more correct."
631 :type 'boolean
632 :group 'cperl-speed)
633
5bd52f0e
RS
634(defcustom cperl-ps-print-face-properties
635 '((font-lock-keyword-face nil nil bold shadow)
636 (font-lock-variable-name-face nil nil bold)
637 (font-lock-function-name-face nil nil bold italic box)
638 (font-lock-constant-face nil "LightGray" bold)
4ab89e7b 639 (cperl-array-face nil "LightGray" bold underline)
8c777c8d 640 (cperl-hash-face nil "LightGray" bold italic underline)
5bd52f0e
RS
641 (font-lock-comment-face nil "LightGray" italic)
642 (font-lock-string-face nil nil italic underline)
4ab89e7b 643 (cperl-nonoverridable-face nil nil italic underline)
5bd52f0e 644 (font-lock-type-face nil nil underline)
4ab89e7b 645 (font-lock-warning-face nil "LightGray" bold italic box)
5bd52f0e
RS
646 (underline nil "LightGray" strikeout))
647 "List given as an argument to `ps-extend-face-list' in `cperl-ps-print'."
5c8b7eaf 648 :type '(repeat (cons symbol
5bd52f0e
RS
649 (cons (choice (const nil) string)
650 (cons (choice (const nil) string)
651 (repeat symbol)))))
652 :group 'cperl-faces)
653
5cc679ab
JB
654(defvar cperl-dark-background
655 (cperl-choose-color "navy" "os2blue" "darkgreen"))
656(defvar cperl-dark-foreground
657 (cperl-choose-color "orchid1" "orange"))
658
4ab89e7b 659(defface cperl-nonoverridable-face
5cc679ab
JB
660 `((((class grayscale) (background light))
661 (:background "Gray90" :slant italic :underline t))
662 (((class grayscale) (background dark))
663 (:foreground "Gray80" :slant italic :underline t :weight bold))
664 (((class color) (background light))
665 (:foreground "chartreuse3"))
666 (((class color) (background dark))
667 (:foreground ,cperl-dark-foreground))
668 (t (:weight bold :underline t)))
c73fce9a 669 "Font Lock mode face used non-overridable keywords and modifiers of regexps."
5cc679ab
JB
670 :group 'cperl-faces)
671
4ab89e7b 672(defface cperl-array-face
5cc679ab
JB
673 `((((class grayscale) (background light))
674 (:background "Gray90" :weight bold))
675 (((class grayscale) (background dark))
676 (:foreground "Gray80" :weight bold))
677 (((class color) (background light))
678 (:foreground "Blue" :background "lightyellow2" :weight bold))
679 (((class color) (background dark))
680 (:foreground "yellow" :background ,cperl-dark-background :weight bold))
681 (t (:weight bold)))
682 "Font Lock mode face used to highlight array names."
683 :group 'cperl-faces)
684
4ab89e7b 685(defface cperl-hash-face
5cc679ab
JB
686 `((((class grayscale) (background light))
687 (:background "Gray90" :weight bold :slant italic))
688 (((class grayscale) (background dark))
689 (:foreground "Gray80" :weight bold :slant italic))
690 (((class color) (background light))
691 (:foreground "Red" :background "lightyellow2" :weight bold :slant italic))
692 (((class color) (background dark))
693 (:foreground "Red" :background ,cperl-dark-background :weight bold :slant italic))
694 (t (:weight bold :slant italic)))
695 "Font Lock mode face used to highlight hash names."
696 :group 'cperl-faces)
5bd52f0e 697
f83d2997
KH
698\f
699
700;;; Short extra-docs.
701
702(defvar cperl-tips 'please-ignore-this-line
83261a2f 703 "Get maybe newer version of this package from
4ab89e7b 704 http://ilyaz.org/software/emacs
db133cb6
RS
705Subdirectory `cperl-mode' may contain yet newer development releases and/or
706patches to related files.
f83d2997 707
5bd52f0e
RS
708For best results apply to an older Emacs the patches from
709 ftp://ftp.math.ohio-state.edu/pub/users/ilya/cperl-mode/patches
83261a2f 710\(this upgrades syntax-parsing abilities of Emacsen v19.34 and
8e3acc66 711v20.2 up to the level of Emacs v20.3 - a must for a good Perl
83261a2f 712mode.) As of beginning of 2003, XEmacs may provide a similar ability.
5bd52f0e 713
f83d2997
KH
714Get support packages choose-color.el (or font-lock-extra.el before
71519.30), imenu-go.el from the same place. \(Look for other files there
716too... ;-). Get a patch for imenu.el in 19.29. Note that for 19.30 and
5c8b7eaf 717later you should use choose-color.el *instead* of font-lock-extra.el
f83d2997
KH
718\(and you will not get smart highlighting in C :-().
719
720Note that to enable Compile choices in the menu you need to install
721mode-compile.el.
722
5efe6a56
SM
723If your Emacs does not default to `cperl-mode' on Perl files, and you
724want it to: put the following into your .emacs file:
725
726 (defalias 'perl-mode 'cperl-mode)
727
a1506d29 728Get perl5-info from
4ab89e7b
SM
729 $CPAN/doc/manual/info/perl5-old/perl5-info.tar.gz
730Also, one can generate a newer documentation running `pod2texi' converter
731 $CPAN/doc/manual/info/perl5/pod2texi-0.1.tar.gz
f83d2997
KH
732
733If you use imenu-go, run imenu on perl5-info buffer (you can do it
5bd52f0e
RS
734from Perl menu). If many files are related, generate TAGS files from
735Tools/Tags submenu in Perl menu.
f83d2997
KH
736
737If some class structure is too complicated, use Tools/Hierarchy-view
029cb4d5 738from Perl menu, or hierarchic view of imenu. The second one uses the
f83d2997 739current buffer only, the first one requires generation of TAGS from
5bd52f0e
RS
740Perl/Tools/Tags menu beforehand.
741
742Run Perl/Tools/Insert-spaces-if-needed to fix your lazy typing.
743
744Switch auto-help on/off with Perl/Tools/Auto-help.
745
746Though with contemporary Emaxen CPerl mode should maintain the correct
747parsing of Perl even when editing, sometimes it may be lost. Fix this by
748
029cb4d5 749 \\[normal-mode]
f83d2997 750
5bd52f0e 751In cases of more severe confusion sometimes it is helpful to do
f83d2997 752
029cb4d5
SM
753 \\[load-library] cperl-mode RET
754 \\[normal-mode]
f83d2997 755
5bd52f0e
RS
756Before reporting (non-)problems look in the problem section of online
757micro-docs on what I know about CPerl problems.")
f83d2997
KH
758
759(defvar cperl-problems 'please-ignore-this-line
f94a632a
RS
760 "Description of problems in CPerl mode.
761Some faces will not be shown on some versions of Emacs unless you
bab27c0c 762install choose-color.el, available from
4ab89e7b 763 http://ilyaz.org/software/emacs
bab27c0c 764
6c389151 765`fill-paragraph' on a comment may leave the point behind the
4ab89e7b
SM
766paragraph. It also triggers a bug in some versions of Emacs (CPerl tries
767to detect it and bulk out).
768
769See documentation of a variable `cperl-problems-old-emaxen' for the
770problems which disappear if you upgrade Emacs to a reasonably new
771version (20.3 for Emacs, and those of 2004 for XEmacs).")
772
773(defvar cperl-problems-old-emaxen 'please-ignore-this-line
774 "Description of problems in CPerl mode specific for older Emacs versions.
6c389151 775
8e3acc66 776Emacs had a _very_ restricted syntax parsing engine until version
5bd52f0e 77720.1. Most problems below are corrected starting from this version of
8e3acc66 778Emacs, and all of them should be fixed in version 20.3. (Or apply
83261a2f
SM
779patches to Emacs 19.33/34 - see tips.) XEmacs was very backward in
780this respect (until 2003).
5bd52f0e 781
6c389151
SM
782Note that even with newer Emacsen in some very rare cases the details
783of interaction of `font-lock' and syntaxification may be not cleaned
784up yet. You may get slightly different colors basing on the order of
785fontification and syntaxification. Say, the initial faces is correct,
786but editing the buffer breaks this.
f83d2997 787
db133cb6
RS
788Even with older Emacsen CPerl mode tries to corrects some Emacs
789misunderstandings, however, for efficiency reasons the degree of
790correction is different for different operations. The partially
791corrected problems are: POD sections, here-documents, regexps. The
792operations are: highlighting, indentation, electric keywords, electric
793braces.
f83d2997
KH
794
795This may be confusing, since the regexp s#//#/#\; may be highlighted
796as a comment, but it will be recognized as a regexp by the indentation
83261a2f 797code. Or the opposite case, when a POD section is highlighted, but
f83d2997
KH
798may break the indentation of the following code (though indentation
799should work if the balance of delimiters is not broken by POD).
800
801The main trick (to make $ a \"backslash\") makes constructions like
802${aaa} look like unbalanced braces. The only trick I can think of is
2e8b9c7d 803to insert it as $ {aaa} (valid in perl5, not in perl4).
f83d2997
KH
804
805Similar problems arise in regexps, when /(\\s|$)/ should be rewritten
db133cb6
RS
806as /($|\\s)/. Note that such a transposition is not always possible.
807
5bd52f0e 808The solution is to upgrade your Emacs or patch an older one. Note
8e3acc66 809that Emacs 20.2 has some bugs related to `syntax-table' text
5bd52f0e
RS
810properties. Patches are available on the main CPerl download site,
811and on CPAN.
db133cb6
RS
812
813If these bugs cannot be fixed on your machine (say, you have an inferior
814environment and cannot recompile), you may still disable all the fancy stuff
83261a2f 815via `cperl-use-syntax-table-text-property'.")
f83d2997 816
f83d2997 817(defvar cperl-praise 'please-ignore-this-line
8e3acc66 818 "Advantages of CPerl mode.
f83d2997
KH
819
8200) It uses the newest `syntax-table' property ;-);
821
8221) It does 99% of Perl syntax correct (as opposed to 80-90% in Perl
5c8b7eaf 823mode - but the latter number may have improved too in last years) even
5bd52f0e
RS
824with old Emaxen which do not support `syntax-table' property.
825
826When using `syntax-table' property for syntax assist hints, it should
827handle 99.995% of lines correct - or somesuch. It automatically
828updates syntax assist hints when you edit your script.
f83d2997 829
bab27c0c 8302) It is generally believed to be \"the most user-friendly Emacs
f83d2997
KH
831package\" whatever it may mean (I doubt that the people who say similar
832things tried _all_ the rest of Emacs ;-), but this was not a lonely
833voice);
834
8353) Everything is customizable, one-by-one or in a big sweep;
836
549c0a96 8374) It has many easily-accessible \"tools\":
f83d2997
KH
838 a) Can run program, check syntax, start debugger;
839 b) Can lineup vertically \"middles\" of rows, like `=' in
840 a = b;
841 cc = d;
53964682 842 c) Can insert spaces where this improves readability (in one
f83d2997
KH
843 interactive sweep over the buffer);
844 d) Has support for imenu, including:
845 1) Separate unordered list of \"interesting places\";
846 2) Separate TOC of POD sections;
847 3) Separate list of packages;
848 4) Hierarchical view of methods in (sub)packages;
849 5) and functions (by the full name - with package);
850 e) Has an interface to INFO docs for Perl; The interface is
851 very flexible, including shrink-wrapping of
852 documentation buffer/frame;
853 f) Has a builtin list of one-line explanations for perl constructs.
854 g) Can show these explanations if you stay long enough at the
855 corresponding place (or on demand);
856 h) Has an enhanced fontification (using 3 or 4 additional faces
857 comparing to font-lock - basically, different
858 namespaces in Perl have different colors);
859 i) Can construct TAGS basing on its knowledge of Perl syntax,
860 the standard menu has 6 different way to generate
db133cb6 861 TAGS (if \"by directory\", .xs files - with C-language
f83d2997
KH
862 bindings - are included in the scan);
863 j) Can build a hierarchical view of classes (via imenu) basing
864 on generated TAGS file;
865 k) Has electric parentheses, electric newlines, uses Abbrev
866 for electric logical constructs
867 while () {}
868 with different styles of expansion (context sensitive
869 to be not so bothering). Electric parentheses behave
870 \"as they should\" in a presence of a visible region.
871 l) Changes msb.el \"on the fly\" to insert a group \"Perl files\";
db133cb6
RS
872 m) Can convert from
873 if (A) { B }
874 to
875 B if A;
f83d2997 876
5bd52f0e 877 n) Highlights (by user-choice) either 3-delimiters constructs
6c389151
SM
878 (such as tr/a/b/), or regular expressions and `y/tr';
879 o) Highlights trailing whitespace;
880 p) Is able to manipulate Perl Regular Expressions to ease
881 conversion to a more readable form.
4ab89e7b
SM
882 q) Can ispell POD sections and HERE-DOCs.
883 r) Understands comments and character classes inside regular
884 expressions; can find matching () and [] in a regular expression.
885 s) Allows indentation of //x-style regular expressions;
886 t) Highlights different symbols in regular expressions according
887 to their function; much less problems with backslashitis;
888 u) Allows to find regular expressions which contain interpolated parts.
5bd52f0e 889
f83d2997
KH
8905) The indentation engine was very smart, but most of tricks may be
891not needed anymore with the support for `syntax-table' property. Has
892progress indicator for indentation (with `imenu' loaded).
893
5c8b7eaf 8946) Indent-region improves inline-comments as well; also corrects
db133cb6 895whitespace *inside* the conditional/loop constructs.
f83d2997
KH
896
8977) Fill-paragraph correctly handles multi-line comments;
db133cb6
RS
898
8998) Can switch to different indentation styles by one command, and restore
900the settings present before the switch.
901
5c8b7eaf 9029) When doing indentation of control constructs, may correct
db133cb6 903line-breaks/spacing between elements of the construct.
029cb4d5 904
91af3942 90510) Uses a linear-time algorithm for indentation of regions (on Emaxen with
4ab89e7b
SM
906capable syntax engines).
907
90811) Syntax-highlight, indentation, sexp-recognition inside regular expressions.
909")
db133cb6
RS
910
911(defvar cperl-speed 'please-ignore-this-line
912 "This is an incomplete compendium of what is available in other parts
913of CPerl documentation. (Please inform me if I skept anything.)
914
915There is a perception that CPerl is slower than alternatives. This part
916of documentation is designed to overcome this misconception.
917
918*By default* CPerl tries to enable the most comfortable settings.
919From most points of view, correctly working package is infinitely more
920comfortable than a non-correctly working one, thus by default CPerl
921prefers correctness over speed. Below is the guide how to change
922settings if your preferences are different.
923
924A) Speed of loading the file. When loading file, CPerl may perform a
925scan which indicates places which cannot be parsed by primitive Emacs
926syntax-parsing routines, and marks them up so that either
927
928 A1) CPerl may work around these deficiencies (for big chunks, mostly
929 PODs and HERE-documents), or
3ed8598c 930 A2) On capable Emaxen CPerl will use improved syntax-handling
db133cb6
RS
931 which reads mark-up hints directly.
932
933 The scan in case A2 is much more comprehensive, thus may be slower.
934
935 User can disable syntax-engine-helping scan of A2 by setting
936 `cperl-use-syntax-table-text-property'
937 variable to nil (if it is set to t).
938
939 One can disable the scan altogether (both A1 and A2) by setting
940 `cperl-pod-here-scan'
941 to nil.
942
5c8b7eaf 943B) Speed of editing operations.
db133cb6
RS
944
945 One can add a (minor) speedup to editing operations by setting
946 `cperl-use-syntax-table-text-property'
947 variable to nil (if it is set to t). This will disable
948 syntax-engine-helping scan, thus will make many more Perl
949 constructs be wrongly recognized by CPerl, thus may lead to
950 wrongly matched parentheses, wrong indentation, etc.
5bd52f0e
RS
951
952 One can unset `cperl-syntaxify-unwind'. This might speed up editing
83261a2f 953 of, say, long POD sections.")
f83d2997 954
5bd52f0e
RS
955(defvar cperl-tips-faces 'please-ignore-this-line
956 "CPerl mode uses following faces for highlighting:
957
4ab89e7b
SM
958 `cperl-array-face' Array names
959 `cperl-hash-face' Hash names
8661c643 960 `font-lock-comment-face' Comments, PODs and whatever is considered
bbd240ce 961 syntactically to be not code
8661c643 962 `font-lock-constant-face' HERE-doc delimiters, labels, delimiters of
5bd52f0e 963 2-arg operators s/y/tr/ or of RExen,
4ab89e7b
SM
964 `font-lock-warning-face' Special-cased m// and s//foo/,
965 `font-lock-function-name-face' _ as a target of a file tests, file tests,
5bd52f0e
RS
966 subroutine names at the moment of definition
967 (except those conflicting with Perl operators),
968 package names (when recognized), format names
8661c643 969 `font-lock-keyword-face' Control flow switch constructs, declarators
4ab89e7b 970 `cperl-nonoverridable-face' Non-overridable keywords, modifiers of RExen
8661c643 971 `font-lock-string-face' Strings, qw() constructs, RExen, POD sections,
5bd52f0e 972 literal parts and the terminator of formats
bbd240ce 973 and whatever is syntactically considered
5bd52f0e 974 as string literals
8661c643
DL
975 `font-lock-type-face' Overridable keywords
976 `font-lock-variable-name-face' Variable declarations, indirect array and
5bd52f0e 977 hash names, POD headers/item names
8c777c8d 978 `cperl-invalid-face' Trailing whitespace
5bd52f0e
RS
979
980Note that in several situations the highlighting tries to inform about
981possible confusion, such as different colors for function names in
982declarations depending on what they (do not) override, or special cases
983m// and s/// which do not do what one would expect them to do.
984
5c8b7eaf 985Help with best setup of these faces for printout requested (for each of
5bd52f0e
RS
986the faces: please specify bold, italic, underline, shadow and box.)
987
8c777c8d 988In regular expressions (including character classes):
4ab89e7b
SM
989 `font-lock-string-face' \"Normal\" stuff and non-0-length constructs
990 `font-lock-constant-face': Delimiters
991 `font-lock-warning-face' Special-cased m// and s//foo/,
992 Mismatched closing delimiters, parens
993 we couldn't match, misplaced quantifiers,
994 unrecognized escape sequences
995 `cperl-nonoverridable-face' Modifiers, as gism in m/REx/gism
8c777c8d 996 `font-lock-type-face' escape sequences with arguments (\\x \\23 \\p \\N)
4ab89e7b
SM
997 and others match-a-char escape sequences
998 `font-lock-keyword-face' Capturing parens, and |
999 `font-lock-function-name-face' Special symbols: $ ^ . [ ] [^ ] (?{ }) (??{ })
8c777c8d
CY
1000 \"Range -\" in character classes
1001 `font-lock-builtin-face' \"Remaining\" 0-length constructs, multipliers
1002 ?+*{}, not-capturing parens, leading
1003 backslashes of escape sequences
1004 `font-lock-variable-name-face' Interpolated constructs, embedded code,
1005 POSIX classes (inside charclasses)
4ab89e7b
SM
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
8c777c8d 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:
40ba43b4 1280 ;; debugging syntaxification can be broken by this???
4ab89e7b
SM
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 "----"
4c36be58 1307 ["CPerl pretty print (experimental)" cperl-ps-print
4ab89e7b 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]*\\)*"
e4769531 1391"Regular expression to match optional whitespace with interspersed comments.
4ab89e7b
SM
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\\)+"
e4769531 1396"Regular expression to match whitespace with interspersed comments.
4ab89e7b
SM
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)
8c777c8d
CY
1499 (modify-syntax-entry ?\" "." cperl-string-syntax-table)
1500 (modify-syntax-entry ?' "." cperl-string-syntax-table)
1501 (modify-syntax-entry ?` "." cperl-string-syntax-table)
83261a2f 1502 (modify-syntax-entry ?# "." cperl-string-syntax-table)) ; (?# comment )
f83d2997
KH
1503
1504
1505\f
db133cb6 1506(defvar cperl-faces-init nil)
f83d2997
KH
1507;; Fix for msb.el
1508(defvar cperl-msb-fixed nil)
83261a2f 1509(defvar cperl-use-major-mode 'cperl-mode)
4ab89e7b
SM
1510(defvar cperl-font-lock-multiline-start nil)
1511(defvar cperl-font-lock-multiline nil)
4ab89e7b 1512(defvar cperl-font-locking nil)
83261a2f 1513
e9bfd3a3 1514;; NB as it stands the code in cperl-mode assumes this only has one
0d26e0b6 1515;; element. If XEmacs 19 support were dropped, this could all be simplified.
e9bfd3a3
GM
1516(defvar cperl-compilation-error-regexp-alist
1517 ;; This look like a paranoiac regexp: could anybody find a better one? (which WORKS).
1518 '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
1519 2 3))
1520 "Alist that specifies how to match errors in perl output.")
1521
73e72da4
DN
1522(defvar compilation-error-regexp-alist)
1523
f83d2997 1524;;;###autoload
5fdd4046 1525(define-derived-mode cperl-mode prog-mode "CPerl"
f83d2997
KH
1526 "Major mode for editing Perl code.
1527Expression and list commands understand all C brackets.
1528Tab indents for Perl code.
1529Paragraphs are separated by blank lines only.
1530Delete converts tabs to spaces as it moves back.
1531
1532Various characters in Perl almost always come in pairs: {}, (), [],
1533sometimes <>. When the user types the first, she gets the second as
1534well, with optional special formatting done on {}. (Disabled by
1535default.) You can always quote (with \\[quoted-insert]) the left
1536\"paren\" to avoid the expansion. The processing of < is special,
f94a632a 1537since most the time you mean \"less\". CPerl mode tries to guess
f83d2997
KH
1538whether you want to type pair <>, and inserts is if it
1539appropriate. You can set `cperl-electric-parens-string' to the string that
bbd240ce
PE
1540contains the parens from the above list you want to be electrical.
1541Electricity of parens is controlled by `cperl-electric-parens'.
f83d2997
KH
1542You may also set `cperl-electric-parens-mark' to have electric parens
1543look for active mark and \"embrace\" a region if possible.'
1544
1545CPerl mode provides expansion of the Perl control constructs:
db133cb6 1546
5c8b7eaf 1547 if, else, elsif, unless, while, until, continue, do,
db133cb6
RS
1548 for, foreach, formy and foreachmy.
1549
1550and POD directives (Disabled by default, see `cperl-electric-keywords'.)
1551
1552The user types the keyword immediately followed by a space, which
1553causes the construct to be expanded, and the point is positioned where
1554she is most likely to want to be. eg. when the user types a space
1555following \"if\" the following appears in the buffer: if () { or if ()
1556} { } and the cursor is between the parentheses. The user can then
1557type some boolean expression within the parens. Having done that,
1558typing \\[cperl-linefeed] places you - appropriately indented - on a
1559new line between the braces (if you typed \\[cperl-linefeed] in a POD
5c8b7eaf 1560directive line, then appropriate number of new lines is inserted).
db133cb6
RS
1561
1562If CPerl decides that you want to insert \"English\" style construct like
1563
f83d2997 1564 bite if angry;
db133cb6
RS
1565
1566it will not do any expansion. See also help on variable
1567`cperl-extra-newline-before-brace'. (Note that one can switch the
1568help message on expansion by setting `cperl-message-electric-keyword'
1569to nil.)
f83d2997
KH
1570
1571\\[cperl-linefeed] is a convenience replacement for typing carriage
1572return. It places you in the next line with proper indentation, or if
1573you type it inside the inline block of control construct, like
db133cb6 1574
f83d2997 1575 foreach (@lines) {print; print}
db133cb6 1576
f83d2997
KH
1577and you are on a boundary of a statement inside braces, it will
1578transform the construct into a multiline and will place you into an
5c8b7eaf 1579appropriately indented blank line. If you need a usual
6292d528 1580`newline-and-indent' behavior, it is on \\[newline-and-indent],
f83d2997
KH
1581see documentation on `cperl-electric-linefeed'.
1582
db133cb6
RS
1583Use \\[cperl-invert-if-unless] to change a construction of the form
1584
1585 if (A) { B }
1586
1587into
1588
1589 B if A;
1590
f83d2997
KH
1591\\{cperl-mode-map}
1592
db133cb6
RS
1593Setting the variable `cperl-font-lock' to t switches on font-lock-mode
1594\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
1595on electric space between $ and {, `cperl-electric-parens-string' is
1596the string that contains parentheses that should be electric in CPerl
1597\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
f83d2997
KH
1598setting `cperl-electric-keywords' enables electric expansion of
1599control structures in CPerl. `cperl-electric-linefeed' governs which
1600one of two linefeed behavior is preferable. You can enable all these
1601options simultaneously (recommended mode of use) by setting
1602`cperl-hairy' to t. In this case you can switch separate options off
db133cb6
RS
1603by setting them to `null'. Note that one may undo the extra
1604whitespace inserted by semis and braces in `auto-newline'-mode by
1605consequent \\[cperl-electric-backspace].
f83d2997
KH
1606
1607If your site has perl5 documentation in info format, you can use commands
1608\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
1609These keys run commands `cperl-info-on-current-command' and
1610`cperl-info-on-command', which one is which is controlled by variable
5c8b7eaf 1611`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
db133cb6 1612\(in turn affected by `cperl-hairy').
f83d2997
KH
1613
1614Even if you have no info-format documentation, short one-liner-style
db133cb6
RS
1615help is available on \\[cperl-get-help], and one can run perldoc or
1616man via menu.
f83d2997 1617
db133cb6
RS
1618It is possible to show this help automatically after some idle time.
1619This is regulated by variable `cperl-lazy-help-time'. Default with
1620`cperl-hairy' (if the value of `cperl-lazy-help-time' is nil) is 5
1621secs idle time . It is also possible to switch this on/off from the
1622menu, or via \\[cperl-toggle-autohelp]. Requires `run-with-idle-timer'.
f83d2997
KH
1623
1624Use \\[cperl-lineup] to vertically lineup some construction - put the
1625beginning of the region at the start of construction, and make region
1626span the needed amount of lines.
1627
1628Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
83261a2f 1629`cperl-pod-face', `cperl-pod-head-face' control processing of POD and
db133cb6
RS
1630here-docs sections. With capable Emaxen results of scan are used
1631for indentation too, otherwise they are used for highlighting only.
f83d2997
KH
1632
1633Variables controlling indentation style:
1634 `cperl-tab-always-indent'
1635 Non-nil means TAB in CPerl mode should always reindent the current line,
1636 regardless of where in the line point is when the TAB command is used.
db133cb6
RS
1637 `cperl-indent-left-aligned-comments'
1638 Non-nil means that the comment starting in leftmost column should indent.
f83d2997
KH
1639 `cperl-auto-newline'
1640 Non-nil means automatically newline before and after braces,
1641 and after colons and semicolons, inserted in Perl code. The following
1642 \\[cperl-electric-backspace] will remove the inserted whitespace.
5c8b7eaf
SS
1643 Insertion after colons requires both this variable and
1644 `cperl-auto-newline-after-colon' set.
f83d2997
KH
1645 `cperl-auto-newline-after-colon'
1646 Non-nil means automatically newline even after colons.
1647 Subject to `cperl-auto-newline' setting.
1648 `cperl-indent-level'
1649 Indentation of Perl statements within surrounding block.
1650 The surrounding block's indentation is the indentation
1651 of the line on which the open-brace appears.
1652 `cperl-continued-statement-offset'
1653 Extra indentation given to a substatement, such as the
1654 then-clause of an if, or body of a while, or just a statement continuation.
1655 `cperl-continued-brace-offset'
1656 Extra indentation given to a brace that starts a substatement.
1657 This is in addition to `cperl-continued-statement-offset'.
1658 `cperl-brace-offset'
1659 Extra indentation for line if it starts with an open brace.
1660 `cperl-brace-imaginary-offset'
1661 An open brace following other text is treated as if it the line started
1662 this far to the right of the actual line indentation.
1663 `cperl-label-offset'
1664 Extra indentation for line that is a label.
1665 `cperl-min-label-indent'
1666 Minimal indentation for line that is a label.
1667
4ab89e7b
SM
1668Settings for classic indent-styles: K&R BSD=C++ GNU PerlStyle=Whitesmith
1669 `cperl-indent-level' 5 4 2 4
1670 `cperl-brace-offset' 0 0 0 0
1671 `cperl-continued-brace-offset' -5 -4 0 0
1672 `cperl-label-offset' -5 -4 -2 -4
1673 `cperl-continued-statement-offset' 5 4 2 4
f83d2997 1674
db133cb6
RS
1675CPerl knows several indentation styles, and may bulk set the
1676corresponding variables. Use \\[cperl-set-style] to do this. Use
1677\\[cperl-set-style-back] to restore the memorized preexisting values
4ab89e7b
SM
1678\(both available from menu). See examples in `cperl-style-examples'.
1679
1680Part of the indentation style is how different parts of if/elsif/else
1681statements are broken into lines; in CPerl, this is reflected on how
1682templates for these constructs are created (controlled by
8c777c8d
CY
1683`cperl-extra-newline-before-brace'), and how reflow-logic should treat
1684\"continuation\" blocks of else/elsif/continue, controlled by the same
1685variable, and by `cperl-extra-newline-before-brace-multiline',
4ab89e7b 1686`cperl-merge-trailing-else', `cperl-indent-region-fix-constructs'.
db133cb6
RS
1687
1688If `cperl-indent-level' is 0, the statement after opening brace in
5c8b7eaf 1689column 0 is indented on
db133cb6 1690`cperl-brace-offset'+`cperl-continued-statement-offset'.
f83d2997
KH
1691
1692Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook'
db133cb6
RS
1693with no args.
1694
1695DO NOT FORGET to read micro-docs (available from `Perl' menu)
1696or as help on variables `cperl-tips', `cperl-problems',
f94a632a 1697`cperl-praise', `cperl-speed'."
f83d2997
KH
1698 (if (cperl-val 'cperl-electric-linefeed)
1699 (progn
1700 (local-set-key "\C-J" 'cperl-linefeed)
1701 (local-set-key "\C-C\C-J" 'newline-and-indent)))
db133cb6
RS
1702 (if (and
1703 (cperl-val 'cperl-clobber-lisp-bindings)
1704 (cperl-val 'cperl-info-on-command-no-prompt))
f83d2997
KH
1705 (progn
1706 ;; don't clobber the backspace binding:
1707 (cperl-define-key "\C-hf" 'cperl-info-on-current-command [(control h) f])
1708 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-command
1709 [(control c) (control h) f])))
449657e8
GM
1710 (let ((prev-a-c abbrevs-changed))
1711 (define-abbrev-table 'cperl-mode-abbrev-table '(
f83d2997
KH
1712 ("if" "if" cperl-electric-keyword 0)
1713 ("elsif" "elsif" cperl-electric-keyword 0)
1714 ("while" "while" cperl-electric-keyword 0)
1715 ("until" "until" cperl-electric-keyword 0)
1716 ("unless" "unless" cperl-electric-keyword 0)
1717 ("else" "else" cperl-electric-else 0)
db133cb6 1718 ("continue" "continue" cperl-electric-else 0)
f83d2997
KH
1719 ("for" "for" cperl-electric-keyword 0)
1720 ("foreach" "foreach" cperl-electric-keyword 0)
db133cb6
RS
1721 ("formy" "formy" cperl-electric-keyword 0)
1722 ("foreachmy" "foreachmy" cperl-electric-keyword 0)
1723 ("do" "do" cperl-electric-keyword 0)
6c389151
SM
1724 ("=pod" "=pod" cperl-electric-pod 0)
1725 ("=over" "=over" cperl-electric-pod 0)
1726 ("=head1" "=head1" cperl-electric-pod 0)
1727 ("=head2" "=head2" cperl-electric-pod 0)
db133cb6
RS
1728 ("pod" "pod" cperl-electric-pod 0)
1729 ("over" "over" cperl-electric-pod 0)
1730 ("head1" "head1" cperl-electric-pod 0)
1731 ("head2" "head2" cperl-electric-pod 0)))
449657e8 1732 (setq abbrevs-changed prev-a-c))
f83d2997 1733 (setq local-abbrev-table cperl-mode-abbrev-table)
4ab89e7b
SM
1734 (if (cperl-val 'cperl-electric-keywords)
1735 (abbrev-mode 1))
f83d2997 1736 (set-syntax-table cperl-mode-syntax-table)
4ab89e7b
SM
1737 ;; Until Emacs is multi-threaded, we do not actually need it local:
1738 (make-local-variable 'cperl-font-lock-multiline-start)
1739 (make-local-variable 'cperl-font-locking)
6c389151
SM
1740 (make-local-variable 'outline-regexp)
1741 ;; (setq outline-regexp imenu-example--function-name-regexp-perl)
1742 (setq outline-regexp cperl-outline-regexp)
1743 (make-local-variable 'outline-level)
1744 (setq outline-level 'cperl-outline-level)
f83d2997
KH
1745 (make-local-variable 'paragraph-start)
1746 (setq paragraph-start (concat "^$\\|" page-delimiter))
1747 (make-local-variable 'paragraph-separate)
1748 (setq paragraph-separate paragraph-start)
1749 (make-local-variable 'paragraph-ignore-fill-prefix)
1750 (setq paragraph-ignore-fill-prefix t)
6546555e 1751 (if (featurep 'xemacs)
4ab89e7b
SM
1752 (progn
1753 (make-local-variable 'paren-backwards-message)
1754 (set 'paren-backwards-message t)))
f83d2997
KH
1755 (make-local-variable 'indent-line-function)
1756 (setq indent-line-function 'cperl-indent-line)
1757 (make-local-variable 'require-final-newline)
7d441781 1758 (setq require-final-newline mode-require-final-newline)
f83d2997
KH
1759 (make-local-variable 'comment-start)
1760 (setq comment-start "# ")
1761 (make-local-variable 'comment-end)
1762 (setq comment-end "")
1763 (make-local-variable 'comment-column)
1764 (setq comment-column cperl-comment-column)
1765 (make-local-variable 'comment-start-skip)
1766 (setq comment-start-skip "#+ *")
1767 (make-local-variable 'defun-prompt-regexp)
4ab89e7b
SM
1768;;; "[ \t]*sub"
1769;;; (cperl-after-sub-regexp 'named nil) ; 8=name 11=proto 14=attr-start
1770;;; cperl-maybe-white-and-comment-rex ; 15=pre-block
1771 (setq defun-prompt-regexp
1772 (concat "^[ \t]*\\(sub"
1773 (cperl-after-sub-regexp 'named 'attr-groups)
1774 "\\|" ; per toke.c
1775 "\\(BEGIN\\|CHECK\\|INIT\\|END\\|AUTOLOAD\\|DESTROY\\)"
1776 "\\)"
1777 cperl-maybe-white-and-comment-rex))
f83d2997
KH
1778 (make-local-variable 'comment-indent-function)
1779 (setq comment-indent-function 'cperl-comment-indent)
4ab89e7b
SM
1780 (and (boundp 'fill-paragraph-function)
1781 (progn
1782 (make-local-variable 'fill-paragraph-function)
1783 (set 'fill-paragraph-function 'cperl-fill-paragraph)))
f83d2997
KH
1784 (make-local-variable 'parse-sexp-ignore-comments)
1785 (setq parse-sexp-ignore-comments t)
1786 (make-local-variable 'indent-region-function)
1787 (setq indent-region-function 'cperl-indent-region)
1788 ;;(setq auto-fill-function 'cperl-do-auto-fill) ; Need to switch on and off!
1789 (make-local-variable 'imenu-create-index-function)
1790 (setq imenu-create-index-function
80585273 1791 (function cperl-imenu--create-perl-index))
f83d2997
KH
1792 (make-local-variable 'imenu-sort-function)
1793 (setq imenu-sort-function nil)
e1a5828f
AS
1794 (make-local-variable 'vc-rcs-header)
1795 (set 'vc-rcs-header cperl-vc-rcs-header)
1796 (make-local-variable 'vc-sccs-header)
1797 (set 'vc-sccs-header cperl-vc-sccs-header)
67141a37
GM
1798 (when (featurep 'xemacs)
1799 ;; This one is obsolete...
1800 (make-local-variable 'vc-header-alist)
1801 (set 'vc-header-alist (or cperl-vc-header-alist ; Avoid warning
1802 `((SCCS ,(car cperl-vc-sccs-header))
1803 (RCS ,(car cperl-vc-rcs-header))))))
4ab89e7b
SM
1804 (cond ((boundp 'compilation-error-regexp-alist-alist);; xemacs 20.x
1805 (make-local-variable 'compilation-error-regexp-alist-alist)
1806 (set 'compilation-error-regexp-alist-alist
e9bfd3a3 1807 (cons (cons 'cperl (car cperl-compilation-error-regexp-alist))
4ab89e7b 1808 (symbol-value 'compilation-error-regexp-alist-alist)))
8c777c8d
CY
1809 (if (fboundp 'compilation-build-compilation-error-regexp-alist)
1810 (let ((f 'compilation-build-compilation-error-regexp-alist))
1811 (funcall f))
1812 (make-local-variable 'compilation-error-regexp-alist)
1813 (push 'cperl compilation-error-regexp-alist)))
ee7683eb 1814 ((boundp 'compilation-error-regexp-alist);; xemacs 19.x
4ab89e7b
SM
1815 (make-local-variable 'compilation-error-regexp-alist)
1816 (set 'compilation-error-regexp-alist
10715960
RS
1817 (append cperl-compilation-error-regexp-alist
1818 (symbol-value 'compilation-error-regexp-alist)))))
f83d2997
KH
1819 (make-local-variable 'font-lock-defaults)
1820 (setq font-lock-defaults
db133cb6
RS
1821 (cond
1822 ((string< emacs-version "19.30")
4ab89e7b 1823 '(cperl-font-lock-keywords-2 nil nil ((?_ . "w"))))
db133cb6 1824 ((string< emacs-version "19.33") ; Which one to use?
5efe6a56
SM
1825 '((cperl-font-lock-keywords
1826 cperl-font-lock-keywords-1
4ab89e7b 1827 cperl-font-lock-keywords-2) nil nil ((?_ . "w"))))
db133cb6
RS
1828 (t
1829 '((cperl-load-font-lock-keywords
1830 cperl-load-font-lock-keywords-1
4ab89e7b 1831 cperl-load-font-lock-keywords-2) nil nil ((?_ . "w"))))))
db133cb6 1832 (make-local-variable 'cperl-syntax-state)
4ab89e7b 1833 (setq cperl-syntax-state nil) ; reset syntaxification cache
f83d2997 1834 (if cperl-use-syntax-table-text-property
cf38dd42
SM
1835 (if (boundp 'syntax-propertize-function)
1836 (progn
1837 ;; Reset syntaxification cache.
1838 (set (make-local-variable 'cperl-syntax-done-to) nil)
1839 (set (make-local-variable 'syntax-propertize-function)
1840 (lambda (start end)
1841 (goto-char start) (cperl-fontify-syntaxically end))))
029cb4d5 1842 (make-local-variable 'parse-sexp-lookup-properties)
f83d2997 1843 ;; Do not introduce variable if not needed, we check it!
db133cb6
RS
1844 (set 'parse-sexp-lookup-properties t)
1845 ;; Fix broken font-lock:
1846 (or (boundp 'font-lock-unfontify-region-function)
1847 (set 'font-lock-unfontify-region-function
83261a2f 1848 'font-lock-default-unfontify-region))
6546555e 1849 (unless (featurep 'xemacs) ; Our: just a plug for wrong font-lock
4ab89e7b
SM
1850 (make-local-variable 'font-lock-unfontify-region-function)
1851 (set 'font-lock-unfontify-region-function ; not present with old Emacs
1852 'cperl-font-lock-unfontify-region-function))
029cb4d5 1853 (make-local-variable 'cperl-syntax-done-to)
4ab89e7b 1854 (setq cperl-syntax-done-to nil) ; reset syntaxification cache
029cb4d5 1855 (make-local-variable 'font-lock-syntactic-keywords)
5c8b7eaf 1856 (setq font-lock-syntactic-keywords
db133cb6 1857 (if cperl-syntaxify-by-font-lock
11b41e6f
SM
1858 '((cperl-fontify-syntaxically))
1859 ;; unless font-lock-syntactic-keywords, font-lock (pre-22.1)
1860 ;; used to ignore syntax-table text-properties. (t) is a hack
1861 ;; to make font-lock think that font-lock-syntactic-keywords
1862 ;; are defined.
db133cb6 1863 '(t)))))
4ab89e7b
SM
1864 (if (boundp 'font-lock-multiline) ; Newer font-lock; use its facilities
1865 (progn
1866 (setq cperl-font-lock-multiline t) ; Not localized...
f453f5a8 1867 (set (make-local-variable 'font-lock-multiline) t))
4ab89e7b
SM
1868 (make-local-variable 'font-lock-fontify-region-function)
1869 (set 'font-lock-fontify-region-function ; not present with old Emacs
1870 'cperl-font-lock-fontify-region-function))
1871 (make-local-variable 'font-lock-fontify-region-function)
1872 (set 'font-lock-fontify-region-function ; not present with old Emacs
1873 'cperl-font-lock-fontify-region-function)
db133cb6 1874 (make-local-variable 'cperl-old-style)
83261a2f
SM
1875 (if (boundp 'normal-auto-fill-function) ; 19.33 and later
1876 (set (make-local-variable 'normal-auto-fill-function)
4ab89e7b 1877 'cperl-do-auto-fill)
83261a2f
SM
1878 (or (fboundp 'cperl-old-auto-fill-mode)
1879 (progn
1880 (fset 'cperl-old-auto-fill-mode (symbol-function 'auto-fill-mode))
1881 (defun auto-fill-mode (&optional arg)
1882 (interactive "P")
1883 (eval '(cperl-old-auto-fill-mode arg)) ; Avoid a warning
1884 (and auto-fill-function (memq major-mode '(perl-mode cperl-mode))
1885 (setq auto-fill-function 'cperl-do-auto-fill))))))
f83d2997 1886 (if (cperl-enable-font-lock)
5c8b7eaf 1887 (if (cperl-val 'cperl-font-lock)
f83d2997
KH
1888 (progn (or cperl-faces-init (cperl-init-faces))
1889 (font-lock-mode 1))))
4ab89e7b
SM
1890 (set (make-local-variable 'facemenu-add-face-function)
1891 'cperl-facemenu-add-face-function) ; XXXX What this guy is for???
f83d2997
KH
1892 (and (boundp 'msb-menu-cond)
1893 (not cperl-msb-fixed)
1894 (cperl-msb-fix))
1895 (if (featurep 'easymenu)
46c72468 1896 (easy-menu-add cperl-menu)) ; A NOP in Emacs.
a3c328ee 1897 (run-mode-hooks 'cperl-mode-hook)
4ab89e7b 1898 (if cperl-hook-after-change
39234e39 1899 (add-hook 'after-change-functions 'cperl-after-change-function nil t))
f83d2997 1900 ;; After hooks since fontification will break this
5c8b7eaf 1901 (if cperl-pod-here-scan
83261a2f 1902 (or cperl-syntaxify-by-font-lock
5bd52f0e
RS
1903 (progn (or cperl-faces-init (cperl-init-faces-weak))
1904 (cperl-find-pods-heres)))))
f83d2997
KH
1905\f
1906;; Fix for perldb - make default reasonable
1907(defun cperl-db ()
1908 (interactive)
1909 (require 'gud)
1910 (perldb (read-from-minibuffer "Run perldb (like this): "
1911 (if (consp gud-perldb-history)
1912 (car gud-perldb-history)
1913 (concat "perl " ;;(file-name-nondirectory
83261a2f
SM
1914 ;; I have problems
1915 ;; in OS/2
1916 ;; otherwise
1917 (buffer-file-name)))
f83d2997
KH
1918 nil nil
1919 '(gud-perldb-history . 1))))
1920\f
f83d2997
KH
1921(defun cperl-msb-fix ()
1922 ;; Adds perl files to msb menu, supposes that msb is already loaded
1923 (setq cperl-msb-fixed t)
1924 (let* ((l (length msb-menu-cond))
1925 (last (nth (1- l) msb-menu-cond))
1926 (precdr (nthcdr (- l 2) msb-menu-cond)) ; cdr of this is last
1927 (handle (1- (nth 1 last))))
1928 (setcdr precdr (list
1929 (list
996e2616 1930 '(memq major-mode '(cperl-mode perl-mode))
f83d2997
KH
1931 handle
1932 "Perl Files (%d)")
1933 last))))
1934\f
1935;; This is used by indent-for-comment
1936;; to decide how much to indent a comment in CPerl code
1937;; based on its context. Do fallback if comment is found wrong.
1938
1939(defvar cperl-wrong-comment)
5bd52f0e
RS
1940(defvar cperl-st-cfence '(14)) ; Comment-fence
1941(defvar cperl-st-sfence '(15)) ; String-fence
1942(defvar cperl-st-punct '(1))
1943(defvar cperl-st-word '(2))
1944(defvar cperl-st-bra '(4 . ?\>))
1945(defvar cperl-st-ket '(5 . ?\<))
1946
f83d2997 1947
4ab89e7b 1948(defun cperl-comment-indent () ; called at point at supposed comment
5bd52f0e 1949 (let ((p (point)) (c (current-column)) was phony)
4ab89e7b
SM
1950 (if (and (not cperl-indent-comment-at-column-0)
1951 (looking-at "^#"))
1952 0 ; Existing comment at bol stays there.
f83d2997
KH
1953 ;; Wrong comment found
1954 (save-excursion
5bd52f0e
RS
1955 (setq was (cperl-to-comment-or-eol)
1956 phony (eq (get-text-property (point) 'syntax-table)
1957 cperl-st-cfence))
1958 (if phony
4ab89e7b 1959 (progn ; Too naive???
5bd52f0e
RS
1960 (re-search-forward "#\\|$") ; Hmm, what about embedded #?
1961 (if (eq (preceding-char) ?\#)
1962 (forward-char -1))
1963 (setq was nil)))
4ab89e7b 1964 (if (= (point) p) ; Our caller found a correct place
f83d2997
KH
1965 (progn
1966 (skip-chars-backward " \t")
4ab89e7b
SM
1967 (setq was (current-column))
1968 (if (eq was 0)
1969 comment-column
1970 (max (1+ was) ; Else indent at comment column
1971 comment-column)))
1972 ;; No, the caller found a random place; we need to edit ourselves
f83d2997
KH
1973 (if was nil
1974 (insert comment-start)
1975 (backward-char (length comment-start)))
1976 (setq cperl-wrong-comment t)
4ab89e7b
SM
1977 (cperl-make-indent comment-column 1) ; Indent min 1
1978 c)))))
f83d2997
KH
1979
1980;;;(defun cperl-comment-indent-fallback ()
1981;;; "Is called if the standard comment-search procedure fails.
1982;;;Point is at start of real comment."
1983;;; (let ((c (current-column)) target cnt prevc)
1984;;; (if (= c comment-column) nil
1985;;; (setq cnt (skip-chars-backward "[ \t]"))
5c8b7eaf 1986;;; (setq target (max (1+ (setq prevc
f83d2997
KH
1987;;; (current-column))) ; Else indent at comment column
1988;;; comment-column))
1989;;; (if (= c comment-column) nil
1990;;; (delete-backward-char cnt)
1991;;; (while (< prevc target)
1992;;; (insert "\t")
1993;;; (setq prevc (current-column)))
1994;;; (if (> prevc target) (progn (delete-char -1) (setq prevc (current-column))))
1995;;; (while (< prevc target)
1996;;; (insert " ")
1997;;; (setq prevc (current-column)))))))
1998
1999(defun cperl-indent-for-comment ()
2000 "Substitute for `indent-for-comment' in CPerl."
2001 (interactive)
2002 (let (cperl-wrong-comment)
2003 (indent-for-comment)
4ab89e7b 2004 (if cperl-wrong-comment ; set by `cperl-comment-indent'
f83d2997
KH
2005 (progn (cperl-to-comment-or-eol)
2006 (forward-char (length comment-start))))))
2007
2008(defun cperl-comment-region (b e arg)
2009 "Comment or uncomment each line in the region in CPerl mode.
2010See `comment-region'."
2011 (interactive "r\np")
2012 (let ((comment-start "#"))
2013 (comment-region b e arg)))
2014
2015(defun cperl-uncomment-region (b e arg)
2016 "Uncomment or comment each line in the region in CPerl mode.
2017See `comment-region'."
2018 (interactive "r\np")
2019 (let ((comment-start "#"))
2020 (comment-region b e (- arg))))
2021
2022(defvar cperl-brace-recursing nil)
2023
2024(defun cperl-electric-brace (arg &optional only-before)
2025 "Insert character and correct line's indentation.
2026If ONLY-BEFORE and `cperl-auto-newline', will insert newline before the
2027place (even in empty line), but not after. If after \")\" and the inserted
5c8b7eaf 2028char is \"{\", insert extra newline before only if
f83d2997
KH
2029`cperl-extra-newline-before-brace'."
2030 (interactive "P")
2031 (let (insertpos
2032 (other-end (if (and cperl-electric-parens-mark
5c8b7eaf 2033 (cperl-mark-active)
f83d2997 2034 (< (mark) (point)))
5c8b7eaf 2035 (mark)
f83d2997
KH
2036 nil)))
2037 (if (and other-end
2038 (not cperl-brace-recursing)
2039 (cperl-val 'cperl-electric-parens)
2040 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point)))
2041 ;; Need to insert a matching pair
2042 (progn
2043 (save-excursion
2044 (setq insertpos (point-marker))
2045 (goto-char other-end)
1ba983e8 2046 (setq last-command-event ?\{)
f83d2997
KH
2047 (cperl-electric-lbrace arg insertpos))
2048 (forward-char 1))
83261a2f 2049 ;; Check whether we close something "usual" with `}'
1ba983e8 2050 (if (and (eq last-command-event ?\})
5c8b7eaf 2051 (not
db133cb6
RS
2052 (condition-case nil
2053 (save-excursion
2054 (up-list (- (prefix-numeric-value arg)))
2055 ;;(cperl-after-block-p (point-min))
f739b53b
SM
2056 (or (cperl-after-expr-p nil "{;)")
2057 ;; after sub, else, continue
2058 (cperl-after-block-p nil 'pre)))
db133cb6
RS
2059 (error nil))))
2060 ;; Just insert the guy
2061 (self-insert-command (prefix-numeric-value arg))
2062 (if (and (not arg) ; No args, end (of empty line or auto)
2063 (eolp)
2064 (or (and (null only-before)
2065 (save-excursion
2066 (skip-chars-backward " \t")
2067 (bolp)))
1ba983e8 2068 (and (eq last-command-event ?\{) ; Do not insert newline
db133cb6
RS
2069 ;; if after ")" and `cperl-extra-newline-before-brace'
2070 ;; is nil, do not insert extra newline.
2071 (not cperl-extra-newline-before-brace)
2072 (save-excursion
2073 (skip-chars-backward " \t")
2074 (eq (preceding-char) ?\))))
5c8b7eaf 2075 (if cperl-auto-newline
db133cb6
RS
2076 (progn (cperl-indent-line) (newline) t) nil)))
2077 (progn
2078 (self-insert-command (prefix-numeric-value arg))
2079 (cperl-indent-line)
2080 (if cperl-auto-newline
2081 (setq insertpos (1- (point))))
2082 (if (and cperl-auto-newline (null only-before))
2083 (progn
2084 (newline)
2085 (cperl-indent-line)))
2086 (save-excursion
2087 (if insertpos (progn (goto-char insertpos)
5c8b7eaf 2088 (search-forward (make-string
1ba983e8 2089 1 last-command-event))
db133cb6
RS
2090 (setq insertpos (1- (point)))))
2091 (delete-char -1))))
2092 (if insertpos
f83d2997 2093 (save-excursion
db133cb6
RS
2094 (goto-char insertpos)
2095 (self-insert-command (prefix-numeric-value arg)))
2096 (self-insert-command (prefix-numeric-value arg)))))))
f83d2997
KH
2097
2098(defun cperl-electric-lbrace (arg &optional end)
2099 "Insert character, correct line's indentation, correct quoting by space."
2100 (interactive "P")
83261a2f
SM
2101 (let ((cperl-brace-recursing t)
2102 (cperl-auto-newline cperl-auto-newline)
2103 (other-end (or end
2104 (if (and cperl-electric-parens-mark
2105 (cperl-mark-active)
2106 (> (mark) (point)))
2107 (save-excursion
2108 (goto-char (mark))
2109 (point-marker))
2110 nil)))
2111 pos after)
f83d2997
KH
2112 (and (cperl-val 'cperl-electric-lbrace-space)
2113 (eq (preceding-char) ?$)
2114 (save-excursion
2115 (skip-chars-backward "$")
2116 (looking-at "\\(\\$\\$\\)*\\$\\([^\\$]\\|$\\)"))
b5b0cb34 2117 (insert ?\s))
bab27c0c 2118 ;; Check whether we are in comment
5c8b7eaf 2119 (if (and
bab27c0c
RS
2120 (save-excursion
2121 (beginning-of-line)
2122 (not (looking-at "[ \t]*#")))
2123 (cperl-after-expr-p nil "{;)"))
2124 nil
2125 (setq cperl-auto-newline nil))
f83d2997
KH
2126 (cperl-electric-brace arg)
2127 (and (cperl-val 'cperl-electric-parens)
1ba983e8
GM
2128 (eq last-command-event ?{)
2129 (memq last-command-event
f83d2997
KH
2130 (append cperl-electric-parens-string nil))
2131 (or (if other-end (goto-char (marker-position other-end)))
2132 t)
1ba983e8 2133 (setq last-command-event ?} pos (point))
f83d2997
KH
2134 (progn (cperl-electric-brace arg t)
2135 (goto-char pos)))))
2136
2137(defun cperl-electric-paren (arg)
f739b53b
SM
2138 "Insert an opening parenthesis or a matching pair of parentheses.
2139See `cperl-electric-parens'."
f83d2997 2140 (interactive "P")
e180ab9f 2141 (let ((beg (point-at-bol))
f83d2997 2142 (other-end (if (and cperl-electric-parens-mark
5c8b7eaf 2143 (cperl-mark-active)
f83d2997 2144 (> (mark) (point)))
83261a2f
SM
2145 (save-excursion
2146 (goto-char (mark))
2147 (point-marker))
f83d2997
KH
2148 nil)))
2149 (if (and (cperl-val 'cperl-electric-parens)
1ba983e8 2150 (memq last-command-event
f83d2997
KH
2151 (append cperl-electric-parens-string nil))
2152 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
2153 ;;(not (save-excursion (search-backward "#" beg t)))
1ba983e8 2154 (if (eq last-command-event ?<)
f83d2997 2155 (progn
7a55c78b
CY
2156 ;; This code is too electric, see Bug#3943.
2157 ;; (and abbrev-mode ; later it is too late, may be after `for'
2158 ;; (expand-abbrev))
f83d2997
KH
2159 (cperl-after-expr-p nil "{;(,:="))
2160 1))
2161 (progn
2162 (self-insert-command (prefix-numeric-value arg))
2163 (if other-end (goto-char (marker-position other-end)))
5c8b7eaf 2164 (insert (make-string
f83d2997 2165 (prefix-numeric-value arg)
1ba983e8 2166 (cdr (assoc last-command-event '((?{ .?})
f83d2997
KH
2167 (?[ . ?])
2168 (?( . ?))
2169 (?< . ?>))))))
2170 (forward-char (- (prefix-numeric-value arg))))
2171 (self-insert-command (prefix-numeric-value arg)))))
2172
2173(defun cperl-electric-rparen (arg)
2174 "Insert a matching pair of parentheses if marking is active.
f739b53b
SM
2175If not, or if we are not at the end of marking range, would self-insert.
2176Affected by `cperl-electric-parens'."
f83d2997 2177 (interactive "P")
e180ab9f 2178 (let ((beg (point-at-bol))
f83d2997
KH
2179 (other-end (if (and cperl-electric-parens-mark
2180 (cperl-val 'cperl-electric-parens)
1ba983e8 2181 (memq last-command-event
f83d2997 2182 (append cperl-electric-parens-string nil))
5c8b7eaf 2183 (cperl-mark-active)
f83d2997 2184 (< (mark) (point)))
5c8b7eaf 2185 (mark)
f83d2997
KH
2186 nil))
2187 p)
2188 (if (and other-end
2189 (cperl-val 'cperl-electric-parens)
1ba983e8 2190 (memq last-command-event '( ?\) ?\] ?\} ?\> ))
f83d2997
KH
2191 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
2192 ;;(not (save-excursion (search-backward "#" beg t)))
2193 )
2194 (progn
2195 (self-insert-command (prefix-numeric-value arg))
2196 (setq p (point))
2197 (if other-end (goto-char other-end))
2198 (insert (make-string
2199 (prefix-numeric-value arg)
1ba983e8 2200 (cdr (assoc last-command-event '((?\} . ?\{)
83261a2f
SM
2201 (?\] . ?\[)
2202 (?\) . ?\()
2203 (?\> . ?\<))))))
f83d2997
KH
2204 (goto-char (1+ p)))
2205 (self-insert-command (prefix-numeric-value arg)))))
2206
2207(defun cperl-electric-keyword ()
db133cb6
RS
2208 "Insert a construction appropriate after a keyword.
2209Help message may be switched off by setting `cperl-message-electric-keyword'
2210to nil."
e180ab9f 2211 (let ((beg (point-at-bol))
1ba983e8 2212 (dollar (and (eq last-command-event ?$)
f83d2997 2213 (eq this-command 'self-insert-command)))
1ba983e8 2214 (delete (and (memq last-command-event '(?\s ?\n ?\t ?\f))
db133cb6
RS
2215 (memq this-command '(self-insert-command newline))))
2216 my do)
f83d2997 2217 (and (save-excursion
db133cb6
RS
2218 (condition-case nil
2219 (progn
2220 (backward-sexp 1)
2221 (setq do (looking-at "do\\>")))
2222 (error nil))
f83d2997 2223 (cperl-after-expr-p nil "{;:"))
5c8b7eaf
SS
2224 (save-excursion
2225 (not
f83d2997 2226 (re-search-backward
5bd52f0e 2227 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
f83d2997
KH
2228 beg t)))
2229 (save-excursion (or (not (re-search-backward "^=" nil t))
db133cb6
RS
2230 (or
2231 (looking-at "=cut")
2232 (and cperl-use-syntax-table-text-property
2233 (not (eq (get-text-property (point)
2234 'syntax-type)
2235 'pod))))))
f739b53b
SM
2236 (save-excursion (forward-sexp -1)
2237 (not (memq (following-char) (append "$@%&*" nil))))
f83d2997 2238 (progn
db133cb6
RS
2239 (and (eq (preceding-char) ?y)
2240 (progn ; "foreachmy"
2241 (forward-char -2)
2242 (insert " ")
2243 (forward-char 2)
5c8b7eaf
SS
2244 (setq my t dollar t
2245 delete
db133cb6 2246 (memq this-command '(self-insert-command newline)))))
f83d2997
KH
2247 (and dollar (insert " $"))
2248 (cperl-indent-line)
2249 ;;(insert " () {\n}")
2250 (cond
2251 (cperl-extra-newline-before-brace
db133cb6 2252 (insert (if do "\n" " ()\n"))
f83d2997
KH
2253 (insert "{")
2254 (cperl-indent-line)
2255 (insert "\n")
2256 (cperl-indent-line)
db133cb6
RS
2257 (insert "\n}")
2258 (and do (insert " while ();")))
f83d2997 2259 (t
83261a2f 2260 (insert (if do " {\n} while ();" " () {\n}"))))
f83d2997
KH
2261 (or (looking-at "[ \t]\\|$") (insert " "))
2262 (cperl-indent-line)
2263 (if dollar (progn (search-backward "$")
5c8b7eaf 2264 (if my
db133cb6
RS
2265 (forward-char 1)
2266 (delete-char 1)))
f739b53b 2267 (search-backward ")")
1ba983e8 2268 (if (eq last-command-event ?\()
f739b53b
SM
2269 (progn ; Avoid "if (())"
2270 (delete-backward-char 1)
2271 (delete-backward-char -1))))
f83d2997 2272 (if delete
db133cb6
RS
2273 (cperl-putback-char cperl-del-back-ch))
2274 (if cperl-message-electric-keyword
2275 (message "Precede char by C-q to avoid expansion"))))))
2276
2277(defun cperl-ensure-newlines (n &optional pos)
2278 "Make sure there are N newlines after the point."
2279 (or pos (setq pos (point)))
2280 (if (looking-at "\n")
2281 (forward-char 1)
2282 (insert "\n"))
2283 (if (> n 1)
2284 (cperl-ensure-newlines (1- n) pos)
2285 (goto-char pos)))
2286
2287(defun cperl-electric-pod ()
2288 "Insert a POD chunk appropriate after a =POD directive."
1ba983e8 2289 (let ((delete (and (memq last-command-event '(?\s ?\n ?\t ?\f))
db133cb6
RS
2290 (memq this-command '(self-insert-command newline))))
2291 head1 notlast name p really-delete over)
2292 (and (save-excursion
6c389151 2293 (forward-word -1)
a1506d29 2294 (and
db133cb6
RS
2295 (eq (preceding-char) ?=)
2296 (progn
6c389151
SM
2297 (setq head1 (looking-at "head1\\>[ \t]*$"))
2298 (setq over (and (looking-at "over\\>[ \t]*$")
2299 (not (looking-at "over[ \t]*\n\n\n*=item\\>"))))
db133cb6
RS
2300 (forward-char -1)
2301 (bolp))
5c8b7eaf 2302 (or
5bd52f0e 2303 (get-text-property (point) 'in-pod)
db133cb6 2304 (cperl-after-expr-p nil "{;:")
4ab89e7b
SM
2305 (and (re-search-backward "\\(\\`\n?\\|^\n\\)=\\sw+" (point-min) t)
2306 (not (looking-at "\n*=cut"))
2307 (or (not cperl-use-syntax-table-text-property)
2308 (eq (get-text-property (point) 'syntax-type) 'pod))))))
db133cb6
RS
2309 (progn
2310 (save-excursion
6c389151 2311 (setq notlast (re-search-forward "^\n=" nil t)))
db133cb6
RS
2312 (or notlast
2313 (progn
2314 (insert "\n\n=cut")
2315 (cperl-ensure-newlines 2)
6c389151 2316 (forward-word -2)
a1506d29
JB
2317 (if (and head1
2318 (not
db133cb6
RS
2319 (save-excursion
2320 (forward-char -1)
2321 (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\>"
83261a2f 2322 nil t)))) ; Only one
a1506d29 2323 (progn
6c389151 2324 (forward-word 1)
db133cb6
RS
2325 (setq name (file-name-sans-extension
2326 (file-name-nondirectory (buffer-file-name)))
2327 p (point))
5c8b7eaf 2328 (insert " NAME\n\n" name
029cb4d5 2329 " - \n\n=head1 SYNOPSIS\n\n\n\n"
db133cb6
RS
2330 "=head1 DESCRIPTION")
2331 (cperl-ensure-newlines 4)
2332 (goto-char p)
6c389151 2333 (forward-word 2)
db133cb6
RS
2334 (end-of-line)
2335 (setq really-delete t))
6c389151 2336 (forward-word 1))))
db133cb6
RS
2337 (if over
2338 (progn
2339 (setq p (point))
2340 (insert "\n\n=item \n\n\n\n"
2341 "=back")
2342 (cperl-ensure-newlines 2)
2343 (goto-char p)
6c389151 2344 (forward-word 1)
db133cb6
RS
2345 (end-of-line)
2346 (setq really-delete t)))
2347 (if (and delete really-delete)
f83d2997
KH
2348 (cperl-putback-char cperl-del-back-ch))))))
2349
2350(defun cperl-electric-else ()
db133cb6
RS
2351 "Insert a construction appropriate after a keyword.
2352Help message may be switched off by setting `cperl-message-electric-keyword'
2353to nil."
e180ab9f 2354 (let ((beg (point-at-bol)))
f83d2997
KH
2355 (and (save-excursion
2356 (backward-sexp 1)
2357 (cperl-after-expr-p nil "{;:"))
5c8b7eaf
SS
2358 (save-excursion
2359 (not
f83d2997 2360 (re-search-backward
5bd52f0e 2361 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
f83d2997
KH
2362 beg t)))
2363 (save-excursion (or (not (re-search-backward "^=" nil t))
db133cb6
RS
2364 (looking-at "=cut")
2365 (and cperl-use-syntax-table-text-property
2366 (not (eq (get-text-property (point)
2367 'syntax-type)
2368 'pod)))))
f83d2997
KH
2369 (progn
2370 (cperl-indent-line)
2371 ;;(insert " {\n\n}")
2372 (cond
2373 (cperl-extra-newline-before-brace
2374 (insert "\n")
2375 (insert "{")
2376 (cperl-indent-line)
2377 (insert "\n\n}"))
2378 (t
83261a2f 2379 (insert " {\n\n}")))
f83d2997
KH
2380 (or (looking-at "[ \t]\\|$") (insert " "))
2381 (cperl-indent-line)
2382 (forward-line -1)
2383 (cperl-indent-line)
db133cb6
RS
2384 (cperl-putback-char cperl-del-back-ch)
2385 (setq this-command 'cperl-electric-else)
2386 (if cperl-message-electric-keyword
2387 (message "Precede char by C-q to avoid expansion"))))))
f83d2997
KH
2388
2389(defun cperl-linefeed ()
db133cb6
RS
2390 "Go to end of line, open a new line and indent appropriately.
2391If in POD, insert appropriate lines."
f83d2997 2392 (interactive)
e180ab9f
GM
2393 (let ((beg (point-at-bol))
2394 (end (point-at-eol))
db133cb6 2395 (pos (point)) start over cut res)
f83d2997 2396 (if (and ; Check if we need to split:
5c8b7eaf 2397 ; i.e., on a boundary and inside "{...}"
f83d2997 2398 (save-excursion (cperl-to-comment-or-eol)
83261a2f 2399 (>= (point) pos)) ; Not in a comment
f83d2997
KH
2400 (or (save-excursion
2401 (skip-chars-backward " \t" beg)
2402 (forward-char -1)
2403 (looking-at "[;{]")) ; After { or ; + spaces
2404 (looking-at "[ \t]*}") ; Before }
2405 (re-search-forward "\\=[ \t]*;" end t)) ; Before spaces + ;
2406 (save-excursion
2407 (and
5c8b7eaf 2408 (eq (car (parse-partial-sexp pos end -1)) -1)
f83d2997
KH
2409 ; Leave the level of parens
2410 (looking-at "[,; \t]*\\($\\|#\\)") ; Comma to allow anon subr
2411 ; Are at end
6c389151 2412 (cperl-after-block-p (point-min))
f83d2997
KH
2413 (progn
2414 (backward-sexp 1)
2415 (setq start (point-marker))
db133cb6 2416 (<= start pos))))) ; Redundant? Are after the
f83d2997
KH
2417 ; start of parens group.
2418 (progn
2419 (skip-chars-backward " \t")
2420 (or (memq (preceding-char) (append ";{" nil))
2421 (insert ";"))
2422 (insert "\n")
2423 (forward-line -1)
2424 (cperl-indent-line)
2425 (goto-char start)
2426 (or (looking-at "{[ \t]*$") ; If there is a statement
2427 ; before, move it to separate line
2428 (progn
2429 (forward-char 1)
2430 (insert "\n")
2431 (cperl-indent-line)))
2432 (forward-line 1) ; We are on the target line
2433 (cperl-indent-line)
2434 (beginning-of-line)
2435 (or (looking-at "[ \t]*}[,; \t]*$") ; If there is a statement
83261a2f 2436 ; after, move it to separate line
f83d2997
KH
2437 (progn
2438 (end-of-line)
2439 (search-backward "}" beg)
2440 (skip-chars-backward " \t")
2441 (or (memq (preceding-char) (append ";{" nil))
2442 (insert ";"))
2443 (insert "\n")
2444 (cperl-indent-line)
2445 (forward-line -1)))
5c8b7eaf 2446 (forward-line -1) ; We are on the line before target
f83d2997
KH
2447 (end-of-line)
2448 (newline-and-indent))
db133cb6 2449 (end-of-line) ; else - no splitting
f83d2997
KH
2450 (cond
2451 ((and (looking-at "\n[ \t]*{$")
2452 (save-excursion
2453 (skip-chars-backward " \t")
2454 (eq (preceding-char) ?\)))) ; Probably if () {} group
83261a2f 2455 ; with an extra newline.
f83d2997
KH
2456 (forward-line 2)
2457 (cperl-indent-line))
db133cb6
RS
2458 ((save-excursion ; In POD header
2459 (forward-paragraph -1)
2460 ;; (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\b")
2461 ;; We are after \n now, so look for the rest
2462 (if (looking-at "\\(\\`\n?\\|\n\\)=\\sw+")
5c8b7eaf 2463 (progn
db133cb6
RS
2464 (setq cut (looking-at "\\(\\`\n?\\|\n\\)=cut\\>"))
2465 (setq over (looking-at "\\(\\`\n?\\|\n\\)=over\\>"))
2466 t)))
2467 (if (and over
2468 (progn
2469 (forward-paragraph -1)
2470 (forward-word 1)
2471 (setq pos (point))
e180ab9f
GM
2472 (setq cut (buffer-substring (point) (point-at-eol)))
2473 (delete-char (- (point-at-eol) (point)))
db133cb6
RS
2474 (setq res (expand-abbrev))
2475 (save-excursion
2476 (goto-char pos)
2477 (insert cut))
2478 res))
2479 nil
2480 (cperl-ensure-newlines (if cut 2 4))
2481 (forward-line 2)))
2482 ((get-text-property (point) 'in-pod) ; In POD section
2483 (cperl-ensure-newlines 4)
2484 (forward-line 2))
f83d2997
KH
2485 ((looking-at "\n[ \t]*$") ; Next line is empty - use it.
2486 (forward-line 1)
2487 (cperl-indent-line))
2488 (t
2489 (newline-and-indent))))))
2490
2491(defun cperl-electric-semi (arg)
2492 "Insert character and correct line's indentation."
2493 (interactive "P")
2494 (if cperl-auto-newline
2495 (cperl-electric-terminator arg)
6c389151
SM
2496 (self-insert-command (prefix-numeric-value arg))
2497 (if cperl-autoindent-on-semi
2498 (cperl-indent-line))))
f83d2997
KH
2499
2500(defun cperl-electric-terminator (arg)
2501 "Insert character and correct line's indentation."
2502 (interactive "P")
83261a2f
SM
2503 (let ((end (point))
2504 (auto (and cperl-auto-newline
1ba983e8 2505 (or (not (eq last-command-event ?:))
83261a2f
SM
2506 cperl-auto-newline-after-colon)))
2507 insertpos)
5c8b7eaf 2508 (if (and ;;(not arg)
f83d2997
KH
2509 (eolp)
2510 (not (save-excursion
2511 (beginning-of-line)
2512 (skip-chars-forward " \t")
2513 (or
2514 ;; Ignore in comment lines
2515 (= (following-char) ?#)
2516 ;; Colon is special only after a label
2517 ;; So quickly rule out most other uses of colon
2518 ;; and do no indentation for them.
1ba983e8 2519 (and (eq last-command-event ?:)
f83d2997
KH
2520 (save-excursion
2521 (forward-word 1)
2522 (skip-chars-forward " \t")
2523 (and (< (point) end)
2524 (progn (goto-char (- end 1))
2525 (not (looking-at ":"))))))
2526 (progn
2527 (beginning-of-defun)
2528 (let ((pps (parse-partial-sexp (point) end)))
2529 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
2530 (progn
2531 (self-insert-command (prefix-numeric-value arg))
2532 ;;(forward-char -1)
2533 (if auto (setq insertpos (point-marker)))
2534 ;;(forward-char 1)
2535 (cperl-indent-line)
2536 (if auto
2537 (progn
2538 (newline)
2539 (cperl-indent-line)))
f83d2997
KH
2540 (save-excursion
2541 (if insertpos (goto-char (1- (marker-position insertpos)))
2542 (forward-char -1))
2543 (delete-char 1))))
2544 (if insertpos
2545 (save-excursion
2546 (goto-char insertpos)
2547 (self-insert-command (prefix-numeric-value arg)))
2548 (self-insert-command (prefix-numeric-value arg)))))
2549
2550(defun cperl-electric-backspace (arg)
8c777c8d
CY
2551 "Backspace, or remove whitespace around the point inserted by an electric key.
2552Will untabify if `cperl-electric-backspace-untabify' is non-nil."
f83d2997 2553 (interactive "p")
5c8b7eaf
SS
2554 (if (and cperl-auto-newline
2555 (memq last-command '(cperl-electric-semi
f83d2997
KH
2556 cperl-electric-terminator
2557 cperl-electric-lbrace))
b5b0cb34 2558 (memq (preceding-char) '(?\s ?\t ?\n)))
f83d2997 2559 (let (p)
5c8b7eaf 2560 (if (eq last-command 'cperl-electric-lbrace)
f83d2997
KH
2561 (skip-chars-forward " \t\n"))
2562 (setq p (point))
2563 (skip-chars-backward " \t\n")
2564 (delete-region (point) p))
db133cb6
RS
2565 (and (eq last-command 'cperl-electric-else)
2566 ;; We are removing the whitespace *inside* cperl-electric-else
2567 (setq this-command 'cperl-electric-else-really))
5c8b7eaf 2568 (if (and cperl-auto-newline
db133cb6 2569 (eq last-command 'cperl-electric-else-really)
b5b0cb34 2570 (memq (preceding-char) '(?\s ?\t ?\n)))
db133cb6
RS
2571 (let (p)
2572 (skip-chars-forward " \t\n")
2573 (setq p (point))
2574 (skip-chars-backward " \t\n")
2575 (delete-region (point) p))
f739b53b
SM
2576 (if cperl-electric-backspace-untabify
2577 (backward-delete-char-untabify arg)
2578 (delete-backward-char arg)))))
f83d2997 2579
d6156ce8
KS
2580(put 'cperl-electric-backspace 'delete-selection 'supersede)
2581
4ab89e7b 2582(defun cperl-inside-parens-p () ;; NOT USED????
f83d2997
KH
2583 (condition-case ()
2584 (save-excursion
2585 (save-restriction
2586 (narrow-to-region (point)
2587 (progn (beginning-of-defun) (point)))
2588 (goto-char (point-max))
2589 (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
2590 (error nil)))
2591\f
2592(defun cperl-indent-command (&optional whole-exp)
2593 "Indent current line as Perl code, or in some cases insert a tab character.
5c8b7eaf 2594If `cperl-tab-always-indent' is non-nil (the default), always indent current
db133cb6 2595line. Otherwise, indent the current line only if point is at the left margin
f83d2997
KH
2596or in the line's indentation; otherwise insert a tab.
2597
2598A numeric argument, regardless of its value,
2599means indent rigidly all the lines of the expression starting after point
2600so that this line becomes properly indented.
2601The relative indentation among the lines of the expression are preserved."
2602 (interactive "P")
5bd52f0e 2603 (cperl-update-syntaxification (point) (point))
f83d2997
KH
2604 (if whole-exp
2605 ;; If arg, always indent this line as Perl
2606 ;; and shift remaining lines of expression the same amount.
2607 (let ((shift-amt (cperl-indent-line))
2608 beg end)
2609 (save-excursion
2610 (if cperl-tab-always-indent
2611 (beginning-of-line))
2612 (setq beg (point))
2613 (forward-sexp 1)
2614 (setq end (point))
2615 (goto-char beg)
2616 (forward-line 1)
2617 (setq beg (point)))
db133cb6 2618 (if (and shift-amt (> end beg))
f83d2997
KH
2619 (indent-code-rigidly beg end shift-amt "#")))
2620 (if (and (not cperl-tab-always-indent)
2621 (save-excursion
2622 (skip-chars-backward " \t")
2623 (not (bolp))))
2624 (insert-tab)
2625 (cperl-indent-line))))
2626
5bd52f0e 2627(defun cperl-indent-line (&optional parse-data)
f83d2997
KH
2628 "Indent current line as Perl code.
2629Return the amount the indentation changed by."
83261a2f
SM
2630 (let ((case-fold-search nil)
2631 (pos (- (point-max) (point)))
2632 indent i beg shift-amt)
5bd52f0e 2633 (setq indent (cperl-calculate-indent parse-data)
db133cb6 2634 i indent)
f83d2997
KH
2635 (beginning-of-line)
2636 (setq beg (point))
2637 (cond ((or (eq indent nil) (eq indent t))
db133cb6 2638 (setq indent (current-indentation) i nil))
f83d2997
KH
2639 ;;((eq indent t) ; Never?
2640 ;; (setq indent (cperl-calculate-indent-within-comment)))
2641 ;;((looking-at "[ \t]*#")
2642 ;; (setq indent 0))
2643 (t
2644 (skip-chars-forward " \t")
2645 (if (listp indent) (setq indent (car indent)))
82d9a08d
SM
2646 (cond ((and (looking-at "[A-Za-z_][A-Za-z_0-9]*:[^:]")
2647 (not (looking-at "[smy]:\\|tr:")))
f83d2997
KH
2648 (and (> indent 0)
2649 (setq indent (max cperl-min-label-indent
2650 (+ indent cperl-label-offset)))))
2651 ((= (following-char) ?})
2652 (setq indent (- indent cperl-indent-level)))
2653 ((memq (following-char) '(?\) ?\])) ; To line up with opening paren.
2654 (setq indent (+ indent cperl-close-paren-offset)))
2655 ((= (following-char) ?{)
2656 (setq indent (+ indent cperl-brace-offset))))))
2657 (skip-chars-forward " \t")
db133cb6
RS
2658 (setq shift-amt (and i (- indent (current-column))))
2659 (if (or (not shift-amt)
2660 (zerop shift-amt))
f83d2997
KH
2661 (if (> (- (point-max) pos) (point))
2662 (goto-char (- (point-max) pos)))
4ab89e7b
SM
2663 ;;;(delete-region beg (point))
2664 ;;;(indent-to indent)
2665 (cperl-make-indent indent)
f83d2997
KH
2666 ;; If initial point was within line's indentation,
2667 ;; position after the indentation. Else stay at same point in text.
2668 (if (> (- (point-max) pos) (point))
2669 (goto-char (- (point-max) pos))))
2670 shift-amt))
2671
2672(defun cperl-after-label ()
2673 ;; Returns true if the point is after label. Does not do save-excursion.
2674 (and (eq (preceding-char) ?:)
2675 (memq (char-syntax (char-after (- (point) 2)))
2676 '(?w ?_))
2677 (progn
2678 (backward-sexp)
2679 (looking-at "[a-zA-Z_][a-zA-Z0-9_]*:[^:]"))))
2680
2681(defun cperl-get-state (&optional parse-start start-state)
5bd52f0e
RS
2682 ;; returns list (START STATE DEPTH PRESTART),
2683 ;; START is a good place to start parsing, or equal to
5c8b7eaf 2684 ;; PARSE-START if preset,
5bd52f0e
RS
2685 ;; STATE is what is returned by `parse-partial-sexp'.
2686 ;; DEPTH is true is we are immediately after end of block
2687 ;; which contains START.
2688 ;; PRESTART is the position basing on which START was found.
f83d2997
KH
2689 (save-excursion
2690 (let ((start-point (point)) depth state start prestart)
5bd52f0e
RS
2691 (if (and parse-start
2692 (<= parse-start start-point))
f83d2997 2693 (goto-char parse-start)
5bd52f0e
RS
2694 (beginning-of-defun)
2695 (setq start-state nil))
f83d2997
KH
2696 (setq prestart (point))
2697 (if start-state nil
2698 ;; Try to go out, if sub is not on the outermost level
2699 (while (< (point) start-point)
2700 (setq start (point) parse-start start depth nil
2701 state (parse-partial-sexp start start-point -1))
2702 (if (> (car state) -1) nil
2703 ;; The current line could start like }}}, so the indentation
2704 ;; corresponds to a different level than what we reached
2705 (setq depth t)
2706 (beginning-of-line 2))) ; Go to the next line.
2707 (if start (goto-char start))) ; Not at the start of file
2708 (setq start (point))
f83d2997
KH
2709 (or state (setq state (parse-partial-sexp start start-point -1 nil start-state)))
2710 (list start state depth prestart))))
2711
f83d2997
KH
2712(defvar cperl-look-for-prop '((pod in-pod) (here-doc-delim here-doc-group)))
2713
4ab89e7b
SM
2714(defun cperl-beginning-of-property (p prop &optional lim)
2715 "Given that P has a property PROP, find where the property starts.
2716Will not look before LIM."
2717 ;;; XXXX What to do at point-max???
2718 (or (previous-single-property-change (cperl-1+ p) prop lim)
2719 (point-min))
2720;;; (cond ((eq p (point-min))
2721;;; p)
2722;;; ((and lim (<= p lim))
2723;;; p)
2724;;; ((not (get-text-property (1- p) prop))
2725;;; p)
2726;;; (t (or (previous-single-property-change p look-prop lim)
2727;;; (point-min))))
2728 )
2729
2730(defun cperl-sniff-for-indent (&optional parse-data) ; was parse-start
8c777c8d 2731 ;; the sniffer logic to understand what the current line MEANS.
f739b53b 2732 (cperl-update-syntaxification (point) (point))
4ab89e7b
SM
2733 (let ((res (get-text-property (point) 'syntax-type)))
2734 (save-excursion
2735 (cond
2736 ((and (memq res '(pod here-doc here-doc-delim format))
2737 (not (get-text-property (point) 'indentable)))
2738 (vector res))
2739 ;; before start of POD - whitespace found since do not have 'pod!
2740 ((looking-at "[ \t]*\n=")
2741 (error "Spaces before POD section!"))
2742 ((and (not cperl-indent-left-aligned-comments)
2743 (looking-at "^#"))
2744 [comment-special:at-beginning-of-line])
2745 ((get-text-property (point) 'in-pod)
2746 [in-pod])
2747 (t
2748 (beginning-of-line)
2749 (let* ((indent-point (point))
2750 (char-after-pos (save-excursion
2751 (skip-chars-forward " \t")
2752 (point)))
2753 (char-after (char-after char-after-pos))
2754 (pre-indent-point (point))
2755 p prop look-prop is-block delim)
2756 (save-excursion ; Know we are not in POD, find appropriate pos before
83261a2f
SM
2757 (cperl-backward-to-noncomment nil)
2758 (setq p (max (point-min) (1- (point)))
2759 prop (get-text-property p 'syntax-type)
2760 look-prop (or (nth 1 (assoc prop cperl-look-for-prop))
2761 'syntax-type))
2762 (if (memq prop '(pod here-doc format here-doc-delim))
2763 (progn
4ab89e7b 2764 (goto-char (cperl-beginning-of-property p look-prop))
83261a2f 2765 (beginning-of-line)
4ab89e7b 2766 (setq pre-indent-point (point)))))
97610156 2767 (goto-char pre-indent-point) ; Orig line skipping preceding pod/etc
4ab89e7b
SM
2768 (let* ((case-fold-search nil)
2769 (s-s (cperl-get-state (car parse-data) (nth 1 parse-data)))
2770 (start (or (nth 2 parse-data) ; last complete sexp terminated
2771 (nth 0 s-s))) ; Good place to start parsing
2772 (state (nth 1 s-s))
2773 (containing-sexp (car (cdr state)))
2774 old-indent)
2775 (if (and
2776 ;;containing-sexp ;; We are buggy at toplevel :-(
2777 parse-data)
2778 (progn
2779 (setcar parse-data pre-indent-point)
2780 (setcar (cdr parse-data) state)
2781 (or (nth 2 parse-data)
2782 (setcar (cddr parse-data) start))
2783 ;; Before this point: end of statement
2784 (setq old-indent (nth 3 parse-data))))
2785 (cond ((get-text-property (point) 'indentable)
2786 ;; indent to "after" the surrounding open
2787 ;; (same offset as `cperl-beautify-regexp-piece'),
2788 ;; skip blanks if we do not close the expression.
2789 (setq delim ; We do not close the expression
2790 (get-text-property
2791 (cperl-1+ char-after-pos) 'indentable)
2792 p (1+ (cperl-beginning-of-property
2793 (point) 'indentable))
97610156
GM
2794 is-block ; misused for: preceding line in REx
2795 (save-excursion ; Find preceding line
4ab89e7b
SM
2796 (cperl-backward-to-noncomment p)
2797 (beginning-of-line)
2798 (if (<= (point) p)
2799 (progn ; get indent from the first line
2800 (goto-char p)
2801 (skip-chars-forward " \t")
2802 (if (memq (char-after (point))
2803 (append "#\n" nil))
53964682 2804 nil ; Can't use indentation of this line...
4ab89e7b
SM
2805 (point)))
2806 (skip-chars-forward " \t")
2807 (point)))
2808 prop (parse-partial-sexp p char-after-pos))
2809 (cond ((not delim) ; End the REx, ignore is-block
2810 (vector 'indentable 'terminator p is-block))
97610156 2811 (is-block ; Indent w.r.t. preceding line
4ab89e7b
SM
2812 (vector 'indentable 'cont-line char-after-pos
2813 is-block char-after p))
97610156 2814 (t ; No preceding line...
4ab89e7b
SM
2815 (vector 'indentable 'first-line p))))
2816 ((get-text-property char-after-pos 'REx-part2)
2817 (vector 'REx-part2 (point)))
4ab89e7b 2818 ((nth 4 state)
82d9a08d
SM
2819 [comment])
2820 ((nth 3 state)
4ab89e7b
SM
2821 [string])
2822 ;; XXXX Do we need to special-case this?
2823 ((null containing-sexp)
2824 ;; Line is at top level. May be data or function definition,
2825 ;; or may be function argument declaration.
2826 ;; Indent like the previous top level line
2827 ;; unless that ends in a closeparen without semicolon,
2828 ;; in which case this line is the first argument decl.
2829 (skip-chars-forward " \t")
2830 (cperl-backward-to-noncomment (or old-indent (point-min)))
2831 (setq state
2832 (or (bobp)
2833 (eq (point) old-indent) ; old-indent was at comment
2834 (eq (preceding-char) ?\;)
2835 ;; Had ?\) too
2836 (and (eq (preceding-char) ?\})
2837 (cperl-after-block-and-statement-beg
2838 (point-min))) ; Was start - too close
2839 (memq char-after (append ")]}" nil))
2840 (and (eq (preceding-char) ?\:) ; label
83261a2f
SM
2841 (progn
2842 (forward-sexp -1)
4ab89e7b
SM
2843 (skip-chars-backward " \t")
2844 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*[ \t]*:")))
2845 (get-text-property (point) 'first-format-line)))
cb5bf6ba 2846
4ab89e7b
SM
2847 ;; Look at previous line that's at column 0
2848 ;; to determine whether we are in top-level decls
2849 ;; or function's arg decls. Set basic-indent accordingly.
2850 ;; Now add a little if this is a continuation line.
2851 (and state
2852 parse-data
2853 (not (eq char-after ?\C-j))
2854 (setcdr (cddr parse-data)
2855 (list pre-indent-point)))
2856 (vector 'toplevel start char-after state (nth 2 s-s)))
2857 ((not
2858 (or (setq is-block
2859 (and (setq delim (= (char-after containing-sexp) ?{))
2860 (save-excursion ; Is it a hash?
2861 (goto-char containing-sexp)
2862 (cperl-block-p))))
2863 cperl-indent-parens-as-block))
2864 ;; group is an expression, not a block:
2865 ;; indent to just after the surrounding open parens,
2866 ;; skip blanks if we do not close the expression.
2867 (goto-char (1+ containing-sexp))
2868 (or (memq char-after
2869 (append (if delim "}" ")]}") nil))
2870 (looking-at "[ \t]*\\(#\\|$\\)")
2871 (skip-chars-forward " \t"))
2872 (setq old-indent (point)) ; delim=is-brace
2873 (vector 'in-parens char-after (point) delim containing-sexp))
2874 (t
2875 ;; Statement level. Is it a continuation or a new statement?
2876 ;; Find previous non-comment character.
2877 (goto-char pre-indent-point) ; Skip one level of POD/etc
2878 (cperl-backward-to-noncomment containing-sexp)
2879 ;; Back up over label lines, since they don't
2880 ;; affect whether our line is a continuation.
2881 ;; (Had \, too)
2882 (while;;(or (eq (preceding-char) ?\,)
2883 (and (eq (preceding-char) ?:)
2884 (or;;(eq (char-after (- (point) 2)) ?\') ; ????
2885 (memq (char-syntax (char-after (- (point) 2)))
2886 '(?w ?_))))
2887 ;;)
2888 ;; This is always FALSE?
2889 (if (eq (preceding-char) ?\,)
2890 ;; Will go to beginning of line, essentially.
2891 ;; Will ignore embedded sexpr XXXX.
2892 (cperl-backward-to-start-of-continued-exp containing-sexp))
2893 (beginning-of-line)
2894 (cperl-backward-to-noncomment containing-sexp))
97610156 2895 ;; Now we get non-label preceding the indent point
4ab89e7b
SM
2896 (if (not (or (eq (1- (point)) containing-sexp)
2897 (memq (preceding-char)
2898 (append (if is-block " ;{" " ,;{") '(nil)))
2899 (and (eq (preceding-char) ?\})
2900 (cperl-after-block-and-statement-beg
2901 containing-sexp))
2902 (get-text-property (point) 'first-format-line)))
2903 ;; This line is continuation of preceding line's statement;
2904 ;; indent `cperl-continued-statement-offset' more than the
2905 ;; previous line of the statement.
2906 ;;
2907 ;; There might be a label on this line, just
2908 ;; consider it bad style and ignore it.
2909 (progn
2910 (cperl-backward-to-start-of-continued-exp containing-sexp)
2911 (vector 'continuation (point) char-after is-block delim))
2912 ;; This line starts a new statement.
2913 ;; Position following last unclosed open brace
2914 (goto-char containing-sexp)
2915 ;; Is line first statement after an open-brace?
2916 (or
2917 ;; If no, find that first statement and indent like
2918 ;; it. If the first statement begins with label, do
2919 ;; not believe when the indentation of the label is too
2920 ;; small.
2921 (save-excursion
2922 (forward-char 1)
2923 (let ((colon-line-end 0))
2924 (while
2925 (progn (skip-chars-forward " \t\n")
82d9a08d
SM
2926 ;; s: foo : bar :x is NOT label
2927 (and (looking-at "#\\|\\([a-zA-Z0-9_$]+\\):[^:]\\|=[a-zA-Z]")
2928 (not (looking-at "[sym]:\\|tr:"))))
4ab89e7b
SM
2929 ;; Skip over comments and labels following openbrace.
2930 (cond ((= (following-char) ?\#)
2931 (forward-line 1))
2932 ((= (following-char) ?\=)
2933 (goto-char
2934 (or (next-single-property-change (point) 'in-pod)
2935 (point-max)))) ; do not loop if no syntaxification
2936 ;; label:
2937 (t
e180ab9f 2938 (setq colon-line-end (point-at-eol))
4ab89e7b
SM
2939 (search-forward ":"))))
2940 ;; We are at beginning of code (NOT label or comment)
2941 ;; First, the following code counts
2942 ;; if it is before the line we want to indent.
2943 (and (< (point) indent-point)
2944 (vector 'have-prev-sibling (point) colon-line-end
2945 containing-sexp))))
2946 (progn
2947 ;; If no previous statement,
2948 ;; indent it relative to line brace is on.
2949
2950 ;; For open-braces not the first thing in a line,
2951 ;; add in cperl-brace-imaginary-offset.
2952
2953 ;; If first thing on a line: ?????
2954 ;; Move back over whitespace before the openbrace.
2955 (setq ; brace first thing on a line
2956 old-indent (progn (skip-chars-backward " \t") (bolp)))
2957 ;; Should we indent w.r.t. earlier than start?
2958 ;; Move to start of control group, possibly on a different line
2959 (or cperl-indent-wrt-brace
2960 (cperl-backward-to-noncomment (point-min)))
2961 ;; If the openbrace is preceded by a parenthesized exp,
2962 ;; move to the beginning of that;
2963 (if (eq (preceding-char) ?\))
2964 (progn
2965 (forward-sexp -1)
2966 (cperl-backward-to-noncomment (point-min))))
2967 ;; In the case it starts a subroutine, indent with
2968 ;; respect to `sub', not with respect to the
2969 ;; first thing on the line, say in the case of
2970 ;; anonymous sub in a hash.
2971 (if (and;; Is it a sub in group starting on this line?
2972 (cond ((get-text-property (point) 'attrib-group)
2973 (goto-char (cperl-beginning-of-property
2974 (point) 'attrib-group)))
2975 ((eq (preceding-char) ?b)
2976 (forward-sexp -1)
2977 (looking-at "sub\\>")))
2978 (setq p (nth 1 ; start of innermost containing list
2979 (parse-partial-sexp
9b026d9f 2980 (point-at-bol)
4ab89e7b
SM
2981 (point)))))
2982 (progn
2983 (goto-char (1+ p)) ; enclosing block on the same line
2984 (skip-chars-forward " \t")
2985 (vector 'code-start-in-block containing-sexp char-after
2986 (and delim (not is-block)) ; is a HASH
2987 old-indent ; brace first thing on a line
2988 t (point) ; have something before...
2989 )
2990 ;;(current-column)
2991 )
2992 ;; Get initial indentation of the line we are on.
2993 ;; If line starts with label, calculate label indentation
2994 (vector 'code-start-in-block containing-sexp char-after
2995 (and delim (not is-block)) ; is a HASH
2996 old-indent ; brace first thing on a line
82d9a08d 2997 nil (point))))))))))))))) ; nothing interesting before
4ab89e7b
SM
2998
2999(defvar cperl-indent-rules-alist
3000 '((pod nil) ; via `syntax-type' property
3001 (here-doc nil) ; via `syntax-type' property
3002 (here-doc-delim nil) ; via `syntax-type' property
3003 (format nil) ; via `syntax-type' property
3004 (in-pod nil) ; via `in-pod' property
3005 (comment-special:at-beginning-of-line nil)
3006 (string t)
3007 (comment nil))
3008 "Alist of indentation rules for CPerl mode.
3009The values mean:
3010 nil: do not indent;
82d9a08d 3011 number: add this amount of indentation.")
4ab89e7b
SM
3012
3013(defun cperl-calculate-indent (&optional parse-data) ; was parse-start
3014 "Return appropriate indentation for current line as Perl code.
3015In usual case returns an integer: the column to indent to.
3016Returns nil if line starts inside a string, t if in a comment.
3017
3018Will not correct the indentation for labels, but will correct it for braces
3019and closing parentheses and brackets."
3020 ;; This code is still a broken architecture: in some cases we need to
3021 ;; compensate for some modifications which `cperl-indent-line' will add later
3022 (save-excursion
3023 (let ((i (cperl-sniff-for-indent parse-data)) what p)
3024 (cond
3025 ;;((or (null i) (eq i t) (numberp i))
3026 ;; i)
3027 ((vectorp i)
3028 (setq what (assoc (elt i 0) cperl-indent-rules-alist))
3029 (cond
3030 (what (cadr what)) ; Load from table
3031 ;;
3032 ;; Indenters for regular expressions with //x and qw()
3033 ;;
3034 ((eq 'REx-part2 (elt i 0)) ;; [self start] start of /REP in s//REP/x
3035 (goto-char (elt i 1))
3036 (condition-case nil ; Use indentation of the 1st part
3037 (forward-sexp -1))
3038 (current-column))
3039 ((eq 'indentable (elt i 0)) ; Indenter for REGEXP qw() etc
3040 (cond ;;; [indentable terminator start-pos is-block]
3041 ((eq 'terminator (elt i 1)) ; Lone terminator of "indentable string"
3042 (goto-char (elt i 2)) ; After opening parens
3043 (1- (current-column)))
3044 ((eq 'first-line (elt i 1)); [indentable first-line start-pos]
3045 (goto-char (elt i 2))
3046 (+ (or cperl-regexp-indent-step cperl-indent-level)
3047 -1
3048 (current-column)))
3049 ((eq 'cont-line (elt i 1)); [indentable cont-line pos prev-pos first-char start-pos]
3050 ;; Indent as the level after closing parens
3051 (goto-char (elt i 2)) ; indent line
3052 (skip-chars-forward " \t)") ; Skip closing parens
3053 (setq p (point))
3054 (goto-char (elt i 3)) ; previous line
3055 (skip-chars-forward " \t)") ; Skip closing parens
3056 ;; Number of parens in between:
3057 (setq p (nth 0 (parse-partial-sexp (point) p))
3058 what (elt i 4)) ; First char on current line
3059 (goto-char (elt i 3)) ; previous line
3060 (+ (* p (or cperl-regexp-indent-step cperl-indent-level))
3061 (cond ((eq what ?\) )
3062 (- cperl-close-paren-offset)) ; compensate
3063 ((eq what ?\| )
3064 (- (or cperl-regexp-indent-step cperl-indent-level)))
3065 (t 0))
3066 (if (eq (following-char) ?\| )
3067 (or cperl-regexp-indent-step cperl-indent-level)
3068 0)
3069 (current-column)))
3070 (t
3071 (error "Unrecognized value of indent: %s" i))))
3072 ;;
3073 ;; Indenter for stuff at toplevel
3074 ;;
3075 ((eq 'toplevel (elt i 0)) ;; [toplevel start char-after state immed-after-block]
3076 (+ (save-excursion ; To beg-of-defun, or end of last sexp
3077 (goto-char (elt i 1)) ; start = Good place to start parsing
cb5bf6ba 3078 (- (current-indentation) ;
4ab89e7b
SM
3079 (if (elt i 4) cperl-indent-level 0))) ; immed-after-block
3080 (if (eq (elt i 2) ?{) cperl-continued-brace-offset 0) ; char-after
3081 ;; Look at previous line that's at column 0
3082 ;; to determine whether we are in top-level decls
3083 ;; or function's arg decls. Set basic-indent accordingly.
3084 ;; Now add a little if this is a continuation line.
3085 (if (elt i 3) ; state (XXX What is the semantic???)
3086 0
3087 cperl-continued-statement-offset)))
3088 ;;
3089 ;; Indenter for stuff in "parentheses" (or brackets, braces-as-hash)
3090 ;;
3091 ((eq 'in-parens (elt i 0))
3092 ;; in-parens char-after old-indent-point is-brace containing-sexp
3093
3094 ;; group is an expression, not a block:
3095 ;; indent to just after the surrounding open parens,
3096 ;; skip blanks if we do not close the expression.
3097 (+ (progn
3098 (goto-char (elt i 2)) ; old-indent-point
3099 (current-column))
3100 (if (and (elt i 3) ; is-brace
3101 (eq (elt i 1) ?\})) ; char-after
3102 ;; Correct indentation of trailing ?\}
3103 (+ cperl-indent-level cperl-close-paren-offset)
3104 0)))
3105 ;;
3106 ;; Indenter for continuation lines
3107 ;;
3108 ((eq 'continuation (elt i 0))
3109 ;; [continuation statement-start char-after is-block is-brace]
3110 (goto-char (elt i 1)) ; statement-start
3111 (+ (if (memq (elt i 2) (append "}])" nil)) ; char-after
3112 0 ; Closing parenth
3113 cperl-continued-statement-offset)
3114 (if (or (elt i 3) ; is-block
3115 (not (elt i 4)) ; is-brace
3116 (not (eq (elt i 2) ?\}))) ; char-after
3117 0
3118 ;; Now it is a hash reference
3119 (+ cperl-indent-level cperl-close-paren-offset))
3120 ;; Labels do not take :: ...
3121 (if (looking-at "\\(\\w\\|_\\)+[ \t]*:")
3122 (if (> (current-indentation) cperl-min-label-indent)
3123 (- (current-indentation) cperl-label-offset)
3124 ;; Do not move `parse-data', this should
3125 ;; be quick anyway (this comment comes
3126 ;; from different location):
3127 (cperl-calculate-indent))
3128 (current-column))
3129 (if (eq (elt i 2) ?\{) ; char-after
3130 cperl-continued-brace-offset 0)))
3131 ;;
3132 ;; Indenter for lines in a block which are not leading lines
3133 ;;
3134 ((eq 'have-prev-sibling (elt i 0))
3135 ;; [have-prev-sibling sibling-beg colon-line-end block-start]
82d9a08d
SM
3136 (goto-char (elt i 1)) ; sibling-beg
3137 (if (> (elt i 2) (point)) ; colon-line-end; have label before point
4ab89e7b
SM
3138 (if (> (current-indentation)
3139 cperl-min-label-indent)
3140 (- (current-indentation) cperl-label-offset)
3141 ;; Do not believe: `max' was involved in calculation of indent
3142 (+ cperl-indent-level
3143 (save-excursion
3144 (goto-char (elt i 3)) ; block-start
3145 (current-indentation))))
3146 (current-column)))
3147 ;;
3148 ;; Indenter for the first line in a block
3149 ;;
3150 ((eq 'code-start-in-block (elt i 0))
3151 ;;[code-start-in-block before-brace char-after
3152 ;; is-a-HASH-ref brace-is-first-thing-on-a-line
3153 ;; group-starts-before-start-of-sub start-of-control-group]
3154 (goto-char (elt i 1))
3155 ;; For open brace in column zero, don't let statement
3156 ;; start there too. If cperl-indent-level=0,
3157 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
3158 (+ (if (and (bolp) (zerop cperl-indent-level))
3159 (+ cperl-brace-offset cperl-continued-statement-offset)
3160 cperl-indent-level)
3161 (if (and (elt i 3) ; is-a-HASH-ref
3162 (eq (elt i 2) ?\})) ; char-after: End of a hash reference
3163 (+ cperl-indent-level cperl-close-paren-offset)
3164 0)
3165 ;; Unless openbrace is the first nonwhite thing on the line,
3166 ;; add the cperl-brace-imaginary-offset.
3167 (if (elt i 4) 0 ; brace-is-first-thing-on-a-line
3168 cperl-brace-imaginary-offset)
3169 (progn
3170 (goto-char (elt i 6)) ; start-of-control-group
3171 (if (elt i 5) ; group-starts-before-start-of-sub
3172 (current-column)
3173 ;; Get initial indentation of the line we are on.
3174 ;; If line starts with label, calculate label indentation
3175 (if (save-excursion
3176 (beginning-of-line)
3177 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
3178 (if (> (current-indentation) cperl-min-label-indent)
3179 (- (current-indentation) cperl-label-offset)
3180 ;; Do not move `parse-data', this should
3181 ;; be quick anyway:
3182 (cperl-calculate-indent))
3183 (current-indentation))))))
3184 (t
3185 (error "Unrecognized value of indent: %s" i))))
3186 (t
3187 (error "Got strange value of indent: %s" i))))))
3188
f83d2997
KH
3189(defun cperl-calculate-indent-within-comment ()
3190 "Return the indentation amount for line, assuming that
3191the current line is to be regarded as part of a block comment."
3192 (let (end star-start)
3193 (save-excursion
3194 (beginning-of-line)
3195 (skip-chars-forward " \t")
3196 (setq end (point))
3197 (and (= (following-char) ?#)
3198 (forward-line -1)
3199 (cperl-to-comment-or-eol)
3200 (setq end (point)))
3201 (goto-char end)
3202 (current-column))))
3203
3204
3205(defun cperl-to-comment-or-eol ()
029cb4d5 3206 "Go to position before comment on the current line, or to end of line.
4ab89e7b
SM
3207Returns true if comment is found. In POD will not move the point."
3208 ;; If the line is inside other syntax groups (qq-style strings, HERE-docs)
3209 ;; then looks for literal # or end-of-line.
e180ab9f 3210 (let (state stop-in cpoint (lim (point-at-eol)) pr e)
4ab89e7b
SM
3211 (or cperl-font-locking
3212 (cperl-update-syntaxification lim lim))
83261a2f 3213 (beginning-of-line)
4ab89e7b
SM
3214 (if (setq pr (get-text-property (point) 'syntax-type))
3215 (setq e (next-single-property-change (point) 'syntax-type nil (point-max))))
3216 (if (or (eq pr 'pod)
3217 (if (or (not e) (> e lim)) ; deep inside a group
3218 (re-search-forward "\\=[ \t]*\\(#\\|$\\)" lim t)))
83261a2f 3219 (if (eq (preceding-char) ?\#) (progn (backward-char 1) t))
4ab89e7b
SM
3220 ;; Else - need to do it the hard way
3221 (and (and e (<= e lim))
3222 (goto-char e))
83261a2f
SM
3223 (while (not stop-in)
3224 (setq state (parse-partial-sexp (point) lim nil nil nil t))
f83d2997 3225 ; stop at comment
83261a2f
SM
3226 ;; If fails (beginning-of-line inside sexp), then contains not-comment
3227 (if (nth 4 state) ; After `#';
f83d2997
KH
3228 ; (nth 2 state) can be
3229 ; beginning of m,s,qq and so
3230 ; on
83261a2f
SM
3231 (if (nth 2 state)
3232 (progn
3233 (setq cpoint (point))
3234 (goto-char (nth 2 state))
3235 (cond
3236 ((looking-at "\\(s\\|tr\\)\\>")
3237 (or (re-search-forward
3238 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*"
3239 lim 'move)
3240 (setq stop-in t)))
3241 ((looking-at "\\(m\\|q\\([qxwr]\\)?\\)\\>")
3242 (or (re-search-forward
3243 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#"
3244 lim 'move)
3245 (setq stop-in t)))
3246 (t ; It was fair comment
3247 (setq stop-in t) ; Finish
3248 (goto-char (1- cpoint)))))
3249 (setq stop-in t) ; Finish
3250 (forward-char -1))
15ca5699 3251 (setq stop-in t))) ; Finish
83261a2f 3252 (nth 4 state))))
f83d2997 3253
f83d2997
KH
3254(defsubst cperl-modify-syntax-type (at how)
3255 (if (< at (point-max))
3256 (progn
3257 (put-text-property at (1+ at) 'syntax-table how)
4ab89e7b 3258 (put-text-property at (1+ at) 'rear-nonsticky '(syntax-table)))))
f83d2997
KH
3259
3260(defun cperl-protect-defun-start (s e)
3261 ;; C code looks for "^\\s(" to skip comment backward in "hard" situations
3262 (save-excursion
3263 (goto-char s)
3264 (while (re-search-forward "^\\s(" e 'to-end)
3265 (put-text-property (1- (point)) (point) 'syntax-table cperl-st-punct))))
3266
5bd52f0e 3267(defun cperl-commentify (bb e string &optional noface)
5c8b7eaf 3268 (if cperl-use-syntax-table-text-property
5bd52f0e
RS
3269 (if (eq noface 'n) ; Only immediate
3270 nil
f83d2997
KH
3271 ;; We suppose that e is _after_ the end of construction, as after eol.
3272 (setq string (if string cperl-st-sfence cperl-st-cfence))
6c389151
SM
3273 (if (> bb (- e 2))
3274 ;; one-char string/comment?!
3275 (cperl-modify-syntax-type bb cperl-st-punct)
3276 (cperl-modify-syntax-type bb string)
3277 (cperl-modify-syntax-type (1- e) string))
f83d2997 3278 (if (and (eq string cperl-st-sfence) (> (- e 2) bb))
5c8b7eaf 3279 (put-text-property (1+ bb) (1- e)
f83d2997 3280 'syntax-table cperl-string-syntax-table))
5bd52f0e
RS
3281 (cperl-protect-defun-start bb e))
3282 ;; Fontify
3283 (or noface
3284 (not cperl-pod-here-fontify)
3285 (put-text-property bb e 'face (if string 'font-lock-string-face
3286 'font-lock-comment-face)))))
6c389151 3287
5bd52f0e
RS
3288(defvar cperl-starters '(( ?\( . ?\) )
3289 ( ?\[ . ?\] )
3290 ( ?\{ . ?\} )
3291 ( ?\< . ?\> )))
f83d2997 3292
4ab89e7b
SM
3293(defun cperl-cached-syntax-table (st)
3294 "Get a syntax table cached in ST, or create and cache into ST a syntax table.
3295All the entries of the syntax table are \".\", except for a backslash, which
3296is quoting."
3297 (if (car-safe st)
3298 (car st)
3299 (setcar st (make-syntax-table))
3300 (setq st (car st))
3301 (let ((i 0))
3302 (while (< i 256)
3303 (modify-syntax-entry i "." st)
3304 (setq i (1+ i))))
3305 (modify-syntax-entry ?\\ "\\" st)
3306 st))
3307
3308(defun cperl-forward-re (lim end is-2arg st-l err-l argument
f83d2997 3309 &optional ostart oend)
4ab89e7b
SM
3310"Find the end of a regular expression or a stringish construct (q[] etc).
3311The point should be before the starting delimiter.
3312
3313Goes to LIM if none is found. If IS-2ARG is non-nil, assumes that it
3314is s/// or tr/// like expression. If END is nil, generates an error
3315message if needed. If SET-ST is non-nil, will use (or generate) a
3316cached syntax table in ST-L. If ERR-L is non-nil, will store the
3317error message in its CAR (unless it already contains some error
3318message). ARGUMENT should be the name of the construct (used in error
3319messages). OSTART, OEND may be set in recursive calls when processing
3320the second argument of 2ARG construct.
3321
3322Works *before* syntax recognition is done. In IS-2ARG situation may
3323modify syntax-type text property if the situation is too hard."
3324 (let (b starter ender st i i2 go-forward reset-st set-st)
f83d2997
KH
3325 (skip-chars-forward " \t")
3326 ;; ender means matching-char matcher.
5c8b7eaf 3327 (setq b (point)
5bd52f0e
RS
3328 starter (if (eobp) 0 (char-after b))
3329 ender (cdr (assoc starter cperl-starters)))
f83d2997 3330 ;; What if starter == ?\\ ????
4ab89e7b 3331 (setq st (cperl-cached-syntax-table st-l))
f83d2997
KH
3332 (setq set-st t)
3333 ;; Whether we have an intermediate point
3334 (setq i nil)
3335 ;; Prepare the syntax table:
4ab89e7b
SM
3336 (if (not ender) ; m/blah/, s/x//, s/x/y/
3337 (modify-syntax-entry starter "$" st)
3338 (modify-syntax-entry starter (concat "(" (list ender)) st)
3339 (modify-syntax-entry ender (concat ")" (list starter)) st))
f83d2997
KH
3340 (condition-case bb
3341 (progn
5bd52f0e
RS
3342 ;; We use `$' syntax class to find matching stuff, but $$
3343 ;; is recognized the same as $, so we need to check this manually.
f83d2997
KH
3344 (if (and (eq starter (char-after (cperl-1+ b)))
3345 (not ender))
3346 ;; $ has TeXish matching rules, so $$ equiv $...
3347 (forward-char 2)
6c389151 3348 (setq reset-st (syntax-table))
f83d2997
KH
3349 (set-syntax-table st)
3350 (forward-sexp 1)
6c389151
SM
3351 (if (<= (point) (1+ b))
3352 (error "Unfinished regular expression"))
3353 (set-syntax-table reset-st)
3354 (setq reset-st nil)
f83d2997
KH
3355 ;; Now the problem is with m;blah;;
3356 (and (not ender)
3357 (eq (preceding-char)
3358 (char-after (- (point) 2)))
3359 (save-excursion
3360 (forward-char -2)
3361 (= 0 (% (skip-chars-backward "\\\\") 2)))
3362 (forward-char -1)))
5bd52f0e 3363 ;; Now we are after the first part.
f83d2997
KH
3364 (and is-2arg ; Have trailing part
3365 (not ender)
3366 (eq (following-char) starter) ; Empty trailing part
3367 (progn
3368 (or (eq (char-syntax (following-char)) ?.)
3369 ;; Make trailing letter into punctuation
3370 (cperl-modify-syntax-type (point) cperl-st-punct))
3371 (setq is-2arg nil go-forward t))) ; Ignore the tail
3372 (if is-2arg ; Not number => have second part
3373 (progn
3374 (setq i (point) i2 i)
3375 (if ender
b5b0cb34 3376 (if (memq (following-char) '(?\s ?\t ?\n ?\f))
f83d2997
KH
3377 (progn
3378 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
3379 (goto-char (match-end 0))
3380 (skip-chars-forward " \t\n\f"))
3381 (setq i2 (point))))
3382 (forward-char -1))
3383 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
5c8b7eaf 3384 (if ender (modify-syntax-entry ender "." st))
f83d2997 3385 (setq set-st nil)
4ab89e7b 3386 (setq ender (cperl-forward-re lim end nil st-l err-l
5bd52f0e 3387 argument starter ender)
8c777c8d 3388 ender (nth 2 ender)))))
f83d2997
KH
3389 (error (goto-char lim)
3390 (setq set-st nil)
6c389151
SM
3391 (if reset-st
3392 (set-syntax-table reset-st))
f83d2997 3393 (or end
8c777c8d
CY
3394 (and cperl-brace-recursing
3395 (or (eq ostart ?\{)
3396 (eq starter ?\{)))
f83d2997 3397 (message
5bd52f0e 3398 "End of `%s%s%c ... %c' string/RE not found: %s"
f83d2997
KH
3399 argument
3400 (if ostart (format "%c ... %c" ostart (or oend ostart)) "")
3401 starter (or ender starter) bb)
3402 (or (car err-l) (setcar err-l b)))))
3403 (if set-st
3404 (progn
3405 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
3406 (if ender (modify-syntax-entry ender "." st))))
5bd52f0e 3407 ;; i: have 2 args, after end of the first arg
e7f767c2 3408 ;; i2: start of the second arg, if any (before delim if `ender').
5bd52f0e
RS
3409 ;; ender: the last arg bounded by parens-like chars, the second one of them
3410 ;; starter: the starting delimiter of the first arg
5efe6a56 3411 ;; go-forward: has 2 args, and the second part is empty
f83d2997
KH
3412 (list i i2 ender starter go-forward)))
3413
4ab89e7b
SM
3414(defun cperl-forward-group-in-re (&optional st-l)
3415 "Find the end of a group in a REx.
3416Return the error message (if any). Does not work if delimiter is `)'.
3417Works before syntax recognition is done."
3418 ;; Works *before* syntax recognition is done
3419 (or st-l (setq st-l (list nil))) ; Avoid overwriting '()
3420 (let (st b reset-st)
3421 (condition-case b
3422 (progn
3423 (setq st (cperl-cached-syntax-table st-l))
3424 (modify-syntax-entry ?\( "()" st)
3425 (modify-syntax-entry ?\) ")(" st)
3426 (setq reset-st (syntax-table))
3427 (set-syntax-table st)
3428 (forward-sexp 1))
3429 (error (message
3430 "cperl-forward-group-in-re: error %s" b)))
3431 ;; now restore the initial state
3432 (if st
3433 (progn
3434 (modify-syntax-entry ?\( "." st)
3435 (modify-syntax-entry ?\) "." st)))
3436 (if reset-st
3437 (set-syntax-table reset-st))
3438 b))
3439
3440
83261a2f
SM
3441(defvar font-lock-string-face)
3442;;(defvar font-lock-reference-face)
3443(defvar font-lock-constant-face)
5c8b7eaf 3444(defsubst cperl-postpone-fontification (b e type val &optional now)
5bd52f0e
RS
3445 ;; Do after syntactic fontification?
3446 (if cperl-syntaxify-by-font-lock
3447 (or now (put-text-property b e 'cperl-postpone (cons type val)))
83261a2f 3448 (put-text-property b e type val)))
5bd52f0e
RS
3449
3450;;; Here is how the global structures (those which cannot be
3451;;; recognized locally) are marked:
5c8b7eaf 3452;; a) PODs:
5bd52f0e
RS
3453;; Start-to-end is marked `in-pod' ==> t
3454;; Each non-literal part is marked `syntax-type' ==> `pod'
3455;; Each literal part is marked `syntax-type' ==> `in-pod'
5c8b7eaf 3456;; b) HEREs:
5bd52f0e
RS
3457;; Start-to-end is marked `here-doc-group' ==> t
3458;; The body is marked `syntax-type' ==> `here-doc'
3459;; The delimiter is marked `syntax-type' ==> `here-doc-delim'
5c8b7eaf 3460;; c) FORMATs:
f739b53b
SM
3461;; First line (to =) marked `first-format-line' ==> t
3462;; After-this--to-end is marked `syntax-type' ==> `format'
5c8b7eaf 3463;; d) 'Q'uoted string:
5bd52f0e 3464;; part between markers inclusive is marked `syntax-type' ==> `string'
6c389151 3465;; part between `q' and the first marker is marked `syntax-type' ==> `prestring'
4ab89e7b
SM
3466;; second part of s///e is marked `syntax-type' ==> `multiline'
3467;; e) Attributes of subroutines: `attrib-group' ==> t
3468;; (or 0 if declaration); up to `{' or ';': `syntax-type' => `sub-decl'.
3469;; f) Multiline my/our declaration lists etc: `syntax-type' => `multiline'
3470
3471;;; In addition, some parts of RExes may be marked as `REx-interpolated'
3472;;; (value: 0 in //o, 1 if "interpolated variable" is whole-REx, t otherwise).
5bd52f0e
RS
3473
3474(defun cperl-unwind-to-safe (before &optional end)
3475 ;; if BEFORE, go to the previous start-of-line on each step of unwinding
3476 (let ((pos (point)) opos)
4ab89e7b
SM
3477 (while (and pos (progn
3478 (beginning-of-line)
3479 (get-text-property (setq pos (point)) 'syntax-type)))
3480 (setq opos pos
3481 pos (cperl-beginning-of-property pos 'syntax-type))
3482 (if (eq pos (point-min))
3483 (setq pos nil))
5bd52f0e
RS
3484 (if pos
3485 (if before
3486 (progn
3487 (goto-char (cperl-1- pos))
3488 (beginning-of-line)
3489 (setq pos (point)))
3490 (goto-char (setq pos (cperl-1- pos))))
3491 ;; Up to the start
3492 (goto-char (point-min))))
6c389151
SM
3493 ;; Skip empty lines
3494 (and (looking-at "\n*=")
3495 (/= 0 (skip-chars-backward "\n"))
3496 (forward-char))
3497 (setq pos (point))
5bd52f0e
RS
3498 (if end
3499 ;; Do the same for end, going small steps
4ab89e7b 3500 (save-excursion
5bd52f0e
RS
3501 (while (and end (get-text-property end 'syntax-type))
3502 (setq pos end
4ab89e7b
SM
3503 end (next-single-property-change end 'syntax-type nil (point-max)))
3504 (if end (progn (goto-char end)
3505 (or (bolp) (forward-line 1))
3506 (setq end (point)))))
5bd52f0e
RS
3507 (or end pos)))))
3508
4ab89e7b 3509;;; These are needed for byte-compile (at least with v19)
6c389151 3510(defvar cperl-nonoverridable-face)
4ab89e7b 3511(defvar font-lock-variable-name-face)
6c389151 3512(defvar font-lock-function-name-face)
4ab89e7b
SM
3513(defvar font-lock-keyword-face)
3514(defvar font-lock-builtin-face)
3515(defvar font-lock-type-face)
6c389151 3516(defvar font-lock-comment-face)
4ab89e7b 3517(defvar font-lock-warning-face)
6c389151 3518
4ab89e7b 3519(defun cperl-find-sub-attrs (&optional st-l b-fname e-fname pos)
bbd240ce 3520 "Syntactically mark (and fontify) attributes of a subroutine.
4ab89e7b
SM
3521Should be called with the point before leading colon of an attribute."
3522 ;; Works *before* syntax recognition is done
3523 (or st-l (setq st-l (list nil))) ; Avoid overwriting '()
3524 (let (st b p reset-st after-first (start (point)) start1 end1)
3525 (condition-case b
3526 (while (looking-at
3527 (concat
3528 "\\(" ; 1=optional? colon
3529 ":" cperl-maybe-white-and-comment-rex ; 2=whitespace/comment?
3530 "\\)"
3531 (if after-first "?" "")
3532 ;; No space between name and paren allowed...
3533 "\\(\\sw+\\)" ; 3=name
3534 "\\((\\)?")) ; 4=optional paren
3535 (and (match-beginning 1)
3536 (cperl-postpone-fontification
3537 (match-beginning 0) (cperl-1+ (match-beginning 0))
3538 'face font-lock-constant-face))
3539 (setq start1 (match-beginning 3) end1 (match-end 3))
3540 (cperl-postpone-fontification start1 end1
3541 'face font-lock-constant-face)
3542 (goto-char end1) ; end or before `('
3543 (if (match-end 4) ; Have attribute arguments...
3544 (progn
3545 (if st nil
3546 (setq st (cperl-cached-syntax-table st-l))
3547 (modify-syntax-entry ?\( "()" st)
3548 (modify-syntax-entry ?\) ")(" st))
3549 (setq reset-st (syntax-table) p (point))
3550 (set-syntax-table st)
3551 (forward-sexp 1)
3552 (set-syntax-table reset-st)
3553 (setq reset-st nil)
3554 (cperl-commentify p (point) t))) ; mark as string
3555 (forward-comment (buffer-size))
3556 (setq after-first t))
3557 (error (message
3558 "L%d: attribute `%s': %s"
3559 (count-lines (point-min) (point))
3560 (and start1 end1 (buffer-substring start1 end1)) b)
3561 (setq start nil)))
3562 (and start
3563 (progn
3564 (put-text-property start (point)
3565 'attrib-group (if (looking-at "{") t 0))
3566 (and pos
3567 (< 1 (count-lines (+ 3 pos) (point))) ; end of `sub'
3568 ;; Apparently, we do not need `multiline': faces added now
3569 (put-text-property (+ 3 pos) (cperl-1+ (point))
3570 'syntax-type 'sub-decl))
3571 (and b-fname ; Fontify here: the following condition
3572 (cperl-postpone-fontification ; is too hard to determine by
3573 b-fname e-fname 'face ; a REx, so do it here
3574 (if (looking-at "{")
3575 font-lock-function-name-face
3576 font-lock-variable-name-face)))))
3577 ;; now restore the initial state
3578 (if st
3579 (progn
3580 (modify-syntax-entry ?\( "." st)
3581 (modify-syntax-entry ?\) "." st)))
3582 (if reset-st
3583 (set-syntax-table reset-st))))
3584
3585(defsubst cperl-look-at-leading-count (is-x-REx e)
82d9a08d
SM
3586 (if (and
3587 (< (point) e)
3588 (re-search-forward (concat "\\=" (if is-x-REx "[ \t\n]*" "") "[{?+*]")
3589 (1- e) t)) ; return nil on failure, no moving
4ab89e7b
SM
3590 (if (eq ?\{ (preceding-char)) nil
3591 (cperl-postpone-fontification
3592 (1- (point)) (point)
3593 'face font-lock-warning-face))))
3594
8c777c8d
CY
3595;; Do some smarter-highlighting
3596;; XXXX Currently ignores alphanum/dash delims,
3597(defsubst cperl-highlight-charclass (endbracket dashface bsface onec-space)
3598 (let ((l '(1 5 7)) ll lle lll
3599 ;; 2 groups, the first takes the whole match (include \[trnfabe])
3600 (singleChar (concat "\\(" "[^\\\\]" "\\|" "\\\\[^cdg-mo-qsu-zA-Z0-9_]" "\\|" "\\\\c." "\\|" "\\\\x" "\\([0-9a-fA-F][0-9a-fA-F]?\\|\\={[0-9a-fA-F]+}\\)" "\\|" "\\\\0?[0-7][0-7]?[0-7]?" "\\|" "\\\\N{[^{}]*}" "\\)")))
3601 (while ; look for unescaped - between non-classes
3602 (re-search-forward
3603 ;; On 19.33, certain simplifications lead
3604 ;; to bugs (as in [^a-z] \\| [trnfabe] )
3605 (concat ; 1: SingleChar (include \[trnfabe])
3606 singleChar
3607 ;;"\\(" "[^\\\\]" "\\|" "\\\\[^cdg-mo-qsu-zA-Z0-9_]" "\\|" "\\\\c." "\\|" "\\\\x" "\\([0-9a-fA-F][0-9a-fA-F]?\\|\\={[0-9a-fA-F]+}\\)" "\\|" "\\\\0?[0-7][0-7]?[0-7]?" "\\|" "\\\\N{[^{}]*}" "\\)"
3608 "\\(" ; 3: DASH SingleChar (match optionally)
3609 "\\(-\\)" ; 4: DASH
3610 singleChar ; 5: SingleChar
3611 ;;"\\(" "[^\\\\]" "\\|" "\\\\[^cdg-mo-qsu-zA-Z0-9_]" "\\|" "\\\\c." "\\|" "\\\\x" "\\([0-9a-fA-F][0-9a-fA-F]?\\|\\={[0-9a-fA-F]+}\\)" "\\|" "\\\\0?[0-7][0-7]?[0-7]?" "\\|" "\\\\N{[^{}]*}" "\\)"
3612 "\\)?"
3613 "\\|"
3614 "\\(" ; 7: other escapes
3615 "\\\\[pP]" "\\([^{]\\|{[^{}]*}\\)"
3616 "\\|" "\\\\[^pP]" "\\)"
3617 )
3618 endbracket 'toend)
3619 (if (match-beginning 4)
3620 (cperl-postpone-fontification
3621 (match-beginning 4) (match-end 4)
3622 'face dashface))
3623 ;; save match data (for looking-at)
3624 (setq lll (mapcar (function (lambda (elt) (cons (match-beginning elt)
3625 (match-end elt)))) l))
3626 (while lll
3627 (setq ll (car lll))
3628 (setq lle (cdr ll)
3629 ll (car ll))
3630 ;; (message "Got %s of %s" ll l)
3631 (if (and ll (eq (char-after ll) ?\\ ))
3632 (save-excursion
3633 (goto-char ll)
3634 (cperl-postpone-fontification ll (1+ ll)
3635 'face bsface)
3636 (if (looking-at "\\\\[a-zA-Z0-9]")
3637 (cperl-postpone-fontification (1+ ll) lle
3638 'face onec-space))))
3639 (setq lll (cdr lll))))
3640 (goto-char endbracket) ; just in case something misbehaves???
3641 t))
3642
4ab89e7b
SM
3643;;; Debugging this may require (setq max-specpdl-size 2000)...
3644(defun cperl-find-pods-heres (&optional min max non-inter end ignore-max end-of-here-doc)
f83d2997 3645 "Scans the buffer for hard-to-parse Perl constructions.
5c8b7eaf
SS
3646If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify
3647the sections using `cperl-pod-head-face', `cperl-pod-face',
f83d2997
KH
3648`cperl-here-face'."
3649 (interactive)
05927f8c 3650 (or min (setq min (point-min)
db133cb6
RS
3651 cperl-syntax-state nil
3652 cperl-syntax-done-to min))
f83d2997 3653 (or max (setq max (point-max)))
83261a2f
SM
3654 (let* ((cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend
3655 face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb
4ab89e7b 3656 is-REx is-x-REx REx-subgr-start REx-subgr-end was-subgr i2 hairy-RE
83261a2f 3657 (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
af1d43f9 3658 (modified (buffer-modified-p)) overshoot is-o-REx name
83261a2f 3659 (after-change-functions nil)
4ab89e7b 3660 (cperl-font-locking t)
83261a2f
SM
3661 (use-syntax-state (and cperl-syntax-state
3662 (>= min (car cperl-syntax-state))))
3663 (state-point (if use-syntax-state
3664 (car cperl-syntax-state)
3665 (point-min)))
3666 (state (if use-syntax-state
3667 (cdr cperl-syntax-state)))
3668 ;; (st-l '(nil)) (err-l '(nil)) ; Would overwrite - propagates from a function call to a function call!
3669 (st-l (list nil)) (err-l (list nil))
3670 ;; Somehow font-lock may be not loaded yet...
4ab89e7b 3671 ;; (e.g., when building TAGS via command-line call)
83261a2f
SM
3672 (font-lock-string-face (if (boundp 'font-lock-string-face)
3673 font-lock-string-face
3674 'font-lock-string-face))
4ab89e7b 3675 (my-cperl-delimiters-face (if (boundp 'font-lock-constant-face)
83261a2f
SM
3676 font-lock-constant-face
3677 'font-lock-constant-face))
4ab89e7b 3678 (my-cperl-REx-spec-char-face ; [] ^.$ and wrapper-of ({})
83261a2f
SM
3679 (if (boundp 'font-lock-function-name-face)
3680 font-lock-function-name-face
3681 'font-lock-function-name-face))
4ab89e7b
SM
3682 (font-lock-variable-name-face ; interpolated vars and ({})-code
3683 (if (boundp 'font-lock-variable-name-face)
3684 font-lock-variable-name-face
3685 'font-lock-variable-name-face))
3686 (font-lock-function-name-face ; used in `cperl-find-sub-attrs'
3687 (if (boundp 'font-lock-function-name-face)
3688 font-lock-function-name-face
3689 'font-lock-function-name-face))
3690 (font-lock-constant-face ; used in `cperl-find-sub-attrs'
3691 (if (boundp 'font-lock-constant-face)
3692 font-lock-constant-face
3693 'font-lock-constant-face))
3694 (my-cperl-REx-0length-face ; 0-length, (?:)etc, non-literal \
3695 (if (boundp 'font-lock-builtin-face)
3696 font-lock-builtin-face
3697 'font-lock-builtin-face))
83261a2f
SM
3698 (font-lock-comment-face
3699 (if (boundp 'font-lock-comment-face)
3700 font-lock-comment-face
3701 'font-lock-comment-face))
4ab89e7b
SM
3702 (font-lock-warning-face
3703 (if (boundp 'font-lock-warning-face)
3704 font-lock-warning-face
3705 'font-lock-warning-face))
3706 (my-cperl-REx-ctl-face ; (|)
3707 (if (boundp 'font-lock-keyword-face)
3708 font-lock-keyword-face
3709 'font-lock-keyword-face))
3710 (my-cperl-REx-modifiers-face ; //gims
83261a2f
SM
3711 (if (boundp 'cperl-nonoverridable-face)
3712 cperl-nonoverridable-face
4ab89e7b
SM
3713 'cperl-nonoverridable-face))
3714 (my-cperl-REx-length1-face ; length=1 escaped chars, POSIX classes
3715 (if (boundp 'font-lock-type-face)
3716 font-lock-type-face
3717 'font-lock-type-face))
83261a2f
SM
3718 (stop-point (if ignore-max
3719 (point-max)
3720 max))
3721 (search
3722 (concat
4ab89e7b 3723 "\\(\\`\n?\\|^\n\\)=" ; POD
83261a2f
SM
3724 "\\|"
3725 ;; One extra () before this:
4ab89e7b 3726 "<<" ; HERE-DOC
83261a2f
SM
3727 "\\(" ; 1 + 1
3728 ;; First variant "BLAH" or just ``.
3729 "[ \t]*" ; Yes, whitespace is allowed!
3730 "\\([\"'`]\\)" ; 2 + 1 = 3
3731 "\\([^\"'`\n]*\\)" ; 3 + 1
3732 "\\3"
3733 "\\|"
f739b53b 3734 ;; Second variant: Identifier or \ID (same as 'ID') or empty
83261a2f
SM
3735 "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
3736 ;; Do not have <<= or << 30 or <<30 or << $blah.
3737 ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
3738 "\\(\\)" ; To preserve count of pars :-( 6 + 1
3739 "\\)"
3740 "\\|"
3741 ;; 1+6 extra () before this:
4ab89e7b 3742 "^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$" ;FRMAT
83261a2f 3743 (if cperl-use-syntax-table-text-property
db133cb6 3744 (concat
db133cb6 3745 "\\|"
83261a2f 3746 ;; 1+6+2=9 extra () before this:
4ab89e7b 3747 "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>" ; QUOTED CONSTRUCT
83261a2f
SM
3748 "\\|"
3749 ;; 1+6+2+1=10 extra () before this:
3750 "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
3751 "\\|"
4ab89e7b
SM
3752 ;; 1+6+2+1+1=11 extra () before this
3753 "\\<sub\\>" ; sub with proto/attr
3754 "\\("
3755 cperl-white-and-comment-rex
3756 "\\(::[a-zA-Z_:'0-9]*\\|[a-zA-Z_'][a-zA-Z_:'0-9]*\\)\\)?" ; name
3757 "\\("
3758 cperl-maybe-white-and-comment-rex
3759 "\\(([^()]*)\\|:[^:]\\)\\)" ; prototype or attribute start
83261a2f 3760 "\\|"
4ab89e7b
SM
3761 ;; 1+6+2+1+1+6=17 extra () before this:
3762 "\\$\\(['{]\\)" ; $' or ${foo}
83261a2f 3763 "\\|"
4ab89e7b
SM
3764 ;; 1+6+2+1+1+6+1=18 extra () before this (old pack'var syntax;
3765 ;; we do not support intervening comments...):
83261a2f 3766 "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'"
4ab89e7b 3767 ;; 1+6+2+1+1+6+1+1=19 extra () before this:
83261a2f 3768 "\\|"
4ab89e7b
SM
3769 "__\\(END\\|DATA\\)__" ; __END__ or __DATA__
3770 ;; 1+6+2+1+1+6+1+1+1=20 extra () before this:
db133cb6 3771 "\\|"
4ab89e7b 3772 "\\\\\\(['`\"($]\\)") ; BACKWACKED something-hairy
83261a2f 3773 ""))))
f83d2997
KH
3774 (unwind-protect
3775 (progn
3776 (save-excursion
3777 (or non-inter
3778 (message "Scanning for \"hard\" Perl constructions..."))
4ab89e7b 3779 ;;(message "find: %s --> %s" min max)
db133cb6 3780 (and cperl-pod-here-fontify
83261a2f
SM
3781 ;; We had evals here, do not know why...
3782 (setq face cperl-pod-face
3783 head-face cperl-pod-head-face
3784 here-face cperl-here-face))
5c8b7eaf 3785 (remove-text-properties min max
5bd52f0e 3786 '(syntax-type t in-pod t syntax-table t
4ab89e7b
SM
3787 attrib-group t
3788 REx-interpolated t
6c389151
SM
3789 cperl-postpone t
3790 syntax-subtype t
3791 rear-nonsticky t
4ab89e7b 3792 front-sticky t
f739b53b
SM
3793 here-doc-group t
3794 first-format-line t
4ab89e7b 3795 REx-part2 t
6c389151 3796 indentable t))
f83d2997
KH
3797 ;; Need to remove face as well...
3798 (goto-char min)
72bc50c0
GM
3799 ;; 'emx not supported by Emacs since at least 21.1.
3800 (and (featurep 'xemacs) (eq system-type 'emx)
4ab89e7b
SM
3801 (eq (point) 1)
3802 (let ((case-fold-search t))
3803 (looking-at "extproc[ \t]")) ; Analogue of #!
5c8b7eaf 3804 (cperl-commentify min
e180ab9f 3805 (point-at-eol)
db133cb6
RS
3806 nil))
3807 (while (and
3808 (< (point) max)
3809 (re-search-forward search max t))
5bd52f0e 3810 (setq tmpend nil) ; Valid for most cases
4ab89e7b
SM
3811 (setq b (match-beginning 0)
3812 state (save-excursion (parse-partial-sexp
3813 state-point b nil nil state))
3814 state-point b)
5c8b7eaf 3815 (cond
4ab89e7b
SM
3816 ;; 1+6+2+1+1+6=17 extra () before this:
3817 ;; "\\$\\(['{]\\)"
3818 ((match-beginning 18) ; $' or ${foo}
3819 (if (eq (preceding-char) ?\') ; $'
3820 (progn
3821 (setq b (1- (point))
3822 state (parse-partial-sexp
3823 state-point (1- b) nil nil state)
3824 state-point (1- b))
3825 (if (nth 3 state) ; in string
3826 (cperl-modify-syntax-type (1- b) cperl-st-punct))
3827 (goto-char (1+ b)))
3828 ;; else: ${
3829 (setq bb (match-beginning 0))
3830 (cperl-modify-syntax-type bb cperl-st-punct)))
3831 ;; No processing in strings/comments beyond this point:
3832 ((or (nth 3 state) (nth 4 state))
3833 t) ; Do nothing in comment/string
f83d2997 3834 ((match-beginning 1) ; POD section
a1506d29 3835 ;; "\\(\\`\n?\\|^\n\\)="
4ab89e7b
SM
3836 (setq b (match-beginning 0)
3837 state (parse-partial-sexp
3838 state-point b nil nil state)
3839 state-point b)
3840 (if (or (nth 3 state) (nth 4 state)
3841 (looking-at "cut\\>"))
3842 (if (or (nth 3 state) (nth 4 state) ignore-max)
5bd52f0e 3843 nil ; Doing a chunk only
f83d2997
KH
3844 (message "=cut is not preceded by a POD section")
3845 (or (car err-l) (setcar err-l (point))))
3846 (beginning-of-line)
5c8b7eaf
SS
3847
3848 (setq b (point)
5bd52f0e
RS
3849 bb b
3850 tb (match-beginning 0)
3851 b1 nil) ; error condition
db133cb6
RS
3852 ;; We do not search to max, since we may be called from
3853 ;; some hook of fontification, and max is random
6c389151 3854 (or (re-search-forward "^\n=cut\\>" stop-point 'toend)
f83d2997 3855 (progn
6c389151
SM
3856 (goto-char b)
3857 (if (re-search-forward "\n=cut\\>" stop-point 'toend)
3858 (progn
3859 (message "=cut is not preceded by an empty line")
3860 (setq b1 t)
3861 (or (car err-l) (setcar err-l b))))))
f83d2997
KH
3862 (beginning-of-line 2) ; An empty line after =cut is not POD!
3863 (setq e (point))
db133cb6 3864 (and (> e max)
6c389151 3865 (progn
a1506d29 3866 (remove-text-properties
6c389151 3867 max e '(syntax-type t in-pod t syntax-table t
4ab89e7b
SM
3868 attrib-group t
3869 REx-interpolated t
6c389151
SM
3870 cperl-postpone t
3871 syntax-subtype t
f739b53b 3872 here-doc-group t
6c389151 3873 rear-nonsticky t
4ab89e7b 3874 front-sticky t
f739b53b 3875 first-format-line t
4ab89e7b 3876 REx-part2 t
6c389151
SM
3877 indentable t))
3878 (setq tmpend tb)))
f83d2997 3879 (put-text-property b e 'in-pod t)
6c389151 3880 (put-text-property b e 'syntax-type 'in-pod)
f83d2997
KH
3881 (goto-char b)
3882 (while (re-search-forward "\n\n[ \t]" e t)
3883 ;; We start 'pod 1 char earlier to include the preceding line
3884 (beginning-of-line)
3885 (put-text-property (cperl-1- b) (point) 'syntax-type 'pod)
5efe6a56
SM
3886 (cperl-put-do-not-fontify b (point) t)
3887 ;; mark the non-literal parts as PODs
a1506d29 3888 (if cperl-pod-here-fontify
5efe6a56 3889 (cperl-postpone-fontification b (point) 'face face t))
f83d2997
KH
3890 (re-search-forward "\n\n[^ \t\f\n]" e 'toend)
3891 (beginning-of-line)
3892 (setq b (point)))
3893 (put-text-property (cperl-1- (point)) e 'syntax-type 'pod)
5efe6a56 3894 (cperl-put-do-not-fontify (point) e t)
a1506d29
JB
3895 (if cperl-pod-here-fontify
3896 (progn
5efe6a56
SM
3897 ;; mark the non-literal parts as PODs
3898 (cperl-postpone-fontification (point) e 'face face t)
3899 (goto-char bb)
a1506d29 3900 (if (looking-at
5efe6a56
SM
3901 "=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$")
3902 ;; mark the headers
a1506d29 3903 (cperl-postpone-fontification
5efe6a56 3904 (match-beginning 1) (match-end 1)
6c389151
SM
3905 'face head-face))
3906 (while (re-search-forward
3907 ;; One paragraph
3908 "^\n=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$"
3909 e 'toend)
3910 ;; mark the headers
a1506d29 3911 (cperl-postpone-fontification
5efe6a56
SM
3912 (match-beginning 1) (match-end 1)
3913 'face head-face))))
f83d2997
KH
3914 (cperl-commentify bb e nil)
3915 (goto-char e)
3916 (or (eq e (point-max))
83261a2f 3917 (forward-char -1)))) ; Prepare for immediate POD start.
f83d2997 3918 ;; Here document
4ab89e7b
SM
3919 ;; We can do many here-per-line;
3920 ;; but multiline quote on the same line as <<HERE confuses us...
5bd52f0e 3921 ;; ;; One extra () before this:
5c8b7eaf 3922 ;;"<<"
5bd52f0e
RS
3923 ;; "\\(" ; 1 + 1
3924 ;; ;; First variant "BLAH" or just ``.
f739b53b 3925 ;; "[ \t]*" ; Yes, whitespace is allowed!
5bd52f0e
RS
3926 ;; "\\([\"'`]\\)" ; 2 + 1
3927 ;; "\\([^\"'`\n]*\\)" ; 3 + 1
3928 ;; "\\3"
3929 ;; "\\|"
3930 ;; ;; Second variant: Identifier or \ID or empty
3931 ;; "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
3932 ;; ;; Do not have <<= or << 30 or <<30 or << $blah.
3933 ;; ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
3934 ;; "\\(\\)" ; To preserve count of pars :-( 6 + 1
3935 ;; "\\)"
f83d2997 3936 ((match-beginning 2) ; 1 + 1
4ab89e7b 3937 (setq b (point)
5bd52f0e 3938 tb (match-beginning 0)
4ab89e7b
SM
3939 c (and ; not HERE-DOC
3940 (match-beginning 5)
3941 (save-match-data
3942 (or (looking-at "[ \t]*(") ; << function_call()
3943 (save-excursion ; 1 << func_name, or $foo << 10
3944 (condition-case nil
3945 (progn
3946 (goto-char tb)
3947 ;;; XXX What to do: foo <<bar ???
3948 ;;; XXX Need to support print {a} <<B ???
3949 (forward-sexp -1)
cb5bf6ba 3950 (save-match-data
4ab89e7b
SM
3951 ; $foo << b; $f .= <<B;
3952 ; ($f+1) << b; a($f) . <<B;
3953 ; foo 1, <<B; $x{a} <<b;
3954 (cond
3955 ((looking-at "[0-9$({]")
3956 (forward-sexp 1)
3957 (and
3958 (looking-at "[ \t]*<<")
3959 (condition-case nil
3960 ;; print $foo <<EOF
3961 (progn
3962 (forward-sexp -2)
3963 (not
3964 (looking-at "\\(printf?\\|system\\|exec\\|sort\\)\\>")))
3965 (error t)))))))
3966 (error nil))) ; func(<<EOF)
3967 (and (not (match-beginning 6)) ; Empty
3968 (looking-at
3969 "[ \t]*[=0-9$@%&(]"))))))
5bd52f0e
RS
3970 (if c ; Not here-doc
3971 nil ; Skip it.
4ab89e7b 3972 (setq c (match-end 2)) ; 1 + 1
f83d2997
KH
3973 (if (match-beginning 5) ;4 + 1
3974 (setq b1 (match-beginning 5) ; 4 + 1
3975 e1 (match-end 5)) ; 4 + 1
3976 (setq b1 (match-beginning 4) ; 3 + 1
3977 e1 (match-end 4))) ; 3 + 1
3978 (setq tag (buffer-substring b1 e1)
3979 qtag (regexp-quote tag))
5c8b7eaf 3980 (cond (cperl-pod-here-fontify
5bd52f0e 3981 ;; Highlight the starting delimiter
cb5bf6ba 3982 (cperl-postpone-fontification
4ab89e7b 3983 b1 e1 'face my-cperl-delimiters-face)
5bd52f0e 3984 (cperl-put-do-not-fontify b1 e1 t)))
f83d2997 3985 (forward-line)
4ab89e7b
SM
3986 (setq i (point))
3987 (if end-of-here-doc
3988 (goto-char end-of-here-doc))
f83d2997 3989 (setq b (point))
db133cb6
RS
3990 ;; We do not search to max, since we may be called from
3991 ;; some hook of fontification, and max is random
f739b53b
SM
3992 (or (and (re-search-forward (concat "^" qtag "$")
3993 stop-point 'toend)
4ab89e7b
SM
3994 ;;;(eq (following-char) ?\n) ; XXXX WHY???
3995 )
f739b53b
SM
3996 (progn ; Pretend we matched at the end
3997 (goto-char (point-max))
3998 (re-search-forward "\\'")
3999 (message "End of here-document `%s' not found." tag)
4000 (or (car err-l) (setcar err-l b))))
4001 (if cperl-pod-here-fontify
4002 (progn
4003 ;; Highlight the ending delimiter
4ab89e7b
SM
4004 (cperl-postpone-fontification
4005 (match-beginning 0) (match-end 0)
4006 'face my-cperl-delimiters-face)
f739b53b
SM
4007 (cperl-put-do-not-fontify b (match-end 0) t)
4008 ;; Highlight the HERE-DOC
4009 (cperl-postpone-fontification b (match-beginning 0)
4010 'face here-face)))
4011 (setq e1 (cperl-1+ (match-end 0)))
4012 (put-text-property b (match-beginning 0)
4013 'syntax-type 'here-doc)
4014 (put-text-property (match-beginning 0) e1
4015 'syntax-type 'here-doc-delim)
4ab89e7b
SM
4016 (put-text-property b e1 'here-doc-group t)
4017 ;; This makes insertion at the start of HERE-DOC update
4018 ;; the whole construct:
4019 (put-text-property b (cperl-1+ b) 'front-sticky '(syntax-type))
f739b53b
SM
4020 (cperl-commentify b e1 nil)
4021 (cperl-put-do-not-fontify b (match-end 0) t)
4ab89e7b
SM
4022 ;; Cache the syntax info...
4023 (setq cperl-syntax-state (cons state-point state))
4024 ;; ... and process the rest of the line...
4025 (setq overshoot
4026 (elt ; non-inter ignore-max
4027 (cperl-find-pods-heres c i t end t e1) 1))
4028 (if (and overshoot (> overshoot (point)))
4029 (goto-char overshoot)
4030 (setq overshoot e1))
f739b53b
SM
4031 (if (> e1 max)
4032 (setq tmpend tb))))
f83d2997
KH
4033 ;; format
4034 ((match-beginning 8)
4035 ;; 1+6=7 extra () before this:
4036 ;;"^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
4037 (setq b (point)
4038 name (if (match-beginning 8) ; 7 + 1
4039 (buffer-substring (match-beginning 8) ; 7 + 1
4040 (match-end 8)) ; 7 + 1
5bd52f0e
RS
4041 "")
4042 tb (match-beginning 0))
f83d2997 4043 (setq argument nil)
9b026d9f 4044 (put-text-property (point-at-bol) b 'first-format-line 't)
5c8b7eaf 4045 (if cperl-pod-here-fontify
f83d2997
KH
4046 (while (and (eq (forward-line) 0)
4047 (not (looking-at "^[.;]$")))
4048 (cond
4049 ((looking-at "^#")) ; Skip comments
4050 ((and argument ; Skip argument multi-lines
5c8b7eaf 4051 (looking-at "^[ \t]*{"))
f83d2997
KH
4052 (forward-sexp 1)
4053 (setq argument nil))
4054 (argument ; Skip argument lines
4055 (setq argument nil))
4056 (t ; Format line
4057 (setq b1 (point))
4058 (setq argument (looking-at "^[^\n]*[@^]"))
4059 (end-of-line)
5bd52f0e 4060 ;; Highlight the format line
5c8b7eaf 4061 (cperl-postpone-fontification b1 (point)
83261a2f 4062 'face font-lock-string-face)
f83d2997 4063 (cperl-commentify b1 (point) nil)
5bd52f0e 4064 (cperl-put-do-not-fontify b1 (point) t))))
db133cb6
RS
4065 ;; We do not search to max, since we may be called from
4066 ;; some hook of fontification, and max is random
4067 (re-search-forward "^[.;]$" stop-point 'toend))
f83d2997 4068 (beginning-of-line)
83261a2f 4069 (if (looking-at "^\\.$") ; ";" is not supported yet
f83d2997 4070 (progn
5bd52f0e
RS
4071 ;; Highlight the ending delimiter
4072 (cperl-postpone-fontification (point) (+ (point) 2)
83261a2f 4073 'face font-lock-string-face)
f83d2997 4074 (cperl-commentify (point) (+ (point) 2) nil)
5bd52f0e 4075 (cperl-put-do-not-fontify (point) (+ (point) 2) t))
f83d2997
KH
4076 (message "End of format `%s' not found." name)
4077 (or (car err-l) (setcar err-l b)))
4078 (forward-line)
5bd52f0e
RS
4079 (if (> (point) max)
4080 (setq tmpend tb))
db133cb6 4081 (put-text-property b (point) 'syntax-type 'format))
4ab89e7b 4082 ;; qq-like String or Regexp:
f83d2997
KH
4083 ((or (match-beginning 10) (match-beginning 11))
4084 ;; 1+6+2=9 extra () before this:
5bd52f0e 4085 ;; "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
f83d2997 4086 ;; "\\|"
5bd52f0e 4087 ;; "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
f83d2997
KH
4088 (setq b1 (if (match-beginning 10) 10 11)
4089 argument (buffer-substring
4090 (match-beginning b1) (match-end b1))
4ab89e7b 4091 b (point) ; end of qq etc
f83d2997
KH
4092 i b
4093 c (char-after (match-beginning b1))
4ab89e7b 4094 bb (char-after (1- (match-beginning b1))) ; tmp holder
5bd52f0e
RS
4095 ;; bb == "Not a stringy"
4096 bb (if (eq b1 10) ; user variables/whatever
f739b53b
SM
4097 (and (memq bb (append "$@%*#_:-&>" nil)) ; $#y)
4098 (cond ((eq bb ?-) (eq c ?s)) ; -s file test
4099 ((eq bb ?\:) ; $opt::s
4100 (eq (char-after
4101 (- (match-beginning b1) 2))
4102 ?\:))
4103 ((eq bb ?\>) ; $foo->s
4104 (eq (char-after
4105 (- (match-beginning b1) 2))
4106 ?\-))
4107 ((eq bb ?\&)
4ab89e7b 4108 (not (eq (char-after ; &&m/blah/
f739b53b
SM
4109 (- (match-beginning b1) 2))
4110 ?\&)))
4111 (t t)))
5bd52f0e
RS
4112 ;; <file> or <$file>
4113 (and (eq c ?\<)
6c389151 4114 ;; Do not stringify <FH>, <$fh> :
5bd52f0e 4115 (save-match-data
5c8b7eaf 4116 (looking-at
6c389151 4117 "\\$?\\([_a-zA-Z:][_a-zA-Z0-9:]*\\)?>"))))
5bd52f0e 4118 tb (match-beginning 0))
db133cb6
RS
4119 (goto-char (match-beginning b1))
4120 (cperl-backward-to-noncomment (point-min))
f83d2997 4121 (or bb
5bd52f0e 4122 (if (eq b1 11) ; bare /blah/ or ?blah? or <foo>
f83d2997 4123 (setq argument ""
f739b53b 4124 b1 nil
db133cb6 4125 bb ; Not a regexp?
4ab89e7b
SM
4126 (not
4127 ;; What is below: regexp-p?
4128 (and
4129 (or (memq (preceding-char)
4130 (append (if (memq c '(?\? ?\<))
4131 ;; $a++ ? 1 : 2
4132 "~{(=|&*!,;:["
4133 "~{(=|&+-*!,;:[") nil))
4134 (and (eq (preceding-char) ?\})
4135 (cperl-after-block-p (point-min)))
4136 (and (eq (char-syntax (preceding-char)) ?w)
4137 (progn
4138 (forward-sexp -1)
6c389151
SM
4139;; After these keywords `/' starts a RE. One should add all the
4140;; functions/builtins which expect an argument, but ...
4ab89e7b
SM
4141 (if (eq (preceding-char) ?-)
4142 ;; -d ?foo? is a RE
4143 (looking-at "[a-zA-Z]\\>")
4144 (and
4145 (not (memq (preceding-char)
4146 '(?$ ?@ ?& ?%)))
4147 (looking-at
4148 "\\(while\\|if\\|unless\\|until\\|and\\|or\\|not\\|xor\\|split\\|grep\\|map\\|print\\)\\>")))))
4149 (and (eq (preceding-char) ?.)
4150 (eq (char-after (- (point) 2)) ?.))
4151 (bobp))
4152 ;; m|blah| ? foo : bar;
4153 (not
4154 (and (eq c ?\?)
4155 cperl-use-syntax-table-text-property
4156 (not (bobp))
4157 (progn
4158 (forward-char -1)
4159 (looking-at "\\s|"))))))
db133cb6
RS
4160 b (1- b))
4161 ;; s y tr m
f739b53b
SM
4162 ;; Check for $a -> y
4163 (setq b1 (preceding-char)
4164 go (point))
4165 (if (and (eq b1 ?>)
4166 (eq (char-after (- go 2)) ?-))
db133cb6
RS
4167 ;; Not a regexp
4168 (setq bb t))))
f739b53b
SM
4169 (or bb
4170 (progn
4ab89e7b 4171 (goto-char b)
f739b53b
SM
4172 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
4173 (goto-char (match-end 0))
4174 (skip-chars-forward " \t\n\f"))
4175 (cond ((and (eq (following-char) ?\})
4176 (eq b1 ?\{))
4177 ;; Check for $a[23]->{ s }, @{s} and *{s::foo}
4178 (goto-char (1- go))
4179 (skip-chars-backward " \t\n\f")
4180 (if (memq (preceding-char) (append "$@%&*" nil))
4181 (setq bb t) ; @{y}
4182 (condition-case nil
4183 (forward-sexp -1)
4184 (error nil)))
4185 (if (or bb
4186 (looking-at ; $foo -> {s}
4187 "[$@]\\$*\\([a-zA-Z0-9_:]+\\|[^{]\\)\\([ \t\n]*->\\)?[ \t\n]*{")
4188 (and ; $foo[12] -> {s}
4189 (memq (following-char) '(?\{ ?\[))
4190 (progn
4191 (forward-sexp 1)
4192 (looking-at "\\([ \t\n]*->\\)?[ \t\n]*{"))))
4193 (setq bb t)
4194 (goto-char b)))
4195 ((and (eq (following-char) ?=)
4196 (eq (char-after (1+ (point))) ?\>))
4197 ;; Check for { foo => 1, s => 2 }
4198 ;; Apparently s=> is never a substitution...
4199 (setq bb t))
4200 ((and (eq (following-char) ?:)
4201 (eq b1 ?\{) ; Check for $ { s::bar }
4202 (looking-at "::[a-zA-Z0-9_:]*[ \t\n\f]*}")
15ca5699 4203 (progn
f739b53b
SM
4204 (goto-char (1- go))
4205 (skip-chars-backward " \t\n\f")
4206 (memq (preceding-char)
4207 (append "$@%&*" nil))))
4ab89e7b
SM
4208 (setq bb t))
4209 ((eobp)
f739b53b
SM
4210 (setq bb t)))))
4211 (if bb
f83d2997 4212 (goto-char i)
6c389151 4213 ;; Skip whitespace and comments...
f83d2997
KH
4214 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
4215 (goto-char (match-end 0))
4216 (skip-chars-forward " \t\n\f"))
6c389151
SM
4217 (if (> (point) b)
4218 (put-text-property b (point) 'syntax-type 'prestring))
f83d2997
KH
4219 ;; qtag means two-arg matcher, may be reset to
4220 ;; 2 or 3 later if some special quoting is needed.
4221 ;; e1 means matching-char matcher.
4ab89e7b 4222 (setq b (point) ; before the first delimiter
5bd52f0e
RS
4223 ;; has 2 args
4224 i2 (string-match "^\\([sy]\\|tr\\)$" argument)
db133cb6
RS
4225 ;; We do not search to max, since we may be called from
4226 ;; some hook of fontification, and max is random
4227 i (cperl-forward-re stop-point end
5bd52f0e 4228 i2
4ab89e7b
SM
4229 st-l err-l argument)
4230 ;; If `go', then it is considered as 1-arg, `b1' is nil
4231 ;; as in s/foo//x; the point is before final "slash"
5bd52f0e 4232 b1 (nth 1 i) ; start of the second part
5c8b7eaf 4233 tag (nth 2 i) ; ender-char, true if second part
5bd52f0e 4234 ; is with matching chars []
f83d2997
KH
4235 go (nth 4 i) ; There is a 1-char part after the end
4236 i (car i) ; intermediate point
5c8b7eaf 4237 e1 (point) ; end
5bd52f0e 4238 ;; Before end of the second part if non-matching: ///
5c8b7eaf 4239 tail (if (and i (not tag))
5bd52f0e
RS
4240 (1- e1))
4241 e (if i i e1) ; end of the first part
6c389151 4242 qtag nil ; need to preserve backslashitis
4ab89e7b
SM
4243 is-x-REx nil is-o-REx nil); REx has //x //o modifiers
4244 ;; If s{} (), then b/b1 are at "{", "(", e1/i after ")", "}"
f83d2997
KH
4245 ;; Commenting \\ is dangerous, what about ( ?
4246 (and i tail
4247 (eq (char-after i) ?\\)
5bd52f0e 4248 (setq qtag t))
4ab89e7b
SM
4249 (and (if go (looking-at ".\\sw*x")
4250 (looking-at "\\sw*x")) ; qr//x
4251 (setq is-x-REx t))
4252 (and (if go (looking-at ".\\sw*o")
4253 (looking-at "\\sw*o")) ; //o
4254 (setq is-o-REx t))
f83d2997 4255 (if (null i)
5bd52f0e 4256 ;; Considered as 1arg form
f83d2997
KH
4257 (progn
4258 (cperl-commentify b (point) t)
5bd52f0e 4259 (put-text-property b (point) 'syntax-type 'string)
6c389151
SM
4260 (if (or is-x-REx
4261 ;; ignore other text properties:
4262 (string-match "^qw$" argument))
4263 (put-text-property b (point) 'indentable t))
5bd52f0e
RS
4264 (and go
4265 (setq e1 (cperl-1+ e1))
4266 (or (eobp)
4267 (forward-char 1))))
f83d2997
KH
4268 (cperl-commentify b i t)
4269 (if (looking-at "\\sw*e") ; s///e
4270 (progn
4ab89e7b
SM
4271 ;; Cache the syntax info...
4272 (setq cperl-syntax-state (cons state-point state))
f83d2997
KH
4273 (and
4274 ;; silent:
4ab89e7b 4275 (car (cperl-find-pods-heres b1 (1- (point)) t end))
f83d2997
KH
4276 ;; Error
4277 (goto-char (1+ max)))
5bd52f0e 4278 (if (and tag (eq (preceding-char) ?\>))
f83d2997
KH
4279 (progn
4280 (cperl-modify-syntax-type (1- (point)) cperl-st-ket)
5bd52f0e 4281 (cperl-modify-syntax-type i cperl-st-bra)))
6c389151 4282 (put-text-property b i 'syntax-type 'string)
4ab89e7b 4283 (put-text-property i (point) 'syntax-type 'multiline)
6c389151
SM
4284 (if is-x-REx
4285 (put-text-property b i 'indentable t)))
5bd52f0e
RS
4286 (cperl-commentify b1 (point) t)
4287 (put-text-property b (point) 'syntax-type 'string)
6c389151
SM
4288 (if is-x-REx
4289 (put-text-property b i 'indentable t))
5bd52f0e 4290 (if qtag
db133cb6 4291 (cperl-modify-syntax-type (1+ i) cperl-st-punct))
f83d2997 4292 (setq tail nil)))
5bd52f0e 4293 ;; Now: tail: if the second part is non-matching without ///e
f83d2997
KH
4294 (if (eq (char-syntax (following-char)) ?w)
4295 (progn
4296 (forward-word 1) ; skip modifiers s///s
5bd52f0e 4297 (if tail (cperl-commentify tail (point) t))
a1506d29 4298 (cperl-postpone-fontification
4ab89e7b 4299 e1 (point) 'face my-cperl-REx-modifiers-face)))
5bd52f0e
RS
4300 ;; Check whether it is m// which means "previous match"
4301 ;; and highlight differently
a1506d29 4302 (setq is-REx
6c389151
SM
4303 (and (string-match "^\\([sm]?\\|qr\\)$" argument)
4304 (or (not (= (length argument) 0))
4305 (not (eq c ?\<)))))
a1506d29 4306 (if (and is-REx
6c389151 4307 (eq e (+ 2 b))
5bd52f0e
RS
4308 ;; split // *is* using zero-pattern
4309 (save-excursion
4310 (condition-case nil
4311 (progn
4312 (goto-char tb)
4313 (forward-sexp -1)
4314 (not (looking-at "split\\>")))
4315 (error t))))
5c8b7eaf 4316 (cperl-postpone-fontification
4ab89e7b 4317 b e 'face font-lock-warning-face)
5bd52f0e
RS
4318 (if (or i2 ; Has 2 args
4319 (and cperl-fontify-m-as-s
4320 (or
4321 (string-match "^\\(m\\|qr\\)$" argument)
4322 (and (eq 0 (length argument))
4323 (not (eq ?\< (char-after b)))))))
4324 (progn
5c8b7eaf 4325 (cperl-postpone-fontification
4ab89e7b 4326 b (cperl-1+ b) 'face my-cperl-delimiters-face)
5c8b7eaf 4327 (cperl-postpone-fontification
4ab89e7b 4328 (1- e) e 'face my-cperl-delimiters-face)))
6c389151 4329 (if (and is-REx cperl-regexp-scan)
4ab89e7b
SM
4330 ;; Process RExen: embedded comments, charclasses and ]
4331;;;/\3333\xFg\x{FFF}a\ppp\PPP\qqq\C\99f(?{ foo })(??{ foo })/;
4332;;;/a\.b[^a[:ff:]b]x$ab->$[|$,$ab->[cd]->[ef]|$ab[xy].|^${a,b}{c,d}/;
4333;;;/(?<=foo)(?<!bar)(x)(?:$ab|\$\/)$|\\\b\x888\776\[\:$/xxx;
4334;;;m?(\?\?{b,a})? + m/(??{aa})(?(?=xx)aa|bb)(?#aac)/;
4335;;;m$(^ab[c]\$)$ + m+(^ab[c]\$\+)+ + m](^ab[c\]$|.+)] + m)(^ab[c]$|.+\));
4336;;;m^a[\^b]c^ + m.a[^b]\.c.;
6c389151
SM
4337 (save-excursion
4338 (goto-char (1+ b))
cb5bf6ba 4339 ;; First
4ab89e7b
SM
4340 (cperl-look-at-leading-count is-x-REx e)
4341 (setq hairy-RE
4342 (concat
4343 (if is-x-REx
4344 (if (eq (char-after b) ?\#)
4345 "\\((\\?\\\\#\\)\\|\\(\\\\#\\)"
4346 "\\((\\?#\\)\\|\\(#\\)")
4347 ;; keep the same count: add a fake group
4348 (if (eq (char-after b) ?\#)
4349 "\\((\\?\\\\#\\)\\(\\)"
4350 "\\((\\?#\\)\\(\\)"))
4351 "\\|"
4352 "\\(\\[\\)" ; 3=[
4353 "\\|"
4354 "\\(]\\)" ; 4=]
4355 "\\|"
4356 ;; XXXX Will not be able to use it in s)))
4357 (if (eq (char-after b) ?\) )
4358 "\\())))\\)" ; Will never match
4359 (if (eq (char-after b) ?? )
4360 ;;"\\((\\\\\\?\\(\\\\\\?\\)?{\\)"
4361 "\\((\\\\\\?\\\\\\?{\\|()\\\\\\?{\\)"
4362 "\\((\\?\\??{\\)")) ; 5= (??{ (?{
4363 "\\|" ; 6= 0-length, 7: name, 8,9:code, 10:group
4364 "\\(" ;; XXXX 1-char variables, exc. |()\s
4365 "[$@]"
4366 "\\("
4367 "[_a-zA-Z:][_a-zA-Z0-9:]*"
4368 "\\|"
4369 "{[^{}]*}" ; only one-level allowed
4370 "\\|"
4371 "[^{(|) \t\r\n\f]"
4372 "\\)"
4373 "\\(" ;;8,9:code part of array/hash elt
4374 "\\(" "->" "\\)?"
4375 "\\[[^][]*\\]"
4376 "\\|"
4377 "{[^{}]*}"
4378 "\\)*"
4379 ;; XXXX: what if u is delim?
4380 "\\|"
4381 "[)^|$.*?+]"
4382 "\\|"
4383 "{[0-9]+}"
4384 "\\|"
4385 "{[0-9]+,[0-9]*}"
4386 "\\|"
4387 "\\\\[luLUEQbBAzZG]"
4388 "\\|"
4389 "(" ; Group opener
4390 "\\(" ; 10 group opener follower
4391 "\\?\\((\\?\\)" ; 11: in (?(?=C)A|B)
4392 "\\|"
4393 "\\?[:=!>?{]" ; "?" something
4394 "\\|"
4395 "\\?[-imsx]+[:)]" ; (?i) (?-s:.)
4396 "\\|"
4397 "\\?([0-9]+)" ; (?(1)foo|bar)
4398 "\\|"
4399 "\\?<[=!]"
4400 ;;;"\\|"
4401 ;;; "\\?"
4402 "\\)?"
4403 "\\)"
4404 "\\|"
4405 "\\\\\\(.\\)" ; 12=\SYMBOL
4406 ))
6c389151 4407 (while
4ab89e7b
SM
4408 (and (< (point) (1- e))
4409 (re-search-forward hairy-RE (1- e) 'to-end))
6c389151 4410 (goto-char (match-beginning 0))
4ab89e7b
SM
4411 (setq REx-subgr-start (point)
4412 was-subgr (following-char))
4413 (cond
4414 ((match-beginning 6) ; 0-length builtins, groups
4415 (goto-char (match-end 0))
4416 (if (match-beginning 11)
4417 (goto-char (match-beginning 11)))
4418 (if (>= (point) e)
4419 (goto-char (1- e)))
4420 (cperl-postpone-fontification
4421 (match-beginning 0) (point)
4422 'face
4423 (cond
4424 ((eq was-subgr ?\) )
4425 (condition-case nil
4426 (save-excursion
4427 (forward-sexp -1)
4428 (if (> (point) b)
4429 (if (if (eq (char-after b) ?? )
4430 (looking-at "(\\\\\\?")
4431 (eq (char-after (1+ (point))) ?\?))
4432 my-cperl-REx-0length-face
4433 my-cperl-REx-ctl-face)
4434 font-lock-warning-face))
4435 (error font-lock-warning-face)))
4436 ((eq was-subgr ?\| )
4437 my-cperl-REx-ctl-face)
4438 ((eq was-subgr ?\$ )
4439 (if (> (point) (1+ REx-subgr-start))
4440 (progn
4441 (put-text-property
4442 (match-beginning 0) (point)
4443 'REx-interpolated
4444 (if is-o-REx 0
4445 (if (and (eq (match-beginning 0)
4446 (1+ b))
4447 (eq (point)
4448 (1- e))) 1 t)))
4449 font-lock-variable-name-face)
4450 my-cperl-REx-spec-char-face))
4451 ((memq was-subgr (append "^." nil) )
4452 my-cperl-REx-spec-char-face)
4453 ((eq was-subgr ?\( )
4454 (if (not (match-beginning 10))
4455 my-cperl-REx-ctl-face
4456 my-cperl-REx-0length-face))
4457 (t my-cperl-REx-0length-face)))
4458 (if (and (memq was-subgr (append "(|" nil))
4459 (not (string-match "(\\?[-imsx]+)"
4460 (match-string 0))))
4461 (cperl-look-at-leading-count is-x-REx e))
4462 (setq was-subgr nil)) ; We do stuff here
4463 ((match-beginning 12) ; \SYMBOL
4464 (forward-char 2)
4465 (if (>= (point) e)
4466 (goto-char (1- e))
4467 ;; How many chars to not highlight:
4468 ;; 0-len special-alnums in other branch =>
4469 ;; Generic: \non-alnum (1), \alnum (1+face)
4470 ;; Is-delim: \non-alnum (1/spec-2) alnum-1 (=what hai)
4471 (setq REx-subgr-start (point)
4472 qtag (preceding-char))
4473 (cperl-postpone-fontification
4474 (- (point) 2) (- (point) 1) 'face
4475 (if (memq qtag
4476 (append "ghijkmoqvFHIJKMORTVY" nil))
4477 font-lock-warning-face
4478 my-cperl-REx-0length-face))
4479 (if (and (eq (char-after b) qtag)
4480 (memq qtag (append ".])^$|*?+" nil)))
4481 (progn
4482 (if (and cperl-use-syntax-table-text-property
4483 (eq qtag ?\) ))
4484 (put-text-property
4485 REx-subgr-start (1- (point))
4486 'syntax-table cperl-st-punct))
4487 (cperl-postpone-fontification
4488 (1- (point)) (point) 'face
4489 ; \] can't appear below
4490 (if (memq qtag (append ".]^$" nil))
4491 'my-cperl-REx-spec-char-face
4492 (if (memq qtag (append "*?+" nil))
4493 'my-cperl-REx-0length-face
4494 'my-cperl-REx-ctl-face))))) ; )|
4495 ;; Test for arguments:
4496 (cond
4497 ;; This is not pretty: the 5.8.7 logic:
4498 ;; \0numx -> octal (up to total 3 dig)
4499 ;; \DIGIT -> backref unless \0
cb5bf6ba 4500 ;; \DIGITs -> backref if valid
4ab89e7b
SM
4501 ;; otherwise up to 3 -> octal
4502 ;; Do not try to distinguish, we guess
4503 ((or (and (memq qtag (append "01234567" nil))
4504 (re-search-forward
4505 "\\=[01234567]?[01234567]?"
4506 (1- e) 'to-end))
4507 (and (memq qtag (append "89" nil))
cb5bf6ba 4508 (re-search-forward
4ab89e7b
SM
4509 "\\=[0123456789]*" (1- e) 'to-end))
4510 (and (eq qtag ?x)
4511 (re-search-forward
4512 "\\=[0-9a-fA-F][0-9a-fA-F]?\\|\\={[0-9a-fA-F]+}"
4513 (1- e) 'to-end))
4514 (and (memq qtag (append "pPN" nil))
4515 (re-search-forward "\\={[^{}]+}\\|."
4516 (1- e) 'to-end))
4517 (eq (char-syntax qtag) ?w))
4518 (cperl-postpone-fontification
4519 (1- REx-subgr-start) (point)
4520 'face my-cperl-REx-length1-face))))
4521 (setq was-subgr nil)) ; We do stuff here
4522 ((match-beginning 3) ; [charclass]
8c777c8d 4523 ;; Highlight leader, trailer, POSIX classes
4ab89e7b
SM
4524 (forward-char 1)
4525 (if (eq (char-after b) ?^ )
4526 (and (eq (following-char) ?\\ )
4527 (eq (char-after (cperl-1+ (point)))
4528 ?^ )
4529 (forward-char 2))
4530 (and (eq (following-char) ?^ )
4531 (forward-char 1)))
8c777c8d 4532 (setq argument b ; continue? & end of last POSIX
4ab89e7b 4533 tag nil ; list of POSIX classes
8c777c8d 4534 qtag (point)) ; after leading ^ if present
4ab89e7b
SM
4535 (if (eq (char-after b) ?\] )
4536 (and (eq (following-char) ?\\ )
4537 (eq (char-after (cperl-1+ (point)))
4538 ?\] )
4539 (setq qtag (1+ qtag))
4540 (forward-char 2))
4541 (and (eq (following-char) ?\] )
4542 (forward-char 1)))
3ed8598c 4543 (setq REx-subgr-end qtag) ;End smart-highlighted
4ab89e7b
SM
4544 ;; Apparently, I can't put \] into a charclass
4545 ;; in m]]: m][\\\]\]] produces [\\]]
4546;;; POSIX? [:word:] [:^word:] only inside []
8c777c8d
CY
4547;;; "\\=\\(\\\\.\\|[^][\\\\]\\|\\[:\\^?\sw+:]\\|\\[[^:]\\)*]")
4548 (while ; look for unescaped ]
4ab89e7b
SM
4549 (and argument
4550 (re-search-forward
4551 (if (eq (char-after b) ?\] )
4552 "\\=\\(\\\\[^]]\\|[^]\\\\]\\)*\\\\]"
4553 "\\=\\(\\\\.\\|[^]\\\\]\\)*]")
4554 (1- e) 'toend))
4555 ;; Is this ] an end of POSIX class?
4556 (if (save-excursion
4557 (and
4558 (search-backward "[" argument t)
4559 (< REx-subgr-start (point))
8c777c8d
CY
4560 (setq argument (point)) ; POSIX-start
4561 (or ; Should work with delim = \
4562 (not (eq (preceding-char) ?\\ ))
4563 ;; XXXX Double \\ is needed with 19.33
4564 (= (% (skip-chars-backward "\\\\") 2) 0))
4ab89e7b
SM
4565 (looking-at
4566 (cond
4567 ((eq (char-after b) ?\] )
4568 "\\\\*\\[:\\^?\\sw+:\\\\\\]")
4569 ((eq (char-after b) ?\: )
4570 "\\\\*\\[\\\\:\\^?\\sw+\\\\:]")
4571 ((eq (char-after b) ?^ )
4572 "\\\\*\\[:\\(\\\\\\^\\)?\\sw+:\]")
4573 ((eq (char-syntax (char-after b))
4574 ?w)
4575 (concat
4576 "\\\\*\\[:\\(\\\\\\^\\)?\\(\\\\"
4577 (char-to-string (char-after b))
4578 "\\|\\sw\\)+:\]"))
4579 (t "\\\\*\\[:\\^?\\sw*:]")))
8c777c8d
CY
4580 (goto-char REx-subgr-end)
4581 (cperl-highlight-charclass
4582 argument my-cperl-REx-spec-char-face
4583 my-cperl-REx-0length-face my-cperl-REx-length1-face)))
4ab89e7b
SM
4584 (setq tag (cons (cons argument (point))
4585 tag)
8c777c8d
CY
4586 argument (point)
4587 REx-subgr-end argument) ; continue
4ab89e7b
SM
4588 (setq argument nil)))
4589 (and argument
4590 (message "Couldn't find end of charclass in a REx, pos=%s"
4591 REx-subgr-start))
8c777c8d
CY
4592 (setq argument (1- (point)))
4593 (goto-char REx-subgr-end)
4594 (cperl-highlight-charclass
4595 argument my-cperl-REx-spec-char-face
4596 my-cperl-REx-0length-face my-cperl-REx-length1-face)
4597 (forward-char 1)
4598 ;; Highlight starter, trailer, POSIX
4ab89e7b
SM
4599 (if (and cperl-use-syntax-table-text-property
4600 (> (- (point) 2) REx-subgr-start))
4601 (put-text-property
4602 (1+ REx-subgr-start) (1- (point))
4603 'syntax-table cperl-st-punct))
4604 (cperl-postpone-fontification
4605 REx-subgr-start qtag
4606 'face my-cperl-REx-spec-char-face)
4607 (cperl-postpone-fontification
4608 (1- (point)) (point) 'face
4609 my-cperl-REx-spec-char-face)
4610 (if (eq (char-after b) ?\] )
4611 (cperl-postpone-fontification
4612 (- (point) 2) (1- (point))
4613 'face my-cperl-REx-0length-face))
4614 (while tag
4615 (cperl-postpone-fontification
4616 (car (car tag)) (cdr (car tag))
8c777c8d 4617 'face font-lock-variable-name-face) ;my-cperl-REx-length1-face
4ab89e7b
SM
4618 (setq tag (cdr tag)))
4619 (setq was-subgr nil)) ; did facing already
4620 ;; Now rare stuff:
4621 ((and (match-beginning 2) ; #-comment
4622 (/= (match-beginning 2) (match-end 2)))
4623 (beginning-of-line 2)
4624 (if (> (point) e)
4625 (goto-char (1- e))))
4626 ((match-beginning 4) ; character "]"
4627 (setq was-subgr nil) ; We do stuff here
4628 (goto-char (match-end 0))
4629 (if cperl-use-syntax-table-text-property
4630 (put-text-property
4631 (1- (point)) (point)
4632 'syntax-table cperl-st-punct))
4633 (cperl-postpone-fontification
4634 (1- (point)) (point)
4635 'face font-lock-warning-face))
4636 ((match-beginning 5) ; before (?{}) (??{})
4637 (setq tag (match-end 0))
4638 (if (or (setq qtag
4639 (cperl-forward-group-in-re st-l))
4640 (and (>= (point) e)
4641 (setq qtag "no matching `)' found"))
4642 (and (not (eq (char-after (- (point) 2))
4643 ?\} ))
4644 (setq qtag "Can't find })")))
a1506d29 4645 (progn
4ab89e7b 4646 (goto-char (1- e))
274f1353 4647 (message "%s" qtag))
4ab89e7b
SM
4648 (cperl-postpone-fontification
4649 (1- tag) (1- (point))
4650 'face font-lock-variable-name-face)
4651 (cperl-postpone-fontification
4652 REx-subgr-start (1- tag)
4653 'face my-cperl-REx-spec-char-face)
4654 (cperl-postpone-fontification
4655 (1- (point)) (point)
4656 'face my-cperl-REx-spec-char-face)
4657 (if cperl-use-syntax-table-text-property
4658 (progn
4659 (put-text-property
4660 (- (point) 2) (1- (point))
4661 'syntax-table cperl-st-cfence)
4662 (put-text-property
4663 (+ REx-subgr-start 2)
4664 (+ REx-subgr-start 3)
4665 'syntax-table cperl-st-cfence))))
4666 (setq was-subgr nil))
4667 (t ; (?#)-comment
4668 ;; Inside "(" and "\" arn't special in any way
4669 ;; Works also if the outside delimiters are ().
4670 (or;;(if (eq (char-after b) ?\) )
4671 ;;(re-search-forward
4672 ;; "[^\\\\]\\(\\\\\\\\\\)*\\\\)"
4673 ;; (1- e) 'toend)
4674 (search-forward ")" (1- e) 'toend)
4675 ;;)
4676 (message
4677 "Couldn't find end of (?#...)-comment in a REx, pos=%s"
4678 REx-subgr-start))))
6c389151
SM
4679 (if (>= (point) e)
4680 (goto-char (1- e)))
4ab89e7b
SM
4681 (cond
4682 (was-subgr
4683 (setq REx-subgr-end (point))
4684 (cperl-commentify
4685 REx-subgr-start REx-subgr-end nil)
4686 (cperl-postpone-fontification
4687 REx-subgr-start REx-subgr-end
4688 'face font-lock-comment-face))))))
6c389151 4689 (if (and is-REx is-x-REx)
a1506d29 4690 (put-text-property (1+ b) (1- e)
6c389151 4691 'syntax-subtype 'x-REx)))
8c777c8d 4692 (if (and i2 e1 (or (not b1) (> e1 b1)))
82d9a08d 4693 (progn ; No errors finding the second part...
5c8b7eaf 4694 (cperl-postpone-fontification
4ab89e7b 4695 (1- e1) e1 'face my-cperl-delimiters-face)
05927f8c
VJL
4696 (if (and (not (eobp))
4697 (assoc (char-after b) cperl-starters))
4ab89e7b
SM
4698 (progn
4699 (cperl-postpone-fontification
4700 b1 (1+ b1) 'face my-cperl-delimiters-face)
4701 (put-text-property b1 (1+ b1)
4702 'REx-part2 t)))))
5bd52f0e
RS
4703 (if (> (point) max)
4704 (setq tmpend tb))))
4ab89e7b
SM
4705 ((match-beginning 17) ; sub with prototype or attribute
4706 ;; 1+6+2+1+1=11 extra () before this (sub with proto/attr):
4707 ;;"\\<sub\\>\\(" ;12
4708 ;; cperl-white-and-comment-rex ;13
4709 ;; "\\([a-zA-Z_:'0-9]+\\)\\)?" ; name ;14
4710 ;;"\\(" cperl-maybe-white-and-comment-rex ;15,16
4711 ;; "\\(([^()]*)\\|:[^:]\\)\\)" ; 17:proto or attribute start
4712 (setq b1 (match-beginning 14) e1 (match-end 14))
f83d2997
KH
4713 (if (memq (char-after (1- b))
4714 '(?\$ ?\@ ?\% ?\& ?\*))
4715 nil
4ab89e7b
SM
4716 (goto-char b)
4717 (if (eq (char-after (match-beginning 17)) ?\( )
4718 (progn
4719 (cperl-commentify ; Prototypes; mark as string
4720 (match-beginning 17) (match-end 17) t)
4721 (goto-char (match-end 0))
4722 ;; Now look for attributes after prototype:
4723 (forward-comment (buffer-size))
4724 (and (looking-at ":[^:]")
4725 (cperl-find-sub-attrs st-l b1 e1 b)))
4726 ;; treat attributes without prototype
4727 (goto-char (match-beginning 17))
4728 (cperl-find-sub-attrs st-l b1 e1 b))))
4729 ;; 1+6+2+1+1+6+1=18 extra () before this:
f83d2997 4730 ;; "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'")
4ab89e7b
SM
4731 ((match-beginning 19) ; old $abc'efg syntax
4732 (setq bb (match-end 0))
4733 ;;;(if (nth 3 state) nil ; in string
4734 (put-text-property (1- bb) bb 'syntax-table cperl-st-word)
f83d2997 4735 (goto-char bb))
4ab89e7b 4736 ;; 1+6+2+1+1+6+1+1=19 extra () before this:
f83d2997 4737 ;; "__\\(END\\|DATA\\)__"
4ab89e7b
SM
4738 ((match-beginning 20) ; __END__, __DATA__
4739 (setq bb (match-end 0))
4740 ;; (put-text-property b (1+ bb) 'syntax-type 'pod) ; Cheat
4741 (cperl-commentify b bb nil)
4742 (setq end t))
4743 ;; "\\\\\\(['`\"($]\\)"
4744 ((match-beginning 21)
4745 ;; Trailing backslash; make non-quoting outside string/comment
4746 (setq bb (match-end 0))
6c389151
SM
4747 (goto-char b)
4748 (skip-chars-backward "\\\\")
4749 ;;;(setq i2 (= (% (skip-chars-backward "\\\\") 2) -1))
4ab89e7b 4750 (cperl-modify-syntax-type b cperl-st-punct)
6c389151
SM
4751 (goto-char bb))
4752 (t (error "Error in regexp of the sniffer")))
db133cb6 4753 (if (> (point) stop-point)
f83d2997 4754 (progn
5c8b7eaf 4755 (if end
f83d2997
KH
4756 (message "Garbage after __END__/__DATA__ ignored")
4757 (message "Unbalanced syntax found while scanning")
4758 (or (car err-l) (setcar err-l b)))
db133cb6
RS
4759 (goto-char stop-point))))
4760 (setq cperl-syntax-state (cons state-point state)
4ab89e7b
SM
4761 ;; Do not mark syntax as done past tmpend???
4762 cperl-syntax-done-to (or tmpend (max (point) max)))
4763 ;;(message "state-at=%s, done-to=%s" state-point cperl-syntax-done-to)
4764 )
f83d2997 4765 (if (car err-l) (goto-char (car err-l))
db133cb6
RS
4766 (or non-inter
4767 (message "Scanning for \"hard\" Perl constructions... done"))))
f83d2997
KH
4768 (and (buffer-modified-p)
4769 (not modified)
4770 (set-buffer-modified-p nil))
00424a9e
SM
4771 ;; I do not understand what this is doing here. It breaks font-locking
4772 ;; because it resets the syntax-table from font-lock-syntax-table to
4773 ;; cperl-mode-syntax-table.
4774 ;; (set-syntax-table cperl-mode-syntax-table)
4775 )
4ab89e7b
SM
4776 (list (car err-l) overshoot)))
4777
4778(defun cperl-find-pods-heres-region (min max)
4779 (interactive "r")
4780 (cperl-find-pods-heres min max))
f83d2997
KH
4781
4782(defun cperl-backward-to-noncomment (lim)
4783 ;; Stops at lim or after non-whitespace that is not in comment
4ab89e7b 4784 ;; XXXX Wrongly understands end-of-multiline strings with # as comment
5bd52f0e 4785 (let (stop p pr)
4ab89e7b 4786 (while (and (not stop) (> (point) (or lim (point-min))))
f83d2997
KH
4787 (skip-chars-backward " \t\n\f" lim)
4788 (setq p (point))
4789 (beginning-of-line)
5bd52f0e
RS
4790 (if (memq (setq pr (get-text-property (point) 'syntax-type))
4791 '(pod here-doc here-doc-delim))
82d9a08d
SM
4792 (progn
4793 (cperl-unwind-to-safe nil)
4794 (setq pr (get-text-property (point) 'syntax-type))))
4795 (or (and (looking-at "^[ \t]*\\(#\\|$\\)")
4796 (not (memq pr '(string prestring))))
4797 (progn (cperl-to-comment-or-eol) (bolp))
4798 (progn
4799 (skip-chars-backward " \t")
4800 (if (< p (point)) (goto-char p))
4801 (setq stop t))))))
f83d2997 4802
4ab89e7b
SM
4803;; Used only in `cperl-calculate-indent'...
4804(defun cperl-block-p () ; Do not C-M-q ! One string contains ";" !
4805 ;; Positions is before ?\{. Checks whether it starts a block.
4806 ;; No save-excursion! This is more a distinguisher of a block/hash ref...
4807 (cperl-backward-to-noncomment (point-min))
4808 (or (memq (preceding-char) (append ";){}$@&%\C-@" nil)) ; Or label! \C-@ at bobp
4809 ; Label may be mixed up with `$blah :'
4810 (save-excursion (cperl-after-label))
4811 (get-text-property (cperl-1- (point)) 'attrib-group)
4812 (and (memq (char-syntax (preceding-char)) '(?w ?_))
4813 (progn
4814 (backward-sexp)
4815 ;; sub {BLK}, print {BLK} $data, but NOT `bless', `return', `tr'
4816 (or (and (looking-at "[a-zA-Z0-9_:]+[ \t\n\f]*[{#]") ; Method call syntax
4817 (not (looking-at "\\(bless\\|return\\|q[wqrx]?\\|tr\\|[smy]\\)\\>")))
4818 ;; sub bless::foo {}
4819 (progn
4820 (cperl-backward-to-noncomment (point-min))
4821 (and (eq (preceding-char) ?b)
4822 (progn
4823 (forward-sexp -1)
4824 (looking-at "sub[ \t\n\f#]")))))))))
4825
4826;;; What is the difference of (cperl-after-block-p lim t) and (cperl-block-p)?
4827;;; No save-excursion; condition-case ... In (cperl-block-p) the block
4828;;; may be a part of an in-statement construct, such as
4829;;; ${something()}, print {FH} $data.
4830;;; Moreover, one takes positive approach (looks for else,grep etc)
4831;;; another negative (looks for bless,tr etc)
f739b53b 4832(defun cperl-after-block-p (lim &optional pre-block)
97610156 4833 "Return true if the preceding } (if PRE-BLOCK, following {) delimits a block.
4ab89e7b
SM
4834Would not look before LIM. Assumes that LIM is a good place to begin a
4835statement. The kind of block we treat here is one after which a new
4836statement would start; thus the block in ${func()} does not count."
f83d2997
KH
4837 (save-excursion
4838 (condition-case nil
4839 (progn
f739b53b 4840 (or pre-block (forward-sexp -1))
f83d2997 4841 (cperl-backward-to-noncomment lim)
bab27c0c 4842 (or (eq (point) lim)
4ab89e7b
SM
4843 ;; if () {} // sub f () {} // sub f :a(') {}
4844 (eq (preceding-char) ?\) )
4845 ;; label: {}
4846 (save-excursion (cperl-after-label))
4847 ;; sub :attr {}
4848 (get-text-property (cperl-1- (point)) 'attrib-group)
4849 (if (memq (char-syntax (preceding-char)) '(?w ?_)) ; else {}
db133cb6
RS
4850 (save-excursion
4851 (forward-sexp -1)
4ab89e7b
SM
4852 ;; else {} but not else::func {}
4853 (or (and (looking-at "\\(else\\|continue\\|grep\\|map\\|BEGIN\\|END\\|CHECK\\|INIT\\)\\>")
4854 (not (looking-at "\\(\\sw\\|_\\)+::")))
db133cb6
RS
4855 ;; sub f {}
4856 (progn
4857 (cperl-backward-to-noncomment lim)
4ab89e7b 4858 (and (eq (preceding-char) ?b)
db133cb6
RS
4859 (progn
4860 (forward-sexp -1)
4ab89e7b 4861 (looking-at "sub[ \t\n\f#]"))))))
97610156 4862 ;; What precedes is not word... XXXX Last statement in sub???
db133cb6 4863 (cperl-after-expr-p lim))))
f83d2997
KH
4864 (error nil))))
4865
4866(defun cperl-after-expr-p (&optional lim chars test)
029cb4d5 4867 "Return true if the position is good for start of expression.
f83d2997
KH
4868TEST is the expression to evaluate at the found position. If absent,
4869CHARS is a string that contains good characters to have before us (however,
4870`}' is treated \"smartly\" if it is not in the list)."
83261a2f 4871 (let ((lim (or lim (point-min)))
f739b53b
SM
4872 stop p pr)
4873 (cperl-update-syntaxification (point) (point))
f83d2997
KH
4874 (save-excursion
4875 (while (and (not stop) (> (point) lim))
4876 (skip-chars-backward " \t\n\f" lim)
4877 (setq p (point))
4878 (beginning-of-line)
f739b53b
SM
4879 ;;(memq (setq pr (get-text-property (point) 'syntax-type))
4880 ;; '(pod here-doc here-doc-delim))
4881 (if (get-text-property (point) 'here-doc-group)
4882 (progn
4883 (goto-char
4ab89e7b 4884 (cperl-beginning-of-property (point) 'here-doc-group))
f739b53b
SM
4885 (beginning-of-line 0)))
4886 (if (get-text-property (point) 'in-pod)
4887 (progn
4888 (goto-char
4ab89e7b 4889 (cperl-beginning-of-property (point) 'in-pod))
f739b53b 4890 (beginning-of-line 0)))
f83d2997 4891 (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip
5bd52f0e 4892 ;; Else: last iteration, or a label
f739b53b 4893 (cperl-to-comment-or-eol) ; Will not move past "." after a format
f83d2997
KH
4894 (skip-chars-backward " \t")
4895 (if (< p (point)) (goto-char p))
5bd52f0e
RS
4896 (setq p (point))
4897 (if (and (eq (preceding-char) ?:)
4898 (progn
4899 (forward-char -1)
4900 (skip-chars-backward " \t\n\f" lim)
4ab89e7b 4901 (memq (char-syntax (preceding-char)) '(?w ?_))))
5bd52f0e
RS
4902 (forward-sexp -1) ; Possibly label. Skip it
4903 (goto-char p)
4904 (setq stop t))))
bab27c0c
RS
4905 (or (bobp) ; ???? Needed
4906 (eq (point) lim)
029cb4d5 4907 (looking-at "[ \t]*__\\(END\\|DATA\\)__") ; After this anything goes
f83d2997
KH
4908 (progn
4909 (if test (eval test)
4910 (or (memq (preceding-char) (append (or chars "{;") nil))
4911 (and (eq (preceding-char) ?\})
f739b53b
SM
4912 (cperl-after-block-p lim))
4913 (and (eq (following-char) ?.) ; in format: see comment above
4914 (eq (get-text-property (point) 'syntax-type)
4915 'format)))))))))
f83d2997 4916
4ab89e7b
SM
4917(defun cperl-backward-to-start-of-expr (&optional lim)
4918 (condition-case nil
4919 (progn
4920 (while (and (or (not lim)
4921 (> (point) lim))
4922 (not (cperl-after-expr-p lim)))
4923 (forward-sexp -1)
4924 ;; May be after $, @, $# etc of a variable
4925 (skip-chars-backward "$@%#")))
4926 (error nil)))
4927
4928(defun cperl-at-end-of-expr (&optional lim)
4929 ;; Since the SEXP approach below is very fragile, do some overengineering
4930 (or (looking-at (concat cperl-maybe-white-and-comment-rex "[;}]"))
4931 (condition-case nil
4932 (save-excursion
4933 ;; If nothing interesting after, does as (forward-sexp -1);
4934 ;; otherwise fails, or ends at a start of following sexp.
4935 ;; XXXX PROBLEMS: if what follows (after ";") @FOO, or ${bar}
4936 ;; may be stuck after @ or $; just put some stupid workaround now:
4937 (let ((p (point)))
4938 (forward-sexp 1)
4939 (forward-sexp -1)
4940 (while (memq (preceding-char) (append "%&@$*" nil))
4941 (forward-char -1))
4942 (or (< (point) p)
4943 (cperl-after-expr-p lim))))
4944 (error t))))
4945
4946(defun cperl-forward-to-end-of-expr (&optional lim)
4947 (let ((p (point))))
4948 (condition-case nil
4949 (progn
4950 (while (and (< (point) (or lim (point-max)))
4951 (not (cperl-at-end-of-expr)))
4952 (forward-sexp 1)))
4953 (error nil)))
4954
f83d2997
KH
4955(defun cperl-backward-to-start-of-continued-exp (lim)
4956 (if (memq (preceding-char) (append ")]}\"'`" nil))
4957 (forward-sexp -1))
4958 (beginning-of-line)
4959 (if (<= (point) lim)
4960 (goto-char (1+ lim)))
4961 (skip-chars-forward " \t"))
4962
db133cb6
RS
4963(defun cperl-after-block-and-statement-beg (lim)
4964 ;; We assume that we are after ?\}
5c8b7eaf 4965 (and
db133cb6
RS
4966 (cperl-after-block-p lim)
4967 (save-excursion
4968 (forward-sexp -1)
4969 (cperl-backward-to-noncomment (point-min))
4970 (or (bobp)
bab27c0c 4971 (eq (point) lim)
db133cb6
RS
4972 (not (= (char-syntax (preceding-char)) ?w))
4973 (progn
4974 (forward-sexp -1)
5c8b7eaf 4975 (not
db133cb6
RS
4976 (looking-at
4977 "\\(map\\|grep\\|printf?\\|system\\|exec\\|tr\\|s\\)\\>")))))))
4978
f83d2997 4979\f
f83d2997
KH
4980(defun cperl-indent-exp ()
4981 "Simple variant of indentation of continued-sexp.
5bd52f0e
RS
4982
4983Will not indent comment if it starts at `comment-indent' or looks like
4984continuation of the comment on the previous line.
db133cb6 4985
5c8b7eaf 4986If `cperl-indent-region-fix-constructs', will improve spacing on
db133cb6 4987conditional/loop constructs."
f83d2997
KH
4988 (interactive)
4989 (save-excursion
e180ab9f 4990 (let ((tmp-end (point-at-eol)) top done)
f83d2997
KH
4991 (save-excursion
4992 (beginning-of-line)
4993 (while (null done)
4994 (setq top (point))
4ab89e7b
SM
4995 ;; Plan A: if line has an unfinished paren-group, go to end-of-group
4996 (while (= -1 (nth 0 (parse-partial-sexp (point) tmp-end -1)))
bbd240ce 4997 (setq top (point))) ; Get the outermost parens in line
f83d2997
KH
4998 (goto-char top)
4999 (while (< (point) tmp-end)
5000 (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol
5001 (or (eolp) (forward-sexp 1)))
4ab89e7b
SM
5002 (if (> (point) tmp-end) ; Yes, there an unfinished block
5003 nil
5004 (if (eq ?\) (preceding-char))
5005 (progn ;; Plan B: find by REGEXP block followup this line
5006 (setq top (point))
5007 (condition-case nil
5008 (progn
5009 (forward-sexp -2)
5010 (if (eq (following-char) ?$ ) ; for my $var (list)
5011 (progn
5012 (forward-sexp -1)
5013 (if (looking-at "\\(my\\|local\\|our\\)\\>")
5014 (forward-sexp -1))))
5015 (if (looking-at
5016 (concat "\\(\\elsif\\|if\\|unless\\|while\\|until"
5017 "\\|for\\(each\\)?\\>\\(\\("
5018 cperl-maybe-white-and-comment-rex
5019 "\\(my\\|local\\|our\\)\\)?"
5020 cperl-maybe-white-and-comment-rex
5021 "\\$[_a-zA-Z0-9]+\\)?\\)\\>"))
5022 (progn
5023 (goto-char top)
5024 (forward-sexp 1)
5025 (setq top (point)))))
5026 (error (setq done t)))
5027 (goto-char top))
5028 (if (looking-at ; Try Plan C: continuation block
5029 (concat cperl-maybe-white-and-comment-rex
5030 "\\<\\(else\\|elsif\|continue\\)\\>"))
5031 (progn
5032 (goto-char (match-end 0))
e180ab9f 5033 (setq tmp-end (point-at-eol)))
4ab89e7b 5034 (setq done t))))
e180ab9f 5035 (setq tmp-end (point-at-eol)))
f83d2997
KH
5036 (goto-char tmp-end)
5037 (setq tmp-end (point-marker)))
db133cb6
RS
5038 (if cperl-indent-region-fix-constructs
5039 (cperl-fix-line-spacing tmp-end))
f83d2997
KH
5040 (cperl-indent-region (point) tmp-end))))
5041
5bd52f0e
RS
5042(defun cperl-fix-line-spacing (&optional end parse-data)
5043 "Improve whitespace in a conditional/loop construct.
5044Returns some position at the last line."
db133cb6
RS
5045 (interactive)
5046 (or end
5047 (setq end (point-max)))
e180ab9f 5048 (let ((ee (point-at-eol))
83261a2f
SM
5049 (cperl-indent-region-fix-constructs
5050 (or cperl-indent-region-fix-constructs 1))
5051 p pp ml have-brace ret)
db133cb6
RS
5052 (save-excursion
5053 (beginning-of-line)
5bd52f0e 5054 (setq ret (point))
5c8b7eaf 5055 ;; }? continue
5bd52f0e 5056 ;; blah; }
5c8b7eaf 5057 (if (not
5bd52f0e
RS
5058 (or (looking-at "[ \t]*\\(els\\(e\\|if\\)\\|continue\\|if\\|while\\|for\\(each\\)?\\|until\\)")
5059 (setq have-brace (save-excursion (search-forward "}" ee t)))))
5060 nil ; Do not need to do anything
83261a2f
SM
5061 ;; Looking at:
5062 ;; }
5063 ;; else
4ab89e7b
SM
5064 (if cperl-merge-trailing-else
5065 (if (looking-at
5066 "[ \t]*}[ \t]*\n[ \t\n]*\\(els\\(e\\|if\\)\\|continue\\)\\>")
5067 (progn
5068 (search-forward "}")
5069 (setq p (point))
5070 (skip-chars-forward " \t\n")
5071 (delete-region p (point))
b5b0cb34 5072 (insert (make-string cperl-indent-region-fix-constructs ?\s))
4ab89e7b
SM
5073 (beginning-of-line)))
5074 (if (looking-at "[ \t]*}[ \t]*\\(els\\(e\\|if\\)\\|continue\\)\\>")
5075 (save-excursion
5076 (search-forward "}")
5077 (delete-horizontal-space)
5078 (insert "\n")
5079 (setq ret (point))
5080 (if (cperl-indent-line parse-data)
5081 (progn
5082 (cperl-fix-line-spacing end parse-data)
5083 (setq ret (point)))))))
83261a2f
SM
5084 ;; Looking at:
5085 ;; } else
5086 (if (looking-at "[ \t]*}\\(\t*\\|[ \t][ \t]+\\)\\<\\(els\\(e\\|if\\)\\|continue\\)\\>")
5087 (progn
5088 (search-forward "}")
5089 (delete-horizontal-space)
b5b0cb34 5090 (insert (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f
SM
5091 (beginning-of-line)))
5092 ;; Looking at:
5093 ;; else {
5094 (if (looking-at
5095 "[ \t]*}?[ \t]*\\<\\(\\els\\(e\\|if\\)\\|continue\\|unless\\|if\\|while\\|for\\(each\\)?\\|until\\)\\>\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
5096 (progn
5097 (forward-word 1)
5098 (delete-horizontal-space)
b5b0cb34 5099 (insert (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f
SM
5100 (beginning-of-line)))
5101 ;; Looking at:
5102 ;; foreach my $var
5103 (if (looking-at
5104 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)\\(\t*\\|[ \t][ \t]+\\)[^ \t\n]")
5105 (progn
5106 (forward-word 2)
5107 (delete-horizontal-space)
b5b0cb34 5108 (insert (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f
SM
5109 (beginning-of-line)))
5110 ;; Looking at:
5111 ;; foreach my $var (
5112 (if (looking-at
6c389151 5113 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)[ \t]*\\$[_a-zA-Z0-9]+\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
83261a2f 5114 (progn
f739b53b 5115 (forward-sexp 3)
83261a2f
SM
5116 (delete-horizontal-space)
5117 (insert
b5b0cb34 5118 (make-string cperl-indent-region-fix-constructs ?\s))
83261a2f 5119 (beginning-of-line)))
4ab89e7b
SM
5120 ;; Looking at (with or without "}" at start, ending after "({"):
5121 ;; } foreach my $var () OR {
83261a2f 5122 (if (looking-at
ce22dd53 5123 "[ \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 5124 (progn
4ab89e7b 5125 (setq ml (match-beginning 8)) ; "(" or "{" after control word
83261a2f
SM
5126 (re-search-forward "[({]")
5127 (forward-char -1)
5128 (setq p (point))
5129 (if (eq (following-char) ?\( )
5130 (progn
5131 (forward-sexp 1)
4ab89e7b 5132 (setq pp (point))) ; past parenth-group
83261a2f
SM
5133 ;; after `else' or nothing
5134 (if ml ; after `else'
5135 (skip-chars-backward " \t\n")
5136 (beginning-of-line))
5137 (setq pp nil))
5138 ;; Now after the sexp before the brace
5139 ;; Multiline expr should be special
5140 (setq ml (and pp (save-excursion (goto-char p)
5141 (search-forward "\n" pp t))))
4ab89e7b 5142 (if (and (or (not pp) (< pp end)) ; Do not go too far...
83261a2f
SM
5143 (looking-at "[ \t\n]*{"))
5144 (progn
5145 (cond
5146 ((bolp) ; Were before `{', no if/else/etc
5147 nil)
4ab89e7b 5148 ((looking-at "\\(\t*\\| [ \t]+\\){") ; Not exactly 1 SPACE
83261a2f
SM
5149 (delete-horizontal-space)
5150 (if (if ml
5151 cperl-extra-newline-before-brace-multiline
5152 cperl-extra-newline-before-brace)
5153 (progn
5154 (delete-horizontal-space)
5155 (insert "\n")
5156 (setq ret (point))
5157 (if (cperl-indent-line parse-data)
5158 (progn
5159 (cperl-fix-line-spacing end parse-data)
5160 (setq ret (point)))))
5161 (insert
b5b0cb34 5162 (make-string cperl-indent-region-fix-constructs ?\s))))
83261a2f
SM
5163 ((and (looking-at "[ \t]*\n")
5164 (not (if ml
5165 cperl-extra-newline-before-brace-multiline
5166 cperl-extra-newline-before-brace)))
5167 (setq pp (point))
5168 (skip-chars-forward " \t\n")
5169 (delete-region pp (point))
db133cb6 5170 (insert
4ab89e7b
SM
5171 (make-string cperl-indent-region-fix-constructs ?\ )))
5172 ((and (looking-at "[\t ]*{")
5173 (if ml cperl-extra-newline-before-brace-multiline
5174 cperl-extra-newline-before-brace))
5175 (delete-horizontal-space)
5176 (insert "\n")
5177 (setq ret (point))
5178 (if (cperl-indent-line parse-data)
5179 (progn
5180 (cperl-fix-line-spacing end parse-data)
5181 (setq ret (point))))))
83261a2f
SM
5182 ;; Now we are before `{'
5183 (if (looking-at "[ \t\n]*{[ \t]*[^ \t\n#]")
5184 (progn
5185 (skip-chars-forward " \t\n")
5186 (setq pp (point))
5187 (forward-sexp 1)
5188 (setq p (point))
5189 (goto-char pp)
5190 (setq ml (search-forward "\n" p t))
5191 (if (or cperl-break-one-line-blocks-when-indent ml)
5192 ;; not good: multi-line BLOCK
5193 (progn
5194 (goto-char (1+ pp))
5195 (delete-horizontal-space)
5196 (insert "\n")
5197 (setq ret (point))
5198 (if (cperl-indent-line parse-data)
5199 (setq ret (cperl-fix-line-spacing end parse-data)))))))))))
5200 (beginning-of-line)
e180ab9f 5201 (setq p (point) pp (point-at-eol)) ; May be different from ee.
83261a2f
SM
5202 ;; Now check whether there is a hanging `}'
5203 ;; Looking at:
5204 ;; } blah
5205 (if (and
5206 cperl-fix-hanging-brace-when-indent
5207 have-brace
5208 (not (looking-at "[ \t]*}[ \t]*\\(\\<\\(els\\(if\\|e\\)\\|continue\\|while\\|until\\)\\>\\|$\\|#\\)"))
5209 (condition-case nil
5210 (progn
5211 (up-list 1)
5212 (if (and (<= (point) pp)
5213 (eq (preceding-char) ?\} )
5214 (cperl-after-block-and-statement-beg (point-min)))
5215 t
5216 (goto-char p)
5217 nil))
5218 (error nil)))
5219 (progn
5220 (forward-char -1)
5221 (skip-chars-backward " \t")
5222 (if (bolp)
5223 ;; `}' was the first thing on the line, insert NL *after* it.
5224 (progn
5225 (cperl-indent-line parse-data)
5226 (search-forward "}")
5227 (delete-horizontal-space)
5228 (insert "\n"))
5229 (delete-horizontal-space)
5230 (or (eq (preceding-char) ?\;)
5231 (bolp)
5232 (and (eq (preceding-char) ?\} )
5233 (cperl-after-block-p (point-min)))
5234 (insert ";"))
5235 (insert "\n")
5236 (setq ret (point)))
5237 (if (cperl-indent-line parse-data)
5238 (setq ret (cperl-fix-line-spacing end parse-data)))
5239 (beginning-of-line)))))
5bd52f0e
RS
5240 ret))
5241
5242(defvar cperl-update-start) ; Do not need to make them local
5243(defvar cperl-update-end)
5244(defun cperl-delay-update-hook (beg end old-len)
5245 (setq cperl-update-start (min beg (or cperl-update-start (point-max))))
5246 (setq cperl-update-end (max end (or cperl-update-end (point-min)))))
db133cb6 5247
f83d2997
KH
5248(defun cperl-indent-region (start end)
5249 "Simple variant of indentation of region in CPerl mode.
5c8b7eaf 5250Should be slow. Will not indent comment if it starts at `comment-indent'
f83d2997 5251or looks like continuation of the comment on the previous line.
5c8b7eaf
SS
5252Indents all the lines whose first character is between START and END
5253inclusive.
db133cb6 5254
5c8b7eaf 5255If `cperl-indent-region-fix-constructs', will improve spacing on
db133cb6 5256conditional/loop constructs."
f83d2997 5257 (interactive "r")
5bd52f0e 5258 (cperl-update-syntaxification end end)
f83d2997 5259 (save-excursion
5bd52f0e 5260 (let (cperl-update-start cperl-update-end (h-a-c after-change-functions))
83261a2f
SM
5261 (let ((indent-info (if cperl-emacs-can-parse
5262 (list nil nil nil) ; Cannot use '(), since will modify
5263 nil))
c326ddd1 5264 (pm 0)
83261a2f
SM
5265 after-change-functions ; Speed it up!
5266 st comm old-comm-indent new-comm-indent p pp i empty)
5bd52f0e 5267 (if h-a-c (add-hook 'after-change-functions 'cperl-delay-update-hook))
83261a2f
SM
5268 (goto-char start)
5269 (setq old-comm-indent (and (cperl-to-comment-or-eol)
5270 (current-column))
5271 new-comm-indent old-comm-indent)
5272 (goto-char start)
5273 (setq end (set-marker (make-marker) end)) ; indentation changes pos
5274 (or (bolp) (beginning-of-line 2))
83261a2f 5275 (while (and (<= (point) end) (not (eobp))) ; bol to check start
5bd52f0e
RS
5276 (setq st (point))
5277 (if (or
5278 (setq empty (looking-at "[ \t]*\n"))
5279 (and (setq comm (looking-at "[ \t]*#"))
83261a2f
SM
5280 (or (eq (current-indentation) (or old-comm-indent
5281 comment-column))
5bd52f0e 5282 (setq old-comm-indent nil))))
8c777c8d 5283 (if (and old-comm-indent
5bd52f0e 5284 (not empty)
8c777c8d 5285 (= (current-indentation) old-comm-indent)
5bd52f0e
RS
5286 (not (eq (get-text-property (point) 'syntax-type) 'pod))
5287 (not (eq (get-text-property (point) 'syntax-table)
5288 cperl-st-cfence)))
83261a2f
SM
5289 (let ((comment-column new-comm-indent))
5290 (indent-for-comment)))
5291 (progn
5bd52f0e 5292 (setq i (cperl-indent-line indent-info))
8c777c8d
CY
5293 (or comm
5294 (not i)
5295 (progn
5296 (if cperl-indent-region-fix-constructs
5bd52f0e 5297 (goto-char (cperl-fix-line-spacing end indent-info)))
83261a2f
SM
5298 (if (setq old-comm-indent
5299 (and (cperl-to-comment-or-eol)
5300 (not (memq (get-text-property (point)
5301 'syntax-type)
5302 '(pod here-doc)))
5c8b7eaf 5303 (not (eq (get-text-property (point)
5bd52f0e
RS
5304 'syntax-table)
5305 cperl-st-cfence))
8c777c8d
CY
5306 (current-column)))
5307 (progn (indent-for-comment)
5308 (skip-chars-backward " \t")
5309 (skip-chars-backward "#")
5310 (setq new-comm-indent (current-column))))))))
5311 (beginning-of-line 2)))
5bd52f0e 5312 ;; Now run the update hooks
83261a2f
SM
5313 (and after-change-functions
5314 cperl-update-end
5315 (save-excursion
5316 (goto-char cperl-update-end)
5317 (insert " ")
5318 (delete-char -1)
5319 (goto-char cperl-update-start)
5320 (insert " ")
5321 (delete-char -1))))))
f83d2997 5322
f83d2997
KH
5323;; Stolen from lisp-mode with a lot of improvements
5324
5325(defun cperl-fill-paragraph (&optional justify iteration)
82eb0dae 5326 "Like `fill-paragraph', but handle CPerl comments.
f83d2997
KH
5327If any of the current line is a comment, fill the comment or the
5328block of it that point is in, preserving the comment's initial
5329indentation and initial hashes. Behaves usually outside of comment."
82eb0dae 5330 ;; (interactive "P") ; Only works when called from fill-paragraph. -stef
83261a2f 5331 (let (;; Non-nil if the current line contains a comment.
f83d2997 5332 has-comment
4ab89e7b 5333 fill-paragraph-function ; do not recurse
f83d2997
KH
5334 ;; If has-comment, the appropriate fill-prefix for the comment.
5335 comment-fill-prefix
5336 ;; Line that contains code and comment (or nil)
5337 start
5338 c spaces len dc (comment-column comment-column))
5339 ;; Figure out what kind of comment we are looking at.
5340 (save-excursion
5341 (beginning-of-line)
5342 (cond
5343
5344 ;; A line with nothing but a comment on it?
5345 ((looking-at "[ \t]*#[# \t]*")
5346 (setq has-comment t
5347 comment-fill-prefix (buffer-substring (match-beginning 0)
5348 (match-end 0))))
5349
5350 ;; A line with some code, followed by a comment? Remember that the
5351 ;; semi which starts the comment shouldn't be part of a string or
5352 ;; character.
5353 ((cperl-to-comment-or-eol)
5354 (setq has-comment t)
5355 (looking-at "#+[ \t]*")
5c8b7eaf 5356 (setq start (point) c (current-column)
f83d2997 5357 comment-fill-prefix
b5b0cb34 5358 (concat (make-string (current-column) ?\s)
f83d2997 5359 (buffer-substring (match-beginning 0) (match-end 0)))
5c8b7eaf 5360 spaces (progn (skip-chars-backward " \t")
f83d2997 5361 (buffer-substring (point) start))
5c8b7eaf 5362 dc (- c (current-column)) len (- start (point))
f83d2997
KH
5363 start (point-marker))
5364 (delete-char len)
4ab89e7b 5365 (insert (make-string dc ?-))))) ; Placeholder (to avoid splitting???)
f83d2997 5366 (if (not has-comment)
83261a2f 5367 (fill-paragraph justify) ; Do the usual thing outside of comment
f83d2997
KH
5368 ;; Narrow to include only the comment, and then fill the region.
5369 (save-restriction
5370 (narrow-to-region
5371 ;; Find the first line we should include in the region to fill.
5372 (if start (progn (beginning-of-line) (point))
5373 (save-excursion
5374 (while (and (zerop (forward-line -1))
5375 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
5376 ;; We may have gone to far. Go forward again.
5377 (or (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")
5378 (forward-line 1))
5379 (point)))
5380 ;; Find the beginning of the first line past the region to fill.
5381 (save-excursion
5382 (while (progn (forward-line 1)
5383 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
5384 (point)))
5385 ;; Remove existing hashes
4ab89e7b 5386 (goto-char (point-min))
8c777c8d
CY
5387 (save-excursion
5388 (while (progn (forward-line 1) (< (point) (point-max)))
5389 (skip-chars-forward " \t")
5390 (if (looking-at "#+")
5391 (progn
5392 (if (and (eq (point) (match-beginning 0))
5393 (not (eq (point) (match-end 0)))) nil
4ab89e7b
SM
5394 (error
5395 "Bug in Emacs: `looking-at' in `narrow-to-region': match-data is garbage"))
5396 (delete-char (- (match-end 0) (match-beginning 0)))))))
f83d2997
KH
5397
5398 ;; Lines with only hashes on them can be paragraph boundaries.
5399 (let ((paragraph-start (concat paragraph-start "\\|^[ \t#]*$"))
5400 (paragraph-separate (concat paragraph-start "\\|^[ \t#]*$"))
5401 (fill-prefix comment-fill-prefix))
5402 (fill-paragraph justify)))
5403 (if (and start)
5c8b7eaf 5404 (progn
f83d2997
KH
5405 (goto-char start)
5406 (if (> dc 0)
83261a2f 5407 (progn (delete-char dc) (insert spaces)))
f83d2997
KH
5408 (if (or (= (current-column) c) iteration) nil
5409 (setq comment-column c)
5410 (indent-for-comment)
5411 ;; Repeat once more, flagging as iteration
4ab89e7b
SM
5412 (cperl-fill-paragraph justify t))))))
5413 t)
f83d2997
KH
5414
5415(defun cperl-do-auto-fill ()
5416 ;; Break out if the line is short enough
5417 (if (> (save-excursion
5418 (end-of-line)
5419 (current-column))
5420 fill-column)
83261a2f
SM
5421 (let ((c (save-excursion (beginning-of-line)
5422 (cperl-to-comment-or-eol) (point)))
8038e2cf 5423 (s (memq (following-char) '(?\s ?\t))) marker)
82eb0dae
SM
5424 (if (>= c (point))
5425 ;; Don't break line inside code: only inside comment.
5426 nil
83261a2f 5427 (setq marker (point-marker))
82eb0dae 5428 (fill-paragraph nil)
83261a2f
SM
5429 (goto-char marker)
5430 ;; Is not enough, sometimes marker is a start of line
5431 (if (bolp) (progn (re-search-forward "#+[ \t]*")
5432 (goto-char (match-end 0))))
5433 ;; Following space could have gone:
8038e2cf 5434 (if (or (not s) (memq (following-char) '(?\s ?\t))) nil
83261a2f
SM
5435 (insert " ")
5436 (backward-char 1))
5437 ;; Previous space could have gone:
8038e2cf 5438 (or (memq (preceding-char) '(?\s ?\t)) (insert " "))))))
f83d2997 5439
f83d2997
KH
5440(defun cperl-imenu-addback (lst &optional isback name)
5441 ;; We suppose that the lst is a DAG, unless the first element only
5442 ;; loops back, and ISBACK is set. Thus this function cannot be
5443 ;; applied twice without ISBACK set.
5444 (cond ((not cperl-imenu-addback) lst)
5445 (t
5c8b7eaf 5446 (or name
f83d2997 5447 (setq name "+++BACK+++"))
dba01120
GM
5448 (mapc (lambda (elt)
5449 (if (and (listp elt) (listp (cdr elt)))
5450 (progn
5451 ;; In the other order it goes up
5452 ;; one level only ;-(
5453 (setcdr elt (cons (cons name lst)
5454 (cdr elt)))
5455 (cperl-imenu-addback (cdr elt) t name))))
5456 (if isback (cdr lst) lst))
f83d2997
KH
5457 lst)))
5458
80585273 5459(defun cperl-imenu--create-perl-index (&optional regexp)
f83d2997 5460 (require 'imenu) ; May be called from TAGS creator
5c8b7eaf 5461 (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '())
f83d2997
KH
5462 (index-unsorted-alist '()) (i-s-f (default-value 'imenu-sort-function))
5463 (index-meth-alist '()) meth
4ab89e7b
SM
5464 packages ends-ranges p marker is-proto
5465 (prev-pos 0) is-pack index index1 name (end-range 0) package)
f83d2997 5466 (goto-char (point-min))
6c389151 5467 (cperl-update-syntaxification (point-max) (point-max))
f83d2997
KH
5468 ;; Search for the function
5469 (progn ;;save-match-data
5470 (while (re-search-forward
80585273 5471 (or regexp cperl-imenu--function-name-regexp-perl)
f83d2997 5472 nil t)
4ab89e7b 5473 ;; 2=package-group, 5=package-name 8=sub-name
f83d2997
KH
5474 (cond
5475 ((and ; Skip some noise if building tags
4ab89e7b
SM
5476 (match-beginning 5) ; package name
5477 ;;(eq (char-after (match-beginning 2)) ?p) ; package
f83d2997 5478 (not (save-match-data
83261a2f 5479 (looking-at "[ \t\n]*;")))) ; Plain text word 'package'
f83d2997
KH
5480 nil)
5481 ((and
4ab89e7b
SM
5482 (or (match-beginning 2)
5483 (match-beginning 8)) ; package or sub
6c389151 5484 ;; Skip if quoted (will not skip multi-line ''-strings :-():
f83d2997
KH
5485 (null (get-text-property (match-beginning 1) 'syntax-table))
5486 (null (get-text-property (match-beginning 1) 'syntax-type))
5487 (null (get-text-property (match-beginning 1) 'in-pod)))
4ab89e7b 5488 (setq is-pack (match-beginning 2))
f83d2997
KH
5489 ;; (if (looking-at "([^()]*)[ \t\n\f]*")
5490 ;; (goto-char (match-end 0))) ; Messes what follows
4ab89e7b 5491 (setq meth nil
f83d2997
KH
5492 p (point))
5493 (while (and ends-ranges (>= p (car ends-ranges)))
5494 ;; delete obsolete entries
5495 (setq ends-ranges (cdr ends-ranges) packages (cdr packages)))
5496 (setq package (or (car packages) "")
5497 end-range (or (car ends-ranges) 0))
4ab89e7b
SM
5498 (if is-pack ; doing "package"
5499 (progn
5500 (if (match-beginning 5) ; named package
5501 (setq name (buffer-substring (match-beginning 5)
5502 (match-end 5))
5503 name (progn
5504 (set-text-properties 0 (length name) nil name)
5505 name)
5506 package (concat name "::")
5507 name (concat "package " name))
5508 ;; Support nameless packages
5509 (setq name "package;" package ""))
5510 (setq end-range
5511 (save-excursion
5512 (parse-partial-sexp (point) (point-max) -1) (point))
5513 ends-ranges (cons end-range ends-ranges)
5514 packages (cons package packages)))
5515 (setq is-proto
5516 (or (eq (following-char) ?\;)
5517 (eq 0 (get-text-property (point) 'attrib-group)))))
f83d2997 5518 ;; Skip this function name if it is a prototype declaration.
4ab89e7b
SM
5519 (if (and is-proto (not is-pack)) nil
5520 (or is-pack
5521 (setq name
5522 (buffer-substring (match-beginning 8) (match-end 8)))
5523 (set-text-properties 0 (length name) nil name))
5524 (setq marker (make-marker))
5525 (set-marker marker (match-end (if is-pack 2 8)))
5526 (cond (is-pack nil)
5527 ((string-match "[:']" name)
5528 (setq meth t))
5529 ((> p end-range) nil)
5530 (t
5531 (setq name (concat package name) meth t)))
6c389151 5532 (setq index (cons name marker))
4ab89e7b 5533 (if is-pack
f83d2997
KH
5534 (push index index-pack-alist)
5535 (push index index-alist))
5536 (if meth (push index index-meth-alist))
5537 (push index index-unsorted-alist)))
4ab89e7b
SM
5538 ((match-beginning 16) ; POD section
5539 (setq name (buffer-substring (match-beginning 17) (match-end 17))
5540 marker (make-marker))
5541 (set-marker marker (match-beginning 17))
f83d2997 5542 (set-text-properties 0 (length name) nil name)
4ab89e7b
SM
5543 (setq name (concat (make-string
5544 (* 3 (- (char-after (match-beginning 16)) ?1))
5545 ?\ )
5546 name)
5547 index (cons name marker))
f83d2997
KH
5548 (setq index1 (cons (concat "=" name) (cdr index)))
5549 (push index index-pod-alist)
5550 (push index1 index-unsorted-alist)))))
5c8b7eaf 5551 (setq index-alist
f83d2997
KH
5552 (if (default-value 'imenu-sort-function)
5553 (sort index-alist (default-value 'imenu-sort-function))
83261a2f 5554 (nreverse index-alist)))
f83d2997
KH
5555 (and index-pod-alist
5556 (push (cons "+POD headers+..."
5557 (nreverse index-pod-alist))
5558 index-alist))
5559 (and (or index-pack-alist index-meth-alist)
5560 (let ((lst index-pack-alist) hier-list pack elt group name)
5561 ;; Remove "package ", reverse and uniquify.
5562 (while lst
5563 (setq elt (car lst) lst (cdr lst) name (substring (car elt) 8))
5564 (if (assoc name hier-list) nil
5565 (setq hier-list (cons (cons name (cdr elt)) hier-list))))
5566 (setq lst index-meth-alist)
5567 (while lst
5568 (setq elt (car lst) lst (cdr lst))
5569 (cond ((string-match "\\(::\\|'\\)[_a-zA-Z0-9]+$" (car elt))
5570 (setq pack (substring (car elt) 0 (match-beginning 0)))
5c8b7eaf 5571 (if (setq group (assoc pack hier-list))
f83d2997
KH
5572 (if (listp (cdr group))
5573 ;; Have some functions already
5c8b7eaf
SS
5574 (setcdr group
5575 (cons (cons (substring
f83d2997
KH
5576 (car elt)
5577 (+ 2 (match-beginning 0)))
5578 (cdr elt))
5579 (cdr group)))
5c8b7eaf 5580 (setcdr group (list (cons (substring
f83d2997
KH
5581 (car elt)
5582 (+ 2 (match-beginning 0)))
5583 (cdr elt)))))
5c8b7eaf
SS
5584 (setq hier-list
5585 (cons (cons pack
5586 (list (cons (substring
f83d2997
KH
5587 (car elt)
5588 (+ 2 (match-beginning 0)))
5589 (cdr elt))))
5590 hier-list))))))
5591 (push (cons "+Hierarchy+..."
5592 hier-list)
5593 index-alist)))
5594 (and index-pack-alist
5595 (push (cons "+Packages+..."
5596 (nreverse index-pack-alist))
5597 index-alist))
5c8b7eaf 5598 (and (or index-pack-alist index-pod-alist
f83d2997
KH
5599 (default-value 'imenu-sort-function))
5600 index-unsorted-alist
5601 (push (cons "+Unsorted List+..."
5602 (nreverse index-unsorted-alist))
5603 index-alist))
5604 (cperl-imenu-addback index-alist)))
5605
6c389151 5606\f
6c389151
SM
5607;; Suggested by Mark A. Hershberger
5608(defun cperl-outline-level ()
5609 (looking-at outline-regexp)
5610 (cond ((not (match-beginning 1)) 0) ; beginning-of-file
4ab89e7b
SM
5611;;;; 2=package-group, 5=package-name 8=sub-name 16=head-level
5612 ((match-beginning 2) 0) ; package
5613 ((match-beginning 8) 1) ; sub
5614 ((match-beginning 16)
5615 (- (char-after (match-beginning 16)) ?0)) ; headN ==> N
5616 (t 5))) ; should not happen
6c389151
SM
5617
5618\f
f83d2997
KH
5619(defun cperl-windowed-init ()
5620 "Initialization under windowed version."
f453f5a8 5621 (cond ((featurep 'ps-print)
82d9a08d
SM
5622 (or cperl-faces-init
5623 (progn
5624 (and (boundp 'font-lock-multiline)
5625 (setq cperl-font-lock-multiline t))
5626 (cperl-init-faces))))
f453f5a8
CY
5627 ((not cperl-faces-init)
5628 (add-hook 'font-lock-mode-hook
5629 (function
5630 (lambda ()
5631 (if (memq major-mode '(perl-mode cperl-mode))
5632 (progn
5633 (or cperl-faces-init (cperl-init-faces)))))))
5634 (if (fboundp 'eval-after-load)
5635 (eval-after-load
5636 "ps-print"
5637 '(or cperl-faces-init (cperl-init-faces)))))))
db133cb6 5638
5efe6a56 5639(defvar cperl-font-lock-keywords-1 nil
80585273 5640 "Additional expressions to highlight in Perl mode. Minimal set.")
5efe6a56 5641(defvar cperl-font-lock-keywords nil
80585273 5642 "Additional expressions to highlight in Perl mode. Default set.")
5efe6a56 5643(defvar cperl-font-lock-keywords-2 nil
80585273
DL
5644 "Additional expressions to highlight in Perl mode. Maximal set")
5645
db133cb6
RS
5646(defun cperl-load-font-lock-keywords ()
5647 (or cperl-faces-init (cperl-init-faces))
5efe6a56 5648 cperl-font-lock-keywords)
db133cb6
RS
5649
5650(defun cperl-load-font-lock-keywords-1 ()
5651 (or cperl-faces-init (cperl-init-faces))
5efe6a56 5652 cperl-font-lock-keywords-1)
db133cb6
RS
5653
5654(defun cperl-load-font-lock-keywords-2 ()
5655 (or cperl-faces-init (cperl-init-faces))
5efe6a56 5656 cperl-font-lock-keywords-2)
f83d2997 5657
5bd52f0e
RS
5658(defun cperl-init-faces-weak ()
5659 ;; Allow `cperl-find-pods-heres' to run.
5660 (or (boundp 'font-lock-constant-face)
5661 (cperl-force-face font-lock-constant-face
4ab89e7b
SM
5662 "Face for constant and label names"))
5663 (or (boundp 'font-lock-warning-face)
5664 (cperl-force-face font-lock-warning-face
5665 "Face for things which should stand out"))
5666 ;;(setq font-lock-constant-face 'font-lock-constant-face)
5667 )
5bd52f0e 5668
f83d2997 5669(defun cperl-init-faces ()
5bd52f0e 5670 (condition-case errs
f83d2997
KH
5671 (progn
5672 (require 'font-lock)
5673 (and (fboundp 'font-lock-fontify-anchored-keywords)
5674 (featurep 'font-lock-extra)
5675 (message "You have an obsolete package `font-lock-extra'. Install `choose-color'."))
5676 (let (t-font-lock-keywords t-font-lock-keywords-1 font-lock-anchored)
f83d2997
KH
5677 (if (fboundp 'font-lock-fontify-anchored-keywords)
5678 (setq font-lock-anchored t))
5c8b7eaf 5679 (setq
f83d2997
KH
5680 t-font-lock-keywords
5681 (list
1f5c1626 5682 `("[ \t]+$" 0 ',cperl-invalid-face t)
f83d2997
KH
5683 (cons
5684 (concat
5685 "\\(^\\|[^$@%&\\]\\)\\<\\("
5686 (mapconcat
5687 'identity
5688 '("if" "until" "while" "elsif" "else" "unless" "for"
5689 "foreach" "continue" "exit" "die" "last" "goto" "next"
4ab89e7b 5690 "redo" "return" "local" "exec" "sub" "do" "dump" "use" "our"
6c389151 5691 "require" "package" "eval" "my" "BEGIN" "END" "CHECK" "INIT")
f83d2997
KH
5692 "\\|") ; Flow control
5693 "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]"
5694 ; In what follows we use `type' style
5695 ; for overwritable builtins
5696 (list
5697 (concat
5698 "\\(^\\|[^$@%&\\]\\)\\<\\("
5699 ;; "CORE" "__FILE__" "__LINE__" "abs" "accept" "alarm"
5700 ;; "and" "atan2" "bind" "binmode" "bless" "caller"
5701 ;; "chdir" "chmod" "chown" "chr" "chroot" "close"
5702 ;; "closedir" "cmp" "connect" "continue" "cos" "crypt"
5703 ;; "dbmclose" "dbmopen" "die" "dump" "endgrent"
5704 ;; "endhostent" "endnetent" "endprotoent" "endpwent"
5705 ;; "endservent" "eof" "eq" "exec" "exit" "exp" "fcntl"
5706 ;; "fileno" "flock" "fork" "formline" "ge" "getc"
5707 ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
5708 ;; "gethostbyname" "gethostent" "getlogin"
5709 ;; "getnetbyaddr" "getnetbyname" "getnetent"
5710 ;; "getpeername" "getpgrp" "getppid" "getpriority"
5711 ;; "getprotobyname" "getprotobynumber" "getprotoent"
5712 ;; "getpwent" "getpwnam" "getpwuid" "getservbyname"
5713 ;; "getservbyport" "getservent" "getsockname"
5714 ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int"
5715 ;; "ioctl" "join" "kill" "lc" "lcfirst" "le" "length"
5bd52f0e 5716 ;; "link" "listen" "localtime" "lock" "log" "lstat" "lt"
f83d2997
KH
5717 ;; "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "ne"
5718 ;; "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
5719 ;; "quotemeta" "rand" "read" "readdir" "readline"
5720 ;; "readlink" "readpipe" "recv" "ref" "rename" "require"
5721 ;; "reset" "reverse" "rewinddir" "rindex" "rmdir" "seek"
5722 ;; "seekdir" "select" "semctl" "semget" "semop" "send"
5723 ;; "setgrent" "sethostent" "setnetent" "setpgrp"
5724 ;; "setpriority" "setprotoent" "setpwent" "setservent"
5725 ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite"
5726 ;; "shutdown" "sin" "sleep" "socket" "socketpair"
5727 ;; "sprintf" "sqrt" "srand" "stat" "substr" "symlink"
6c389151 5728 ;; "syscall" "sysopen" "sysread" "system" "syswrite" "tell"
f83d2997
KH
5729 ;; "telldir" "time" "times" "truncate" "uc" "ucfirst"
5730 ;; "umask" "unlink" "unpack" "utime" "values" "vec"
5731 ;; "wait" "waitpid" "wantarray" "warn" "write" "x" "xor"
5c8b7eaf 5732 "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|"
f83d2997
KH
5733 "b\\(in\\(d\\|mode\\)\\|less\\)\\|"
5734 "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|"
5735 "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|"
5736 "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|"
5737 "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|"
5738 "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|"
5739 "f\\(ileno\\|cntl\\|lock\\|or\\(k\\|mline\\)\\)\\|"
5740 "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|"
5741 "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w"
5742 "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|"
5743 "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|"
5744 "ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|"
5745 "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|"
5746 "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|"
5747 "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e"
5bd52f0e 5748 "\\(\\|ngth\\)\\|o\\(c\\(altime\\|k\\)\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|"
f83d2997
KH
5749 "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|"
5750 "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|"
5751 "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin"
5752 "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name"
5753 "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r"
5754 "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|"
5755 "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|"
5756 "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|"
6c389151 5757 "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|open\\|tem\\|write\\)\\|"
f83d2997
KH
5758 "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|"
5759 "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|"
5760 "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|"
5761 "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|"
5762 "x\\(\\|or\\)\\|__\\(FILE__\\|LINE__\\|PACKAGE__\\)"
5763 "\\)\\>") 2 'font-lock-type-face)
5764 ;; In what follows we use `other' style
5765 ;; for nonoverwritable builtins
5766 ;; Somehow 's', 'm' are not auto-generated???
5767 (list
5768 (concat
5769 "\\(^\\|[^$@%&\\]\\)\\<\\("
6c389151 5770 ;; "AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "__END__" "chomp"
f83d2997
KH
5771 ;; "chop" "defined" "delete" "do" "each" "else" "elsif"
5772 ;; "eval" "exists" "for" "foreach" "format" "goto"
5773 ;; "grep" "if" "keys" "last" "local" "map" "my" "next"
4ab89e7b 5774 ;; "no" "our" "package" "pop" "pos" "print" "printf" "push"
f83d2997
KH
5775 ;; "q" "qq" "qw" "qx" "redo" "return" "scalar" "shift"
5776 ;; "sort" "splice" "split" "study" "sub" "tie" "tr"
5777 ;; "undef" "unless" "unshift" "untie" "until" "use"
5778 ;; "while" "y"
6c389151 5779 "AUTOLOAD\\|BEGIN\\|CHECK\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|"
f83d2997 5780 "o\\)\\|DESTROY\\|e\\(ach\\|val\\|xists\\|ls\\(e\\|if\\)\\)\\|"
6c389151
SM
5781 "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|INIT\\|if\\|keys\\|"
5782 "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|our\\|"
f83d2997 5783 "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|"
5bd52f0e 5784 "q\\(\\|q\\|w\\|x\\|r\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|"
f83d2997
KH
5785 "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|"
5786 "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|"
5787 "while\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added manually
5788 "\\|[sm]" ; Added manually
4ab89e7b 5789 "\\)\\>") 2 'cperl-nonoverridable-face)
f83d2997
KH
5790 ;; (mapconcat 'identity
5791 ;; '("#endif" "#else" "#ifdef" "#ifndef" "#if"
5792 ;; "#include" "#define" "#undef")
5793 ;; "\\|")
5794 '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0
5795 font-lock-function-name-face keep) ; Not very good, triggers at "[a-z]"
4c36be58 5796 ;; This highlights declarations and definitions differently.
4ab89e7b
SM
5797 ;; We do not try to highlight in the case of attributes:
5798 ;; it is already done by `cperl-find-pods-heres'
5799 (list (concat "\\<sub"
5800 cperl-white-and-comment-rex ; whitespace/comments
5801 "\\([^ \n\t{;()]+\\)" ; 2=name (assume non-anonymous)
5802 "\\("
5803 cperl-maybe-white-and-comment-rex ;whitespace/comments?
5804 "([^()]*)\\)?" ; prototype
5805 cperl-maybe-white-and-comment-rex ; whitespace/comments?
5806 "[{;]")
5807 2 (if cperl-font-lock-multiline
5808 '(if (eq (char-after (cperl-1- (match-end 0))) ?\{ )
5809 'font-lock-function-name-face
5810 'font-lock-variable-name-face)
5811 ;; need to manually set 'multiline' for older font-locks
5812 '(progn
5813 (if (< 1 (count-lines (match-beginning 0)
5814 (match-end 0)))
5815 (put-text-property
5816 (+ 3 (match-beginning 0)) (match-end 0)
5817 'syntax-type 'multiline))
5818 (if (eq (char-after (cperl-1- (match-end 0))) ?\{ )
5819 'font-lock-function-name-face
5820 'font-lock-variable-name-face))))
f83d2997
KH
5821 '("\\<\\(package\\|require\\|use\\|import\\|no\\|bootstrap\\)[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t;]" ; require A if B;
5822 2 font-lock-function-name-face)
5823 '("^[ \t]*format[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t]*=[ \t]*$"
5824 1 font-lock-function-name-face)
5825 (cond ((featurep 'font-lock-extra)
5c8b7eaf 5826 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
f83d2997
KH
5827 (2 font-lock-string-face t)
5828 (0 '(restart 2 t)))) ; To highlight $a{bc}{ef}
5829 (font-lock-anchored
5830 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
5831 (2 font-lock-string-face t)
5832 ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
5833 nil nil
5834 (1 font-lock-string-face t))))
5835 (t '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
5836 2 font-lock-string-face t)))
db133cb6 5837 '("[\[ \t{,(]\\(-?[a-zA-Z0-9_:]+\\)[ \t]*=>" 1
f83d2997 5838 font-lock-string-face t)
5c8b7eaf 5839 '("^[ \t]*\\([a-zA-Z0-9_]+[ \t]*:\\)[ \t]*\\($\\|{\\|\\<\\(until\\|while\\|for\\(each\\)?\\|do\\)\\>\\)" 1
83261a2f 5840 font-lock-constant-face) ; labels
f83d2997 5841 '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets
883212ce 5842 2 font-lock-constant-face)
6c389151
SM
5843 ;; Uncomment to get perl-mode-like vars
5844 ;;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
5845 ;;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
5846 ;;; (2 (cons font-lock-variable-name-face '(underline))))
f83d2997 5847 (cond ((featurep 'font-lock-extra)
6c389151 5848 '("^[ \t]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
f83d2997
KH
5849 (3 font-lock-variable-name-face)
5850 (4 '(another 4 nil
5851 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
5852 (1 font-lock-variable-name-face)
5c8b7eaf 5853 (2 '(restart 2 nil) nil t)))
f83d2997
KH
5854 nil t))) ; local variables, multiple
5855 (font-lock-anchored
4ab89e7b 5856 ;; 1=my_etc, 2=white? 3=(+white? 4=white? 5=var
9edd6ee6 5857 `(,(concat "\\<\\(my\\|local\\|our\\)"
4ab89e7b
SM
5858 cperl-maybe-white-and-comment-rex
5859 "\\(("
5860 cperl-maybe-white-and-comment-rex
9edd6ee6
SM
5861 "\\)?\\([$@%*]\\([a-zA-Z0-9_:]+\\|[^a-zA-Z0-9_]\\)\\)")
5862 (5 ,(if cperl-font-lock-multiline
4ab89e7b
SM
5863 'font-lock-variable-name-face
5864 '(progn (setq cperl-font-lock-multiline-start
5865 (match-beginning 0))
9edd6ee6
SM
5866 'font-lock-variable-name-face)))
5867 (,(concat "\\="
4ab89e7b
SM
5868 cperl-maybe-white-and-comment-rex
5869 ","
5870 cperl-maybe-white-and-comment-rex
9edd6ee6 5871 "\\([$@%*]\\([a-zA-Z0-9_:]+\\|[^a-zA-Z0-9_]\\)\\)")
cb5bf6ba 5872 ;; Bug in font-lock: limit is used not only to limit
4ab89e7b
SM
5873 ;; searches, but to set the "extend window for
5874 ;; facification" property. Thus we need to minimize.
9edd6ee6 5875 ,(if cperl-font-lock-multiline
4ab89e7b
SM
5876 '(if (match-beginning 3)
5877 (save-excursion
5878 (goto-char (match-beginning 3))
5879 (condition-case nil
5880 (forward-sexp 1)
5881 (error
5882 (condition-case nil
5883 (forward-char 200)
5884 (error nil)))) ; typeahead
5885 (1- (point))) ; report limit
5886 (forward-char -2)) ; disable continued expr
5887 '(if (match-beginning 3)
5888 (point-max) ; No limit for continuation
9edd6ee6
SM
5889 (forward-char -2))) ; disable continued expr
5890 ,(if cperl-font-lock-multiline
4ab89e7b
SM
5891 nil
5892 '(progn ; Do at end
5893 ;; "my" may be already fontified (POD),
5894 ;; so cperl-font-lock-multiline-start is nil
5895 (if (or (not cperl-font-lock-multiline-start)
5896 (> 2 (count-lines
5897 cperl-font-lock-multiline-start
5898 (point))))
5899 nil
5900 (put-text-property
5901 (1+ cperl-font-lock-multiline-start) (point)
5902 'syntax-type 'multiline))
9edd6ee6
SM
5903 (setq cperl-font-lock-multiline-start nil)))
5904 (3 font-lock-variable-name-face))))
4ab89e7b 5905 (t '("^[ \t{}]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
f83d2997 5906 3 font-lock-variable-name-face)))
6c389151 5907 '("\\<for\\(each\\)?\\([ \t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*("
eb6121fc 5908 4 font-lock-variable-name-face)
bbd240ce 5909 ;; Avoid $!, and s!!, qq!! etc. when not fontifying syntactically
9ed9fd35 5910 '("\\(?:^\\|[^smywqrx$]\\)\\(!\\)" 1 font-lock-negation-char-face)
eb6121fc 5911 '("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend)))
a1506d29 5912 (setq
f83d2997
KH
5913 t-font-lock-keywords-1
5914 (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock
4ab89e7b
SM
5915 ;; not yet as of XEmacs 19.12, works with 21.1.11
5916 (or
6546555e 5917 (not (featurep 'xemacs))
4ab89e7b
SM
5918 (string< "21.1.9" emacs-version)
5919 (and (string< "21.1.10" emacs-version)
5920 (string< emacs-version "21.1.2")))
f83d2997
KH
5921 '(
5922 ("\\(\\([@%]\\|\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
5923 (if (eq (char-after (match-beginning 2)) ?%)
4ab89e7b
SM
5924 'cperl-hash-face
5925 'cperl-array-face)
f83d2997
KH
5926 t) ; arrays and hashes
5927 ("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
5928 1
5c8b7eaf 5929 (if (= (- (match-end 2) (match-beginning 2)) 1)
f83d2997 5930 (if (eq (char-after (match-beginning 3)) ?{)
4ab89e7b
SM
5931 'cperl-hash-face
5932 'cperl-array-face) ; arrays and hashes
f83d2997
KH
5933 font-lock-variable-name-face) ; Just to put something
5934 t)
4ab89e7b
SM
5935 ("\\(@\\|\\$#\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
5936 (1 cperl-array-face)
5937 (2 font-lock-variable-name-face))
5938 ("\\(%\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
5939 (1 cperl-hash-face)
5940 (2 font-lock-variable-name-face))
f83d2997
KH
5941 ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
5942 ;;; Too much noise from \s* @s[ and friends
5c8b7eaf 5943 ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
f83d2997
KH
5944 ;;(3 font-lock-function-name-face t t)
5945 ;;(4
5946 ;; (if (cperl-slash-is-regexp)
5947 ;; font-lock-function-name-face 'default) nil t))
5948 )))
6c389151
SM
5949 (if cperl-highlight-variables-indiscriminately
5950 (setq t-font-lock-keywords-1
5951 (append t-font-lock-keywords-1
4ab89e7b 5952 (list '("\\([$*]{?\\sw+\\)" 1
6c389151 5953 font-lock-variable-name-face)))))
a1506d29 5954 (setq cperl-font-lock-keywords-1
5bd52f0e
RS
5955 (if cperl-syntaxify-by-font-lock
5956 (cons 'cperl-fontify-update
5957 t-font-lock-keywords)
5958 t-font-lock-keywords)
5efe6a56
SM
5959 cperl-font-lock-keywords cperl-font-lock-keywords-1
5960 cperl-font-lock-keywords-2 (append
6c389151
SM
5961 cperl-font-lock-keywords-1
5962 t-font-lock-keywords-1)))
f83d2997
KH
5963 (if (fboundp 'ps-print-buffer) (cperl-ps-print-init))
5964 (if (or (featurep 'choose-color) (featurep 'font-lock-extra))
db133cb6 5965 (eval ; Avoid a warning
83261a2f
SM
5966 '(font-lock-require-faces
5967 (list
5968 ;; Color-light Color-dark Gray-light Gray-dark Mono
5969 (list 'font-lock-comment-face
5970 ["Firebrick" "OrangeRed" "DimGray" "Gray80"]
5971 nil
5972 [nil nil t t t]
5973 [nil nil t t t]
5974 nil)
5975 (list 'font-lock-string-face
5976 ["RosyBrown" "LightSalmon" "Gray50" "LightGray"]
5977 nil
5978 nil
5979 [nil nil t t t]
5980 nil)
5981 (list 'font-lock-function-name-face
5982 (vector
5983 "Blue" "LightSkyBlue" "Gray50" "LightGray"
5984 (cdr (assq 'background-color ; if mono
5985 (frame-parameters))))
5986 (vector
5987 nil nil nil nil
5988 (cdr (assq 'foreground-color ; if mono
5989 (frame-parameters))))
5990 [nil nil t t t]
5991 nil
5992 nil)
5993 (list 'font-lock-variable-name-face
5994 ["DarkGoldenrod" "LightGoldenrod" "DimGray" "Gray90"]
5995 nil
5996 [nil nil t t t]
5997 [nil nil t t t]
5998 nil)
5999 (list 'font-lock-type-face
6000 ["DarkOliveGreen" "PaleGreen" "DimGray" "Gray80"]
6001 nil
6002 [nil nil t t t]
6003 nil
6004 [nil nil t t t])
4ab89e7b
SM
6005 (list 'font-lock-warning-face
6006 ["Pink" "Red" "Gray50" "LightGray"]
6007 ["gray20" "gray90"
6008 "gray80" "gray20"]
6009 [nil nil t t t]
6010 nil
6011 [nil nil t t t]
6012 )
83261a2f
SM
6013 (list 'font-lock-constant-face
6014 ["CadetBlue" "Aquamarine" "Gray50" "LightGray"]
6015 nil
6016 [nil nil t t t]
6017 nil
6018 [nil nil t t t])
4ab89e7b 6019 (list 'cperl-nonoverridable-face
83261a2f
SM
6020 ["chartreuse3" ("orchid1" "orange")
6021 nil "Gray80"]
6022 [nil nil "gray90"]
6023 [nil nil nil t t]
6024 [nil nil t t]
6025 [nil nil t t t])
4ab89e7b 6026 (list 'cperl-array-face
83261a2f
SM
6027 ["blue" "yellow" nil "Gray80"]
6028 ["lightyellow2" ("navy" "os2blue" "darkgreen")
6029 "gray90"]
6030 t
6031 nil
6032 nil)
4ab89e7b 6033 (list 'cperl-hash-face
83261a2f
SM
6034 ["red" "red" nil "Gray80"]
6035 ["lightyellow2" ("navy" "os2blue" "darkgreen")
6036 "gray90"]
6037 t
6038 t
6039 nil))))
5bd52f0e 6040 ;; Do it the dull way, without choose-color
f83d2997
KH
6041 (defvar cperl-guessed-background nil
6042 "Display characteristics as guessed by cperl.")
83261a2f 6043 ;; (or (fboundp 'x-color-defined-p)
15ca5699 6044 ;; (defalias 'x-color-defined-p
83261a2f
SM
6045 ;; (cond ((fboundp 'color-defined-p) 'color-defined-p)
6046 ;; ;; XEmacs >= 19.12
6047 ;; ((fboundp 'valid-color-name-p) 'valid-color-name-p)
6048 ;; ;; XEmacs 19.11
6049 ;; (t 'x-valid-color-name-p))))
5c8b7eaf 6050 (cperl-force-face font-lock-constant-face
5bd52f0e
RS
6051 "Face for constant and label names")
6052 (cperl-force-face font-lock-variable-name-face
6053 "Face for variable names")
6054 (cperl-force-face font-lock-type-face
6055 "Face for data types")
4ab89e7b 6056 (cperl-force-face cperl-nonoverridable-face
5bd52f0e 6057 "Face for data types from another group")
4ab89e7b
SM
6058 (cperl-force-face font-lock-warning-face
6059 "Face for things which should stand out")
5bd52f0e
RS
6060 (cperl-force-face font-lock-comment-face
6061 "Face for comments")
6062 (cperl-force-face font-lock-function-name-face
6063 "Face for function names")
4ab89e7b 6064 (cperl-force-face cperl-hash-face
5bd52f0e 6065 "Face for hashes")
4ab89e7b 6066 (cperl-force-face cperl-array-face
5bd52f0e
RS
6067 "Face for arrays")
6068 ;;(defvar font-lock-constant-face 'font-lock-constant-face)
6069 ;;(defvar font-lock-variable-name-face 'font-lock-variable-name-face)
6070 ;;(or (boundp 'font-lock-type-face)
6071 ;; (defconst font-lock-type-face
6072 ;; 'font-lock-type-face
6073 ;; "Face to use for data types."))
6074 ;;(or (boundp 'cperl-nonoverridable-face)
6075 ;; (defconst cperl-nonoverridable-face
4ab89e7b 6076 ;; 'cperl-nonoverridable-face
5bd52f0e 6077 ;; "Face to use for data types from another group."))
6546555e 6078 ;;(if (not (featurep 'xemacs)) nil
5bd52f0e
RS
6079 ;; (or (boundp 'font-lock-comment-face)
6080 ;; (defconst font-lock-comment-face
6081 ;; 'font-lock-comment-face
6082 ;; "Face to use for comments."))
6083 ;; (or (boundp 'font-lock-keyword-face)
6084 ;; (defconst font-lock-keyword-face
6085 ;; 'font-lock-keyword-face
6086 ;; "Face to use for keywords."))
6087 ;; (or (boundp 'font-lock-function-name-face)
6088 ;; (defconst font-lock-function-name-face
6089 ;; 'font-lock-function-name-face
6090 ;; "Face to use for function names.")))
6091 (if (and
4ab89e7b 6092 (not (cperl-is-face 'cperl-array-face))
5c8b7eaf 6093 (cperl-is-face 'font-lock-emphasized-face))
4ab89e7b 6094 (copy-face 'font-lock-emphasized-face 'cperl-array-face))
5bd52f0e 6095 (if (and
4ab89e7b 6096 (not (cperl-is-face 'cperl-hash-face))
5c8b7eaf 6097 (cperl-is-face 'font-lock-other-emphasized-face))
4ab89e7b 6098 (copy-face 'font-lock-other-emphasized-face 'cperl-hash-face))
5bd52f0e 6099 (if (and
4ab89e7b 6100 (not (cperl-is-face 'cperl-nonoverridable-face))
5c8b7eaf 6101 (cperl-is-face 'font-lock-other-type-face))
4ab89e7b 6102 (copy-face 'font-lock-other-type-face 'cperl-nonoverridable-face))
5bd52f0e
RS
6103 ;;(or (boundp 'cperl-hash-face)
6104 ;; (defconst cperl-hash-face
4ab89e7b 6105 ;; 'cperl-hash-face
5bd52f0e
RS
6106 ;; "Face to use for hashes."))
6107 ;;(or (boundp 'cperl-array-face)
6108 ;; (defconst cperl-array-face
4ab89e7b 6109 ;; 'cperl-array-face
5bd52f0e 6110 ;; "Face to use for arrays."))
f83d2997
KH
6111 ;; Here we try to guess background
6112 (let ((background
6113 (if (boundp 'font-lock-background-mode)
6114 font-lock-background-mode
5c8b7eaf 6115 'light))
83261a2f 6116 (face-list (and (fboundp 'face-list) (face-list))))
5bd52f0e
RS
6117;;;; (fset 'cperl-is-face
6118;;;; (cond ((fboundp 'find-face)
6119;;;; (symbol-function 'find-face))
6120;;;; (face-list
6121;;;; (function (lambda (face) (member face face-list))))
6122;;;; (t
6123;;;; (function (lambda (face) (boundp face))))))
f83d2997
KH
6124 (defvar cperl-guessed-background
6125 (if (and (boundp 'font-lock-display-type)
6126 (eq font-lock-display-type 'grayscale))
6127 'gray
6128 background)
6129 "Background as guessed by CPerl mode")
83261a2f
SM
6130 (and (not (cperl-is-face 'font-lock-constant-face))
6131 (cperl-is-face 'font-lock-reference-face)
6132 (copy-face 'font-lock-reference-face 'font-lock-constant-face))
db133cb6 6133 (if (cperl-is-face 'font-lock-type-face) nil
f83d2997
KH
6134 (copy-face 'default 'font-lock-type-face)
6135 (cond
6136 ((eq background 'light)
6137 (set-face-foreground 'font-lock-type-face
6138 (if (x-color-defined-p "seagreen")
6139 "seagreen"
6140 "sea green")))
6141 ((eq background 'dark)
6142 (set-face-foreground 'font-lock-type-face
6143 (if (x-color-defined-p "os2pink")
6144 "os2pink"
6145 "pink")))
6146 (t
6147 (set-face-background 'font-lock-type-face "gray90"))))
4ab89e7b 6148 (if (cperl-is-face 'cperl-nonoverridable-face)
f83d2997 6149 nil
4ab89e7b 6150 (copy-face 'font-lock-type-face 'cperl-nonoverridable-face)
f83d2997
KH
6151 (cond
6152 ((eq background 'light)
4ab89e7b 6153 (set-face-foreground 'cperl-nonoverridable-face
f83d2997
KH
6154 (if (x-color-defined-p "chartreuse3")
6155 "chartreuse3"
6156 "chartreuse")))
6157 ((eq background 'dark)
4ab89e7b 6158 (set-face-foreground 'cperl-nonoverridable-face
f83d2997
KH
6159 (if (x-color-defined-p "orchid1")
6160 "orchid1"
6161 "orange")))))
5bd52f0e
RS
6162;;; (if (cperl-is-face 'font-lock-other-emphasized-face) nil
6163;;; (copy-face 'bold-italic 'font-lock-other-emphasized-face)
6164;;; (cond
6165;;; ((eq background 'light)
6166;;; (set-face-background 'font-lock-other-emphasized-face
6167;;; (if (x-color-defined-p "lightyellow2")
6168;;; "lightyellow2"
6169;;; (if (x-color-defined-p "lightyellow")
6170;;; "lightyellow"
6171;;; "light yellow"))))
6172;;; ((eq background 'dark)
6173;;; (set-face-background 'font-lock-other-emphasized-face
6174;;; (if (x-color-defined-p "navy")
6175;;; "navy"
6176;;; (if (x-color-defined-p "darkgreen")
6177;;; "darkgreen"
6178;;; "dark green"))))
6179;;; (t (set-face-background 'font-lock-other-emphasized-face "gray90"))))
6180;;; (if (cperl-is-face 'font-lock-emphasized-face) nil
6181;;; (copy-face 'bold 'font-lock-emphasized-face)
6182;;; (cond
6183;;; ((eq background 'light)
6184;;; (set-face-background 'font-lock-emphasized-face
6185;;; (if (x-color-defined-p "lightyellow2")
6186;;; "lightyellow2"
6187;;; "lightyellow")))
6188;;; ((eq background 'dark)
6189;;; (set-face-background 'font-lock-emphasized-face
6190;;; (if (x-color-defined-p "navy")
6191;;; "navy"
6192;;; (if (x-color-defined-p "darkgreen")
6193;;; "darkgreen"
6194;;; "dark green"))))
6195;;; (t (set-face-background 'font-lock-emphasized-face "gray90"))))
db133cb6 6196 (if (cperl-is-face 'font-lock-variable-name-face) nil
f83d2997 6197 (copy-face 'italic 'font-lock-variable-name-face))
db133cb6 6198 (if (cperl-is-face 'font-lock-constant-face) nil
883212ce 6199 (copy-face 'italic 'font-lock-constant-face))))
f83d2997 6200 (setq cperl-faces-init t))
5bd52f0e 6201 (error (message "cperl-init-faces (ignored): %s" errs))))
f83d2997
KH
6202
6203
6204(defun cperl-ps-print-init ()
6205 "Initialization of `ps-print' components for faces used in CPerl."
5bd52f0e
RS
6206 (eval-after-load "ps-print"
6207 '(setq ps-bold-faces
5c8b7eaf 6208 ;; font-lock-variable-name-face
5bd52f0e 6209 ;; font-lock-constant-face
4ab89e7b 6210 (append '(cperl-array-face cperl-hash-face)
5bd52f0e
RS
6211 ps-bold-faces)
6212 ps-italic-faces
6213 ;; font-lock-constant-face
4ab89e7b 6214 (append '(cperl-nonoverridable-face cperl-hash-face)
5bd52f0e
RS
6215 ps-italic-faces)
6216 ps-underlined-faces
6217 ;; font-lock-type-face
4ab89e7b 6218 (append '(cperl-array-face cperl-hash-face underline cperl-nonoverridable-face)
5bd52f0e
RS
6219 ps-underlined-faces))))
6220
6221(defvar ps-print-face-extension-alist)
6222
6223(defun cperl-ps-print (&optional file)
6224 "Pretty-print in CPerl style.
6225If optional argument FILE is an empty string, prints to printer, otherwise
6226to the file FILE. If FILE is nil, prompts for a file name.
6227
6228Style of printout regulated by the variable `cperl-ps-print-face-properties'."
6229 (interactive)
5c8b7eaf
SS
6230 (or file
6231 (setq file (read-from-minibuffer
5bd52f0e
RS
6232 "Print to file (if empty - to printer): "
6233 (concat (buffer-file-name) ".ps")
6234 nil nil 'file-name-history)))
6235 (or (> (length file) 0)
6236 (setq file nil))
6237 (require 'ps-print) ; To get ps-print-face-extension-alist
6238 (let ((ps-print-color-p t)
6239 (ps-print-face-extension-alist ps-print-face-extension-alist))
6240 (cperl-ps-extend-face-list cperl-ps-print-face-properties)
6241 (ps-print-buffer-with-faces file)))
6242
6243;;; (defun cperl-ps-print-init ()
6244;;; "Initialization of `ps-print' components for faces used in CPerl."
6245;;; ;; Guard against old versions
6246;;; (defvar ps-underlined-faces nil)
6247;;; (defvar ps-bold-faces nil)
6248;;; (defvar ps-italic-faces nil)
6249;;; (setq ps-bold-faces
6250;;; (append '(font-lock-emphasized-face
4ab89e7b 6251;;; cperl-array-face
5c8b7eaf
SS
6252;;; font-lock-keyword-face
6253;;; font-lock-variable-name-face
6254;;; font-lock-constant-face
6255;;; font-lock-reference-face
5bd52f0e 6256;;; font-lock-other-emphasized-face
4ab89e7b 6257;;; cperl-hash-face)
5bd52f0e
RS
6258;;; ps-bold-faces))
6259;;; (setq ps-italic-faces
4ab89e7b 6260;;; (append '(cperl-nonoverridable-face
5c8b7eaf
SS
6261;;; font-lock-constant-face
6262;;; font-lock-reference-face
5bd52f0e 6263;;; font-lock-other-emphasized-face
4ab89e7b 6264;;; cperl-hash-face)
5bd52f0e
RS
6265;;; ps-italic-faces))
6266;;; (setq ps-underlined-faces
6267;;; (append '(font-lock-emphasized-face
4ab89e7b 6268;;; cperl-array-face
5bd52f0e 6269;;; font-lock-other-emphasized-face
4ab89e7b
SM
6270;;; cperl-hash-face
6271;;; cperl-nonoverridable-face font-lock-type-face)
5bd52f0e
RS
6272;;; ps-underlined-faces))
6273;;; (cons 'font-lock-type-face ps-underlined-faces))
f83d2997
KH
6274
6275
6276(if (cperl-enable-font-lock) (cperl-windowed-init))
6277
db133cb6 6278(defconst cperl-styles-entries
5c8b7eaf
SS
6279 '(cperl-indent-level cperl-brace-offset cperl-continued-brace-offset
6280 cperl-label-offset cperl-extra-newline-before-brace
4ab89e7b 6281 cperl-extra-newline-before-brace-multiline
bab27c0c 6282 cperl-merge-trailing-else
db133cb6
RS
6283 cperl-continued-statement-offset))
6284
4ab89e7b
SM
6285(defconst cperl-style-examples
6286"##### Numbers etc are: cperl-indent-level cperl-brace-offset
6287##### cperl-continued-brace-offset cperl-label-offset
6288##### cperl-continued-statement-offset
6289##### cperl-merge-trailing-else cperl-extra-newline-before-brace
6290
6291########### (Do not forget cperl-extra-newline-before-brace-multiline)
6292
6293### CPerl (=GNU - extra-newline-before-brace + merge-trailing-else) 2/0/0/-2/2/t/nil
6294if (foo) {
6295 bar
6296 baz;
6297 label:
6298 {
6299 boon;
6300 }
6301} else {
6302 stop;
6303}
6304
6305### PerlStyle (=CPerl with 4 as indent) 4/0/0/-4/4/t/nil
6306if (foo) {
6307 bar
6308 baz;
6309 label:
6310 {
6311 boon;
6312 }
6313} else {
6314 stop;
6315}
6316
6317### GNU 2/0/0/-2/2/nil/t
6318if (foo)
6319 {
6320 bar
6321 baz;
6322 label:
6323 {
6324 boon;
6325 }
6326 }
6327else
6328 {
6329 stop;
6330 }
6331
6332### C++ (=PerlStyle with braces aligned with control words) 4/0/-4/-4/4/nil/t
6333if (foo)
6334{
6335 bar
6336 baz;
6337 label:
6338 {
6339 boon;
6340 }
6341}
6342else
6343{
6344 stop;
6345}
6346
6347### BSD (=C++, but will not change preexisting merge-trailing-else
6348### and extra-newline-before-brace ) 4/0/-4/-4/4
6349if (foo)
6350{
6351 bar
6352 baz;
6353 label:
6354 {
6355 boon;
6356 }
6357}
6358else
6359{
6360 stop;
6361}
6362
6363### K&R (=C++ with indent 5 - merge-trailing-else, but will not
6364### change preexisting extra-newline-before-brace) 5/0/-5/-5/5/nil
6365if (foo)
6366{
6367 bar
6368 baz;
6369 label:
6370 {
6371 boon;
6372 }
6373}
6374else
6375{
6376 stop;
6377}
6378
6379### Whitesmith (=PerlStyle, but will not change preexisting
6380### extra-newline-before-brace and merge-trailing-else) 4/0/0/-4/4
6381if (foo)
6382 {
6383 bar
6384 baz;
6385 label:
6386 {
6387 boon;
6388 }
6389 }
6390else
6391 {
6392 stop;
6393 }
6394"
6395"Examples of if/else with different indent styles (with v4.23).")
6396
db133cb6 6397(defconst cperl-style-alist
4ab89e7b 6398 '(("CPerl" ;; =GNU - extra-newline-before-brace + cperl-merge-trailing-else
db133cb6
RS
6399 (cperl-indent-level . 2)
6400 (cperl-brace-offset . 0)
6401 (cperl-continued-brace-offset . 0)
6402 (cperl-label-offset . -2)
4ab89e7b 6403 (cperl-continued-statement-offset . 2)
db133cb6 6404 (cperl-extra-newline-before-brace . nil)
4ab89e7b
SM
6405 (cperl-extra-newline-before-brace-multiline . nil)
6406 (cperl-merge-trailing-else . t))
6407
83261a2f 6408 ("PerlStyle" ; CPerl with 4 as indent
db133cb6
RS
6409 (cperl-indent-level . 4)
6410 (cperl-brace-offset . 0)
6411 (cperl-continued-brace-offset . 0)
6412 (cperl-label-offset . -4)
4ab89e7b 6413 (cperl-continued-statement-offset . 4)
db133cb6 6414 (cperl-extra-newline-before-brace . nil)
4ab89e7b
SM
6415 (cperl-extra-newline-before-brace-multiline . nil)
6416 (cperl-merge-trailing-else . t))
6417
db133cb6
RS
6418 ("GNU"
6419 (cperl-indent-level . 2)
6420 (cperl-brace-offset . 0)
6421 (cperl-continued-brace-offset . 0)
6422 (cperl-label-offset . -2)
4ab89e7b 6423 (cperl-continued-statement-offset . 2)
db133cb6 6424 (cperl-extra-newline-before-brace . t)
4ab89e7b
SM
6425 (cperl-extra-newline-before-brace-multiline . t)
6426 (cperl-merge-trailing-else . nil))
6427
db133cb6
RS
6428 ("K&R"
6429 (cperl-indent-level . 5)
6430 (cperl-brace-offset . 0)
6431 (cperl-continued-brace-offset . -5)
6432 (cperl-label-offset . -5)
4ab89e7b 6433 (cperl-continued-statement-offset . 5)
db133cb6 6434 ;;(cperl-extra-newline-before-brace . nil) ; ???
4ab89e7b
SM
6435 ;;(cperl-extra-newline-before-brace-multiline . nil)
6436 (cperl-merge-trailing-else . nil))
6437
db133cb6
RS
6438 ("BSD"
6439 (cperl-indent-level . 4)
6440 (cperl-brace-offset . 0)
6441 (cperl-continued-brace-offset . -4)
6442 (cperl-label-offset . -4)
4ab89e7b 6443 (cperl-continued-statement-offset . 4)
db133cb6 6444 ;;(cperl-extra-newline-before-brace . nil) ; ???
4ab89e7b
SM
6445 ;;(cperl-extra-newline-before-brace-multiline . nil)
6446 ;;(cperl-merge-trailing-else . nil) ; ???
6447 )
6448
db133cb6
RS
6449 ("C++"
6450 (cperl-indent-level . 4)
6451 (cperl-brace-offset . 0)
6452 (cperl-continued-brace-offset . -4)
6453 (cperl-label-offset . -4)
6454 (cperl-continued-statement-offset . 4)
4ab89e7b
SM
6455 (cperl-extra-newline-before-brace . t)
6456 (cperl-extra-newline-before-brace-multiline . t)
6457 (cperl-merge-trailing-else . nil))
6458
db133cb6
RS
6459 ("Whitesmith"
6460 (cperl-indent-level . 4)
6461 (cperl-brace-offset . 0)
6462 (cperl-continued-brace-offset . 0)
6463 (cperl-label-offset . -4)
4ab89e7b 6464 (cperl-continued-statement-offset . 4)
db133cb6 6465 ;;(cperl-extra-newline-before-brace . nil) ; ???
4ab89e7b
SM
6466 ;;(cperl-extra-newline-before-brace-multiline . nil)
6467 ;;(cperl-merge-trailing-else . nil) ; ???
6468 )
6469 ("Current"))
6470 "List of variables to set to get a particular indentation style.
6471Should be used via `cperl-set-style' or via Perl menu.
6472
6473See examples in `cperl-style-examples'.")
db133cb6 6474
f83d2997 6475(defun cperl-set-style (style)
f94a632a 6476 "Set CPerl mode variables to use one of several different indentation styles.
f83d2997 6477The arguments are a string representing the desired style.
5c8b7eaf 6478The list of styles is in `cperl-style-alist', available styles
4ab89e7b 6479are CPerl, PerlStyle, GNU, K&R, BSD, C++ and Whitesmith.
db133cb6
RS
6480
6481The current value of style is memorized (unless there is a memorized
6482data already), may be restored by `cperl-set-style-back'.
6483
fe3c5669 6484Choosing \"Current\" style will not change style, so this may be used for
4ab89e7b 6485side-effect of memorizing only. Examples in `cperl-style-examples'."
5c8b7eaf 6486 (interactive
15ca5699 6487 (let ((list (mapcar (function (lambda (elt) (list (car elt))))
db133cb6 6488 cperl-style-alist)))
f83d2997 6489 (list (completing-read "Enter style: " list nil 'insist))))
db133cb6
RS
6490 (or cperl-old-style
6491 (setq cperl-old-style
6492 (mapcar (function
6493 (lambda (name)
6494 (cons name (eval name))))
6495 cperl-styles-entries)))
6496 (let ((style (cdr (assoc style cperl-style-alist))) setting str sym)
f83d2997
KH
6497 (while style
6498 (setq setting (car style) style (cdr style))
db133cb6
RS
6499 (set (car setting) (cdr setting)))))
6500
6501(defun cperl-set-style-back ()
810fb442 6502 "Restore a style memorized by `cperl-set-style'."
db133cb6
RS
6503 (interactive)
6504 (or cperl-old-style (error "The style was not changed"))
6505 (let (setting)
6506 (while cperl-old-style
5c8b7eaf 6507 (setq setting (car cperl-old-style)
db133cb6
RS
6508 cperl-old-style (cdr cperl-old-style))
6509 (set (car setting) (cdr setting)))))
f83d2997
KH
6510
6511(defun cperl-check-syntax ()
6512 (interactive)
6513 (require 'mode-compile)
db133cb6
RS
6514 (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc")))
6515 (eval '(mode-compile)))) ; Avoid a warning
f83d2997
KH
6516
6517(defun cperl-info-buffer (type)
6518 ;; Returns buffer with documentation. Creates if missing.
6519 ;; If TYPE, this vars buffer.
6520 ;; Special care is taken to not stomp over an existing info buffer
6521 (let* ((bname (if type "*info-perl-var*" "*info-perl*"))
6522 (info (get-buffer bname))
6523 (oldbuf (get-buffer "*info*")))
6524 (if info info
6525 (save-window-excursion
6526 ;; Get Info running
6527 (require 'info)
6528 (cond (oldbuf
6529 (set-buffer oldbuf)
6530 (rename-buffer "*info-perl-tmp*")))
6531 (save-window-excursion
6532 (info))
6533 (Info-find-node cperl-info-page (if type "perlvar" "perlfunc"))
6534 (set-buffer "*info*")
6535 (rename-buffer bname)
6536 (cond (oldbuf
6537 (set-buffer "*info-perl-tmp*")
6538 (rename-buffer "*info*")
6539 (set-buffer bname)))
029cb4d5 6540 (make-local-variable 'window-min-height)
f83d2997
KH
6541 (setq window-min-height 2)
6542 (current-buffer)))))
6543
6544(defun cperl-word-at-point (&optional p)
f94a632a 6545 "Return the word at point or at P."
f83d2997
KH
6546 (save-excursion
6547 (if p (goto-char p))
6548 (or (cperl-word-at-point-hard)
6549 (progn
6550 (require 'etags)
6551 (funcall (or (and (boundp 'find-tag-default-function)
6552 find-tag-default-function)
6553 (get major-mode 'find-tag-default-function)
6554 ;; XEmacs 19.12 has `find-tag-default-hook'; it is
6555 ;; automatically used within `find-tag-default':
6556 'find-tag-default))))))
6557
6558(defun cperl-info-on-command (command)
f94a632a 6559 "Show documentation for Perl command COMMAND in other window.
f83d2997
KH
6560If perl-info buffer is shown in some frame, uses this frame.
6561Customized by setting variables `cperl-shrink-wrap-info-frame',
6562`cperl-max-help-size'."
5c8b7eaf 6563 (interactive
f83d2997 6564 (let* ((default (cperl-word-at-point))
5c8b7eaf 6565 (read (read-string
83261a2f
SM
6566 (format "Find doc for Perl function (default %s): "
6567 default))))
5c8b7eaf 6568 (list (if (equal read "")
83261a2f
SM
6569 default
6570 read))))
f83d2997
KH
6571
6572 (let ((buffer (current-buffer))
6573 (cmd-desc (concat "^" (regexp-quote command) "[^a-zA-Z_0-9]")) ; "tr///"
6574 pos isvar height iniheight frheight buf win fr1 fr2 iniwin not-loner
6575 max-height char-height buf-list)
6576 (if (string-match "^-[a-zA-Z]$" command)
6577 (setq cmd-desc "^-X[ \t\n]"))
6578 (setq isvar (string-match "^[$@%]" command)
6579 buf (cperl-info-buffer isvar)
6580 iniwin (selected-window)
6581 fr1 (window-frame iniwin))
6582 (set-buffer buf)
fc49c9c6 6583 (goto-char (point-min))
5c8b7eaf 6584 (or isvar
f83d2997
KH
6585 (progn (re-search-forward "^-X[ \t\n]")
6586 (forward-line -1)))
6587 (if (re-search-forward cmd-desc nil t)
6588 (progn
6589 ;; Go back to beginning of the group (ex, for qq)
6590 (if (re-search-backward "^[ \t\n\f]")
6591 (forward-line 1))
6592 (beginning-of-line)
5c8b7eaf 6593 ;; Get some of
f83d2997
KH
6594 (setq pos (point)
6595 buf-list (list buf "*info-perl-var*" "*info-perl*"))
6596 (while (and (not win) buf-list)
6597 (setq win (get-buffer-window (car buf-list) t))
6598 (setq buf-list (cdr buf-list)))
6599 (or (not win)
6600 (eq (window-buffer win) buf)
6601 (set-window-buffer win buf))
6602 (and win (setq fr2 (window-frame win)))
6603 (if (or (not fr2) (eq fr1 fr2))
6604 (pop-to-buffer buf)
6605 (special-display-popup-frame buf) ; Make it visible
6606 (select-window win))
6607 (goto-char pos) ; Needed (?!).
6608 ;; Resize
6609 (setq iniheight (window-height)
6610 frheight (frame-height)
6611 not-loner (< iniheight (1- frheight))) ; Are not alone
5c8b7eaf 6612 (cond ((if not-loner cperl-max-help-size
f83d2997 6613 cperl-shrink-wrap-info-frame)
5c8b7eaf
SS
6614 (setq height
6615 (+ 2
6616 (count-lines
6617 pos
f83d2997
KH
6618 (save-excursion
6619 (if (re-search-forward
6620 "^[ \t][^\n]*\n+\\([^ \t\n\f]\\|\\'\\)" nil t)
6621 (match-beginning 0) (point-max)))))
5c8b7eaf 6622 max-height
f83d2997
KH
6623 (if not-loner
6624 (/ (* (- frheight 3) cperl-max-help-size) 100)
6625 (setq char-height (frame-char-height))
6626 ;; Non-functioning under OS/2:
6627 (if (eq char-height 1) (setq char-height 18))
6628 ;; Title, menubar, + 2 for slack
d431decb 6629 (- (/ (display-pixel-height) char-height) 4)))
f83d2997
KH
6630 (if (> height max-height) (setq height max-height))
6631 ;;(message "was %s doing %s" iniheight height)
6632 (if not-loner
6633 (enlarge-window (- height iniheight))
6634 (set-frame-height (window-frame win) (1+ height)))))
6635 (set-window-start (selected-window) pos))
6636 (message "No entry for %s found." command))
6637 ;;(pop-to-buffer buffer)
6638 (select-window iniwin)))
6639
6640(defun cperl-info-on-current-command ()
029cb4d5 6641 "Show documentation for Perl command at point in other window."
f83d2997
KH
6642 (interactive)
6643 (cperl-info-on-command (cperl-word-at-point)))
6644
6645(defun cperl-imenu-info-imenu-search ()
6646 (if (looking-at "^-X[ \t\n]") nil
6647 (re-search-backward
6648 "^\n\\([-a-zA-Z_]+\\)[ \t\n]")
6649 (forward-line 1)))
6650
5c8b7eaf 6651(defun cperl-imenu-info-imenu-name ()
f83d2997
KH
6652 (buffer-substring
6653 (match-beginning 1) (match-end 1)))
6654
6655(defun cperl-imenu-on-info ()
4ab89e7b
SM
6656 "Shows imenu for Perl Info Buffer.
6657Opens Perl Info buffer if needed."
f83d2997
KH
6658 (interactive)
6659 (let* ((buffer (current-buffer))
6660 imenu-create-index-function
5c8b7eaf
SS
6661 imenu-prev-index-position-function
6662 imenu-extract-index-name-function
f83d2997
KH
6663 (index-item (save-restriction
6664 (save-window-excursion
6665 (set-buffer (cperl-info-buffer nil))
5c8b7eaf 6666 (setq imenu-create-index-function
f83d2997
KH
6667 'imenu-default-create-index-function
6668 imenu-prev-index-position-function
6669 'cperl-imenu-info-imenu-search
6670 imenu-extract-index-name-function
6671 'cperl-imenu-info-imenu-name)
6672 (imenu-choose-buffer-index)))))
6673 (and index-item
6674 (progn
6675 (push-mark)
6676 (pop-to-buffer "*info-perl*")
6677 (cond
6678 ((markerp (cdr index-item))
6679 (goto-char (marker-position (cdr index-item))))
6680 (t
6681 (goto-char (cdr index-item))))
6682 (set-window-start (selected-window) (point))
6683 (pop-to-buffer buffer)))))
6684
6685(defun cperl-lineup (beg end &optional step minshift)
6686 "Lineup construction in a region.
6687Beginning of region should be at the start of a construction.
6688All first occurrences of this construction in the lines that are
6689partially contained in the region are lined up at the same column.
6690
6691MINSHIFT is the minimal amount of space to insert before the construction.
6692STEP is the tabwidth to position constructions.
029cb4d5 6693If STEP is nil, `cperl-lineup-step' will be used
15ca5699 6694\(or `cperl-indent-level', if `cperl-lineup-step' is nil).
f83d2997
KH
6695Will not move the position at the start to the left."
6696 (interactive "r")
4ab89e7b 6697 (let (search col tcol seen b)
f83d2997
KH
6698 (save-excursion
6699 (goto-char end)
6700 (end-of-line)
6701 (setq end (point-marker))
6702 (goto-char beg)
6703 (skip-chars-forward " \t\f")
6704 (setq beg (point-marker))
6705 (indent-region beg end nil)
6706 (goto-char beg)
6707 (setq col (current-column))
6708 (if (looking-at "[a-zA-Z0-9_]")
6709 (if (looking-at "\\<[a-zA-Z0-9_]+\\>")
6710 (setq search
5c8b7eaf
SS
6711 (concat "\\<"
6712 (regexp-quote
f83d2997
KH
6713 (buffer-substring (match-beginning 0)
6714 (match-end 0))) "\\>"))
6715 (error "Cannot line up in a middle of the word"))
6716 (if (looking-at "$")
6717 (error "Cannot line up end of line"))
6718 (setq search (regexp-quote (char-to-string (following-char)))))
6719 (setq step (or step cperl-lineup-step cperl-indent-level))
6720 (or minshift (setq minshift 1))
6721 (while (progn
6722 (beginning-of-line 2)
5c8b7eaf 6723 (and (< (point) end)
f83d2997
KH
6724 (re-search-forward search end t)
6725 (goto-char (match-beginning 0))))
6726 (setq tcol (current-column) seen t)
6727 (if (> tcol col) (setq col tcol)))
6728 (or seen
6729 (error "The construction to line up occurred only once"))
6730 (goto-char beg)
6731 (setq col (+ col minshift))
6732 (if (/= (% col step) 0) (setq step (* step (1+ (/ col step)))))
5c8b7eaf 6733 (while
f83d2997 6734 (progn
4ab89e7b 6735 (cperl-make-indent col)
5c8b7eaf
SS
6736 (beginning-of-line 2)
6737 (and (< (point) end)
f83d2997
KH
6738 (re-search-forward search end t)
6739 (goto-char (match-beginning 0)))))))) ; No body
6740
4ab89e7b 6741(defun cperl-etags (&optional add all files) ;; NOT USED???
f83d2997
KH
6742 "Run etags with appropriate options for Perl files.
6743If optional argument ALL is `recursive', will process Perl files
6744in subdirectories too."
6745 (interactive)
6746 (let ((cmd "etags")
4ab89e7b
SM
6747 (args '("-l" "none" "-r"
6748 ;; 1=fullname 2=package? 3=name 4=proto? 5=attrs? (VERY APPROX!)
6749 "/\\<sub[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)\\)[ \\t]*\\(([^()]*)[ \t]*\\)?\\([ \t]*:[^#{;]*\\)?\\([{#]\\|$\\)/\\3/"
6750 "-r"
6751 "/\\<package[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)\\)[ \\t]*\\([#;]\\|$\\)/\\1/"
6752 "-r"
6753 "/\\<\\(package\\)[ \\t]*;/\\1;/"))
f83d2997
KH
6754 res)
6755 (if add (setq args (cons "-a" args)))
6756 (or files (setq files (list buffer-file-name)))
6757 (cond
6758 ((eq all 'recursive)
6759 ;;(error "Not implemented: recursive")
5c8b7eaf 6760 (setq args (append (list "-e"
f83d2997
KH
6761 "sub wanted {push @ARGV, $File::Find::name if /\\.[pP][Llm]$/}
6762 use File::Find;
6763 find(\\&wanted, '.');
5c8b7eaf 6764 exec @ARGV;"
f83d2997
KH
6765 cmd) args)
6766 cmd "perl"))
5c8b7eaf 6767 (all
f83d2997 6768 ;;(error "Not implemented: all")
5c8b7eaf 6769 (setq args (append (list "-e"
f83d2997 6770 "push @ARGV, <*.PL *.pl *.pm>;
5c8b7eaf 6771 exec @ARGV;"
f83d2997
KH
6772 cmd) args)
6773 cmd "perl"))
6774 (t
6775 (setq args (append args files))))
6776 (setq res (apply 'call-process cmd nil nil nil args))
6777 (or (eq res 0)
6778 (message "etags returned \"%s\"" res))))
6779
6780(defun cperl-toggle-auto-newline ()
6781 "Toggle the state of `cperl-auto-newline'."
6782 (interactive)
6783 (setq cperl-auto-newline (not cperl-auto-newline))
5c8b7eaf 6784 (message "Newlines will %sbe auto-inserted now."
f83d2997
KH
6785 (if cperl-auto-newline "" "not ")))
6786
6787(defun cperl-toggle-abbrev ()
6788 "Toggle the state of automatic keyword expansion in CPerl mode."
6789 (interactive)
6790 (abbrev-mode (if abbrev-mode 0 1))
5c8b7eaf 6791 (message "Perl control structure will %sbe auto-inserted now."
f83d2997
KH
6792 (if abbrev-mode "" "not ")))
6793
6794
6795(defun cperl-toggle-electric ()
6796 "Toggle the state of parentheses doubling in CPerl mode."
6797 (interactive)
6798 (setq cperl-electric-parens (if (cperl-val 'cperl-electric-parens) 'null t))
5c8b7eaf 6799 (message "Parentheses will %sbe auto-doubled now."
f83d2997
KH
6800 (if (cperl-val 'cperl-electric-parens) "" "not ")))
6801
db133cb6 6802(defun cperl-toggle-autohelp ()
f739b53b
SM
6803 "Toggle the state of Auto-Help on Perl constructs (put in the message area).
6804Delay of auto-help controlled by `cperl-lazy-help-time'."
db133cb6
RS
6805 (interactive)
6806 (if (fboundp 'run-with-idle-timer)
6807 (progn
6808 (if cperl-lazy-installed
f739b53b 6809 (cperl-lazy-unstall)
db133cb6 6810 (cperl-lazy-install))
5c8b7eaf 6811 (message "Perl help messages will %sbe automatically shown now."
db133cb6
RS
6812 (if cperl-lazy-installed "" "not ")))
6813 (message "Cannot automatically show Perl help messages - run-with-idle-timer missing.")))
6814
6815(defun cperl-toggle-construct-fix ()
6816 "Toggle whether `indent-region'/`indent-sexp' fix whitespace too."
6817 (interactive)
5c8b7eaf 6818 (setq cperl-indent-region-fix-constructs
5bd52f0e
RS
6819 (if cperl-indent-region-fix-constructs
6820 nil
6821 1))
5c8b7eaf 6822 (message "indent-region/indent-sexp will %sbe automatically fix whitespace."
db133cb6
RS
6823 (if cperl-indent-region-fix-constructs "" "not ")))
6824
4ab89e7b
SM
6825(defun cperl-toggle-set-debug-unwind (arg &optional backtrace)
6826 "Toggle (or, with numeric argument, set) debugging state of syntaxification.
6827Nonpositive numeric argument disables debugging messages. The message
6828summarizes which regions it was decided to rescan for syntactic constructs.
6829
6830The message looks like this:
6831
6832 Syxify req=123..138 actual=101..146 done-to: 112=>146 statepos: 73=>117
6833
6834Numbers are character positions in the buffer. REQ provides the range to
6835rescan requested by `font-lock'. ACTUAL is the range actually resyntaxified;
6836for correct operation it should start and end outside any special syntactic
6837construct. DONE-TO and STATEPOS indicate changes to internal caches maintained
6838by CPerl."
6839 (interactive "P")
6840 (or arg
cb5bf6ba 6841 (setq arg (if (eq cperl-syntaxify-by-font-lock
4ab89e7b
SM
6842 (if backtrace 'backtrace 'message)) 0 1)))
6843 (setq arg (if (> arg 0) (if backtrace 'backtrace 'message) t))
6844 (setq cperl-syntaxify-by-font-lock arg)
6845 (message "Debugging messages of syntax unwind %sabled."
6846 (if (eq arg t) "dis" "en")))
6847
f83d2997
KH
6848;;;; Tags file creation.
6849
6850(defvar cperl-tmp-buffer " *cperl-tmp*")
6851
6852(defun cperl-setup-tmp-buf ()
6853 (set-buffer (get-buffer-create cperl-tmp-buffer))
6854 (set-syntax-table cperl-mode-syntax-table)
6855 (buffer-disable-undo)
6856 (auto-fill-mode 0)
6857 (if cperl-use-syntax-table-text-property-for-tags
6858 (progn
029cb4d5 6859 (make-local-variable 'parse-sexp-lookup-properties)
f83d2997
KH
6860 ;; Do not introduce variable if not needed, we check it!
6861 (set 'parse-sexp-lookup-properties t))))
6862
47e83968
GM
6863;; Copied from imenu-example--name-and-position.
6864(defvar imenu-use-markers)
6865
6866(defun cperl-imenu-name-and-position ()
6867 "Return the current/previous sexp and its (beginning) location.
6868Does not move point."
6869 (save-excursion
6870 (forward-sexp -1)
6871 (let ((beg (if imenu-use-markers (point-marker) (point)))
6872 (end (progn (forward-sexp) (point))))
6873 (cons (buffer-substring beg end)
6874 beg))))
6875
f83d2997 6876(defun cperl-xsub-scan ()
f83d2997 6877 (require 'imenu)
5c8b7eaf 6878 (let ((index-alist '())
f83d2997
KH
6879 (prev-pos 0) index index1 name package prefix)
6880 (goto-char (point-min))
f83d2997
KH
6881 ;; Search for the function
6882 (progn ;;save-match-data
6883 (while (re-search-forward
6884 "^\\([ \t]*MODULE\\>[^\n]*\\<PACKAGE[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9:]*\\)\\>\\|\\([a-zA-Z_][a-zA-Z_0-9]*\\)(\\|[ \t]*BOOT:\\)"
6885 nil t)
f83d2997 6886 (cond
83261a2f 6887 ((match-beginning 2) ; SECTION
f83d2997
KH
6888 (setq package (buffer-substring (match-beginning 2) (match-end 2)))
6889 (goto-char (match-beginning 0))
6890 (skip-chars-forward " \t")
6891 (forward-char 1)
6892 (if (looking-at "[^\n]*\\<PREFIX[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9]*\\)\\>")
6893 (setq prefix (buffer-substring (match-beginning 1) (match-end 1)))
6894 (setq prefix nil)))
6895 ((not package) nil) ; C language section
6896 ((match-beginning 3) ; XSUB
6897 (goto-char (1+ (match-beginning 3)))
47e83968 6898 (setq index (cperl-imenu-name-and-position))
f83d2997
KH
6899 (setq name (buffer-substring (match-beginning 3) (match-end 3)))
6900 (if (and prefix (string-match (concat "^" prefix) name))
6901 (setq name (substring name (length prefix))))
6902 (cond ((string-match "::" name) nil)
6903 (t
6904 (setq index1 (cons (concat package "::" name) (cdr index)))
6905 (push index1 index-alist)))
6906 (setcar index name)
6907 (push index index-alist))
6908 (t ; BOOT: section
6909 ;; (beginning-of-line)
47e83968 6910 (setq index (cperl-imenu-name-and-position))
f83d2997
KH
6911 (setcar index (concat package "::BOOT:"))
6912 (push index index-alist)))))
f83d2997
KH
6913 index-alist))
6914
6c389151
SM
6915(defvar cperl-unreadable-ok nil)
6916
6917(defun cperl-find-tags (ifile xs topdir)
83261a2f
SM
6918 (let ((b (get-buffer cperl-tmp-buffer)) ind lst elt pos ret rel
6919 (cperl-pod-here-fontify nil) f file)
f83d2997
KH
6920 (save-excursion
6921 (if b (set-buffer b)
83261a2f 6922 (cperl-setup-tmp-buf))
f83d2997 6923 (erase-buffer)
6c389151
SM
6924 (condition-case err
6925 (setq file (car (insert-file-contents ifile)))
6926 (error (if cperl-unreadable-ok nil
6927 (if (y-or-n-p
6928 (format "File %s unreadable. Continue? " ifile))
6929 (setq cperl-unreadable-ok t)
6930 (error "Aborting: unreadable file %s" ifile)))))
a1506d29 6931 (if (not file)
6c389151 6932 (message "Unreadable file %s" ifile)
83261a2f
SM
6933 (message "Scanning file %s ..." file)
6934 (if (and cperl-use-syntax-table-text-property-for-tags
6935 (not xs))
6936 (condition-case err ; after __END__ may have garbage
6937 (cperl-find-pods-heres nil nil noninteractive)
6938 (error (message "While scanning for syntax: %s" err))))
6939 (if xs
6940 (setq lst (cperl-xsub-scan))
6941 (setq ind (cperl-imenu--create-perl-index))
6942 (setq lst (cdr (assoc "+Unsorted List+..." ind))))
6943 (setq lst
6944 (mapcar
6945 (function
6946 (lambda (elt)
6947 (cond ((string-match "^[_a-zA-Z]" (car elt))
6948 (goto-char (cdr elt))
6949 (beginning-of-line) ; pos should be of the start of the line
6950 (list (car elt)
6951 (point)
6952 (1+ (count-lines 1 (point))) ; 1+ since at beg-o-l
6953 (buffer-substring (progn
6954 (goto-char (cdr elt))
6955 ;; After name now...
6956 (or (eolp) (forward-char 1))
6957 (point))
6958 (progn
6959 (beginning-of-line)
6960 (point))))))))
6961 lst))
6962 (erase-buffer)
6963 (while lst
6964 (setq elt (car lst) lst (cdr lst))
6965 (if elt
6966 (progn
6967 (insert (elt elt 3)
6968 127
6969 (if (string-match "^package " (car elt))
6970 (substring (car elt) 8)
6971 (car elt) )
6972 1
6973 (number-to-string (elt elt 2)) ; Line
6974 ","
6975 (number-to-string (1- (elt elt 1))) ; Char pos 0-based
6976 "\n")
6977 (if (and (string-match "^[_a-zA-Z]+::" (car elt))
6978 (string-match "^sub[ \t]+\\([_a-zA-Z]+\\)[^:_a-zA-Z]"
6979 (elt elt 3)))
6980 ;; Need to insert the name without package as well
15ca5699 6981 (setq lst (cons (cons (substring (elt elt 3)
83261a2f
SM
6982 (match-beginning 1)
6983 (match-end 1))
6984 (cdr elt))
6985 lst))))))
6986 (setq pos (point))
6987 (goto-char 1)
6988 (setq rel file)
6989 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
6990 (set-text-properties 0 (length rel) nil rel)
6991 (and (equal topdir (substring rel 0 (length topdir)))
6992 (setq rel (substring file (length topdir))))
6993 (insert "\f\n" rel "," (number-to-string (1- pos)) "\n")
6994 (setq ret (buffer-substring 1 (point-max)))
6995 (erase-buffer)
6996 (or noninteractive
6997 (message "Scanning file %s finished" file))
6998 ret))))
f83d2997
KH
6999
7000(defun cperl-add-tags-recurse-noxs ()
4ab89e7b 7001 "Add to TAGS data for \"pure\" Perl files in the current directory and kids.
f83d2997
KH
7002Use as
7003 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
4ab89e7b 7004 -f cperl-add-tags-recurse-noxs
f83d2997
KH
7005"
7006 (cperl-write-tags nil nil t t nil t))
7007
4ab89e7b
SM
7008(defun cperl-add-tags-recurse-noxs-fullpath ()
7009 "Add to TAGS data for \"pure\" Perl in the current directory and kids.
7010Writes down fullpath, so TAGS is relocatable (but if the build directory
7011is relocated, the file TAGS inside it breaks). Use as
7012 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
7013 -f cperl-add-tags-recurse-noxs-fullpath
7014"
7015 (cperl-write-tags nil nil t t nil t ""))
7016
f83d2997
KH
7017(defun cperl-add-tags-recurse ()
7018 "Add to TAGS file data for Perl files in the current directory and kids.
7019Use as
7020 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
5c8b7eaf 7021 -f cperl-add-tags-recurse
f83d2997
KH
7022"
7023 (cperl-write-tags nil nil t t))
7024
7025(defun cperl-write-tags (&optional file erase recurse dir inbuffer noxs topdir)
7026 ;; If INBUFFER, do not select buffer, and do not save
7027 ;; If ERASE is `ignore', do not erase, and do not try to delete old info.
7028 (require 'etags)
7029 (if file nil
7030 (setq file (if dir default-directory (buffer-file-name)))
7031 (if (and (not dir) (buffer-modified-p)) (error "Save buffer first!")))
7032 (or topdir
7033 (setq topdir default-directory))
7034 (let ((tags-file-name "TAGS")
72bc50c0 7035 (case-fold-search (and (featurep 'xemacs) (eq system-type 'emx)))
6c389151 7036 xs rel tm)
f83d2997
KH
7037 (save-excursion
7038 (cond (inbuffer nil) ; Already there
7039 ((file-exists-p tags-file-name)
6546555e 7040 (if (featurep 'xemacs)
5bd52f0e 7041 (visit-tags-table-buffer)
83261a2f 7042 (visit-tags-table-buffer tags-file-name)))
f83d2997
KH
7043 (t (set-buffer (find-file-noselect tags-file-name))))
7044 (cond
7045 (dir
7046 (cond ((eq erase 'ignore))
7047 (erase
7048 (erase-buffer)
7049 (setq erase 'ignore)))
a1506d29 7050 (let ((files
6c389151 7051 (condition-case err
a1506d29 7052 (directory-files file t
6c389151
SM
7053 (if recurse nil cperl-scan-files-regexp)
7054 t)
7055 (error
7056 (if cperl-unreadable-ok nil
7057 (if (y-or-n-p
7058 (format "Directory %s unreadable. Continue? " file))
a1506d29 7059 (setq cperl-unreadable-ok t
83261a2f 7060 tm nil) ; Return empty list
6c389151 7061 (error "Aborting: unreadable directory %s" file)))))))
dba01120
GM
7062 (mapc (function
7063 (lambda (file)
7064 (cond
7065 ((string-match cperl-noscan-files-regexp file)
7066 nil)
7067 ((not (file-directory-p file))
7068 (if (string-match cperl-scan-files-regexp file)
7069 (cperl-write-tags file erase recurse nil t noxs topdir)))
7070 ((not recurse) nil)
7071 (t (cperl-write-tags file erase recurse t t noxs topdir)))))
7072 files)))
f83d2997
KH
7073 (t
7074 (setq xs (string-match "\\.xs$" file))
7075 (if (not (and xs noxs))
7076 (progn
7077 (cond ((eq erase 'ignore) (goto-char (point-max)))
83261a2f
SM
7078 (erase (erase-buffer))
7079 (t
7080 (goto-char 1)
7081 (setq rel file)
7082 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
7083 (set-text-properties 0 (length rel) nil rel)
7084 (and (equal topdir (substring rel 0 (length topdir)))
7085 (setq rel (substring file (length topdir))))
7086 (if (search-forward (concat "\f\n" rel ",") nil t)
7087 (progn
7088 (search-backward "\f\n")
7089 (delete-region (point)
7090 (save-excursion
7091 (forward-char 1)
7092 (if (search-forward "\f\n"
7093 nil 'toend)
7094 (- (point) 2)
7095 (point-max)))))
7096 (goto-char (point-max)))))
f83d2997 7097 (insert (cperl-find-tags file xs topdir))))))
83261a2f
SM
7098 (if inbuffer nil ; Delegate to the caller
7099 (save-buffer 0) ; No backup
f83d2997
KH
7100 (if (fboundp 'initialize-new-tags-table) ; Do we need something special in XEmacs?
7101 (initialize-new-tags-table))))))
7102
7103(defvar cperl-tags-hier-regexp-list
5c8b7eaf 7104 (concat
f83d2997
KH
7105 "^\\("
7106 "\\(package\\)\\>"
7107 "\\|"
7108 "sub\\>[^\n]+::"
7109 "\\|"
7110 "[a-zA-Z_][a-zA-Z_0-9:]*(\C-?[^\n]+::" ; XSUB?
7111 "\\|"
7112 "[ \t]*BOOT:\C-?[^\n]+::" ; BOOT section
7113 "\\)"))
7114
7115(defvar cperl-hierarchy '(() ())
f94a632a 7116 "Global hierarchy of classes.")
f83d2997
KH
7117
7118(defun cperl-tags-hier-fill ()
7119 ;; Suppose we are in a tag table cooked by cperl.
7120 (goto-char 1)
7121 (let (type pack name pos line chunk ord cons1 file str info fileind)
7122 (while (re-search-forward cperl-tags-hier-regexp-list nil t)
5c8b7eaf 7123 (setq pos (match-beginning 0)
f83d2997
KH
7124 pack (match-beginning 2))
7125 (beginning-of-line)
7126 (if (looking-at (concat
7127 "\\([^\n]+\\)"
7128 "\C-?"
7129 "\\([^\n]+\\)"
7130 "\C-a"
7131 "\\([0-9]+\\)"
7132 ","
7133 "\\([0-9]+\\)"))
7134 (progn
7135 (setq ;;str (buffer-substring (match-beginning 1) (match-end 1))
7136 name (buffer-substring (match-beginning 2) (match-end 2))
7137 ;;pos (buffer-substring (match-beginning 3) (match-end 3))
5bd52f0e 7138 line (buffer-substring (match-beginning 3) (match-end 3))
f83d2997 7139 ord (if pack 1 0)
f83d2997 7140 file (file-of-tag)
5bd52f0e
RS
7141 fileind (format "%s:%s" file line)
7142 ;; Moves to beginning of the next line:
7143 info (cperl-etags-snarf-tag file line))
f83d2997
KH
7144 ;; Move back
7145 (forward-char -1)
7146 ;; Make new member of hierarchy name ==> file ==> pos if needed
7147 (if (setq cons1 (assoc name (nth ord cperl-hierarchy)))
7148 ;; Name known
7149 (setcdr cons1 (cons (cons fileind (vector file info))
7150 (cdr cons1)))
7151 ;; First occurrence of the name, start alist
7152 (setq cons1 (cons name (list (cons fileind (vector file info)))))
5c8b7eaf 7153 (if pack
f83d2997
KH
7154 (setcar (cdr cperl-hierarchy)
7155 (cons cons1 (nth 1 cperl-hierarchy)))
7156 (setcar cperl-hierarchy
7157 (cons cons1 (car cperl-hierarchy)))))))
7158 (end-of-line))))
7159
e8a11b22 7160(declare-function x-popup-menu "menu.c" (position menu))
f2d9c15f 7161
f83d2997
KH
7162(defun cperl-tags-hier-init (&optional update)
7163 "Show hierarchical menu of classes and methods.
7164Finds info about classes by a scan of loaded TAGS files.
7165Supposes that the TAGS files contain fully qualified function names.
7166One may build such TAGS files from CPerl mode menu."
7167 (interactive)
7168 (require 'etags)
7169 (require 'imenu)
7170 (if (or update (null (nth 2 cperl-hierarchy)))
83261a2f
SM
7171 (let ((remover (function (lambda (elt) ; (name (file1...) (file2..))
7172 (or (nthcdr 2 elt)
7173 ;; Only in one file
7174 (setcdr elt (cdr (nth 1 elt)))))))
7175 pack name cons1 to l1 l2 l3 l4 b)
f83d2997
KH
7176 ;; (setq cperl-hierarchy '(() () ())) ; Would write into '() later!
7177 (setq cperl-hierarchy (list l1 l2 l3))
6546555e 7178 (if (featurep 'xemacs) ; Not checked
5bd52f0e
RS
7179 (progn
7180 (or tags-file-name
7181 ;; Does this work in XEmacs?
8c777c8d
CY
7182 (call-interactively 'visit-tags-table))
7183 (message "Updating list of classes...")
5bd52f0e
RS
7184 (set-buffer (get-file-buffer tags-file-name))
7185 (cperl-tags-hier-fill))
7186 (or tags-table-list
7187 (call-interactively 'visit-tags-table))
dba01120 7188 (mapc
4ab89e7b
SM
7189 (function
7190 (lambda (tagsfile)
5bd52f0e 7191 (message "Updating list of classes... %s" tagsfile)
8c777c8d
CY
7192 (set-buffer (get-file-buffer tagsfile))
7193 (cperl-tags-hier-fill)))
dba01120 7194 tags-table-list)
5bd52f0e 7195 (message "Updating list of classes... postprocessing..."))
dba01120
GM
7196 (mapc remover (car cperl-hierarchy))
7197 (mapc remover (nth 1 cperl-hierarchy))
f83d2997
KH
7198 (setq to (list nil (cons "Packages: " (nth 1 cperl-hierarchy))
7199 (cons "Methods: " (car cperl-hierarchy))))
7200 (cperl-tags-treeify to 1)
7201 (setcar (nthcdr 2 cperl-hierarchy)
7202 (cperl-menu-to-keymap (cons '("+++UPDATE+++" . -999) (cdr to))))
7203 (message "Updating list of classes: done, requesting display...")
7204 ;;(cperl-imenu-addback (nth 2 cperl-hierarchy))
7205 ))
7206 (or (nth 2 cperl-hierarchy)
7207 (error "No items found"))
7208 (setq update
7209;;; (imenu-choose-buffer-index "Packages: " (nth 2 cperl-hierarchy))
83261a2f
SM
7210 (if (if (fboundp 'display-popup-menus-p)
7211 (let ((f 'display-popup-menus-p))
7212 (funcall f))
7213 window-system)
f83d2997
KH
7214 (x-popup-menu t (nth 2 cperl-hierarchy))
7215 (require 'tmm)
7216 (tmm-prompt (nth 2 cperl-hierarchy))))
7217 (if (and update (listp update))
7218 (progn (while (cdr update) (setq update (cdr update)))
7219 (setq update (car update)))) ; Get the last from the list
5c8b7eaf 7220 (if (vectorp update)
f83d2997
KH
7221 (progn
7222 (find-file (elt update 0))
5bd52f0e 7223 (cperl-etags-goto-tag-location (elt update 1))))
f83d2997
KH
7224 (if (eq update -999) (cperl-tags-hier-init t)))
7225
7226(defun cperl-tags-treeify (to level)
7227 ;; cadr of `to' is read-write. On start it is a cons
5c8b7eaf 7228 (let* ((regexp (concat "^\\(" (mapconcat
f83d2997
KH
7229 'identity
7230 (make-list level "[_a-zA-Z0-9]+")
7231 "::")
7232 "\\)\\(::\\)?"))
7233 (packages (cdr (nth 1 to)))
7234 (methods (cdr (nth 2 to)))
7235 l1 head tail cons1 cons2 ord writeto packs recurse
7236 root-packages root-functions ms many_ms same_name ps
7237 (move-deeper
5c8b7eaf 7238 (function
f83d2997
KH
7239 (lambda (elt)
7240 (cond ((and (string-match regexp (car elt))
7241 (or (eq ord 1) (match-end 2)))
7242 (setq head (substring (car elt) 0 (match-end 1))
5c8b7eaf 7243 tail (if (match-end 2) (substring (car elt)
f83d2997
KH
7244 (match-end 2)))
7245 recurse t)
7246 (if (setq cons1 (assoc head writeto)) nil
7247 ;; Need to init new head
7248 (setcdr writeto (cons (list head (list "Packages: ")
7249 (list "Methods: "))
7250 (cdr writeto)))
7251 (setq cons1 (nth 1 writeto)))
7252 (setq cons2 (nth ord cons1)) ; Either packs or meths
7253 (setcdr cons2 (cons elt (cdr cons2))))
7254 ((eq ord 2)
7255 (setq root-functions (cons elt root-functions)))
7256 (t
7257 (setq root-packages (cons elt root-packages))))))))
7258 (setcdr to l1) ; Init to dynamic space
7259 (setq writeto to)
7260 (setq ord 1)
dba01120 7261 (mapc move-deeper packages)
f83d2997 7262 (setq ord 2)
dba01120 7263 (mapc move-deeper methods)
f83d2997 7264 (if recurse
dba01120 7265 (mapc (function (lambda (elt)
f83d2997 7266 (cperl-tags-treeify elt (1+ level))))
dba01120 7267 (cdr to)))
f83d2997 7268 ;;Now clean up leaders with one child only
dba01120
GM
7269 (mapc (function (lambda (elt)
7270 (if (not (and (listp (cdr elt))
7271 (eq (length elt) 2))) nil
7272 (setcar elt (car (nth 1 elt)))
7273 (setcdr elt (cdr (nth 1 elt))))))
7274 (cdr to))
f83d2997
KH
7275 ;; Sort the roots of subtrees
7276 (if (default-value 'imenu-sort-function)
7277 (setcdr to
7278 (sort (cdr to) (default-value 'imenu-sort-function))))
7279 ;; Now add back functions removed from display
dba01120
GM
7280 (mapc (function (lambda (elt)
7281 (setcdr to (cons elt (cdr to)))))
7282 (if (default-value 'imenu-sort-function)
7283 (nreverse
7284 (sort root-functions (default-value 'imenu-sort-function)))
7285 root-functions))
f83d2997 7286 ;; Now add back packages removed from display
dba01120
GM
7287 (mapc (function (lambda (elt)
7288 (setcdr to (cons (cons (concat "package " (car elt))
7289 (cdr elt))
7290 (cdr to)))))
7291 (if (default-value 'imenu-sort-function)
7292 (nreverse
7293 (sort root-packages (default-value 'imenu-sort-function)))
7294 root-packages))))
f83d2997
KH
7295
7296;;;(x-popup-menu t
5c8b7eaf 7297;;; '(keymap "Name1"
f83d2997 7298;;; ("Ret1" "aa")
5c8b7eaf
SS
7299;;; ("Head1" "ab"
7300;;; keymap "Name2"
f83d2997
KH
7301;;; ("Tail1" "x") ("Tail2" "y"))))
7302
7303(defun cperl-list-fold (list name limit)
7304 (let (list1 list2 elt1 (num 0))
7305 (if (<= (length list) limit) list
7306 (setq list1 nil list2 nil)
7307 (while list
5c8b7eaf 7308 (setq num (1+ num)
f83d2997
KH
7309 elt1 (car list)
7310 list (cdr list))
7311 (if (<= num imenu-max-items)
7312 (setq list2 (cons elt1 list2))
7313 (setq list1 (cons (cons name
7314 (nreverse list2))
7315 list1)
7316 list2 (list elt1)
7317 num 1)))
7318 (nreverse (cons (cons name
7319 (nreverse list2))
7320 list1)))))
7321
7322(defun cperl-menu-to-keymap (menu &optional name)
7323 (let (list)
5c8b7eaf
SS
7324 (cons 'keymap
7325 (mapcar
7326 (function
f83d2997
KH
7327 (lambda (elt)
7328 (cond ((listp (cdr elt))
7329 (setq list (cperl-list-fold
7330 (cdr elt) (car elt) imenu-max-items))
7331 (cons nil
7332 (cons (car elt)
7333 (cperl-menu-to-keymap list))))
7334 (t
7335 (list (cdr elt) (car elt) t))))) ; t is needed in 19.34
7336 (cperl-list-fold menu "Root" imenu-max-items)))))
7337
7338\f
7339(defvar cperl-bad-style-regexp
7340 (mapconcat 'identity
83261a2f 7341 '("[^-\n\t <>=+!.&|(*/'`\"#^][-=+<>!|&^]" ; char sign
15ca5699 7342 "[-<>=+^&|]+[^- \t\n=+<>~]") ; sign+ char
83261a2f 7343 "\\|")
f83d2997
KH
7344 "Finds places such that insertion of a whitespace may help a lot.")
7345
5c8b7eaf 7346(defvar cperl-not-bad-style-regexp
15ca5699 7347 (mapconcat
83261a2f 7348 'identity
f83d2997
KH
7349 '("[^-\t <>=+]\\(--\\|\\+\\+\\)" ; var-- var++
7350 "[a-zA-Z0-9_][|&][a-zA-Z0-9_$]" ; abc|def abc&def are often used.
7351 "&[(a-zA-Z0-9_$]" ; &subroutine &(var->field)
4ab89e7b 7352 "<\\$?\\sw+\\(\\.\\(\\sw\\|_\\)+\\)?>" ; <IN> <stdin.h>
5bd52f0e 7353 "-[a-zA-Z][ \t]+[_$\"'`a-zA-Z]" ; -f file, -t STDIN
f83d2997
KH
7354 "-[0-9]" ; -5
7355 "\\+\\+" ; ++var
7356 "--" ; --var
7357 ".->" ; a->b
7358 "->" ; a SPACE ->b
7359 "\\[-" ; a[-1]
5bd52f0e 7360 "\\\\[&$@*\\\\]" ; \&func
f83d2997 7361 "^=" ; =head
5bd52f0e
RS
7362 "\\$." ; $|
7363 "<<[a-zA-Z_'\"`]" ; <<FOO, <<'FOO'
f83d2997
KH
7364 "||"
7365 "&&"
7366 "[CBIXSLFZ]<\\(\\sw\\|\\s \\|\\s_\\|[\n]\\)*>" ; C<code like text>
83261a2f 7367 "-[a-zA-Z_0-9]+[ \t]*=>" ; -option => value
f83d2997
KH
7368 ;; Unaddressed trouble spots: = -abc, f(56, -abc) --- specialcased below
7369 ;;"[*/+-|&<.]+="
7370 )
7371 "\\|")
7372 "If matches at the start of match found by `my-bad-c-style-regexp',
7373insertion of a whitespace will not help.")
7374
7375(defvar found-bad)
7376
7377(defun cperl-find-bad-style ()
7378 "Find places in the buffer where insertion of a whitespace may help.
7379Prompts user for insertion of spaces.
7380Currently it is tuned to C and Perl syntax."
7381 (interactive)
7382 (let (found-bad (p (point)))
7383 (setq last-nonmenu-event 13) ; To disable popup
4ab89e7b 7384 (goto-char (point-min))
f83d2997 7385 (map-y-or-n-p "Insert space here? "
83261a2f 7386 (lambda (arg) (insert " "))
f83d2997 7387 'cperl-next-bad-style
5c8b7eaf 7388 '("location" "locations" "insert a space into")
f83d2997
KH
7389 '((?\C-r (lambda (arg)
7390 (let ((buffer-quit-function
7391 'exit-recursive-edit))
7392 (message "Exit with Esc Esc")
7393 (recursive-edit)
7394 t)) ; Consider acted upon
5c8b7eaf 7395 "edit, exit with Esc Esc")
f83d2997
KH
7396 (?e (lambda (arg)
7397 (let ((buffer-quit-function
7398 'exit-recursive-edit))
7399 (message "Exit with Esc Esc")
7400 (recursive-edit)
7401 t)) ; Consider acted upon
7402 "edit, exit with Esc Esc"))
7403 t)
7404 (if found-bad (goto-char found-bad)
7405 (goto-char p)
7406 (message "No appropriate place found"))))
7407
7408(defun cperl-next-bad-style ()
7409 (let (p (not-found t) (point (point)) found)
7410 (while (and not-found
7411 (re-search-forward cperl-bad-style-regexp nil 'to-end))
7412 (setq p (point))
7413 (goto-char (match-beginning 0))
7414 (if (or
7415 (looking-at cperl-not-bad-style-regexp)
7416 ;; Check for a < -b and friends
7417 (and (eq (following-char) ?\-)
7418 (save-excursion
7419 (skip-chars-backward " \t\n")
07cb2aa3 7420 (memq (preceding-char) '(?\= ?\> ?\< ?\, ?\( ?\[ ?\{))))
f83d2997
KH
7421 ;; Now check for syntax type
7422 (save-match-data
7423 (setq found (point))
7424 (beginning-of-defun)
7425 (let ((pps (parse-partial-sexp (point) found)))
7426 (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))
7427 (goto-char (match-end 0))
7428 (goto-char (1- p))
7429 (setq not-found nil
7430 found-bad found)))
7431 (not not-found)))
7432
f1d851ae 7433\f
f83d2997 7434;;; Getting help
5c8b7eaf 7435(defvar cperl-have-help-regexp
f83d2997
KH
7436 ;;(concat "\\("
7437 (mapconcat
7438 'identity
83261a2f 7439 '("[$@%*&][0-9a-zA-Z_:]+\\([ \t]*[[{]\\)?" ; Usual variable
f83d2997
KH
7440 "[$@]\\^[a-zA-Z]" ; Special variable
7441 "[$@][^ \n\t]" ; Special variable
7442 "-[a-zA-Z]" ; File test
7443 "\\\\[a-zA-Z0]" ; Special chars
83261a2f 7444 "^=[a-z][a-zA-Z0-9_]*" ; POD sections
f83d2997
KH
7445 "[-!&*+,-./<=>?\\\\^|~]+" ; Operator
7446 "[a-zA-Z_0-9:]+" ; symbol or number
7447 "x="
83261a2f 7448 "#!")
f83d2997 7449 ;;"\\)\\|\\("
83261a2f
SM
7450 "\\|")
7451 ;;"\\)"
7452 ;;)
f83d2997
KH
7453 "Matches places in the buffer we can find help for.")
7454
7455(defvar cperl-message-on-help-error t)
7456(defvar cperl-help-from-timer nil)
7457
7458(defun cperl-word-at-point-hard ()
7459 ;; Does not save-excursion
7460 ;; Get to the something meaningful
7461 (or (eobp) (eolp) (forward-char 1))
5c8b7eaf 7462 (re-search-backward "[-a-zA-Z0-9_:!&*+,-./<=>?\\\\^|~$%@]"
e180ab9f 7463 (point-at-bol)
f83d2997
KH
7464 'to-beg)
7465 ;; (cond
7466 ;; ((or (eobp) (looking-at "[][ \t\n{}();,]")) ; Not at a symbol
7467 ;; (skip-chars-backward " \n\t\r({[]});,")
7468 ;; (or (bobp) (backward-char 1))))
7469 ;; Try to backtrace
7470 (cond
7471 ((looking-at "[a-zA-Z0-9_:]") ; symbol
7472 (skip-chars-backward "a-zA-Z0-9_:")
5c8b7eaf 7473 (cond
f83d2997
KH
7474 ((and (eq (preceding-char) ?^) ; $^I
7475 (eq (char-after (- (point) 2)) ?\$))
7476 (forward-char -2))
7477 ((memq (preceding-char) (append "*$@%&\\" nil)) ; *glob
7478 (forward-char -1))
7479 ((and (eq (preceding-char) ?\=)
7480 (eq (current-column) 1))
7481 (forward-char -1))) ; =head1
7482 (if (and (eq (preceding-char) ?\<)
7483 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <FH>
7484 (forward-char -1)))
7485 ((and (looking-at "=") (eq (preceding-char) ?x)) ; x=
7486 (forward-char -1))
7487 ((and (looking-at "\\^") (eq (preceding-char) ?\$)) ; $^I
7488 (forward-char -1))
7489 ((looking-at "[-!&*+,-./<=>?\\\\^|~]")
7490 (skip-chars-backward "-!&*+,-./<=>?\\\\^|~")
7491 (cond
7492 ((and (eq (preceding-char) ?\$)
7493 (not (eq (char-after (- (point) 2)) ?\$))) ; $-
7494 (forward-char -1))
7495 ((and (eq (following-char) ?\>)
7496 (string-match "[a-zA-Z0-9_]" (char-to-string (preceding-char)))
7497 (save-excursion
7498 (forward-sexp -1)
7499 (and (eq (preceding-char) ?\<)
7500 (looking-at "\\$?[a-zA-Z0-9_:]+>")))) ; <FH>
7501 (search-backward "<"))))
7502 ((and (eq (following-char) ?\$)
7503 (eq (preceding-char) ?\<)
7504 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <$fh>
7505 (forward-char -1)))
7506 (if (looking-at cperl-have-help-regexp)
7507 (buffer-substring (match-beginning 0) (match-end 0))))
7508
7509(defun cperl-get-help ()
7510 "Get one-line docs on the symbol at the point.
7511The data for these docs is a little bit obsolete and may be in fact longer
7512than a line. Your contribution to update/shorten it is appreciated."
7513 (interactive)
7514 (save-match-data ; May be called "inside" query-replace
7515 (save-excursion
7516 (let ((word (cperl-word-at-point-hard)))
7517 (if word
7518 (if (and cperl-help-from-timer ; Bail out if not in mainland
7519 (not (string-match "^#!\\|\\\\\\|^=" word)) ; Show help even in comments/strings.
7520 (or (memq (get-text-property (point) 'face)
7521 '(font-lock-comment-face font-lock-string-face))
7522 (memq (get-text-property (point) 'syntax-type)
7523 '(pod here-doc format))))
7524 nil
7525 (cperl-describe-perl-symbol word))
7526 (if cperl-message-on-help-error
5c8b7eaf 7527 (message "Nothing found for %s..."
f83d2997
KH
7528 (buffer-substring (point) (min (+ 5 (point)) (point-max))))))))))
7529
7530;;; Stolen from perl-descr.el by Johan Vromans:
7531
7532(defvar cperl-doc-buffer " *perl-doc*"
7533 "Where the documentation can be found.")
7534
7535(defun cperl-describe-perl-symbol (val)
7536 "Display the documentation of symbol at point, a Perl operator."
7537 (let ((enable-recursive-minibuffers t)
7538 args-file regexp)
7539 (cond
83261a2f
SM
7540 ((string-match "^[&*][a-zA-Z_]" val)
7541 (setq val (concat (substring val 0 1) "NAME")))
7542 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*\\[" val)
7543 (setq val (concat "@" (substring val 1 (match-end 1)))))
7544 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*{" val)
7545 (setq val (concat "%" (substring val 1 (match-end 1)))))
7546 ((and (string= val "x") (string-match "^x=" val))
7547 (setq val "x="))
7548 ((string-match "^\\$[\C-a-\C-z]" val)
7549 (setq val (concat "$^" (char-to-string (+ ?A -1 (aref val 1))))))
7550 ((string-match "^CORE::" val)
7551 (setq val "CORE::"))
7552 ((string-match "^SUPER::" val)
7553 (setq val "SUPER::"))
7554 ((and (string= "<" val) (string-match "^<\\$?[a-zA-Z0-9_:]+>" val))
7555 (setq val "<NAME>")))
5c8b7eaf 7556 (setq regexp (concat "^"
f83d2997 7557 "\\([^a-zA-Z0-9_:]+[ \t]+\\)?"
5c8b7eaf 7558 (regexp-quote val)
f83d2997
KH
7559 "\\([ \t([/]\\|$\\)"))
7560
7561 ;; get the buffer with the documentation text
7562 (cperl-switch-to-doc-buffer)
7563
7564 ;; lookup in the doc
7565 (goto-char (point-min))
7566 (let ((case-fold-search nil))
5c8b7eaf 7567 (list
f83d2997
KH
7568 (if (re-search-forward regexp (point-max) t)
7569 (save-excursion
7570 (beginning-of-line 1)
7571 (let ((lnstart (point)))
7572 (end-of-line)
7573 (message "%s" (buffer-substring lnstart (point)))))
7574 (if cperl-message-on-help-error
7575 (message "No definition for %s" val)))))))
7576
83261a2f 7577(defvar cperl-short-docs 'please-ignore-this-line
f83d2997
KH
7578 ;; Perl4 version was written by Johan Vromans (jvromans@squirrel.nl)
7579 "# based on '@(#)@ perl-descr.el 1.9 - describe-perl-symbol' [Perl 5]
f739b53b 7580... Range (list context); flip/flop [no flop when flip] (scalar context).
5c8b7eaf 7581! ... Logical negation.
f83d2997
KH
7582... != ... Numeric inequality.
7583... !~ ... Search pattern, substitution, or translation (negated).
7584$! In numeric context: errno. In a string context: error string.
7585$\" The separator which joins elements of arrays interpolated in strings.
f739b53b 7586$# The output format for printed numbers. Default is %.15g or close.
f83d2997
KH
7587$$ Process number of this script. Changes in the fork()ed child process.
7588$% The current page number of the currently selected output channel.
7589
7590 The following variables are always local to the current block:
7591
7592$1 Match of the 1st set of parentheses in the last match (auto-local).
7593$2 Match of the 2nd set of parentheses in the last match (auto-local).
7594$3 Match of the 3rd set of parentheses in the last match (auto-local).
7595$4 Match of the 4th set of parentheses in the last match (auto-local).
7596$5 Match of the 5th set of parentheses in the last match (auto-local).
7597$6 Match of the 6th set of parentheses in the last match (auto-local).
7598$7 Match of the 7th set of parentheses in the last match (auto-local).
7599$8 Match of the 8th set of parentheses in the last match (auto-local).
7600$9 Match of the 9th set of parentheses in the last match (auto-local).
7601$& The string matched by the last pattern match (auto-local).
7602$' The string after what was matched by the last match (auto-local).
7603$` The string before what was matched by the last match (auto-local).
7604
7605$( The real gid of this process.
7606$) The effective gid of this process.
7607$* Deprecated: Set to 1 to do multiline matching within a string.
7608$+ The last bracket matched by the last search pattern.
7609$, The output field separator for the print operator.
7610$- The number of lines left on the page.
7611$. The current input line number of the last filehandle that was read.
7612$/ The input record separator, newline by default.
f739b53b 7613$0 Name of the file containing the current perl script (read/write).
f83d2997
KH
7614$: String may be broken after these characters to fill ^-lines in a format.
7615$; Subscript separator for multi-dim array emulation. Default \"\\034\".
7616$< The real uid of this process.
7617$= The page length of the current output channel. Default is 60 lines.
7618$> The effective uid of this process.
7619$? The status returned by the last ``, pipe close or `system'.
7620$@ The perl error message from the last eval or do @var{EXPR} command.
7621$ARGV The name of the current file used with <> .
7622$[ Deprecated: The index of the first element/char in an array/string.
7623$\\ The output record separator for the print operator.
7624$] The perl version string as displayed with perl -v.
7625$^ The name of the current top-of-page format.
7626$^A The current value of the write() accumulator for format() lines.
7627$^D The value of the perl debug (-D) flags.
7628$^E Information about the last system error other than that provided by $!.
7629$^F The highest system file descriptor, ordinarily 2.
7630$^H The current set of syntax checks enabled by `use strict'.
7631$^I The value of the in-place edit extension (perl -i option).
d7584f0f 7632$^L What formats output to perform a formfeed. Default is \\f.
5bd52f0e 7633$^M A buffer for emergency memory allocation when running out of memory.
f83d2997
KH
7634$^O The operating system name under which this copy of Perl was built.
7635$^P Internal debugging flag.
7636$^T The time the script was started. Used by -A/-M/-C file tests.
7637$^W True if warnings are requested (perl -w flag).
7638$^X The name under which perl was invoked (argv[0] in C-speech).
7639$_ The default input and pattern-searching space.
5c8b7eaf 7640$| Auto-flush after write/print on current output channel? Default 0.
f83d2997
KH
7641$~ The name of the current report format.
7642... % ... Modulo division.
7643... %= ... Modulo division assignment.
7644%ENV Contains the current environment.
7645%INC List of files that have been require-d or do-ne.
7646%SIG Used to set signal handlers for various signals.
7647... & ... Bitwise and.
7648... && ... Logical and.
7649... &&= ... Logical and assignment.
7650... &= ... Bitwise and assignment.
7651... * ... Multiplication.
7652... ** ... Exponentiation.
e4920bc9 7653*NAME Glob: all objects referred by NAME. *NAM1 = *NAM2 aliases NAM1 to NAM2.
f83d2997
KH
7654&NAME(arg0, ...) Subroutine call. Arguments go to @_.
7655... + ... Addition. +EXPR Makes EXPR into scalar context.
7656++ Auto-increment (magical on strings). ++EXPR EXPR++
7657... += ... Addition assignment.
7658, Comma operator.
7659... - ... Subtraction.
7660-- Auto-decrement (NOT magical on strings). --EXPR EXPR--
7661... -= ... Subtraction assignment.
7662-A Access time in days since script started.
7663-B File is a non-text (binary) file.
7664-C Inode change time in days since script started.
7665-M Age in days since script started.
7666-O File is owned by real uid.
7667-R File is readable by real uid.
7668-S File is a socket .
7669-T File is a text file.
7670-W File is writable by real uid.
7671-X File is executable by real uid.
7672-b File is a block special file.
7673-c File is a character special file.
7674-d File is a directory.
7675-e File exists .
7676-f File is a plain file.
7677-g File has setgid bit set.
7678-k File has sticky bit set.
7679-l File is a symbolic link.
7680-o File is owned by effective uid.
7681-p File is a named pipe (FIFO).
7682-r File is readable by effective uid.
7683-s File has non-zero size.
7684-t Tests if filehandle (STDIN by default) is opened to a tty.
7685-u File has setuid bit set.
7686-w File is writable by effective uid.
7687-x File is executable by effective uid.
7688-z File has zero size.
7689. Concatenate strings.
f739b53b 7690.. Range (list context); flip/flop (scalar context) operator.
f83d2997
KH
7691.= Concatenate assignment strings
7692... / ... Division. /PATTERN/ioxsmg Pattern match
7693... /= ... Division assignment.
7694/PATTERN/ioxsmg Pattern match.
f739b53b 7695... < ... Numeric less than. <pattern> Glob. See <NAME>, <> as well.
f83d2997
KH
7696<NAME> Reads line from filehandle NAME (a bareword or dollar-bareword).
7697<pattern> Glob (Unless pattern is bareword/dollar-bareword - see <NAME>).
7698<> Reads line from union of files in @ARGV (= command line) and STDIN.
7699... << ... Bitwise shift left. << start of HERE-DOCUMENT.
7700... <= ... Numeric less than or equal to.
7701... <=> ... Numeric compare.
7702... = ... Assignment.
7703... == ... Numeric equality.
7704... =~ ... Search pattern, substitution, or translation
7705... > ... Numeric greater than.
7706... >= ... Numeric greater than or equal to.
7707... >> ... Bitwise shift right.
7708... >>= ... Bitwise shift right assignment.
7709... ? ... : ... Condition=if-then-else operator. ?PAT? One-time pattern match.
7710?PATTERN? One-time pattern match.
7711@ARGV Command line arguments (not including the command name - see $0).
7712@INC List of places to look for perl scripts during do/include/use.
f739b53b 7713@_ Parameter array for subroutines; result of split() unless in list context.
d7584f0f 7714\\ Creates reference to what follows, like \\$var, or quotes non-\\w in strings.
f83d2997
KH
7715\\0 Octal char, e.g. \\033.
7716\\E Case modification terminator. See \\Q, \\L, and \\U.
d7584f0f
AS
7717\\L Lowercase until \\E . See also \\l, lc.
7718\\U Upcase until \\E . See also \\u, uc.
f83d2997
KH
7719\\Q Quote metacharacters until \\E . See also quotemeta.
7720\\a Alarm character (octal 007).
7721\\b Backspace character (octal 010).
7722\\c Control character, e.g. \\c[ .
7723\\e Escape character (octal 033).
7724\\f Formfeed character (octal 014).
7725\\l Lowercase the next character. See also \\L and \\u, lcfirst.
7726\\n Newline character (octal 012 on most systems).
7727\\r Return character (octal 015 on most systems).
7728\\t Tab character (octal 011).
7729\\u Upcase the next character. See also \\U and \\l, ucfirst.
7730\\x Hex character, e.g. \\x1b.
7731... ^ ... Bitwise exclusive or.
7732__END__ Ends program source.
7733__DATA__ Ends program source.
7734__FILE__ Current (source) filename.
7735__LINE__ Current line in current source.
7736__PACKAGE__ Current package.
7737ARGV Default multi-file input filehandle. <ARGV> is a synonym for <>.
7738ARGVOUT Output filehandle with -i flag.
7739BEGIN { ... } Immediately executed (during compilation) piece of code.
7740END { ... } Pseudo-subroutine executed after the script finishes.
6c389151
SM
7741CHECK { ... } Pseudo-subroutine executed after the script is compiled.
7742INIT { ... } Pseudo-subroutine executed before the script starts running.
f83d2997
KH
7743DATA Input filehandle for what follows after __END__ or __DATA__.
7744accept(NEWSOCKET,GENERICSOCKET)
7745alarm(SECONDS)
7746atan2(X,Y)
7747bind(SOCKET,NAME)
7748binmode(FILEHANDLE)
7749caller[(LEVEL)]
7750chdir(EXPR)
7751chmod(LIST)
7752chop[(LIST|VAR)]
7753chown(LIST)
7754chroot(FILENAME)
7755close(FILEHANDLE)
7756closedir(DIRHANDLE)
7757... cmp ... String compare.
7758connect(SOCKET,NAME)
7759continue of { block } continue { block }. Is executed after `next' or at end.
7760cos(EXPR)
7761crypt(PLAINTEXT,SALT)
7762dbmclose(%HASH)
7763dbmopen(%HASH,DBNAME,MODE)
7764defined(EXPR)
7765delete($HASH{KEY})
7766die(LIST)
7767do { ... }|SUBR while|until EXPR executes at least once
7768do(EXPR|SUBR([LIST])) (with while|until executes at least once)
7769dump LABEL
7770each(%HASH)
7771endgrent
7772endhostent
7773endnetent
7774endprotoent
7775endpwent
7776endservent
7777eof[([FILEHANDLE])]
7778... eq ... String equality.
7779eval(EXPR) or eval { BLOCK }
4ab89e7b 7780exec([TRUENAME] ARGV0, ARGVs) or exec(SHELL_COMMAND_LINE)
f83d2997
KH
7781exit(EXPR)
7782exp(EXPR)
7783fcntl(FILEHANDLE,FUNCTION,SCALAR)
7784fileno(FILEHANDLE)
7785flock(FILEHANDLE,OPERATION)
7786for (EXPR;EXPR;EXPR) { ... }
7787foreach [VAR] (@ARRAY) { ... }
7788fork
7789... ge ... String greater than or equal.
7790getc[(FILEHANDLE)]
7791getgrent
7792getgrgid(GID)
7793getgrnam(NAME)
7794gethostbyaddr(ADDR,ADDRTYPE)
7795gethostbyname(NAME)
7796gethostent
7797getlogin
7798getnetbyaddr(ADDR,ADDRTYPE)
7799getnetbyname(NAME)
7800getnetent
7801getpeername(SOCKET)
7802getpgrp(PID)
7803getppid
7804getpriority(WHICH,WHO)
7805getprotobyname(NAME)
7806getprotobynumber(NUMBER)
7807getprotoent
7808getpwent
7809getpwnam(NAME)
7810getpwuid(UID)
7811getservbyname(NAME,PROTO)
7812getservbyport(PORT,PROTO)
7813getservent
7814getsockname(SOCKET)
7815getsockopt(SOCKET,LEVEL,OPTNAME)
7816gmtime(EXPR)
7817goto LABEL
f83d2997
KH
7818... gt ... String greater than.
7819hex(EXPR)
7820if (EXPR) { ... } [ elsif (EXPR) { ... } ... ] [ else { ... } ] or EXPR if EXPR
7821index(STR,SUBSTR[,OFFSET])
7822int(EXPR)
7823ioctl(FILEHANDLE,FUNCTION,SCALAR)
7824join(EXPR,LIST)
7825keys(%HASH)
7826kill(LIST)
7827last [LABEL]
7828... le ... String less than or equal.
7829length(EXPR)
7830link(OLDFILE,NEWFILE)
7831listen(SOCKET,QUEUESIZE)
7832local(LIST)
7833localtime(EXPR)
7834log(EXPR)
7835lstat(EXPR|FILEHANDLE|VAR)
7836... lt ... String less than.
7837m/PATTERN/iogsmx
7838mkdir(FILENAME,MODE)
7839msgctl(ID,CMD,ARG)
7840msgget(KEY,FLAGS)
7841msgrcv(ID,VAR,SIZE,TYPE.FLAGS)
7842msgsnd(ID,MSG,FLAGS)
7843my VAR or my (VAR1,...) Introduces a lexical variable ($VAR, @ARR, or %HASH).
6c389151 7844our VAR or our (VAR1,...) Lexically enable a global variable ($V, @A, or %H).
f83d2997
KH
7845... ne ... String inequality.
7846next [LABEL]
7847oct(EXPR)
7848open(FILEHANDLE[,EXPR])
7849opendir(DIRHANDLE,EXPR)
7850ord(EXPR) ASCII value of the first char of the string.
7851pack(TEMPLATE,LIST)
7852package NAME Introduces package context.
7853pipe(READHANDLE,WRITEHANDLE) Create a pair of filehandles on ends of a pipe.
7854pop(ARRAY)
7855print [FILEHANDLE] [(LIST)]
7856printf [FILEHANDLE] (FORMAT,LIST)
7857push(ARRAY,LIST)
7858q/STRING/ Synonym for 'STRING'
7859qq/STRING/ Synonym for \"STRING\"
7860qx/STRING/ Synonym for `STRING`
7861rand[(EXPR)]
7862read(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7863readdir(DIRHANDLE)
7864readlink(EXPR)
7865recv(SOCKET,SCALAR,LEN,FLAGS)
7866redo [LABEL]
7867rename(OLDNAME,NEWNAME)
7868require [FILENAME | PERL_VERSION]
7869reset[(EXPR)]
7870return(LIST)
7871reverse(LIST)
7872rewinddir(DIRHANDLE)
7873rindex(STR,SUBSTR[,OFFSET])
7874rmdir(FILENAME)
7875s/PATTERN/REPLACEMENT/gieoxsm
7876scalar(EXPR)
7877seek(FILEHANDLE,POSITION,WHENCE)
7878seekdir(DIRHANDLE,POS)
7879select(FILEHANDLE | RBITS,WBITS,EBITS,TIMEOUT)
7880semctl(ID,SEMNUM,CMD,ARG)
7881semget(KEY,NSEMS,SIZE,FLAGS)
7882semop(KEY,...)
7883send(SOCKET,MSG,FLAGS[,TO])
7884setgrent
7885sethostent(STAYOPEN)
7886setnetent(STAYOPEN)
7887setpgrp(PID,PGRP)
7888setpriority(WHICH,WHO,PRIORITY)
7889setprotoent(STAYOPEN)
7890setpwent
7891setservent(STAYOPEN)
7892setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)
7893shift[(ARRAY)]
7894shmctl(ID,CMD,ARG)
7895shmget(KEY,SIZE,FLAGS)
7896shmread(ID,VAR,POS,SIZE)
7897shmwrite(ID,STRING,POS,SIZE)
7898shutdown(SOCKET,HOW)
7899sin(EXPR)
7900sleep[(EXPR)]
7901socket(SOCKET,DOMAIN,TYPE,PROTOCOL)
7902socketpair(SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL)
7903sort [SUBROUTINE] (LIST)
7904splice(ARRAY,OFFSET[,LENGTH[,LIST]])
7905split[(/PATTERN/[,EXPR[,LIMIT]])]
7906sprintf(FORMAT,LIST)
7907sqrt(EXPR)
7908srand(EXPR)
7909stat(EXPR|FILEHANDLE|VAR)
7910study[(SCALAR)]
7911sub [NAME [(format)]] { BODY } sub NAME [(format)]; sub [(format)] {...}
7912substr(EXPR,OFFSET[,LEN])
7913symlink(OLDFILE,NEWFILE)
7914syscall(LIST)
7915sysread(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
4ab89e7b 7916system([TRUENAME] ARGV0 [,ARGV]) or system(SHELL_COMMAND_LINE)
f83d2997
KH
7917syswrite(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7918tell[(FILEHANDLE)]
7919telldir(DIRHANDLE)
7920time
7921times
7922tr/SEARCHLIST/REPLACEMENTLIST/cds
7923truncate(FILE|EXPR,LENGTH)
7924umask[(EXPR)]
7925undef[(EXPR)]
7926unless (EXPR) { ... } [ else { ... } ] or EXPR unless EXPR
7927unlink(LIST)
7928unpack(TEMPLATE,EXPR)
7929unshift(ARRAY,LIST)
7930until (EXPR) { ... } EXPR until EXPR
7931utime(LIST)
7932values(%HASH)
7933vec(EXPR,OFFSET,BITS)
7934wait
7935waitpid(PID,FLAGS)
7936wantarray Returns true if the sub/eval is called in list context.
7937warn(LIST)
7938while (EXPR) { ... } EXPR while EXPR
7939write[(EXPR|FILEHANDLE)]
7940... x ... Repeat string or array.
7941x= ... Repetition assignment.
7942y/SEARCHLIST/REPLACEMENTLIST/
7943... | ... Bitwise or.
7944... || ... Logical or.
7945~ ... Unary bitwise complement.
db133cb6 7946#! OS interpreter indicator. If contains `perl', used for options, and -x.
f83d2997
KH
7947AUTOLOAD {...} Shorthand for `sub AUTOLOAD {...}'.
7948CORE:: Prefix to access builtin function if imported sub obscures it.
7949SUPER:: Prefix to lookup for a method in @ISA classes.
7950DESTROY Shorthand for `sub DESTROY {...}'.
7951... EQ ... Obsolete synonym of `eq'.
7952... GE ... Obsolete synonym of `ge'.
7953... GT ... Obsolete synonym of `gt'.
7954... LE ... Obsolete synonym of `le'.
7955... LT ... Obsolete synonym of `lt'.
7956... NE ... Obsolete synonym of `ne'.
7957abs [ EXPR ] absolute value
7958... and ... Low-precedence synonym for &&.
7959bless REFERENCE [, PACKAGE] Makes reference into an object of a package.
7960chomp [LIST] Strips $/ off LIST/$_. Returns count. Special if $/ eq ''!
7961chr Converts a number to char with the same ordinal.
7962else Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
7963elsif Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
83261a2f 7964exists $HASH{KEY} True if the key exists.
f83d2997
KH
7965format [NAME] = Start of output format. Ended by a single dot (.) on a line.
7966formline PICTURE, LIST Backdoor into \"format\" processing.
7967glob EXPR Synonym of <EXPR>.
7968lc [ EXPR ] Returns lowercased EXPR.
7969lcfirst [ EXPR ] Returns EXPR with lower-cased first letter.
db133cb6 7970grep EXPR,LIST or grep {BLOCK} LIST Filters LIST via EXPR/BLOCK.
f83d2997
KH
7971map EXPR, LIST or map {BLOCK} LIST Applies EXPR/BLOCK to elts of LIST.
7972no PACKAGE [SYMBOL1, ...] Partial reverse for `use'. Runs `unimport' method.
7973not ... Low-precedence synonym for ! - negation.
7974... or ... Low-precedence synonym for ||.
7975pos STRING Set/Get end-position of the last match over this string, see \\G.
7976quotemeta [ EXPR ] Quote regexp metacharacters.
7977qw/WORD1 .../ Synonym of split('', 'WORD1 ...')
7978readline FH Synonym of <FH>.
7979readpipe CMD Synonym of `CMD`.
7980ref [ EXPR ] Type of EXPR when dereferenced.
7981sysopen FH, FILENAME, MODE [, PERM] (MODE is numeric, see Fcntl.)
7982tie VAR, PACKAGE, LIST Hide an object behind a simple Perl variable.
7983tied Returns internal object for a tied data.
7984uc [ EXPR ] Returns upcased EXPR.
7985ucfirst [ EXPR ] Returns EXPR with upcased first letter.
7986untie VAR Unlink an object from a simple Perl variable.
7987use PACKAGE [SYMBOL1, ...] Compile-time `require' with consequent `import'.
7988... xor ... Low-precedence synonym for exclusive or.
d7584f0f 7989prototype \\&SUB Returns prototype of the function given a reference.
f83d2997
KH
7990=head1 Top-level heading.
7991=head2 Second-level heading.
7992=head3 Third-level heading (is there such?).
7993=over [ NUMBER ] Start list.
7994=item [ TITLE ] Start new item in the list.
7995=back End list.
7996=cut Switch from POD to Perl.
7997=pod Switch from Perl to POD.
7998")
7999
21df56d5 8000(defun cperl-switch-to-doc-buffer (&optional interactive)
f83d2997 8001 "Go to the perl documentation buffer and insert the documentation."
21df56d5 8002 (interactive "p")
f83d2997 8003 (let ((buf (get-buffer-create cperl-doc-buffer)))
21df56d5 8004 (if interactive
f83d2997
KH
8005 (switch-to-buffer-other-window buf)
8006 (set-buffer buf))
8007 (if (= (buffer-size) 0)
8008 (progn
8009 (insert (documentation-property 'cperl-short-docs
8010 'variable-documentation))
8011 (setq buffer-read-only t)))))
8012
6c389151 8013(defun cperl-beautify-regexp-piece (b e embed level)
f83d2997
KH
8014 ;; b is before the starting delimiter, e before the ending
8015 ;; e should be a marker, may be changed, but remains "correct".
e7f767c2 8016 ;; EMBED is nil if we process the whole REx.
4ab89e7b 8017 ;; The REx is guaranteed to have //x
6c389151
SM
8018 ;; LEVEL shows how many levels deep to go
8019 ;; position at enter and at leave is not defined
8020 (let (s c tmp (m (make-marker)) (m1 (make-marker)) c1 spaces inline code pos)
8c777c8d
CY
8021 (if embed
8022 (progn
8023 (goto-char b)
8024 (setq c (if (eq embed t) (current-indentation) (current-column)))
8025 (cond ((looking-at "(\\?\\\\#") ; (?#) wrongly commented when //x-ing
8026 (forward-char 2)
8027 (delete-char 1)
8028 (forward-char 1))
8029 ((looking-at "(\\?[^a-zA-Z]")
8030 (forward-char 3))
8031 ((looking-at "(\\?") ; (?i)
8032 (forward-char 2))
8033 (t
8034 (forward-char 1))))
8035 (goto-char (1+ b))
8036 (setq c (1- (current-column))))
8037 (setq c1 (+ c (or cperl-regexp-indent-step cperl-indent-level)))
f83d2997
KH
8038 (or (looking-at "[ \t]*[\n#]")
8039 (progn
8040 (insert "\n")))
8041 (goto-char e)
8042 (beginning-of-line)
8043 (if (re-search-forward "[^ \t]" e t)
83261a2f 8044 (progn ; Something before the ending delimiter
f83d2997 8045 (goto-char e)
6c389151 8046 (delete-horizontal-space)
f83d2997 8047 (insert "\n")
4ab89e7b 8048 (cperl-make-indent c)
f83d2997
KH
8049 (set-marker e (point))))
8050 (goto-char b)
8051 (end-of-line 2)
8052 (while (< (point) (marker-position e))
8053 (beginning-of-line)
8054 (setq s (point)
8055 inline t)
8056 (skip-chars-forward " \t")
8057 (delete-region s (point))
4ab89e7b 8058 (cperl-make-indent c1)
f83d2997
KH
8059 (while (and
8060 inline
5c8b7eaf 8061 (looking-at
f83d2997
KH
8062 (concat "\\([a-zA-Z0-9]+[^*+{?]\\)" ; 1 word
8063 "\\|" ; Embedded variable
8064 "\\$\\([a-zA-Z0-9_]+\\([[{]\\)?\\|[^\n \t)|]\\)" ; 2 3
8065 "\\|" ; $ ^
8066 "[$^]"
8067 "\\|" ; simple-code simple-code*?
8068 "\\(\\\\.\\|[^][()#|*+?\n]\\)\\([*+{?]\\??\\)?" ; 4 5
8069 "\\|" ; Class
8070 "\\(\\[\\)" ; 6
8071 "\\|" ; Grouping
8072 "\\((\\(\\?\\)?\\)" ; 7 8
8073 "\\|" ; |
83261a2f 8074 "\\(|\\)"))) ; 9
f83d2997
KH
8075 (goto-char (match-end 0))
8076 (setq spaces t)
8077 (cond ((match-beginning 1) ; Alphanum word + junk
8078 (forward-char -1))
8079 ((or (match-beginning 3) ; $ab[12]
8080 (and (match-beginning 5) ; X* X+ X{2,3}
8081 (eq (preceding-char) ?\{)))
8082 (forward-char -1)
8083 (forward-sexp 1))
4ab89e7b
SM
8084 ((and ; [], already syntaxified
8085 (match-beginning 6)
8086 cperl-regexp-scan
8087 cperl-use-syntax-table-text-property)
8088 (forward-char -1)
8089 (forward-sexp 1)
8090 (or (eq (preceding-char) ?\])
8091 (error "[]-group not terminated"))
8092 (re-search-forward
8093 "\\=\\([*+?]\\|{[0-9]+\\(,[0-9]*\\)?}\\)\\??" e t))
f83d2997
KH
8094 ((match-beginning 6) ; []
8095 (setq tmp (point))
8096 (if (looking-at "\\^?\\]")
8097 (goto-char (match-end 0)))
6c389151
SM
8098 ;; XXXX POSIX classes?!
8099 (while (and (not pos)
8100 (re-search-forward "\\[:\\|\\]" e t))
8101 (if (eq (preceding-char) ?:)
8102 (or (re-search-forward ":\\]" e t)
8103 (error "[:POSIX:]-group in []-group not terminated"))
8104 (setq pos t)))
8105 (or (eq (preceding-char) ?\])
8106 (error "[]-group not terminated"))
4ab89e7b
SM
8107 (re-search-forward
8108 "\\=\\([*+?]\\|{[0-9]+\\(,[0-9]*\\)?}\\)\\??" e t))
f83d2997
KH
8109 ((match-beginning 7) ; ()
8110 (goto-char (match-beginning 0))
6c389151
SM
8111 (setq pos (current-column))
8112 (or (eq pos c1)
f83d2997 8113 (progn
6c389151 8114 (delete-horizontal-space)
f83d2997 8115 (insert "\n")
4ab89e7b 8116 (cperl-make-indent c1)))
f83d2997
KH
8117 (setq tmp (point))
8118 (forward-sexp 1)
8119 ;; (or (forward-sexp 1)
8120 ;; (progn
8121 ;; (goto-char tmp)
8122 ;; (error "()-group not terminated")))
8123 (set-marker m (1- (point)))
8124 (set-marker m1 (point))
6c389151
SM
8125 (if (= level 1)
8126 (if (progn ; indent rigidly if multiline
a1506d29 8127 ;; In fact does not make a lot of sense, since
6c389151
SM
8128 ;; the starting position can be already lost due
8129 ;; to insertion of "\n" and " "
8130 (goto-char tmp)
8131 (search-forward "\n" m1 t))
8132 (indent-rigidly (point) m1 (- c1 pos)))
8133 (setq level (1- level))
8134 (cond
8135 ((not (match-beginning 8))
8136 (cperl-beautify-regexp-piece tmp m t level))
8137 ((eq (char-after (+ 2 tmp)) ?\{) ; Code
8138 t)
8139 ((eq (char-after (+ 2 tmp)) ?\() ; Conditional
8140 (goto-char (+ 2 tmp))
8141 (forward-sexp 1)
8142 (cperl-beautify-regexp-piece (point) m t level))
8143 ((eq (char-after (+ 2 tmp)) ?<) ; Lookbehind
8144 (goto-char (+ 3 tmp))
8145 (cperl-beautify-regexp-piece (point) m t level))
8146 (t
8147 (cperl-beautify-regexp-piece tmp m t level))))
f83d2997
KH
8148 (goto-char m1)
8149 (cond ((looking-at "[*+?]\\??")
8150 (goto-char (match-end 0)))
8151 ((eq (following-char) ?\{)
8152 (forward-sexp 1)
8153 (if (eq (following-char) ?\?)
8154 (forward-char))))
8155 (skip-chars-forward " \t")
8156 (setq spaces nil)
8157 (if (looking-at "[#\n]")
8158 (progn
8159 (or (eolp) (indent-for-comment))
8160 (beginning-of-line 2))
6c389151 8161 (delete-horizontal-space)
f83d2997
KH
8162 (insert "\n"))
8163 (end-of-line)
8164 (setq inline nil))
8165 ((match-beginning 9) ; |
8166 (forward-char -1)
8167 (setq tmp (point))
8168 (beginning-of-line)
8169 (if (re-search-forward "[^ \t]" tmp t)
8170 (progn
8171 (goto-char tmp)
6c389151 8172 (delete-horizontal-space)
f83d2997
KH
8173 (insert "\n"))
8174 ;; first at line
8175 (delete-region (point) tmp))
4ab89e7b 8176 (cperl-make-indent c)
f83d2997
KH
8177 (forward-char 1)
8178 (skip-chars-forward " \t")
8179 (setq spaces nil)
8180 (if (looking-at "[#\n]")
8181 (beginning-of-line 2)
6c389151 8182 (delete-horizontal-space)
f83d2997
KH
8183 (insert "\n"))
8184 (end-of-line)
8185 (setq inline nil)))
8186 (or (looking-at "[ \t\n]")
8187 (not spaces)
8188 (insert " "))
8189 (skip-chars-forward " \t"))
83261a2f
SM
8190 (or (looking-at "[#\n]")
8191 (error "Unknown code `%s' in a regexp"
8192 (buffer-substring (point) (1+ (point)))))
8193 (and inline (end-of-line 2)))
f83d2997
KH
8194 ;; Special-case the last line of group
8195 (if (and (>= (point) (marker-position e))
8196 (/= (current-indentation) c))
8197 (progn
83261a2f 8198 (beginning-of-line)
4ab89e7b 8199 (cperl-make-indent c)))))
f83d2997
KH
8200
8201(defun cperl-make-regexp-x ()
db133cb6 8202 ;; Returns position of the start
6c389151 8203 ;; XXX this is called too often! Need to cache the result!
f83d2997
KH
8204 (save-excursion
8205 (or cperl-use-syntax-table-text-property
5bd52f0e 8206 (error "I need to have a regexp marked!"))
f83d2997 8207 ;; Find the start
db133cb6
RS
8208 (if (looking-at "\\s|")
8209 nil ; good already
8c777c8d
CY
8210 (if (or (looking-at "\\([smy]\\|qr\\)\\s|")
8211 (and (eq (preceding-char) ?q)
8212 (looking-at "\\(r\\)\\s|")))
8213 (goto-char (match-end 1))
83261a2f 8214 (re-search-backward "\\s|"))) ; Assume it is scanned already.
f83d2997
KH
8215 ;;(forward-char 1)
8216 (let ((b (point)) (e (make-marker)) have-x delim (c (current-column))
8217 (sub-p (eq (preceding-char) ?s)) s)
8218 (forward-sexp 1)
8219 (set-marker e (1- (point)))
8220 (setq delim (preceding-char))
8221 (if (and sub-p (eq delim (char-after (- (point) 2))))
8222 (error "Possible s/blah// - do not know how to deal with"))
8223 (if sub-p (forward-sexp 1))
5c8b7eaf 8224 (if (looking-at "\\sw*x")
f83d2997
KH
8225 (setq have-x t)
8226 (insert "x"))
8227 ;; Protect fragile " ", "#"
8228 (if have-x nil
8229 (goto-char (1+ b))
8230 (while (re-search-forward "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*[ \t\n#]" e t) ; Need to include (?#) too?
8231 (forward-char -1)
8232 (insert "\\")
8233 (forward-char 1)))
8234 b)))
8235
6c389151 8236(defun cperl-beautify-regexp (&optional deep)
f94a632a 8237 "Do it. (Experimental, may change semantics, recheck the result.)
f83d2997 8238We suppose that the regexp is scanned already."
6c389151 8239 (interactive "P")
0c602a0f 8240 (setq deep (if deep (prefix-numeric-value deep) -1))
6c389151
SM
8241 (save-excursion
8242 (goto-char (cperl-make-regexp-x))
8243 (let ((b (point)) (e (make-marker)))
8244 (forward-sexp 1)
8245 (set-marker e (1- (point)))
8246 (cperl-beautify-regexp-piece b e nil deep))))
f83d2997 8247
db133cb6
RS
8248(defun cperl-regext-to-level-start ()
8249 "Goto start of an enclosing group in regexp.
f83d2997
KH
8250We suppose that the regexp is scanned already."
8251 (interactive)
db133cb6 8252 (let ((limit (cperl-make-regexp-x)) done)
f83d2997
KH
8253 (while (not done)
8254 (or (eq (following-char) ?\()
db133cb6 8255 (search-backward "(" (1+ limit) t)
f83d2997
KH
8256 (error "Cannot find `(' which starts a group"))
8257 (setq done
8258 (save-excursion
8259 (skip-chars-backward "\\")
8260 (looking-at "\\(\\\\\\\\\\)*(")))
db133cb6
RS
8261 (or done (forward-char -1)))))
8262
8263(defun cperl-contract-level ()
5bd52f0e 8264 "Find an enclosing group in regexp and contract it.
db133cb6
RS
8265\(Experimental, may change semantics, recheck the result.)
8266We suppose that the regexp is scanned already."
8267 (interactive)
6c389151 8268 ;; (save-excursion ; Can't, breaks `cperl-contract-levels'
83261a2f 8269 (cperl-regext-to-level-start)
4ab89e7b 8270 (let ((b (point)) (e (make-marker)) c)
83261a2f
SM
8271 (forward-sexp 1)
8272 (set-marker e (1- (point)))
8273 (goto-char b)
8274 (while (re-search-forward "\\(#\\)\\|\n" e 'to-end)
8275 (cond
8276 ((match-beginning 1) ; #-comment
8277 (or c (setq c (current-indentation)))
8278 (beginning-of-line 2) ; Skip
4ab89e7b 8279 (cperl-make-indent c))
83261a2f
SM
8280 (t
8281 (delete-char -1)
8282 (just-one-space))))))
db133cb6
RS
8283
8284(defun cperl-contract-levels ()
5bd52f0e 8285 "Find an enclosing group in regexp and contract all the kids.
db133cb6
RS
8286\(Experimental, may change semantics, recheck the result.)
8287We suppose that the regexp is scanned already."
8288 (interactive)
6c389151
SM
8289 (save-excursion
8290 (condition-case nil
8291 (cperl-regext-to-level-start)
8292 (error ; We are outside outermost group
5efe6a56
SM
8293 (goto-char (cperl-make-regexp-x))))
8294 (let ((b (point)) (e (make-marker)) s c)
8295 (forward-sexp 1)
8296 (set-marker e (1- (point)))
8297 (goto-char (1+ b))
8298 (while (re-search-forward "\\(\\\\\\\\\\)\\|(" e t)
a1506d29 8299 (cond
6c389151
SM
8300 ((match-beginning 1) ; Skip
8301 nil)
8302 (t ; Group
8303 (cperl-contract-level)))))))
f83d2997 8304
6c389151 8305(defun cperl-beautify-level (&optional deep)
f83d2997
KH
8306 "Find an enclosing group in regexp and beautify it.
8307\(Experimental, may change semantics, recheck the result.)
8308We suppose that the regexp is scanned already."
6c389151 8309 (interactive "P")
0c602a0f 8310 (setq deep (if deep (prefix-numeric-value deep) -1))
6c389151
SM
8311 (save-excursion
8312 (cperl-regext-to-level-start)
8313 (let ((b (point)) (e (make-marker)))
8314 (forward-sexp 1)
8315 (set-marker e (1- (point)))
8c777c8d 8316 (cperl-beautify-regexp-piece b e 'level deep))))
db133cb6 8317
4ab89e7b
SM
8318(defun cperl-invert-if-unless-modifiers ()
8319 "Change `B if A;' into `if (A) {B}' etc if possible.
8320\(Unfinished.)"
8c777c8d 8321 (interactive)
4ab89e7b
SM
8322 (let (A B pre-B post-B pre-if post-if pre-A post-A if-string
8323 (w-rex "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>"))
8324 (and (= (char-syntax (preceding-char)) ?w)
8325 (forward-sexp -1))
8326 (setq pre-if (point))
8327 (cperl-backward-to-start-of-expr)
8328 (setq pre-B (point))
8329 (forward-sexp 1) ; otherwise forward-to-end-of-expr is NOP
8330 (cperl-forward-to-end-of-expr)
8331 (setq post-A (point))
8332 (goto-char pre-if)
8333 (or (looking-at w-rex)
8334 ;; Find the position
8335 (progn (goto-char post-A)
8336 (while (and
8337 (not (looking-at w-rex))
8338 (> (point) pre-B))
8339 (forward-sexp -1))
8340 (setq pre-if (point))))
8341 (or (looking-at w-rex)
8342 (error "Can't find `if', `unless', `while', `until', `for' or `foreach'"))
8343 ;; 1 B 2 ... 3 B-com ... 4 if 5 ... if-com 6 ... 7 A 8
8344 (setq if-string (buffer-substring (match-beginning 0) (match-end 0)))
8345 ;; First, simple part: find code boundaries
8346 (forward-sexp 1)
8347 (setq post-if (point))
8348 (forward-sexp -2)
8349 (forward-sexp 1)
8350 (setq post-B (point))
8351 (cperl-backward-to-start-of-expr)
8352 (setq pre-B (point))
8353 (setq B (buffer-substring pre-B post-B))
8354 (goto-char pre-if)
8355 (forward-sexp 2)
8356 (forward-sexp -1)
8357 ;; May be after $, @, $# etc of a variable
8358 (skip-chars-backward "$@%#")
8359 (setq pre-A (point))
8360 (cperl-forward-to-end-of-expr)
8361 (setq post-A (point))
8362 (setq A (buffer-substring pre-A post-A))
8363 ;; Now modify (from end, to not break the stuff)
8364 (skip-chars-forward " \t;")
8365 (delete-region pre-A (point)) ; we move to pre-A
8366 (insert "\n" B ";\n}")
8367 (and (looking-at "[ \t]*#") (cperl-indent-for-comment))
8368 (delete-region pre-if post-if)
8369 (delete-region pre-B post-B)
8370 (goto-char pre-B)
8371 (insert if-string " (" A ") {")
8372 (setq post-B (point))
8373 (if (looking-at "[ \t]+$")
8374 (delete-horizontal-space)
8375 (if (looking-at "[ \t]*#")
8376 (cperl-indent-for-comment)
8377 (just-one-space)))
8378 (forward-line 1)
8379 (if (looking-at "[ \t]*$")
8380 (progn ; delete line
8381 (delete-horizontal-space)
8382 (delete-region (point) (1+ (point)))))
8383 (cperl-indent-line)
8384 (goto-char (1- post-B))
8385 (forward-sexp 1)
8386 (cperl-indent-line)
8387 (goto-char pre-B)))
8388
db133cb6 8389(defun cperl-invert-if-unless ()
4ab89e7b
SM
8390 "Change `if (A) {B}' into `B if A;' etc (or visa versa) if possible.
8391If the cursor is not on the leading keyword of the BLOCK flavor of
8392construct, will assume it is the STATEMENT flavor, so will try to find
8393the appropriate statement modifier."
db133cb6 8394 (interactive)
4ab89e7b
SM
8395 (and (= (char-syntax (preceding-char)) ?w)
8396 (forward-sexp -1))
6c389151 8397 (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>")
4ab89e7b
SM
8398 (let ((pre-if (point))
8399 pre-A post-A pre-B post-B A B state p end-B-code is-block B-comment
8400 (if-string (buffer-substring (match-beginning 0) (match-end 0))))
db133cb6 8401 (forward-sexp 2)
4ab89e7b 8402 (setq post-A (point))
db133cb6 8403 (forward-sexp -1)
4ab89e7b
SM
8404 (setq pre-A (point))
8405 (setq is-block (and (eq (following-char) ?\( )
8406 (save-excursion
8407 (condition-case nil
8408 (progn
8409 (forward-sexp 2)
8410 (forward-sexp -1)
8411 (eq (following-char) ?\{ ))
8412 (error nil)))))
8413 (if is-block
db133cb6 8414 (progn
4ab89e7b 8415 (goto-char post-A)
db133cb6 8416 (forward-sexp 1)
4ab89e7b 8417 (setq post-B (point))
db133cb6 8418 (forward-sexp -1)
4ab89e7b 8419 (setq pre-B (point))
db133cb6
RS
8420 (if (and (eq (following-char) ?\{ )
8421 (progn
4ab89e7b 8422 (cperl-backward-to-noncomment post-A)
db133cb6
RS
8423 (eq (preceding-char) ?\) )))
8424 (if (condition-case nil
8425 (progn
4ab89e7b 8426 (goto-char post-B)
db133cb6
RS
8427 (forward-sexp 1)
8428 (forward-sexp -1)
8429 (looking-at "\\<els\\(e\\|if\\)\\>"))
8430 (error nil))
8431 (error
4ab89e7b
SM
8432 "`%s' (EXPR) {BLOCK} with `else'/`elsif'" if-string)
8433 (goto-char (1- post-B))
8434 (cperl-backward-to-noncomment pre-B)
db133cb6
RS
8435 (if (eq (preceding-char) ?\;)
8436 (forward-char -1))
4ab89e7b
SM
8437 (setq end-B-code (point))
8438 (goto-char pre-B)
8439 (while (re-search-forward "\\<\\(for\\|foreach\\|if\\|unless\\|while\\|until\\)\\>\\|;" end-B-code t)
db133cb6 8440 (setq p (match-beginning 0)
4ab89e7b
SM
8441 A (buffer-substring p (match-end 0))
8442 state (parse-partial-sexp pre-B p))
5c8b7eaf 8443 (or (nth 3 state)
db133cb6
RS
8444 (nth 4 state)
8445 (nth 5 state)
4ab89e7b 8446 (error "`%s' inside `%s' BLOCK" A if-string))
db133cb6
RS
8447 (goto-char (match-end 0)))
8448 ;; Finally got it
4ab89e7b 8449 (goto-char (1+ pre-B))
db133cb6 8450 (skip-chars-forward " \t\n")
4ab89e7b
SM
8451 (setq B (buffer-substring (point) end-B-code))
8452 (goto-char end-B-code)
db133cb6
RS
8453 (or (looking-at ";?[ \t\n]*}")
8454 (progn
8455 (skip-chars-forward "; \t\n")
4ab89e7b
SM
8456 (setq B-comment
8457 (buffer-substring (point) (1- post-B)))))
8458 (and (equal B "")
8459 (setq B "1"))
8460 (goto-char (1- post-A))
8461 (cperl-backward-to-noncomment pre-A)
db133cb6 8462 (or (looking-at "[ \t\n]*)")
4ab89e7b 8463 (goto-char (1- post-A)))
db133cb6 8464 (setq p (point))
4ab89e7b 8465 (goto-char (1+ pre-A))
db133cb6 8466 (skip-chars-forward " \t\n")
4ab89e7b
SM
8467 (setq A (buffer-substring (point) p))
8468 (delete-region pre-B post-B)
8469 (delete-region pre-A post-A)
8470 (goto-char pre-if)
8471 (insert B " ")
8472 (and B-comment (insert B-comment " "))
db133cb6
RS
8473 (just-one-space)
8474 (forward-word 1)
4ab89e7b
SM
8475 (setq pre-A (point))
8476 (insert " " A ";")
6c389151 8477 (delete-horizontal-space)
4ab89e7b
SM
8478 (setq post-B (point))
8479 (if (looking-at "#")
8480 (indent-for-comment))
8481 (goto-char post-B)
db133cb6
RS
8482 (forward-char -1)
8483 (delete-horizontal-space)
4ab89e7b 8484 (goto-char pre-A)
db133cb6 8485 (just-one-space)
4ab89e7b
SM
8486 (goto-char pre-if)
8487 (setq pre-A (set-marker (make-marker) pre-A))
8488 (while (<= (point) (marker-position pre-A))
8489 (cperl-indent-line)
8490 (forward-line 1))
8491 (goto-char (marker-position pre-A))
8492 (if B-comment
8493 (progn
8494 (forward-line -1)
8495 (indent-for-comment)
8496 (goto-char (marker-position pre-A)))))
8497 (error "`%s' (EXPR) not with an {BLOCK}" if-string)))
8498 ;; (error "`%s' not with an (EXPR)" if-string)
8499 (forward-sexp -1)
8500 (cperl-invert-if-unless-modifiers)))
8501 ;;(error "Not at `if', `unless', `while', `until', `for' or `foreach'")
8502 (cperl-invert-if-unless-modifiers)))
db133cb6 8503
5bd52f0e 8504;;; By Anthony Foiani <afoiani@uswest.com>
b7ec9e59
RS
8505;;; Getting help on modules in C-h f ?
8506;;; This is a modified version of `man'.
8507;;; Need to teach it how to lookup functions
4ab89e7b 8508;;;###autoload
b7ec9e59
RS
8509(defun cperl-perldoc (word)
8510 "Run `perldoc' on WORD."
8511 (interactive
8512 (list (let* ((default-entry (cperl-word-at-point))
8513 (input (read-string
8514 (format "perldoc entry%s: "
8515 (if (string= default-entry "")
8516 ""
8517 (format " (default %s)" default-entry))))))
8518 (if (string= input "")
8519 (if (string= default-entry "")
8520 (error "No perldoc args given")
8521 default-entry)
8522 input))))
a8e1e57f 8523 (require 'man)
f739b53b
SM
8524 (let* ((case-fold-search nil)
8525 (is-func (and
b7ec9e59
RS
8526 (string-match "^[a-z]+$" word)
8527 (string-match (concat "^" word "\\>")
8528 (documentation-property
8529 'cperl-short-docs
8530 'variable-documentation))))
8c777c8d 8531 (Man-switches "")
b7ec9e59 8532 (manual-program (if is-func "perldoc -f" "perldoc")))
f739b53b 8533 (cond
6546555e 8534 ((featurep 'xemacs)
f739b53b
SM
8535 (let ((Manual-program "perldoc")
8536 (Manual-switches (if is-func (list "-f"))))
8537 (manual-entry word)))
8538 (t
8539 (Man-getpage-in-background word)))))
b7ec9e59 8540
4ab89e7b 8541;;;###autoload
b7ec9e59
RS
8542(defun cperl-perldoc-at-point ()
8543 "Run a `perldoc' on the word around point."
8544 (interactive)
8545 (cperl-perldoc (cperl-word-at-point)))
8546
8547(defcustom pod2man-program "pod2man"
8548 "*File name for `pod2man'."
8549 :type 'file
8550 :group 'cperl)
8551
5bd52f0e 8552;;; By Nick Roberts <Nick.Roberts@src.bae.co.uk> (with changes)
b7ec9e59
RS
8553(defun cperl-pod-to-manpage ()
8554 "Create a virtual manpage in Emacs from the Perl Online Documentation."
8555 (interactive)
8556 (require 'man)
8557 (let* ((pod2man-args (concat buffer-file-name " | nroff -man "))
8558 (bufname (concat "Man " buffer-file-name))
8559 (buffer (generate-new-buffer bufname)))
9a529312 8560 (with-current-buffer buffer
b7ec9e59
RS
8561 (let ((process-environment (copy-sequence process-environment)))
8562 ;; Prevent any attempt to use display terminal fanciness.
8563 (setenv "TERM" "dumb")
8564 (set-process-sentinel
8565 (start-process pod2man-program buffer "sh" "-c"
8566 (format (cperl-pod2man-build-command) pod2man-args))
8567 'Man-bgproc-sentinel)))))
8568
f739b53b
SM
8569;;; Updated version by him too
8570(defun cperl-build-manpage ()
8571 "Create a virtual manpage in Emacs from the POD in the file."
8572 (interactive)
8573 (require 'man)
8574 (cond
6546555e 8575 ((featurep 'xemacs)
f739b53b
SM
8576 (let ((Manual-program "perldoc"))
8577 (manual-entry buffer-file-name)))
8578 (t
8c777c8d
CY
8579 (let* ((manual-program "perldoc")
8580 (Man-switches ""))
f739b53b
SM
8581 (Man-getpage-in-background buffer-file-name)))))
8582
b7ec9e59
RS
8583(defun cperl-pod2man-build-command ()
8584 "Builds the entire background manpage and cleaning command."
8585 (let ((command (concat pod2man-program " %s 2>/dev/null"))
4ab89e7b 8586 (flist (and (boundp 'Man-filter-list) Man-filter-list)))
b7ec9e59
RS
8587 (while (and flist (car flist))
8588 (let ((pcom (car (car flist)))
8589 (pargs (cdr (car flist))))
8590 (setq command
8591 (concat command " | " pcom " "
4f91a816
SM
8592 (mapconcat (lambda (phrase)
8593 (if (not (stringp phrase))
8594 (error "Malformed Man-filter-list"))
8595 phrase)
b7ec9e59
RS
8596 pargs " ")))
8597 (setq flist (cdr flist))))
8598 command))
db133cb6 8599
4ab89e7b
SM
8600
8601(defun cperl-next-interpolated-REx-1 ()
8602 "Move point to next REx which has interpolated parts without //o.
8603Skips RExes consisting of one interpolated variable.
8604
8605Note that skipped RExen are not performance hits."
8606 (interactive "")
8607 (cperl-next-interpolated-REx 1))
8608
8609(defun cperl-next-interpolated-REx-0 ()
8610 "Move point to next REx which has interpolated parts without //o."
8611 (interactive "")
8612 (cperl-next-interpolated-REx 0))
8613
8614(defun cperl-next-interpolated-REx (&optional skip beg limit)
8615 "Move point to next REx which has interpolated parts.
8616SKIP is a list of possible types to skip, BEG and LIMIT are the starting
8617point and the limit of search (default to point and end of buffer).
8618
8619SKIP may be a number, then it behaves as list of numbers up to SKIP; this
8620semantic may be used as a numeric argument.
8621
8622Types are 0 for / $rex /o (interpolated once), 1 for /$rex/ (if $rex is
8623a result of qr//, this is not a performance hit), t for the rest."
8624 (interactive "P")
8625 (if (numberp skip) (setq skip (list 0 skip)))
8626 (or beg (setq beg (point)))
8627 (or limit (setq limit (point-max))) ; needed for n-s-p-c
8628 (let (pp)
8629 (and (eq (get-text-property beg 'syntax-type) 'string)
8630 (setq beg (next-single-property-change beg 'syntax-type nil limit)))
8631 (cperl-map-pods-heres
8632 (function (lambda (s e p)
8633 (if (memq (get-text-property s 'REx-interpolated) skip)
8634 t
8635 (setq pp s)
8636 nil))) ; nil stops
8637 'REx-interpolated beg limit)
8638 (if pp (goto-char pp)
8639 (message "No more interpolated REx"))))
8640
8641;;; Initial version contributed by Trey Belew
8642(defun cperl-here-doc-spell (&optional beg end)
8643 "Spell-check HERE-documents in the Perl buffer.
8644If a region is highlighted, restricts to the region."
8645 (interactive "")
8646 (cperl-pod-spell t beg end))
8647
8648(defun cperl-pod-spell (&optional do-heres beg end)
8649 "Spell-check POD documentation.
8650If invoked with prefix argument, will do HERE-DOCs instead.
8651If a region is highlighted, restricts to the region."
8652 (interactive "P")
8653 (save-excursion
8654 (let (beg end)
8655 (if (cperl-mark-active)
8656 (setq beg (min (mark) (point))
8657 end (max (mark) (point)))
8658 (setq beg (point-min)
8659 end (point-max)))
8660 (cperl-map-pods-heres (function
8661 (lambda (s e p)
8662 (if do-heres
8663 (setq e (save-excursion
8664 (goto-char e)
8665 (forward-line -1)
8666 (point))))
8667 (ispell-region s e)
8668 t))
8669 (if do-heres 'here-doc-group 'in-pod)
8670 beg end))))
8671
8672(defun cperl-map-pods-heres (func &optional prop s end)
8673 "Executes a function over regions of pods or here-documents.
8674PROP is the text-property to search for; default to `in-pod'. Stop when
8675function returns nil."
8676 (let (pos posend has-prop (cont t))
8677 (or prop (setq prop 'in-pod))
8678 (or s (setq s (point-min)))
8679 (or end (setq end (point-max)))
8680 (cperl-update-syntaxification end end)
8681 (save-excursion
8682 (goto-char (setq pos s))
8683 (while (and cont (< pos end))
8684 (setq has-prop (get-text-property pos prop))
8685 (setq posend (next-single-property-change pos prop nil end))
8686 (and has-prop
8687 (setq cont (funcall func pos posend prop)))
8688 (setq pos posend)))))
8689
8690;;; Based on code by Masatake YAMATO:
8691(defun cperl-get-here-doc-region (&optional pos pod)
8692 "Return HERE document region around the point.
8693Return nil if the point is not in a HERE document region. If POD is non-nil,
8694will return a POD section if point is in a POD section."
8695 (or pos (setq pos (point)))
8696 (cperl-update-syntaxification pos pos)
8697 (if (or (eq 'here-doc (get-text-property pos 'syntax-type))
8698 (and pod
8699 (eq 'pod (get-text-property pos 'syntax-type))))
8700 (let ((b (cperl-beginning-of-property pos 'syntax-type))
8701 (e (next-single-property-change pos 'syntax-type)))
8702 (cons b (or e (point-max))))))
8703
8704(defun cperl-narrow-to-here-doc (&optional pos)
8705 "Narrows editing region to the HERE-DOC at POS.
8706POS defaults to the point."
8707 (interactive "d")
8708 (or pos (setq pos (point)))
8709 (let ((p (cperl-get-here-doc-region pos)))
8710 (or p (error "Not inside a HERE document"))
8711 (narrow-to-region (car p) (cdr p))
8712 (message
8713 "When you are finished with narrow editing, type C-x n w")))
8714
8715(defun cperl-select-this-pod-or-here-doc (&optional pos)
8716 "Select the HERE-DOC (or POD section) at POS.
8717POS defaults to the point."
8718 (interactive "d")
8719 (let ((p (cperl-get-here-doc-region pos t)))
8720 (if p
8721 (progn
8722 (goto-char (car p))
8723 (push-mark (cdr p) nil t)) ; Message, activate in transient-mode
8724 (message "I do not think POS is in POD or a HERE-doc..."))))
8725
8726(defun cperl-facemenu-add-face-function (face end)
8727 "A callback to process user-initiated font-change requests.
8728Translates `bold', `italic', and `bold-italic' requests to insertion of
8729corresponding POD directives, and `underline' to C<> POD directive.
8730
8731Such requests are usually bound to M-o LETTER."
8732 (or (get-text-property (point) 'in-pod)
8733 (error "Faces can only be set within POD"))
8734 (setq facemenu-end-add-face (if (eq face 'bold-italic) ">>" ">"))
8735 (cdr (or (assq face '((bold . "B<")
8736 (italic . "I<")
8737 (bold-italic . "B<I<")
8738 (underline . "C<")))
8739 (error "Face %s not configured for cperl-mode"
8740 face))))
8741\f
8742(defun cperl-time-fontification (&optional l step lim)
8743 "Times how long it takes to do incremental fontification in a region.
8744L is the line to start at, STEP is the number of lines to skip when
8745doing next incremental fontification, LIM is the maximal number of
8746incremental fontification to perform. Messages are accumulated in
8747*Messages* buffer.
8748
8749May be used for pinpointing which construct slows down buffer fontification:
8750start with default arguments, then refine the slowdown regions."
8751 (interactive "nLine to start at: \nnStep to do incremental fontification: ")
8752 (or l (setq l 1))
8753 (or step (setq step 500))
8754 (or lim (setq lim 40))
8755 (let* ((timems (function (lambda ()
8756 (let ((tt (current-time)))
8757 (+ (* 1000 (nth 1 tt)) (/ (nth 2 tt) 1000))))))
8758 (tt (funcall timems)) (c 0) delta tot)
47e83968
GM
8759 (goto-char (point-min))
8760 (forward-line (1- l))
4ab89e7b
SM
8761 (cperl-mode)
8762 (setq tot (- (- tt (setq tt (funcall timems)))))
8763 (message "cperl-mode at %s: %s" l tot)
8764 (while (and (< c lim) (not (eobp)))
8765 (forward-line step)
8766 (setq l (+ l step))
8767 (setq c (1+ c))
8768 (cperl-update-syntaxification (point) (point))
8769 (setq delta (- (- tt (setq tt (funcall timems)))) tot (+ tot delta))
8770 (message "to %s:%6s,%7s" l delta tot))
8771 tot))
8772
6546555e
DN
8773(defvar font-lock-cache-position)
8774
4ab89e7b
SM
8775(defun cperl-emulate-lazy-lock (&optional window-size)
8776 "Emulate `lazy-lock' without `condition-case', so `debug-on-error' works.
8777Start fontifying the buffer from the start (or end) using the given
8778WINDOW-SIZE (units is lines). Negative WINDOW-SIZE starts at end, and
8779goes backwards; default is -50. This function is not CPerl-specific; it
8780may be used to debug problems with delayed incremental fontification."
8781 (interactive
8782 "nSize of window for incremental fontification, negative goes backwards: ")
8783 (or window-size (setq window-size -50))
8784 (let ((pos (if (> window-size 0)
8785 (point-min)
8786 (point-max)))
8787 p)
8788 (goto-char pos)
8789 (normal-mode)
8790 ;; Why needed??? With older font-locks???
8791 (set (make-local-variable 'font-lock-cache-position) (make-marker))
8792 (while (if (> window-size 0)
8793 (< pos (point-max))
8794 (> pos (point-min)))
8795 (setq p (progn
8796 (forward-line window-size)
8797 (point)))
8798 (font-lock-fontify-region (min p pos) (max p pos))
8799 (setq pos p))))
8800
8801\f
db133cb6 8802(defun cperl-lazy-install ()) ; Avoid a warning
f739b53b 8803(defun cperl-lazy-unstall ()) ; Avoid a warning
f83d2997
KH
8804
8805(if (fboundp 'run-with-idle-timer)
8806 (progn
8807 (defvar cperl-help-shown nil
8808 "Non-nil means that the help was already shown now.")
8809
8810 (defvar cperl-lazy-installed nil
8811 "Non-nil means that the lazy-help handlers are installed now.")
8812
8813 (defun cperl-lazy-install ()
f739b53b
SM
8814 "Switches on Auto-Help on Perl constructs (put in the message area).
8815Delay of auto-help controlled by `cperl-lazy-help-time'."
f83d2997 8816 (interactive)
4ab89e7b 8817 (make-local-variable 'cperl-help-shown)
f83d2997
KH
8818 (if (and (cperl-val 'cperl-lazy-help-time)
8819 (not cperl-lazy-installed))
8820 (progn
8821 (add-hook 'post-command-hook 'cperl-lazy-hook)
5c8b7eaf
SS
8822 (run-with-idle-timer
8823 (cperl-val 'cperl-lazy-help-time 1000000 5)
8824 t
f83d2997
KH
8825 'cperl-get-help-defer)
8826 (setq cperl-lazy-installed t))))
8827
8828 (defun cperl-lazy-unstall ()
f739b53b
SM
8829 "Switches off Auto-Help on Perl constructs (put in the message area).
8830Delay of auto-help controlled by `cperl-lazy-help-time'."
f83d2997
KH
8831 (interactive)
8832 (remove-hook 'post-command-hook 'cperl-lazy-hook)
8833 (cancel-function-timers 'cperl-get-help-defer)
8834 (setq cperl-lazy-installed nil))
8835
8836 (defun cperl-lazy-hook ()
8837 (setq cperl-help-shown nil))
8838
8839 (defun cperl-get-help-defer ()
83261a2f 8840 (if (not (memq major-mode '(perl-mode cperl-mode))) nil
f83d2997
KH
8841 (let ((cperl-message-on-help-error nil) (cperl-help-from-timer t))
8842 (cperl-get-help)
8843 (setq cperl-help-shown t))))
8844 (cperl-lazy-install)))
8845
db133cb6
RS
8846
8847;;; Plug for wrong font-lock:
8848
8849(defun cperl-font-lock-unfontify-region-function (beg end)
4ab89e7b
SM
8850 (let* ((modified (buffer-modified-p)) (buffer-undo-list t)
8851 (inhibit-read-only t) (inhibit-point-motion-hooks t)
8852 before-change-functions after-change-functions
8853 deactivate-mark buffer-file-name buffer-file-truename)
8854 (remove-text-properties beg end '(face nil))
8855 (if (and (not modified) (buffer-modified-p))
8856 (set-buffer-modified-p nil))))
8857
8858(defun cperl-font-lock-fontify-region-function (beg end loudly)
8859 "Extends the region to safe positions, then calls the default function.
8860Newer `font-lock's can do it themselves.
8861We unwind only as far as needed for fontification. Syntaxification may
8862do extra unwind via `cperl-unwind-to-safe'."
8863 (save-excursion
8864 (goto-char beg)
8865 (while (and beg
8866 (progn
8867 (beginning-of-line)
8868 (eq (get-text-property (setq beg (point)) 'syntax-type)
8869 'multiline)))
8870 (if (setq beg (cperl-beginning-of-property beg 'syntax-type))
8871 (goto-char beg)))
8872 (setq beg (point))
8873 (goto-char end)
8874 (while (and end
8875 (progn
8876 (or (bolp) (condition-case nil
8877 (forward-line 1)
8878 (error nil)))
8879 (eq (get-text-property (setq end (point)) 'syntax-type)
8880 'multiline)))
8881 (setq end (next-single-property-change end 'syntax-type nil (point-max)))
8882 (goto-char end))
8883 (setq end (point)))
8884 (font-lock-default-fontify-region beg end loudly))
db133cb6
RS
8885
8886(defvar cperl-d-l nil)
8887(defun cperl-fontify-syntaxically (end)
5bd52f0e 8888 ;; Some vars for debugging only
6c389151 8889 ;; (message "Syntaxifying...")
4ab89e7b 8890 (let ((dbg (point)) (iend end) (idone cperl-syntax-done-to)
83261a2f 8891 (istate (car cperl-syntax-state))
4ab89e7b
SM
8892 start from-start edebug-backtrace-buffer)
8893 (if (eq cperl-syntaxify-by-font-lock 'backtrace)
8894 (progn
8895 (require 'edebug)
8896 (let ((f 'edebug-backtrace))
8897 (funcall f)))) ; Avoid compile-time warning
db133cb6 8898 (or cperl-syntax-done-to
4ab89e7b
SM
8899 (setq cperl-syntax-done-to (point-min)
8900 from-start t))
8901 (setq start (if (and cperl-hook-after-change
8902 (not from-start))
8903 cperl-syntax-done-to ; Fontify without change; ignore start
8904 ;; Need to forget what is after `start'
8905 (min cperl-syntax-done-to (point))))
8906 (goto-char start)
8907 (beginning-of-line)
8908 (setq start (point))
8909 (and cperl-syntaxify-unwind
8910 (setq end (cperl-unwind-to-safe t end)
8911 start (point)))
db133cb6
RS
8912 (and (> end start)
8913 (setq cperl-syntax-done-to start) ; In case what follows fails
8914 (cperl-find-pods-heres start end t nil t))
4ab89e7b
SM
8915 (if (memq cperl-syntaxify-by-font-lock '(backtrace message))
8916 (message "Syxify req=%s..%s actual=%s..%s done-to: %s=>%s statepos: %s=>%s"
8917 dbg iend start end idone cperl-syntax-done-to
5c8b7eaf 8918 istate (car cperl-syntax-state))) ; For debugging
83261a2f 8919 nil)) ; Do not iterate
db133cb6 8920
5bd52f0e 8921(defun cperl-fontify-update (end)
4ab89e7b
SM
8922 (let ((pos (point-min)) prop posend)
8923 (setq end (point-max))
5bd52f0e 8924 (while (< pos end)
4ab89e7b
SM
8925 (setq prop (get-text-property pos 'cperl-postpone)
8926 posend (next-single-property-change pos 'cperl-postpone nil end))
5bd52f0e
RS
8927 (and prop (put-text-property pos posend (car prop) (cdr prop)))
8928 (setq pos posend)))
83261a2f 8929 nil) ; Do not iterate
5bd52f0e 8930
4ab89e7b
SM
8931(defun cperl-fontify-update-bad (end)
8932 ;; Since fontification happens with different region than syntaxification,
8933 ;; do to the end of buffer, not to END;;; likewise, start earlier if needed
8934 (let* ((pos (point)) (prop (get-text-property pos 'cperl-postpone)) posend)
8935 (if prop
8936 (setq pos (or (cperl-beginning-of-property
8937 (cperl-1+ pos) 'cperl-postpone)
8938 (point-min))))
8939 (while (< pos end)
8940 (setq posend (next-single-property-change pos 'cperl-postpone))
8941 (and prop (put-text-property pos posend (car prop) (cdr prop)))
8942 (setq pos posend)
8943 (setq prop (get-text-property pos 'cperl-postpone))))
8944 nil) ; Do not iterate
8945
8946;; Called when any modification is made to buffer text.
8947(defun cperl-after-change-function (beg end old-len)
8948 ;; We should have been informed about changes by `font-lock'. Since it
4c36be58 8949 ;; does not inform as which calls are deferred, do it ourselves
4ab89e7b
SM
8950 (if cperl-syntax-done-to
8951 (setq cperl-syntax-done-to (min cperl-syntax-done-to beg))))
8952
5bd52f0e
RS
8953(defun cperl-update-syntaxification (from to)
8954 (if (and cperl-use-syntax-table-text-property
8955 cperl-syntaxify-by-font-lock
8956 (or (null cperl-syntax-done-to)
8957 (< cperl-syntax-done-to to)))
8958 (progn
8959 (save-excursion
8960 (goto-char from)
8961 (cperl-fontify-syntaxically to)))))
8962
5c8b7eaf 8963(defvar cperl-version
8c777c8d 8964 (let ((v "Revision: 6.2"))
5bd52f0e
RS
8965 (string-match ":\\s *\\([0-9.]+\\)" v)
8966 (substring v (match-beginning 1) (match-end 1)))
8967 "Version of IZ-supported CPerl package this file is based on.")
8968
f83d2997
KH
8969(provide 'cperl-mode)
8970
8971;;; cperl-mode.el ends here