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