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