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