(reftex-TeX-master-file): Use really the buffer file name if no other master
[bpt/emacs.git] / lisp / progmodes / cperl-mode.el
CommitLineData
f83d2997
KH
1;;; cperl-mode.el --- Perl code editing commands for Emacs
2
3;; Copyright (C) 1985, 86, 87, 91, 92, 93, 94, 95, 96, 1997
4;; Free Software Foundation, Inc.
5
6;; Author: Ilya Zakharevich and Bob Olson
7;; Maintainer: Ilya Zakharevich <ilya@math.ohio-state.edu>
8;; Keywords: languages, Perl
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
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
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;;; Corrections made by Ilya Zakharevich ilya@math.mps.ohio-state.edu
f83d2997
KH
28
29;;; Commentary:
30
31;;; You can either fine-tune the bells and whistles of this mode or
32;;; bulk enable them by putting
33
34;; (setq cperl-hairy t)
35
36;;; in your .emacs file. (Emacs rulers do not consider it politically
37;;; correct to make whistles enabled by default.)
38
39;;; DO NOT FORGET to read micro-docs (available from `Perl' menu) <<<<<<
40;;; or as help on variables `cperl-tips', `cperl-problems', <<<<<<
f94a632a 41;;; `cperl-praise', `cperl-speed'. <<<<<<
f83d2997
KH
42
43;;; The mode information (on C-h m) provides some customization help.
44;;; If you use font-lock feature of this mode, it is advisable to use
45;;; either lazy-lock-mode or fast-lock-mode. I prefer lazy-lock.
46
47;;; Faces used now: three faces for first-class and second-class keywords
48;;; and control flow words, one for each: comments, string, labels,
49;;; functions definitions and packages, arrays, hashes, and variable
50;;; definitions. If you do not see all these faces, your font-lock does
51;;; not define them, so you need to define them manually.
52
53;;; into your .emacs file.
54
55;;;; This mode supports font-lock, imenu and mode-compile. In the
56;;;; hairy version font-lock is on, but you should activate imenu
57;;;; yourself (note that mode-compile is not standard yet). Well, you
58;;;; can use imenu from keyboard anyway (M-x imenu), but it is better
59;;;; to bind it like that:
60
61;; (define-key global-map [M-S-down-mouse-3] 'imenu)
62
63;;; Code:
64
5bd52f0e 65;; Some macros are needed for `defcustom'
80585273
DL
66(eval-when-compile
67 (require 'font-lock)
68 (defvar msb-menu-cond)
69 (defvar gud-perldb-history)
70 (defvar font-lock-background-mode) ; not in Emacs
71 (defvar font-lock-display-type) ; ditto
72 (defconst cperl-xemacs-p (string-match "XEmacs\\|Lucid" emacs-version))
73 (defmacro cperl-is-face (arg) ; Takes quoted arg
74 (cond ((fboundp 'find-face)
75 `(find-face ,arg))
76 (;;(and (fboundp 'face-list)
77 ;; (face-list))
78 (fboundp 'face-list)
79 `(member ,arg (and (fboundp 'face-list)
80 (face-list))))
81 (t
82 `(boundp ,arg))))
83 (defmacro cperl-make-face (arg descr) ; Takes unquoted arg
84 (cond ((fboundp 'make-face)
85 `(make-face (quote ,arg)))
86 (t
ce22dd53 87 `(defvar ,arg (quote ,arg) ,descr))))
80585273
DL
88 (defmacro cperl-force-face (arg descr) ; Takes unquoted arg
89 `(progn
90 (or (cperl-is-face (quote ,arg))
91 (cperl-make-face ,arg ,descr))
92 (or (boundp (quote ,arg)) ; We use unquoted variants too
ce22dd53 93 (defvar ,arg (quote ,arg) ,descr))))
80585273
DL
94 (if cperl-xemacs-p
95 (defmacro cperl-etags-snarf-tag (file line)
b787fc05 96 `(progn
80585273
DL
97 (beginning-of-line 2)
98 (list ,file ,line)))
99 (defmacro cperl-etags-snarf-tag (file line)
100 `(etags-snarf-tag)))
101 (if cperl-xemacs-p
102 (defmacro cperl-etags-goto-tag-location (elt)
103 ;;(progn
104 ;; (switch-to-buffer (get-file-buffer (elt (, elt) 0)))
105 ;; (set-buffer (get-file-buffer (elt (, elt) 0)))
106 ;; Probably will not work due to some save-excursion???
107 ;; Or save-file-position?
108 ;; (message "Did I get to line %s?" (elt (, elt) 1))
109 `(goto-line (string-to-int (elt ,elt 1))))
110 ;;)
111 (defmacro cperl-etags-goto-tag-location (elt)
112 `(etags-goto-tag-location ,elt)))
113 (autoload 'tmm-prompt "tmm"))
5bd52f0e
RS
114
115(defun cperl-choose-color (&rest list)
116 (let (answer)
117 (while list
118 (or answer
119 (if (or (x-color-defined-p (car list))
120 (null (cdr list)))
121 (setq answer (car list))))
122 (setq list (cdr list)))
123 answer))
124
ccc3ce39
SE
125(defgroup cperl nil
126 "Major mode for editing Perl code."
127 :prefix "cperl-"
db133cb6
RS
128 :group 'languages
129 :version "20.3")
130
131(defgroup cperl-indentation-details nil
132 "Indentation."
133 :prefix "cperl-"
134 :group 'cperl)
135
136(defgroup cperl-affected-by-hairy nil
137 "Variables affected by `cperl-hairy'."
138 :prefix "cperl-"
139 :group 'cperl)
140
141(defgroup cperl-autoinsert-details nil
142 "Auto-insert tuneup."
143 :prefix "cperl-"
144 :group 'cperl)
145
146(defgroup cperl-faces nil
147 "Fontification colors."
148 :prefix "cperl-"
149 :group 'cperl)
150
151(defgroup cperl-speed nil
152 "Speed vs. validity tuneup."
153 :prefix "cperl-"
154 :group 'cperl)
155
156(defgroup cperl-help-system nil
157 "Help system tuneup."
158 :prefix "cperl-"
159 :group 'cperl)
ccc3ce39 160
f83d2997 161\f
ccc3ce39 162(defcustom cperl-extra-newline-before-brace nil
f83d2997
KH
163 "*Non-nil means that if, elsif, while, until, else, for, foreach
164and do constructs look like:
165
166 if ()
167 {
168 }
169
170instead of:
171
172 if () {
173 }
ccc3ce39
SE
174"
175 :type 'boolean
db133cb6
RS
176 :group 'cperl-autoinsert-details)
177
5c8b7eaf 178(defcustom cperl-extra-newline-before-brace-multiline
db133cb6
RS
179 cperl-extra-newline-before-brace
180 "*Non-nil means the same as `cperl-extra-newline-before-brace', but
181for constructs with multiline if/unless/while/until/for/foreach condition."
182 :type 'boolean
183 :group 'cperl-autoinsert-details)
ccc3ce39
SE
184
185(defcustom cperl-indent-level 2
186 "*Indentation of CPerl statements with respect to containing block."
187 :type 'integer
db133cb6 188 :group 'cperl-indentation-details)
f83d2997 189
ccc3ce39 190(defcustom cperl-lineup-step nil
f83d2997 191 "*`cperl-lineup' will always lineup at multiple of this number.
029cb4d5 192If nil, the value of `cperl-indent-level' will be used."
ccc3ce39 193 :type '(choice (const nil) integer)
db133cb6
RS
194 :group 'cperl-indentation-details)
195
ccc3ce39 196(defcustom cperl-brace-imaginary-offset 0
f83d2997
KH
197 "*Imagined indentation of a Perl open brace that actually follows a statement.
198An open brace following other text is treated as if it were this far
ccc3ce39
SE
199to the right of the start of its line."
200 :type 'integer
db133cb6 201 :group 'cperl-indentation-details)
ccc3ce39
SE
202
203(defcustom cperl-brace-offset 0
204 "*Extra indentation for braces, compared with other text in same context."
205 :type 'integer
db133cb6 206 :group 'cperl-indentation-details)
ccc3ce39
SE
207(defcustom cperl-label-offset -2
208 "*Offset of CPerl label lines relative to usual indentation."
209 :type 'integer
db133cb6 210 :group 'cperl-indentation-details)
ccc3ce39
SE
211(defcustom cperl-min-label-indent 1
212 "*Minimal offset of CPerl label lines."
213 :type 'integer
db133cb6 214 :group 'cperl-indentation-details)
ccc3ce39
SE
215(defcustom cperl-continued-statement-offset 2
216 "*Extra indent for lines not starting new statements."
217 :type 'integer
db133cb6 218 :group 'cperl-indentation-details)
ccc3ce39 219(defcustom cperl-continued-brace-offset 0
f83d2997 220 "*Extra indent for substatements that start with open-braces.
ccc3ce39
SE
221This is in addition to cperl-continued-statement-offset."
222 :type 'integer
db133cb6 223 :group 'cperl-indentation-details)
ccc3ce39
SE
224(defcustom cperl-close-paren-offset -1
225 "*Extra indent for substatements that start with close-parenthesis."
226 :type 'integer
db133cb6 227 :group 'cperl-indentation-details)
ccc3ce39
SE
228
229(defcustom cperl-auto-newline nil
f83d2997
KH
230 "*Non-nil means automatically newline before and after braces,
231and after colons and semicolons, inserted in CPerl code. The following
232\\[cperl-electric-backspace] will remove the inserted whitespace.
5c8b7eaf 233Insertion after colons requires both this variable and
ccc3ce39
SE
234`cperl-auto-newline-after-colon' set."
235 :type 'boolean
db133cb6 236 :group 'cperl-autoinsert-details)
f83d2997 237
6c389151
SM
238(defcustom cperl-autoindent-on-semi nil
239 "*Non-nil means automatically indent after insertion of (semi)colon.
240Active if `cperl-auto-newline' is false."
241 :type 'boolean
242 :group 'cperl-autoinsert-details)
243
ccc3ce39 244(defcustom cperl-auto-newline-after-colon nil
f83d2997 245 "*Non-nil means automatically newline even after colons.
ccc3ce39
SE
246Subject to `cperl-auto-newline' setting."
247 :type 'boolean
db133cb6 248 :group 'cperl-autoinsert-details)
f83d2997 249
ccc3ce39 250(defcustom cperl-tab-always-indent t
f83d2997 251 "*Non-nil means TAB in CPerl mode should always reindent the current line,
ccc3ce39
SE
252regardless of where in the line point is when the TAB command is used."
253 :type 'boolean
db133cb6 254 :group 'cperl-indentation-details)
f83d2997 255
ccc3ce39 256(defcustom cperl-font-lock nil
029cb4d5 257 "*Non-nil (and non-null) means CPerl buffers will use `font-lock-mode'.
ccc3ce39 258Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
259 :type '(choice (const null) boolean)
260 :group 'cperl-affected-by-hairy)
f83d2997 261
ccc3ce39 262(defcustom cperl-electric-lbrace-space nil
029cb4d5 263 "*Non-nil (and non-null) means { after $ should be preceded by ` '.
ccc3ce39 264Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
265 :type '(choice (const null) boolean)
266 :group 'cperl-affected-by-hairy)
f83d2997 267
ccc3ce39 268(defcustom cperl-electric-parens-string "({[]})<"
f83d2997 269 "*String of parentheses that should be electric in CPerl.
ccc3ce39
SE
270Closing ones are electric only if the region is highlighted."
271 :type 'string
db133cb6 272 :group 'cperl-affected-by-hairy)
f83d2997 273
ccc3ce39 274(defcustom cperl-electric-parens nil
f83d2997 275 "*Non-nil (and non-null) means parentheses should be electric in CPerl.
ccc3ce39 276Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
277 :type '(choice (const null) boolean)
278 :group 'cperl-affected-by-hairy)
279
280(defvar zmacs-regions) ; Avoid warning
281
5c8b7eaf 282(defcustom cperl-electric-parens-mark
f83d2997
KH
283 (and window-system
284 (or (and (boundp 'transient-mark-mode) ; For Emacs
285 transient-mark-mode)
286 (and (boundp 'zmacs-regions) ; For XEmacs
287 zmacs-regions)))
288 "*Not-nil means that electric parens look for active mark.
ccc3ce39
SE
289Default is yes if there is visual feedback on mark."
290 :type 'boolean
db133cb6 291 :group 'cperl-autoinsert-details)
f83d2997 292
ccc3ce39 293(defcustom cperl-electric-linefeed nil
f83d2997
KH
294 "*If true, LFD should be hairy in CPerl, otherwise C-c LFD is hairy.
295In any case these two mean plain and hairy linefeeds together.
ccc3ce39 296Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
297 :type '(choice (const null) boolean)
298 :group 'cperl-affected-by-hairy)
f83d2997 299
ccc3ce39 300(defcustom cperl-electric-keywords nil
f83d2997 301 "*Not-nil (and non-null) means keywords are electric in CPerl.
ccc3ce39 302Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
303 :type '(choice (const null) boolean)
304 :group 'cperl-affected-by-hairy)
ccc3ce39
SE
305
306(defcustom cperl-hairy nil
db133cb6 307 "*Not-nil means most of the bells and whistles are enabled in CPerl.
5c8b7eaf 308Affects: `cperl-font-lock', `cperl-electric-lbrace-space',
db133cb6
RS
309`cperl-electric-parens', `cperl-electric-linefeed', `cperl-electric-keywords',
310`cperl-info-on-command-no-prompt', `cperl-clobber-lisp-bindings',
311`cperl-lazy-help-time'."
ccc3ce39 312 :type 'boolean
db133cb6 313 :group 'cperl-affected-by-hairy)
ccc3ce39
SE
314
315(defcustom cperl-comment-column 32
316 "*Column to put comments in CPerl (use \\[cperl-indent] to lineup with code)."
317 :type 'integer
db133cb6 318 :group 'cperl-indentation-details)
ccc3ce39
SE
319
320(defcustom cperl-vc-header-alist '((SCCS "$sccs = '%W\%' ;")
321 (RCS "$rcs = ' $Id\$ ' ;"))
322 "*What to use as `vc-header-alist' in CPerl."
323 :type '(repeat (list symbol string))
324 :group 'cperl)
325
5c8b7eaf 326(defcustom cperl-clobber-mode-lists
5bd52f0e
RS
327 (not
328 (and
329 (boundp 'interpreter-mode-alist)
330 (assoc "miniperl" interpreter-mode-alist)
331 (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist)))
332 "*Whether to install us into `interpreter-' and `extension' mode lists."
333 :type 'boolean
334 :group 'cperl)
335
ccc3ce39 336(defcustom cperl-info-on-command-no-prompt nil
f83d2997
KH
337 "*Not-nil (and non-null) means not to prompt on C-h f.
338The opposite behaviour is always available if prefixed with C-c.
ccc3ce39 339Can be overwritten by `cperl-hairy' if nil."
db133cb6
RS
340 :type '(choice (const null) boolean)
341 :group 'cperl-affected-by-hairy)
342
343(defcustom cperl-clobber-lisp-bindings nil
344 "*Not-nil (and non-null) means not overwrite C-h f.
345The function is available on \\[cperl-info-on-command], \\[cperl-get-help].
346Can be overwritten by `cperl-hairy' if nil."
347 :type '(choice (const null) boolean)
348 :group 'cperl-affected-by-hairy)
f83d2997 349
ccc3ce39 350(defcustom cperl-lazy-help-time nil
db133cb6
RS
351 "*Not-nil (and non-null) means to show lazy help after given idle time.
352Can be overwritten by `cperl-hairy' to be 5 sec if nil."
300f7bb3 353 :type '(choice (const null) (const nil) integer)
db133cb6 354 :group 'cperl-affected-by-hairy)
f83d2997 355
ccc3ce39 356(defcustom cperl-pod-face 'font-lock-comment-face
80585273 357 "*Face for pod highlighting."
ccc3ce39 358 :type 'face
db133cb6 359 :group 'cperl-faces)
f83d2997 360
ccc3ce39 361(defcustom cperl-pod-head-face 'font-lock-variable-name-face
80585273 362 "*Face for pod highlighting.
ccc3ce39
SE
363Font for POD headers."
364 :type 'face
db133cb6 365 :group 'cperl-faces)
f83d2997 366
ccc3ce39 367(defcustom cperl-here-face 'font-lock-string-face
80585273 368 "*Face for here-docs highlighting."
ccc3ce39 369 :type 'face
db133cb6 370 :group 'cperl-faces)
f83d2997 371
ac6857fb 372(defcustom cperl-invalid-face 'underline
80585273
DL
373 "*Face for highlighting trailing whitespace."
374 :type 'face
ac6857fb 375 :version "21.1"
5bd52f0e
RS
376 :group 'cperl-faces)
377
ccc3ce39
SE
378(defcustom cperl-pod-here-fontify '(featurep 'font-lock)
379 "*Not-nil after evaluation means to highlight pod and here-docs sections."
380 :type 'boolean
db133cb6 381 :group 'cperl-faces)
f83d2997 382
5bd52f0e
RS
383(defcustom cperl-fontify-m-as-s t
384 "*Not-nil means highlight 1arg regular expressions operators same as 2arg."
385 :type 'boolean
386 :group 'cperl-faces)
387
6c389151
SM
388(defcustom cperl-highlight-variables-indiscriminately nil
389 "*Non-nil means perform additional highlighting on variables.
390Currently only changes how scalar variables are highlighted.
391Note that that variable is only read at initialization time for
392the variable `cperl-font-lock-keywords-2', so changing it after you've
f94a632a 393entered CPerl mode the first time will have no effect."
6c389151
SM
394 :type 'boolean
395 :group 'cperl)
396
ccc3ce39 397(defcustom cperl-pod-here-scan t
f83d2997 398 "*Not-nil means look for pod and here-docs sections during startup.
ccc3ce39
SE
399You can always make lookup from menu or using \\[cperl-find-pods-heres]."
400 :type 'boolean
db133cb6 401 :group 'cperl-speed)
f83d2997 402
6c389151
SM
403(defcustom cperl-regexp-scan t
404 "*Not-nil means make marking of regular expression more thorough.
405Effective only with `cperl-pod-here-scan'. Not implemented yet."
406 :type 'boolean
407 :group 'cperl-speed)
408
ccc3ce39 409(defcustom cperl-imenu-addback nil
f83d2997 410 "*Not-nil means add backreferences to generated `imenu's.
db133cb6 411May require patched `imenu' and `imenu-go'. Obsolete."
ccc3ce39 412 :type 'boolean
db133cb6 413 :group 'cperl-help-system)
f83d2997 414
ccc3ce39
SE
415(defcustom cperl-max-help-size 66
416 "*Non-nil means shrink-wrapping of info-buffer allowed up to these percents."
417 :type '(choice integer (const nil))
db133cb6 418 :group 'cperl-help-system)
f83d2997 419
ccc3ce39
SE
420(defcustom cperl-shrink-wrap-info-frame t
421 "*Non-nil means shrink-wrapping of info-buffer-frame allowed."
422 :type 'boolean
db133cb6 423 :group 'cperl-help-system)
f83d2997 424
ccc3ce39 425(defcustom cperl-info-page "perl"
f83d2997 426 "*Name of the info page containing perl docs.
ccc3ce39
SE
427Older version of this page was called `perl5', newer `perl'."
428 :type 'string
db133cb6 429 :group 'cperl-help-system)
f83d2997 430
5c8b7eaf 431(defcustom cperl-use-syntax-table-text-property
f83d2997 432 (boundp 'parse-sexp-lookup-properties)
ccc3ce39
SE
433 "*Non-nil means CPerl sets up and uses `syntax-table' text property."
434 :type 'boolean
db133cb6 435 :group 'cperl-speed)
f83d2997 436
5c8b7eaf 437(defcustom cperl-use-syntax-table-text-property-for-tags
f83d2997 438 cperl-use-syntax-table-text-property
ccc3ce39
SE
439 "*Non-nil means: set up and use `syntax-table' text property generating TAGS."
440 :type 'boolean
db133cb6 441 :group 'cperl-speed)
ccc3ce39
SE
442
443(defcustom cperl-scan-files-regexp "\\.\\([pP][Llm]\\|xs\\)$"
444 "*Regexp to match files to scan when generating TAGS."
445 :type 'regexp
446 :group 'cperl)
447
8937f01b
RS
448(defcustom cperl-noscan-files-regexp
449 "/\\(\\.\\.?\\|SCCS\\|RCS\\|CVS\\|blib\\)$"
ccc3ce39
SE
450 "*Regexp to match files/dirs to skip when generating TAGS."
451 :type 'regexp
452 :group 'cperl)
453
454(defcustom cperl-regexp-indent-step nil
455 "*Indentation used when beautifying regexps.
029cb4d5 456If nil, the value of `cperl-indent-level' will be used."
ccc3ce39 457 :type '(choice integer (const nil))
db133cb6 458 :group 'cperl-indentation-details)
ccc3ce39
SE
459
460(defcustom cperl-indent-left-aligned-comments t
461 "*Non-nil means that the comment starting in leftmost column should indent."
462 :type 'boolean
db133cb6 463 :group 'cperl-indentation-details)
ccc3ce39 464
8f222248 465(defcustom cperl-under-as-char nil
ccc3ce39
SE
466 "*Non-nil means that the _ (underline) should be treated as word char."
467 :type 'boolean
468 :group 'cperl)
f83d2997 469
db133cb6
RS
470(defcustom cperl-extra-perl-args ""
471 "*Extra arguments to use when starting Perl.
472Currently used with `cperl-check-syntax' only."
473 :type 'string
474 :group 'cperl)
475
476(defcustom cperl-message-electric-keyword t
477 "*Non-nil means that the `cperl-electric-keyword' prints a help message."
478 :type 'boolean
479 :group 'cperl-help-system)
480
481(defcustom cperl-indent-region-fix-constructs 1
482 "*Amount of space to insert between `}' and `else' or `elsif'
483in `cperl-indent-region'. Set to nil to leave as is. Values other
484than 1 and nil will probably not work."
485 :type '(choice (const nil) (const 1))
486 :group 'cperl-indentation-details)
487
488(defcustom cperl-break-one-line-blocks-when-indent t
489 "*Non-nil means that one-line if/unless/while/until/for/foreach BLOCKs
2022c546 490need to be reformatted into multiline ones when indenting a region."
db133cb6
RS
491 :type 'boolean
492 :group 'cperl-indentation-details)
493
494(defcustom cperl-fix-hanging-brace-when-indent t
495 "*Non-nil means that BLOCK-end `}' may be put on a separate line
5c8b7eaf 496when indenting a region.
db133cb6
RS
497Braces followed by else/elsif/while/until are excepted."
498 :type 'boolean
499 :group 'cperl-indentation-details)
500
501(defcustom cperl-merge-trailing-else t
5c8b7eaf 502 "*Non-nil means that BLOCK-end `}' followed by else/elsif/continue
db133cb6
RS
503may be merged to be on the same line when indenting a region."
504 :type 'boolean
505 :group 'cperl-indentation-details)
506
6c389151
SM
507(defcustom cperl-indent-parens-as-block nil
508 "*Non-nil means that non-block ()-, {}- and []-groups are indented as blocks,
509but for trailing \",\" inside the group, which won't increase indentation.
510One should tune up `cperl-close-paren-offset' as well."
511 :type 'boolean
512 :group 'cperl-indentation-details)
513
514(defcustom cperl-syntaxify-by-font-lock
515 (and window-system
5bd52f0e 516 (boundp 'parse-sexp-lookup-properties))
6c389151 517 "*Non-nil means that CPerl uses `font-lock's routines for syntaxification."
5bd52f0e
RS
518 :type '(choice (const message) boolean)
519 :group 'cperl-speed)
520
521(defcustom cperl-syntaxify-unwind
522 t
f94a632a 523 "*Non-nil means that CPerl unwinds to a start of a long construction
5bd52f0e 524when syntaxifying a chunk of buffer."
db133cb6
RS
525 :type 'boolean
526 :group 'cperl-speed)
527
5bd52f0e
RS
528(defcustom cperl-ps-print-face-properties
529 '((font-lock-keyword-face nil nil bold shadow)
530 (font-lock-variable-name-face nil nil bold)
531 (font-lock-function-name-face nil nil bold italic box)
532 (font-lock-constant-face nil "LightGray" bold)
533 (cperl-array-face nil "LightGray" bold underline)
534 (cperl-hash-face nil "LightGray" bold italic underline)
535 (font-lock-comment-face nil "LightGray" italic)
536 (font-lock-string-face nil nil italic underline)
537 (cperl-nonoverridable-face nil nil italic underline)
538 (font-lock-type-face nil nil underline)
539 (underline nil "LightGray" strikeout))
540 "List given as an argument to `ps-extend-face-list' in `cperl-ps-print'."
5c8b7eaf 541 :type '(repeat (cons symbol
5bd52f0e
RS
542 (cons (choice (const nil) string)
543 (cons (choice (const nil) string)
544 (repeat symbol)))))
545 :group 'cperl-faces)
546
5cc679ab
JB
547(defvar cperl-dark-background
548 (cperl-choose-color "navy" "os2blue" "darkgreen"))
549(defvar cperl-dark-foreground
550 (cperl-choose-color "orchid1" "orange"))
551
552(defface cperl-nonoverridable-face
553 `((((class grayscale) (background light))
554 (:background "Gray90" :slant italic :underline t))
555 (((class grayscale) (background dark))
556 (:foreground "Gray80" :slant italic :underline t :weight bold))
557 (((class color) (background light))
558 (:foreground "chartreuse3"))
559 (((class color) (background dark))
560 (:foreground ,cperl-dark-foreground))
561 (t (:weight bold :underline t)))
562 "Font Lock mode face used to highlight array names."
563 :group 'cperl-faces)
564
565(defface cperl-array-face
566 `((((class grayscale) (background light))
567 (:background "Gray90" :weight bold))
568 (((class grayscale) (background dark))
569 (:foreground "Gray80" :weight bold))
570 (((class color) (background light))
571 (:foreground "Blue" :background "lightyellow2" :weight bold))
572 (((class color) (background dark))
573 (:foreground "yellow" :background ,cperl-dark-background :weight bold))
574 (t (:weight bold)))
575 "Font Lock mode face used to highlight array names."
576 :group 'cperl-faces)
577
578(defface cperl-hash-face
579 `((((class grayscale) (background light))
580 (:background "Gray90" :weight bold :slant italic))
581 (((class grayscale) (background dark))
582 (:foreground "Gray80" :weight bold :slant italic))
583 (((class color) (background light))
584 (:foreground "Red" :background "lightyellow2" :weight bold :slant italic))
585 (((class color) (background dark))
586 (:foreground "Red" :background ,cperl-dark-background :weight bold :slant italic))
587 (t (:weight bold :slant italic)))
588 "Font Lock mode face used to highlight hash names."
589 :group 'cperl-faces)
5bd52f0e 590
f83d2997
KH
591\f
592
593;;; Short extra-docs.
594
595(defvar cperl-tips 'please-ignore-this-line
596 "Get newest version of this package from
597 ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs
598and/or
599 ftp://ftp.math.ohio-state.edu/pub/users/ilya/perl
db133cb6
RS
600Subdirectory `cperl-mode' may contain yet newer development releases and/or
601patches to related files.
f83d2997 602
5bd52f0e
RS
603For best results apply to an older Emacs the patches from
604 ftp://ftp.math.ohio-state.edu/pub/users/ilya/cperl-mode/patches
8e3acc66
RS
605\(this upgrades syntax-parsing abilities of Emaxen v19.34 and
606v20.2 up to the level of Emacs v20.3 - a must for a good Perl
607mode.)
5bd52f0e 608
f83d2997
KH
609Get support packages choose-color.el (or font-lock-extra.el before
61019.30), imenu-go.el from the same place. \(Look for other files there
611too... ;-). Get a patch for imenu.el in 19.29. Note that for 19.30 and
5c8b7eaf 612later you should use choose-color.el *instead* of font-lock-extra.el
f83d2997
KH
613\(and you will not get smart highlighting in C :-().
614
615Note that to enable Compile choices in the menu you need to install
616mode-compile.el.
617
5efe6a56
SM
618If your Emacs does not default to `cperl-mode' on Perl files, and you
619want it to: put the following into your .emacs file:
620
621 (defalias 'perl-mode 'cperl-mode)
622
623Get perl5-info from
f83d2997
KH
624 $CPAN/doc/manual/info/perl-info.tar.gz
625older version was on
626 http://www.metronet.com:70/9/perlinfo/perl5/manual/perl5-info.tar.gz
627
628If you use imenu-go, run imenu on perl5-info buffer (you can do it
5bd52f0e
RS
629from Perl menu). If many files are related, generate TAGS files from
630Tools/Tags submenu in Perl menu.
f83d2997
KH
631
632If some class structure is too complicated, use Tools/Hierarchy-view
029cb4d5 633from Perl menu, or hierarchic view of imenu. The second one uses the
f83d2997 634current buffer only, the first one requires generation of TAGS from
5bd52f0e
RS
635Perl/Tools/Tags menu beforehand.
636
637Run Perl/Tools/Insert-spaces-if-needed to fix your lazy typing.
638
639Switch auto-help on/off with Perl/Tools/Auto-help.
640
641Though with contemporary Emaxen CPerl mode should maintain the correct
642parsing of Perl even when editing, sometimes it may be lost. Fix this by
643
029cb4d5 644 \\[normal-mode]
f83d2997 645
5bd52f0e 646In cases of more severe confusion sometimes it is helpful to do
f83d2997 647
029cb4d5
SM
648 \\[load-library] cperl-mode RET
649 \\[normal-mode]
f83d2997 650
5bd52f0e
RS
651Before reporting (non-)problems look in the problem section of online
652micro-docs on what I know about CPerl problems.")
f83d2997
KH
653
654(defvar cperl-problems 'please-ignore-this-line
f94a632a
RS
655 "Description of problems in CPerl mode.
656Some faces will not be shown on some versions of Emacs unless you
bab27c0c
RS
657install choose-color.el, available from
658 ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs/
659
6c389151
SM
660`fill-paragraph' on a comment may leave the point behind the
661paragraph. Parsing of lines with several <<EOF is not implemented
662yet.
663
8e3acc66 664Emacs had a _very_ restricted syntax parsing engine until version
5bd52f0e 66520.1. Most problems below are corrected starting from this version of
8e3acc66
RS
666Emacs, and all of them should be fixed in version 20.3. (Or apply
667patches to Emacs 19.33/34 - see tips.)
5bd52f0e 668
6c389151
SM
669Note that even with newer Emacsen in some very rare cases the details
670of interaction of `font-lock' and syntaxification may be not cleaned
671up yet. You may get slightly different colors basing on the order of
672fontification and syntaxification. Say, the initial faces is correct,
673but editing the buffer breaks this.
f83d2997 674
db133cb6
RS
675Even with older Emacsen CPerl mode tries to corrects some Emacs
676misunderstandings, however, for efficiency reasons the degree of
677correction is different for different operations. The partially
678corrected problems are: POD sections, here-documents, regexps. The
679operations are: highlighting, indentation, electric keywords, electric
680braces.
f83d2997
KH
681
682This may be confusing, since the regexp s#//#/#\; may be highlighted
683as a comment, but it will be recognized as a regexp by the indentation
684code. Or the opposite case, when a pod section is highlighted, but
685may break the indentation of the following code (though indentation
686should work if the balance of delimiters is not broken by POD).
687
688The main trick (to make $ a \"backslash\") makes constructions like
689${aaa} look like unbalanced braces. The only trick I can think of is
5c8b7eaf 690to insert it as $ {aaa} (legal in perl5, not in perl4).
f83d2997
KH
691
692Similar problems arise in regexps, when /(\\s|$)/ should be rewritten
db133cb6
RS
693as /($|\\s)/. Note that such a transposition is not always possible.
694
5bd52f0e 695The solution is to upgrade your Emacs or patch an older one. Note
8e3acc66 696that Emacs 20.2 has some bugs related to `syntax-table' text
5bd52f0e
RS
697properties. Patches are available on the main CPerl download site,
698and on CPAN.
db133cb6
RS
699
700If these bugs cannot be fixed on your machine (say, you have an inferior
701environment and cannot recompile), you may still disable all the fancy stuff
702via `cperl-use-syntax-table-text-property'." )
f83d2997 703
f83d2997 704(defvar cperl-praise 'please-ignore-this-line
8e3acc66 705 "Advantages of CPerl mode.
f83d2997
KH
706
7070) It uses the newest `syntax-table' property ;-);
708
7091) It does 99% of Perl syntax correct (as opposed to 80-90% in Perl
5c8b7eaf 710mode - but the latter number may have improved too in last years) even
5bd52f0e
RS
711with old Emaxen which do not support `syntax-table' property.
712
713When using `syntax-table' property for syntax assist hints, it should
714handle 99.995% of lines correct - or somesuch. It automatically
715updates syntax assist hints when you edit your script.
f83d2997 716
bab27c0c 7172) It is generally believed to be \"the most user-friendly Emacs
f83d2997
KH
718package\" whatever it may mean (I doubt that the people who say similar
719things tried _all_ the rest of Emacs ;-), but this was not a lonely
720voice);
721
7223) Everything is customizable, one-by-one or in a big sweep;
723
7244) It has many easily-accessable \"tools\":
725 a) Can run program, check syntax, start debugger;
726 b) Can lineup vertically \"middles\" of rows, like `=' in
727 a = b;
728 cc = d;
729 c) Can insert spaces where this impoves readability (in one
730 interactive sweep over the buffer);
731 d) Has support for imenu, including:
732 1) Separate unordered list of \"interesting places\";
733 2) Separate TOC of POD sections;
734 3) Separate list of packages;
735 4) Hierarchical view of methods in (sub)packages;
736 5) and functions (by the full name - with package);
737 e) Has an interface to INFO docs for Perl; The interface is
738 very flexible, including shrink-wrapping of
739 documentation buffer/frame;
740 f) Has a builtin list of one-line explanations for perl constructs.
741 g) Can show these explanations if you stay long enough at the
742 corresponding place (or on demand);
743 h) Has an enhanced fontification (using 3 or 4 additional faces
744 comparing to font-lock - basically, different
745 namespaces in Perl have different colors);
746 i) Can construct TAGS basing on its knowledge of Perl syntax,
747 the standard menu has 6 different way to generate
db133cb6 748 TAGS (if \"by directory\", .xs files - with C-language
f83d2997
KH
749 bindings - are included in the scan);
750 j) Can build a hierarchical view of classes (via imenu) basing
751 on generated TAGS file;
752 k) Has electric parentheses, electric newlines, uses Abbrev
753 for electric logical constructs
754 while () {}
755 with different styles of expansion (context sensitive
756 to be not so bothering). Electric parentheses behave
757 \"as they should\" in a presence of a visible region.
758 l) Changes msb.el \"on the fly\" to insert a group \"Perl files\";
db133cb6
RS
759 m) Can convert from
760 if (A) { B }
761 to
762 B if A;
f83d2997 763
5bd52f0e 764 n) Highlights (by user-choice) either 3-delimiters constructs
6c389151
SM
765 (such as tr/a/b/), or regular expressions and `y/tr';
766 o) Highlights trailing whitespace;
767 p) Is able to manipulate Perl Regular Expressions to ease
768 conversion to a more readable form.
5bd52f0e 769
f83d2997
KH
7705) The indentation engine was very smart, but most of tricks may be
771not needed anymore with the support for `syntax-table' property. Has
772progress indicator for indentation (with `imenu' loaded).
773
5c8b7eaf 7746) Indent-region improves inline-comments as well; also corrects
db133cb6 775whitespace *inside* the conditional/loop constructs.
f83d2997
KH
776
7777) Fill-paragraph correctly handles multi-line comments;
db133cb6
RS
778
7798) Can switch to different indentation styles by one command, and restore
780the settings present before the switch.
781
5c8b7eaf 7829) When doing indentation of control constructs, may correct
db133cb6 783line-breaks/spacing between elements of the construct.
029cb4d5
SM
784
78510) Uses a linear-time algorith for indentation of regions (on Emaxen with
786capable syntax engines).
db133cb6
RS
787")
788
789(defvar cperl-speed 'please-ignore-this-line
790 "This is an incomplete compendium of what is available in other parts
791of CPerl documentation. (Please inform me if I skept anything.)
792
793There is a perception that CPerl is slower than alternatives. This part
794of documentation is designed to overcome this misconception.
795
796*By default* CPerl tries to enable the most comfortable settings.
797From most points of view, correctly working package is infinitely more
798comfortable than a non-correctly working one, thus by default CPerl
799prefers correctness over speed. Below is the guide how to change
800settings if your preferences are different.
801
802A) Speed of loading the file. When loading file, CPerl may perform a
803scan which indicates places which cannot be parsed by primitive Emacs
804syntax-parsing routines, and marks them up so that either
805
806 A1) CPerl may work around these deficiencies (for big chunks, mostly
807 PODs and HERE-documents), or
808 A2) On capable Emaxen CPerl will use improved syntax-handlings
809 which reads mark-up hints directly.
810
811 The scan in case A2 is much more comprehensive, thus may be slower.
812
813 User can disable syntax-engine-helping scan of A2 by setting
814 `cperl-use-syntax-table-text-property'
815 variable to nil (if it is set to t).
816
817 One can disable the scan altogether (both A1 and A2) by setting
818 `cperl-pod-here-scan'
819 to nil.
820
5c8b7eaf 821B) Speed of editing operations.
db133cb6
RS
822
823 One can add a (minor) speedup to editing operations by setting
824 `cperl-use-syntax-table-text-property'
825 variable to nil (if it is set to t). This will disable
826 syntax-engine-helping scan, thus will make many more Perl
827 constructs be wrongly recognized by CPerl, thus may lead to
828 wrongly matched parentheses, wrong indentation, etc.
5bd52f0e
RS
829
830 One can unset `cperl-syntaxify-unwind'. This might speed up editing
831 of, say, long POD sections.
f83d2997
KH
832")
833
5bd52f0e
RS
834(defvar cperl-tips-faces 'please-ignore-this-line
835 "CPerl mode uses following faces for highlighting:
836
8661c643
DL
837 `cperl-array-face' Array names
838 `cperl-hash-face' Hash names
839 `font-lock-comment-face' Comments, PODs and whatever is considered
5bd52f0e 840 syntaxically to be not code
8661c643 841 `font-lock-constant-face' HERE-doc delimiters, labels, delimiters of
5bd52f0e 842 2-arg operators s/y/tr/ or of RExen,
8661c643 843 `font-lock-function-name-face' Special-cased m// and s//foo/, _ as
5bd52f0e
RS
844 a target of a file tests, file tests,
845 subroutine names at the moment of definition
846 (except those conflicting with Perl operators),
847 package names (when recognized), format names
8661c643
DL
848 `font-lock-keyword-face' Control flow switch constructs, declarators
849 `cperl-nonoverridable-face' Non-overridable keywords, modifiers of RExen
850 `font-lock-string-face' Strings, qw() constructs, RExen, POD sections,
5bd52f0e
RS
851 literal parts and the terminator of formats
852 and whatever is syntaxically considered
853 as string literals
8661c643
DL
854 `font-lock-type-face' Overridable keywords
855 `font-lock-variable-name-face' Variable declarations, indirect array and
5bd52f0e 856 hash names, POD headers/item names
8661c643 857 `cperl-invalid-face' Trailing whitespace
5bd52f0e
RS
858
859Note that in several situations the highlighting tries to inform about
860possible confusion, such as different colors for function names in
861declarations depending on what they (do not) override, or special cases
862m// and s/// which do not do what one would expect them to do.
863
5c8b7eaf 864Help with best setup of these faces for printout requested (for each of
5bd52f0e
RS
865the faces: please specify bold, italic, underline, shadow and box.)
866
867\(Not finished.)")
868
f83d2997
KH
869\f
870
871;;; Portability stuff:
872
db133cb6
RS
873(defconst cperl-xemacs-p (string-match "XEmacs\\|Lucid" emacs-version))
874
f83d2997 875(defmacro cperl-define-key (emacs-key definition &optional xemacs-key)
b787fc05
GM
876 `(define-key cperl-mode-map
877 ,(if xemacs-key
878 `(if cperl-xemacs-p ,xemacs-key ,emacs-key)
879 emacs-key)
880 ,definition))
f83d2997
KH
881
882(defvar cperl-del-back-ch
883 (car (append (where-is-internal 'delete-backward-char)
884 (where-is-internal 'backward-delete-char-untabify)))
029cb4d5 885 "Character generated by key bound to `delete-backward-char'.")
f83d2997 886
5c8b7eaf 887(and (vectorp cperl-del-back-ch) (= (length cperl-del-back-ch) 1)
f83d2997
KH
888 (setq cperl-del-back-ch (aref cperl-del-back-ch 0)))
889
db133cb6 890(defun cperl-mark-active () (mark)) ; Avoid undefined warning
f83d2997
KH
891(if cperl-xemacs-p
892 (progn
893 ;; "Active regions" are on: use region only if active
894 ;; "Active regions" are off: use region unconditionally
895 (defun cperl-use-region-p ()
db133cb6 896 (if zmacs-regions (mark) t)))
f83d2997
KH
897 (defun cperl-use-region-p ()
898 (if transient-mark-mode mark-active t))
899 (defun cperl-mark-active () mark-active))
900
901(defsubst cperl-enable-font-lock ()
902 (or cperl-xemacs-p window-system))
903
db133cb6
RS
904(defun cperl-putback-char (c) ; Emacs 19
905 (set 'unread-command-events (list c))) ; Avoid undefined warning
906
f83d2997
KH
907(if (boundp 'unread-command-events)
908 (if cperl-xemacs-p
909 (defun cperl-putback-char (c) ; XEmacs >= 19.12
db133cb6 910 (setq unread-command-events (list (eval '(character-to-event c))))))
f83d2997 911 (defun cperl-putback-char (c) ; XEmacs <= 19.11
db133cb6 912 (set 'unread-command-event (eval '(character-to-event c))))) ; Avoid warnings
f83d2997
KH
913
914(or (fboundp 'uncomment-region)
915 (defun uncomment-region (beg end)
916 (interactive "r")
917 (comment-region beg end -1)))
918
919(defvar cperl-do-not-fontify
920 (if (string< emacs-version "19.30")
921 'fontified
922 'lazy-lock)
923 "Text property which inhibits refontification.")
924
5bd52f0e
RS
925(defsubst cperl-put-do-not-fontify (from to &optional post)
926 ;; If POST, do not do it with postponed fontification
927 (if (and post cperl-syntaxify-by-font-lock)
928 nil
f83d2997 929 (put-text-property (max (point-min) (1- from))
5bd52f0e 930 to cperl-do-not-fontify t)))
f83d2997 931
ccc3ce39 932(defcustom cperl-mode-hook nil
f94a632a 933 "Hook run by CPerl mode."
ccc3ce39
SE
934 :type 'hook
935 :group 'cperl)
f83d2997 936
db133cb6
RS
937(defvar cperl-syntax-state nil)
938(defvar cperl-syntax-done-to nil)
5bd52f0e 939(defvar cperl-emacs-can-parse (> (length (save-excursion
ce22dd53 940 (parse-partial-sexp (point) (point)))) 9))
db133cb6
RS
941\f
942;; Make customization possible "in reverse"
943(defsubst cperl-val (symbol &optional default hairy)
944 (cond
945 ((eq (symbol-value symbol) 'null) default)
946 (cperl-hairy (or hairy t))
947 (t (symbol-value symbol))))
f83d2997
KH
948\f
949;;; Probably it is too late to set these guys already, but it can help later:
950
5bd52f0e 951;;;(and cperl-clobber-mode-lists
f83d2997
KH
952;;;(setq auto-mode-alist
953;;; (append '(("\\.\\([pP][Llm]\\|al\\)$" . perl-mode)) auto-mode-alist ))
954;;;(and (boundp 'interpreter-mode-alist)
955;;; (setq interpreter-mode-alist (append interpreter-mode-alist
5bd52f0e 956;;; '(("miniperl" . perl-mode))))))
80585273
DL
957(eval-when-compile
958 (condition-case nil
959 (require 'imenu)
960 (error nil))
961 (condition-case nil
962 (require 'easymenu)
963 (error nil))
964 (condition-case nil
965 (require 'etags)
966 (error nil))
967 (condition-case nil
968 (require 'timer)
969 (error nil))
970 (condition-case nil
971 (require 'man)
972 (error nil))
973 (condition-case nil
974 (require 'info)
975 (error nil))
976 (if (fboundp 'ps-extend-face-list)
977 (defmacro cperl-ps-extend-face-list (arg)
978 `(ps-extend-face-list ,arg))
979 (defmacro cperl-ps-extend-face-list (arg)
e8af40ee 980 `(error "This version of Emacs has no `ps-extend-face-list'")))
80585273
DL
981 ;; Calling `cperl-enable-font-lock' below doesn't compile on XEmacs,
982 ;; macros instead of defsubsts don't work on Emacs, so we do the
983 ;; expansion manually. Any other suggestions?
984 (require 'cl))
f83d2997
KH
985
986(defvar cperl-mode-abbrev-table nil
f94a632a 987 "Abbrev table in use in CPerl mode buffers.")
f83d2997
KH
988
989(add-hook 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-")))
990
991(defvar cperl-mode-map () "Keymap used in CPerl mode.")
992
993(if cperl-mode-map nil
994 (setq cperl-mode-map (make-sparse-keymap))
995 (cperl-define-key "{" 'cperl-electric-lbrace)
996 (cperl-define-key "[" 'cperl-electric-paren)
997 (cperl-define-key "(" 'cperl-electric-paren)
998 (cperl-define-key "<" 'cperl-electric-paren)
999 (cperl-define-key "}" 'cperl-electric-brace)
1000 (cperl-define-key "]" 'cperl-electric-rparen)
1001 (cperl-define-key ")" 'cperl-electric-rparen)
1002 (cperl-define-key ";" 'cperl-electric-semi)
1003 (cperl-define-key ":" 'cperl-electric-terminator)
1004 (cperl-define-key "\C-j" 'newline-and-indent)
1005 (cperl-define-key "\C-c\C-j" 'cperl-linefeed)
db133cb6 1006 (cperl-define-key "\C-c\C-t" 'cperl-invert-if-unless)
f83d2997
KH
1007 (cperl-define-key "\C-c\C-a" 'cperl-toggle-auto-newline)
1008 (cperl-define-key "\C-c\C-k" 'cperl-toggle-abbrev)
db133cb6
RS
1009 (cperl-define-key "\C-c\C-w" 'cperl-toggle-construct-fix)
1010 (cperl-define-key "\C-c\C-f" 'auto-fill-mode)
f83d2997 1011 (cperl-define-key "\C-c\C-e" 'cperl-toggle-electric)
db133cb6 1012 (cperl-define-key "\C-c\C-ha" 'cperl-toggle-autohelp)
f83d2997
KH
1013 (cperl-define-key "\e\C-q" 'cperl-indent-exp) ; Usually not bound
1014 (cperl-define-key [?\C-\M-\|] 'cperl-lineup
1015 [(control meta |)])
1016 ;;(cperl-define-key "\M-q" 'cperl-fill-paragraph)
1017 ;;(cperl-define-key "\e;" 'cperl-indent-for-comment)
1018 (cperl-define-key "\177" 'cperl-electric-backspace)
1019 (cperl-define-key "\t" 'cperl-indent-command)
1020 ;; don't clobber the backspace binding:
db133cb6
RS
1021 (cperl-define-key "\C-c\C-hF" 'cperl-info-on-command
1022 [(control c) (control h) F])
db133cb6
RS
1023 (if (cperl-val 'cperl-clobber-lisp-bindings)
1024 (progn
1025 (cperl-define-key "\C-hf"
1026 ;;(concat (char-to-string help-char) "f") ; does not work
1027 'cperl-info-on-command
1028 [(control h) f])
1029 (cperl-define-key "\C-hv"
1030 ;;(concat (char-to-string help-char) "v") ; does not work
1031 'cperl-get-help
5bd52f0e
RS
1032 [(control h) v])
1033 (cperl-define-key "\C-c\C-hf"
1034 ;;(concat (char-to-string help-char) "f") ; does not work
1035 (key-binding "\C-hf")
1036 [(control c) (control h) f])
1037 (cperl-define-key "\C-c\C-hv"
1038 ;;(concat (char-to-string help-char) "v") ; does not work
1039 (key-binding "\C-hv")
1040 [(control c) (control h) v]))
1041 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-current-command
1042 [(control c) (control h) f])
1043 (cperl-define-key "\C-c\C-hv"
1044 ;;(concat (char-to-string help-char) "v") ; does not work
1045 'cperl-get-help
1046 [(control c) (control h) v]))
5c8b7eaf 1047 (if (and cperl-xemacs-p
f83d2997
KH
1048 (<= emacs-minor-version 11) (<= emacs-major-version 19))
1049 (progn
1050 ;; substitute-key-definition is usefulness-deenhanced...
1051 (cperl-define-key "\M-q" 'cperl-fill-paragraph)
1052 (cperl-define-key "\e;" 'cperl-indent-for-comment)
1053 (cperl-define-key "\e\C-\\" 'cperl-indent-region))
1054 (substitute-key-definition
1055 'indent-sexp 'cperl-indent-exp
1056 cperl-mode-map global-map)
1057 (substitute-key-definition
1058 'fill-paragraph 'cperl-fill-paragraph
1059 cperl-mode-map global-map)
1060 (substitute-key-definition
1061 'indent-region 'cperl-indent-region
1062 cperl-mode-map global-map)
1063 (substitute-key-definition
1064 'indent-for-comment 'cperl-indent-for-comment
1065 cperl-mode-map global-map)))
1066
1067(defvar cperl-menu)
db133cb6
RS
1068(defvar cperl-lazy-installed)
1069(defvar cperl-old-style nil)
f83d2997
KH
1070(condition-case nil
1071 (progn
1072 (require 'easymenu)
1073 (easy-menu-define cperl-menu cperl-mode-map "Menu for CPerl mode"
1074 '("Perl"
1075 ["Beginning of function" beginning-of-defun t]
1076 ["End of function" end-of-defun t]
1077 ["Mark function" mark-defun t]
1078 ["Indent expression" cperl-indent-exp t]
1079 ["Fill paragraph/comment" cperl-fill-paragraph t]
1080 "----"
1081 ["Line up a construction" cperl-lineup (cperl-use-region-p)]
6c389151 1082 ["Invert if/unless/while etc" cperl-invert-if-unless t]
db133cb6
RS
1083 ("Regexp"
1084 ["Beautify" cperl-beautify-regexp
1085 cperl-use-syntax-table-text-property]
6c389151
SM
1086 ["Beautify one level deep" (cperl-beautify-regexp 1)
1087 cperl-use-syntax-table-text-property]
db133cb6
RS
1088 ["Beautify a group" cperl-beautify-level
1089 cperl-use-syntax-table-text-property]
6c389151
SM
1090 ["Beautify a group one level deep" (cperl-beautify-level 1)
1091 cperl-use-syntax-table-text-property]
db133cb6
RS
1092 ["Contract a group" cperl-contract-level
1093 cperl-use-syntax-table-text-property]
1094 ["Contract groups" cperl-contract-levels
1095 cperl-use-syntax-table-text-property])
f83d2997
KH
1096 ["Refresh \"hard\" constructions" cperl-find-pods-heres t]
1097 "----"
1098 ["Indent region" cperl-indent-region (cperl-use-region-p)]
1099 ["Comment region" cperl-comment-region (cperl-use-region-p)]
1100 ["Uncomment region" cperl-uncomment-region (cperl-use-region-p)]
1101 "----"
1102 ["Run" mode-compile (fboundp 'mode-compile)]
1103 ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
1104 (get-buffer "*compilation*"))]
1105 ["Next error" next-error (get-buffer "*compilation*")]
1106 ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
1107 "----"
1108 ["Debugger" cperl-db t]
1109 "----"
1110 ("Tools"
1111 ["Imenu" imenu (fboundp 'imenu)]
1112 ["Insert spaces if needed" cperl-find-bad-style t]
1113 ["Class Hierarchy from TAGS" cperl-tags-hier-init t]
1114 ;;["Update classes" (cperl-tags-hier-init t) tags-table-list]
5c8b7eaf 1115 ["CPerl pretty print (exprmntl)" cperl-ps-print
5bd52f0e 1116 (fboundp 'ps-extend-face-list)]
f83d2997
KH
1117 ["Imenu on info" cperl-imenu-on-info (featurep 'imenu)]
1118 ("Tags"
1119;;; ["Create tags for current file" cperl-etags t]
1120;;; ["Add tags for current file" (cperl-etags t) t]
1121;;; ["Create tags for Perl files in directory" (cperl-etags nil t) t]
1122;;; ["Add tags for Perl files in directory" (cperl-etags t t) t]
5c8b7eaf 1123;;; ["Create tags for Perl files in (sub)directories"
f83d2997
KH
1124;;; (cperl-etags nil 'recursive) t]
1125;;; ["Add tags for Perl files in (sub)directories"
5c8b7eaf 1126;;; (cperl-etags t 'recursive) t])
f83d2997
KH
1127;;;; cperl-write-tags (&optional file erase recurse dir inbuffer)
1128 ["Create tags for current file" (cperl-write-tags nil t) t]
1129 ["Add tags for current file" (cperl-write-tags) t]
5c8b7eaf 1130 ["Create tags for Perl files in directory"
f83d2997 1131 (cperl-write-tags nil t nil t) t]
5c8b7eaf 1132 ["Add tags for Perl files in directory"
f83d2997 1133 (cperl-write-tags nil nil nil t) t]
5c8b7eaf 1134 ["Create tags for Perl files in (sub)directories"
f83d2997
KH
1135 (cperl-write-tags nil t t t) t]
1136 ["Add tags for Perl files in (sub)directories"
db133cb6
RS
1137 (cperl-write-tags nil nil t t) t]))
1138 ("Perl docs"
5c8b7eaf 1139 ["Define word at point" imenu-go-find-at-position
f83d2997
KH
1140 (fboundp 'imenu-go-find-at-position)]
1141 ["Help on function" cperl-info-on-command t]
1142 ["Help on function at point" cperl-info-on-current-command t]
1143 ["Help on symbol at point" cperl-get-help t]
db133cb6
RS
1144 ["Perldoc" cperl-perldoc t]
1145 ["Perldoc on word at point" cperl-perldoc-at-point t]
1146 ["View manpage of POD in this file" cperl-pod-to-manpage t]
5c8b7eaf 1147 ["Auto-help on" cperl-lazy-install
db133cb6
RS
1148 (and (fboundp 'run-with-idle-timer)
1149 (not cperl-lazy-installed))]
5c8b7eaf 1150 ["Auto-help off" (eval '(cperl-lazy-unstall))
db133cb6
RS
1151 (and (fboundp 'run-with-idle-timer)
1152 cperl-lazy-installed)])
f83d2997
KH
1153 ("Toggle..."
1154 ["Auto newline" cperl-toggle-auto-newline t]
1155 ["Electric parens" cperl-toggle-electric t]
1156 ["Electric keywords" cperl-toggle-abbrev t]
db133cb6 1157 ["Fix whitespace on indent" cperl-toggle-construct-fix t]
5c8b7eaf 1158 ["Auto fill" auto-fill-mode t])
f83d2997 1159 ("Indent styles..."
db133cb6
RS
1160 ["CPerl" (cperl-set-style "CPerl") t]
1161 ["PerlStyle" (cperl-set-style "PerlStyle") t]
f83d2997
KH
1162 ["GNU" (cperl-set-style "GNU") t]
1163 ["C++" (cperl-set-style "C++") t]
1164 ["FSF" (cperl-set-style "FSF") t]
1165 ["BSD" (cperl-set-style "BSD") t]
db133cb6
RS
1166 ["Whitesmith" (cperl-set-style "Whitesmith") t]
1167 ["Current" (cperl-set-style "Current") t]
1168 ["Memorized" (cperl-set-style-back) cperl-old-style])
f83d2997
KH
1169 ("Micro-docs"
1170 ["Tips" (describe-variable 'cperl-tips) t]
1171 ["Problems" (describe-variable 'cperl-problems) t]
db133cb6
RS
1172 ["Speed" (describe-variable 'cperl-speed) t]
1173 ["Praise" (describe-variable 'cperl-praise) t]
5bd52f0e
RS
1174 ["Faces" (describe-variable 'cperl-tips-faces) t]
1175 ["CPerl mode" (describe-function 'cperl-mode) t]
5c8b7eaf 1176 ["CPerl version"
bedf0b73 1177 (message "The version of master-file for this CPerl is %s-emacs"
5bd52f0e 1178 cperl-version) t]))))
f83d2997
KH
1179 (error nil))
1180
1181(autoload 'c-macro-expand "cmacexp"
1182 "Display the result of expanding all C macros occurring in the region.
1183The expansion is entirely correct because it uses the C preprocessor."
1184 t)
1185
95f433f4
RS
1186(defvar cperl-imenu--function-name-regexp-perl
1187 (concat
1188 "^\\("
1189 "[ \t]*\\(sub\\|package\\)[ \t\n]+\\([a-zA-Z_0-9:']+\\)[ \t]*\\(([^()]*)[ \t]*\\)?"
1190 "\\|"
1191 "=head\\([12]\\)[ \t]+\\([^\n]+\\)$"
1192 "\\)"))
1193
8dd511f6
RS
1194(defvar cperl-outline-regexp
1195 (concat cperl-imenu--function-name-regexp-perl "\\|" "\\`"))
1196
f83d2997 1197(defvar cperl-mode-syntax-table nil
f94a632a 1198 "Syntax table in use in CPerl mode buffers.")
f83d2997
KH
1199
1200(defvar cperl-string-syntax-table nil
f94a632a 1201 "Syntax table in use in CPerl mode string-like chunks.")
f83d2997
KH
1202
1203(if cperl-mode-syntax-table
1204 ()
1205 (setq cperl-mode-syntax-table (make-syntax-table))
1206 (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table)
1207 (modify-syntax-entry ?/ "." cperl-mode-syntax-table)
1208 (modify-syntax-entry ?* "." cperl-mode-syntax-table)
1209 (modify-syntax-entry ?+ "." cperl-mode-syntax-table)
1210 (modify-syntax-entry ?- "." cperl-mode-syntax-table)
1211 (modify-syntax-entry ?= "." cperl-mode-syntax-table)
1212 (modify-syntax-entry ?% "." cperl-mode-syntax-table)
1213 (modify-syntax-entry ?< "." cperl-mode-syntax-table)
1214 (modify-syntax-entry ?> "." cperl-mode-syntax-table)
1215 (modify-syntax-entry ?& "." cperl-mode-syntax-table)
1216 (modify-syntax-entry ?$ "\\" cperl-mode-syntax-table)
1217 (modify-syntax-entry ?\n ">" cperl-mode-syntax-table)
1218 (modify-syntax-entry ?# "<" cperl-mode-syntax-table)
1219 (modify-syntax-entry ?' "\"" cperl-mode-syntax-table)
1220 (modify-syntax-entry ?` "\"" cperl-mode-syntax-table)
1221 (if cperl-under-as-char
1222 (modify-syntax-entry ?_ "w" cperl-mode-syntax-table))
1223 (modify-syntax-entry ?: "_" cperl-mode-syntax-table)
1224 (modify-syntax-entry ?| "." cperl-mode-syntax-table)
1225 (setq cperl-string-syntax-table (copy-syntax-table cperl-mode-syntax-table))
1226 (modify-syntax-entry ?$ "." cperl-string-syntax-table)
1227 (modify-syntax-entry ?# "." cperl-string-syntax-table) ; (?# comment )
1228)
1229
1230
1231\f
db133cb6 1232(defvar cperl-faces-init nil)
f83d2997
KH
1233;; Fix for msb.el
1234(defvar cperl-msb-fixed nil)
1235;;;###autoload
1236(defun cperl-mode ()
1237 "Major mode for editing Perl code.
1238Expression and list commands understand all C brackets.
1239Tab indents for Perl code.
1240Paragraphs are separated by blank lines only.
1241Delete converts tabs to spaces as it moves back.
1242
1243Various characters in Perl almost always come in pairs: {}, (), [],
1244sometimes <>. When the user types the first, she gets the second as
1245well, with optional special formatting done on {}. (Disabled by
1246default.) You can always quote (with \\[quoted-insert]) the left
1247\"paren\" to avoid the expansion. The processing of < is special,
f94a632a 1248since most the time you mean \"less\". CPerl mode tries to guess
f83d2997
KH
1249whether you want to type pair <>, and inserts is if it
1250appropriate. You can set `cperl-electric-parens-string' to the string that
1251contains the parenths from the above list you want to be electrical.
1252Electricity of parenths is controlled by `cperl-electric-parens'.
1253You may also set `cperl-electric-parens-mark' to have electric parens
1254look for active mark and \"embrace\" a region if possible.'
1255
1256CPerl mode provides expansion of the Perl control constructs:
db133cb6 1257
5c8b7eaf 1258 if, else, elsif, unless, while, until, continue, do,
db133cb6
RS
1259 for, foreach, formy and foreachmy.
1260
1261and POD directives (Disabled by default, see `cperl-electric-keywords'.)
1262
1263The user types the keyword immediately followed by a space, which
1264causes the construct to be expanded, and the point is positioned where
1265she is most likely to want to be. eg. when the user types a space
1266following \"if\" the following appears in the buffer: if () { or if ()
1267} { } and the cursor is between the parentheses. The user can then
1268type some boolean expression within the parens. Having done that,
1269typing \\[cperl-linefeed] places you - appropriately indented - on a
1270new line between the braces (if you typed \\[cperl-linefeed] in a POD
5c8b7eaf 1271directive line, then appropriate number of new lines is inserted).
db133cb6
RS
1272
1273If CPerl decides that you want to insert \"English\" style construct like
1274
f83d2997 1275 bite if angry;
db133cb6
RS
1276
1277it will not do any expansion. See also help on variable
1278`cperl-extra-newline-before-brace'. (Note that one can switch the
1279help message on expansion by setting `cperl-message-electric-keyword'
1280to nil.)
f83d2997
KH
1281
1282\\[cperl-linefeed] is a convenience replacement for typing carriage
1283return. It places you in the next line with proper indentation, or if
1284you type it inside the inline block of control construct, like
db133cb6 1285
f83d2997 1286 foreach (@lines) {print; print}
db133cb6 1287
f83d2997
KH
1288and you are on a boundary of a statement inside braces, it will
1289transform the construct into a multiline and will place you into an
5c8b7eaf
SS
1290appropriately indented blank line. If you need a usual
1291`newline-and-indent' behaviour, it is on \\[newline-and-indent],
f83d2997
KH
1292see documentation on `cperl-electric-linefeed'.
1293
db133cb6
RS
1294Use \\[cperl-invert-if-unless] to change a construction of the form
1295
1296 if (A) { B }
1297
1298into
1299
1300 B if A;
1301
f83d2997
KH
1302\\{cperl-mode-map}
1303
db133cb6
RS
1304Setting the variable `cperl-font-lock' to t switches on font-lock-mode
1305\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
1306on electric space between $ and {, `cperl-electric-parens-string' is
1307the string that contains parentheses that should be electric in CPerl
1308\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
f83d2997
KH
1309setting `cperl-electric-keywords' enables electric expansion of
1310control structures in CPerl. `cperl-electric-linefeed' governs which
1311one of two linefeed behavior is preferable. You can enable all these
1312options simultaneously (recommended mode of use) by setting
1313`cperl-hairy' to t. In this case you can switch separate options off
db133cb6
RS
1314by setting them to `null'. Note that one may undo the extra
1315whitespace inserted by semis and braces in `auto-newline'-mode by
1316consequent \\[cperl-electric-backspace].
f83d2997
KH
1317
1318If your site has perl5 documentation in info format, you can use commands
1319\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
1320These keys run commands `cperl-info-on-current-command' and
1321`cperl-info-on-command', which one is which is controlled by variable
5c8b7eaf 1322`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
db133cb6 1323\(in turn affected by `cperl-hairy').
f83d2997
KH
1324
1325Even if you have no info-format documentation, short one-liner-style
db133cb6
RS
1326help is available on \\[cperl-get-help], and one can run perldoc or
1327man via menu.
f83d2997 1328
db133cb6
RS
1329It is possible to show this help automatically after some idle time.
1330This is regulated by variable `cperl-lazy-help-time'. Default with
1331`cperl-hairy' (if the value of `cperl-lazy-help-time' is nil) is 5
1332secs idle time . It is also possible to switch this on/off from the
1333menu, or via \\[cperl-toggle-autohelp]. Requires `run-with-idle-timer'.
f83d2997
KH
1334
1335Use \\[cperl-lineup] to vertically lineup some construction - put the
1336beginning of the region at the start of construction, and make region
1337span the needed amount of lines.
1338
1339Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
1340`cperl-pod-face', `cperl-pod-head-face' control processing of pod and
db133cb6
RS
1341here-docs sections. With capable Emaxen results of scan are used
1342for indentation too, otherwise they are used for highlighting only.
f83d2997
KH
1343
1344Variables controlling indentation style:
1345 `cperl-tab-always-indent'
1346 Non-nil means TAB in CPerl mode should always reindent the current line,
1347 regardless of where in the line point is when the TAB command is used.
db133cb6
RS
1348 `cperl-indent-left-aligned-comments'
1349 Non-nil means that the comment starting in leftmost column should indent.
f83d2997
KH
1350 `cperl-auto-newline'
1351 Non-nil means automatically newline before and after braces,
1352 and after colons and semicolons, inserted in Perl code. The following
1353 \\[cperl-electric-backspace] will remove the inserted whitespace.
5c8b7eaf
SS
1354 Insertion after colons requires both this variable and
1355 `cperl-auto-newline-after-colon' set.
f83d2997
KH
1356 `cperl-auto-newline-after-colon'
1357 Non-nil means automatically newline even after colons.
1358 Subject to `cperl-auto-newline' setting.
1359 `cperl-indent-level'
1360 Indentation of Perl statements within surrounding block.
1361 The surrounding block's indentation is the indentation
1362 of the line on which the open-brace appears.
1363 `cperl-continued-statement-offset'
1364 Extra indentation given to a substatement, such as the
1365 then-clause of an if, or body of a while, or just a statement continuation.
1366 `cperl-continued-brace-offset'
1367 Extra indentation given to a brace that starts a substatement.
1368 This is in addition to `cperl-continued-statement-offset'.
1369 `cperl-brace-offset'
1370 Extra indentation for line if it starts with an open brace.
1371 `cperl-brace-imaginary-offset'
1372 An open brace following other text is treated as if it the line started
1373 this far to the right of the actual line indentation.
1374 `cperl-label-offset'
1375 Extra indentation for line that is a label.
1376 `cperl-min-label-indent'
1377 Minimal indentation for line that is a label.
1378
1379Settings for K&R and BSD indentation styles are
1380 `cperl-indent-level' 5 8
1381 `cperl-continued-statement-offset' 5 8
1382 `cperl-brace-offset' -5 -8
1383 `cperl-label-offset' -5 -8
1384
db133cb6
RS
1385CPerl knows several indentation styles, and may bulk set the
1386corresponding variables. Use \\[cperl-set-style] to do this. Use
1387\\[cperl-set-style-back] to restore the memorized preexisting values
1388\(both available from menu).
1389
1390If `cperl-indent-level' is 0, the statement after opening brace in
5c8b7eaf 1391column 0 is indented on
db133cb6 1392`cperl-brace-offset'+`cperl-continued-statement-offset'.
f83d2997
KH
1393
1394Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook'
db133cb6
RS
1395with no args.
1396
1397DO NOT FORGET to read micro-docs (available from `Perl' menu)
1398or as help on variables `cperl-tips', `cperl-problems',
f94a632a 1399`cperl-praise', `cperl-speed'."
f83d2997
KH
1400 (interactive)
1401 (kill-all-local-variables)
f83d2997
KH
1402 (use-local-map cperl-mode-map)
1403 (if (cperl-val 'cperl-electric-linefeed)
1404 (progn
1405 (local-set-key "\C-J" 'cperl-linefeed)
1406 (local-set-key "\C-C\C-J" 'newline-and-indent)))
db133cb6
RS
1407 (if (and
1408 (cperl-val 'cperl-clobber-lisp-bindings)
1409 (cperl-val 'cperl-info-on-command-no-prompt))
f83d2997
KH
1410 (progn
1411 ;; don't clobber the backspace binding:
1412 (cperl-define-key "\C-hf" 'cperl-info-on-current-command [(control h) f])
1413 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-command
1414 [(control c) (control h) f])))
029cb4d5 1415 (setq major-mode 'cperl-mode)
f83d2997
KH
1416 (setq mode-name "CPerl")
1417 (if (not cperl-mode-abbrev-table)
1418 (let ((prev-a-c abbrevs-changed))
1419 (define-abbrev-table 'cperl-mode-abbrev-table '(
1420 ("if" "if" cperl-electric-keyword 0)
1421 ("elsif" "elsif" cperl-electric-keyword 0)
1422 ("while" "while" cperl-electric-keyword 0)
1423 ("until" "until" cperl-electric-keyword 0)
1424 ("unless" "unless" cperl-electric-keyword 0)
1425 ("else" "else" cperl-electric-else 0)
db133cb6 1426 ("continue" "continue" cperl-electric-else 0)
f83d2997
KH
1427 ("for" "for" cperl-electric-keyword 0)
1428 ("foreach" "foreach" cperl-electric-keyword 0)
db133cb6
RS
1429 ("formy" "formy" cperl-electric-keyword 0)
1430 ("foreachmy" "foreachmy" cperl-electric-keyword 0)
1431 ("do" "do" cperl-electric-keyword 0)
6c389151
SM
1432 ("=pod" "=pod" cperl-electric-pod 0)
1433 ("=over" "=over" cperl-electric-pod 0)
1434 ("=head1" "=head1" cperl-electric-pod 0)
1435 ("=head2" "=head2" cperl-electric-pod 0)
db133cb6
RS
1436 ("pod" "pod" cperl-electric-pod 0)
1437 ("over" "over" cperl-electric-pod 0)
1438 ("head1" "head1" cperl-electric-pod 0)
1439 ("head2" "head2" cperl-electric-pod 0)))
f83d2997
KH
1440 (setq abbrevs-changed prev-a-c)))
1441 (setq local-abbrev-table cperl-mode-abbrev-table)
1442 (abbrev-mode (if (cperl-val 'cperl-electric-keywords) 1 0))
1443 (set-syntax-table cperl-mode-syntax-table)
6c389151
SM
1444 (make-local-variable 'outline-regexp)
1445 ;; (setq outline-regexp imenu-example--function-name-regexp-perl)
1446 (setq outline-regexp cperl-outline-regexp)
1447 (make-local-variable 'outline-level)
1448 (setq outline-level 'cperl-outline-level)
f83d2997
KH
1449 (make-local-variable 'paragraph-start)
1450 (setq paragraph-start (concat "^$\\|" page-delimiter))
1451 (make-local-variable 'paragraph-separate)
1452 (setq paragraph-separate paragraph-start)
1453 (make-local-variable 'paragraph-ignore-fill-prefix)
1454 (setq paragraph-ignore-fill-prefix t)
1455 (make-local-variable 'indent-line-function)
1456 (setq indent-line-function 'cperl-indent-line)
1457 (make-local-variable 'require-final-newline)
1458 (setq require-final-newline t)
1459 (make-local-variable 'comment-start)
1460 (setq comment-start "# ")
1461 (make-local-variable 'comment-end)
1462 (setq comment-end "")
1463 (make-local-variable 'comment-column)
1464 (setq comment-column cperl-comment-column)
1465 (make-local-variable 'comment-start-skip)
1466 (setq comment-start-skip "#+ *")
1467 (make-local-variable 'defun-prompt-regexp)
1468 (setq defun-prompt-regexp "^[ \t]*sub[ \t]+\\([^ \t\n{(;]+\\)[ \t]*")
1469 (make-local-variable 'comment-indent-function)
1470 (setq comment-indent-function 'cperl-comment-indent)
1471 (make-local-variable 'parse-sexp-ignore-comments)
1472 (setq parse-sexp-ignore-comments t)
1473 (make-local-variable 'indent-region-function)
1474 (setq indent-region-function 'cperl-indent-region)
1475 ;;(setq auto-fill-function 'cperl-do-auto-fill) ; Need to switch on and off!
1476 (make-local-variable 'imenu-create-index-function)
1477 (setq imenu-create-index-function
80585273 1478 (function cperl-imenu--create-perl-index))
f83d2997
KH
1479 (make-local-variable 'imenu-sort-function)
1480 (setq imenu-sort-function nil)
1481 (make-local-variable 'vc-header-alist)
db133cb6 1482 (set 'vc-header-alist cperl-vc-header-alist) ; Avoid warning
f83d2997
KH
1483 (make-local-variable 'font-lock-defaults)
1484 (setq font-lock-defaults
db133cb6
RS
1485 (cond
1486 ((string< emacs-version "19.30")
5efe6a56 1487 '(cperl-font-lock-keywords-2))
db133cb6 1488 ((string< emacs-version "19.33") ; Which one to use?
5efe6a56
SM
1489 '((cperl-font-lock-keywords
1490 cperl-font-lock-keywords-1
1491 cperl-font-lock-keywords-2)))
db133cb6
RS
1492 (t
1493 '((cperl-load-font-lock-keywords
1494 cperl-load-font-lock-keywords-1
1495 cperl-load-font-lock-keywords-2)))))
1496 (make-local-variable 'cperl-syntax-state)
f83d2997
KH
1497 (if cperl-use-syntax-table-text-property
1498 (progn
029cb4d5 1499 (make-local-variable 'parse-sexp-lookup-properties)
f83d2997 1500 ;; Do not introduce variable if not needed, we check it!
db133cb6
RS
1501 (set 'parse-sexp-lookup-properties t)
1502 ;; Fix broken font-lock:
1503 (or (boundp 'font-lock-unfontify-region-function)
1504 (set 'font-lock-unfontify-region-function
5bd52f0e 1505 'font-lock-default-unfontify-region))
029cb4d5 1506 (make-local-variable 'font-lock-unfontify-region-function)
5c8b7eaf 1507 (set 'font-lock-unfontify-region-function
db133cb6 1508 'cperl-font-lock-unfontify-region-function)
029cb4d5 1509 (make-local-variable 'cperl-syntax-done-to)
db133cb6
RS
1510 ;; Another bug: unless font-lock-syntactic-keywords, font-lock
1511 ;; ignores syntax-table text-property. (t) is a hack
1512 ;; to make font-lock think that font-lock-syntactic-keywords
1513 ;; are defined
029cb4d5 1514 (make-local-variable 'font-lock-syntactic-keywords)
5c8b7eaf 1515 (setq font-lock-syntactic-keywords
db133cb6
RS
1516 (if cperl-syntaxify-by-font-lock
1517 '(t (cperl-fontify-syntaxically))
1518 '(t)))))
1519 (make-local-variable 'cperl-old-style)
80585273 1520 (set (make-local-variable 'normal-auto-fill-function)
072cb6f9 1521 #'cperl-do-auto-fill)
f83d2997 1522 (if (cperl-enable-font-lock)
5c8b7eaf 1523 (if (cperl-val 'cperl-font-lock)
f83d2997
KH
1524 (progn (or cperl-faces-init (cperl-init-faces))
1525 (font-lock-mode 1))))
1526 (and (boundp 'msb-menu-cond)
1527 (not cperl-msb-fixed)
1528 (cperl-msb-fix))
1529 (if (featurep 'easymenu)
46c72468 1530 (easy-menu-add cperl-menu)) ; A NOP in Emacs.
f83d2997
KH
1531 (run-hooks 'cperl-mode-hook)
1532 ;; After hooks since fontification will break this
5c8b7eaf 1533 (if cperl-pod-here-scan
5bd52f0e
RS
1534 (or ;;(and (boundp 'font-lock-mode)
1535 ;; (eval 'font-lock-mode) ; Avoid warning
1536 ;; (boundp 'font-lock-hot-pass) ; Newer font-lock
1537 cperl-syntaxify-by-font-lock ;;)
1538 (progn (or cperl-faces-init (cperl-init-faces-weak))
1539 (cperl-find-pods-heres)))))
f83d2997
KH
1540\f
1541;; Fix for perldb - make default reasonable
1542(defun cperl-db ()
1543 (interactive)
1544 (require 'gud)
1545 (perldb (read-from-minibuffer "Run perldb (like this): "
1546 (if (consp gud-perldb-history)
1547 (car gud-perldb-history)
1548 (concat "perl " ;;(file-name-nondirectory
1549 ;; I have problems
1550 ;; in OS/2
1551 ;; otherwise
1552 (buffer-file-name)))
1553 nil nil
1554 '(gud-perldb-history . 1))))
1555\f
f83d2997
KH
1556(defun cperl-msb-fix ()
1557 ;; Adds perl files to msb menu, supposes that msb is already loaded
1558 (setq cperl-msb-fixed t)
1559 (let* ((l (length msb-menu-cond))
1560 (last (nth (1- l) msb-menu-cond))
1561 (precdr (nthcdr (- l 2) msb-menu-cond)) ; cdr of this is last
1562 (handle (1- (nth 1 last))))
1563 (setcdr precdr (list
1564 (list
996e2616 1565 '(memq major-mode '(cperl-mode perl-mode))
f83d2997
KH
1566 handle
1567 "Perl Files (%d)")
1568 last))))
1569\f
1570;; This is used by indent-for-comment
1571;; to decide how much to indent a comment in CPerl code
1572;; based on its context. Do fallback if comment is found wrong.
1573
1574(defvar cperl-wrong-comment)
5bd52f0e
RS
1575(defvar cperl-st-cfence '(14)) ; Comment-fence
1576(defvar cperl-st-sfence '(15)) ; String-fence
1577(defvar cperl-st-punct '(1))
1578(defvar cperl-st-word '(2))
1579(defvar cperl-st-bra '(4 . ?\>))
1580(defvar cperl-st-ket '(5 . ?\<))
1581
f83d2997
KH
1582
1583(defun cperl-comment-indent ()
5bd52f0e 1584 (let ((p (point)) (c (current-column)) was phony)
f83d2997
KH
1585 (if (looking-at "^#") 0 ; Existing comment at bol stays there.
1586 ;; Wrong comment found
1587 (save-excursion
5bd52f0e
RS
1588 (setq was (cperl-to-comment-or-eol)
1589 phony (eq (get-text-property (point) 'syntax-table)
1590 cperl-st-cfence))
1591 (if phony
1592 (progn
1593 (re-search-forward "#\\|$") ; Hmm, what about embedded #?
1594 (if (eq (preceding-char) ?\#)
1595 (forward-char -1))
1596 (setq was nil)))
f83d2997
KH
1597 (if (= (point) p)
1598 (progn
1599 (skip-chars-backward " \t")
1600 (max (1+ (current-column)) ; Else indent at comment column
1601 comment-column))
1602 (if was nil
1603 (insert comment-start)
1604 (backward-char (length comment-start)))
1605 (setq cperl-wrong-comment t)
1606 (indent-to comment-column 1) ; Indent minimum 1
1607 c))))) ; except leave at least one space.
1608
1609;;;(defun cperl-comment-indent-fallback ()
1610;;; "Is called if the standard comment-search procedure fails.
1611;;;Point is at start of real comment."
1612;;; (let ((c (current-column)) target cnt prevc)
1613;;; (if (= c comment-column) nil
1614;;; (setq cnt (skip-chars-backward "[ \t]"))
5c8b7eaf 1615;;; (setq target (max (1+ (setq prevc
f83d2997
KH
1616;;; (current-column))) ; Else indent at comment column
1617;;; comment-column))
1618;;; (if (= c comment-column) nil
1619;;; (delete-backward-char cnt)
1620;;; (while (< prevc target)
1621;;; (insert "\t")
1622;;; (setq prevc (current-column)))
1623;;; (if (> prevc target) (progn (delete-char -1) (setq prevc (current-column))))
1624;;; (while (< prevc target)
1625;;; (insert " ")
1626;;; (setq prevc (current-column)))))))
1627
1628(defun cperl-indent-for-comment ()
1629 "Substitute for `indent-for-comment' in CPerl."
1630 (interactive)
1631 (let (cperl-wrong-comment)
1632 (indent-for-comment)
1633 (if cperl-wrong-comment
1634 (progn (cperl-to-comment-or-eol)
1635 (forward-char (length comment-start))))))
1636
1637(defun cperl-comment-region (b e arg)
1638 "Comment or uncomment each line in the region in CPerl mode.
1639See `comment-region'."
1640 (interactive "r\np")
1641 (let ((comment-start "#"))
1642 (comment-region b e arg)))
1643
1644(defun cperl-uncomment-region (b e arg)
1645 "Uncomment or comment each line in the region in CPerl mode.
1646See `comment-region'."
1647 (interactive "r\np")
1648 (let ((comment-start "#"))
1649 (comment-region b e (- arg))))
1650
1651(defvar cperl-brace-recursing nil)
1652
1653(defun cperl-electric-brace (arg &optional only-before)
1654 "Insert character and correct line's indentation.
1655If ONLY-BEFORE and `cperl-auto-newline', will insert newline before the
1656place (even in empty line), but not after. If after \")\" and the inserted
5c8b7eaf 1657char is \"{\", insert extra newline before only if
f83d2997
KH
1658`cperl-extra-newline-before-brace'."
1659 (interactive "P")
1660 (let (insertpos
1661 (other-end (if (and cperl-electric-parens-mark
5c8b7eaf 1662 (cperl-mark-active)
f83d2997 1663 (< (mark) (point)))
5c8b7eaf 1664 (mark)
f83d2997
KH
1665 nil)))
1666 (if (and other-end
1667 (not cperl-brace-recursing)
1668 (cperl-val 'cperl-electric-parens)
1669 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point)))
1670 ;; Need to insert a matching pair
1671 (progn
1672 (save-excursion
1673 (setq insertpos (point-marker))
1674 (goto-char other-end)
1675 (setq last-command-char ?\{)
1676 (cperl-electric-lbrace arg insertpos))
1677 (forward-char 1))
db133cb6
RS
1678 ;: Check whether we close something "usual" with `}'
1679 (if (and (eq last-command-char ?\})
5c8b7eaf 1680 (not
db133cb6
RS
1681 (condition-case nil
1682 (save-excursion
1683 (up-list (- (prefix-numeric-value arg)))
1684 ;;(cperl-after-block-p (point-min))
1685 (cperl-after-expr-p nil "{;)"))
1686 (error nil))))
1687 ;; Just insert the guy
1688 (self-insert-command (prefix-numeric-value arg))
1689 (if (and (not arg) ; No args, end (of empty line or auto)
1690 (eolp)
1691 (or (and (null only-before)
1692 (save-excursion
1693 (skip-chars-backward " \t")
1694 (bolp)))
1695 (and (eq last-command-char ?\{) ; Do not insert newline
1696 ;; if after ")" and `cperl-extra-newline-before-brace'
1697 ;; is nil, do not insert extra newline.
1698 (not cperl-extra-newline-before-brace)
1699 (save-excursion
1700 (skip-chars-backward " \t")
1701 (eq (preceding-char) ?\))))
5c8b7eaf 1702 (if cperl-auto-newline
db133cb6
RS
1703 (progn (cperl-indent-line) (newline) t) nil)))
1704 (progn
1705 (self-insert-command (prefix-numeric-value arg))
1706 (cperl-indent-line)
1707 (if cperl-auto-newline
1708 (setq insertpos (1- (point))))
1709 (if (and cperl-auto-newline (null only-before))
1710 (progn
1711 (newline)
1712 (cperl-indent-line)))
1713 (save-excursion
1714 (if insertpos (progn (goto-char insertpos)
5c8b7eaf 1715 (search-forward (make-string
db133cb6
RS
1716 1 last-command-char))
1717 (setq insertpos (1- (point)))))
1718 (delete-char -1))))
1719 (if insertpos
f83d2997 1720 (save-excursion
db133cb6
RS
1721 (goto-char insertpos)
1722 (self-insert-command (prefix-numeric-value arg)))
1723 (self-insert-command (prefix-numeric-value arg)))))))
f83d2997
KH
1724
1725(defun cperl-electric-lbrace (arg &optional end)
1726 "Insert character, correct line's indentation, correct quoting by space."
1727 (interactive "P")
5c8b7eaf 1728 (let (pos after
f83d2997
KH
1729 (cperl-brace-recursing t)
1730 (cperl-auto-newline cperl-auto-newline)
1731 (other-end (or end
1732 (if (and cperl-electric-parens-mark
1733 (cperl-mark-active)
1734 (> (mark) (point)))
1735 (save-excursion
1736 (goto-char (mark))
5c8b7eaf 1737 (point-marker))
f83d2997
KH
1738 nil))))
1739 (and (cperl-val 'cperl-electric-lbrace-space)
1740 (eq (preceding-char) ?$)
1741 (save-excursion
1742 (skip-chars-backward "$")
1743 (looking-at "\\(\\$\\$\\)*\\$\\([^\\$]\\|$\\)"))
1744 (insert ?\ ))
bab27c0c 1745 ;; Check whether we are in comment
5c8b7eaf 1746 (if (and
bab27c0c
RS
1747 (save-excursion
1748 (beginning-of-line)
1749 (not (looking-at "[ \t]*#")))
1750 (cperl-after-expr-p nil "{;)"))
1751 nil
1752 (setq cperl-auto-newline nil))
f83d2997
KH
1753 (cperl-electric-brace arg)
1754 (and (cperl-val 'cperl-electric-parens)
1755 (eq last-command-char ?{)
5c8b7eaf 1756 (memq last-command-char
f83d2997
KH
1757 (append cperl-electric-parens-string nil))
1758 (or (if other-end (goto-char (marker-position other-end)))
1759 t)
1760 (setq last-command-char ?} pos (point))
1761 (progn (cperl-electric-brace arg t)
1762 (goto-char pos)))))
1763
1764(defun cperl-electric-paren (arg)
1765 "Insert a matching pair of parentheses."
1766 (interactive "P")
1767 (let ((beg (save-excursion (beginning-of-line) (point)))
1768 (other-end (if (and cperl-electric-parens-mark
5c8b7eaf 1769 (cperl-mark-active)
f83d2997
KH
1770 (> (mark) (point)))
1771 (save-excursion
1772 (goto-char (mark))
5c8b7eaf 1773 (point-marker))
f83d2997
KH
1774 nil)))
1775 (if (and (cperl-val 'cperl-electric-parens)
1776 (memq last-command-char
1777 (append cperl-electric-parens-string nil))
1778 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
1779 ;;(not (save-excursion (search-backward "#" beg t)))
1780 (if (eq last-command-char ?<)
1781 (progn
1782 (and abbrev-mode ; later it is too late, may be after `for'
1783 (expand-abbrev))
1784 (cperl-after-expr-p nil "{;(,:="))
1785 1))
1786 (progn
1787 (self-insert-command (prefix-numeric-value arg))
1788 (if other-end (goto-char (marker-position other-end)))
5c8b7eaf 1789 (insert (make-string
f83d2997
KH
1790 (prefix-numeric-value arg)
1791 (cdr (assoc last-command-char '((?{ .?})
1792 (?[ . ?])
1793 (?( . ?))
1794 (?< . ?>))))))
1795 (forward-char (- (prefix-numeric-value arg))))
1796 (self-insert-command (prefix-numeric-value arg)))))
1797
1798(defun cperl-electric-rparen (arg)
1799 "Insert a matching pair of parentheses if marking is active.
1800If not, or if we are not at the end of marking range, would self-insert."
1801 (interactive "P")
1802 (let ((beg (save-excursion (beginning-of-line) (point)))
1803 (other-end (if (and cperl-electric-parens-mark
1804 (cperl-val 'cperl-electric-parens)
1805 (memq last-command-char
1806 (append cperl-electric-parens-string nil))
5c8b7eaf 1807 (cperl-mark-active)
f83d2997 1808 (< (mark) (point)))
5c8b7eaf 1809 (mark)
f83d2997
KH
1810 nil))
1811 p)
1812 (if (and other-end
1813 (cperl-val 'cperl-electric-parens)
1814 (memq last-command-char '( ?\) ?\] ?\} ?\> ))
1815 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
1816 ;;(not (save-excursion (search-backward "#" beg t)))
1817 )
1818 (progn
1819 (self-insert-command (prefix-numeric-value arg))
1820 (setq p (point))
1821 (if other-end (goto-char other-end))
1822 (insert (make-string
1823 (prefix-numeric-value arg)
1824 (cdr (assoc last-command-char '((?\} . ?\{)
1825 (?\] . ?\[)
1826 (?\) . ?\()
1827 (?\> . ?\<))))))
1828 (goto-char (1+ p)))
1829 (self-insert-command (prefix-numeric-value arg)))))
1830
1831(defun cperl-electric-keyword ()
db133cb6
RS
1832 "Insert a construction appropriate after a keyword.
1833Help message may be switched off by setting `cperl-message-electric-keyword'
1834to nil."
5c8b7eaf 1835 (let ((beg (save-excursion (beginning-of-line) (point)))
f83d2997
KH
1836 (dollar (and (eq last-command-char ?$)
1837 (eq this-command 'self-insert-command)))
1838 (delete (and (memq last-command-char '(?\ ?\n ?\t ?\f))
db133cb6
RS
1839 (memq this-command '(self-insert-command newline))))
1840 my do)
f83d2997 1841 (and (save-excursion
db133cb6
RS
1842 (condition-case nil
1843 (progn
1844 (backward-sexp 1)
1845 (setq do (looking-at "do\\>")))
1846 (error nil))
f83d2997 1847 (cperl-after-expr-p nil "{;:"))
5c8b7eaf
SS
1848 (save-excursion
1849 (not
f83d2997 1850 (re-search-backward
5bd52f0e 1851 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
f83d2997
KH
1852 beg t)))
1853 (save-excursion (or (not (re-search-backward "^=" nil t))
db133cb6
RS
1854 (or
1855 (looking-at "=cut")
1856 (and cperl-use-syntax-table-text-property
1857 (not (eq (get-text-property (point)
1858 'syntax-type)
1859 'pod))))))
f83d2997 1860 (progn
db133cb6
RS
1861 (and (eq (preceding-char) ?y)
1862 (progn ; "foreachmy"
1863 (forward-char -2)
1864 (insert " ")
1865 (forward-char 2)
5c8b7eaf
SS
1866 (setq my t dollar t
1867 delete
db133cb6 1868 (memq this-command '(self-insert-command newline)))))
f83d2997
KH
1869 (and dollar (insert " $"))
1870 (cperl-indent-line)
1871 ;;(insert " () {\n}")
1872 (cond
1873 (cperl-extra-newline-before-brace
db133cb6 1874 (insert (if do "\n" " ()\n"))
f83d2997
KH
1875 (insert "{")
1876 (cperl-indent-line)
1877 (insert "\n")
1878 (cperl-indent-line)
db133cb6
RS
1879 (insert "\n}")
1880 (and do (insert " while ();")))
f83d2997 1881 (t
db133cb6 1882 (insert (if do " {\n} while ();" " () {\n}")))
f83d2997
KH
1883 )
1884 (or (looking-at "[ \t]\\|$") (insert " "))
1885 (cperl-indent-line)
1886 (if dollar (progn (search-backward "$")
5c8b7eaf 1887 (if my
db133cb6
RS
1888 (forward-char 1)
1889 (delete-char 1)))
f83d2997
KH
1890 (search-backward ")"))
1891 (if delete
db133cb6
RS
1892 (cperl-putback-char cperl-del-back-ch))
1893 (if cperl-message-electric-keyword
1894 (message "Precede char by C-q to avoid expansion"))))))
1895
1896(defun cperl-ensure-newlines (n &optional pos)
1897 "Make sure there are N newlines after the point."
1898 (or pos (setq pos (point)))
1899 (if (looking-at "\n")
1900 (forward-char 1)
1901 (insert "\n"))
1902 (if (> n 1)
1903 (cperl-ensure-newlines (1- n) pos)
1904 (goto-char pos)))
1905
1906(defun cperl-electric-pod ()
1907 "Insert a POD chunk appropriate after a =POD directive."
1908 (let ((delete (and (memq last-command-char '(?\ ?\n ?\t ?\f))
1909 (memq this-command '(self-insert-command newline))))
1910 head1 notlast name p really-delete over)
1911 (and (save-excursion
6c389151
SM
1912 (forward-word -1)
1913 (and
db133cb6
RS
1914 (eq (preceding-char) ?=)
1915 (progn
6c389151
SM
1916 (setq head1 (looking-at "head1\\>[ \t]*$"))
1917 (setq over (and (looking-at "over\\>[ \t]*$")
1918 (not (looking-at "over[ \t]*\n\n\n*=item\\>"))))
db133cb6
RS
1919 (forward-char -1)
1920 (bolp))
5c8b7eaf 1921 (or
5bd52f0e 1922 (get-text-property (point) 'in-pod)
db133cb6
RS
1923 (cperl-after-expr-p nil "{;:")
1924 (and (re-search-backward
6c389151
SM
1925 ;; "\\(\\`\n?\\|\n\n\\)=\\sw+"
1926 "\\(\\`\n?\\|^\n\\)=\\sw+"
1927 (point-min) t)
db133cb6
RS
1928 (not (or
1929 (looking-at "=cut")
1930 (and cperl-use-syntax-table-text-property
1931 (not (eq (get-text-property (point) 'syntax-type)
1932 'pod)))))))))
1933 (progn
1934 (save-excursion
6c389151 1935 (setq notlast (re-search-forward "^\n=" nil t)))
db133cb6
RS
1936 (or notlast
1937 (progn
1938 (insert "\n\n=cut")
1939 (cperl-ensure-newlines 2)
6c389151
SM
1940 (forward-word -2)
1941 (if (and head1
1942 (not
db133cb6
RS
1943 (save-excursion
1944 (forward-char -1)
1945 (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\>"
1946 nil t)))) ; Only one
6c389151
SM
1947 (progn
1948 (forward-word 1)
db133cb6
RS
1949 (setq name (file-name-sans-extension
1950 (file-name-nondirectory (buffer-file-name)))
1951 p (point))
5c8b7eaf 1952 (insert " NAME\n\n" name
029cb4d5 1953 " - \n\n=head1 SYNOPSIS\n\n\n\n"
db133cb6
RS
1954 "=head1 DESCRIPTION")
1955 (cperl-ensure-newlines 4)
1956 (goto-char p)
6c389151 1957 (forward-word 2)
db133cb6
RS
1958 (end-of-line)
1959 (setq really-delete t))
6c389151 1960 (forward-word 1))))
db133cb6
RS
1961 (if over
1962 (progn
1963 (setq p (point))
1964 (insert "\n\n=item \n\n\n\n"
1965 "=back")
1966 (cperl-ensure-newlines 2)
1967 (goto-char p)
6c389151 1968 (forward-word 1)
db133cb6
RS
1969 (end-of-line)
1970 (setq really-delete t)))
1971 (if (and delete really-delete)
f83d2997
KH
1972 (cperl-putback-char cperl-del-back-ch))))))
1973
1974(defun cperl-electric-else ()
db133cb6
RS
1975 "Insert a construction appropriate after a keyword.
1976Help message may be switched off by setting `cperl-message-electric-keyword'
1977to nil."
f83d2997
KH
1978 (let ((beg (save-excursion (beginning-of-line) (point))))
1979 (and (save-excursion
1980 (backward-sexp 1)
1981 (cperl-after-expr-p nil "{;:"))
5c8b7eaf
SS
1982 (save-excursion
1983 (not
f83d2997 1984 (re-search-backward
5bd52f0e 1985 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
f83d2997
KH
1986 beg t)))
1987 (save-excursion (or (not (re-search-backward "^=" nil t))
db133cb6
RS
1988 (looking-at "=cut")
1989 (and cperl-use-syntax-table-text-property
1990 (not (eq (get-text-property (point)
1991 'syntax-type)
1992 'pod)))))
f83d2997
KH
1993 (progn
1994 (cperl-indent-line)
1995 ;;(insert " {\n\n}")
1996 (cond
1997 (cperl-extra-newline-before-brace
1998 (insert "\n")
1999 (insert "{")
2000 (cperl-indent-line)
2001 (insert "\n\n}"))
2002 (t
2003 (insert " {\n\n}"))
2004 )
2005 (or (looking-at "[ \t]\\|$") (insert " "))
2006 (cperl-indent-line)
2007 (forward-line -1)
2008 (cperl-indent-line)
db133cb6
RS
2009 (cperl-putback-char cperl-del-back-ch)
2010 (setq this-command 'cperl-electric-else)
2011 (if cperl-message-electric-keyword
2012 (message "Precede char by C-q to avoid expansion"))))))
f83d2997
KH
2013
2014(defun cperl-linefeed ()
db133cb6
RS
2015 "Go to end of line, open a new line and indent appropriately.
2016If in POD, insert appropriate lines."
f83d2997
KH
2017 (interactive)
2018 (let ((beg (save-excursion (beginning-of-line) (point)))
2019 (end (save-excursion (end-of-line) (point)))
db133cb6 2020 (pos (point)) start over cut res)
f83d2997 2021 (if (and ; Check if we need to split:
5c8b7eaf 2022 ; i.e., on a boundary and inside "{...}"
f83d2997
KH
2023 (save-excursion (cperl-to-comment-or-eol)
2024 (>= (point) pos)) ; Not in a comment
2025 (or (save-excursion
2026 (skip-chars-backward " \t" beg)
2027 (forward-char -1)
2028 (looking-at "[;{]")) ; After { or ; + spaces
2029 (looking-at "[ \t]*}") ; Before }
2030 (re-search-forward "\\=[ \t]*;" end t)) ; Before spaces + ;
2031 (save-excursion
2032 (and
5c8b7eaf 2033 (eq (car (parse-partial-sexp pos end -1)) -1)
f83d2997
KH
2034 ; Leave the level of parens
2035 (looking-at "[,; \t]*\\($\\|#\\)") ; Comma to allow anon subr
2036 ; Are at end
6c389151 2037 (cperl-after-block-p (point-min))
f83d2997
KH
2038 (progn
2039 (backward-sexp 1)
2040 (setq start (point-marker))
db133cb6 2041 (<= start pos))))) ; Redundant? Are after the
f83d2997
KH
2042 ; start of parens group.
2043 (progn
2044 (skip-chars-backward " \t")
2045 (or (memq (preceding-char) (append ";{" nil))
2046 (insert ";"))
2047 (insert "\n")
2048 (forward-line -1)
2049 (cperl-indent-line)
2050 (goto-char start)
2051 (or (looking-at "{[ \t]*$") ; If there is a statement
2052 ; before, move it to separate line
2053 (progn
2054 (forward-char 1)
2055 (insert "\n")
2056 (cperl-indent-line)))
2057 (forward-line 1) ; We are on the target line
2058 (cperl-indent-line)
2059 (beginning-of-line)
2060 (or (looking-at "[ \t]*}[,; \t]*$") ; If there is a statement
2061 ; after, move it to separate line
2062 (progn
2063 (end-of-line)
2064 (search-backward "}" beg)
2065 (skip-chars-backward " \t")
2066 (or (memq (preceding-char) (append ";{" nil))
2067 (insert ";"))
2068 (insert "\n")
2069 (cperl-indent-line)
2070 (forward-line -1)))
5c8b7eaf 2071 (forward-line -1) ; We are on the line before target
f83d2997
KH
2072 (end-of-line)
2073 (newline-and-indent))
db133cb6 2074 (end-of-line) ; else - no splitting
f83d2997
KH
2075 (cond
2076 ((and (looking-at "\n[ \t]*{$")
2077 (save-excursion
2078 (skip-chars-backward " \t")
2079 (eq (preceding-char) ?\)))) ; Probably if () {} group
2080 ; with an extra newline.
2081 (forward-line 2)
2082 (cperl-indent-line))
db133cb6
RS
2083 ((save-excursion ; In POD header
2084 (forward-paragraph -1)
2085 ;; (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\b")
2086 ;; We are after \n now, so look for the rest
2087 (if (looking-at "\\(\\`\n?\\|\n\\)=\\sw+")
5c8b7eaf 2088 (progn
db133cb6
RS
2089 (setq cut (looking-at "\\(\\`\n?\\|\n\\)=cut\\>"))
2090 (setq over (looking-at "\\(\\`\n?\\|\n\\)=over\\>"))
2091 t)))
2092 (if (and over
2093 (progn
2094 (forward-paragraph -1)
2095 (forward-word 1)
2096 (setq pos (point))
2097 (setq cut (buffer-substring (point)
2098 (save-excursion
2099 (end-of-line)
2100 (point))))
2101 (delete-char (- (save-excursion (end-of-line) (point))
2102 (point)))
2103 (setq res (expand-abbrev))
2104 (save-excursion
2105 (goto-char pos)
2106 (insert cut))
2107 res))
2108 nil
2109 (cperl-ensure-newlines (if cut 2 4))
2110 (forward-line 2)))
2111 ((get-text-property (point) 'in-pod) ; In POD section
2112 (cperl-ensure-newlines 4)
2113 (forward-line 2))
f83d2997
KH
2114 ((looking-at "\n[ \t]*$") ; Next line is empty - use it.
2115 (forward-line 1)
2116 (cperl-indent-line))
2117 (t
2118 (newline-and-indent))))))
2119
2120(defun cperl-electric-semi (arg)
2121 "Insert character and correct line's indentation."
2122 (interactive "P")
2123 (if cperl-auto-newline
2124 (cperl-electric-terminator arg)
6c389151
SM
2125 (self-insert-command (prefix-numeric-value arg))
2126 (if cperl-autoindent-on-semi
2127 (cperl-indent-line))))
f83d2997
KH
2128
2129(defun cperl-electric-terminator (arg)
2130 "Insert character and correct line's indentation."
2131 (interactive "P")
5c8b7eaf 2132 (let (insertpos (end (point))
f83d2997
KH
2133 (auto (and cperl-auto-newline
2134 (or (not (eq last-command-char ?:))
2135 cperl-auto-newline-after-colon))))
5c8b7eaf 2136 (if (and ;;(not arg)
f83d2997
KH
2137 (eolp)
2138 (not (save-excursion
2139 (beginning-of-line)
2140 (skip-chars-forward " \t")
2141 (or
2142 ;; Ignore in comment lines
2143 (= (following-char) ?#)
2144 ;; Colon is special only after a label
2145 ;; So quickly rule out most other uses of colon
2146 ;; and do no indentation for them.
2147 (and (eq last-command-char ?:)
2148 (save-excursion
2149 (forward-word 1)
2150 (skip-chars-forward " \t")
2151 (and (< (point) end)
2152 (progn (goto-char (- end 1))
2153 (not (looking-at ":"))))))
2154 (progn
2155 (beginning-of-defun)
2156 (let ((pps (parse-partial-sexp (point) end)))
2157 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
2158 (progn
2159 (self-insert-command (prefix-numeric-value arg))
2160 ;;(forward-char -1)
2161 (if auto (setq insertpos (point-marker)))
2162 ;;(forward-char 1)
2163 (cperl-indent-line)
2164 (if auto
2165 (progn
2166 (newline)
2167 (cperl-indent-line)))
f83d2997
KH
2168 (save-excursion
2169 (if insertpos (goto-char (1- (marker-position insertpos)))
2170 (forward-char -1))
2171 (delete-char 1))))
2172 (if insertpos
2173 (save-excursion
2174 (goto-char insertpos)
2175 (self-insert-command (prefix-numeric-value arg)))
2176 (self-insert-command (prefix-numeric-value arg)))))
2177
2178(defun cperl-electric-backspace (arg)
5c8b7eaf 2179 "Backspace-untabify, or remove the whitespace around the point inserted
db133cb6 2180by an electric key."
f83d2997 2181 (interactive "p")
5c8b7eaf
SS
2182 (if (and cperl-auto-newline
2183 (memq last-command '(cperl-electric-semi
f83d2997
KH
2184 cperl-electric-terminator
2185 cperl-electric-lbrace))
2186 (memq (preceding-char) '(?\ ?\t ?\n)))
2187 (let (p)
5c8b7eaf 2188 (if (eq last-command 'cperl-electric-lbrace)
f83d2997
KH
2189 (skip-chars-forward " \t\n"))
2190 (setq p (point))
2191 (skip-chars-backward " \t\n")
2192 (delete-region (point) p))
db133cb6
RS
2193 (and (eq last-command 'cperl-electric-else)
2194 ;; We are removing the whitespace *inside* cperl-electric-else
2195 (setq this-command 'cperl-electric-else-really))
5c8b7eaf 2196 (if (and cperl-auto-newline
db133cb6
RS
2197 (eq last-command 'cperl-electric-else-really)
2198 (memq (preceding-char) '(?\ ?\t ?\n)))
2199 (let (p)
2200 (skip-chars-forward " \t\n")
2201 (setq p (point))
2202 (skip-chars-backward " \t\n")
2203 (delete-region (point) p))
2204 (backward-delete-char-untabify arg))))
f83d2997
KH
2205
2206(defun cperl-inside-parens-p ()
2207 (condition-case ()
2208 (save-excursion
2209 (save-restriction
2210 (narrow-to-region (point)
2211 (progn (beginning-of-defun) (point)))
2212 (goto-char (point-max))
2213 (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
2214 (error nil)))
2215\f
2216(defun cperl-indent-command (&optional whole-exp)
2217 "Indent current line as Perl code, or in some cases insert a tab character.
5c8b7eaf 2218If `cperl-tab-always-indent' is non-nil (the default), always indent current
db133cb6 2219line. Otherwise, indent the current line only if point is at the left margin
f83d2997
KH
2220or in the line's indentation; otherwise insert a tab.
2221
2222A numeric argument, regardless of its value,
2223means indent rigidly all the lines of the expression starting after point
2224so that this line becomes properly indented.
2225The relative indentation among the lines of the expression are preserved."
2226 (interactive "P")
5bd52f0e 2227 (cperl-update-syntaxification (point) (point))
f83d2997
KH
2228 (if whole-exp
2229 ;; If arg, always indent this line as Perl
2230 ;; and shift remaining lines of expression the same amount.
2231 (let ((shift-amt (cperl-indent-line))
2232 beg end)
2233 (save-excursion
2234 (if cperl-tab-always-indent
2235 (beginning-of-line))
2236 (setq beg (point))
2237 (forward-sexp 1)
2238 (setq end (point))
2239 (goto-char beg)
2240 (forward-line 1)
2241 (setq beg (point)))
db133cb6 2242 (if (and shift-amt (> end beg))
f83d2997
KH
2243 (indent-code-rigidly beg end shift-amt "#")))
2244 (if (and (not cperl-tab-always-indent)
2245 (save-excursion
2246 (skip-chars-backward " \t")
2247 (not (bolp))))
2248 (insert-tab)
2249 (cperl-indent-line))))
2250
5bd52f0e 2251(defun cperl-indent-line (&optional parse-data)
f83d2997
KH
2252 "Indent current line as Perl code.
2253Return the amount the indentation changed by."
db133cb6 2254 (let (indent i beg shift-amt
f83d2997
KH
2255 (case-fold-search nil)
2256 (pos (- (point-max) (point))))
5bd52f0e 2257 (setq indent (cperl-calculate-indent parse-data)
db133cb6 2258 i indent)
f83d2997
KH
2259 (beginning-of-line)
2260 (setq beg (point))
2261 (cond ((or (eq indent nil) (eq indent t))
db133cb6 2262 (setq indent (current-indentation) i nil))
f83d2997
KH
2263 ;;((eq indent t) ; Never?
2264 ;; (setq indent (cperl-calculate-indent-within-comment)))
2265 ;;((looking-at "[ \t]*#")
2266 ;; (setq indent 0))
2267 (t
2268 (skip-chars-forward " \t")
2269 (if (listp indent) (setq indent (car indent)))
2270 (cond ((looking-at "[A-Za-z_][A-Za-z_0-9]*:[^:]")
2271 (and (> indent 0)
2272 (setq indent (max cperl-min-label-indent
2273 (+ indent cperl-label-offset)))))
2274 ((= (following-char) ?})
2275 (setq indent (- indent cperl-indent-level)))
2276 ((memq (following-char) '(?\) ?\])) ; To line up with opening paren.
2277 (setq indent (+ indent cperl-close-paren-offset)))
2278 ((= (following-char) ?{)
2279 (setq indent (+ indent cperl-brace-offset))))))
2280 (skip-chars-forward " \t")
db133cb6
RS
2281 (setq shift-amt (and i (- indent (current-column))))
2282 (if (or (not shift-amt)
2283 (zerop shift-amt))
f83d2997
KH
2284 (if (> (- (point-max) pos) (point))
2285 (goto-char (- (point-max) pos)))
2286 (delete-region beg (point))
2287 (indent-to indent)
2288 ;; If initial point was within line's indentation,
2289 ;; position after the indentation. Else stay at same point in text.
2290 (if (> (- (point-max) pos) (point))
2291 (goto-char (- (point-max) pos))))
2292 shift-amt))
2293
2294(defun cperl-after-label ()
2295 ;; Returns true if the point is after label. Does not do save-excursion.
2296 (and (eq (preceding-char) ?:)
2297 (memq (char-syntax (char-after (- (point) 2)))
2298 '(?w ?_))
2299 (progn
2300 (backward-sexp)
2301 (looking-at "[a-zA-Z_][a-zA-Z0-9_]*:[^:]"))))
2302
2303(defun cperl-get-state (&optional parse-start start-state)
5bd52f0e
RS
2304 ;; returns list (START STATE DEPTH PRESTART),
2305 ;; START is a good place to start parsing, or equal to
5c8b7eaf 2306 ;; PARSE-START if preset,
5bd52f0e
RS
2307 ;; STATE is what is returned by `parse-partial-sexp'.
2308 ;; DEPTH is true is we are immediately after end of block
2309 ;; which contains START.
2310 ;; PRESTART is the position basing on which START was found.
f83d2997
KH
2311 (save-excursion
2312 (let ((start-point (point)) depth state start prestart)
5bd52f0e
RS
2313 (if (and parse-start
2314 (<= parse-start start-point))
f83d2997 2315 (goto-char parse-start)
5bd52f0e
RS
2316 (beginning-of-defun)
2317 (setq start-state nil))
f83d2997
KH
2318 (setq prestart (point))
2319 (if start-state nil
2320 ;; Try to go out, if sub is not on the outermost level
2321 (while (< (point) start-point)
2322 (setq start (point) parse-start start depth nil
2323 state (parse-partial-sexp start start-point -1))
2324 (if (> (car state) -1) nil
2325 ;; The current line could start like }}}, so the indentation
2326 ;; corresponds to a different level than what we reached
2327 (setq depth t)
2328 (beginning-of-line 2))) ; Go to the next line.
2329 (if start (goto-char start))) ; Not at the start of file
2330 (setq start (point))
f83d2997
KH
2331 (or state (setq state (parse-partial-sexp start start-point -1 nil start-state)))
2332 (list start state depth prestart))))
2333
2334(defun cperl-block-p () ; Do not C-M-q ! One string contains ";" !
2335 ;; Positions is before ?\{. Checks whether it starts a block.
2336 ;; No save-excursion!
2337 (cperl-backward-to-noncomment (point-min))
f83d2997
KH
2338 (or (memq (preceding-char) (append ";){}$@&%\C-@" nil)) ; Or label! \C-@ at bobp
2339 ; Label may be mixed up with `$blah :'
2340 (save-excursion (cperl-after-label))
2341 (and (memq (char-syntax (preceding-char)) '(?w ?_))
2342 (progn
2343 (backward-sexp)
2344 ;; Need take into account `bless', `return', `tr',...
2345 (or (and (looking-at "[a-zA-Z0-9_:]+[ \t\n\f]*[{#]") ; Method call syntax
5bd52f0e 2346 (not (looking-at "\\(bless\\|return\\|q[wqrx]?\\|tr\\|[smy]\\)\\>")))
f83d2997
KH
2347 (progn
2348 (skip-chars-backward " \t\n\f")
2349 (and (memq (char-syntax (preceding-char)) '(?w ?_))
2350 (progn
2351 (backward-sexp)
5c8b7eaf 2352 (looking-at
f83d2997
KH
2353 "sub[ \t]+[a-zA-Z0-9_:]+[ \t\n\f]*\\(([^()]*)[ \t\n\f]*\\)?[#{]")))))))))
2354
2355(defvar cperl-look-for-prop '((pod in-pod) (here-doc-delim here-doc-group)))
2356
5bd52f0e 2357(defun cperl-calculate-indent (&optional parse-data) ; was parse-start
f83d2997
KH
2358 "Return appropriate indentation for current line as Perl code.
2359In usual case returns an integer: the column to indent to.
5bd52f0e
RS
2360Returns nil if line starts inside a string, t if in a comment.
2361
2362Will not correct the indentation for labels, but will correct it for braces
2363and closing parentheses and brackets.."
f83d2997
KH
2364 (save-excursion
2365 (if (or
6c389151
SM
2366 (and (memq (get-text-property (point) 'syntax-type)
2367 '(pod here-doc here-doc-delim format))
2368 (not (get-text-property (point) 'indentable)))
f83d2997
KH
2369 ;; before start of POD - whitespace found since do not have 'pod!
2370 (and (looking-at "[ \t]*\n=")
2371 (error "Spaces before pod section!"))
2372 (and (not cperl-indent-left-aligned-comments)
2373 (looking-at "^#")))
2374 nil
2375 (beginning-of-line)
2376 (let ((indent-point (point))
2377 (char-after (save-excursion
2378 (skip-chars-forward " \t")
2379 (following-char)))
2380 (in-pod (get-text-property (point) 'in-pod))
2381 (pre-indent-point (point))
6c389151 2382 p prop look-prop is-block delim)
f83d2997 2383 (cond
5c8b7eaf 2384 (in-pod
f83d2997
KH
2385 ;; In the verbatim part, probably code example. What to do???
2386 )
5c8b7eaf 2387 (t
f83d2997
KH
2388 (save-excursion
2389 ;; Not in pod
2390 (cperl-backward-to-noncomment nil)
2391 (setq p (max (point-min) (1- (point)))
2392 prop (get-text-property p 'syntax-type)
2393 look-prop (or (nth 1 (assoc prop cperl-look-for-prop))
2394 'syntax-type))
2395 (if (memq prop '(pod here-doc format here-doc-delim))
2396 (progn
5c8b7eaf 2397 (goto-char (or (previous-single-property-change p look-prop)
f83d2997
KH
2398 (point-min)))
2399 (beginning-of-line)
2400 (setq pre-indent-point (point)))))))
2401 (goto-char pre-indent-point)
2402 (let* ((case-fold-search nil)
5bd52f0e 2403 (s-s (cperl-get-state (car parse-data) (nth 1 parse-data)))
5c8b7eaf 2404 (start (or (nth 2 parse-data)
5bd52f0e 2405 (nth 0 s-s)))
f83d2997
KH
2406 (state (nth 1 s-s))
2407 (containing-sexp (car (cdr state)))
f83d2997 2408 old-indent)
5c8b7eaf 2409 (if (and
5bd52f0e 2410 ;;containing-sexp ;; We are buggy at toplevel :-(
5c8b7eaf 2411 parse-data)
5bd52f0e
RS
2412 (progn
2413 (setcar parse-data pre-indent-point)
2414 (setcar (cdr parse-data) state)
2415 (or (nth 2 parse-data)
2416 (setcar (cddr parse-data) start))
2417 ;; Before this point: end of statement
2418 (setq old-indent (nth 3 parse-data))))
6c389151
SM
2419 (cond ((get-text-property (point) 'indentable)
2420 ;; indent to just after the surrounding open,
2421 ;; skip blanks if we do not close the expression.
2422 (goto-char (1+ (previous-single-property-change (point) 'indentable)))
2423 (or (memq char-after (append ")]}" nil))
2424 (looking-at "[ \t]*\\(#\\|$\\)")
2425 (skip-chars-forward " \t"))
2426 (current-column))
2427 ((or (nth 3 state) (nth 4 state))
f83d2997
KH
2428 ;; return nil or t if should not change this line
2429 (nth 4 state))
6c389151 2430 ;; XXXX Do we need to special-case this?
f83d2997
KH
2431 ((null containing-sexp)
2432 ;; Line is at top level. May be data or function definition,
2433 ;; or may be function argument declaration.
2434 ;; Indent like the previous top level line
2435 ;; unless that ends in a closeparen without semicolon,
2436 ;; in which case this line is the first argument decl.
2437 (skip-chars-forward " \t")
5bd52f0e
RS
2438 (+ (save-excursion
2439 (goto-char start)
2440 (- (current-indentation)
2441 (if (nth 2 s-s) cperl-indent-level 0)))
2442 (if (= char-after ?{) cperl-continued-brace-offset 0)
f83d2997 2443 (progn
5bd52f0e 2444 (cperl-backward-to-noncomment (or old-indent (point-min)))
f83d2997
KH
2445 ;; Look at previous line that's at column 0
2446 ;; to determine whether we are in top-level decls
2447 ;; or function's arg decls. Set basic-indent accordingly.
2448 ;; Now add a little if this is a continuation line.
2449 (if (or (bobp)
5bd52f0e 2450 (eq (point) old-indent) ; old-indent was at comment
db133cb6
RS
2451 (eq (preceding-char) ?\;)
2452 ;; Had ?\) too
2453 (and (eq (preceding-char) ?\})
5bd52f0e
RS
2454 (cperl-after-block-and-statement-beg
2455 (point-min))) ; Was start - too close
f83d2997
KH
2456 (memq char-after (append ")]}" nil))
2457 (and (eq (preceding-char) ?\:) ; label
2458 (progn
2459 (forward-sexp -1)
2460 (skip-chars-backward " \t")
5c8b7eaf 2461 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*[ \t]*:"))))
5bd52f0e
RS
2462 (progn
2463 (if (and parse-data
2464 (not (eq char-after ?\C-j)))
2465 (setcdr (cddr parse-data)
2466 (list pre-indent-point)))
2467 0)
f83d2997 2468 cperl-continued-statement-offset))))
6c389151
SM
2469 ((not
2470 (or (setq is-block
2471 (and (setq delim (= (char-after containing-sexp) ?{))
2472 (save-excursion ; Is it a hash?
2473 (goto-char containing-sexp)
2474 (cperl-block-p))))
2475 cperl-indent-parens-as-block))
2476 ;; group is an expression, not a block:
2477 ;; indent to just after the surrounding open parens,
f83d2997
KH
2478 ;; skip blanks if we do not close the expression.
2479 (goto-char (1+ containing-sexp))
2480 (or (memq char-after (append ")]}" nil))
2481 (looking-at "[ \t]*\\(#\\|$\\)")
2482 (skip-chars-forward " \t"))
2483 (current-column))
2484 ((progn
2485 ;; Containing-expr starts with \{. Check whether it is a hash.
2486 (goto-char containing-sexp)
2487 (not (cperl-block-p)))
2488 (goto-char (1+ containing-sexp))
6c389151
SM
2489 (or (memq char-after
2490 (append (if delim "}" ")]}") nil))
f83d2997
KH
2491 (looking-at "[ \t]*\\(#\\|$\\)")
2492 (skip-chars-forward " \t"))
6c389151
SM
2493 (+ (current-column)
2494 (if (and delim
2495 (eq char-after ?\}))
2496 ;; Correct indentation of trailing ?\}
2497 (+ cperl-indent-level cperl-close-paren-offset)
f83d2997 2498 0)))
6c389151
SM
2499;;; ((and (/= (char-after containing-sexp) ?{)
2500;;; (not cperl-indent-parens-as-block))
2501;;; ;; line is expression, not statement:
2502;;; ;; indent to just after the surrounding open,
2503;;; ;; skip blanks if we do not close the expression.
2504;;; (goto-char (1+ containing-sexp))
2505;;; (or (memq char-after (append ")]}" nil))
2506;;; (looking-at "[ \t]*\\(#\\|$\\)")
2507;;; (skip-chars-forward " \t"))
2508;;; (current-column))
2509;;; ((progn
2510;;; ;; Containing-expr starts with \{. Check whether it is a hash.
2511;;; (goto-char containing-sexp)
2512;;; (and (not (cperl-block-p))
2513;;; (not cperl-indent-parens-as-block)))
2514;;; (goto-char (1+ containing-sexp))
2515;;; (or (eq char-after ?\})
2516;;; (looking-at "[ \t]*\\(#\\|$\\)")
2517;;; (skip-chars-forward " \t"))
2518;;; (+ (current-column) ; Correct indentation of trailing ?\}
2519;;; (if (eq char-after ?\}) (+ cperl-indent-level
2520;;; cperl-close-paren-offset)
2521;;; 0)))
f83d2997
KH
2522 (t
2523 ;; Statement level. Is it a continuation or a new statement?
2524 ;; Find previous non-comment character.
2525 (goto-char pre-indent-point)
2526 (cperl-backward-to-noncomment containing-sexp)
2527 ;; Back up over label lines, since they don't
2528 ;; affect whether our line is a continuation.
5bd52f0e
RS
2529 ;; (Had \, too)
2530 (while ;;(or (eq (preceding-char) ?\,)
f83d2997
KH
2531 (and (eq (preceding-char) ?:)
2532 (or;;(eq (char-after (- (point) 2)) ?\') ; ????
2533 (memq (char-syntax (char-after (- (point) 2)))
5bd52f0e
RS
2534 '(?w ?_))))
2535 ;;)
f83d2997
KH
2536 (if (eq (preceding-char) ?\,)
2537 ;; Will go to beginning of line, essentially.
2538 ;; Will ignore embedded sexpr XXXX.
2539 (cperl-backward-to-start-of-continued-exp containing-sexp))
2540 (beginning-of-line)
2541 (cperl-backward-to-noncomment containing-sexp))
2542 ;; Now we get the answer.
6c389151
SM
2543 (if (not (or (eq (1- (point)) containing-sexp)
2544 (memq (preceding-char)
2545 (append (if is-block " ;{" " ,;{") '(nil)))
db133cb6 2546 (and (eq (preceding-char) ?\})
6c389151
SM
2547 (cperl-after-block-and-statement-beg
2548 containing-sexp))))
f83d2997
KH
2549 ;; This line is continuation of preceding line's statement;
2550 ;; indent `cperl-continued-statement-offset' more than the
2551 ;; previous line of the statement.
5bd52f0e
RS
2552 ;;
2553 ;; There might be a label on this line, just
2554 ;; consider it bad style and ignore it.
f83d2997
KH
2555 (progn
2556 (cperl-backward-to-start-of-continued-exp containing-sexp)
2557 (+ (if (memq char-after (append "}])" nil))
2558 0 ; Closing parenth
2559 cperl-continued-statement-offset)
6c389151
SM
2560 (if (or is-block
2561 (not delim)
2562 (not (eq char-after ?\})))
2563 0
2564 ;; Now it is a hash reference
2565 (+ cperl-indent-level cperl-close-paren-offset))
5bd52f0e
RS
2566 (if (looking-at "\\w+[ \t]*:")
2567 (if (> (current-indentation) cperl-min-label-indent)
2568 (- (current-indentation) cperl-label-offset)
2569 ;; Do not move `parse-data', this should
5c8b7eaf 2570 ;; be quick anyway (this comment comes
f94a632a 2571 ;; from different location):
5bd52f0e
RS
2572 (cperl-calculate-indent))
2573 (current-column))
f83d2997
KH
2574 (if (eq char-after ?\{)
2575 cperl-continued-brace-offset 0)))
2576 ;; This line starts a new statement.
2577 ;; Position following last unclosed open.
2578 (goto-char containing-sexp)
2579 ;; Is line first statement after an open-brace?
2580 (or
2581 ;; If no, find that first statement and indent like
2582 ;; it. If the first statement begins with label, do
2583 ;; not believe when the indentation of the label is too
2584 ;; small.
2585 (save-excursion
2586 (forward-char 1)
2587 (setq old-indent (current-indentation))
2588 (let ((colon-line-end 0))
2589 (while (progn (skip-chars-forward " \t\n")
2590 (looking-at "#\\|[a-zA-Z0-9_$]*:[^:]"))
2591 ;; Skip over comments and labels following openbrace.
2592 (cond ((= (following-char) ?\#)
2593 (forward-line 1))
2594 ;; label:
2595 (t
2596 (save-excursion (end-of-line)
2597 (setq colon-line-end (point)))
2598 (search-forward ":"))))
2599 ;; The first following code counts
2600 ;; if it is before the line we want to indent.
2601 (and (< (point) indent-point)
2602 (if (> colon-line-end (point)) ; After label
5c8b7eaf 2603 (if (> (current-indentation)
f83d2997
KH
2604 cperl-min-label-indent)
2605 (- (current-indentation) cperl-label-offset)
2606 ;; Do not believe: `max' is involved
2607 (+ old-indent cperl-indent-level))
2608 (current-column)))))
2609 ;; If no previous statement,
2610 ;; indent it relative to line brace is on.
2611 ;; For open brace in column zero, don't let statement
2612 ;; start there too. If cperl-indent-level is zero,
2613 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
2614 ;; For open-braces not the first thing in a line,
2615 ;; add in cperl-brace-imaginary-offset.
2616
2617 ;; If first thing on a line: ?????
2618 (+ (if (and (bolp) (zerop cperl-indent-level))
2619 (+ cperl-brace-offset cperl-continued-statement-offset)
2620 cperl-indent-level)
6c389151
SM
2621 (if (or is-block
2622 (not delim)
2623 (not (eq char-after ?\})))
2624 0
2625 ;; Now it is a hash reference
2626 (+ cperl-indent-level cperl-close-paren-offset))
f83d2997
KH
2627 ;; Move back over whitespace before the openbrace.
2628 ;; If openbrace is not first nonwhite thing on the line,
2629 ;; add the cperl-brace-imaginary-offset.
2630 (progn (skip-chars-backward " \t")
2631 (if (bolp) 0 cperl-brace-imaginary-offset))
2632 ;; If the openbrace is preceded by a parenthesized exp,
2633 ;; move to the beginning of that;
2634 ;; possibly a different line
2635 (progn
2636 (if (eq (preceding-char) ?\))
2637 (forward-sexp -1))
2638 ;; In the case it starts a subroutine, indent with
110c171f 2639 ;; respect to `sub', not with respect to the
f83d2997
KH
2640 ;; first thing on the line, say in the case of
2641 ;; anonymous sub in a hash.
2642 ;;
2643 (skip-chars-backward " \t")
2644 (if (and (eq (preceding-char) ?b)
2645 (progn
2646 (forward-sexp -1)
2647 (looking-at "sub\\>"))
5c8b7eaf
SS
2648 (setq old-indent
2649 (nth 1
2650 (parse-partial-sexp
2651 (save-excursion (beginning-of-line) (point))
f83d2997
KH
2652 (point)))))
2653 (progn (goto-char (1+ old-indent))
2654 (skip-chars-forward " \t")
2655 (current-column))
2656 ;; Get initial indentation of the line we are on.
2657 ;; If line starts with label, calculate label indentation
2658 (if (save-excursion
2659 (beginning-of-line)
2660 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
2661 (if (> (current-indentation) cperl-min-label-indent)
2662 (- (current-indentation) cperl-label-offset)
5bd52f0e
RS
2663 ;; Do not move `parse-data', this should
2664 ;; be quick anyway:
2665 (cperl-calculate-indent))
f83d2997
KH
2666 (current-indentation))))))))))))))
2667
2668(defvar cperl-indent-alist
2669 '((string nil)
2670 (comment nil)
2671 (toplevel 0)
2672 (toplevel-after-parenth 2)
2673 (toplevel-continued 2)
2674 (expression 1))
2675 "Alist of indentation rules for CPerl mode.
2676The values mean:
2677 nil: do not indent;
db133cb6
RS
2678 number: add this amount of indentation.
2679
2680Not finished, not used.")
f83d2997
KH
2681
2682(defun cperl-where-am-i (&optional parse-start start-state)
2683 ;; Unfinished
2684 "Return a list of lists ((TYPE POS)...) of good points before the point.
db133cb6
RS
2685POS may be nil if it is hard to find, say, when TYPE is `string' or `comment'.
2686
2687Not finished, not used."
f83d2997
KH
2688 (save-excursion
2689 (let* ((start-point (point))
2690 (s-s (cperl-get-state))
2691 (start (nth 0 s-s))
2692 (state (nth 1 s-s))
2693 (prestart (nth 3 s-s))
2694 (containing-sexp (car (cdr state)))
2695 (case-fold-search nil)
2696 (res (list (list 'parse-start start) (list 'parse-prestart prestart))))
2697 (cond ((nth 3 state) ; In string
2698 (setq res (cons (list 'string nil (nth 3 state)) res))) ; What started string
2699 ((nth 4 state) ; In comment
2700 (setq res (cons '(comment) res)))
2701 ((null containing-sexp)
5c8b7eaf 2702 ;; Line is at top level.
f83d2997
KH
2703 ;; Indent like the previous top level line
2704 ;; unless that ends in a closeparen without semicolon,
2705 ;; in which case this line is the first argument decl.
2706 (cperl-backward-to-noncomment (or parse-start (point-min)))
2707 ;;(skip-chars-backward " \t\f\n")
2708 (cond
2709 ((or (bobp)
2710 (memq (preceding-char) (append ";}" nil)))
2711 (setq res (cons (list 'toplevel start) res)))
2712 ((eq (preceding-char) ?\) )
2713 (setq res (cons (list 'toplevel-after-parenth start) res)))
5c8b7eaf 2714 (t
f83d2997
KH
2715 (setq res (cons (list 'toplevel-continued start) res)))))
2716 ((/= (char-after containing-sexp) ?{)
2717 ;; line is expression, not statement:
2718 ;; indent to just after the surrounding open.
2719 ;; skip blanks if we do not close the expression.
2720 (setq res (cons (list 'expression-blanks
2721 (progn
2722 (goto-char (1+ containing-sexp))
2723 (or (looking-at "[ \t]*\\(#\\|$\\)")
2724 (skip-chars-forward " \t"))
2725 (point)))
2726 (cons (list 'expression containing-sexp) res))))
2727 ((progn
2728 ;; Containing-expr starts with \{. Check whether it is a hash.
2729 (goto-char containing-sexp)
2730 (not (cperl-block-p)))
2731 (setq res (cons (list 'expression-blanks
2732 (progn
2733 (goto-char (1+ containing-sexp))
2734 (or (looking-at "[ \t]*\\(#\\|$\\)")
2735 (skip-chars-forward " \t"))
2736 (point)))
2737 (cons (list 'expression containing-sexp) res))))
2738 (t
2739 ;; Statement level.
2740 (setq res (cons (list 'in-block containing-sexp) res))
2741 ;; Is it a continuation or a new statement?
2742 ;; Find previous non-comment character.
2743 (cperl-backward-to-noncomment containing-sexp)
2744 ;; Back up over label lines, since they don't
2745 ;; affect whether our line is a continuation.
2746 ;; Back up comma-delimited lines too ?????
2747 (while (or (eq (preceding-char) ?\,)
2748 (save-excursion (cperl-after-label)))
2749 (if (eq (preceding-char) ?\,)
2750 ;; Will go to beginning of line, essentially
2751 ;; Will ignore embedded sexpr XXXX.
2752 (cperl-backward-to-start-of-continued-exp containing-sexp))
2753 (beginning-of-line)
2754 (cperl-backward-to-noncomment containing-sexp))
2755 ;; Now we get the answer.
2756 (if (not (memq (preceding-char) (append ";}{" '(nil)))) ; Was ?\,
2757 ;; This line is continuation of preceding line's statement.
2758 (list (list 'statement-continued containing-sexp))
2759 ;; This line starts a new statement.
2760 ;; Position following last unclosed open.
2761 (goto-char containing-sexp)
2762 ;; Is line first statement after an open-brace?
2763 (or
2764 ;; If no, find that first statement and indent like
2765 ;; it. If the first statement begins with label, do
2766 ;; not believe when the indentation of the label is too
2767 ;; small.
2768 (save-excursion
2769 (forward-char 1)
2770 (let ((colon-line-end 0))
2771 (while (progn (skip-chars-forward " \t\n" start-point)
2772 (and (< (point) start-point)
2773 (looking-at
2774 "#\\|[a-zA-Z_][a-zA-Z0-9_]*:[^:]")))
2775 ;; Skip over comments and labels following openbrace.
2776 (cond ((= (following-char) ?\#)
2777 ;;(forward-line 1)
2778 (end-of-line))
2779 ;; label:
2780 (t
2781 (save-excursion (end-of-line)
2782 (setq colon-line-end (point)))
2783 (search-forward ":"))))
5c8b7eaf 2784 ;; Now at the point, after label, or at start
f83d2997
KH
2785 ;; of first statement in the block.
2786 (and (< (point) start-point)
5c8b7eaf 2787 (if (> colon-line-end (point))
f83d2997 2788 ;; Before statement after label
5c8b7eaf 2789 (if (> (current-indentation)
f83d2997
KH
2790 cperl-min-label-indent)
2791 (list (list 'label-in-block (point)))
2792 ;; Do not believe: `max' is involved
2793 (list
2794 (list 'label-in-block-min-indent (point))))
2795 ;; Before statement
2796 (list 'statement-in-block (point))))))
2797 ;; If no previous statement,
2798 ;; indent it relative to line brace is on.
2799 ;; For open brace in column zero, don't let statement
2800 ;; start there too. If cperl-indent-level is zero,
2801 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
2802 ;; For open-braces not the first thing in a line,
2803 ;; add in cperl-brace-imaginary-offset.
2804
2805 ;; If first thing on a line: ?????
2806 (+ (if (and (bolp) (zerop cperl-indent-level))
2807 (+ cperl-brace-offset cperl-continued-statement-offset)
2808 cperl-indent-level)
2809 ;; Move back over whitespace before the openbrace.
2810 ;; If openbrace is not first nonwhite thing on the line,
2811 ;; add the cperl-brace-imaginary-offset.
2812 (progn (skip-chars-backward " \t")
2813 (if (bolp) 0 cperl-brace-imaginary-offset))
2814 ;; If the openbrace is preceded by a parenthesized exp,
2815 ;; move to the beginning of that;
2816 ;; possibly a different line
2817 (progn
2818 (if (eq (preceding-char) ?\))
2819 (forward-sexp -1))
2820 ;; Get initial indentation of the line we are on.
2821 ;; If line starts with label, calculate label indentation
2822 (if (save-excursion
2823 (beginning-of-line)
2824 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
2825 (if (> (current-indentation) cperl-min-label-indent)
2826 (- (current-indentation) cperl-label-offset)
5bd52f0e 2827 (cperl-calculate-indent))
f83d2997
KH
2828 (current-indentation))))))))
2829 res)))
2830
2831(defun cperl-calculate-indent-within-comment ()
2832 "Return the indentation amount for line, assuming that
2833the current line is to be regarded as part of a block comment."
2834 (let (end star-start)
2835 (save-excursion
2836 (beginning-of-line)
2837 (skip-chars-forward " \t")
2838 (setq end (point))
2839 (and (= (following-char) ?#)
2840 (forward-line -1)
2841 (cperl-to-comment-or-eol)
2842 (setq end (point)))
2843 (goto-char end)
2844 (current-column))))
2845
2846
2847(defun cperl-to-comment-or-eol ()
029cb4d5 2848 "Go to position before comment on the current line, or to end of line.
f83d2997
KH
2849Returns true if comment is found."
2850 (let (state stop-in cpoint (lim (progn (end-of-line) (point))))
2851 (beginning-of-line)
5c8b7eaf 2852 (if (or
f83d2997
KH
2853 (eq (get-text-property (point) 'syntax-type) 'pod)
2854 (re-search-forward "\\=[ \t]*\\(#\\|$\\)" lim t))
2855 (if (eq (preceding-char) ?\#) (progn (backward-char 1) t))
2856 ;; Else
2857 (while (not stop-in)
2858 (setq state (parse-partial-sexp (point) lim nil nil nil t))
2859 ; stop at comment
2860 ;; If fails (beginning-of-line inside sexp), then contains not-comment
f83d2997
KH
2861 (if (nth 4 state) ; After `#';
2862 ; (nth 2 state) can be
2863 ; beginning of m,s,qq and so
2864 ; on
2865 (if (nth 2 state)
2866 (progn
2867 (setq cpoint (point))
2868 (goto-char (nth 2 state))
2869 (cond
2870 ((looking-at "\\(s\\|tr\\)\\>")
2871 (or (re-search-forward
2872 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*"
2873 lim 'move)
2874 (setq stop-in t)))
5bd52f0e 2875 ((looking-at "\\(m\\|q\\([qxwr]\\)?\\)\\>")
f83d2997
KH
2876 (or (re-search-forward
2877 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#"
2878 lim 'move)
2879 (setq stop-in t)))
2880 (t ; It was fair comment
2881 (setq stop-in t) ; Finish
2882 (goto-char (1- cpoint)))))
2883 (setq stop-in t) ; Finish
2884 (forward-char -1))
2885 (setq stop-in t)) ; Finish
2886 )
2887 (nth 4 state))))
2888
2889(defsubst cperl-1- (p)
2890 (max (point-min) (1- p)))
2891
2892(defsubst cperl-1+ (p)
2893 (min (point-max) (1+ p)))
2894
f83d2997
KH
2895(defsubst cperl-modify-syntax-type (at how)
2896 (if (< at (point-max))
2897 (progn
2898 (put-text-property at (1+ at) 'syntax-table how)
2899 (put-text-property at (1+ at) 'rear-nonsticky t))))
2900
2901(defun cperl-protect-defun-start (s e)
2902 ;; C code looks for "^\\s(" to skip comment backward in "hard" situations
2903 (save-excursion
2904 (goto-char s)
2905 (while (re-search-forward "^\\s(" e 'to-end)
2906 (put-text-property (1- (point)) (point) 'syntax-table cperl-st-punct))))
2907
5bd52f0e 2908(defun cperl-commentify (bb e string &optional noface)
5c8b7eaf 2909 (if cperl-use-syntax-table-text-property
5bd52f0e
RS
2910 (if (eq noface 'n) ; Only immediate
2911 nil
f83d2997
KH
2912 ;; We suppose that e is _after_ the end of construction, as after eol.
2913 (setq string (if string cperl-st-sfence cperl-st-cfence))
6c389151
SM
2914 (if (> bb (- e 2))
2915 ;; one-char string/comment?!
2916 (cperl-modify-syntax-type bb cperl-st-punct)
2917 (cperl-modify-syntax-type bb string)
2918 (cperl-modify-syntax-type (1- e) string))
f83d2997 2919 (if (and (eq string cperl-st-sfence) (> (- e 2) bb))
5c8b7eaf 2920 (put-text-property (1+ bb) (1- e)
f83d2997 2921 'syntax-table cperl-string-syntax-table))
5bd52f0e
RS
2922 (cperl-protect-defun-start bb e))
2923 ;; Fontify
2924 (or noface
2925 (not cperl-pod-here-fontify)
2926 (put-text-property bb e 'face (if string 'font-lock-string-face
2927 'font-lock-comment-face)))))
6c389151 2928
5bd52f0e
RS
2929(defvar cperl-starters '(( ?\( . ?\) )
2930 ( ?\[ . ?\] )
2931 ( ?\{ . ?\} )
2932 ( ?\< . ?\> )))
f83d2997
KH
2933
2934(defun cperl-forward-re (lim end is-2arg set-st st-l err-l argument
2935 &optional ostart oend)
2936 ;; Works *before* syntax recognition is done
2937 ;; May modify syntax-type text property if the situation is too hard
6c389151 2938 (let (b starter ender st i i2 go-forward reset-st)
f83d2997
KH
2939 (skip-chars-forward " \t")
2940 ;; ender means matching-char matcher.
5c8b7eaf 2941 (setq b (point)
5bd52f0e
RS
2942 starter (if (eobp) 0 (char-after b))
2943 ender (cdr (assoc starter cperl-starters)))
f83d2997
KH
2944 ;; What if starter == ?\\ ????
2945 (if set-st
2946 (if (car st-l)
2947 (setq st (car st-l))
2948 (setcar st-l (make-syntax-table))
2949 (setq i 0 st (car st-l))
2950 (while (< i 256)
2951 (modify-syntax-entry i "." st)
2952 (setq i (1+ i)))
2953 (modify-syntax-entry ?\\ "\\" st)))
2954 (setq set-st t)
2955 ;; Whether we have an intermediate point
2956 (setq i nil)
2957 ;; Prepare the syntax table:
2958 (and set-st
2959 (if (not ender) ; m/blah/, s/x//, s/x/y/
2960 (modify-syntax-entry starter "$" st)
2961 (modify-syntax-entry starter (concat "(" (list ender)) st)
2962 (modify-syntax-entry ender (concat ")" (list starter)) st)))
2963 (condition-case bb
2964 (progn
5bd52f0e
RS
2965 ;; We use `$' syntax class to find matching stuff, but $$
2966 ;; is recognized the same as $, so we need to check this manually.
f83d2997
KH
2967 (if (and (eq starter (char-after (cperl-1+ b)))
2968 (not ender))
2969 ;; $ has TeXish matching rules, so $$ equiv $...
2970 (forward-char 2)
6c389151 2971 (setq reset-st (syntax-table))
f83d2997
KH
2972 (set-syntax-table st)
2973 (forward-sexp 1)
6c389151
SM
2974 (if (<= (point) (1+ b))
2975 (error "Unfinished regular expression"))
2976 (set-syntax-table reset-st)
2977 (setq reset-st nil)
f83d2997
KH
2978 ;; Now the problem is with m;blah;;
2979 (and (not ender)
2980 (eq (preceding-char)
2981 (char-after (- (point) 2)))
2982 (save-excursion
2983 (forward-char -2)
2984 (= 0 (% (skip-chars-backward "\\\\") 2)))
2985 (forward-char -1)))
5bd52f0e 2986 ;; Now we are after the first part.
f83d2997
KH
2987 (and is-2arg ; Have trailing part
2988 (not ender)
2989 (eq (following-char) starter) ; Empty trailing part
2990 (progn
2991 (or (eq (char-syntax (following-char)) ?.)
2992 ;; Make trailing letter into punctuation
2993 (cperl-modify-syntax-type (point) cperl-st-punct))
2994 (setq is-2arg nil go-forward t))) ; Ignore the tail
2995 (if is-2arg ; Not number => have second part
2996 (progn
2997 (setq i (point) i2 i)
2998 (if ender
2999 (if (memq (following-char) '(?\ ?\t ?\n ?\f))
3000 (progn
3001 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
3002 (goto-char (match-end 0))
3003 (skip-chars-forward " \t\n\f"))
3004 (setq i2 (point))))
3005 (forward-char -1))
3006 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
5c8b7eaf 3007 (if ender (modify-syntax-entry ender "." st))
f83d2997 3008 (setq set-st nil)
5bd52f0e
RS
3009 (setq ender (cperl-forward-re lim end nil t st-l err-l
3010 argument starter ender)
f83d2997
KH
3011 ender (nth 2 ender)))))
3012 (error (goto-char lim)
3013 (setq set-st nil)
6c389151
SM
3014 (if reset-st
3015 (set-syntax-table reset-st))
f83d2997
KH
3016 (or end
3017 (message
5bd52f0e 3018 "End of `%s%s%c ... %c' string/RE not found: %s"
f83d2997
KH
3019 argument
3020 (if ostart (format "%c ... %c" ostart (or oend ostart)) "")
3021 starter (or ender starter) bb)
3022 (or (car err-l) (setcar err-l b)))))
3023 (if set-st
3024 (progn
3025 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
3026 (if ender (modify-syntax-entry ender "." st))))
5bd52f0e
RS
3027 ;; i: have 2 args, after end of the first arg
3028 ;; i2: start of the second arg, if any (before delim iff `ender').
3029 ;; ender: the last arg bounded by parens-like chars, the second one of them
3030 ;; starter: the starting delimiter of the first arg
5efe6a56 3031 ;; go-forward: has 2 args, and the second part is empty
f83d2997
KH
3032 (list i i2 ender starter go-forward)))
3033
5c8b7eaf 3034(defsubst cperl-postpone-fontification (b e type val &optional now)
5bd52f0e
RS
3035 ;; Do after syntactic fontification?
3036 (if cperl-syntaxify-by-font-lock
3037 (or now (put-text-property b e 'cperl-postpone (cons type val)))
3038 (put-text-property b e type val)))
3039
3040;;; Here is how the global structures (those which cannot be
3041;;; recognized locally) are marked:
5c8b7eaf 3042;; a) PODs:
5bd52f0e
RS
3043;; Start-to-end is marked `in-pod' ==> t
3044;; Each non-literal part is marked `syntax-type' ==> `pod'
3045;; Each literal part is marked `syntax-type' ==> `in-pod'
5c8b7eaf 3046;; b) HEREs:
5bd52f0e
RS
3047;; Start-to-end is marked `here-doc-group' ==> t
3048;; The body is marked `syntax-type' ==> `here-doc'
3049;; The delimiter is marked `syntax-type' ==> `here-doc-delim'
5c8b7eaf 3050;; c) FORMATs:
5bd52f0e 3051;; After-initial-line--to-end is marked `syntax-type' ==> `format'
5c8b7eaf 3052;; d) 'Q'uoted string:
5bd52f0e 3053;; part between markers inclusive is marked `syntax-type' ==> `string'
6c389151 3054;; part between `q' and the first marker is marked `syntax-type' ==> `prestring'
5bd52f0e
RS
3055
3056(defun cperl-unwind-to-safe (before &optional end)
3057 ;; if BEFORE, go to the previous start-of-line on each step of unwinding
3058 (let ((pos (point)) opos)
3059 (setq opos pos)
3060 (while (and pos (get-text-property pos 'syntax-type))
3061 (setq pos (previous-single-property-change pos 'syntax-type))
3062 (if pos
3063 (if before
3064 (progn
3065 (goto-char (cperl-1- pos))
3066 (beginning-of-line)
3067 (setq pos (point)))
3068 (goto-char (setq pos (cperl-1- pos))))
3069 ;; Up to the start
3070 (goto-char (point-min))))
6c389151
SM
3071 ;; Skip empty lines
3072 (and (looking-at "\n*=")
3073 (/= 0 (skip-chars-backward "\n"))
3074 (forward-char))
3075 (setq pos (point))
5bd52f0e
RS
3076 (if end
3077 ;; Do the same for end, going small steps
3078 (progn
3079 (while (and end (get-text-property end 'syntax-type))
3080 (setq pos end
3081 end (next-single-property-change end 'syntax-type)))
3082 (or end pos)))))
3083
6c389151
SM
3084(defvar cperl-nonoverridable-face)
3085(defvar font-lock-function-name-face)
3086(defvar font-lock-comment-face)
3087
db133cb6 3088(defun cperl-find-pods-heres (&optional min max non-inter end ignore-max)
f83d2997 3089 "Scans the buffer for hard-to-parse Perl constructions.
5c8b7eaf
SS
3090If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify
3091the sections using `cperl-pod-head-face', `cperl-pod-face',
f83d2997
KH
3092`cperl-here-face'."
3093 (interactive)
db133cb6
RS
3094 (or min (setq min (point-min)
3095 cperl-syntax-state nil
3096 cperl-syntax-done-to min))
f83d2997 3097 (or max (setq max (point-max)))
5bd52f0e 3098 (let* (face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb
6c389151
SM
3099 is-REx is-x-REx REx-comment-start REx-comment-end was-comment i2
3100 (cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend
db133cb6
RS
3101 (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
3102 (modified (buffer-modified-p))
3103 (after-change-functions nil)
3104 (use-syntax-state (and cperl-syntax-state
3105 (>= min (car cperl-syntax-state))))
3106 (state-point (if use-syntax-state
3107 (car cperl-syntax-state)
3108 (point-min)))
3109 (state (if use-syntax-state
3110 (cdr cperl-syntax-state)))
6c389151
SM
3111 ;; (st-l '(nil)) (err-l '(nil)) ; Would overwrite - propagates from a function call to a function call!
3112 (st-l (list nil)) (err-l (list nil))
db133cb6
RS
3113 ;; Somehow font-lock may be not loaded yet...
3114 (font-lock-string-face (if (boundp 'font-lock-string-face)
3115 font-lock-string-face
3116 'font-lock-string-face))
5bd52f0e
RS
3117 (font-lock-constant-face (if (boundp 'font-lock-constant-face)
3118 font-lock-constant-face
3119 'font-lock-constant-face))
5c8b7eaf 3120 (font-lock-function-name-face
5bd52f0e
RS
3121 (if (boundp 'font-lock-function-name-face)
3122 font-lock-function-name-face
3123 'font-lock-function-name-face))
6c389151
SM
3124 (font-lock-comment-face
3125 (if (boundp 'font-lock-comment-face)
3126 font-lock-comment-face
3127 'font-lock-comment-face))
3128 (cperl-nonoverridable-face
5bd52f0e
RS
3129 (if (boundp 'cperl-nonoverridable-face)
3130 cperl-nonoverridable-face
3131 'cperl-nonoverridable-face))
5c8b7eaf 3132 (stop-point (if ignore-max
db133cb6
RS
3133 (point-max)
3134 max))
3135 (search
3136 (concat
6c389151 3137 "\\(\\`\n?\\|^\n\\)="
db133cb6
RS
3138 "\\|"
3139 ;; One extra () before this:
5c8b7eaf 3140 "<<"
5bd52f0e 3141 "\\(" ; 1 + 1
db133cb6 3142 ;; First variant "BLAH" or just ``.
6c389151
SM
3143 "[ \t]*" ; Yes, whitespace is allowed!
3144 "\\([\"'`]\\)" ; 2 + 1 = 3
5bd52f0e 3145 "\\([^\"'`\n]*\\)" ; 3 + 1
db133cb6
RS
3146 "\\3"
3147 "\\|"
5bd52f0e
RS
3148 ;; Second variant: Identifier or \ID or empty
3149 "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
3150 ;; Do not have <<= or << 30 or <<30 or << $blah.
3151 ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
3152 "\\(\\)" ; To preserve count of pars :-( 6 + 1
db133cb6
RS
3153 "\\)"
3154 "\\|"
3155 ;; 1+6 extra () before this:
3156 "^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
3157 (if cperl-use-syntax-table-text-property
3158 (concat
3159 "\\|"
3160 ;; 1+6+2=9 extra () before this:
5bd52f0e 3161 "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
db133cb6
RS
3162 "\\|"
3163 ;; 1+6+2+1=10 extra () before this:
5bd52f0e 3164 "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
db133cb6
RS
3165 "\\|"
3166 ;; 1+6+2+1+1=11 extra () before this:
3167 "\\<sub\\>[ \t]*\\([a-zA-Z_:'0-9]+[ \t]*\\)?\\(([^()]*)\\)"
3168 "\\|"
3169 ;; 1+6+2+1+1+2=13 extra () before this:
3170 "\\$\\(['{]\\)"
3171 "\\|"
3172 ;; 1+6+2+1+1+2+1=14 extra () before this:
3173 "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'"
3174 ;; 1+6+2+1+1+2+1+1=15 extra () before this:
3175 "\\|"
6c389151
SM
3176 "__\\(END\\|DATA\\)__"
3177 ;; 1+6+2+1+1+2+1+1+1=16 extra () before this:
3178 "\\|"
3179 "\\\\\\(['`\"]\\)"
db133cb6
RS
3180 )
3181 ""))))
f83d2997
KH
3182 (unwind-protect
3183 (progn
3184 (save-excursion
3185 (or non-inter
3186 (message "Scanning for \"hard\" Perl constructions..."))
db133cb6 3187 (and cperl-pod-here-fontify
f83d2997
KH
3188 ;; We had evals here, do not know why...
3189 (setq face cperl-pod-face
3190 head-face cperl-pod-head-face
3191 here-face cperl-here-face))
5c8b7eaf 3192 (remove-text-properties min max
5bd52f0e 3193 '(syntax-type t in-pod t syntax-table t
6c389151
SM
3194 cperl-postpone t
3195 syntax-subtype t
3196 rear-nonsticky t
3197 indentable t))
f83d2997
KH
3198 ;; Need to remove face as well...
3199 (goto-char min)
db133cb6
RS
3200 (and (eq system-type 'emx)
3201 (looking-at "extproc[ \t]") ; Analogue of #!
5c8b7eaf 3202 (cperl-commentify min
db133cb6
RS
3203 (save-excursion (end-of-line) (point))
3204 nil))
3205 (while (and
3206 (< (point) max)
3207 (re-search-forward search max t))
5bd52f0e 3208 (setq tmpend nil) ; Valid for most cases
5c8b7eaf 3209 (cond
f83d2997 3210 ((match-beginning 1) ; POD section
6c389151
SM
3211 ;; "\\(\\`\n?\\|^\n\\)="
3212 (if (looking-at "cut\\>")
5bd52f0e
RS
3213 (if ignore-max
3214 nil ; Doing a chunk only
f83d2997
KH
3215 (message "=cut is not preceded by a POD section")
3216 (or (car err-l) (setcar err-l (point))))
3217 (beginning-of-line)
5c8b7eaf
SS
3218
3219 (setq b (point)
5bd52f0e
RS
3220 bb b
3221 tb (match-beginning 0)
3222 b1 nil) ; error condition
db133cb6
RS
3223 ;; We do not search to max, since we may be called from
3224 ;; some hook of fontification, and max is random
6c389151 3225 (or (re-search-forward "^\n=cut\\>" stop-point 'toend)
f83d2997 3226 (progn
6c389151
SM
3227 (goto-char b)
3228 (if (re-search-forward "\n=cut\\>" stop-point 'toend)
3229 (progn
3230 (message "=cut is not preceded by an empty line")
3231 (setq b1 t)
3232 (or (car err-l) (setcar err-l b))))))
f83d2997
KH
3233 (beginning-of-line 2) ; An empty line after =cut is not POD!
3234 (setq e (point))
db133cb6 3235 (and (> e max)
6c389151
SM
3236 (progn
3237 (remove-text-properties
3238 max e '(syntax-type t in-pod t syntax-table t
3239 cperl-postpone t
3240 syntax-subtype t
3241 rear-nonsticky t
3242 indentable t))
3243 (setq tmpend tb)))
f83d2997 3244 (put-text-property b e 'in-pod t)
6c389151 3245 (put-text-property b e 'syntax-type 'in-pod)
f83d2997
KH
3246 (goto-char b)
3247 (while (re-search-forward "\n\n[ \t]" e t)
3248 ;; We start 'pod 1 char earlier to include the preceding line
3249 (beginning-of-line)
3250 (put-text-property (cperl-1- b) (point) 'syntax-type 'pod)
5efe6a56
SM
3251 (cperl-put-do-not-fontify b (point) t)
3252 ;; mark the non-literal parts as PODs
3253 (if cperl-pod-here-fontify
3254 (cperl-postpone-fontification b (point) 'face face t))
f83d2997
KH
3255 (re-search-forward "\n\n[^ \t\f\n]" e 'toend)
3256 (beginning-of-line)
3257 (setq b (point)))
3258 (put-text-property (cperl-1- (point)) e 'syntax-type 'pod)
5efe6a56
SM
3259 (cperl-put-do-not-fontify (point) e t)
3260 (if cperl-pod-here-fontify
3261 (progn
3262 ;; mark the non-literal parts as PODs
3263 (cperl-postpone-fontification (point) e 'face face t)
3264 (goto-char bb)
3265 (if (looking-at
3266 "=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$")
3267 ;; mark the headers
3268 (cperl-postpone-fontification
3269 (match-beginning 1) (match-end 1)
6c389151
SM
3270 'face head-face))
3271 (while (re-search-forward
3272 ;; One paragraph
3273 "^\n=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$"
3274 e 'toend)
3275 ;; mark the headers
3276 (cperl-postpone-fontification
5efe6a56
SM
3277 (match-beginning 1) (match-end 1)
3278 'face head-face))))
f83d2997
KH
3279 (cperl-commentify bb e nil)
3280 (goto-char e)
3281 (or (eq e (point-max))
6c389151 3282 (forward-char -1)))) ; Prepare for immediate pod start.
f83d2997
KH
3283 ;; Here document
3284 ;; We do only one here-per-line
5bd52f0e 3285 ;; ;; One extra () before this:
5c8b7eaf 3286 ;;"<<"
5bd52f0e
RS
3287 ;; "\\(" ; 1 + 1
3288 ;; ;; First variant "BLAH" or just ``.
3289 ;; "\\([\"'`]\\)" ; 2 + 1
3290 ;; "\\([^\"'`\n]*\\)" ; 3 + 1
3291 ;; "\\3"
3292 ;; "\\|"
3293 ;; ;; Second variant: Identifier or \ID or empty
3294 ;; "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
3295 ;; ;; Do not have <<= or << 30 or <<30 or << $blah.
3296 ;; ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
3297 ;; "\\(\\)" ; To preserve count of pars :-( 6 + 1
3298 ;; "\\)"
f83d2997
KH
3299 ((match-beginning 2) ; 1 + 1
3300 ;; Abort in comment:
3301 (setq b (point))
3302 (setq state (parse-partial-sexp state-point b nil nil state)
5bd52f0e
RS
3303 state-point b
3304 tb (match-beginning 0)
3305 i (or (nth 3 state) (nth 4 state)))
5c8b7eaf 3306 (if i
5bd52f0e
RS
3307 (setq c t)
3308 (setq c (and
3309 (match-beginning 5)
3310 (not (match-beginning 6)) ; Empty
3311 (looking-at
3312 "[ \t]*[=0-9$@%&(]"))))
3313 (if c ; Not here-doc
3314 nil ; Skip it.
f83d2997
KH
3315 (if (match-beginning 5) ;4 + 1
3316 (setq b1 (match-beginning 5) ; 4 + 1
3317 e1 (match-end 5)) ; 4 + 1
3318 (setq b1 (match-beginning 4) ; 3 + 1
3319 e1 (match-end 4))) ; 3 + 1
3320 (setq tag (buffer-substring b1 e1)
3321 qtag (regexp-quote tag))
5c8b7eaf 3322 (cond (cperl-pod-here-fontify
5bd52f0e
RS
3323 ;; Highlight the starting delimiter
3324 (cperl-postpone-fontification b1 e1 'face font-lock-constant-face)
3325 (cperl-put-do-not-fontify b1 e1 t)))
f83d2997
KH
3326 (forward-line)
3327 (setq b (point))
db133cb6
RS
3328 ;; We do not search to max, since we may be called from
3329 ;; some hook of fontification, and max is random
5c8b7eaf 3330 (cond ((re-search-forward (concat "^" qtag "$")
db133cb6 3331 stop-point 'toend)
5c8b7eaf 3332 (if cperl-pod-here-fontify
f83d2997 3333 (progn
5bd52f0e 3334 ;; Highlight the ending delimiter
5c8b7eaf 3335 (cperl-postpone-fontification (match-beginning 0) (match-end 0)
883212ce 3336 'face font-lock-constant-face)
5bd52f0e
RS
3337 (cperl-put-do-not-fontify b (match-end 0) t)
3338 ;; Highlight the HERE-DOC
5c8b7eaf 3339 (cperl-postpone-fontification b (match-beginning 0)
f83d2997
KH
3340 'face here-face)))
3341 (setq e1 (cperl-1+ (match-end 0)))
5c8b7eaf 3342 (put-text-property b (match-beginning 0)
f83d2997
KH
3343 'syntax-type 'here-doc)
3344 (put-text-property (match-beginning 0) e1
3345 'syntax-type 'here-doc-delim)
3346 (put-text-property b e1
3347 'here-doc-group t)
3348 (cperl-commentify b e1 nil)
5bd52f0e
RS
3349 (cperl-put-do-not-fontify b (match-end 0) t)
3350 (if (> e1 max)
3351 (setq tmpend tb)))
f83d2997
KH
3352 (t (message "End of here-document `%s' not found." tag)
3353 (or (car err-l) (setcar err-l b))))))
3354 ;; format
3355 ((match-beginning 8)
3356 ;; 1+6=7 extra () before this:
3357 ;;"^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
3358 (setq b (point)
3359 name (if (match-beginning 8) ; 7 + 1
3360 (buffer-substring (match-beginning 8) ; 7 + 1
3361 (match-end 8)) ; 7 + 1
5bd52f0e
RS
3362 "")
3363 tb (match-beginning 0))
f83d2997 3364 (setq argument nil)
5c8b7eaf 3365 (if cperl-pod-here-fontify
f83d2997
KH
3366 (while (and (eq (forward-line) 0)
3367 (not (looking-at "^[.;]$")))
3368 (cond
3369 ((looking-at "^#")) ; Skip comments
3370 ((and argument ; Skip argument multi-lines
5c8b7eaf 3371 (looking-at "^[ \t]*{"))
f83d2997
KH
3372 (forward-sexp 1)
3373 (setq argument nil))
3374 (argument ; Skip argument lines
3375 (setq argument nil))
3376 (t ; Format line
3377 (setq b1 (point))
3378 (setq argument (looking-at "^[^\n]*[@^]"))
3379 (end-of-line)
5bd52f0e 3380 ;; Highlight the format line
5c8b7eaf 3381 (cperl-postpone-fontification b1 (point)
f83d2997
KH
3382 'face font-lock-string-face)
3383 (cperl-commentify b1 (point) nil)
5bd52f0e 3384 (cperl-put-do-not-fontify b1 (point) t))))
db133cb6
RS
3385 ;; We do not search to max, since we may be called from
3386 ;; some hook of fontification, and max is random
3387 (re-search-forward "^[.;]$" stop-point 'toend))
f83d2997 3388 (beginning-of-line)
5bd52f0e 3389 (if (looking-at "^\\.$") ; ";" is not supported yet
f83d2997 3390 (progn
5bd52f0e
RS
3391 ;; Highlight the ending delimiter
3392 (cperl-postpone-fontification (point) (+ (point) 2)
f83d2997
KH
3393 'face font-lock-string-face)
3394 (cperl-commentify (point) (+ (point) 2) nil)
5bd52f0e 3395 (cperl-put-do-not-fontify (point) (+ (point) 2) t))
f83d2997
KH
3396 (message "End of format `%s' not found." name)
3397 (or (car err-l) (setcar err-l b)))
3398 (forward-line)
5bd52f0e
RS
3399 (if (> (point) max)
3400 (setq tmpend tb))
db133cb6 3401 (put-text-property b (point) 'syntax-type 'format))
f83d2997
KH
3402 ;; Regexp:
3403 ((or (match-beginning 10) (match-beginning 11))
3404 ;; 1+6+2=9 extra () before this:
5bd52f0e 3405 ;; "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
f83d2997 3406 ;; "\\|"
5bd52f0e 3407 ;; "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
f83d2997
KH
3408 (setq b1 (if (match-beginning 10) 10 11)
3409 argument (buffer-substring
3410 (match-beginning b1) (match-end b1))
3411 b (point)
3412 i b
3413 c (char-after (match-beginning b1))
3414 bb (char-after (1- (match-beginning b1))) ; tmp holder
5bd52f0e
RS
3415 ;; bb == "Not a stringy"
3416 bb (if (eq b1 10) ; user variables/whatever
6c389151
SM
3417 (or
3418 (memq bb '(?\$ ?\@ ?\% ?\* ?\#)) ; $#y
3419 (and (eq bb ?-) (eq c ?s)) ; -s file test
3420 (and (eq bb ?\&)
3421 (not (eq (char-after ; &&m/blah/
3422 (- (match-beginning b1) 2))
5bd52f0e
RS
3423 ?\&))))
3424 ;; <file> or <$file>
3425 (and (eq c ?\<)
6c389151 3426 ;; Do not stringify <FH>, <$fh> :
5bd52f0e 3427 (save-match-data
5c8b7eaf 3428 (looking-at
6c389151 3429 "\\$?\\([_a-zA-Z:][_a-zA-Z0-9:]*\\)?>"))))
5bd52f0e 3430 tb (match-beginning 0))
db133cb6
RS
3431 (goto-char (match-beginning b1))
3432 (cperl-backward-to-noncomment (point-min))
f83d2997 3433 (or bb
5bd52f0e 3434 (if (eq b1 11) ; bare /blah/ or ?blah? or <foo>
f83d2997 3435 (setq argument ""
db133cb6
RS
3436 bb ; Not a regexp?
3437 (progn
5c8b7eaf 3438 (not
db133cb6
RS
3439 ;; What is below: regexp-p?
3440 (and
3441 (or (memq (preceding-char)
5bd52f0e 3442 (append (if (memq c '(?\? ?\<))
db133cb6 3443 ;; $a++ ? 1 : 2
5bd52f0e
RS
3444 "~{(=|&*!,;:"
3445 "~{(=|&+-*!,;:") nil))
db133cb6
RS
3446 (and (eq (preceding-char) ?\})
3447 (cperl-after-block-p (point-min)))
3448 (and (eq (char-syntax (preceding-char)) ?w)
3449 (progn
3450 (forward-sexp -1)
6c389151
SM
3451;; After these keywords `/' starts a RE. One should add all the
3452;; functions/builtins which expect an argument, but ...
5bd52f0e
RS
3453 (if (eq (preceding-char) ?-)
3454 ;; -d ?foo? is a RE
3455 (looking-at "[a-zA-Z]\\>")
029cb4d5
SM
3456 (and
3457 (not (memq (preceding-char)
3458 '(?$ ?@ ?& ?%)))
3459 (looking-at
3460 "\\(while\\|if\\|unless\\|until\\|and\\|or\\|not\\|xor\\|split\\|grep\\|map\\|print\\)\\>")))))
db133cb6
RS
3461 (and (eq (preceding-char) ?.)
3462 (eq (char-after (- (point) 2)) ?.))
3463 (bobp))
3464 ;; m|blah| ? foo : bar;
3465 (not
3466 (and (eq c ?\?)
5c8b7eaf 3467 cperl-use-syntax-table-text-property
db133cb6
RS
3468 (not (bobp))
3469 (progn
3470 (forward-char -1)
3471 (looking-at "\\s|")))))))
3472 b (1- b))
3473 ;; s y tr m
3474 ;; Check for $a->y
3475 (if (and (eq (preceding-char) ?>)
3476 (eq (char-after (- (point) 2)) ?-))
3477 ;; Not a regexp
3478 (setq bb t))))
5c8b7eaf 3479 (or bb (setq state (parse-partial-sexp
f83d2997
KH
3480 state-point b nil nil state)
3481 state-point b))
3482 (goto-char b)
3483 (if (or bb (nth 3 state) (nth 4 state))
3484 (goto-char i)
6c389151 3485 ;; Skip whitespace and comments...
f83d2997
KH
3486 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
3487 (goto-char (match-end 0))
3488 (skip-chars-forward " \t\n\f"))
6c389151
SM
3489 (if (> (point) b)
3490 (put-text-property b (point) 'syntax-type 'prestring))
f83d2997
KH
3491 ;; qtag means two-arg matcher, may be reset to
3492 ;; 2 or 3 later if some special quoting is needed.
3493 ;; e1 means matching-char matcher.
3494 (setq b (point)
5bd52f0e
RS
3495 ;; has 2 args
3496 i2 (string-match "^\\([sy]\\|tr\\)$" argument)
db133cb6
RS
3497 ;; We do not search to max, since we may be called from
3498 ;; some hook of fontification, and max is random
3499 i (cperl-forward-re stop-point end
5bd52f0e 3500 i2
db133cb6 3501 t st-l err-l argument)
5bd52f0e
RS
3502 ;; Note that if `go', then it is considered as 1-arg
3503 b1 (nth 1 i) ; start of the second part
5c8b7eaf 3504 tag (nth 2 i) ; ender-char, true if second part
5bd52f0e 3505 ; is with matching chars []
f83d2997
KH
3506 go (nth 4 i) ; There is a 1-char part after the end
3507 i (car i) ; intermediate point
5c8b7eaf 3508 e1 (point) ; end
5bd52f0e 3509 ;; Before end of the second part if non-matching: ///
5c8b7eaf 3510 tail (if (and i (not tag))
5bd52f0e
RS
3511 (1- e1))
3512 e (if i i e1) ; end of the first part
6c389151
SM
3513 qtag nil ; need to preserve backslashitis
3514 is-x-REx nil) ; REx has //x modifier
f83d2997
KH
3515 ;; Commenting \\ is dangerous, what about ( ?
3516 (and i tail
3517 (eq (char-after i) ?\\)
5bd52f0e 3518 (setq qtag t))
6c389151
SM
3519 (if (looking-at "\\sw*x") ; qr//x
3520 (setq is-x-REx t))
f83d2997 3521 (if (null i)
5bd52f0e 3522 ;; Considered as 1arg form
f83d2997
KH
3523 (progn
3524 (cperl-commentify b (point) t)
5bd52f0e 3525 (put-text-property b (point) 'syntax-type 'string)
6c389151
SM
3526 (if (or is-x-REx
3527 ;; ignore other text properties:
3528 (string-match "^qw$" argument))
3529 (put-text-property b (point) 'indentable t))
5bd52f0e
RS
3530 (and go
3531 (setq e1 (cperl-1+ e1))
3532 (or (eobp)
3533 (forward-char 1))))
f83d2997
KH
3534 (cperl-commentify b i t)
3535 (if (looking-at "\\sw*e") ; s///e
3536 (progn
3537 (and
3538 ;; silent:
5bd52f0e 3539 (cperl-find-pods-heres b1 (1- (point)) t end)
f83d2997
KH
3540 ;; Error
3541 (goto-char (1+ max)))
5bd52f0e 3542 (if (and tag (eq (preceding-char) ?\>))
f83d2997
KH
3543 (progn
3544 (cperl-modify-syntax-type (1- (point)) cperl-st-ket)
5bd52f0e 3545 (cperl-modify-syntax-type i cperl-st-bra)))
6c389151
SM
3546 (put-text-property b i 'syntax-type 'string)
3547 (if is-x-REx
3548 (put-text-property b i 'indentable t)))
5bd52f0e
RS
3549 (cperl-commentify b1 (point) t)
3550 (put-text-property b (point) 'syntax-type 'string)
6c389151
SM
3551 (if is-x-REx
3552 (put-text-property b i 'indentable t))
5bd52f0e 3553 (if qtag
db133cb6 3554 (cperl-modify-syntax-type (1+ i) cperl-st-punct))
f83d2997 3555 (setq tail nil)))
5bd52f0e 3556 ;; Now: tail: if the second part is non-matching without ///e
f83d2997
KH
3557 (if (eq (char-syntax (following-char)) ?w)
3558 (progn
3559 (forward-word 1) ; skip modifiers s///s
5bd52f0e 3560 (if tail (cperl-commentify tail (point) t))
6c389151
SM
3561 (cperl-postpone-fontification
3562 e1 (point) 'face 'cperl-nonoverridable-face)))
5bd52f0e
RS
3563 ;; Check whether it is m// which means "previous match"
3564 ;; and highlight differently
6c389151
SM
3565 (setq is-REx
3566 (and (string-match "^\\([sm]?\\|qr\\)$" argument)
3567 (or (not (= (length argument) 0))
3568 (not (eq c ?\<)))))
3569 (if (and is-REx
3570 (eq e (+ 2 b))
5bd52f0e
RS
3571 ;; split // *is* using zero-pattern
3572 (save-excursion
3573 (condition-case nil
3574 (progn
3575 (goto-char tb)
3576 (forward-sexp -1)
3577 (not (looking-at "split\\>")))
3578 (error t))))
5c8b7eaf 3579 (cperl-postpone-fontification
5bd52f0e
RS
3580 b e 'face font-lock-function-name-face)
3581 (if (or i2 ; Has 2 args
3582 (and cperl-fontify-m-as-s
3583 (or
3584 (string-match "^\\(m\\|qr\\)$" argument)
3585 (and (eq 0 (length argument))
3586 (not (eq ?\< (char-after b)))))))
3587 (progn
5c8b7eaf 3588 (cperl-postpone-fontification
5bd52f0e 3589 b (cperl-1+ b) 'face font-lock-constant-face)
5c8b7eaf 3590 (cperl-postpone-fontification
6c389151
SM
3591 (1- e) e 'face font-lock-constant-face)))
3592 (if (and is-REx cperl-regexp-scan)
3593 ;; Process RExen better
3594 (save-excursion
3595 (goto-char (1+ b))
3596 (while
3597 (and (< (point) e)
3598 (re-search-forward
3599 (if is-x-REx
3600 (if (eq (char-after b) ?\#)
3601 "\\((\\?\\\\#\\)\\|\\(\\\\#\\)"
3602 "\\((\\?#\\)\\|\\(#\\)")
3603 (if (eq (char-after b) ?\#)
3604 "\\((\\?\\\\#\\)"
3605 "\\((\\?#\\)"))
3606 (1- e) 'to-end))
3607 (goto-char (match-beginning 0))
3608 (setq REx-comment-start (point)
3609 was-comment t)
3610 (if (save-excursion
3611 (and
3612 ;; XXX not working if outside delimiter is #
3613 (eq (preceding-char) ?\\)
3614 (= (% (skip-chars-backward "$\\\\") 2) -1)))
3615 ;; Not a comment, avoid loop:
3616 (progn (setq was-comment nil)
3617 (forward-char 1))
3618 (if (match-beginning 2)
3619 (progn
3620 (beginning-of-line 2)
3621 (if (> (point) e)
3622 (goto-char (1- e))))
3623 ;; Works also if the outside delimiters are ().
3624 (or (search-forward ")" (1- e) 'toend)
3625 (message
3626 "Couldn't find end of (?#...)-comment in a REx, pos=%s"
3627 REx-comment-start))))
3628 (if (>= (point) e)
3629 (goto-char (1- e)))
3630 (if was-comment
3631 (progn
3632 (setq REx-comment-end (point))
3633 (cperl-commentify
3634 REx-comment-start REx-comment-end nil)
3635 (cperl-postpone-fontification
3636 REx-comment-start REx-comment-end
3637 'face font-lock-comment-face))))))
3638 (if (and is-REx is-x-REx)
3639 (put-text-property (1+ b) (1- e)
3640 'syntax-subtype 'x-REx)))
5bd52f0e
RS
3641 (if i2
3642 (progn
5c8b7eaf 3643 (cperl-postpone-fontification
5bd52f0e
RS
3644 (1- e1) e1 'face font-lock-constant-face)
3645 (if (assoc (char-after b) cperl-starters)
5c8b7eaf 3646 (cperl-postpone-fontification
5bd52f0e
RS
3647 b1 (1+ b1) 'face font-lock-constant-face))))
3648 (if (> (point) max)
3649 (setq tmpend tb))))
f83d2997
KH
3650 ((match-beginning 13) ; sub with prototypes
3651 (setq b (match-beginning 0))
3652 (if (memq (char-after (1- b))
3653 '(?\$ ?\@ ?\% ?\& ?\*))
3654 nil
5c8b7eaf 3655 (setq state (parse-partial-sexp
5bd52f0e
RS
3656 state-point b nil nil state)
3657 state-point b)
f83d2997
KH
3658 (if (or (nth 3 state) (nth 4 state))
3659 nil
3660 ;; Mark as string
3661 (cperl-commentify (match-beginning 13) (match-end 13) t))
3662 (goto-char (match-end 0))))
3663 ;; 1+6+2+1+1+2=13 extra () before this:
3664 ;; "\\$\\(['{]\\)"
3665 ((and (match-beginning 14)
db133cb6 3666 (eq (preceding-char) ?\')) ; $'
f83d2997 3667 (setq b (1- (point))
5c8b7eaf 3668 state (parse-partial-sexp
f83d2997
KH
3669 state-point (1- b) nil nil state)
3670 state-point (1- b))
3671 (if (nth 3 state) ; in string
3672 (cperl-modify-syntax-type (1- b) cperl-st-punct))
3673 (goto-char (1+ b)))
3674 ;; 1+6+2+1+1+2=13 extra () before this:
3675 ;; "\\$\\(['{]\\)"
3676 ((match-beginning 14) ; ${
3677 (setq bb (match-beginning 0))
3678 (cperl-modify-syntax-type bb cperl-st-punct))
3679 ;; 1+6+2+1+1+2+1=14 extra () before this:
3680 ;; "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'")
3681 ((match-beginning 15) ; old $abc'efg syntax
3682 (setq bb (match-end 0)
3683 b (match-beginning 0)
5c8b7eaf 3684 state (parse-partial-sexp
f83d2997
KH
3685 state-point b nil nil state)
3686 state-point b)
3687 (if (nth 3 state) ; in string
3688 nil
3689 (put-text-property (1- bb) bb 'syntax-table cperl-st-word))
3690 (goto-char bb))
3691 ;; 1+6+2+1+1+2+1+1=15 extra () before this:
3692 ;; "__\\(END\\|DATA\\)__"
6c389151 3693 ((match-beginning 16) ; __END__, __DATA__
f83d2997
KH
3694 (setq bb (match-end 0)
3695 b (match-beginning 0)
5c8b7eaf 3696 state (parse-partial-sexp
f83d2997
KH
3697 state-point b nil nil state)
3698 state-point b)
3699 (if (or (nth 3 state) (nth 4 state))
3700 nil
3701 ;; (put-text-property b (1+ bb) 'syntax-type 'pod) ; Cheat
3702 (cperl-commentify b bb nil)
3703 (setq end t))
6c389151
SM
3704 (goto-char bb))
3705 ((match-beginning 17) ; "\\\\\\(['`\"]\\)"
3706 (setq bb (match-end 0)
3707 b (match-beginning 0))
3708 (goto-char b)
3709 (skip-chars-backward "\\\\")
3710 ;;;(setq i2 (= (% (skip-chars-backward "\\\\") 2) -1))
3711 (setq state (parse-partial-sexp
3712 state-point b nil nil state)
3713 state-point b)
3714 (if (or (nth 3 state) (nth 4 state) )
3715 nil
3716 (cperl-modify-syntax-type b cperl-st-punct))
3717 (goto-char bb))
3718 (t (error "Error in regexp of the sniffer")))
db133cb6 3719 (if (> (point) stop-point)
f83d2997 3720 (progn
5c8b7eaf 3721 (if end
f83d2997
KH
3722 (message "Garbage after __END__/__DATA__ ignored")
3723 (message "Unbalanced syntax found while scanning")
3724 (or (car err-l) (setcar err-l b)))
db133cb6
RS
3725 (goto-char stop-point))))
3726 (setq cperl-syntax-state (cons state-point state)
5bd52f0e 3727 cperl-syntax-done-to (or tmpend (max (point) max))))
f83d2997 3728 (if (car err-l) (goto-char (car err-l))
db133cb6
RS
3729 (or non-inter
3730 (message "Scanning for \"hard\" Perl constructions... done"))))
f83d2997
KH
3731 (and (buffer-modified-p)
3732 (not modified)
3733 (set-buffer-modified-p nil))
3734 (set-syntax-table cperl-mode-syntax-table))
3735 (car err-l)))
3736
3737(defun cperl-backward-to-noncomment (lim)
3738 ;; Stops at lim or after non-whitespace that is not in comment
5bd52f0e 3739 (let (stop p pr)
f83d2997
KH
3740 (while (and (not stop) (> (point) (or lim 1)))
3741 (skip-chars-backward " \t\n\f" lim)
3742 (setq p (point))
3743 (beginning-of-line)
5bd52f0e
RS
3744 (if (memq (setq pr (get-text-property (point) 'syntax-type))
3745 '(pod here-doc here-doc-delim))
3746 (cperl-unwind-to-safe nil)
f83d2997
KH
3747 (if (or (looking-at "^[ \t]*\\(#\\|$\\)")
3748 (progn (cperl-to-comment-or-eol) (bolp)))
3749 nil ; Only comment, skip
3750 ;; Else
3751 (skip-chars-backward " \t")
3752 (if (< p (point)) (goto-char p))
5bd52f0e 3753 (setq stop t))))))
f83d2997
KH
3754
3755(defun cperl-after-block-p (lim)
3756 ;; We suppose that the preceding char is }.
3757 (save-excursion
3758 (condition-case nil
3759 (progn
3760 (forward-sexp -1)
3761 (cperl-backward-to-noncomment lim)
bab27c0c
RS
3762 (or (eq (point) lim)
3763 (eq (preceding-char) ?\) ) ; if () {} sub f () {}
db133cb6
RS
3764 (if (eq (char-syntax (preceding-char)) ?w) ; else {}
3765 (save-excursion
3766 (forward-sexp -1)
6c389151 3767 (or (looking-at "\\(else\\|grep\\|map\\|BEGIN\\|END\\|CHECK\\|INIT\\)\\>")
db133cb6
RS
3768 ;; sub f {}
3769 (progn
3770 (cperl-backward-to-noncomment lim)
3771 (and (eq (char-syntax (preceding-char)) ?w)
3772 (progn
3773 (forward-sexp -1)
3774 (looking-at "sub\\>"))))))
3775 (cperl-after-expr-p lim))))
f83d2997
KH
3776 (error nil))))
3777
3778(defun cperl-after-expr-p (&optional lim chars test)
029cb4d5 3779 "Return true if the position is good for start of expression.
f83d2997
KH
3780TEST is the expression to evaluate at the found position. If absent,
3781CHARS is a string that contains good characters to have before us (however,
3782`}' is treated \"smartly\" if it is not in the list)."
5c8b7eaf 3783 (let (stop p
f83d2997
KH
3784 (lim (or lim (point-min))))
3785 (save-excursion
3786 (while (and (not stop) (> (point) lim))
3787 (skip-chars-backward " \t\n\f" lim)
3788 (setq p (point))
3789 (beginning-of-line)
3790 (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip
5bd52f0e 3791 ;; Else: last iteration, or a label
5c8b7eaf 3792 (cperl-to-comment-or-eol)
f83d2997
KH
3793 (skip-chars-backward " \t")
3794 (if (< p (point)) (goto-char p))
5bd52f0e
RS
3795 (setq p (point))
3796 (if (and (eq (preceding-char) ?:)
3797 (progn
3798 (forward-char -1)
3799 (skip-chars-backward " \t\n\f" lim)
3800 (eq (char-syntax (preceding-char)) ?w)))
3801 (forward-sexp -1) ; Possibly label. Skip it
3802 (goto-char p)
3803 (setq stop t))))
bab27c0c
RS
3804 (or (bobp) ; ???? Needed
3805 (eq (point) lim)
029cb4d5 3806 (looking-at "[ \t]*__\\(END\\|DATA\\)__") ; After this anything goes
f83d2997
KH
3807 (progn
3808 (if test (eval test)
3809 (or (memq (preceding-char) (append (or chars "{;") nil))
3810 (and (eq (preceding-char) ?\})
3811 (cperl-after-block-p lim)))))))))
3812
3813(defun cperl-backward-to-start-of-continued-exp (lim)
3814 (if (memq (preceding-char) (append ")]}\"'`" nil))
3815 (forward-sexp -1))
3816 (beginning-of-line)
3817 (if (<= (point) lim)
3818 (goto-char (1+ lim)))
3819 (skip-chars-forward " \t"))
3820
db133cb6
RS
3821(defun cperl-after-block-and-statement-beg (lim)
3822 ;; We assume that we are after ?\}
5c8b7eaf 3823 (and
db133cb6
RS
3824 (cperl-after-block-p lim)
3825 (save-excursion
3826 (forward-sexp -1)
3827 (cperl-backward-to-noncomment (point-min))
3828 (or (bobp)
bab27c0c 3829 (eq (point) lim)
db133cb6
RS
3830 (not (= (char-syntax (preceding-char)) ?w))
3831 (progn
3832 (forward-sexp -1)
5c8b7eaf 3833 (not
db133cb6
RS
3834 (looking-at
3835 "\\(map\\|grep\\|printf?\\|system\\|exec\\|tr\\|s\\)\\>")))))))
3836
f83d2997 3837\f
f83d2997
KH
3838(defun cperl-indent-exp ()
3839 "Simple variant of indentation of continued-sexp.
5bd52f0e
RS
3840
3841Will not indent comment if it starts at `comment-indent' or looks like
3842continuation of the comment on the previous line.
db133cb6 3843
5c8b7eaf 3844If `cperl-indent-region-fix-constructs', will improve spacing on
db133cb6 3845conditional/loop constructs."
f83d2997
KH
3846 (interactive)
3847 (save-excursion
3848 (let ((tmp-end (progn (end-of-line) (point))) top done)
3849 (save-excursion
3850 (beginning-of-line)
3851 (while (null done)
3852 (setq top (point))
3853 (while (= (nth 0 (parse-partial-sexp (point) tmp-end
3854 -1)) -1)
3855 (setq top (point))) ; Get the outermost parenths in line
3856 (goto-char top)
3857 (while (< (point) tmp-end)
3858 (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol
3859 (or (eolp) (forward-sexp 1)))
5bd52f0e
RS
3860 (if (> (point) tmp-end)
3861 (save-excursion
3862 (end-of-line)
3863 (setq tmp-end (point)))
f83d2997
KH
3864 (setq done t)))
3865 (goto-char tmp-end)
3866 (setq tmp-end (point-marker)))
db133cb6
RS
3867 (if cperl-indent-region-fix-constructs
3868 (cperl-fix-line-spacing tmp-end))
f83d2997
KH
3869 (cperl-indent-region (point) tmp-end))))
3870
5bd52f0e
RS
3871(defun cperl-fix-line-spacing (&optional end parse-data)
3872 "Improve whitespace in a conditional/loop construct.
3873Returns some position at the last line."
db133cb6
RS
3874 (interactive)
3875 (or end
3876 (setq end (point-max)))
5bd52f0e
RS
3877 (let (p pp ml have-brace ret
3878 (ee (save-excursion (end-of-line) (point)))
db133cb6
RS
3879 (cperl-indent-region-fix-constructs
3880 (or cperl-indent-region-fix-constructs 1)))
3881 (save-excursion
3882 (beginning-of-line)
5bd52f0e 3883 (setq ret (point))
5c8b7eaf 3884 ;; }? continue
5bd52f0e 3885 ;; blah; }
5c8b7eaf 3886 (if (not
5bd52f0e
RS
3887 (or (looking-at "[ \t]*\\(els\\(e\\|if\\)\\|continue\\|if\\|while\\|for\\(each\\)?\\|until\\)")
3888 (setq have-brace (save-excursion (search-forward "}" ee t)))))
3889 nil ; Do not need to do anything
db133cb6 3890 ;; Looking at:
5c8b7eaf 3891 ;; }
db133cb6
RS
3892 ;; else
3893 (if (and cperl-merge-trailing-else
3894 (looking-at
3895 "[ \t]*}[ \t]*\n[ \t\n]*\\(els\\(e\\|if\\)\\|continue\\)\\>"))
3896 (progn
3897 (search-forward "}")
3898 (setq p (point))
3899 (skip-chars-forward " \t\n")
3900 (delete-region p (point))
3901 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
3902 (beginning-of-line)))
3903 ;; Looking at:
3904 ;; } else
3905 (if (looking-at "[ \t]*}\\(\t*\\|[ \t][ \t]+\\)\\<\\(els\\(e\\|if\\)\\|continue\\)\\>")
3906 (progn
3907 (search-forward "}")
3908 (delete-horizontal-space)
3909 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
3910 (beginning-of-line)))
3911 ;; Looking at:
3912 ;; else {
5c8b7eaf 3913 (if (looking-at
5bd52f0e 3914 "[ \t]*}?[ \t]*\\<\\(\\els\\(e\\|if\\)\\|continue\\|unless\\|if\\|while\\|for\\(each\\)?\\|until\\)\\>\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
db133cb6
RS
3915 (progn
3916 (forward-word 1)
3917 (delete-horizontal-space)
3918 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
3919 (beginning-of-line)))
3920 ;; Looking at:
3921 ;; foreach my $var
6c389151
SM
3922 (if (looking-at
3923 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)\\(\t*\\|[ \t][ \t]+\\)[^ \t\n]")
db133cb6
RS
3924 (progn
3925 (forward-word 2)
3926 (delete-horizontal-space)
3927 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
3928 (beginning-of-line)))
3929 ;; Looking at:
3930 ;; foreach my $var (
6c389151
SM
3931 (if (looking-at
3932 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)[ \t]*\\$[_a-zA-Z0-9]+\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
db133cb6
RS
3933 (progn
3934 (forward-word 3)
3935 (delete-horizontal-space)
3936 (insert
3937 (make-string cperl-indent-region-fix-constructs ?\ ))
3938 (beginning-of-line)))
3939 ;; Looking at:
3940 ;; } foreach my $var () {
6c389151 3941 (if (looking-at
ce22dd53 3942 "[ \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]*{")
db133cb6
RS
3943 (progn
3944 (setq ml (match-beginning 8))
3945 (re-search-forward "[({]")
3946 (forward-char -1)
3947 (setq p (point))
3948 (if (eq (following-char) ?\( )
3949 (progn
3950 (forward-sexp 1)
3951 (setq pp (point)))
3952 ;; after `else' or nothing
3953 (if ml ; after `else'
3954 (skip-chars-backward " \t\n")
3955 (beginning-of-line))
3956 (setq pp nil))
3957 ;; Now after the sexp before the brace
3958 ;; Multiline expr should be special
3959 (setq ml (and pp (save-excursion (goto-char p)
3960 (search-forward "\n" pp t))))
3961 (if (and (or (not pp) (< pp end))
3962 (looking-at "[ \t\n]*{"))
3963 (progn
5c8b7eaf 3964 (cond
db133cb6
RS
3965 ((bolp) ; Were before `{', no if/else/etc
3966 nil)
3967 ((looking-at "\\(\t*\\| [ \t]+\\){")
3968 (delete-horizontal-space)
5c8b7eaf 3969 (if (if ml
db133cb6
RS
3970 cperl-extra-newline-before-brace-multiline
3971 cperl-extra-newline-before-brace)
3972 (progn
3973 (delete-horizontal-space)
3974 (insert "\n")
5bd52f0e
RS
3975 (setq ret (point))
3976 (if (cperl-indent-line parse-data)
5c8b7eaf 3977 (progn
5bd52f0e
RS
3978 (cperl-fix-line-spacing end parse-data)
3979 (setq ret (point)))))
db133cb6
RS
3980 (insert
3981 (make-string cperl-indent-region-fix-constructs ?\ ))))
3982 ((and (looking-at "[ \t]*\n")
5c8b7eaf 3983 (not (if ml
db133cb6
RS
3984 cperl-extra-newline-before-brace-multiline
3985 cperl-extra-newline-before-brace)))
3986 (setq pp (point))
3987 (skip-chars-forward " \t\n")
3988 (delete-region pp (point))
3989 (insert
3990 (make-string cperl-indent-region-fix-constructs ?\ ))))
3991 ;; Now we are before `{'
3992 (if (looking-at "[ \t\n]*{[ \t]*[^ \t\n#]")
3993 (progn
3994 (skip-chars-forward " \t\n")
3995 (setq pp (point))
3996 (forward-sexp 1)
3997 (setq p (point))
3998 (goto-char pp)
3999 (setq ml (search-forward "\n" p t))
4000 (if (or cperl-break-one-line-blocks-when-indent ml)
4001 ;; not good: multi-line BLOCK
4002 (progn
4003 (goto-char (1+ pp))
4004 (delete-horizontal-space)
4005 (insert "\n")
5bd52f0e
RS
4006 (setq ret (point))
4007 (if (cperl-indent-line parse-data)
4008 (setq ret (cperl-fix-line-spacing end parse-data)))))))))))
db133cb6 4009 (beginning-of-line)
5bd52f0e 4010 (setq p (point) pp (save-excursion (end-of-line) (point))) ; May be different from ee.
db133cb6
RS
4011 ;; Now check whether there is a hanging `}'
4012 ;; Looking at:
4013 ;; } blah
5c8b7eaf 4014 (if (and
db133cb6 4015 cperl-fix-hanging-brace-when-indent
5bd52f0e 4016 have-brace
db133cb6
RS
4017 (not (looking-at "[ \t]*}[ \t]*\\(\\<\\(els\\(if\\|e\\)\\|continue\\|while\\|until\\)\\>\\|$\\|#\\)"))
4018 (condition-case nil
4019 (progn
4020 (up-list 1)
5c8b7eaf 4021 (if (and (<= (point) pp)
db133cb6 4022 (eq (preceding-char) ?\} )
5c8b7eaf 4023 (cperl-after-block-and-statement-beg (point-min)))
db133cb6
RS
4024 t
4025 (goto-char p)
4026 nil))
4027 (error nil)))
4028 (progn
4029 (forward-char -1)
4030 (skip-chars-backward " \t")
4031 (if (bolp)
4032 ;; `}' was the first thing on the line, insert NL *after* it.
4033 (progn
5bd52f0e 4034 (cperl-indent-line parse-data)
db133cb6
RS
4035 (search-forward "}")
4036 (delete-horizontal-space)
4037 (insert "\n"))
4038 (delete-horizontal-space)
4039 (or (eq (preceding-char) ?\;)
4040 (bolp)
4041 (and (eq (preceding-char) ?\} )
4042 (cperl-after-block-p (point-min)))
4043 (insert ";"))
5bd52f0e
RS
4044 (insert "\n")
4045 (setq ret (point)))
4046 (if (cperl-indent-line parse-data)
4047 (setq ret (cperl-fix-line-spacing end parse-data)))
4048 (beginning-of-line)))))
4049 ret))
4050
4051(defvar cperl-update-start) ; Do not need to make them local
4052(defvar cperl-update-end)
4053(defun cperl-delay-update-hook (beg end old-len)
4054 (setq cperl-update-start (min beg (or cperl-update-start (point-max))))
4055 (setq cperl-update-end (max end (or cperl-update-end (point-min)))))
db133cb6 4056
f83d2997
KH
4057(defun cperl-indent-region (start end)
4058 "Simple variant of indentation of region in CPerl mode.
5c8b7eaf 4059Should be slow. Will not indent comment if it starts at `comment-indent'
f83d2997 4060or looks like continuation of the comment on the previous line.
5c8b7eaf
SS
4061Indents all the lines whose first character is between START and END
4062inclusive.
db133cb6 4063
5c8b7eaf 4064If `cperl-indent-region-fix-constructs', will improve spacing on
db133cb6 4065conditional/loop constructs."
f83d2997 4066 (interactive "r")
5bd52f0e 4067 (cperl-update-syntaxification end end)
f83d2997 4068 (save-excursion
5bd52f0e
RS
4069 (let (cperl-update-start cperl-update-end (h-a-c after-change-functions))
4070 (let (st comm old-comm-indent new-comm-indent p pp i empty
4071 (indent-info (if cperl-emacs-can-parse
4072 (list nil nil nil) ; Cannot use '(), since will modify
4073 nil))
4074 after-change-functions ; Speed it up!
f83d2997 4075 (pm 0) (imenu-scanning-message "Indenting... (%3d%%)"))
5bd52f0e 4076 (if h-a-c (add-hook 'after-change-functions 'cperl-delay-update-hook))
f83d2997
KH
4077 (goto-char start)
4078 (setq old-comm-indent (and (cperl-to-comment-or-eol)
4079 (current-column))
4080 new-comm-indent old-comm-indent)
4081 (goto-char start)
bab27c0c 4082 (setq end (set-marker (make-marker) end)) ; indentation changes pos
f83d2997
KH
4083 (or (bolp) (beginning-of-line 2))
4084 (or (fboundp 'imenu-progress-message)
4085 (message "Indenting... For feedback load `imenu'..."))
4086 (while (and (<= (point) end) (not (eobp))) ; bol to check start
4087 (and (fboundp 'imenu-progress-message)
5c8b7eaf 4088 (imenu-progress-message
f83d2997 4089 pm (/ (* 100 (- (point) start)) (- end start -1))))
5bd52f0e
RS
4090 (setq st (point))
4091 (if (or
4092 (setq empty (looking-at "[ \t]*\n"))
4093 (and (setq comm (looking-at "[ \t]*#"))
5c8b7eaf 4094 (or (eq (current-indentation) (or old-comm-indent
f83d2997 4095 comment-column))
5bd52f0e 4096 (setq old-comm-indent nil))))
f83d2997 4097 (if (and old-comm-indent
5bd52f0e 4098 (not empty)
f83d2997 4099 (= (current-indentation) old-comm-indent)
5bd52f0e
RS
4100 (not (eq (get-text-property (point) 'syntax-type) 'pod))
4101 (not (eq (get-text-property (point) 'syntax-table)
4102 cperl-st-cfence)))
f83d2997
KH
4103 (let ((comment-column new-comm-indent))
4104 (indent-for-comment)))
5c8b7eaf 4105 (progn
5bd52f0e 4106 (setq i (cperl-indent-line indent-info))
f83d2997 4107 (or comm
db133cb6 4108 (not i)
f83d2997 4109 (progn
db133cb6 4110 (if cperl-indent-region-fix-constructs
5bd52f0e 4111 (goto-char (cperl-fix-line-spacing end indent-info)))
5c8b7eaf 4112 (if (setq old-comm-indent
f83d2997 4113 (and (cperl-to-comment-or-eol)
5c8b7eaf 4114 (not (memq (get-text-property (point)
f83d2997
KH
4115 'syntax-type)
4116 '(pod here-doc)))
5c8b7eaf 4117 (not (eq (get-text-property (point)
5bd52f0e
RS
4118 'syntax-table)
4119 cperl-st-cfence))
f83d2997
KH
4120 (current-column)))
4121 (progn (indent-for-comment)
4122 (skip-chars-backward " \t")
4123 (skip-chars-backward "#")
4124 (setq new-comm-indent (current-column))))))))
4125 (beginning-of-line 2))
4126 (if (fboundp 'imenu-progress-message)
4127 (imenu-progress-message pm 100)
5bd52f0e
RS
4128 (message nil)))
4129 ;; Now run the update hooks
4130 (if after-change-functions
4131 (save-excursion
4132 (if cperl-update-end
4133 (progn
4134 (goto-char cperl-update-end)
4135 (insert " ")
4136 (delete-char -1)
4137 (goto-char cperl-update-start)
4138 (insert " ")
4139 (delete-char -1))))))))
f83d2997 4140
f83d2997
KH
4141;; Stolen from lisp-mode with a lot of improvements
4142
4143(defun cperl-fill-paragraph (&optional justify iteration)
4144 "Like \\[fill-paragraph], but handle CPerl comments.
4145If any of the current line is a comment, fill the comment or the
4146block of it that point is in, preserving the comment's initial
4147indentation and initial hashes. Behaves usually outside of comment."
4148 (interactive "P")
4149 (let (
4150 ;; Non-nil if the current line contains a comment.
4151 has-comment
4152
4153 ;; If has-comment, the appropriate fill-prefix for the comment.
4154 comment-fill-prefix
4155 ;; Line that contains code and comment (or nil)
4156 start
4157 c spaces len dc (comment-column comment-column))
4158 ;; Figure out what kind of comment we are looking at.
4159 (save-excursion
4160 (beginning-of-line)
4161 (cond
4162
4163 ;; A line with nothing but a comment on it?
4164 ((looking-at "[ \t]*#[# \t]*")
4165 (setq has-comment t
4166 comment-fill-prefix (buffer-substring (match-beginning 0)
4167 (match-end 0))))
4168
4169 ;; A line with some code, followed by a comment? Remember that the
4170 ;; semi which starts the comment shouldn't be part of a string or
4171 ;; character.
4172 ((cperl-to-comment-or-eol)
4173 (setq has-comment t)
4174 (looking-at "#+[ \t]*")
5c8b7eaf 4175 (setq start (point) c (current-column)
f83d2997
KH
4176 comment-fill-prefix
4177 (concat (make-string (current-column) ?\ )
4178 (buffer-substring (match-beginning 0) (match-end 0)))
5c8b7eaf 4179 spaces (progn (skip-chars-backward " \t")
f83d2997 4180 (buffer-substring (point) start))
5c8b7eaf 4181 dc (- c (current-column)) len (- start (point))
f83d2997
KH
4182 start (point-marker))
4183 (delete-char len)
4184 (insert (make-string dc ?-)))))
4185 (if (not has-comment)
4186 (fill-paragraph justify) ; Do the usual thing outside of comment
4187 ;; Narrow to include only the comment, and then fill the region.
4188 (save-restriction
4189 (narrow-to-region
4190 ;; Find the first line we should include in the region to fill.
4191 (if start (progn (beginning-of-line) (point))
4192 (save-excursion
4193 (while (and (zerop (forward-line -1))
4194 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
4195 ;; We may have gone to far. Go forward again.
4196 (or (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")
4197 (forward-line 1))
4198 (point)))
4199 ;; Find the beginning of the first line past the region to fill.
4200 (save-excursion
4201 (while (progn (forward-line 1)
4202 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
4203 (point)))
4204 ;; Remove existing hashes
4205 (goto-char (point-min))
4206 (while (progn (forward-line 1) (< (point) (point-max)))
4207 (skip-chars-forward " \t")
5c8b7eaf 4208 (and (looking-at "#+")
f83d2997
KH
4209 (delete-char (- (match-end 0) (match-beginning 0)))))
4210
4211 ;; Lines with only hashes on them can be paragraph boundaries.
4212 (let ((paragraph-start (concat paragraph-start "\\|^[ \t#]*$"))
4213 (paragraph-separate (concat paragraph-start "\\|^[ \t#]*$"))
4214 (fill-prefix comment-fill-prefix))
4215 (fill-paragraph justify)))
4216 (if (and start)
5c8b7eaf 4217 (progn
f83d2997
KH
4218 (goto-char start)
4219 (if (> dc 0)
4220 (progn (delete-char dc) (insert spaces)))
4221 (if (or (= (current-column) c) iteration) nil
4222 (setq comment-column c)
4223 (indent-for-comment)
4224 ;; Repeat once more, flagging as iteration
4225 (cperl-fill-paragraph justify t)))))))
4226
4227(defun cperl-do-auto-fill ()
4228 ;; Break out if the line is short enough
4229 (if (> (save-excursion
4230 (end-of-line)
4231 (current-column))
4232 fill-column)
4233 (let ((c (save-excursion (beginning-of-line)
4234 (cperl-to-comment-or-eol) (point)))
4235 (s (memq (following-char) '(?\ ?\t))) marker)
4236 (if (>= c (point)) nil
4237 (setq marker (point-marker))
4238 (cperl-fill-paragraph)
4239 (goto-char marker)
4240 ;; Is not enough, sometimes marker is a start of line
5c8b7eaf 4241 (if (bolp) (progn (re-search-forward "#+[ \t]*")
f83d2997
KH
4242 (goto-char (match-end 0))))
4243 ;; Following space could have gone:
4244 (if (or (not s) (memq (following-char) '(?\ ?\t))) nil
4245 (insert " ")
4246 (backward-char 1))
4247 ;; Previous space could have gone:
4248 (or (memq (preceding-char) '(?\ ?\t)) (insert " "))))))
4249
f83d2997
KH
4250(defun cperl-imenu-addback (lst &optional isback name)
4251 ;; We suppose that the lst is a DAG, unless the first element only
4252 ;; loops back, and ISBACK is set. Thus this function cannot be
4253 ;; applied twice without ISBACK set.
4254 (cond ((not cperl-imenu-addback) lst)
4255 (t
5c8b7eaf 4256 (or name
f83d2997
KH
4257 (setq name "+++BACK+++"))
4258 (mapcar (function (lambda (elt)
4259 (if (and (listp elt) (listp (cdr elt)))
4260 (progn
4261 ;; In the other order it goes up
4262 ;; one level only ;-(
4263 (setcdr elt (cons (cons name lst)
4264 (cdr elt)))
4265 (cperl-imenu-addback (cdr elt) t name)
4266 ))))
4267 (if isback (cdr lst) lst))
4268 lst)))
4269
80585273 4270(defun cperl-imenu--create-perl-index (&optional regexp)
f83d2997 4271 (require 'imenu) ; May be called from TAGS creator
5c8b7eaf 4272 (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '())
f83d2997
KH
4273 (index-unsorted-alist '()) (i-s-f (default-value 'imenu-sort-function))
4274 (index-meth-alist '()) meth
6c389151 4275 packages ends-ranges p marker
f83d2997
KH
4276 (prev-pos 0) char fchar index index1 name (end-range 0) package)
4277 (goto-char (point-min))
4278 (if noninteractive
4279 (message "Scanning Perl for index")
4280 (imenu-progress-message prev-pos 0))
6c389151 4281 (cperl-update-syntaxification (point-max) (point-max))
f83d2997
KH
4282 ;; Search for the function
4283 (progn ;;save-match-data
4284 (while (re-search-forward
80585273 4285 (or regexp cperl-imenu--function-name-regexp-perl)
f83d2997
KH
4286 nil t)
4287 (or noninteractive
4288 (imenu-progress-message prev-pos))
f83d2997
KH
4289 (cond
4290 ((and ; Skip some noise if building tags
4291 (match-beginning 2) ; package or sub
4292 (eq (char-after (match-beginning 2)) ?p) ; package
4293 (not (save-match-data
4294 (looking-at "[ \t\n]*;")))) ; Plain text word 'package'
4295 nil)
4296 ((and
4297 (match-beginning 2) ; package or sub
6c389151 4298 ;; Skip if quoted (will not skip multi-line ''-strings :-():
f83d2997
KH
4299 (null (get-text-property (match-beginning 1) 'syntax-table))
4300 (null (get-text-property (match-beginning 1) 'syntax-type))
4301 (null (get-text-property (match-beginning 1) 'in-pod)))
4302 (save-excursion
4303 (goto-char (match-beginning 2))
4304 (setq fchar (following-char))
4305 )
4306 ;; (if (looking-at "([^()]*)[ \t\n\f]*")
4307 ;; (goto-char (match-end 0))) ; Messes what follows
6c389151 4308 (setq char (following-char) ; ?\; for "sub foo () ;"
f83d2997
KH
4309 meth nil
4310 p (point))
4311 (while (and ends-ranges (>= p (car ends-ranges)))
4312 ;; delete obsolete entries
4313 (setq ends-ranges (cdr ends-ranges) packages (cdr packages)))
4314 (setq package (or (car packages) "")
4315 end-range (or (car ends-ranges) 0))
4316 (if (eq fchar ?p)
4317 (setq name (buffer-substring (match-beginning 3) (match-end 3))
4318 name (progn
4319 (set-text-properties 0 (length name) nil name)
4320 name)
5c8b7eaf 4321 package (concat name "::")
f83d2997 4322 name (concat "package " name)
5c8b7eaf 4323 end-range
f83d2997
KH
4324 (save-excursion
4325 (parse-partial-sexp (point) (point-max) -1) (point))
4326 ends-ranges (cons end-range ends-ranges)
4327 packages (cons package packages)))
4328 ;; )
4329 ;; Skip this function name if it is a prototype declaration.
4330 (if (and (eq fchar ?s) (eq char ?\;)) nil
6c389151
SM
4331 (setq name (buffer-substring (match-beginning 3) (match-end 3))
4332 marker (make-marker))
4333 (set-text-properties 0 (length name) nil name)
4334 (set-marker marker (match-end 3))
4335 (if (eq fchar ?p)
4336 (setq name (concat "package " name))
f83d2997
KH
4337 (cond ((string-match "[:']" name)
4338 (setq meth t))
4339 ((> p end-range) nil)
5c8b7eaf 4340 (t
f83d2997 4341 (setq name (concat package name) meth t))))
6c389151
SM
4342 (setq index (cons name marker))
4343 (if (eq fchar ?p)
f83d2997
KH
4344 (push index index-pack-alist)
4345 (push index index-alist))
4346 (if meth (push index index-meth-alist))
4347 (push index index-unsorted-alist)))
4348 ((match-beginning 5) ; Pod section
4349 ;; (beginning-of-line)
4350 (setq index (imenu-example--name-and-position)
4351 name (buffer-substring (match-beginning 6) (match-end 6)))
4352 (set-text-properties 0 (length name) nil name)
4353 (if (eq (char-after (match-beginning 5)) ?2)
4354 (setq name (concat " " name)))
4355 (setcar index name)
4356 (setq index1 (cons (concat "=" name) (cdr index)))
4357 (push index index-pod-alist)
4358 (push index1 index-unsorted-alist)))))
4359 (or noninteractive
4360 (imenu-progress-message prev-pos 100))
5c8b7eaf 4361 (setq index-alist
f83d2997
KH
4362 (if (default-value 'imenu-sort-function)
4363 (sort index-alist (default-value 'imenu-sort-function))
4364 (nreverse index-alist)))
4365 (and index-pod-alist
4366 (push (cons "+POD headers+..."
4367 (nreverse index-pod-alist))
4368 index-alist))
4369 (and (or index-pack-alist index-meth-alist)
4370 (let ((lst index-pack-alist) hier-list pack elt group name)
4371 ;; Remove "package ", reverse and uniquify.
4372 (while lst
4373 (setq elt (car lst) lst (cdr lst) name (substring (car elt) 8))
4374 (if (assoc name hier-list) nil
4375 (setq hier-list (cons (cons name (cdr elt)) hier-list))))
4376 (setq lst index-meth-alist)
4377 (while lst
4378 (setq elt (car lst) lst (cdr lst))
4379 (cond ((string-match "\\(::\\|'\\)[_a-zA-Z0-9]+$" (car elt))
4380 (setq pack (substring (car elt) 0 (match-beginning 0)))
5c8b7eaf 4381 (if (setq group (assoc pack hier-list))
f83d2997
KH
4382 (if (listp (cdr group))
4383 ;; Have some functions already
5c8b7eaf
SS
4384 (setcdr group
4385 (cons (cons (substring
f83d2997
KH
4386 (car elt)
4387 (+ 2 (match-beginning 0)))
4388 (cdr elt))
4389 (cdr group)))
5c8b7eaf 4390 (setcdr group (list (cons (substring
f83d2997
KH
4391 (car elt)
4392 (+ 2 (match-beginning 0)))
4393 (cdr elt)))))
5c8b7eaf
SS
4394 (setq hier-list
4395 (cons (cons pack
4396 (list (cons (substring
f83d2997
KH
4397 (car elt)
4398 (+ 2 (match-beginning 0)))
4399 (cdr elt))))
4400 hier-list))))))
4401 (push (cons "+Hierarchy+..."
4402 hier-list)
4403 index-alist)))
4404 (and index-pack-alist
4405 (push (cons "+Packages+..."
4406 (nreverse index-pack-alist))
4407 index-alist))
5c8b7eaf 4408 (and (or index-pack-alist index-pod-alist
f83d2997
KH
4409 (default-value 'imenu-sort-function))
4410 index-unsorted-alist
4411 (push (cons "+Unsorted List+..."
4412 (nreverse index-unsorted-alist))
4413 index-alist))
4414 (cperl-imenu-addback index-alist)))
4415
6c389151 4416\f
6c389151
SM
4417;; Suggested by Mark A. Hershberger
4418(defun cperl-outline-level ()
4419 (looking-at outline-regexp)
4420 (cond ((not (match-beginning 1)) 0) ; beginning-of-file
4421 ((match-beginning 2)
4422 (if (eq (char-after (match-beginning 2)) ?p)
4423 0 ; package
4424 1)) ; sub
4425 ((match-beginning 5)
4426 (if (eq (char-after (match-beginning 5)) ?1)
4427 1 ; head1
4428 2)) ; head2
4429 (t 3))) ; should not happen
4430
4431\f
4432(defvar cperl-compilation-error-regexp-alist
f83d2997
KH
4433 ;; This look like a paranoiac regexp: could anybody find a better one? (which WORK).
4434 '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
4435 2 3))
4436 "Alist that specifies how to match errors in perl output.")
4437
4438(if (fboundp 'eval-after-load)
4439 (eval-after-load
4440 "mode-compile"
4441 '(setq perl-compilation-error-regexp-alist
4442 cperl-compilation-error-regexp-alist)))
4443
4444
f83d2997
KH
4445(defun cperl-windowed-init ()
4446 "Initialization under windowed version."
db133cb6
RS
4447 (if (or (featurep 'ps-print) cperl-faces-init)
4448 ;; Need to init anyway:
4449 (or cperl-faces-init (cperl-init-faces))
4450 (add-hook 'font-lock-mode-hook
4451 (function
4452 (lambda ()
996e2616 4453 (if (memq major-mode '(perl-mode cperl-mode))
db133cb6
RS
4454 (progn
4455 (or cperl-faces-init (cperl-init-faces)))))))
4456 (if (fboundp 'eval-after-load)
4457 (eval-after-load
4458 "ps-print"
4459 '(or cperl-faces-init (cperl-init-faces))))))
4460
5efe6a56 4461(defvar cperl-font-lock-keywords-1 nil
80585273 4462 "Additional expressions to highlight in Perl mode. Minimal set.")
5efe6a56 4463(defvar cperl-font-lock-keywords nil
80585273 4464 "Additional expressions to highlight in Perl mode. Default set.")
5efe6a56 4465(defvar cperl-font-lock-keywords-2 nil
80585273
DL
4466 "Additional expressions to highlight in Perl mode. Maximal set")
4467
db133cb6
RS
4468(defun cperl-load-font-lock-keywords ()
4469 (or cperl-faces-init (cperl-init-faces))
5efe6a56 4470 cperl-font-lock-keywords)
db133cb6
RS
4471
4472(defun cperl-load-font-lock-keywords-1 ()
4473 (or cperl-faces-init (cperl-init-faces))
5efe6a56 4474 cperl-font-lock-keywords-1)
db133cb6
RS
4475
4476(defun cperl-load-font-lock-keywords-2 ()
4477 (or cperl-faces-init (cperl-init-faces))
5efe6a56 4478 cperl-font-lock-keywords-2)
f83d2997 4479
5bd52f0e
RS
4480(defun cperl-init-faces-weak ()
4481 ;; Allow `cperl-find-pods-heres' to run.
4482 (or (boundp 'font-lock-constant-face)
4483 (cperl-force-face font-lock-constant-face
4484 "Face for constant and label names")
4485 ;;(setq font-lock-constant-face 'font-lock-constant-face)
4486 ))
4487
f83d2997 4488(defun cperl-init-faces ()
5bd52f0e 4489 (condition-case errs
f83d2997
KH
4490 (progn
4491 (require 'font-lock)
4492 (and (fboundp 'font-lock-fontify-anchored-keywords)
4493 (featurep 'font-lock-extra)
4494 (message "You have an obsolete package `font-lock-extra'. Install `choose-color'."))
4495 (let (t-font-lock-keywords t-font-lock-keywords-1 font-lock-anchored)
f83d2997
KH
4496 (if (fboundp 'font-lock-fontify-anchored-keywords)
4497 (setq font-lock-anchored t))
5c8b7eaf 4498 (setq
f83d2997
KH
4499 t-font-lock-keywords
4500 (list
ac6857fb 4501 `("[ \t]+$" 0 ',cperl-invalid-face t)
f83d2997
KH
4502 (cons
4503 (concat
4504 "\\(^\\|[^$@%&\\]\\)\\<\\("
4505 (mapconcat
4506 'identity
4507 '("if" "until" "while" "elsif" "else" "unless" "for"
4508 "foreach" "continue" "exit" "die" "last" "goto" "next"
4509 "redo" "return" "local" "exec" "sub" "do" "dump" "use"
6c389151 4510 "require" "package" "eval" "my" "BEGIN" "END" "CHECK" "INIT")
f83d2997
KH
4511 "\\|") ; Flow control
4512 "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]"
4513 ; In what follows we use `type' style
4514 ; for overwritable builtins
4515 (list
4516 (concat
4517 "\\(^\\|[^$@%&\\]\\)\\<\\("
4518 ;; "CORE" "__FILE__" "__LINE__" "abs" "accept" "alarm"
4519 ;; "and" "atan2" "bind" "binmode" "bless" "caller"
4520 ;; "chdir" "chmod" "chown" "chr" "chroot" "close"
4521 ;; "closedir" "cmp" "connect" "continue" "cos" "crypt"
4522 ;; "dbmclose" "dbmopen" "die" "dump" "endgrent"
4523 ;; "endhostent" "endnetent" "endprotoent" "endpwent"
4524 ;; "endservent" "eof" "eq" "exec" "exit" "exp" "fcntl"
4525 ;; "fileno" "flock" "fork" "formline" "ge" "getc"
4526 ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
4527 ;; "gethostbyname" "gethostent" "getlogin"
4528 ;; "getnetbyaddr" "getnetbyname" "getnetent"
4529 ;; "getpeername" "getpgrp" "getppid" "getpriority"
4530 ;; "getprotobyname" "getprotobynumber" "getprotoent"
4531 ;; "getpwent" "getpwnam" "getpwuid" "getservbyname"
4532 ;; "getservbyport" "getservent" "getsockname"
4533 ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int"
4534 ;; "ioctl" "join" "kill" "lc" "lcfirst" "le" "length"
5bd52f0e 4535 ;; "link" "listen" "localtime" "lock" "log" "lstat" "lt"
f83d2997
KH
4536 ;; "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "ne"
4537 ;; "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
4538 ;; "quotemeta" "rand" "read" "readdir" "readline"
4539 ;; "readlink" "readpipe" "recv" "ref" "rename" "require"
4540 ;; "reset" "reverse" "rewinddir" "rindex" "rmdir" "seek"
4541 ;; "seekdir" "select" "semctl" "semget" "semop" "send"
4542 ;; "setgrent" "sethostent" "setnetent" "setpgrp"
4543 ;; "setpriority" "setprotoent" "setpwent" "setservent"
4544 ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite"
4545 ;; "shutdown" "sin" "sleep" "socket" "socketpair"
4546 ;; "sprintf" "sqrt" "srand" "stat" "substr" "symlink"
6c389151 4547 ;; "syscall" "sysopen" "sysread" "system" "syswrite" "tell"
f83d2997
KH
4548 ;; "telldir" "time" "times" "truncate" "uc" "ucfirst"
4549 ;; "umask" "unlink" "unpack" "utime" "values" "vec"
4550 ;; "wait" "waitpid" "wantarray" "warn" "write" "x" "xor"
5c8b7eaf 4551 "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|"
f83d2997
KH
4552 "b\\(in\\(d\\|mode\\)\\|less\\)\\|"
4553 "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|"
4554 "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|"
4555 "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|"
4556 "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|"
4557 "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|"
4558 "f\\(ileno\\|cntl\\|lock\\|or\\(k\\|mline\\)\\)\\|"
4559 "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|"
4560 "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w"
4561 "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|"
4562 "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|"
4563 "ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|"
4564 "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|"
4565 "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|"
4566 "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e"
5bd52f0e 4567 "\\(\\|ngth\\)\\|o\\(c\\(altime\\|k\\)\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|"
f83d2997
KH
4568 "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|"
4569 "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|"
4570 "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin"
4571 "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name"
4572 "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r"
4573 "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|"
4574 "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|"
4575 "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|"
6c389151 4576 "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|open\\|tem\\|write\\)\\|"
f83d2997
KH
4577 "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|"
4578 "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|"
4579 "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|"
4580 "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|"
4581 "x\\(\\|or\\)\\|__\\(FILE__\\|LINE__\\|PACKAGE__\\)"
4582 "\\)\\>") 2 'font-lock-type-face)
4583 ;; In what follows we use `other' style
4584 ;; for nonoverwritable builtins
4585 ;; Somehow 's', 'm' are not auto-generated???
4586 (list
4587 (concat
4588 "\\(^\\|[^$@%&\\]\\)\\<\\("
6c389151 4589 ;; "AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "__END__" "chomp"
f83d2997
KH
4590 ;; "chop" "defined" "delete" "do" "each" "else" "elsif"
4591 ;; "eval" "exists" "for" "foreach" "format" "goto"
4592 ;; "grep" "if" "keys" "last" "local" "map" "my" "next"
4593 ;; "no" "package" "pop" "pos" "print" "printf" "push"
4594 ;; "q" "qq" "qw" "qx" "redo" "return" "scalar" "shift"
4595 ;; "sort" "splice" "split" "study" "sub" "tie" "tr"
4596 ;; "undef" "unless" "unshift" "untie" "until" "use"
4597 ;; "while" "y"
6c389151 4598 "AUTOLOAD\\|BEGIN\\|CHECK\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|"
f83d2997 4599 "o\\)\\|DESTROY\\|e\\(ach\\|val\\|xists\\|ls\\(e\\|if\\)\\)\\|"
6c389151
SM
4600 "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|INIT\\|if\\|keys\\|"
4601 "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|our\\|"
f83d2997 4602 "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|"
5bd52f0e 4603 "q\\(\\|q\\|w\\|x\\|r\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|"
f83d2997
KH
4604 "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|"
4605 "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|"
4606 "while\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added manually
4607 "\\|[sm]" ; Added manually
5bd52f0e 4608 "\\)\\>") 2 'cperl-nonoverridable-face)
f83d2997
KH
4609 ;; (mapconcat 'identity
4610 ;; '("#endif" "#else" "#ifdef" "#ifndef" "#if"
4611 ;; "#include" "#define" "#undef")
4612 ;; "\\|")
4613 '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0
4614 font-lock-function-name-face keep) ; Not very good, triggers at "[a-z]"
5bd52f0e 4615 '("\\<sub[ \t]+\\([^ \t{;()]+\\)[ \t]*\\(([^()]*)[ \t]*\\)?[#{\n]" 1
f83d2997
KH
4616 font-lock-function-name-face)
4617 '("\\<\\(package\\|require\\|use\\|import\\|no\\|bootstrap\\)[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t;]" ; require A if B;
4618 2 font-lock-function-name-face)
4619 '("^[ \t]*format[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t]*=[ \t]*$"
4620 1 font-lock-function-name-face)
4621 (cond ((featurep 'font-lock-extra)
5c8b7eaf 4622 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
f83d2997
KH
4623 (2 font-lock-string-face t)
4624 (0 '(restart 2 t)))) ; To highlight $a{bc}{ef}
4625 (font-lock-anchored
4626 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
4627 (2 font-lock-string-face t)
4628 ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
4629 nil nil
4630 (1 font-lock-string-face t))))
4631 (t '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
4632 2 font-lock-string-face t)))
db133cb6 4633 '("[\[ \t{,(]\\(-?[a-zA-Z0-9_:]+\\)[ \t]*=>" 1
f83d2997 4634 font-lock-string-face t)
5c8b7eaf 4635 '("^[ \t]*\\([a-zA-Z0-9_]+[ \t]*:\\)[ \t]*\\($\\|{\\|\\<\\(until\\|while\\|for\\(each\\)?\\|do\\)\\>\\)" 1
883212ce 4636 font-lock-constant-face) ; labels
f83d2997 4637 '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets
883212ce 4638 2 font-lock-constant-face)
6c389151
SM
4639 ;; Uncomment to get perl-mode-like vars
4640 ;;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
4641 ;;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
4642 ;;; (2 (cons font-lock-variable-name-face '(underline))))
f83d2997 4643 (cond ((featurep 'font-lock-extra)
6c389151 4644 '("^[ \t]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
f83d2997
KH
4645 (3 font-lock-variable-name-face)
4646 (4 '(another 4 nil
4647 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
4648 (1 font-lock-variable-name-face)
5c8b7eaf 4649 (2 '(restart 2 nil) nil t)))
f83d2997
KH
4650 nil t))) ; local variables, multiple
4651 (font-lock-anchored
6c389151 4652 '("^[ \t{}]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
f83d2997
KH
4653 (3 font-lock-variable-name-face)
4654 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)"
4655 nil nil
4656 (1 font-lock-variable-name-face))))
6c389151 4657 (t '("^[ \t{}]*\\(my\\|local\\our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
f83d2997 4658 3 font-lock-variable-name-face)))
6c389151
SM
4659 '("\\<for\\(each\\)?\\([ \t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*("
4660 4 font-lock-variable-name-face)))
4661 (setq
f83d2997
KH
4662 t-font-lock-keywords-1
4663 (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock
4664 (not cperl-xemacs-p) ; not yet as of XEmacs 19.12
4665 '(
4666 ("\\(\\([@%]\\|\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
4667 (if (eq (char-after (match-beginning 2)) ?%)
5bd52f0e
RS
4668 cperl-hash-face
4669 cperl-array-face)
f83d2997
KH
4670 t) ; arrays and hashes
4671 ("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
4672 1
5c8b7eaf 4673 (if (= (- (match-end 2) (match-beginning 2)) 1)
f83d2997 4674 (if (eq (char-after (match-beginning 3)) ?{)
5bd52f0e
RS
4675 cperl-hash-face
4676 cperl-array-face) ; arrays and hashes
f83d2997
KH
4677 font-lock-variable-name-face) ; Just to put something
4678 t)
4679 ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
4680 ;;; Too much noise from \s* @s[ and friends
5c8b7eaf 4681 ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
f83d2997
KH
4682 ;;(3 font-lock-function-name-face t t)
4683 ;;(4
4684 ;; (if (cperl-slash-is-regexp)
4685 ;; font-lock-function-name-face 'default) nil t))
4686 )))
6c389151
SM
4687 (if cperl-highlight-variables-indiscriminately
4688 (setq t-font-lock-keywords-1
4689 (append t-font-lock-keywords-1
4690 (list '("[$*]{?\\(\\sw+\\)" 1
4691 font-lock-variable-name-face)))))
4692 (setq cperl-font-lock-keywords-1
5bd52f0e
RS
4693 (if cperl-syntaxify-by-font-lock
4694 (cons 'cperl-fontify-update
4695 t-font-lock-keywords)
4696 t-font-lock-keywords)
5efe6a56
SM
4697 cperl-font-lock-keywords cperl-font-lock-keywords-1
4698 cperl-font-lock-keywords-2 (append
6c389151
SM
4699 cperl-font-lock-keywords-1
4700 t-font-lock-keywords-1)))
f83d2997
KH
4701 (if (fboundp 'ps-print-buffer) (cperl-ps-print-init))
4702 (if (or (featurep 'choose-color) (featurep 'font-lock-extra))
db133cb6
RS
4703 (eval ; Avoid a warning
4704 '(font-lock-require-faces
f83d2997
KH
4705 (list
4706 ;; Color-light Color-dark Gray-light Gray-dark Mono
4707 (list 'font-lock-comment-face
4708 ["Firebrick" "OrangeRed" "DimGray" "Gray80"]
4709 nil
4710 [nil nil t t t]
4711 [nil nil t t t]
4712 nil)
4713 (list 'font-lock-string-face
4714 ["RosyBrown" "LightSalmon" "Gray50" "LightGray"]
4715 nil
4716 nil
4717 [nil nil t t t]
4718 nil)
f83d2997
KH
4719 (list 'font-lock-function-name-face
4720 (vector
4721 "Blue" "LightSkyBlue" "Gray50" "LightGray"
4722 (cdr (assq 'background-color ; if mono
4723 (frame-parameters))))
4724 (vector
4725 nil nil nil nil
4726 (cdr (assq 'foreground-color ; if mono
4727 (frame-parameters))))
4728 [nil nil t t t]
4729 nil
4730 nil)
4731 (list 'font-lock-variable-name-face
4732 ["DarkGoldenrod" "LightGoldenrod" "DimGray" "Gray90"]
4733 nil
4734 [nil nil t t t]
4735 [nil nil t t t]
4736 nil)
4737 (list 'font-lock-type-face
4738 ["DarkOliveGreen" "PaleGreen" "DimGray" "Gray80"]
4739 nil
4740 [nil nil t t t]
4741 nil
4742 [nil nil t t t]
4743 )
883212ce 4744 (list 'font-lock-constant-face
f83d2997
KH
4745 ["CadetBlue" "Aquamarine" "Gray50" "LightGray"]
4746 nil
4747 [nil nil t t t]
4748 nil
4749 [nil nil t t t]
4750 )
5bd52f0e 4751 (list 'cperl-nonoverridable-face
f83d2997
KH
4752 ["chartreuse3" ("orchid1" "orange")
4753 nil "Gray80"]
4754 [nil nil "gray90"]
4755 [nil nil nil t t]
4756 [nil nil t t]
4757 [nil nil t t t]
4758 )
5bd52f0e 4759 (list 'cperl-array-face
f83d2997
KH
4760 ["blue" "yellow" nil "Gray80"]
4761 ["lightyellow2" ("navy" "os2blue" "darkgreen")
4762 "gray90"]
4763 t
4764 nil
4765 nil)
5bd52f0e 4766 (list 'cperl-hash-face
f83d2997
KH
4767 ["red" "red" nil "Gray80"]
4768 ["lightyellow2" ("navy" "os2blue" "darkgreen")
4769 "gray90"]
4770 t
4771 t
db133cb6 4772 nil))))
5bd52f0e 4773 ;; Do it the dull way, without choose-color
f83d2997
KH
4774 (defvar cperl-guessed-background nil
4775 "Display characteristics as guessed by cperl.")
5bd52f0e 4776;; (or (fboundp 'x-color-defined-p)
5c8b7eaf 4777;; (defalias 'x-color-defined-p
5bd52f0e
RS
4778;; (cond ((fboundp 'color-defined-p) 'color-defined-p)
4779;; ;; XEmacs >= 19.12
4780;; ((fboundp 'valid-color-name-p) 'valid-color-name-p)
4781;; ;; XEmacs 19.11
4782;; (t 'x-valid-color-name-p))))
5c8b7eaf 4783 (cperl-force-face font-lock-constant-face
5bd52f0e
RS
4784 "Face for constant and label names")
4785 (cperl-force-face font-lock-variable-name-face
4786 "Face for variable names")
4787 (cperl-force-face font-lock-type-face
4788 "Face for data types")
4789 (cperl-force-face cperl-nonoverridable-face
4790 "Face for data types from another group")
4791 (cperl-force-face font-lock-comment-face
4792 "Face for comments")
4793 (cperl-force-face font-lock-function-name-face
4794 "Face for function names")
4795 (cperl-force-face cperl-hash-face
4796 "Face for hashes")
4797 (cperl-force-face cperl-array-face
4798 "Face for arrays")
4799 ;;(defvar font-lock-constant-face 'font-lock-constant-face)
4800 ;;(defvar font-lock-variable-name-face 'font-lock-variable-name-face)
4801 ;;(or (boundp 'font-lock-type-face)
4802 ;; (defconst font-lock-type-face
4803 ;; 'font-lock-type-face
4804 ;; "Face to use for data types."))
4805 ;;(or (boundp 'cperl-nonoverridable-face)
4806 ;; (defconst cperl-nonoverridable-face
4807 ;; 'cperl-nonoverridable-face
4808 ;; "Face to use for data types from another group."))
4809 ;;(if (not cperl-xemacs-p) nil
4810 ;; (or (boundp 'font-lock-comment-face)
4811 ;; (defconst font-lock-comment-face
4812 ;; 'font-lock-comment-face
4813 ;; "Face to use for comments."))
4814 ;; (or (boundp 'font-lock-keyword-face)
4815 ;; (defconst font-lock-keyword-face
4816 ;; 'font-lock-keyword-face
4817 ;; "Face to use for keywords."))
4818 ;; (or (boundp 'font-lock-function-name-face)
4819 ;; (defconst font-lock-function-name-face
4820 ;; 'font-lock-function-name-face
4821 ;; "Face to use for function names.")))
4822 (if (and
5c8b7eaf
SS
4823 (not (cperl-is-face 'cperl-array-face))
4824 (cperl-is-face 'font-lock-emphasized-face))
5bd52f0e
RS
4825 (copy-face 'font-lock-emphasized-face 'cperl-array-face))
4826 (if (and
5c8b7eaf
SS
4827 (not (cperl-is-face 'cperl-hash-face))
4828 (cperl-is-face 'font-lock-other-emphasized-face))
4829 (copy-face 'font-lock-other-emphasized-face
5bd52f0e
RS
4830 'cperl-hash-face))
4831 (if (and
5c8b7eaf
SS
4832 (not (cperl-is-face 'cperl-nonoverridable-face))
4833 (cperl-is-face 'font-lock-other-type-face))
4834 (copy-face 'font-lock-other-type-face
5bd52f0e
RS
4835 'cperl-nonoverridable-face))
4836 ;;(or (boundp 'cperl-hash-face)
4837 ;; (defconst cperl-hash-face
4838 ;; 'cperl-hash-face
4839 ;; "Face to use for hashes."))
4840 ;;(or (boundp 'cperl-array-face)
4841 ;; (defconst cperl-array-face
4842 ;; 'cperl-array-face
4843 ;; "Face to use for arrays."))
f83d2997
KH
4844 ;; Here we try to guess background
4845 (let ((background
4846 (if (boundp 'font-lock-background-mode)
4847 font-lock-background-mode
5c8b7eaf 4848 'light))
f83d2997 4849 (face-list (and (fboundp 'face-list) (face-list)))
5bd52f0e
RS
4850 ;; cperl-is-face
4851 )
4852;;;; (fset 'cperl-is-face
4853;;;; (cond ((fboundp 'find-face)
4854;;;; (symbol-function 'find-face))
4855;;;; (face-list
4856;;;; (function (lambda (face) (member face face-list))))
4857;;;; (t
4858;;;; (function (lambda (face) (boundp face))))))
f83d2997
KH
4859 (defvar cperl-guessed-background
4860 (if (and (boundp 'font-lock-display-type)
4861 (eq font-lock-display-type 'grayscale))
4862 'gray
4863 background)
4864 "Background as guessed by CPerl mode")
5c8b7eaf
SS
4865 (if (and
4866 (not (cperl-is-face 'font-lock-constant-face))
4867 (cperl-is-face 'font-lock-reference-face))
db133cb6
RS
4868 (copy-face 'font-lock-reference-face 'font-lock-constant-face))
4869 (if (cperl-is-face 'font-lock-type-face) nil
f83d2997
KH
4870 (copy-face 'default 'font-lock-type-face)
4871 (cond
4872 ((eq background 'light)
4873 (set-face-foreground 'font-lock-type-face
4874 (if (x-color-defined-p "seagreen")
4875 "seagreen"
4876 "sea green")))
4877 ((eq background 'dark)
4878 (set-face-foreground 'font-lock-type-face
4879 (if (x-color-defined-p "os2pink")
4880 "os2pink"
4881 "pink")))
4882 (t
4883 (set-face-background 'font-lock-type-face "gray90"))))
5bd52f0e 4884 (if (cperl-is-face 'cperl-nonoverridable-face)
f83d2997 4885 nil
5bd52f0e 4886 (copy-face 'font-lock-type-face 'cperl-nonoverridable-face)
f83d2997
KH
4887 (cond
4888 ((eq background 'light)
5bd52f0e 4889 (set-face-foreground 'cperl-nonoverridable-face
f83d2997
KH
4890 (if (x-color-defined-p "chartreuse3")
4891 "chartreuse3"
4892 "chartreuse")))
4893 ((eq background 'dark)
5bd52f0e 4894 (set-face-foreground 'cperl-nonoverridable-face
f83d2997
KH
4895 (if (x-color-defined-p "orchid1")
4896 "orchid1"
4897 "orange")))))
5bd52f0e
RS
4898;;; (if (cperl-is-face 'font-lock-other-emphasized-face) nil
4899;;; (copy-face 'bold-italic 'font-lock-other-emphasized-face)
4900;;; (cond
4901;;; ((eq background 'light)
4902;;; (set-face-background 'font-lock-other-emphasized-face
4903;;; (if (x-color-defined-p "lightyellow2")
4904;;; "lightyellow2"
4905;;; (if (x-color-defined-p "lightyellow")
4906;;; "lightyellow"
4907;;; "light yellow"))))
4908;;; ((eq background 'dark)
4909;;; (set-face-background 'font-lock-other-emphasized-face
4910;;; (if (x-color-defined-p "navy")
4911;;; "navy"
4912;;; (if (x-color-defined-p "darkgreen")
4913;;; "darkgreen"
4914;;; "dark green"))))
4915;;; (t (set-face-background 'font-lock-other-emphasized-face "gray90"))))
4916;;; (if (cperl-is-face 'font-lock-emphasized-face) nil
4917;;; (copy-face 'bold 'font-lock-emphasized-face)
4918;;; (cond
4919;;; ((eq background 'light)
4920;;; (set-face-background 'font-lock-emphasized-face
4921;;; (if (x-color-defined-p "lightyellow2")
4922;;; "lightyellow2"
4923;;; "lightyellow")))
4924;;; ((eq background 'dark)
4925;;; (set-face-background 'font-lock-emphasized-face
4926;;; (if (x-color-defined-p "navy")
4927;;; "navy"
4928;;; (if (x-color-defined-p "darkgreen")
4929;;; "darkgreen"
4930;;; "dark green"))))
4931;;; (t (set-face-background 'font-lock-emphasized-face "gray90"))))
db133cb6 4932 (if (cperl-is-face 'font-lock-variable-name-face) nil
f83d2997 4933 (copy-face 'italic 'font-lock-variable-name-face))
db133cb6 4934 (if (cperl-is-face 'font-lock-constant-face) nil
883212ce 4935 (copy-face 'italic 'font-lock-constant-face))))
f83d2997 4936 (setq cperl-faces-init t))
5bd52f0e 4937 (error (message "cperl-init-faces (ignored): %s" errs))))
f83d2997
KH
4938
4939
4940(defun cperl-ps-print-init ()
4941 "Initialization of `ps-print' components for faces used in CPerl."
5bd52f0e
RS
4942 (eval-after-load "ps-print"
4943 '(setq ps-bold-faces
5c8b7eaf 4944 ;; font-lock-variable-name-face
5bd52f0e
RS
4945 ;; font-lock-constant-face
4946 (append '(cperl-array-face
5c8b7eaf 4947 cperl-hash-face)
5bd52f0e
RS
4948 ps-bold-faces)
4949 ps-italic-faces
4950 ;; font-lock-constant-face
4951 (append '(cperl-nonoverridable-face
4952 cperl-hash-face)
4953 ps-italic-faces)
4954 ps-underlined-faces
4955 ;; font-lock-type-face
4956 (append '(cperl-array-face
4957 cperl-hash-face
4958 underline
4959 cperl-nonoverridable-face)
4960 ps-underlined-faces))))
4961
4962(defvar ps-print-face-extension-alist)
4963
4964(defun cperl-ps-print (&optional file)
4965 "Pretty-print in CPerl style.
4966If optional argument FILE is an empty string, prints to printer, otherwise
4967to the file FILE. If FILE is nil, prompts for a file name.
4968
4969Style of printout regulated by the variable `cperl-ps-print-face-properties'."
4970 (interactive)
5c8b7eaf
SS
4971 (or file
4972 (setq file (read-from-minibuffer
5bd52f0e
RS
4973 "Print to file (if empty - to printer): "
4974 (concat (buffer-file-name) ".ps")
4975 nil nil 'file-name-history)))
4976 (or (> (length file) 0)
4977 (setq file nil))
4978 (require 'ps-print) ; To get ps-print-face-extension-alist
4979 (let ((ps-print-color-p t)
4980 (ps-print-face-extension-alist ps-print-face-extension-alist))
4981 (cperl-ps-extend-face-list cperl-ps-print-face-properties)
4982 (ps-print-buffer-with-faces file)))
4983
4984;;; (defun cperl-ps-print-init ()
4985;;; "Initialization of `ps-print' components for faces used in CPerl."
4986;;; ;; Guard against old versions
4987;;; (defvar ps-underlined-faces nil)
4988;;; (defvar ps-bold-faces nil)
4989;;; (defvar ps-italic-faces nil)
4990;;; (setq ps-bold-faces
4991;;; (append '(font-lock-emphasized-face
4992;;; cperl-array-face
5c8b7eaf
SS
4993;;; font-lock-keyword-face
4994;;; font-lock-variable-name-face
4995;;; font-lock-constant-face
4996;;; font-lock-reference-face
5bd52f0e 4997;;; font-lock-other-emphasized-face
5c8b7eaf 4998;;; cperl-hash-face)
5bd52f0e
RS
4999;;; ps-bold-faces))
5000;;; (setq ps-italic-faces
5001;;; (append '(cperl-nonoverridable-face
5c8b7eaf
SS
5002;;; font-lock-constant-face
5003;;; font-lock-reference-face
5bd52f0e
RS
5004;;; font-lock-other-emphasized-face
5005;;; cperl-hash-face)
5006;;; ps-italic-faces))
5007;;; (setq ps-underlined-faces
5008;;; (append '(font-lock-emphasized-face
5009;;; cperl-array-face
5010;;; font-lock-other-emphasized-face
5011;;; cperl-hash-face
5012;;; cperl-nonoverridable-face font-lock-type-face)
5013;;; ps-underlined-faces))
5014;;; (cons 'font-lock-type-face ps-underlined-faces))
f83d2997
KH
5015
5016
5017(if (cperl-enable-font-lock) (cperl-windowed-init))
5018
db133cb6 5019(defconst cperl-styles-entries
5c8b7eaf
SS
5020 '(cperl-indent-level cperl-brace-offset cperl-continued-brace-offset
5021 cperl-label-offset cperl-extra-newline-before-brace
bab27c0c 5022 cperl-merge-trailing-else
db133cb6
RS
5023 cperl-continued-statement-offset))
5024
5025(defconst cperl-style-alist
5026 '(("CPerl" ; =GNU without extra-newline-before-brace
5027 (cperl-indent-level . 2)
5028 (cperl-brace-offset . 0)
5029 (cperl-continued-brace-offset . 0)
5030 (cperl-label-offset . -2)
5031 (cperl-extra-newline-before-brace . nil)
bab27c0c 5032 (cperl-merge-trailing-else . t)
db133cb6
RS
5033 (cperl-continued-statement-offset . 2))
5034 ("PerlStyle" ; CPerl with 4 as indent
5035 (cperl-indent-level . 4)
5036 (cperl-brace-offset . 0)
5037 (cperl-continued-brace-offset . 0)
5038 (cperl-label-offset . -4)
5039 (cperl-extra-newline-before-brace . nil)
bab27c0c 5040 (cperl-merge-trailing-else . t)
db133cb6
RS
5041 (cperl-continued-statement-offset . 4))
5042 ("GNU"
5043 (cperl-indent-level . 2)
5044 (cperl-brace-offset . 0)
5045 (cperl-continued-brace-offset . 0)
5046 (cperl-label-offset . -2)
5047 (cperl-extra-newline-before-brace . t)
bab27c0c 5048 (cperl-merge-trailing-else . nil)
db133cb6
RS
5049 (cperl-continued-statement-offset . 2))
5050 ("K&R"
5051 (cperl-indent-level . 5)
5052 (cperl-brace-offset . 0)
5053 (cperl-continued-brace-offset . -5)
5054 (cperl-label-offset . -5)
5055 ;;(cperl-extra-newline-before-brace . nil) ; ???
bab27c0c 5056 (cperl-merge-trailing-else . nil)
db133cb6
RS
5057 (cperl-continued-statement-offset . 5))
5058 ("BSD"
5059 (cperl-indent-level . 4)
5060 (cperl-brace-offset . 0)
5061 (cperl-continued-brace-offset . -4)
5062 (cperl-label-offset . -4)
5063 ;;(cperl-extra-newline-before-brace . nil) ; ???
5064 (cperl-continued-statement-offset . 4))
5065 ("C++"
5066 (cperl-indent-level . 4)
5067 (cperl-brace-offset . 0)
5068 (cperl-continued-brace-offset . -4)
5069 (cperl-label-offset . -4)
5070 (cperl-continued-statement-offset . 4)
bab27c0c 5071 (cperl-merge-trailing-else . nil)
db133cb6
RS
5072 (cperl-extra-newline-before-brace . t))
5073 ("Current")
5074 ("Whitesmith"
5075 (cperl-indent-level . 4)
5076 (cperl-brace-offset . 0)
5077 (cperl-continued-brace-offset . 0)
5078 (cperl-label-offset . -4)
5079 ;;(cperl-extra-newline-before-brace . nil) ; ???
5080 (cperl-continued-statement-offset . 4)))
5081 "(Experimental) list of variables to set to get a particular indentation style.
5bd52f0e 5082Should be used via `cperl-set-style' or via Perl menu.")
db133cb6 5083
f83d2997 5084(defun cperl-set-style (style)
f94a632a 5085 "Set CPerl mode variables to use one of several different indentation styles.
f83d2997 5086The arguments are a string representing the desired style.
5c8b7eaf 5087The list of styles is in `cperl-style-alist', available styles
db133cb6
RS
5088are GNU, K&R, BSD, C++ and Whitesmith.
5089
5090The current value of style is memorized (unless there is a memorized
5091data already), may be restored by `cperl-set-style-back'.
5092
5093Chosing \"Current\" style will not change style, so this may be used for
5094side-effect of memorizing only."
5c8b7eaf
SS
5095 (interactive
5096 (let ((list (mapcar (function (lambda (elt) (list (car elt))))
db133cb6 5097 cperl-style-alist)))
f83d2997 5098 (list (completing-read "Enter style: " list nil 'insist))))
db133cb6
RS
5099 (or cperl-old-style
5100 (setq cperl-old-style
5101 (mapcar (function
5102 (lambda (name)
5103 (cons name (eval name))))
5104 cperl-styles-entries)))
5105 (let ((style (cdr (assoc style cperl-style-alist))) setting str sym)
f83d2997
KH
5106 (while style
5107 (setq setting (car style) style (cdr style))
db133cb6
RS
5108 (set (car setting) (cdr setting)))))
5109
5110(defun cperl-set-style-back ()
5111 "Restore a style memorised by `cperl-set-style'."
5112 (interactive)
5113 (or cperl-old-style (error "The style was not changed"))
5114 (let (setting)
5115 (while cperl-old-style
5c8b7eaf 5116 (setq setting (car cperl-old-style)
db133cb6
RS
5117 cperl-old-style (cdr cperl-old-style))
5118 (set (car setting) (cdr setting)))))
f83d2997
KH
5119
5120(defun cperl-check-syntax ()
5121 (interactive)
5122 (require 'mode-compile)
db133cb6
RS
5123 (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc")))
5124 (eval '(mode-compile)))) ; Avoid a warning
f83d2997
KH
5125
5126(defun cperl-info-buffer (type)
5127 ;; Returns buffer with documentation. Creates if missing.
5128 ;; If TYPE, this vars buffer.
5129 ;; Special care is taken to not stomp over an existing info buffer
5130 (let* ((bname (if type "*info-perl-var*" "*info-perl*"))
5131 (info (get-buffer bname))
5132 (oldbuf (get-buffer "*info*")))
5133 (if info info
5134 (save-window-excursion
5135 ;; Get Info running
5136 (require 'info)
5137 (cond (oldbuf
5138 (set-buffer oldbuf)
5139 (rename-buffer "*info-perl-tmp*")))
5140 (save-window-excursion
5141 (info))
5142 (Info-find-node cperl-info-page (if type "perlvar" "perlfunc"))
5143 (set-buffer "*info*")
5144 (rename-buffer bname)
5145 (cond (oldbuf
5146 (set-buffer "*info-perl-tmp*")
5147 (rename-buffer "*info*")
5148 (set-buffer bname)))
029cb4d5 5149 (make-local-variable 'window-min-height)
f83d2997
KH
5150 (setq window-min-height 2)
5151 (current-buffer)))))
5152
5153(defun cperl-word-at-point (&optional p)
f94a632a 5154 "Return the word at point or at P."
f83d2997
KH
5155 (save-excursion
5156 (if p (goto-char p))
5157 (or (cperl-word-at-point-hard)
5158 (progn
5159 (require 'etags)
5160 (funcall (or (and (boundp 'find-tag-default-function)
5161 find-tag-default-function)
5162 (get major-mode 'find-tag-default-function)
5163 ;; XEmacs 19.12 has `find-tag-default-hook'; it is
5164 ;; automatically used within `find-tag-default':
5165 'find-tag-default))))))
5166
5167(defun cperl-info-on-command (command)
f94a632a 5168 "Show documentation for Perl command COMMAND in other window.
f83d2997
KH
5169If perl-info buffer is shown in some frame, uses this frame.
5170Customized by setting variables `cperl-shrink-wrap-info-frame',
5171`cperl-max-help-size'."
5c8b7eaf 5172 (interactive
f83d2997 5173 (let* ((default (cperl-word-at-point))
5c8b7eaf
SS
5174 (read (read-string
5175 (format "Find doc for Perl function (default %s): "
f83d2997 5176 default))))
5c8b7eaf
SS
5177 (list (if (equal read "")
5178 default
f83d2997
KH
5179 read))))
5180
5181 (let ((buffer (current-buffer))
5182 (cmd-desc (concat "^" (regexp-quote command) "[^a-zA-Z_0-9]")) ; "tr///"
5183 pos isvar height iniheight frheight buf win fr1 fr2 iniwin not-loner
5184 max-height char-height buf-list)
5185 (if (string-match "^-[a-zA-Z]$" command)
5186 (setq cmd-desc "^-X[ \t\n]"))
5187 (setq isvar (string-match "^[$@%]" command)
5188 buf (cperl-info-buffer isvar)
5189 iniwin (selected-window)
5190 fr1 (window-frame iniwin))
5191 (set-buffer buf)
5192 (beginning-of-buffer)
5c8b7eaf 5193 (or isvar
f83d2997
KH
5194 (progn (re-search-forward "^-X[ \t\n]")
5195 (forward-line -1)))
5196 (if (re-search-forward cmd-desc nil t)
5197 (progn
5198 ;; Go back to beginning of the group (ex, for qq)
5199 (if (re-search-backward "^[ \t\n\f]")
5200 (forward-line 1))
5201 (beginning-of-line)
5c8b7eaf 5202 ;; Get some of
f83d2997
KH
5203 (setq pos (point)
5204 buf-list (list buf "*info-perl-var*" "*info-perl*"))
5205 (while (and (not win) buf-list)
5206 (setq win (get-buffer-window (car buf-list) t))
5207 (setq buf-list (cdr buf-list)))
5208 (or (not win)
5209 (eq (window-buffer win) buf)
5210 (set-window-buffer win buf))
5211 (and win (setq fr2 (window-frame win)))
5212 (if (or (not fr2) (eq fr1 fr2))
5213 (pop-to-buffer buf)
5214 (special-display-popup-frame buf) ; Make it visible
5215 (select-window win))
5216 (goto-char pos) ; Needed (?!).
5217 ;; Resize
5218 (setq iniheight (window-height)
5219 frheight (frame-height)
5220 not-loner (< iniheight (1- frheight))) ; Are not alone
5c8b7eaf 5221 (cond ((if not-loner cperl-max-help-size
f83d2997 5222 cperl-shrink-wrap-info-frame)
5c8b7eaf
SS
5223 (setq height
5224 (+ 2
5225 (count-lines
5226 pos
f83d2997
KH
5227 (save-excursion
5228 (if (re-search-forward
5229 "^[ \t][^\n]*\n+\\([^ \t\n\f]\\|\\'\\)" nil t)
5230 (match-beginning 0) (point-max)))))
5c8b7eaf 5231 max-height
f83d2997
KH
5232 (if not-loner
5233 (/ (* (- frheight 3) cperl-max-help-size) 100)
5234 (setq char-height (frame-char-height))
5235 ;; Non-functioning under OS/2:
5236 (if (eq char-height 1) (setq char-height 18))
5237 ;; Title, menubar, + 2 for slack
5238 (- (/ (x-display-pixel-height) char-height) 4)
5239 ))
5240 (if (> height max-height) (setq height max-height))
5241 ;;(message "was %s doing %s" iniheight height)
5242 (if not-loner
5243 (enlarge-window (- height iniheight))
5244 (set-frame-height (window-frame win) (1+ height)))))
5245 (set-window-start (selected-window) pos))
5246 (message "No entry for %s found." command))
5247 ;;(pop-to-buffer buffer)
5248 (select-window iniwin)))
5249
5250(defun cperl-info-on-current-command ()
029cb4d5 5251 "Show documentation for Perl command at point in other window."
f83d2997
KH
5252 (interactive)
5253 (cperl-info-on-command (cperl-word-at-point)))
5254
5255(defun cperl-imenu-info-imenu-search ()
5256 (if (looking-at "^-X[ \t\n]") nil
5257 (re-search-backward
5258 "^\n\\([-a-zA-Z_]+\\)[ \t\n]")
5259 (forward-line 1)))
5260
5c8b7eaf 5261(defun cperl-imenu-info-imenu-name ()
f83d2997
KH
5262 (buffer-substring
5263 (match-beginning 1) (match-end 1)))
5264
5265(defun cperl-imenu-on-info ()
5266 (interactive)
5267 (let* ((buffer (current-buffer))
5268 imenu-create-index-function
5c8b7eaf
SS
5269 imenu-prev-index-position-function
5270 imenu-extract-index-name-function
f83d2997
KH
5271 (index-item (save-restriction
5272 (save-window-excursion
5273 (set-buffer (cperl-info-buffer nil))
5c8b7eaf 5274 (setq imenu-create-index-function
f83d2997
KH
5275 'imenu-default-create-index-function
5276 imenu-prev-index-position-function
5277 'cperl-imenu-info-imenu-search
5278 imenu-extract-index-name-function
5279 'cperl-imenu-info-imenu-name)
5280 (imenu-choose-buffer-index)))))
5281 (and index-item
5282 (progn
5283 (push-mark)
5284 (pop-to-buffer "*info-perl*")
5285 (cond
5286 ((markerp (cdr index-item))
5287 (goto-char (marker-position (cdr index-item))))
5288 (t
5289 (goto-char (cdr index-item))))
5290 (set-window-start (selected-window) (point))
5291 (pop-to-buffer buffer)))))
5292
5293(defun cperl-lineup (beg end &optional step minshift)
5294 "Lineup construction in a region.
5295Beginning of region should be at the start of a construction.
5296All first occurrences of this construction in the lines that are
5297partially contained in the region are lined up at the same column.
5298
5299MINSHIFT is the minimal amount of space to insert before the construction.
5300STEP is the tabwidth to position constructions.
029cb4d5 5301If STEP is nil, `cperl-lineup-step' will be used
f83d2997
KH
5302\(or `cperl-indent-level', if `cperl-lineup-step' is `nil').
5303Will not move the position at the start to the left."
5304 (interactive "r")
5305 (let (search col tcol seen b e)
5306 (save-excursion
5307 (goto-char end)
5308 (end-of-line)
5309 (setq end (point-marker))
5310 (goto-char beg)
5311 (skip-chars-forward " \t\f")
5312 (setq beg (point-marker))
5313 (indent-region beg end nil)
5314 (goto-char beg)
5315 (setq col (current-column))
5316 (if (looking-at "[a-zA-Z0-9_]")
5317 (if (looking-at "\\<[a-zA-Z0-9_]+\\>")
5318 (setq search
5c8b7eaf
SS
5319 (concat "\\<"
5320 (regexp-quote
f83d2997
KH
5321 (buffer-substring (match-beginning 0)
5322 (match-end 0))) "\\>"))
5323 (error "Cannot line up in a middle of the word"))
5324 (if (looking-at "$")
5325 (error "Cannot line up end of line"))
5326 (setq search (regexp-quote (char-to-string (following-char)))))
5327 (setq step (or step cperl-lineup-step cperl-indent-level))
5328 (or minshift (setq minshift 1))
5329 (while (progn
5330 (beginning-of-line 2)
5c8b7eaf 5331 (and (< (point) end)
f83d2997
KH
5332 (re-search-forward search end t)
5333 (goto-char (match-beginning 0))))
5334 (setq tcol (current-column) seen t)
5335 (if (> tcol col) (setq col tcol)))
5336 (or seen
5337 (error "The construction to line up occurred only once"))
5338 (goto-char beg)
5339 (setq col (+ col minshift))
5340 (if (/= (% col step) 0) (setq step (* step (1+ (/ col step)))))
5c8b7eaf 5341 (while
f83d2997
KH
5342 (progn
5343 (setq e (point))
5344 (skip-chars-backward " \t")
5345 (delete-region (point) e)
5346 (indent-to-column col); (make-string (- col (current-column)) ?\ ))
5c8b7eaf
SS
5347 (beginning-of-line 2)
5348 (and (< (point) end)
f83d2997
KH
5349 (re-search-forward search end t)
5350 (goto-char (match-beginning 0)))))))) ; No body
5351
5352(defun cperl-etags (&optional add all files)
5353 "Run etags with appropriate options for Perl files.
5354If optional argument ALL is `recursive', will process Perl files
5355in subdirectories too."
5356 (interactive)
5357 (let ((cmd "etags")
5358 (args '("-l" "none" "-r" "/\\<\\(package\\|sub\\)[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)[ \\t]*\\(([^()]*)[ \t]*\\)?\\([{#]\\|$\\)\\)/\\4/"))
5359 res)
5360 (if add (setq args (cons "-a" args)))
5361 (or files (setq files (list buffer-file-name)))
5362 (cond
5363 ((eq all 'recursive)
5364 ;;(error "Not implemented: recursive")
5c8b7eaf 5365 (setq args (append (list "-e"
f83d2997
KH
5366 "sub wanted {push @ARGV, $File::Find::name if /\\.[pP][Llm]$/}
5367 use File::Find;
5368 find(\\&wanted, '.');
5c8b7eaf 5369 exec @ARGV;"
f83d2997
KH
5370 cmd) args)
5371 cmd "perl"))
5c8b7eaf 5372 (all
f83d2997 5373 ;;(error "Not implemented: all")
5c8b7eaf 5374 (setq args (append (list "-e"
f83d2997 5375 "push @ARGV, <*.PL *.pl *.pm>;
5c8b7eaf 5376 exec @ARGV;"
f83d2997
KH
5377 cmd) args)
5378 cmd "perl"))
5379 (t
5380 (setq args (append args files))))
5381 (setq res (apply 'call-process cmd nil nil nil args))
5382 (or (eq res 0)
5383 (message "etags returned \"%s\"" res))))
5384
5385(defun cperl-toggle-auto-newline ()
5386 "Toggle the state of `cperl-auto-newline'."
5387 (interactive)
5388 (setq cperl-auto-newline (not cperl-auto-newline))
5c8b7eaf 5389 (message "Newlines will %sbe auto-inserted now."
f83d2997
KH
5390 (if cperl-auto-newline "" "not ")))
5391
5392(defun cperl-toggle-abbrev ()
5393 "Toggle the state of automatic keyword expansion in CPerl mode."
5394 (interactive)
5395 (abbrev-mode (if abbrev-mode 0 1))
5c8b7eaf 5396 (message "Perl control structure will %sbe auto-inserted now."
f83d2997
KH
5397 (if abbrev-mode "" "not ")))
5398
5399
5400(defun cperl-toggle-electric ()
5401 "Toggle the state of parentheses doubling in CPerl mode."
5402 (interactive)
5403 (setq cperl-electric-parens (if (cperl-val 'cperl-electric-parens) 'null t))
5c8b7eaf 5404 (message "Parentheses will %sbe auto-doubled now."
f83d2997
KH
5405 (if (cperl-val 'cperl-electric-parens) "" "not ")))
5406
db133cb6
RS
5407(defun cperl-toggle-autohelp ()
5408 "Toggle the state of automatic help message in CPerl mode.
5409See `cperl-lazy-help-time' too."
5410 (interactive)
5411 (if (fboundp 'run-with-idle-timer)
5412 (progn
5413 (if cperl-lazy-installed
5414 (eval '(cperl-lazy-unstall))
5415 (cperl-lazy-install))
5c8b7eaf 5416 (message "Perl help messages will %sbe automatically shown now."
db133cb6
RS
5417 (if cperl-lazy-installed "" "not ")))
5418 (message "Cannot automatically show Perl help messages - run-with-idle-timer missing.")))
5419
5420(defun cperl-toggle-construct-fix ()
5421 "Toggle whether `indent-region'/`indent-sexp' fix whitespace too."
5422 (interactive)
5c8b7eaf 5423 (setq cperl-indent-region-fix-constructs
5bd52f0e
RS
5424 (if cperl-indent-region-fix-constructs
5425 nil
5426 1))
5c8b7eaf 5427 (message "indent-region/indent-sexp will %sbe automatically fix whitespace."
db133cb6
RS
5428 (if cperl-indent-region-fix-constructs "" "not ")))
5429
f83d2997
KH
5430;;;; Tags file creation.
5431
5432(defvar cperl-tmp-buffer " *cperl-tmp*")
5433
5434(defun cperl-setup-tmp-buf ()
5435 (set-buffer (get-buffer-create cperl-tmp-buffer))
5436 (set-syntax-table cperl-mode-syntax-table)
5437 (buffer-disable-undo)
5438 (auto-fill-mode 0)
5439 (if cperl-use-syntax-table-text-property-for-tags
5440 (progn
029cb4d5 5441 (make-local-variable 'parse-sexp-lookup-properties)
f83d2997
KH
5442 ;; Do not introduce variable if not needed, we check it!
5443 (set 'parse-sexp-lookup-properties t))))
5444
5445(defun cperl-xsub-scan ()
f83d2997 5446 (require 'imenu)
5c8b7eaf 5447 (let ((index-alist '())
f83d2997
KH
5448 (prev-pos 0) index index1 name package prefix)
5449 (goto-char (point-min))
5450 (if noninteractive
5451 (message "Scanning XSUB for index")
5452 (imenu-progress-message prev-pos 0))
5453 ;; Search for the function
5454 (progn ;;save-match-data
5455 (while (re-search-forward
5456 "^\\([ \t]*MODULE\\>[^\n]*\\<PACKAGE[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9:]*\\)\\>\\|\\([a-zA-Z_][a-zA-Z_0-9]*\\)(\\|[ \t]*BOOT:\\)"
5457 nil t)
5458 (or noninteractive
5459 (imenu-progress-message prev-pos))
5460 (cond
5461 ((match-beginning 2) ; SECTION
5462 (setq package (buffer-substring (match-beginning 2) (match-end 2)))
5463 (goto-char (match-beginning 0))
5464 (skip-chars-forward " \t")
5465 (forward-char 1)
5466 (if (looking-at "[^\n]*\\<PREFIX[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9]*\\)\\>")
5467 (setq prefix (buffer-substring (match-beginning 1) (match-end 1)))
5468 (setq prefix nil)))
5469 ((not package) nil) ; C language section
5470 ((match-beginning 3) ; XSUB
5471 (goto-char (1+ (match-beginning 3)))
5472 (setq index (imenu-example--name-and-position))
5473 (setq name (buffer-substring (match-beginning 3) (match-end 3)))
5474 (if (and prefix (string-match (concat "^" prefix) name))
5475 (setq name (substring name (length prefix))))
5476 (cond ((string-match "::" name) nil)
5477 (t
5478 (setq index1 (cons (concat package "::" name) (cdr index)))
5479 (push index1 index-alist)))
5480 (setcar index name)
5481 (push index index-alist))
5482 (t ; BOOT: section
5483 ;; (beginning-of-line)
5484 (setq index (imenu-example--name-and-position))
5485 (setcar index (concat package "::BOOT:"))
5486 (push index index-alist)))))
5487 (or noninteractive
5488 (imenu-progress-message prev-pos 100))
f83d2997
KH
5489 index-alist))
5490
6c389151
SM
5491(defvar cperl-unreadable-ok nil)
5492
5493(defun cperl-find-tags (ifile xs topdir)
f83d2997 5494 (let (ind (b (get-buffer cperl-tmp-buffer)) lst elt pos ret rel
6c389151 5495 (cperl-pod-here-fontify nil) f file)
f83d2997
KH
5496 (save-excursion
5497 (if b (set-buffer b)
5498 (cperl-setup-tmp-buf))
5499 (erase-buffer)
6c389151
SM
5500 (condition-case err
5501 (setq file (car (insert-file-contents ifile)))
5502 (error (if cperl-unreadable-ok nil
5503 (if (y-or-n-p
5504 (format "File %s unreadable. Continue? " ifile))
5505 (setq cperl-unreadable-ok t)
5506 (error "Aborting: unreadable file %s" ifile)))))
5507 (if (not file)
5508 (message "Unreadable file %s" ifile)
f83d2997
KH
5509 (message "Scanning file %s ..." file)
5510 (if (and cperl-use-syntax-table-text-property-for-tags
5511 (not xs))
5512 (condition-case err ; after __END__ may have garbage
6c389151 5513 (cperl-find-pods-heres nil nil noninteractive)
f83d2997
KH
5514 (error (message "While scanning for syntax: %s" err))))
5515 (if xs
5516 (setq lst (cperl-xsub-scan))
80585273 5517 (setq ind (cperl-imenu--create-perl-index))
f83d2997 5518 (setq lst (cdr (assoc "+Unsorted List+..." ind))))
5c8b7eaf
SS
5519 (setq lst
5520 (mapcar
5521 (function
f83d2997
KH
5522 (lambda (elt)
5523 (cond ((string-match "^[_a-zA-Z]" (car elt))
5524 (goto-char (cdr elt))
5bd52f0e 5525 (beginning-of-line) ; pos should be of the start of the line
5c8b7eaf
SS
5526 (list (car elt)
5527 (point)
5bd52f0e 5528 (1+ (count-lines 1 (point))) ; 1+ since at beg-o-l
f83d2997 5529 (buffer-substring (progn
6c389151
SM
5530 (goto-char (cdr elt))
5531 ;; After name now...
f83d2997
KH
5532 (or (eolp) (forward-char 1))
5533 (point))
5534 (progn
5535 (beginning-of-line)
5536 (point))))))))
5537 lst))
5538 (erase-buffer)
5539 (while lst
5540 (setq elt (car lst) lst (cdr lst))
5541 (if elt
5542 (progn
5c8b7eaf 5543 (insert (elt elt 3)
f83d2997
KH
5544 127
5545 (if (string-match "^package " (car elt))
5546 (substring (car elt) 8)
5547 (car elt) )
5548 1
5bd52f0e 5549 (number-to-string (elt elt 2)) ; Line
f83d2997 5550 ","
5bd52f0e 5551 (number-to-string (1- (elt elt 1))) ; Char pos 0-based
f83d2997
KH
5552 "\n")
5553 (if (and (string-match "^[_a-zA-Z]+::" (car elt))
5554 (string-match "^sub[ \t]+\\([_a-zA-Z]+\\)[^:_a-zA-Z]"
5555 (elt elt 3)))
5556 ;; Need to insert the name without package as well
5c8b7eaf 5557 (setq lst (cons (cons (substring (elt elt 3)
f83d2997
KH
5558 (match-beginning 1)
5559 (match-end 1))
5560 (cdr elt))
5561 lst))))))
5562 (setq pos (point))
5563 (goto-char 1)
5564 (setq rel file)
5565 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
5566 (set-text-properties 0 (length rel) nil rel)
5567 (and (equal topdir (substring rel 0 (length topdir)))
5568 (setq rel (substring file (length topdir))))
5569 (insert "\f\n" rel "," (number-to-string (1- pos)) "\n")
5570 (setq ret (buffer-substring 1 (point-max)))
5571 (erase-buffer)
5572 (or noninteractive
5573 (message "Scanning file %s finished" file))
6c389151 5574 ret))))
f83d2997
KH
5575
5576(defun cperl-add-tags-recurse-noxs ()
5577 "Add to TAGS data for Perl and XSUB files in the current directory and kids.
5578Use as
5579 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
5c8b7eaf 5580 -f cperl-add-tags-recurse
f83d2997
KH
5581"
5582 (cperl-write-tags nil nil t t nil t))
5583
5584(defun cperl-add-tags-recurse ()
5585 "Add to TAGS file data for Perl files in the current directory and kids.
5586Use as
5587 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
5c8b7eaf 5588 -f cperl-add-tags-recurse
f83d2997
KH
5589"
5590 (cperl-write-tags nil nil t t))
5591
5592(defun cperl-write-tags (&optional file erase recurse dir inbuffer noxs topdir)
5593 ;; If INBUFFER, do not select buffer, and do not save
5594 ;; If ERASE is `ignore', do not erase, and do not try to delete old info.
5595 (require 'etags)
5596 (if file nil
5597 (setq file (if dir default-directory (buffer-file-name)))
5598 (if (and (not dir) (buffer-modified-p)) (error "Save buffer first!")))
5599 (or topdir
5600 (setq topdir default-directory))
5601 (let ((tags-file-name "TAGS")
5602 (case-fold-search (eq system-type 'emx))
6c389151 5603 xs rel tm)
f83d2997
KH
5604 (save-excursion
5605 (cond (inbuffer nil) ; Already there
5606 ((file-exists-p tags-file-name)
5bd52f0e
RS
5607 (if cperl-xemacs-p
5608 (visit-tags-table-buffer)
5609 (visit-tags-table-buffer tags-file-name)))
f83d2997
KH
5610 (t (set-buffer (find-file-noselect tags-file-name))))
5611 (cond
5612 (dir
5613 (cond ((eq erase 'ignore))
5614 (erase
5615 (erase-buffer)
5616 (setq erase 'ignore)))
6c389151
SM
5617 (let ((files
5618 (condition-case err
5619 (directory-files file t
5620 (if recurse nil cperl-scan-files-regexp)
5621 t)
5622 (error
5623 (if cperl-unreadable-ok nil
5624 (if (y-or-n-p
5625 (format "Directory %s unreadable. Continue? " file))
5626 (setq cperl-unreadable-ok t
5627 tm nil) ; Return empty list
5628 (error "Aborting: unreadable directory %s" file)))))))
f83d2997
KH
5629 (mapcar (function (lambda (file)
5630 (cond
5631 ((string-match cperl-noscan-files-regexp file)
5632 nil)
5633 ((not (file-directory-p file))
5634 (if (string-match cperl-scan-files-regexp file)
5635 (cperl-write-tags file erase recurse nil t noxs topdir)))
5636 ((not recurse) nil)
5637 (t (cperl-write-tags file erase recurse t t noxs topdir)))))
5638 files))
5639 )
5640 (t
5641 (setq xs (string-match "\\.xs$" file))
5642 (if (not (and xs noxs))
5643 (progn
5644 (cond ((eq erase 'ignore) (goto-char (point-max)))
5645 (erase (erase-buffer))
5646 (t
5647 (goto-char 1)
5bd52f0e
RS
5648 (setq rel file)
5649 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
5650 (set-text-properties 0 (length rel) nil rel)
5651 (and (equal topdir (substring rel 0 (length topdir)))
5652 (setq rel (substring file (length topdir))))
5653 (if (search-forward (concat "\f\n" rel ",") nil t)
f83d2997
KH
5654 (progn
5655 (search-backward "\f\n")
5656 (delete-region (point)
5657 (save-excursion
5658 (forward-char 1)
5c8b7eaf 5659 (if (search-forward "\f\n"
f83d2997
KH
5660 nil 'toend)
5661 (- (point) 2)
5662 (point-max)))))
5663 (goto-char (point-max)))))
5664 (insert (cperl-find-tags file xs topdir))))))
5665 (if inbuffer nil ; Delegate to the caller
5666 (save-buffer 0) ; No backup
5667 (if (fboundp 'initialize-new-tags-table) ; Do we need something special in XEmacs?
5668 (initialize-new-tags-table))))))
5669
5670(defvar cperl-tags-hier-regexp-list
5c8b7eaf 5671 (concat
f83d2997
KH
5672 "^\\("
5673 "\\(package\\)\\>"
5674 "\\|"
5675 "sub\\>[^\n]+::"
5676 "\\|"
5677 "[a-zA-Z_][a-zA-Z_0-9:]*(\C-?[^\n]+::" ; XSUB?
5678 "\\|"
5679 "[ \t]*BOOT:\C-?[^\n]+::" ; BOOT section
5680 "\\)"))
5681
5682(defvar cperl-hierarchy '(() ())
f94a632a 5683 "Global hierarchy of classes.")
f83d2997
KH
5684
5685(defun cperl-tags-hier-fill ()
5686 ;; Suppose we are in a tag table cooked by cperl.
5687 (goto-char 1)
5688 (let (type pack name pos line chunk ord cons1 file str info fileind)
5689 (while (re-search-forward cperl-tags-hier-regexp-list nil t)
5c8b7eaf 5690 (setq pos (match-beginning 0)
f83d2997
KH
5691 pack (match-beginning 2))
5692 (beginning-of-line)
5693 (if (looking-at (concat
5694 "\\([^\n]+\\)"
5695 "\C-?"
5696 "\\([^\n]+\\)"
5697 "\C-a"
5698 "\\([0-9]+\\)"
5699 ","
5700 "\\([0-9]+\\)"))
5701 (progn
5702 (setq ;;str (buffer-substring (match-beginning 1) (match-end 1))
5703 name (buffer-substring (match-beginning 2) (match-end 2))
5704 ;;pos (buffer-substring (match-beginning 3) (match-end 3))
5bd52f0e 5705 line (buffer-substring (match-beginning 3) (match-end 3))
f83d2997 5706 ord (if pack 1 0)
f83d2997 5707 file (file-of-tag)
5bd52f0e
RS
5708 fileind (format "%s:%s" file line)
5709 ;; Moves to beginning of the next line:
5710 info (cperl-etags-snarf-tag file line))
f83d2997
KH
5711 ;; Move back
5712 (forward-char -1)
5713 ;; Make new member of hierarchy name ==> file ==> pos if needed
5714 (if (setq cons1 (assoc name (nth ord cperl-hierarchy)))
5715 ;; Name known
5716 (setcdr cons1 (cons (cons fileind (vector file info))
5717 (cdr cons1)))
5718 ;; First occurrence of the name, start alist
5719 (setq cons1 (cons name (list (cons fileind (vector file info)))))
5c8b7eaf 5720 (if pack
f83d2997
KH
5721 (setcar (cdr cperl-hierarchy)
5722 (cons cons1 (nth 1 cperl-hierarchy)))
5723 (setcar cperl-hierarchy
5724 (cons cons1 (car cperl-hierarchy)))))))
5725 (end-of-line))))
5726
5727(defun cperl-tags-hier-init (&optional update)
5728 "Show hierarchical menu of classes and methods.
5729Finds info about classes by a scan of loaded TAGS files.
5730Supposes that the TAGS files contain fully qualified function names.
5731One may build such TAGS files from CPerl mode menu."
5732 (interactive)
5733 (require 'etags)
5734 (require 'imenu)
5735 (if (or update (null (nth 2 cperl-hierarchy)))
5bd52f0e 5736 (let (pack name cons1 to l1 l2 l3 l4 b
f83d2997
KH
5737 (remover (function (lambda (elt) ; (name (file1...) (file2..))
5738 (or (nthcdr 2 elt)
5739 ;; Only in one file
5740 (setcdr elt (cdr (nth 1 elt))))))))
5741 ;; (setq cperl-hierarchy '(() () ())) ; Would write into '() later!
5742 (setq cperl-hierarchy (list l1 l2 l3))
5bd52f0e
RS
5743 (if cperl-xemacs-p ; Not checked
5744 (progn
5745 (or tags-file-name
5746 ;; Does this work in XEmacs?
f83d2997
KH
5747 (call-interactively 'visit-tags-table))
5748 (message "Updating list of classes...")
5bd52f0e
RS
5749 (set-buffer (get-file-buffer tags-file-name))
5750 (cperl-tags-hier-fill))
5751 (or tags-table-list
5752 (call-interactively 'visit-tags-table))
5c8b7eaf 5753 (mapcar
f83d2997
KH
5754 (function
5755 (lambda (tagsfile)
5bd52f0e 5756 (message "Updating list of classes... %s" tagsfile)
f83d2997
KH
5757 (set-buffer (get-file-buffer tagsfile))
5758 (cperl-tags-hier-fill)))
5759 tags-table-list)
5bd52f0e 5760 (message "Updating list of classes... postprocessing..."))
f83d2997
KH
5761 (mapcar remover (car cperl-hierarchy))
5762 (mapcar remover (nth 1 cperl-hierarchy))
5763 (setq to (list nil (cons "Packages: " (nth 1 cperl-hierarchy))
5764 (cons "Methods: " (car cperl-hierarchy))))
5765 (cperl-tags-treeify to 1)
5766 (setcar (nthcdr 2 cperl-hierarchy)
5767 (cperl-menu-to-keymap (cons '("+++UPDATE+++" . -999) (cdr to))))
5768 (message "Updating list of classes: done, requesting display...")
5769 ;;(cperl-imenu-addback (nth 2 cperl-hierarchy))
5770 ))
5771 (or (nth 2 cperl-hierarchy)
5772 (error "No items found"))
5773 (setq update
5774;;; (imenu-choose-buffer-index "Packages: " (nth 2 cperl-hierarchy))
5775 (if window-system
5776 (x-popup-menu t (nth 2 cperl-hierarchy))
5777 (require 'tmm)
5778 (tmm-prompt (nth 2 cperl-hierarchy))))
5779 (if (and update (listp update))
5780 (progn (while (cdr update) (setq update (cdr update)))
5781 (setq update (car update)))) ; Get the last from the list
5c8b7eaf 5782 (if (vectorp update)
f83d2997
KH
5783 (progn
5784 (find-file (elt update 0))
5bd52f0e 5785 (cperl-etags-goto-tag-location (elt update 1))))
f83d2997
KH
5786 (if (eq update -999) (cperl-tags-hier-init t)))
5787
5788(defun cperl-tags-treeify (to level)
5789 ;; cadr of `to' is read-write. On start it is a cons
5c8b7eaf 5790 (let* ((regexp (concat "^\\(" (mapconcat
f83d2997
KH
5791 'identity
5792 (make-list level "[_a-zA-Z0-9]+")
5793 "::")
5794 "\\)\\(::\\)?"))
5795 (packages (cdr (nth 1 to)))
5796 (methods (cdr (nth 2 to)))
5797 l1 head tail cons1 cons2 ord writeto packs recurse
5798 root-packages root-functions ms many_ms same_name ps
5799 (move-deeper
5c8b7eaf 5800 (function
f83d2997
KH
5801 (lambda (elt)
5802 (cond ((and (string-match regexp (car elt))
5803 (or (eq ord 1) (match-end 2)))
5804 (setq head (substring (car elt) 0 (match-end 1))
5c8b7eaf 5805 tail (if (match-end 2) (substring (car elt)
f83d2997
KH
5806 (match-end 2)))
5807 recurse t)
5808 (if (setq cons1 (assoc head writeto)) nil
5809 ;; Need to init new head
5810 (setcdr writeto (cons (list head (list "Packages: ")
5811 (list "Methods: "))
5812 (cdr writeto)))
5813 (setq cons1 (nth 1 writeto)))
5814 (setq cons2 (nth ord cons1)) ; Either packs or meths
5815 (setcdr cons2 (cons elt (cdr cons2))))
5816 ((eq ord 2)
5817 (setq root-functions (cons elt root-functions)))
5818 (t
5819 (setq root-packages (cons elt root-packages))))))))
5820 (setcdr to l1) ; Init to dynamic space
5821 (setq writeto to)
5822 (setq ord 1)
5823 (mapcar move-deeper packages)
5824 (setq ord 2)
5825 (mapcar move-deeper methods)
5826 (if recurse
5827 (mapcar (function (lambda (elt)
5828 (cperl-tags-treeify elt (1+ level))))
5829 (cdr to)))
5830 ;;Now clean up leaders with one child only
5831 (mapcar (function (lambda (elt)
5c8b7eaf 5832 (if (not (and (listp (cdr elt))
f83d2997
KH
5833 (eq (length elt) 2))) nil
5834 (setcar elt (car (nth 1 elt)))
5835 (setcdr elt (cdr (nth 1 elt))))))
5836 (cdr to))
5837 ;; Sort the roots of subtrees
5838 (if (default-value 'imenu-sort-function)
5839 (setcdr to
5840 (sort (cdr to) (default-value 'imenu-sort-function))))
5841 ;; Now add back functions removed from display
5842 (mapcar (function (lambda (elt)
5843 (setcdr to (cons elt (cdr to)))))
5844 (if (default-value 'imenu-sort-function)
5845 (nreverse
5846 (sort root-functions (default-value 'imenu-sort-function)))
5847 root-functions))
5848 ;; Now add back packages removed from display
5849 (mapcar (function (lambda (elt)
5c8b7eaf
SS
5850 (setcdr to (cons (cons (concat "package " (car elt))
5851 (cdr elt))
f83d2997
KH
5852 (cdr to)))))
5853 (if (default-value 'imenu-sort-function)
5c8b7eaf 5854 (nreverse
f83d2997
KH
5855 (sort root-packages (default-value 'imenu-sort-function)))
5856 root-packages))
5857 ))
5858
5859;;;(x-popup-menu t
5c8b7eaf 5860;;; '(keymap "Name1"
f83d2997 5861;;; ("Ret1" "aa")
5c8b7eaf
SS
5862;;; ("Head1" "ab"
5863;;; keymap "Name2"
f83d2997
KH
5864;;; ("Tail1" "x") ("Tail2" "y"))))
5865
5866(defun cperl-list-fold (list name limit)
5867 (let (list1 list2 elt1 (num 0))
5868 (if (<= (length list) limit) list
5869 (setq list1 nil list2 nil)
5870 (while list
5c8b7eaf 5871 (setq num (1+ num)
f83d2997
KH
5872 elt1 (car list)
5873 list (cdr list))
5874 (if (<= num imenu-max-items)
5875 (setq list2 (cons elt1 list2))
5876 (setq list1 (cons (cons name
5877 (nreverse list2))
5878 list1)
5879 list2 (list elt1)
5880 num 1)))
5881 (nreverse (cons (cons name
5882 (nreverse list2))
5883 list1)))))
5884
5885(defun cperl-menu-to-keymap (menu &optional name)
5886 (let (list)
5c8b7eaf
SS
5887 (cons 'keymap
5888 (mapcar
5889 (function
f83d2997
KH
5890 (lambda (elt)
5891 (cond ((listp (cdr elt))
5892 (setq list (cperl-list-fold
5893 (cdr elt) (car elt) imenu-max-items))
5894 (cons nil
5895 (cons (car elt)
5896 (cperl-menu-to-keymap list))))
5897 (t
5898 (list (cdr elt) (car elt) t))))) ; t is needed in 19.34
5899 (cperl-list-fold menu "Root" imenu-max-items)))))
5900
5901\f
5902(defvar cperl-bad-style-regexp
5903 (mapconcat 'identity
5904 '("[^-\n\t <>=+!.&|(*/'`\"#^][-=+<>!|&^]" ; char sign
5905 "[-<>=+^&|]+[^- \t\n=+<>~]" ; sign+ char
5906 )
5907 "\\|")
5908 "Finds places such that insertion of a whitespace may help a lot.")
5909
5c8b7eaf 5910(defvar cperl-not-bad-style-regexp
f83d2997
KH
5911 (mapconcat 'identity
5912 '("[^-\t <>=+]\\(--\\|\\+\\+\\)" ; var-- var++
5913 "[a-zA-Z0-9_][|&][a-zA-Z0-9_$]" ; abc|def abc&def are often used.
5914 "&[(a-zA-Z0-9_$]" ; &subroutine &(var->field)
5915 "<\\$?\\sw+\\(\\.\\sw+\\)?>" ; <IN> <stdin.h>
5bd52f0e 5916 "-[a-zA-Z][ \t]+[_$\"'`a-zA-Z]" ; -f file, -t STDIN
f83d2997
KH
5917 "-[0-9]" ; -5
5918 "\\+\\+" ; ++var
5919 "--" ; --var
5920 ".->" ; a->b
5921 "->" ; a SPACE ->b
5922 "\\[-" ; a[-1]
5bd52f0e 5923 "\\\\[&$@*\\\\]" ; \&func
f83d2997 5924 "^=" ; =head
5bd52f0e
RS
5925 "\\$." ; $|
5926 "<<[a-zA-Z_'\"`]" ; <<FOO, <<'FOO'
f83d2997
KH
5927 "||"
5928 "&&"
5929 "[CBIXSLFZ]<\\(\\sw\\|\\s \\|\\s_\\|[\n]\\)*>" ; C<code like text>
5930 "-[a-zA-Z_0-9]+[ \t]*=>" ; -option => value
5931 ;; Unaddressed trouble spots: = -abc, f(56, -abc) --- specialcased below
5932 ;;"[*/+-|&<.]+="
5933 )
5934 "\\|")
5935 "If matches at the start of match found by `my-bad-c-style-regexp',
5936insertion of a whitespace will not help.")
5937
5938(defvar found-bad)
5939
5940(defun cperl-find-bad-style ()
5941 "Find places in the buffer where insertion of a whitespace may help.
5942Prompts user for insertion of spaces.
5943Currently it is tuned to C and Perl syntax."
5944 (interactive)
5945 (let (found-bad (p (point)))
5946 (setq last-nonmenu-event 13) ; To disable popup
5947 (beginning-of-buffer)
5948 (map-y-or-n-p "Insert space here? "
5949 (function (lambda (arg) (insert " ")))
5950 'cperl-next-bad-style
5c8b7eaf 5951 '("location" "locations" "insert a space into")
f83d2997
KH
5952 '((?\C-r (lambda (arg)
5953 (let ((buffer-quit-function
5954 'exit-recursive-edit))
5955 (message "Exit with Esc Esc")
5956 (recursive-edit)
5957 t)) ; Consider acted upon
5c8b7eaf 5958 "edit, exit with Esc Esc")
f83d2997
KH
5959 (?e (lambda (arg)
5960 (let ((buffer-quit-function
5961 'exit-recursive-edit))
5962 (message "Exit with Esc Esc")
5963 (recursive-edit)
5964 t)) ; Consider acted upon
5965 "edit, exit with Esc Esc"))
5966 t)
5967 (if found-bad (goto-char found-bad)
5968 (goto-char p)
5969 (message "No appropriate place found"))))
5970
5971(defun cperl-next-bad-style ()
5972 (let (p (not-found t) (point (point)) found)
5973 (while (and not-found
5974 (re-search-forward cperl-bad-style-regexp nil 'to-end))
5975 (setq p (point))
5976 (goto-char (match-beginning 0))
5977 (if (or
5978 (looking-at cperl-not-bad-style-regexp)
5979 ;; Check for a < -b and friends
5980 (and (eq (following-char) ?\-)
5981 (save-excursion
5982 (skip-chars-backward " \t\n")
5983 (memq (preceding-char) '(?\= ?\> ?\< ?\, ?\(, ?\[, ?\{))))
5984 ;; Now check for syntax type
5985 (save-match-data
5986 (setq found (point))
5987 (beginning-of-defun)
5988 (let ((pps (parse-partial-sexp (point) found)))
5989 (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))
5990 (goto-char (match-end 0))
5991 (goto-char (1- p))
5992 (setq not-found nil
5993 found-bad found)))
5994 (not not-found)))
5995
f1d851ae 5996\f
f83d2997 5997;;; Getting help
5c8b7eaf 5998(defvar cperl-have-help-regexp
f83d2997
KH
5999 ;;(concat "\\("
6000 (mapconcat
6001 'identity
6002 '("[$@%*&][0-9a-zA-Z_:]+\\([ \t]*[[{]\\)?" ; Usual variable
6003 "[$@]\\^[a-zA-Z]" ; Special variable
6004 "[$@][^ \n\t]" ; Special variable
6005 "-[a-zA-Z]" ; File test
6006 "\\\\[a-zA-Z0]" ; Special chars
6007 "^=[a-z][a-zA-Z0-9_]*" ; Pod sections
6008 "[-!&*+,-./<=>?\\\\^|~]+" ; Operator
6009 "[a-zA-Z_0-9:]+" ; symbol or number
6010 "x="
6011 "#!"
6012 )
6013 ;;"\\)\\|\\("
6014 "\\|"
6015 )
6016 ;;"\\)"
6017 ;;)
6018 "Matches places in the buffer we can find help for.")
6019
6020(defvar cperl-message-on-help-error t)
6021(defvar cperl-help-from-timer nil)
6022
6023(defun cperl-word-at-point-hard ()
6024 ;; Does not save-excursion
6025 ;; Get to the something meaningful
6026 (or (eobp) (eolp) (forward-char 1))
5c8b7eaf 6027 (re-search-backward "[-a-zA-Z0-9_:!&*+,-./<=>?\\\\^|~$%@]"
f83d2997
KH
6028 (save-excursion (beginning-of-line) (point))
6029 'to-beg)
6030 ;; (cond
6031 ;; ((or (eobp) (looking-at "[][ \t\n{}();,]")) ; Not at a symbol
6032 ;; (skip-chars-backward " \n\t\r({[]});,")
6033 ;; (or (bobp) (backward-char 1))))
6034 ;; Try to backtrace
6035 (cond
6036 ((looking-at "[a-zA-Z0-9_:]") ; symbol
6037 (skip-chars-backward "a-zA-Z0-9_:")
5c8b7eaf 6038 (cond
f83d2997
KH
6039 ((and (eq (preceding-char) ?^) ; $^I
6040 (eq (char-after (- (point) 2)) ?\$))
6041 (forward-char -2))
6042 ((memq (preceding-char) (append "*$@%&\\" nil)) ; *glob
6043 (forward-char -1))
6044 ((and (eq (preceding-char) ?\=)
6045 (eq (current-column) 1))
6046 (forward-char -1))) ; =head1
6047 (if (and (eq (preceding-char) ?\<)
6048 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <FH>
6049 (forward-char -1)))
6050 ((and (looking-at "=") (eq (preceding-char) ?x)) ; x=
6051 (forward-char -1))
6052 ((and (looking-at "\\^") (eq (preceding-char) ?\$)) ; $^I
6053 (forward-char -1))
6054 ((looking-at "[-!&*+,-./<=>?\\\\^|~]")
6055 (skip-chars-backward "-!&*+,-./<=>?\\\\^|~")
6056 (cond
6057 ((and (eq (preceding-char) ?\$)
6058 (not (eq (char-after (- (point) 2)) ?\$))) ; $-
6059 (forward-char -1))
6060 ((and (eq (following-char) ?\>)
6061 (string-match "[a-zA-Z0-9_]" (char-to-string (preceding-char)))
6062 (save-excursion
6063 (forward-sexp -1)
6064 (and (eq (preceding-char) ?\<)
6065 (looking-at "\\$?[a-zA-Z0-9_:]+>")))) ; <FH>
6066 (search-backward "<"))))
6067 ((and (eq (following-char) ?\$)
6068 (eq (preceding-char) ?\<)
6069 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <$fh>
6070 (forward-char -1)))
6071 (if (looking-at cperl-have-help-regexp)
6072 (buffer-substring (match-beginning 0) (match-end 0))))
6073
6074(defun cperl-get-help ()
6075 "Get one-line docs on the symbol at the point.
6076The data for these docs is a little bit obsolete and may be in fact longer
6077than a line. Your contribution to update/shorten it is appreciated."
6078 (interactive)
6079 (save-match-data ; May be called "inside" query-replace
6080 (save-excursion
6081 (let ((word (cperl-word-at-point-hard)))
6082 (if word
6083 (if (and cperl-help-from-timer ; Bail out if not in mainland
6084 (not (string-match "^#!\\|\\\\\\|^=" word)) ; Show help even in comments/strings.
6085 (or (memq (get-text-property (point) 'face)
6086 '(font-lock-comment-face font-lock-string-face))
6087 (memq (get-text-property (point) 'syntax-type)
6088 '(pod here-doc format))))
6089 nil
6090 (cperl-describe-perl-symbol word))
6091 (if cperl-message-on-help-error
5c8b7eaf 6092 (message "Nothing found for %s..."
f83d2997
KH
6093 (buffer-substring (point) (min (+ 5 (point)) (point-max))))))))))
6094
6095;;; Stolen from perl-descr.el by Johan Vromans:
6096
6097(defvar cperl-doc-buffer " *perl-doc*"
6098 "Where the documentation can be found.")
6099
6100(defun cperl-describe-perl-symbol (val)
6101 "Display the documentation of symbol at point, a Perl operator."
6102 (let ((enable-recursive-minibuffers t)
6103 args-file regexp)
6104 (cond
6105 ((string-match "^[&*][a-zA-Z_]" val)
6106 (setq val (concat (substring val 0 1) "NAME")))
6107 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*\\[" val)
6108 (setq val (concat "@" (substring val 1 (match-end 1)))))
6109 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*{" val)
6110 (setq val (concat "%" (substring val 1 (match-end 1)))))
6111 ((and (string= val "x") (string-match "^x=" val))
6112 (setq val "x="))
6113 ((string-match "^\\$[\C-a-\C-z]" val)
6114 (setq val (concat "$^" (char-to-string (+ ?A -1 (aref val 1))))))
6115 ((string-match "^CORE::" val)
6116 (setq val "CORE::"))
6117 ((string-match "^SUPER::" val)
6118 (setq val "SUPER::"))
6119 ((and (string= "<" val) (string-match "^<\\$?[a-zA-Z0-9_:]+>" val))
6120 (setq val "<NAME>")))
5c8b7eaf 6121 (setq regexp (concat "^"
f83d2997 6122 "\\([^a-zA-Z0-9_:]+[ \t]+\\)?"
5c8b7eaf 6123 (regexp-quote val)
f83d2997
KH
6124 "\\([ \t([/]\\|$\\)"))
6125
6126 ;; get the buffer with the documentation text
6127 (cperl-switch-to-doc-buffer)
6128
6129 ;; lookup in the doc
6130 (goto-char (point-min))
6131 (let ((case-fold-search nil))
5c8b7eaf 6132 (list
f83d2997
KH
6133 (if (re-search-forward regexp (point-max) t)
6134 (save-excursion
6135 (beginning-of-line 1)
6136 (let ((lnstart (point)))
6137 (end-of-line)
6138 (message "%s" (buffer-substring lnstart (point)))))
6139 (if cperl-message-on-help-error
6140 (message "No definition for %s" val)))))))
6141
6142(defvar cperl-short-docs "Ignore my value"
6143 ;; Perl4 version was written by Johan Vromans (jvromans@squirrel.nl)
6144 "# based on '@(#)@ perl-descr.el 1.9 - describe-perl-symbol' [Perl 5]
5c8b7eaf 6145! ... Logical negation.
f83d2997
KH
6146... != ... Numeric inequality.
6147... !~ ... Search pattern, substitution, or translation (negated).
6148$! In numeric context: errno. In a string context: error string.
6149$\" The separator which joins elements of arrays interpolated in strings.
6150$# The output format for printed numbers. Initial value is %.15g or close.
6151$$ Process number of this script. Changes in the fork()ed child process.
6152$% The current page number of the currently selected output channel.
6153
6154 The following variables are always local to the current block:
6155
6156$1 Match of the 1st set of parentheses in the last match (auto-local).
6157$2 Match of the 2nd set of parentheses in the last match (auto-local).
6158$3 Match of the 3rd set of parentheses in the last match (auto-local).
6159$4 Match of the 4th set of parentheses in the last match (auto-local).
6160$5 Match of the 5th set of parentheses in the last match (auto-local).
6161$6 Match of the 6th set of parentheses in the last match (auto-local).
6162$7 Match of the 7th set of parentheses in the last match (auto-local).
6163$8 Match of the 8th set of parentheses in the last match (auto-local).
6164$9 Match of the 9th set of parentheses in the last match (auto-local).
6165$& The string matched by the last pattern match (auto-local).
6166$' The string after what was matched by the last match (auto-local).
6167$` The string before what was matched by the last match (auto-local).
6168
6169$( The real gid of this process.
6170$) The effective gid of this process.
6171$* Deprecated: Set to 1 to do multiline matching within a string.
6172$+ The last bracket matched by the last search pattern.
6173$, The output field separator for the print operator.
6174$- The number of lines left on the page.
6175$. The current input line number of the last filehandle that was read.
6176$/ The input record separator, newline by default.
6177$0 Name of the file containing the perl script being executed. May be set.
6178$: String may be broken after these characters to fill ^-lines in a format.
6179$; Subscript separator for multi-dim array emulation. Default \"\\034\".
6180$< The real uid of this process.
6181$= The page length of the current output channel. Default is 60 lines.
6182$> The effective uid of this process.
6183$? The status returned by the last ``, pipe close or `system'.
6184$@ The perl error message from the last eval or do @var{EXPR} command.
6185$ARGV The name of the current file used with <> .
6186$[ Deprecated: The index of the first element/char in an array/string.
6187$\\ The output record separator for the print operator.
6188$] The perl version string as displayed with perl -v.
6189$^ The name of the current top-of-page format.
6190$^A The current value of the write() accumulator for format() lines.
6191$^D The value of the perl debug (-D) flags.
6192$^E Information about the last system error other than that provided by $!.
6193$^F The highest system file descriptor, ordinarily 2.
6194$^H The current set of syntax checks enabled by `use strict'.
6195$^I The value of the in-place edit extension (perl -i option).
6196$^L What formats output to perform a formfeed. Default is \f.
5bd52f0e 6197$^M A buffer for emergency memory allocation when running out of memory.
f83d2997
KH
6198$^O The operating system name under which this copy of Perl was built.
6199$^P Internal debugging flag.
6200$^T The time the script was started. Used by -A/-M/-C file tests.
6201$^W True if warnings are requested (perl -w flag).
6202$^X The name under which perl was invoked (argv[0] in C-speech).
6203$_ The default input and pattern-searching space.
5c8b7eaf 6204$| Auto-flush after write/print on current output channel? Default 0.
f83d2997
KH
6205$~ The name of the current report format.
6206... % ... Modulo division.
6207... %= ... Modulo division assignment.
6208%ENV Contains the current environment.
6209%INC List of files that have been require-d or do-ne.
6210%SIG Used to set signal handlers for various signals.
6211... & ... Bitwise and.
6212... && ... Logical and.
6213... &&= ... Logical and assignment.
6214... &= ... Bitwise and assignment.
6215... * ... Multiplication.
6216... ** ... Exponentiation.
6217*NAME Glob: all objects refered by NAME. *NAM1 = *NAM2 aliases NAM1 to NAM2.
6218&NAME(arg0, ...) Subroutine call. Arguments go to @_.
6219... + ... Addition. +EXPR Makes EXPR into scalar context.
6220++ Auto-increment (magical on strings). ++EXPR EXPR++
6221... += ... Addition assignment.
6222, Comma operator.
6223... - ... Subtraction.
6224-- Auto-decrement (NOT magical on strings). --EXPR EXPR--
6225... -= ... Subtraction assignment.
6226-A Access time in days since script started.
6227-B File is a non-text (binary) file.
6228-C Inode change time in days since script started.
6229-M Age in days since script started.
6230-O File is owned by real uid.
6231-R File is readable by real uid.
6232-S File is a socket .
6233-T File is a text file.
6234-W File is writable by real uid.
6235-X File is executable by real uid.
6236-b File is a block special file.
6237-c File is a character special file.
6238-d File is a directory.
6239-e File exists .
6240-f File is a plain file.
6241-g File has setgid bit set.
6242-k File has sticky bit set.
6243-l File is a symbolic link.
6244-o File is owned by effective uid.
6245-p File is a named pipe (FIFO).
6246-r File is readable by effective uid.
6247-s File has non-zero size.
6248-t Tests if filehandle (STDIN by default) is opened to a tty.
6249-u File has setuid bit set.
6250-w File is writable by effective uid.
6251-x File is executable by effective uid.
6252-z File has zero size.
6253. Concatenate strings.
6254.. Alternation, also range operator.
6255.= Concatenate assignment strings
6256... / ... Division. /PATTERN/ioxsmg Pattern match
6257... /= ... Division assignment.
6258/PATTERN/ioxsmg Pattern match.
6259... < ... Numeric less than. <pattern> Glob. See <NAME>, <> as well.
6260<NAME> Reads line from filehandle NAME (a bareword or dollar-bareword).
6261<pattern> Glob (Unless pattern is bareword/dollar-bareword - see <NAME>).
6262<> Reads line from union of files in @ARGV (= command line) and STDIN.
6263... << ... Bitwise shift left. << start of HERE-DOCUMENT.
6264... <= ... Numeric less than or equal to.
6265... <=> ... Numeric compare.
6266... = ... Assignment.
6267... == ... Numeric equality.
6268... =~ ... Search pattern, substitution, or translation
6269... > ... Numeric greater than.
6270... >= ... Numeric greater than or equal to.
6271... >> ... Bitwise shift right.
6272... >>= ... Bitwise shift right assignment.
6273... ? ... : ... Condition=if-then-else operator. ?PAT? One-time pattern match.
6274?PATTERN? One-time pattern match.
6275@ARGV Command line arguments (not including the command name - see $0).
6276@INC List of places to look for perl scripts during do/include/use.
6277@_ Parameter array for subroutines. Also used by split unless in array context.
6278\\ Creates reference to what follows, like \$var, or quotes non-\w in strings.
6279\\0 Octal char, e.g. \\033.
6280\\E Case modification terminator. See \\Q, \\L, and \\U.
6281\\L Lowercase until \\E . See also \l, lc.
6282\\U Upcase until \\E . See also \u, uc.
6283\\Q Quote metacharacters until \\E . See also quotemeta.
6284\\a Alarm character (octal 007).
6285\\b Backspace character (octal 010).
6286\\c Control character, e.g. \\c[ .
6287\\e Escape character (octal 033).
6288\\f Formfeed character (octal 014).
6289\\l Lowercase the next character. See also \\L and \\u, lcfirst.
6290\\n Newline character (octal 012 on most systems).
6291\\r Return character (octal 015 on most systems).
6292\\t Tab character (octal 011).
6293\\u Upcase the next character. See also \\U and \\l, ucfirst.
6294\\x Hex character, e.g. \\x1b.
6295... ^ ... Bitwise exclusive or.
6296__END__ Ends program source.
6297__DATA__ Ends program source.
6298__FILE__ Current (source) filename.
6299__LINE__ Current line in current source.
6300__PACKAGE__ Current package.
6301ARGV Default multi-file input filehandle. <ARGV> is a synonym for <>.
6302ARGVOUT Output filehandle with -i flag.
6303BEGIN { ... } Immediately executed (during compilation) piece of code.
6304END { ... } Pseudo-subroutine executed after the script finishes.
6c389151
SM
6305CHECK { ... } Pseudo-subroutine executed after the script is compiled.
6306INIT { ... } Pseudo-subroutine executed before the script starts running.
f83d2997
KH
6307DATA Input filehandle for what follows after __END__ or __DATA__.
6308accept(NEWSOCKET,GENERICSOCKET)
6309alarm(SECONDS)
6310atan2(X,Y)
6311bind(SOCKET,NAME)
6312binmode(FILEHANDLE)
6313caller[(LEVEL)]
6314chdir(EXPR)
6315chmod(LIST)
6316chop[(LIST|VAR)]
6317chown(LIST)
6318chroot(FILENAME)
6319close(FILEHANDLE)
6320closedir(DIRHANDLE)
6321... cmp ... String compare.
6322connect(SOCKET,NAME)
6323continue of { block } continue { block }. Is executed after `next' or at end.
6324cos(EXPR)
6325crypt(PLAINTEXT,SALT)
6326dbmclose(%HASH)
6327dbmopen(%HASH,DBNAME,MODE)
6328defined(EXPR)
6329delete($HASH{KEY})
6330die(LIST)
6331do { ... }|SUBR while|until EXPR executes at least once
6332do(EXPR|SUBR([LIST])) (with while|until executes at least once)
6333dump LABEL
6334each(%HASH)
6335endgrent
6336endhostent
6337endnetent
6338endprotoent
6339endpwent
6340endservent
6341eof[([FILEHANDLE])]
6342... eq ... String equality.
6343eval(EXPR) or eval { BLOCK }
6344exec(LIST)
6345exit(EXPR)
6346exp(EXPR)
6347fcntl(FILEHANDLE,FUNCTION,SCALAR)
6348fileno(FILEHANDLE)
6349flock(FILEHANDLE,OPERATION)
6350for (EXPR;EXPR;EXPR) { ... }
6351foreach [VAR] (@ARRAY) { ... }
6352fork
6353... ge ... String greater than or equal.
6354getc[(FILEHANDLE)]
6355getgrent
6356getgrgid(GID)
6357getgrnam(NAME)
6358gethostbyaddr(ADDR,ADDRTYPE)
6359gethostbyname(NAME)
6360gethostent
6361getlogin
6362getnetbyaddr(ADDR,ADDRTYPE)
6363getnetbyname(NAME)
6364getnetent
6365getpeername(SOCKET)
6366getpgrp(PID)
6367getppid
6368getpriority(WHICH,WHO)
6369getprotobyname(NAME)
6370getprotobynumber(NUMBER)
6371getprotoent
6372getpwent
6373getpwnam(NAME)
6374getpwuid(UID)
6375getservbyname(NAME,PROTO)
6376getservbyport(PORT,PROTO)
6377getservent
6378getsockname(SOCKET)
6379getsockopt(SOCKET,LEVEL,OPTNAME)
6380gmtime(EXPR)
6381goto LABEL
f83d2997
KH
6382... gt ... String greater than.
6383hex(EXPR)
6384if (EXPR) { ... } [ elsif (EXPR) { ... } ... ] [ else { ... } ] or EXPR if EXPR
6385index(STR,SUBSTR[,OFFSET])
6386int(EXPR)
6387ioctl(FILEHANDLE,FUNCTION,SCALAR)
6388join(EXPR,LIST)
6389keys(%HASH)
6390kill(LIST)
6391last [LABEL]
6392... le ... String less than or equal.
6393length(EXPR)
6394link(OLDFILE,NEWFILE)
6395listen(SOCKET,QUEUESIZE)
6396local(LIST)
6397localtime(EXPR)
6398log(EXPR)
6399lstat(EXPR|FILEHANDLE|VAR)
6400... lt ... String less than.
6401m/PATTERN/iogsmx
6402mkdir(FILENAME,MODE)
6403msgctl(ID,CMD,ARG)
6404msgget(KEY,FLAGS)
6405msgrcv(ID,VAR,SIZE,TYPE.FLAGS)
6406msgsnd(ID,MSG,FLAGS)
6407my VAR or my (VAR1,...) Introduces a lexical variable ($VAR, @ARR, or %HASH).
6c389151 6408our VAR or our (VAR1,...) Lexically enable a global variable ($V, @A, or %H).
f83d2997
KH
6409... ne ... String inequality.
6410next [LABEL]
6411oct(EXPR)
6412open(FILEHANDLE[,EXPR])
6413opendir(DIRHANDLE,EXPR)
6414ord(EXPR) ASCII value of the first char of the string.
6415pack(TEMPLATE,LIST)
6416package NAME Introduces package context.
6417pipe(READHANDLE,WRITEHANDLE) Create a pair of filehandles on ends of a pipe.
6418pop(ARRAY)
6419print [FILEHANDLE] [(LIST)]
6420printf [FILEHANDLE] (FORMAT,LIST)
6421push(ARRAY,LIST)
6422q/STRING/ Synonym for 'STRING'
6423qq/STRING/ Synonym for \"STRING\"
6424qx/STRING/ Synonym for `STRING`
6425rand[(EXPR)]
6426read(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
6427readdir(DIRHANDLE)
6428readlink(EXPR)
6429recv(SOCKET,SCALAR,LEN,FLAGS)
6430redo [LABEL]
6431rename(OLDNAME,NEWNAME)
6432require [FILENAME | PERL_VERSION]
6433reset[(EXPR)]
6434return(LIST)
6435reverse(LIST)
6436rewinddir(DIRHANDLE)
6437rindex(STR,SUBSTR[,OFFSET])
6438rmdir(FILENAME)
6439s/PATTERN/REPLACEMENT/gieoxsm
6440scalar(EXPR)
6441seek(FILEHANDLE,POSITION,WHENCE)
6442seekdir(DIRHANDLE,POS)
6443select(FILEHANDLE | RBITS,WBITS,EBITS,TIMEOUT)
6444semctl(ID,SEMNUM,CMD,ARG)
6445semget(KEY,NSEMS,SIZE,FLAGS)
6446semop(KEY,...)
6447send(SOCKET,MSG,FLAGS[,TO])
6448setgrent
6449sethostent(STAYOPEN)
6450setnetent(STAYOPEN)
6451setpgrp(PID,PGRP)
6452setpriority(WHICH,WHO,PRIORITY)
6453setprotoent(STAYOPEN)
6454setpwent
6455setservent(STAYOPEN)
6456setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)
6457shift[(ARRAY)]
6458shmctl(ID,CMD,ARG)
6459shmget(KEY,SIZE,FLAGS)
6460shmread(ID,VAR,POS,SIZE)
6461shmwrite(ID,STRING,POS,SIZE)
6462shutdown(SOCKET,HOW)
6463sin(EXPR)
6464sleep[(EXPR)]
6465socket(SOCKET,DOMAIN,TYPE,PROTOCOL)
6466socketpair(SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL)
6467sort [SUBROUTINE] (LIST)
6468splice(ARRAY,OFFSET[,LENGTH[,LIST]])
6469split[(/PATTERN/[,EXPR[,LIMIT]])]
6470sprintf(FORMAT,LIST)
6471sqrt(EXPR)
6472srand(EXPR)
6473stat(EXPR|FILEHANDLE|VAR)
6474study[(SCALAR)]
6475sub [NAME [(format)]] { BODY } sub NAME [(format)]; sub [(format)] {...}
6476substr(EXPR,OFFSET[,LEN])
6477symlink(OLDFILE,NEWFILE)
6478syscall(LIST)
6479sysread(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
6480system(LIST)
6481syswrite(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
6482tell[(FILEHANDLE)]
6483telldir(DIRHANDLE)
6484time
6485times
6486tr/SEARCHLIST/REPLACEMENTLIST/cds
6487truncate(FILE|EXPR,LENGTH)
6488umask[(EXPR)]
6489undef[(EXPR)]
6490unless (EXPR) { ... } [ else { ... } ] or EXPR unless EXPR
6491unlink(LIST)
6492unpack(TEMPLATE,EXPR)
6493unshift(ARRAY,LIST)
6494until (EXPR) { ... } EXPR until EXPR
6495utime(LIST)
6496values(%HASH)
6497vec(EXPR,OFFSET,BITS)
6498wait
6499waitpid(PID,FLAGS)
6500wantarray Returns true if the sub/eval is called in list context.
6501warn(LIST)
6502while (EXPR) { ... } EXPR while EXPR
6503write[(EXPR|FILEHANDLE)]
6504... x ... Repeat string or array.
6505x= ... Repetition assignment.
6506y/SEARCHLIST/REPLACEMENTLIST/
6507... | ... Bitwise or.
6508... || ... Logical or.
6509~ ... Unary bitwise complement.
db133cb6 6510#! OS interpreter indicator. If contains `perl', used for options, and -x.
f83d2997
KH
6511AUTOLOAD {...} Shorthand for `sub AUTOLOAD {...}'.
6512CORE:: Prefix to access builtin function if imported sub obscures it.
6513SUPER:: Prefix to lookup for a method in @ISA classes.
6514DESTROY Shorthand for `sub DESTROY {...}'.
6515... EQ ... Obsolete synonym of `eq'.
6516... GE ... Obsolete synonym of `ge'.
6517... GT ... Obsolete synonym of `gt'.
6518... LE ... Obsolete synonym of `le'.
6519... LT ... Obsolete synonym of `lt'.
6520... NE ... Obsolete synonym of `ne'.
6521abs [ EXPR ] absolute value
6522... and ... Low-precedence synonym for &&.
6523bless REFERENCE [, PACKAGE] Makes reference into an object of a package.
6524chomp [LIST] Strips $/ off LIST/$_. Returns count. Special if $/ eq ''!
6525chr Converts a number to char with the same ordinal.
6526else Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
6527elsif Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
6528exists $HASH{KEY} True if the key exists.
6529format [NAME] = Start of output format. Ended by a single dot (.) on a line.
6530formline PICTURE, LIST Backdoor into \"format\" processing.
6531glob EXPR Synonym of <EXPR>.
6532lc [ EXPR ] Returns lowercased EXPR.
6533lcfirst [ EXPR ] Returns EXPR with lower-cased first letter.
db133cb6 6534grep EXPR,LIST or grep {BLOCK} LIST Filters LIST via EXPR/BLOCK.
f83d2997
KH
6535map EXPR, LIST or map {BLOCK} LIST Applies EXPR/BLOCK to elts of LIST.
6536no PACKAGE [SYMBOL1, ...] Partial reverse for `use'. Runs `unimport' method.
6537not ... Low-precedence synonym for ! - negation.
6538... or ... Low-precedence synonym for ||.
6539pos STRING Set/Get end-position of the last match over this string, see \\G.
6540quotemeta [ EXPR ] Quote regexp metacharacters.
6541qw/WORD1 .../ Synonym of split('', 'WORD1 ...')
6542readline FH Synonym of <FH>.
6543readpipe CMD Synonym of `CMD`.
6544ref [ EXPR ] Type of EXPR when dereferenced.
6545sysopen FH, FILENAME, MODE [, PERM] (MODE is numeric, see Fcntl.)
6546tie VAR, PACKAGE, LIST Hide an object behind a simple Perl variable.
6547tied Returns internal object for a tied data.
6548uc [ EXPR ] Returns upcased EXPR.
6549ucfirst [ EXPR ] Returns EXPR with upcased first letter.
6550untie VAR Unlink an object from a simple Perl variable.
6551use PACKAGE [SYMBOL1, ...] Compile-time `require' with consequent `import'.
6552... xor ... Low-precedence synonym for exclusive or.
6553prototype \&SUB Returns prototype of the function given a reference.
6554=head1 Top-level heading.
6555=head2 Second-level heading.
6556=head3 Third-level heading (is there such?).
6557=over [ NUMBER ] Start list.
6558=item [ TITLE ] Start new item in the list.
6559=back End list.
6560=cut Switch from POD to Perl.
6561=pod Switch from Perl to POD.
6562")
6563
6564(defun cperl-switch-to-doc-buffer ()
6565 "Go to the perl documentation buffer and insert the documentation."
6566 (interactive)
6567 (let ((buf (get-buffer-create cperl-doc-buffer)))
6568 (if (interactive-p)
6569 (switch-to-buffer-other-window buf)
6570 (set-buffer buf))
6571 (if (= (buffer-size) 0)
6572 (progn
6573 (insert (documentation-property 'cperl-short-docs
6574 'variable-documentation))
6575 (setq buffer-read-only t)))))
6576
6c389151 6577(defun cperl-beautify-regexp-piece (b e embed level)
f83d2997
KH
6578 ;; b is before the starting delimiter, e before the ending
6579 ;; e should be a marker, may be changed, but remains "correct".
6c389151
SM
6580 ;; EMBED is nil iff we process the whole REx.
6581 ;; The REx is guarantied to have //x
6582 ;; LEVEL shows how many levels deep to go
6583 ;; position at enter and at leave is not defined
6584 (let (s c tmp (m (make-marker)) (m1 (make-marker)) c1 spaces inline code pos)
f83d2997
KH
6585 (if (not embed)
6586 (goto-char (1+ b))
6587 (goto-char b)
6c389151 6588 (cond ((looking-at "(\\?\\\\#") ; (?#) wrongly commented when //x-ing
f83d2997
KH
6589 (forward-char 2)
6590 (delete-char 1)
6591 (forward-char 1))
6592 ((looking-at "(\\?[^a-zA-Z]")
6593 (forward-char 3))
6594 ((looking-at "(\\?") ; (?i)
6595 (forward-char 2))
6596 (t
6597 (forward-char 1))))
6598 (setq c (if embed (current-indentation) (1- (current-column)))
6599 c1 (+ c (or cperl-regexp-indent-step cperl-indent-level)))
6600 (or (looking-at "[ \t]*[\n#]")
6601 (progn
6602 (insert "\n")))
6603 (goto-char e)
6604 (beginning-of-line)
6605 (if (re-search-forward "[^ \t]" e t)
6c389151 6606 (progn ; Something before the ending delimiter
f83d2997 6607 (goto-char e)
6c389151 6608 (delete-horizontal-space)
f83d2997
KH
6609 (insert "\n")
6610 (indent-to-column c)
6611 (set-marker e (point))))
6612 (goto-char b)
6613 (end-of-line 2)
6614 (while (< (point) (marker-position e))
6615 (beginning-of-line)
6616 (setq s (point)
6617 inline t)
6618 (skip-chars-forward " \t")
6619 (delete-region s (point))
6620 (indent-to-column c1)
6621 (while (and
6622 inline
5c8b7eaf 6623 (looking-at
f83d2997
KH
6624 (concat "\\([a-zA-Z0-9]+[^*+{?]\\)" ; 1 word
6625 "\\|" ; Embedded variable
6626 "\\$\\([a-zA-Z0-9_]+\\([[{]\\)?\\|[^\n \t)|]\\)" ; 2 3
6627 "\\|" ; $ ^
6628 "[$^]"
6629 "\\|" ; simple-code simple-code*?
6630 "\\(\\\\.\\|[^][()#|*+?\n]\\)\\([*+{?]\\??\\)?" ; 4 5
6631 "\\|" ; Class
6632 "\\(\\[\\)" ; 6
6633 "\\|" ; Grouping
6634 "\\((\\(\\?\\)?\\)" ; 7 8
6635 "\\|" ; |
6636 "\\(|\\)" ; 9
6637 )))
6638 (goto-char (match-end 0))
6639 (setq spaces t)
6640 (cond ((match-beginning 1) ; Alphanum word + junk
6641 (forward-char -1))
6642 ((or (match-beginning 3) ; $ab[12]
6643 (and (match-beginning 5) ; X* X+ X{2,3}
6644 (eq (preceding-char) ?\{)))
6645 (forward-char -1)
6646 (forward-sexp 1))
6647 ((match-beginning 6) ; []
6648 (setq tmp (point))
6649 (if (looking-at "\\^?\\]")
6650 (goto-char (match-end 0)))
6c389151
SM
6651 ;; XXXX POSIX classes?!
6652 (while (and (not pos)
6653 (re-search-forward "\\[:\\|\\]" e t))
6654 (if (eq (preceding-char) ?:)
6655 (or (re-search-forward ":\\]" e t)
6656 (error "[:POSIX:]-group in []-group not terminated"))
6657 (setq pos t)))
6658 (or (eq (preceding-char) ?\])
6659 (error "[]-group not terminated"))
6660 (if (eq (following-char) ?\{)
f83d2997 6661 (progn
6c389151
SM
6662 (forward-sexp 1)
6663 (and (eq (following-char) ??)
6664 (forward-char 1)))
6665 (re-search-forward "\\=\\([*+?]\\??\\)" e t)))
f83d2997
KH
6666 ((match-beginning 7) ; ()
6667 (goto-char (match-beginning 0))
6c389151
SM
6668 (setq pos (current-column))
6669 (or (eq pos c1)
f83d2997 6670 (progn
6c389151 6671 (delete-horizontal-space)
f83d2997
KH
6672 (insert "\n")
6673 (indent-to-column c1)))
6674 (setq tmp (point))
6675 (forward-sexp 1)
6676 ;; (or (forward-sexp 1)
6677 ;; (progn
6678 ;; (goto-char tmp)
6679 ;; (error "()-group not terminated")))
6680 (set-marker m (1- (point)))
6681 (set-marker m1 (point))
6c389151
SM
6682 (if (= level 1)
6683 (if (progn ; indent rigidly if multiline
6684 ;; In fact does not make a lot of sense, since
6685 ;; the starting position can be already lost due
6686 ;; to insertion of "\n" and " "
6687 (goto-char tmp)
6688 (search-forward "\n" m1 t))
6689 (indent-rigidly (point) m1 (- c1 pos)))
6690 (setq level (1- level))
6691 (cond
6692 ((not (match-beginning 8))
6693 (cperl-beautify-regexp-piece tmp m t level))
6694 ((eq (char-after (+ 2 tmp)) ?\{) ; Code
6695 t)
6696 ((eq (char-after (+ 2 tmp)) ?\() ; Conditional
6697 (goto-char (+ 2 tmp))
6698 (forward-sexp 1)
6699 (cperl-beautify-regexp-piece (point) m t level))
6700 ((eq (char-after (+ 2 tmp)) ?<) ; Lookbehind
6701 (goto-char (+ 3 tmp))
6702 (cperl-beautify-regexp-piece (point) m t level))
6703 (t
6704 (cperl-beautify-regexp-piece tmp m t level))))
f83d2997
KH
6705 (goto-char m1)
6706 (cond ((looking-at "[*+?]\\??")
6707 (goto-char (match-end 0)))
6708 ((eq (following-char) ?\{)
6709 (forward-sexp 1)
6710 (if (eq (following-char) ?\?)
6711 (forward-char))))
6712 (skip-chars-forward " \t")
6713 (setq spaces nil)
6714 (if (looking-at "[#\n]")
6715 (progn
6716 (or (eolp) (indent-for-comment))
6717 (beginning-of-line 2))
6c389151 6718 (delete-horizontal-space)
f83d2997
KH
6719 (insert "\n"))
6720 (end-of-line)
6721 (setq inline nil))
6722 ((match-beginning 9) ; |
6723 (forward-char -1)
6724 (setq tmp (point))
6725 (beginning-of-line)
6726 (if (re-search-forward "[^ \t]" tmp t)
6727 (progn
6728 (goto-char tmp)
6c389151 6729 (delete-horizontal-space)
f83d2997
KH
6730 (insert "\n"))
6731 ;; first at line
6732 (delete-region (point) tmp))
6733 (indent-to-column c)
6734 (forward-char 1)
6735 (skip-chars-forward " \t")
6736 (setq spaces nil)
6737 (if (looking-at "[#\n]")
6738 (beginning-of-line 2)
6c389151 6739 (delete-horizontal-space)
f83d2997
KH
6740 (insert "\n"))
6741 (end-of-line)
6742 (setq inline nil)))
6743 (or (looking-at "[ \t\n]")
6744 (not spaces)
6745 (insert " "))
6746 (skip-chars-forward " \t"))
6747 (or (looking-at "[#\n]")
f94a632a 6748 (error "Unknown code `%s' in a regexp"
6c389151 6749 (buffer-substring (point) (1+ (point)))))
f83d2997
KH
6750 (and inline (end-of-line 2)))
6751 ;; Special-case the last line of group
6752 (if (and (>= (point) (marker-position e))
6753 (/= (current-indentation) c))
6754 (progn
6755 (beginning-of-line)
6756 (setq s (point))
6757 (skip-chars-forward " \t")
6758 (delete-region s (point))
6759 (indent-to-column c)))
6760 ))
6761
6762(defun cperl-make-regexp-x ()
db133cb6 6763 ;; Returns position of the start
6c389151 6764 ;; XXX this is called too often! Need to cache the result!
f83d2997
KH
6765 (save-excursion
6766 (or cperl-use-syntax-table-text-property
5bd52f0e 6767 (error "I need to have a regexp marked!"))
f83d2997 6768 ;; Find the start
db133cb6
RS
6769 (if (looking-at "\\s|")
6770 nil ; good already
5bd52f0e 6771 (if (looking-at "\\([smy]\\|qr\\)\\s|")
db133cb6
RS
6772 (forward-char 1)
6773 (re-search-backward "\\s|"))) ; Assume it is scanned already.
f83d2997
KH
6774 ;;(forward-char 1)
6775 (let ((b (point)) (e (make-marker)) have-x delim (c (current-column))
6776 (sub-p (eq (preceding-char) ?s)) s)
6777 (forward-sexp 1)
6778 (set-marker e (1- (point)))
6779 (setq delim (preceding-char))
6780 (if (and sub-p (eq delim (char-after (- (point) 2))))
6781 (error "Possible s/blah// - do not know how to deal with"))
6782 (if sub-p (forward-sexp 1))
5c8b7eaf 6783 (if (looking-at "\\sw*x")
f83d2997
KH
6784 (setq have-x t)
6785 (insert "x"))
6786 ;; Protect fragile " ", "#"
6787 (if have-x nil
6788 (goto-char (1+ b))
6789 (while (re-search-forward "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*[ \t\n#]" e t) ; Need to include (?#) too?
6790 (forward-char -1)
6791 (insert "\\")
6792 (forward-char 1)))
6793 b)))
6794
6c389151 6795(defun cperl-beautify-regexp (&optional deep)
f94a632a 6796 "Do it. (Experimental, may change semantics, recheck the result.)
f83d2997 6797We suppose that the regexp is scanned already."
6c389151
SM
6798 (interactive "P")
6799 (if deep
6800 (prefix-numeric-value deep)
6801 (setq deep -1))
6802 (save-excursion
6803 (goto-char (cperl-make-regexp-x))
6804 (let ((b (point)) (e (make-marker)))
6805 (forward-sexp 1)
6806 (set-marker e (1- (point)))
6807 (cperl-beautify-regexp-piece b e nil deep))))
f83d2997 6808
db133cb6
RS
6809(defun cperl-regext-to-level-start ()
6810 "Goto start of an enclosing group in regexp.
f83d2997
KH
6811We suppose that the regexp is scanned already."
6812 (interactive)
db133cb6 6813 (let ((limit (cperl-make-regexp-x)) done)
f83d2997
KH
6814 (while (not done)
6815 (or (eq (following-char) ?\()
db133cb6 6816 (search-backward "(" (1+ limit) t)
f83d2997
KH
6817 (error "Cannot find `(' which starts a group"))
6818 (setq done
6819 (save-excursion
6820 (skip-chars-backward "\\")
6821 (looking-at "\\(\\\\\\\\\\)*(")))
db133cb6
RS
6822 (or done (forward-char -1)))))
6823
6824(defun cperl-contract-level ()
5bd52f0e 6825 "Find an enclosing group in regexp and contract it.
db133cb6
RS
6826\(Experimental, may change semantics, recheck the result.)
6827We suppose that the regexp is scanned already."
6828 (interactive)
6c389151
SM
6829 ;; (save-excursion ; Can't, breaks `cperl-contract-levels'
6830 (cperl-regext-to-level-start)
6831 (let ((b (point)) (e (make-marker)) s c)
6832 (forward-sexp 1)
6833 (set-marker e (1- (point)))
6834 (goto-char b)
6835 (while (re-search-forward "\\(#\\)\\|\n" e 'to-end)
6836 (cond
6837 ((match-beginning 1) ; #-comment
6838 (or c (setq c (current-indentation)))
5efe6a56
SM
6839 (beginning-of-line 2) ; Skip
6840 (setq s (point))
6841 (skip-chars-forward " \t")
6842 (delete-region s (point))
6843 (indent-to-column c))
6844 (t
6845 (delete-char -1)
6846 (just-one-space))))))
db133cb6
RS
6847
6848(defun cperl-contract-levels ()
5bd52f0e 6849 "Find an enclosing group in regexp and contract all the kids.
db133cb6
RS
6850\(Experimental, may change semantics, recheck the result.)
6851We suppose that the regexp is scanned already."
6852 (interactive)
6c389151
SM
6853 (save-excursion
6854 (condition-case nil
6855 (cperl-regext-to-level-start)
6856 (error ; We are outside outermost group
5efe6a56
SM
6857 (goto-char (cperl-make-regexp-x))))
6858 (let ((b (point)) (e (make-marker)) s c)
6859 (forward-sexp 1)
6860 (set-marker e (1- (point)))
6861 (goto-char (1+ b))
6862 (while (re-search-forward "\\(\\\\\\\\\\)\\|(" e t)
6863 (cond
6c389151
SM
6864 ((match-beginning 1) ; Skip
6865 nil)
6866 (t ; Group
6867 (cperl-contract-level)))))))
f83d2997 6868
6c389151 6869(defun cperl-beautify-level (&optional deep)
f83d2997
KH
6870 "Find an enclosing group in regexp and beautify it.
6871\(Experimental, may change semantics, recheck the result.)
6872We suppose that the regexp is scanned already."
6c389151
SM
6873 (interactive "P")
6874 (if deep
6875 (prefix-numeric-value deep)
6876 (setq deep -1))
6877 (save-excursion
6878 (cperl-regext-to-level-start)
6879 (let ((b (point)) (e (make-marker)))
6880 (forward-sexp 1)
6881 (set-marker e (1- (point)))
6882 (cperl-beautify-regexp-piece b e nil deep))))
db133cb6
RS
6883
6884(defun cperl-invert-if-unless ()
6c389151 6885 "Change `if (A) {B}' into `B if A;' etc if possible."
db133cb6
RS
6886 (interactive)
6887 (or (looking-at "\\<")
6888 (forward-sexp -1))
6c389151 6889 (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>")
db133cb6
RS
6890 (let ((pos1 (point))
6891 pos2 pos3 pos4 pos5 s1 s2 state p pos45
6892 (s0 (buffer-substring (match-beginning 0) (match-end 0))))
6893 (forward-sexp 2)
6894 (setq pos3 (point))
6895 (forward-sexp -1)
6896 (setq pos2 (point))
6897 (if (eq (following-char) ?\( )
6898 (progn
6899 (goto-char pos3)
6900 (forward-sexp 1)
6901 (setq pos5 (point))
6902 (forward-sexp -1)
6903 (setq pos4 (point))
6904 ;; XXXX In fact may be `A if (B); {C}' ...
6905 (if (and (eq (following-char) ?\{ )
6906 (progn
6907 (cperl-backward-to-noncomment pos3)
6908 (eq (preceding-char) ?\) )))
6909 (if (condition-case nil
6910 (progn
6911 (goto-char pos5)
6912 (forward-sexp 1)
6913 (forward-sexp -1)
6914 (looking-at "\\<els\\(e\\|if\\)\\>"))
6915 (error nil))
6916 (error
6917 "`%s' (EXPR) {BLOCK} with `else'/`elsif'" s0)
6918 (goto-char (1- pos5))
6919 (cperl-backward-to-noncomment pos4)
6920 (if (eq (preceding-char) ?\;)
6921 (forward-char -1))
6922 (setq pos45 (point))
6923 (goto-char pos4)
6924 (while (re-search-forward "\\<\\(for\\|foreach\\|if\\|unless\\|while\\|until\\)\\>\\|;" pos45 t)
6925 (setq p (match-beginning 0)
6926 s1 (buffer-substring p (match-end 0))
6927 state (parse-partial-sexp pos4 p))
5c8b7eaf 6928 (or (nth 3 state)
db133cb6
RS
6929 (nth 4 state)
6930 (nth 5 state)
6931 (error "`%s' inside `%s' BLOCK" s1 s0))
6932 (goto-char (match-end 0)))
6933 ;; Finally got it
6934 (goto-char (1+ pos4))
6935 (skip-chars-forward " \t\n")
6936 (setq s2 (buffer-substring (point) pos45))
6937 (goto-char pos45)
6938 (or (looking-at ";?[ \t\n]*}")
6939 (progn
6940 (skip-chars-forward "; \t\n")
6941 (setq s2 (concat s2 "\n" (buffer-substring (point) (1- pos5))))))
6942 (and (equal s2 "")
6943 (setq s2 "1"))
6944 (goto-char (1- pos3))
6945 (cperl-backward-to-noncomment pos2)
6946 (or (looking-at "[ \t\n]*)")
6947 (goto-char (1- pos3)))
6948 (setq p (point))
6949 (goto-char (1+ pos2))
6950 (skip-chars-forward " \t\n")
6951 (setq s1 (buffer-substring (point) p))
6952 (delete-region pos4 pos5)
6953 (delete-region pos2 pos3)
6954 (goto-char pos1)
6955 (insert s2 " ")
6956 (just-one-space)
6957 (forward-word 1)
6958 (setq pos1 (point))
6959 (insert " " s1 ";")
6c389151 6960 (delete-horizontal-space)
db133cb6
RS
6961 (forward-char -1)
6962 (delete-horizontal-space)
6963 (goto-char pos1)
6964 (just-one-space)
6965 (cperl-indent-line))
6966 (error "`%s' (EXPR) not with an {BLOCK}" s0)))
6967 (error "`%s' not with an (EXPR)" s0)))
f94a632a 6968 (error "Not at `if', `unless', `while', `until', `for' or `foreach'")))
db133cb6 6969
5bd52f0e 6970;;; By Anthony Foiani <afoiani@uswest.com>
b7ec9e59
RS
6971;;; Getting help on modules in C-h f ?
6972;;; This is a modified version of `man'.
6973;;; Need to teach it how to lookup functions
6974(defun cperl-perldoc (word)
6975 "Run `perldoc' on WORD."
6976 (interactive
6977 (list (let* ((default-entry (cperl-word-at-point))
6978 (input (read-string
6979 (format "perldoc entry%s: "
6980 (if (string= default-entry "")
6981 ""
6982 (format " (default %s)" default-entry))))))
6983 (if (string= input "")
6984 (if (string= default-entry "")
6985 (error "No perldoc args given")
6986 default-entry)
6987 input))))
a8e1e57f 6988 (require 'man)
5c8b7eaf 6989 (let* ((is-func (and
b7ec9e59
RS
6990 (string-match "^[a-z]+$" word)
6991 (string-match (concat "^" word "\\>")
6992 (documentation-property
6993 'cperl-short-docs
6994 'variable-documentation))))
6995 (manual-program (if is-func "perldoc -f" "perldoc")))
b7ec9e59
RS
6996 (Man-getpage-in-background word)))
6997
6998(defun cperl-perldoc-at-point ()
6999 "Run a `perldoc' on the word around point."
7000 (interactive)
7001 (cperl-perldoc (cperl-word-at-point)))
7002
7003(defcustom pod2man-program "pod2man"
7004 "*File name for `pod2man'."
7005 :type 'file
7006 :group 'cperl)
7007
5bd52f0e 7008;;; By Nick Roberts <Nick.Roberts@src.bae.co.uk> (with changes)
b7ec9e59
RS
7009(defun cperl-pod-to-manpage ()
7010 "Create a virtual manpage in Emacs from the Perl Online Documentation."
7011 (interactive)
7012 (require 'man)
7013 (let* ((pod2man-args (concat buffer-file-name " | nroff -man "))
7014 (bufname (concat "Man " buffer-file-name))
7015 (buffer (generate-new-buffer bufname)))
7016 (save-excursion
7017 (set-buffer buffer)
7018 (let ((process-environment (copy-sequence process-environment)))
7019 ;; Prevent any attempt to use display terminal fanciness.
7020 (setenv "TERM" "dumb")
7021 (set-process-sentinel
7022 (start-process pod2man-program buffer "sh" "-c"
7023 (format (cperl-pod2man-build-command) pod2man-args))
7024 'Man-bgproc-sentinel)))))
7025
7026(defun cperl-pod2man-build-command ()
7027 "Builds the entire background manpage and cleaning command."
7028 (let ((command (concat pod2man-program " %s 2>/dev/null"))
7029 (flist Man-filter-list))
7030 (while (and flist (car flist))
7031 (let ((pcom (car (car flist)))
7032 (pargs (cdr (car flist))))
7033 (setq command
7034 (concat command " | " pcom " "
7035 (mapconcat '(lambda (phrase)
7036 (if (not (stringp phrase))
7037 (error "Malformed Man-filter-list"))
7038 phrase)
7039 pargs " ")))
7040 (setq flist (cdr flist))))
7041 command))
db133cb6
RS
7042
7043(defun cperl-lazy-install ()) ; Avoid a warning
f83d2997
KH
7044
7045(if (fboundp 'run-with-idle-timer)
7046 (progn
7047 (defvar cperl-help-shown nil
7048 "Non-nil means that the help was already shown now.")
7049
7050 (defvar cperl-lazy-installed nil
7051 "Non-nil means that the lazy-help handlers are installed now.")
7052
7053 (defun cperl-lazy-install ()
7054 (interactive)
7055 (make-variable-buffer-local 'cperl-help-shown)
7056 (if (and (cperl-val 'cperl-lazy-help-time)
7057 (not cperl-lazy-installed))
7058 (progn
7059 (add-hook 'post-command-hook 'cperl-lazy-hook)
5c8b7eaf
SS
7060 (run-with-idle-timer
7061 (cperl-val 'cperl-lazy-help-time 1000000 5)
7062 t
f83d2997
KH
7063 'cperl-get-help-defer)
7064 (setq cperl-lazy-installed t))))
7065
7066 (defun cperl-lazy-unstall ()
7067 (interactive)
7068 (remove-hook 'post-command-hook 'cperl-lazy-hook)
7069 (cancel-function-timers 'cperl-get-help-defer)
7070 (setq cperl-lazy-installed nil))
7071
7072 (defun cperl-lazy-hook ()
7073 (setq cperl-help-shown nil))
7074
7075 (defun cperl-get-help-defer ()
996e2616 7076 (when (memq major-mode '(perl-mode cperl-mode))
f83d2997
KH
7077 (let ((cperl-message-on-help-error nil) (cperl-help-from-timer t))
7078 (cperl-get-help)
7079 (setq cperl-help-shown t))))
7080 (cperl-lazy-install)))
7081
db133cb6
RS
7082
7083;;; Plug for wrong font-lock:
7084
7085(defun cperl-font-lock-unfontify-region-function (beg end)
7086 (let* ((modified (buffer-modified-p)) (buffer-undo-list t)
7087 (inhibit-read-only t) (inhibit-point-motion-hooks t)
7088 before-change-functions after-change-functions
7089 deactivate-mark buffer-file-name buffer-file-truename)
7090 (remove-text-properties beg end '(face nil))
7091 (when (and (not modified) (buffer-modified-p))
7092 (set-buffer-modified-p nil))))
7093
7094(defvar cperl-d-l nil)
7095(defun cperl-fontify-syntaxically (end)
5bd52f0e 7096 ;; Some vars for debugging only
6c389151
SM
7097 ;; (message "Syntaxifying...")
7098 (let (start (dbg (point)) (iend end)
5bd52f0e
RS
7099 (istate (car cperl-syntax-state)))
7100 (and cperl-syntaxify-unwind
7101 (setq end (cperl-unwind-to-safe t end)))
7102 (setq start (point))
db133cb6
RS
7103 (or cperl-syntax-done-to
7104 (setq cperl-syntax-done-to (point-min)))
7105 (if (or (not (boundp 'font-lock-hot-pass))
5bd52f0e
RS
7106 (eval 'font-lock-hot-pass)
7107 t) ; Not debugged otherwise
db133cb6
RS
7108 ;; Need to forget what is after `start'
7109 (setq start (min cperl-syntax-done-to start))
7110 ;; Fontification without a change
7111 (setq start (max cperl-syntax-done-to start)))
7112 (and (> end start)
7113 (setq cperl-syntax-done-to start) ; In case what follows fails
7114 (cperl-find-pods-heres start end t nil t))
5bd52f0e 7115 (if (eq cperl-syntaxify-by-font-lock 'message)
5c8b7eaf
SS
7116 (message "Syntaxified %s..%s from %s to %s(%s), state %s-->%s"
7117 dbg iend
7118 start end cperl-syntax-done-to
7119 istate (car cperl-syntax-state))) ; For debugging
db133cb6
RS
7120 nil)) ; Do not iterate
7121
5bd52f0e
RS
7122(defun cperl-fontify-update (end)
7123 (let ((pos (point)) prop posend)
7124 (while (< pos end)
7125 (setq prop (get-text-property pos 'cperl-postpone))
7126 (setq posend (next-single-property-change pos 'cperl-postpone nil end))
7127 (and prop (put-text-property pos posend (car prop) (cdr prop)))
7128 (setq pos posend)))
7129 nil) ; Do not iterate
7130
7131(defun cperl-update-syntaxification (from to)
7132 (if (and cperl-use-syntax-table-text-property
7133 cperl-syntaxify-by-font-lock
7134 (or (null cperl-syntax-done-to)
7135 (< cperl-syntax-done-to to)))
7136 (progn
7137 (save-excursion
7138 (goto-char from)
7139 (cperl-fontify-syntaxically to)))))
7140
5c8b7eaf 7141(defvar cperl-version
6c389151 7142 (let ((v "Revision: 4.32"))
5bd52f0e
RS
7143 (string-match ":\\s *\\([0-9.]+\\)" v)
7144 (substring v (match-beginning 1) (match-end 1)))
7145 "Version of IZ-supported CPerl package this file is based on.")
7146
f83d2997
KH
7147(provide 'cperl-mode)
7148
7149;;; cperl-mode.el ends here