This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[Patch Encode.xs] calculation of need overflows
[perl5.git] / emacs / cperl-mode.el
CommitLineData
6c72d195
IZ
1;;; cperl-mode.el --- Perl code editing commands for Emacs
2
3;;;; The following message is relative to GNU version of the module:
4
7bcea553 5;; Copyright (C) 1985, 86, 87, 1991--2000
6c72d195
IZ
6;; Free Software Foundation, Inc.
7
8;; Author: Ilya Zakharevich and Bob Olson
9;; Maintainer: Ilya Zakharevich <ilya@math.ohio-state.edu>
10;; Keywords: languages, Perl
11
12;; This file is part of GNU Emacs.
13
14;;; This code started from the following message of long time ago
15;;; (IZ), but Bob does not maintain this mode any more:
4633a7c4
LW
16
17;;; From: olson@mcs.anl.gov (Bob Olson)
18;;; Newsgroups: comp.lang.perl
19;;; Subject: cperl-mode: Another perl mode for Gnuemacs
20;;; Date: 14 Aug 91 15:20:01 GMT
21
6c72d195 22;; Copyright (C) Ilya Zakharevich and Bob Olson
4633a7c4 23
6c72d195 24;; This file may be distributed
499d5216 25;; either under the same terms as GNU Emacs, or under the same terms
55497cff 26;; as Perl. You should have received a copy of Perl Artistic license
499d5216 27;; along with the Perl distribution.
4633a7c4
LW
28
29;; GNU Emacs is free software; you can redistribute it and/or modify
30;; it under the terms of the GNU General Public License as published by
31;; the Free Software Foundation; either version 2, or (at your option)
32;; any later version.
33
34;; GNU Emacs is distributed in the hope that it will be useful,
35;; but WITHOUT ANY WARRANTY; without even the implied warranty of
36;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37;; GNU General Public License for more details.
38
39;; You should have received a copy of the GNU General Public License
55497cff 40;; along with GNU Emacs; see the file COPYING. If not, write to the
41;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
42;; Boston, MA 02111-1307, USA.
43
4633a7c4
LW
44;;; Corrections made by Ilya Zakharevich ilya@math.mps.ohio-state.edu
45;;; XEmacs changes by Peter Arius arius@informatik.uni-erlangen.de
46
6c72d195 47;;; Commentary:
4633a7c4 48
7bcea553 49;; $Id: cperl-mode.el,v 4.32 2000/05/31 05:13:15 ilya Exp ilya $
6c72d195 50
7bcea553
IZ
51;;; If your Emacs does not default to `cperl-mode' on Perl files:
52;;; To use this mode put the following into
6c72d195 53;;; your .emacs file:
4633a7c4
LW
54
55;; (autoload 'perl-mode "cperl-mode" "alternate mode for editing Perl programs" t)
56
57;;; You can either fine-tune the bells and whistles of this mode or
58;;; bulk enable them by putting
59
60;; (setq cperl-hairy t)
61
6c72d195 62;;; in your .emacs file. (Emacs rulers do not consider it politically
4633a7c4
LW
63;;; correct to make whistles enabled by default.)
64
6c72d195 65;;; DO NOT FORGET to read micro-docs (available from `Perl' menu) <<<<<<
5f05dabc 66;;; or as help on variables `cperl-tips', `cperl-problems', <<<<<<
6c72d195 67;;; `cperl-non-problems', `cperl-praise', `cperl-speed'. <<<<<<
5f05dabc 68
6c72d195 69;;; Additional useful commands to put into your .emacs file (before
4584684c 70;;; RMS Emacs 20.3):
4633a7c4
LW
71
72;; (setq auto-mode-alist
05bbd9c3 73;; (append '(("\\.\\([pP][Llm]\\|al\\)$" . perl-mode)) auto-mode-alist ))
4633a7c4
LW
74;; (setq interpreter-mode-alist (append interpreter-mode-alist
75;; '(("miniperl" . perl-mode))))
76
ebcd4dbc 77;;; The mode information (on C-h m) provides some customization help.
4633a7c4 78;;; If you use font-lock feature of this mode, it is advisable to use
6c72d195 79;;; either lazy-lock-mode or fast-lock-mode. I prefer lazy-lock.
4633a7c4
LW
80
81;;; Faces used now: three faces for first-class and second-class keywords
82;;; and control flow words, one for each: comments, string, labels,
83;;; functions definitions and packages, arrays, hashes, and variable
6c72d195
IZ
84;;; definitions. If you do not see all these faces, your font-lock does
85;;; not define them, so you need to define them manually. Maybe you have
86;;; an obsolete font-lock from 19.28 or earlier. Upgrade.
4633a7c4 87
55497cff 88;;; If you have a grayscale monitor, and do not have the variable
4633a7c4
LW
89;;; font-lock-display-type bound to 'grayscale, insert
90
91;;; (setq font-lock-display-type 'grayscale)
92
6c72d195 93;;; into your .emacs file (this is relevant before RMS Emacs 20).
4633a7c4 94
6c72d195 95;;;; This mode supports font-lock, imenu and mode-compile. In the
4633a7c4 96;;;; hairy version font-lock is on, but you should activate imenu
6c72d195 97;;;; yourself (note that mode-compile is not standard yet). Well, you
4633a7c4
LW
98;;;; can use imenu from keyboard anyway (M-x imenu), but it is better
99;;;; to bind it like that:
100
101;; (define-key global-map [M-S-down-mouse-3] 'imenu)
102
103;;; In fact the version of font-lock that this version supports can be
104;;; much newer than the version you actually have. This means that a
105;;; lot of faces can be set up, but are not visible on your screen
106;;; since the coloring rules for this faces are not defined.
107
4633a7c4
LW
108;;; Updates: ========================================
109
110;;; Made less hairy by default: parentheses not electric,
111;;; linefeed not magic. Bug with abbrev-mode corrected.
112
113;;;; After 1.4:
114;;; Better indentation:
115;;; subs inside braces should work now,
116;;; Toplevel braces obey customization.
117;;; indent-for-comment knows about bad cases, cperl-indent-for-comment
118;;; moves cursor to a correct place.
119;;; cperl-indent-exp written from the scratch! Slow... (quadratic!) :-(
120;;; (50 secs on DB::DB (sub of 430 lines), 486/66)
121;;; Minor documentation fixes.
122;;; Imenu understands packages as prefixes (including nested).
123;;; Hairy options can be switched off one-by-one by setting to null.
124;;; Names of functions and variables changed to conform to `cperl-' style.
125
126;;;; After 1.5:
127;;; Some bugs with indentation of labels (and embedded subs) corrected.
128;;; `cperl-indent-region' done (slow :-()).
129;;; `cperl-fill-paragraph' done.
130;;; Better package support for `imenu'.
131;;; Progress indicator for indentation (with `imenu' loaded).
132;;; `Cperl-set' was busted, now setting the individual hairy option
133;;; should be better.
134
135;;;; After 1.6:
136;;; `cperl-set-style' done.
137;;; `cperl-check-syntax' done.
138;;; Menu done.
139;;; New config variables `cperl-close-paren-offset' and `cperl-comment-column'.
140;;; Bugs with `cperl-auto-newline' corrected.
141;;; `cperl-electric-lbrace' can work with `cperl-auto-newline' in situation
142;;; like $hash{.
143
144;;;; 1.7 XEmacs (arius@informatik.uni-erlangen.de):
145;;; - use `next-command-event', if `next-command-events' does not exist
146;;; - use `find-face' as def. of `is-face'
147;;; - corrected def. of `x-color-defined-p'
148;;; - added const defs for font-lock-comment-face,
149;;; font-lock-keyword-face and font-lock-function-name-face
150;;; - added def. of font-lock-variable-name-face
151;;; - added (require 'easymenu) inside an `eval-when-compile'
152;;; - replaced 4-argument `substitute-key-definition' with ordinary
153;;; `define-key's
154;;; - replaced `mark-active' in menu definition by `cperl-use-region-p'.
155;;; Todo (at least):
156;;; - use emacs-vers.el (http://www.cs.utah.edu/~eeide/emacs/emacs-vers.el.gz)
157;;; for portable code?
158;;; - should `cperl-mode' do a
159;;; (if (featurep 'easymenu) (easy-menu-add cperl-menu))
160;;; or should this be left to the user's `cperl-mode-hook'?
161
162;;; Some bugs introduced by the above fix corrected (IZ ;-).
163;;; Some bugs under XEmacs introduced by the correction corrected.
164
165;;; Some more can remain since there are two many different variants.
166;;; Please feedback!
167
168;;; We do not support fontification of arrays and hashes under
169;;; obsolete font-lock any more. Upgrade.
170
171;;;; after 1.8 Minor bug with parentheses.
172;;;; after 1.9 Improvements from Joe Marzot.
173;;;; after 1.10
174;;; Does not need easymenu to compile under XEmacs.
175;;; `vc-insert-headers' should work better.
176;;; Should work with 19.29 and 19.12.
177;;; Small improvements to fontification.
178;;; Expansion of keywords does not depend on C-? being backspace.
179
180;;; after 1.10+
181;;; 19.29 and 19.12 supported.
182;;; `cperl-font-lock-enhanced' deprecated. Use font-lock-extra.el.
183;;; Support for font-lock-extra.el.
184
185;;;; After 1.11:
186;;; Tools submenu.
187;;; Support for perl5-info.
188;;; `imenu-go-find-at-position' in Tools requires imenu-go.el (see hints above)
189;;; Imenu entries do not work with stock imenu.el. Patch sent to maintainers.
190;;; Fontifies `require a if b;', __DATA__.
191;;; Arglist for auto-fill-mode was incorrect.
192
193;;;; After 1.12:
194;;; `cperl-lineup-step' and `cperl-lineup' added: lineup constructions
195;;; vertically.
196;;; `cperl-do-auto-fill' updated for 19.29 style.
197;;; `cperl-info-on-command' now has a default.
198;;; Workaround for broken C-h on XEmacs.
199;;; VC strings escaped.
200;;; C-h f now may prompt for function name instead of going on,
201;;; controlled by `cperl-info-on-command-no-prompt'.
202
203;;;; After 1.13:
204;;; Msb buffer list includes perl files
205;;; Indent-for-comment uses indent-to
206;;; Can write tag files using etags.
207
208;;;; After 1.14:
209;;; Recognizes (tries to ;-) {...} which are not blocks during indentation.
210;;; `cperl-close-paren-offset' affects ?\] too (and ?\} if not block)
c07a80fd 211;;; Bug with auto-filling comments started with "##" corrected.
212
213;;;; Very slow now: on DB::DB 0.91, 486/66:
214
215;;;Function Name Call Count Elapsed Time Average Time
216;;;======================================== ========== ============ ============
217;;;cperl-block-p 469 3.7799999999 0.0080597014
218;;;cperl-get-state 505 163.39000000 0.3235445544
219;;;cperl-comment-indent 12 0.0299999999 0.0024999999
220;;;cperl-backward-to-noncomment 939 4.4599999999 0.0047497337
221;;;cperl-calculate-indent 505 172.22000000 0.3410297029
222;;;cperl-indent-line 505 172.88000000 0.3423366336
223;;;cperl-use-region-p 40 0.0299999999 0.0007499999
224;;;cperl-indent-exp 1 177.97000000 177.97000000
225;;;cperl-to-comment-or-eol 1453 3.9800000000 0.0027391603
226;;;cperl-backward-to-start-of-continued-exp 9 0.0300000000 0.0033333333
227;;;cperl-indent-region 1 177.94000000 177.94000000
228
229;;;; After 1.15:
230;;; Takes into account white space after opening parentheses during indent.
231;;; May highlight pods and here-documents: see `cperl-pod-here-scan',
232;;; `cperl-pod-here-fontify', `cperl-pod-face'. Does not use this info
233;;; for indentation so far.
234;;; Fontification updated to 19.30 style.
235;;; The change 19.29->30 did not add all the required functionality,
236;;; but broke "font-lock-extra.el". Get "choose-color.el" from
237;;; ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs
238
239;;;; After 1.16:
240;;; else # comment
241;;; recognized as a start of a block.
242;;; Two different font-lock-levels provided.
243;;; `cperl-pod-head-face' introduced. Used for highlighting.
244;;; `imenu' marks pods, +Packages moved to the head.
245
246;;;; After 1.17:
247;;; Scan for pods highlights here-docs too.
248;;; Note that the tag of here-doc may be rehighlighted later by lazy-lock.
249;;; Only one here-doc-tag per line is supported, and one in comment
250;;; or a string may break fontification.
251;;; POD headers were supposed to fill one line only.
252
253;;;; After 1.18:
254;;; `font-lock-keywords' were set in 19.30 style _always_. Current scheme
255;;; may break under XEmacs.
256;;; `cperl-calculate-indent' dis suppose that `parse-start' was defined.
257;;; `fontified' tag is added to fontified text as well as `lazy-lock' (for
258;;; compatibility with older lazy-lock.el) (older one overfontifies
259;;; something nevertheless :-().
260;;; Will not indent something inside pod and here-documents.
261;;; Fontifies the package name after import/no/bootstrap.
262;;; Added new entry to menu with meta-info about the mode.
4633a7c4 263
29043b61 264;;;; After 1.19:
265;;; Prefontification works much better with 19.29. Should be checked
266;;; with 19.30 as well.
267;;; Some misprints in docs corrected.
268;;; Now $a{-text} and -text => "blah" are fontified as strings too.
269;;; Now the pod search is much stricter, so it can help you to find
270;;; pod sections which are broken because of whitespace before =blah
271;;; - just observe the fontification.
272
9ea28adb 273;;;; After 1.20
274;;; Anonymous subs are indented with respect to the level of
275;;; indentation of `sub' now.
276;;; {} is recognized as hash after `bless' and `return'.
277;;; Anonymous subs are split by `cperl-linefeed' as well.
278;;; Electric parens embrace a region if present.
279;;; To make `cperl-auto-newline' useful,
280;;; `cperl-auto-newline-after-colon' is introduced.
281;;; `cperl-electric-parens' is now t or nul. The old meaning is moved to
282;;; `cperl-electric-parens-string'.
283;;; `cperl-toggle-auto-newline' introduced, put on C-c C-a.
284;;; `cperl-toggle-abbrev' introduced, put on C-c C-k.
285;;; `cperl-toggle-electric' introduced, put on C-c C-e.
286;;; Beginning-of-defun-regexp was not anchored.
287
288;;;; After 1.21
289;;; Auto-newline grants `cperl-extra-newline-before-brace' if "{" is typed
290;;; after ")".
291;;; {} is recognized as expression after `tr' and friends.
292
293;;;; After 1.22
294;;; Entry Hierarchy added to imenu. Very primitive so far.
295;;; One needs newer `imenu-go'.el. A patch to `imenu' is needed as well.
296;;; Writes its own TAGS files.
297;;; Class viewer based on TAGS files. Does not trace @ISA so far.
298;;; 19.31: Problems with scan for PODs corrected.
299;;; First POD header correctly fontified.
300;;; I needed (setq imenu-use-keymap-menu t) to get good imenu in 19.31.
301;;; Apparently it makes a lot of hierarchy code obsolete...
302
303;;;; After 1.23
304;;; Tags filler now scans *.xs as well.
305;;; The info from *.xs scan is used by the hierarchy viewer.
306;;; Hierarchy viewer documented.
307;;; Bug in 19.31 imenu documented.
308
499d5216
IZ
309;;;; After 1.24
310;;; New location for info-files mentioned,
311;;; Electric-; should work better.
312;;; Minor bugs with POD marking.
313
55497cff 314;;;; After 1.25 (probably not...)
499d5216
IZ
315;;; `cperl-info-page' introduced.
316;;; To make `uncomment-region' working, `comment-region' would
317;;; not insert extra space.
318;;; Here documents delimiters better recognized
319;;; (empty one, and non-alphanums in quotes handled). May be wrong with 1<<14?
320;;; `cperl-db' added, used in menu.
321;;; imenu scan removes text-properties, for better debugging
322;;; - but the bug is in 19.31 imenu.
323;;; formats highlighted by font-lock and prescan, embedded comments
324;;; are not treated.
325;;; POD/friends scan merged in one pass.
326;;; Syntax class is not used for analyzing the code, only char-syntax
55497cff 327;;; may be checked against _ or'ed with w.
499d5216
IZ
328;;; Syntax class of `:' changed to be _.
329;;; `cperl-find-bad-style' added.
330
55497cff 331;;;; After 1.25
332;;; When search for here-documents, we ignore commented << in simplest cases.
333;;; `cperl-get-help' added, available on C-h v and from menu.
334;;; Auto-help added. Default with `cperl-hairy', switchable on/off
335;;; with startup variable `cperl-lazy-help-time' and from
336;;; menu. Requires `run-with-idle-timer'.
337;;; Highlighting of @abc{@efg} was wrong - interchanged two regexps.
338
339;;;; After 1.27
340;;; Indentation: At toplevel after a label - fixed.
341;;; 1.27 was put to archives in binary mode ===> DOSish :-(
342
343;;;; After 1.28
344;;; Thanks to Martin Buchholz <mrb@Eng.Sun.COM>: misprints in
345;;; comments and docstrings corrected, XEmacs support cleaned up.
346;;; The closing parenths would enclose the region into matching
347;;; parens under the same conditions as the opening ones.
348;;; Minor updates to `cperl-short-docs'.
349;;; Will not consider <<= as start of here-doc.
350
5f05dabc 351;;;; After 1.29
352;;; Added an extra advice to look into Micro-docs. ;-).
353;;; Enclosing of region when you press a closing parenth is regulated by
354;;; `cperl-electric-parens-string'.
355;;; Minor updates to `cperl-short-docs'.
356;;; `initialize-new-tags-table' called only if present (Does this help
357;;; with generation of tags under XEmacs?).
358;;; When creating/updating tag files, new info is written at the old place,
359;;; or at the end (is this a wanted behaviour? I need this in perl build directory).
360
361;;;; After 1.30
362;;; All the keywords from keywords.pl included (maybe with dummy explanation).
363;;; No auto-help inside strings, comment, here-docs, formats, and pods.
ebcd4dbc
IZ
364;;; Shrinkwrapping of info, regulated by `cperl-max-help-size',
365;;; `cperl-shrink-wrap-info-frame'.
5f05dabc 366;;; Info on variables as well.
367;;; Recognision of HERE-DOCS improved yet more.
368;;; Autonewline works on `}' without warnings.
369;;; Autohelp works again on $_[0].
370
371;;;; After 1.31
372;;; perl-descr.el found its author - hi, Johan!
ebcd4dbc
IZ
373;;; Some support for correct indent after here-docs and friends (may
374;;; be superseeded by eminent change to Emacs internals).
375;;; Should work with older Emaxen as well ( `-style stuff removed).
376
377;;;; After 1.32
378
379;;; Started to add support for `syntax-table' property (should work
380;;; with patched Emaxen), controlled by
381;;; `cperl-use-syntax-table-text-property'. Currently recognized:
382;;; All quote-like operators: m, s, y, tr, qq, qw, qx, q,
383;;; // in most frequent context:
384;;; after block or
385;;; ~ { ( = | & + - * ! , ;
386;;; or
387;;; while if unless until and or not xor split grep map
388;;; Here-documents, formats, PODs,
389;;; ${...}
390;;; 'abc$'
391;;; sub a ($); sub a ($) {}
392;;; (provide 'cperl-mode) was missing!
393;;; `cperl-after-expr-p' is now much smarter after `}'.
394;;; `cperl-praise' added to mini-docs.
395;;; Utilities try to support subs-with-prototypes.
396
397;;;; After 1.32.1
398;;; `cperl-after-expr-p' is now much smarter after "() {}" and "word {}":
399;;; if word is "else, map, grep".
400;;; Updated for new values of syntax-table constants.
401;;; Uses `help-char' (at last!) (disabled, does not work?!)
402;;; A couple of regexps where missing _ in character classes.
403;;; -s could be considered as start of regexp, 1../blah/ was not,
404;;; as was not /blah/ at start of file.
405
406;;;; After 1.32.2
407;;; "\C-hv" was wrongly "\C-hf"
408;;; C-hv was not working on `[index()]' because of [] in skip-chars-*.
409;;; `__PACKAGE__' supported.
410;;; Thanks for Greg Badros: `cperl-lazy-unstall' is more complete,
411;;; `cperl-get-help' is made compatible with `query-replace'.
412
413;;;; As of Apr 15, development version of 19.34 supports
414;;;; `syntax-table' text properties. Try setting
415;;;; `cperl-use-syntax-table-text-property'.
416
417;;;; After 1.32.3
05bbd9c3 418;;; We scan for s{}[] as well (in simplest situations).
ebcd4dbc
IZ
419;;; We scan for $blah'foo as well.
420;;; The default is to use `syntax-table' text property if Emacs is good enough.
421;;; `cperl-lineup' is put on C-M-| (=C-M-S-\\).
422;;; Start of `cperl-beautify-regexp'.
423
424;;;; After 1.32.4
425;;; `cperl-tags-hier-init' did not work in text-mode.
426;;; `cperl-noscan-files-regexp' had a misprint.
427;;; Generation of Class Hierarchy was broken due to a bug in `x-popup-menu'
428;;; in 19.34.
5f05dabc 429
05bbd9c3
IZ
430;;;; After 1.33:
431;;; my,local highlight vars after {} too.
432;;; TAGS could not be created before imenu was loaded.
433;;; `cperl-indent-left-aligned-comments' created.
434;;; Logic of `cperl-indent-exp' changed a little bit, should be more
435;;; robust w.r.t. multiline strings.
436;;; Recognition of blah'foo takes into account strings.
437;;; Added '.al' to the list of Perl extensions.
438;;; Class hierarchy is "mostly" sorted (need to rethink algorthm
439;;; of pruning one-root-branch subtrees to get yet better sorting.)
440;;; Regeneration of TAGS was busted.
441;;; Can use `syntax-table' property when generating TAGS
442;;; (governed by `cperl-use-syntax-table-text-property-for-tags').
443
444;;;; After 1.35:
445;;; Can process several =pod/=cut sections one after another.
446;;; Knows of `extproc' when under `emx', indents with `__END__' and `__DATA__'.
447;;; `cperl-under-as-char' implemented (XEmacs people like broken behaviour).
448;;; Beautifier for regexps fixed.
449;;; `cperl-beautify-level', `cperl-contract-level' coded
450;;;
451;;;; Emacs's 20.2 problems:
452;;; `imenu.el' has bugs, `imenu-add-to-menubar' does not work.
453;;; Couple of others problems with 20.2 were reported, my ability to check/fix
454;;; them is very reduced now.
455
456;;;; After 1.36:
457;;; 'C-M-|' in XEmacs fixed
458
459;;;; After 1.37:
460;;; &&s was not recognized as start of regular expression;
461;;; Will "preprocess" the contents of //e part of s///e too;
462;;; What to do with s# blah # foo #e ?
463;;; Should handle s;blah;foo;; better.
464;;; Now the only known problems with regular expression recognition:
465;;;;;;; s<foo>/bar/ - different delimiters (end ignored)
466;;;;;;; s/foo/\\bar/ - backslash at start of subst (made into one chunk)
467;;;;;;; s/foo// - empty subst (made into one chunk + '/')
468;;;;;;; s/foo/(bar)/ - start-group at start of subst (internal group will not match backwards)
469
470;;;; After 1.38:
471;;; We highlight closing / of s/blah/foo/e;
472;;; This handles s# blah # foo #e too;
473;;; s//blah/, s///, s/blah// works again, and s#blah## too, the algorithm
474;;; is much simpler now;
475;;; Next round of changes: s\\\ works, s<blah>/foo/,
476;;; comments between the first and the second part allowed
477;;; Another problem discovered:
478;;;;;;; s[foo] <blah>e - e part delimited by different <> (will not match)
479;;; `cperl-find-pods-heres' somehow maybe called when string-face is undefined
480;;; - put a stupid workaround for 20.1
481
3ee700d1
IZ
482;;;; After 1.39:
483;;; Could indent here-docs for comments;
484;;; These problems fixed:
485;;;;;;; s/foo/\\bar/ - backslash at start of subst (made into two chunk)
486;;;;;;; s[foo] <blah>e - "e" part delimited by "different" <> (will match)
487;;; Matching brackets honor prefices, may expand abbreviations;
488;;; When expanding abbrevs, will remove last char only after
489;;; self-inserted whitespace;
490;;; More convenient "Refress hard constructs" in menu;
491;;; `cperl-add-tags-recurse', `cperl-add-tags-recurse-noxs'
492;;; added (for -batch mode);
493;;; Better handling of errors when scanning for Perl constructs;
494;;;;;;; Possible "problem" with class hierarchy in Perl distribution
495;;;;;;; directory: ./ext duplicates ./lib;
496;;; Write relative paths for generated TAGS;
497
498;;;; After 1.40:
499;;; s /// may be separated by "\n\f" too;
500;;; `s #blah' recognized as a comment;
501;;; Would highlight s/abc//s wrong;
502;;; Debugging code in `cperl-electric-keywords' was leaking a message;
503
6c72d195 504;;;; After 1.41:
4584684c 505;;; RMS changes for 20.3 merged
6c72d195
IZ
506
507;;;; 2.0.1.0: RMS mode (has 3 misprints)
508
509;;;; After 2.0:
4584684c 510;;; RMS whitespace changes for 20.3 merged
6c72d195
IZ
511
512;;;; After 2.1:
513;;; History updated
514
515;;;; After 2.2:
516;;; Merge `c-style-alist' since `c-mode' is no more. (Somebody who
517;;; uses the styles should check that they work OK!)
518;;; All the variable warnings go away, some undef functions too.
519
520;;;; After 2.3:
521;;; Added `cperl-perldoc' (thanks to Anthony Foiani <afoiani@uswest.com>)
522;;; Added `cperl-pod-to-manpage' (thanks to Nick Roberts <Nick.Roberts@src.bae.co.uk>)
523;;; All the function warnings go away.
524
525;;;; After 2.4:
526;;; `Perl doc', `Regexp' submenus created (latter to allow short displays).
527;;; `cperl-clobber-lisp-bindings' added.
528;;; $a->y() is not y///.
529;;; `cperl-after-block-p' was missing a `save-excursion' => wrong results.
530;;; `cperl-val' was defined too late.
531;;; `cperl-init-faces' was failing.
532;;; Init faces when loading `ps-print'.
533
534;;;; After 2.4:
535;;; `cperl-toggle-autohelp' implemented.
536;;; `while SPACE LESS' was buggy.
537;;; `-text' in `[-text => 1]' was not highlighted.
538;;; `cperl-after-block-p' was FALSE after `sub f {}'.
539
540;;;; After 2.5:
541;;; `foreachmy', `formy' expanded too.
542;;; Expand `=pod-directive'.
543;;; `cperl-linefeed' behaves reasonable in POD-directive lines.
544;;; `cperl-electric-keyword' prints a message, governed by
545;;; `cperl-message-electric-keyword'.
546
547;;;; After 2.6:
548;;; Typing `}' was not checking for being block or not.
549;;; Beautifying levels in RE: Did not know about lookbehind;
550;;; finding *which* level was not intuitive;
551;;; `cperl-beautify-levels' added.
552;;; Allow here-docs contain `=head1' and friends (at least for keywords).
553
554;;;; After 2.7:
555;;; Fix for broken `font-lock-unfontify-region-function'. Should
556;;; preserve `syntax-table' properties even with `lazy-lock'.
557
558;;;; After 2.8:
559;;; Some more compile time warnings crept in.
560;;; `cperl-indent-region-fix-else' implemented.
561;;; `cperl-fix-line-spacing' implemented.
562;;; `cperl-invert-if-unless' implemented (C-c C-t and in Menu).
563;;; Upgraded hints to mention 20.2's goods/bads.
564;;; Started to use `cperl-extra-newline-before-brace-multiline',
565;;; `cperl-break-one-line-blocks-when-indent',
566;;; `cperl-fix-hanging-brace-when-indent', `cperl-merge-trailing-else'.
567
568;;;; After 2.9:
569;;; Workaround for another `font-lock's `syntax-table' text-property bug.
570;;; `zerop' could be applied to nil.
571;;; At last, may work with `font-lock' without setting `cperl-font-lock'.
572;;; (We expect that starting from 19.33, `font-lock' supports keywords
573;;; being a function - what is a correct version?)
574;;; Rename `cperl-indent-region-fix-else' to
575;;; `cperl-indent-region-fix-constructs'.
576;;; `cperl-fix-line-spacing' could be triggered inside strings, would not
577;;; know what to do with BLOCKs of map/printf/etc.
578;;; `cperl-merge-trailing-else' and `cperl-fix-line-spacing' handle
579;;; `continue' too.
580;;; Indentation after {BLOCK} knows about map/printf/etc.
581;;; Finally: treat after-comma lines as continuation lines.
582
583;;;; After 2.10:
584;;; `continue' made electric.
585;;; Electric `do' inserts `do/while'.
586;;; Some extra compile-time warnings crept in.
587;;; `font-lock' of 19.33 could not handle font-lock-keywords being a function
588;;; returning a symbol.
589
590;;;; After 2.11:
591;;; Changes to make syntaxification to be autoredone via `font-lock'.
592;;; Switched on by `cperl-syntaxify-by-font-lock', off by default so far.
593
594;;;; After 2.12:
595;;; Remove some commented out chunks.
596;;; Styles are slightly updated (a lot of work is needed, especially
597;;; with new `cperl-fix-line-spacing').
598
599;;;; After 2.13:
600;;; Old value of style is memorized when choosing a new style, may be
601;;; restored from the same menu.
602;;; Mode-documentation added to micro-docs.
603;;; `cperl-praise' updated.
604;;; `cperl-toggle-construct-fix' added on C-c C-w and menu.
605;;; `auto-fill-mode' added on C-c C-f and menu.
606;;; `PerlStyle' style added.
607;;; Message for termination of scan corrected.
608
609;;;; After 2.14:
610
611;;; Did not work with -q
612
613;;;; After 2.15:
614
615;;; `cperl-speed' hints added.
616;;; Minor style fixes.
617
618;;;; After 2.15:
619;;; Make backspace electric after expansion of `else/continue' too.
620
621;;;; After 2.16:
622;;; Starting to merge changes to RMS emacs version.
623
624;;;; After 2.17:
625;;; Merged custom stuff and darn `font-lock-constant-face'.
626
627;;;; After 2.18:
628;;; Bumped the version to 3.1
629
630;;;; After 3.1:
631;;; Fixed customization to honor cperl-hairy.
632;;; Created customization groups. Sent to RMS to include into 2.3.
633
634;;;; After 3.2:
635;;; Interaction of `font-lock-hot-pass' and `cperl-syntaxify-by-font-lock'.
636;;; (`cperl-after-block-and-statement-beg'):
637;;; (`cperl-after-block-p'):
638;;; (`cperl-after-expr-p'): It is BLOCK if we reach lim when backup sexp.
639;;; (`cperl-indent-region'): Make a marker for END - text added/removed.
640;;; (`cperl-style-alist', `cperl-styles-entries')
641;;; Include `cperl-merge-trailing-else' where the value is clear.
642
643;;;; After 3.3:
644;;; (`cperl-tips'):
645;;; (`cperl-problems'): Improvements to docs.
646
647;;;; After 3.4:
648;;; (`cperl-mode'): Make lazy syntaxification possible.
649;;; (`cperl-find-pods-heres'): Safe a position in buffer where it is safe to
650;;; restart syntaxification.
651;;; (`cperl-syntaxify-by-font-lock'): Set to t, should be safe now.
652
653;;;; After 3.5:
654;;; (`cperl-syntaxify-by-font-lock'): Better default, customizes to
655;;; `message' too.
656
657;;;; After 3.6:
658;;; (`cperl-find-pods-heres'): changed so that -d ?foo? is a RE.
659;;; (`cperl-array-face'): changed name from `font-lock-emphasized-face'.
660;;; (`cperl-hash-face'): changed name from `font-lock-other-emphasized-face'.
661;;; Use `defface' to define these two extra faces.
662
663;;;; After 3.7:
664;;; Can use linear algorithm for indentation if Emacs supports it:
665;;; indenting DB::DB (800+ lines) improved from 69 sec to 11 sec
666;;; (73 vs 15 with imenu).
667;;; (`cperl-emacs-can-parse'): New state.
668;;; (`cperl-indent-line'): Corrected to use global state.
669;;; (`cperl-calculate-indent'): Likewise.
670;;; (`cperl-fix-line-spacing'): Likewise (not used yet).
671
672;;;; After 3.8:
673;;; (`cperl-choose-color'): Converted to a function (to be compilable in text-mode).
674
675;;;; After 3.9:
676;;; (`cperl-dark-background '): Disable without window-system.
677
678;;;; After 3.10:
679;;; Do `defface' only if window-system.
680
681;;;; After 3.11:
682;;; (`cperl-fix-line-spacing'): sped up to bail out early.
683;;; (`cperl-indent-region'): Disable hooks during the call (how to call them later?).
684
685;;; Now indents 820-line-long function in 6.5 sec (including syntaxification) the first time
686;;; (when buffer has few properties), 7.1 sec the second time.
687
688;;;Function Name Call Count Elapsed Time Average Time
689;;;========================================= ========== ============ ============
690;;;cperl-indent-exp 1 10.039999999 10.039999999
691;;;cperl-indent-region 1 10.0 10.0
692;;;cperl-indent-line 821 6.2100000000 0.0075639464
693;;;cperl-calculate-indent 821 5.0199999999 0.0061144945
694;;;cperl-backward-to-noncomment 2856 2.0500000000 0.0007177871
695;;;cperl-fontify-syntaxically 2 1.78 0.8900000000
696;;;cperl-find-pods-heres 2 1.78 0.8900000000
697;;;cperl-update-syntaxification 1 1.78 1.78
698;;;cperl-fix-line-spacing 769 1.4800000000 0.0019245773
699;;;cperl-after-block-and-statement-beg 163 1.4100000000 0.0086503067
700;;;cperl-block-p 775 1.1800000000 0.0015225806
701;;;cperl-to-comment-or-eol 3652 1.1200000000 0.0003066812
702;;;cperl-after-block-p 165 1.0500000000 0.0063636363
703;;;cperl-commentify 141 0.22 0.0015602836
704;;;cperl-get-state 813 0.16 0.0001968019
705;;;cperl-backward-to-start-of-continued-exp 26 0.12 0.0046153846
706;;;cperl-delay-update-hook 2107 0.0899999999 4.271...e-05
707;;;cperl-protect-defun-start 141 0.0700000000 0.0004964539
708;;;cperl-after-label 407 0.0599999999 0.0001474201
709;;;cperl-forward-re 139 0.0299999999 0.0002158273
710;;;cperl-comment-indent 26 0.0299999999 0.0011538461
711;;;cperl-use-region-p 8 0.0 0.0
712;;;cperl-lazy-hook 15 0.0 0.0
713;;;cperl-after-expr-p 8 0.0 0.0
714;;;cperl-font-lock-unfontify-region-function 1 0.0 0.0
715
716;;;Function Name Call Count Elapsed Time Average Time
717;;;========================================= ========== ============ ============
718;;;cperl-fix-line-spacing 769 1.4500000000 0.0018855656
719;;;cperl-indent-line 13 0.3100000000 0.0238461538
720;;;cperl-after-block-and-statement-beg 69 0.2700000000 0.0039130434
721;;;cperl-after-block-p 69 0.2099999999 0.0030434782
722;;;cperl-calculate-indent 13 0.1000000000 0.0076923076
723;;;cperl-backward-to-noncomment 177 0.0700000000 0.0003954802
724;;;cperl-get-state 13 0.0 0.0
725;;;cperl-to-comment-or-eol 179 0.0 0.0
726;;;cperl-get-help-defer 1 0.0 0.0
727;;;cperl-lazy-hook 11 0.0 0.0
728;;;cperl-after-expr-p 2 0.0 0.0
729;;;cperl-block-p 13 0.0 0.0
730;;;cperl-after-label 5 0.0 0.0
731
732;;;; After 3.12:
733;;; (`cperl-find-pods-heres'): do not warn on `=cut' if doing a chunk only.
734
735;;;; After 3.13:
736;;; (`cperl-mode'): load pseudo-faces on `cperl-find-pods-heres' (for 19.30).
737;;; (`x-color-defined-p'): was not compiling on XEmacs
738;;; (`cperl-find-pods-heres'): 1 << 6 was OK, but 1<<6 was considered as HERE
739;;; <file/glob> made into a string.
740
20675f5d
IZ
741;;;; After 3.14:
742;;; (`cperl-find-pods-heres'): Postpone addition of faces after syntactic step
743;;; Recognition of <FH> was wrong.
744;;; (`cperl-clobber-lisp-bindings'): if set, C-c variants are the old ones
745;;; (`cperl-unwind-to-safe'): New function.
746;;; (`cperl-fontify-syntaxically'): Use `cperl-unwind-to-safe' to start at reasonable position.
747
748;;;; After 3.15:
749;;; (`cperl-forward-re'): Highlight the trailing / in s/foo// as string.
750;;; Highlight the starting // in s//foo/ as function-name.
751
752;;;; After 3.16:
753;;; (`cperl-find-pods-heres'): Highlight `gem' in s///gem as a keyword.
754
755;;;; After 4.0:
756;;; (`cperl-find-pods-heres'): `qr' added
757;;; (`cperl-electric-keyword'): Likewise
758;;; (`cperl-electric-else'): Likewise
759;;; (`cperl-to-comment-or-eol'): Likewise
760;;; (`cperl-make-regexp-x'): Likewise
761;;; (`cperl-init-faces'): Likewise, and `lock' (as overridable?).
762;;; (`cperl-find-pods-heres'): Knows that split// is null-RE.
763;;; Highlights separators in 3-parts expressions
764;;; as labels.
765
766;;;; After 4.1:
767;;; (`cperl-find-pods-heres'): <> was considered as a glob
768;;; (`cperl-syntaxify-unwind'): New configuration variable
769;;; (`cperl-fontify-m-as-s'): New configuration variable
770
771;;;; After 4.2:
772;;; (`cperl-find-pods-heres'): of the last line being `=head1' fixed.
773
774;;; Handling of a long construct is still buggy if only the part of
775;;; construct touches the updated region (we unwind to the start of
776;;; long construct, but the end may have residual properties).
777
778;;; (`cperl-unwind-to-safe'): would not go to beginning of buffer.
779;;; (`cperl-electric-pod'): check for after-expr was performed
780;;; inside of POD too.
781
782;;;; After 4.3:
783;;; (`cperl-backward-to-noncomment'): better treatment of PODs and HEREs.
784
785;;; Indent-line works good, but indent-region does not - at toplevel...
786;;; (`cperl-unwind-to-safe'): Signature changed.
787;;; (`x-color-defined-p'): was defmacro'ed with a tick. Remove another def.
788;;; (`cperl-clobber-mode-lists'): New configuration variable.
789;;; (`cperl-array-face'): One of definitions was garbled.
790
791;;;; After 4.4:
7bcea553 792;;; (`cperl-not-bad-style-regexp'): Updated.
20675f5d
IZ
793;;; (`cperl-make-regexp-x'): Misprint in a message.
794;;; (`cperl-find-pods-heres'): $a-1 ? foo : bar; was a regexp.
795;;; `<< (' was considered a start of POD.
796;;; Init: `cperl-is-face' was busted.
797;;; (`cperl-make-face'): New macros.
798;;; (`cperl-force-face'): New macros.
799;;; (`cperl-init-faces'): Corrected to use new macros;
800;;; `if' for copying `reference-face' to
801;;; `constant-face' was backward.
802;;; (`font-lock-other-type-face'): Done via `defface' too.
803
4584684c
GS
804;;;; After 4.5:
805;;; (`cperl-init-faces-weak'): use `cperl-force-face'.
806;;; (`cperl-after-block-p'): After END/BEGIN we are a block.
807;;; (`cperl-mode'): `font-lock-unfontify-region-function'
808;;; was set to a wrong function.
809;;; (`cperl-comment-indent'): Commenting __END__ was not working.
810;;; (`cperl-indent-for-comment'): Likewise.
811;;; (Indenting is still misbehaving at toplevel.)
812
813;;;; After 4.5:
814;;; (`cperl-unwind-to-safe'): Signature changed, unwinds end too.
815;;; (`cperl-find-pods-heres'): mark qq[]-etc sections as syntax-type=string
816;;; (`cperl-fontify-syntaxically'): Unwinds start and end to go out of
817;;; long strings (not very successful).
818
819;;; >>>> CPerl should be usable in write mode too now <<<<
820
821;;; (`cperl-syntaxify-by-font-lock'): Better default - off in text-mode.
822;;; (`cperl-tips'): Updated docs.
823;;; (`cperl-problems'): Updated docs.
824
825;;;; After 4.6:
826;;; (`cperl-calculate-indent'): Did not consider `,' as continuation mark for statements.
827;;; (`cperl-write-tags'): Correct for XEmacs's `visit-tags-table-buffer'.
828
829;;;; After 4.7:
830;;; (`cperl-calculate-indent'): Avoid parse-data optimization at toplevel.
831;;; Should indent correctly at toplevel too.
832;;; (`cperl-tags-hier-init'): Gross hack to pretend we work (are we?).
833;;; (`cperl-find-pods-heres'): Was not processing sub protos after a comment ine.
834;;; Was treating $a++ <= 5 as a glob.
835
836;;;; After 4.8:
837;;; (toplevel): require custom unprotected => failure on 19.28.
838;;; (`cperl-xemacs-p') defined when compile too
839;;; (`cperl-tags-hier-init'): Another try to work around XEmacs problems
840;;; Better progress messages.
841;;; (`cperl-find-tags'): Was writing line/pos in a wrong order,
842;;; pos off by 1 and not at beg-of-line.
843;;; (`cperl-etags-snarf-tag'): New macro
844;;; (`cperl-etags-goto-tag-location'): New macro
845;;; (`cperl-write-tags'): When removing old TAGS info was not
846;;; relativizing filename
847
848;;;; After 4.9:
849;;; (`cperl-version'): New variable. New menu entry
850
851;;;; After 4.10:
852;;; (`cperl-tips'): Updated.
853;;; (`cperl-non-problems'): Updated.
854;;; random: References to future 20.3 removed.
855
856;;;; After 4.11:
857;;; (`perl-font-lock-keywords'): Would not highlight `sub foo($$);'.
858;;; Docstrings: Menu was described as `CPerl' instead of `Perl'
859
860;;;; After 4.12:
861;;; (`cperl-toggle-construct-fix'): Was toggling to t instead of 1.
862;;; (`cperl-ps-print-init'): Associate `cperl-array-face', `cperl-hash-face'
863;;; remove `font-lock-emphasized-face'.
864;;; remove `font-lock-other-emphasized-face'.
865;;; remove `font-lock-reference-face'.
866;;; remove `font-lock-keyword-face'.
867;;; Use `eval-after-load'.
868;;; (`cperl-init-faces'): remove init `font-lock-other-emphasized-face'.
869;;; remove init `font-lock-emphasized-face'.
870;;; remove init `font-lock-keyword-face'.
871;;; (`cperl-tips-faces'): New variable and an entry into Mini-docs.
872;;; (`cperl-indent-region'): Do not indent whitespace lines
873;;; (`cperl-indent-exp'): Was not processing else-blocks.
874;;; (`cperl-calculate-indent'): Remove another parse-data optimization
875;;; at toplevel: would indent correctly.
876;;; (`cperl-get-state'): NOP line removed.
877
878;;;; After 4.13:
879;;; (`cperl-ps-print-init'): Remove not-CPerl-related faces.
880;;; (`cperl-ps-print'): New function and menu entry.
881;;; (`cperl-ps-print-face-properties'): New configuration variable.
882;;; (`cperl-invalid-face'): New configuration variable.
883;;; (`cperl-nonoverridable-face'): New face. Renamed from
884;;; `font-lock-other-type-face'.
885;;; (`perl-font-lock-keywords'): Highlight trailing whitespace
886;;; (`cperl-contract-levels'): Documentation corrected.
887;;; (`cperl-contract-level'): Likewise.
888
889;;;; After 4.14:
890;;; (`cperl-ps-print'): `ps-print-face-extension-alist' was not in old Emaxen,
891;;; same with `ps-extend-face-list'
892;;; (`cperl-ps-extend-face-list'): New macro.
893
894;;;; After 4.15:
895;;; (`cperl-init-faces'): Interpolate `cperl-invalid-face'.
896;;; (`cperl-forward-re'): Emit a meaningful error instead of a cryptic
897;;; one for uncomplete REx near end-of-buffer.
898;;; (`cperl-find-pods-heres'): Tolerate unfinished REx at end-of-buffer.
899
900;;;; After 4.16:
901;;; (`cperl-find-pods-heres'): `unwind-protect' was left commented.
902
903;;;; After 4.17:
904;;; (`cperl-invalid-face'): Change to ''underline.
905
906;;;; After 4.18:
907;;; (`cperl-find-pods-heres'): / and ? after : start a REx.
908;;; (`cperl-after-expr-p'): Skip labels when checking
909;;; (`cperl-calculate-indent'): Correct for labels when calculating
910;;; indentation of continuations.
911;;; Docstring updated.
7bcea553
IZ
912
913;;;; After 4.19:
914;;; Minor (mostly spelling) corrections from 20.3.3 merged.
915
916;;;; After 4.20:
917;;; (`cperl-tips'): Another workaround added. Sent to RMS for 20.4.
918
919;;;; After 4.21:
920;;; (`cperl-praise'): Mention linear-time indent.
921;;; (`cperl-find-pods-heres'): @if ? a : b was considered a REx.
922
923;;;; After 4.22:
924;;; (`cperl-after-expr-p'): Make true after __END__.
925;;; (`cperl-electric-pod'): "SYNOPSIS" was misspelled.
926
927;;;; After 4.23:
928;;; (`cperl-beautify-regexp-piece'): Was not allowing for *? after a class.
929;;; Allow for POSIX char-classes.
930;;; Remove trailing whitespace when
931;;; adding new linebreak.
932;;; Add a level counter to stop shallow.
933;;; Indents unprocessed groups rigidly.
934;;; (`cperl-beautify-regexp'): Add an optional count argument to go that
935;;; many levels deep.
936;;; (`cperl-beautify-level'): Likewise
937;;; Menu: Add new entries to Regexp menu to do one level
938;;; (`cperl-contract-level'): Was entering an infinite loop
939;;; (`cperl-find-pods-heres'): Typo (double quoting).
940;;; Was detecting < $file > as FH instead of glob.
941;;; Support for comments in RExen (except
942;;; for m#\#comment#x), governed by
943;;; `cperl-regexp-scan'.
944;;; (`cperl-regexp-scan'): New customization variable.
945;;; (`cperl-forward-re'): Improve logic of resetting syntax table.
946
947;;;; After 4.23 and: After 4.24:
948;;; (`cperl-contract-levels'): Restore position.
949;;; (`cperl-beautify-level'): Likewise.
950;;; (`cperl-beautify-regexp'): Likewise.
951;;; (`cperl-commentify'): Rudimental support for length=1 runs
952;;; (`cperl-find-pods-heres'): Process 1-char long REx comments too /a#/x
953;;; Processes REx-comments in #-delimited RExen.
954;;; MAJOR BUG CORRECTED: after a misparse
955;;; a body of a subroutine could be corrupted!!!
956;;; One might need to reeval the function body
957;;; to fix things. (A similar bug was
958;;; present in `cperl-indent-region' eons ago.)
959;;; To reproduce:
960;; (defun foo () (let ((a '(t))) (insert (format "%s" a)) (setcar a 'BUG) t))
961;; (foo)
962;; (foo)
963;;; C-x C-e the above three lines (at end-of-line). First evaluation
964;;; of `foo' inserts (t), second one inserts (BUG) ?!
965;;;
966;;; In CPerl it was triggered by inserting then deleting `/' at start of
967;;; / a (?# asdf {[(}asdf )ef,/;
968
969;;;; After 4.25:
970;;; (`cperl-commentify'): Was recognizing length=2 "strings" as length=1.
971;;; (`imenu-example--create-perl-index'):
972;;; Was not enforcing syntaxification-to-the-end.
973;;; (`cperl-invert-if-unless'): Allow `for', `foreach'.
974;;; (`cperl-find-pods-heres'): Quote `cperl-nonoverridable-face'.
975;;; Mark qw(), m()x as indentable.
976;;; (`cperl-init-faces'): Highlight `sysopen' too.
977;;; Highlight $var in `for my $var' too.
978;;; (`cperl-invert-if-unless'): Was leaving whitespace at end.
979;;; (`cperl-linefeed'): Was splitting $var{$foo} if point after `{'.
980;;; (`cperl-calculate-indent'): Remove old commented out code.
981;;; Support (primitive) indentation of qw(), m()x.
982
983
984;;;; After 4.26:
985;;; (`cperl-problems'): Mention `fill-paragraph' on comment. \"" and
986;;; q [] with intervening newlines.
987;;; (`cperl-autoindent-on-semi'): New customization variable.
988;;; (`cperl-electric-semi'): Use `cperl-autoindent-on-semi'.
989;;; (`cperl-tips'): Mention how to make CPerl the default mode.
990;;; (`cperl-mode'): Support `outline-minor-mode'
991;;; (Thanks to Mark A. Hershberger).
992;;; (`cperl-outline-level'): New function.
993;;; (`cperl-highlight-variables-indiscriminately'): New customization var.
994;;; (`cperl-init-faces'): Use `cperl-highlight-variables-indiscriminately'.
995;;; (Thanks to Sean Kamath <kamath@pogo.wv.tek.com>).
996;;; (`cperl-after-block-p'): Support CHECK and INIT.
997;;; (`cperl-init-faces'): Likewise and "our".
998;;; (Thanks to Doug MacEachern <dougm@covalent.net>).
999;;; (`cperl-short-docs'): Likewise and "our".
1000
1001
1002;;;; After 4.27:
1003;;; (`cperl-find-pods-heres'): Recognize \"" as a string.
1004;;; Mark whitespace and comments between q and []
1005;;; as `syntax-type' => `prestring'.
1006;;; Allow whitespace between << and "FOO".
1007;;; (`cperl-problems'): Remove \"" and q [] with intervening newlines.
1008;;; Mention multiple <<EOF as unsupported.
1009;;; (`cperl-highlight-variables-indiscriminately'): Doc misprint fixed.
1010;;; (`cperl-indent-parens-as-block'): New configuration variable.
1011;;; (`cperl-calculate-indent'): Merge cases of indenting non-BLOCK groups.
1012;;; Use `cperl-indent-parens-as-block'.
1013;;; (`cperl-find-pods-heres'): Test for =cut without empty line instead of
1014;;; complaining about no =cut.
1015;;; (`cperl-electric-pod'): Change the REx for POD from "\n\n=" to "^\n=".
1016;;; (`cperl-find-pods-heres'): Likewise.
1017;;; (`cperl-electric-pod'): Change `forward-sexp' to `forward-word':
1018;;; POD could've been marked as comment already.
1019;;; (`cperl-unwind-to-safe'): Unwind before start of POD too.
1020
1021;;;; After 4.28:
1022;;; (`cperl-forward-re'): Throw an error at proper moment REx unfinished.
1023
1024;;;; After 4.29:
1025;;; (`x-color-defined-p'): Make an extra case to peacify the warning.
1026;;; Toplevel: `defvar' to peacify the warnings.
1027;;; (`cperl-find-pods-heres'): Could access `font-lock-comment-face' in -nw.
1028;;;; No -nw-compile time warnings now.
1029;;; (`cperl-find-tags'): TAGS file had too short substring-to-search.
1030;;; Be less verbose in non-interactive mode
1031;;; (`imenu-example--create-perl-index'): Set index-marker after name
1032;;; (`cperl-outline-regexp'): New variable.
1033;;; (`cperl-outline-level'): Made compatible with `cperl-outline-regexp'.
1034;;; (`cperl-mode'): Made use `cperl-outline-regexp'.
1035
1036;;;; After 4.30:
1037;;; (`cperl-find-pods-heres'): =cut the last thing, no blank line, was error.
1038;;; (`cperl-outline-level'): Make start-of-file same level as `package'.
1039
1040;;;; After 4.31:
1041;;; (`cperl-electric-pod'): `head1' and `over' electric only if empty.
1042;;; (`cperl-unreadable-ok'): New variable.
1043;;; (`cperl-find-tags'): Use `cperl-unreadable-ok', do not fail
1044;;; on an unreadable file
1045;;; (`cperl-write-tags'): Use `cperl-unreadable-ok', do not fail
1046;;; on an unreadable directory
1047
6c72d195
IZ
1048;;; Code:
1049
1050\f
1051(if (fboundp 'eval-when-compile)
1052 (eval-when-compile
1053 (condition-case nil
1054 (require 'custom)
1055 (error nil))
4584684c 1056 (defconst cperl-xemacs-p (string-match "XEmacs\\|Lucid" emacs-version))
6c72d195
IZ
1057 (or (fboundp 'defgroup)
1058 (defmacro defgroup (name val doc &rest arr)
1059 nil))
1060 (or (fboundp 'custom-declare-variable)
1061 (defmacro defcustom (name val doc &rest arr)
1062 (` (defvar (, name) (, val) (, doc)))))
1063 (or (and (fboundp 'custom-declare-variable)
1064 (string< "19.31" emacs-version)) ; Checked with 19.30: defface does not work
1065 (defmacro defface (&rest arr)
1066 nil))
1067 ;; Avoid warning (tmp definitions)
1068 (or (fboundp 'x-color-defined-p)
20675f5d 1069 (defmacro x-color-defined-p (col)
6c72d195
IZ
1070 (cond ((fboundp 'color-defined-p) (` (color-defined-p (, col))))
1071 ;; XEmacs >= 19.12
1072 ((fboundp 'valid-color-name-p) (` (valid-color-name-p (, col))))
1073 ;; XEmacs 19.11
7bcea553
IZ
1074 ((fboundp 'x-valid-color-name-p) (` (x-valid-color-name-p (, col))))
1075 (t '(error "Cannot implement color-defined-p")))))
20675f5d 1076 (defmacro cperl-is-face (arg) ; Takes quoted arg
6c72d195 1077 (cond ((fboundp 'find-face)
20675f5d
IZ
1078 (` (find-face (, arg))))
1079 (;;(and (fboundp 'face-list)
1080 ;; (face-list))
1081 (fboundp 'face-list)
1082 (` (member (, arg) (and (fboundp 'face-list)
1083 (face-list)))))
6c72d195 1084 (t
20675f5d
IZ
1085 (` (boundp (, arg))))))
1086 (defmacro cperl-make-face (arg descr) ; Takes unquoted arg
1087 (cond ((fboundp 'make-face)
1088 (` (make-face (quote (, arg)))))
1089 (t
1090 (` (defconst (, arg) (quote (, arg)) (, descr))))))
1091 (defmacro cperl-force-face (arg descr) ; Takes unquoted arg
1092 (` (progn
1093 (or (cperl-is-face (quote (, arg)))
1094 (cperl-make-face (, arg) (, descr)))
1095 (or (boundp (quote (, arg))) ; We use unquoted variants too
4584684c
GS
1096 (defconst (, arg) (quote (, arg)) (, descr))))))
1097 (if cperl-xemacs-p
1098 (defmacro cperl-etags-snarf-tag (file line)
1099 (` (progn
1100 (beginning-of-line 2)
1101 (list (, file) (, line)))))
1102 (defmacro cperl-etags-snarf-tag (file line)
1103 (` (etags-snarf-tag))))
1104 (if cperl-xemacs-p
1105 (defmacro cperl-etags-goto-tag-location (elt)
1106 (` ;;(progn
1107 ;; (switch-to-buffer (get-file-buffer (elt (, elt) 0)))
1108 ;; (set-buffer (get-file-buffer (elt (, elt) 0)))
1109 ;; Probably will not work due to some save-excursion???
1110 ;; Or save-file-position?
1111 ;; (message "Did I get to line %s?" (elt (, elt) 1))
1112 (goto-line (string-to-int (elt (, elt) 1)))))
1113 ;;)
1114 (defmacro cperl-etags-goto-tag-location (elt)
1115 (` (etags-goto-tag-location (, elt)))))))
1116
1117(condition-case nil
1118 (require 'custom)
1119 (error nil)) ; Already fixed by eval-when-compile
6c72d195 1120
6c72d195
IZ
1121(defun cperl-choose-color (&rest list)
1122 (let (answer)
1123 (while list
1124 (or answer
1125 (if (or (x-color-defined-p (car list))
1126 (null (cdr list)))
1127 (setq answer (car list))))
1128 (setq list (cdr list)))
1129 answer))
1130
ebcd4dbc 1131\f
6c72d195
IZ
1132(defgroup cperl nil
1133 "Major mode for editing Perl code."
1134 :prefix "cperl-"
1135 :group 'languages)
1136
1137(defgroup cperl-indentation-details nil
1138 "Indentation."
1139 :prefix "cperl-"
1140 :group 'cperl)
1141
1142(defgroup cperl-affected-by-hairy nil
1143 "Variables affected by `cperl-hairy'."
1144 :prefix "cperl-"
1145 :group 'cperl)
1146
1147(defgroup cperl-autoinsert-details nil
1148 "Auto-insert tuneup."
1149 :prefix "cperl-"
1150 :group 'cperl)
1151
1152(defgroup cperl-faces nil
1153 "Fontification colors."
1154 :prefix "cperl-"
1155 :group 'cperl)
1156
1157(defgroup cperl-speed nil
1158 "Speed vs. validity tuneup."
1159 :prefix "cperl-"
1160 :group 'cperl)
1161
1162(defgroup cperl-help-system nil
1163 "Help system tuneup."
1164 :prefix "cperl-"
1165 :group 'cperl)
1166
1167\f
1168(defcustom cperl-extra-newline-before-brace nil
4633a7c4
LW
1169 "*Non-nil means that if, elsif, while, until, else, for, foreach
1170and do constructs look like:
1171
1172 if ()
1173 {
1174 }
1175
1176instead of:
1177
1178 if () {
1179 }
6c72d195
IZ
1180"
1181 :type 'boolean
1182 :group 'cperl-autoinsert-details)
1183
1184(defcustom cperl-extra-newline-before-brace-multiline
1185 cperl-extra-newline-before-brace
1186 "*Non-nil means the same as `cperl-extra-newline-before-brace', but
1187for constructs with multiline if/unless/while/until/for/foreach condition."
1188 :type 'boolean
1189 :group 'cperl-autoinsert-details)
1190
1191(defcustom cperl-indent-level 2
1192 "*Indentation of CPerl statements with respect to containing block."
1193 :type 'integer
1194 :group 'cperl-indentation-details)
1195
1196(defcustom cperl-lineup-step nil
4633a7c4 1197 "*`cperl-lineup' will always lineup at multiple of this number.
6c72d195
IZ
1198If `nil', the value of `cperl-indent-level' will be used."
1199 :type '(choice (const nil) integer)
1200 :group 'cperl-indentation-details)
1201
1202(defcustom cperl-brace-imaginary-offset 0
4633a7c4
LW
1203 "*Imagined indentation of a Perl open brace that actually follows a statement.
1204An open brace following other text is treated as if it were this far
6c72d195
IZ
1205to the right of the start of its line."
1206 :type 'integer
1207 :group 'cperl-indentation-details)
1208
1209(defcustom cperl-brace-offset 0
1210 "*Extra indentation for braces, compared with other text in same context."
1211 :type 'integer
1212 :group 'cperl-indentation-details)
1213(defcustom cperl-label-offset -2
1214 "*Offset of CPerl label lines relative to usual indentation."
1215 :type 'integer
1216 :group 'cperl-indentation-details)
1217(defcustom cperl-min-label-indent 1
1218 "*Minimal offset of CPerl label lines."
1219 :type 'integer
1220 :group 'cperl-indentation-details)
1221(defcustom cperl-continued-statement-offset 2
1222 "*Extra indent for lines not starting new statements."
1223 :type 'integer
1224 :group 'cperl-indentation-details)
1225(defcustom cperl-continued-brace-offset 0
4633a7c4 1226 "*Extra indent for substatements that start with open-braces.
6c72d195
IZ
1227This is in addition to cperl-continued-statement-offset."
1228 :type 'integer
1229 :group 'cperl-indentation-details)
1230(defcustom cperl-close-paren-offset -1
1231 "*Extra indent for substatements that start with close-parenthesis."
1232 :type 'integer
1233 :group 'cperl-indentation-details)
1234
1235(defcustom cperl-auto-newline nil
4633a7c4 1236 "*Non-nil means automatically newline before and after braces,
6c72d195 1237and after colons and semicolons, inserted in CPerl code. The following
9ea28adb 1238\\[cperl-electric-backspace] will remove the inserted whitespace.
1239Insertion after colons requires both this variable and
6c72d195
IZ
1240`cperl-auto-newline-after-colon' set."
1241 :type 'boolean
1242 :group 'cperl-autoinsert-details)
9ea28adb 1243
7bcea553
IZ
1244(defcustom cperl-autoindent-on-semi nil
1245 "*Non-nil means automatically indent after insertion of (semi)colon.
1246Active if `cperl-auto-newline' is false."
1247 :type 'boolean
1248 :group 'cperl-autoinsert-details)
1249
6c72d195 1250(defcustom cperl-auto-newline-after-colon nil
9ea28adb 1251 "*Non-nil means automatically newline even after colons.
6c72d195
IZ
1252Subject to `cperl-auto-newline' setting."
1253 :type 'boolean
1254 :group 'cperl-autoinsert-details)
4633a7c4 1255
6c72d195 1256(defcustom cperl-tab-always-indent t
4633a7c4 1257 "*Non-nil means TAB in CPerl mode should always reindent the current line,
6c72d195
IZ
1258regardless of where in the line point is when the TAB command is used."
1259 :type 'boolean
1260 :group 'cperl-indentation-details)
4633a7c4 1261
6c72d195 1262(defcustom cperl-font-lock nil
4633a7c4 1263 "*Non-nil (and non-null) means CPerl buffers will use font-lock-mode.
6c72d195
IZ
1264Can be overwritten by `cperl-hairy' if nil."
1265 :type '(choice (const null) boolean)
1266 :group 'cperl-affected-by-hairy)
4633a7c4 1267
6c72d195 1268(defcustom cperl-electric-lbrace-space nil
ebcd4dbc 1269 "*Non-nil (and non-null) means { after $ in CPerl buffers should be preceded by ` '.
6c72d195
IZ
1270Can be overwritten by `cperl-hairy' if nil."
1271 :type '(choice (const null) boolean)
1272 :group 'cperl-affected-by-hairy)
4633a7c4 1273
6c72d195 1274(defcustom cperl-electric-parens-string "({[]})<"
05bbd9c3 1275 "*String of parentheses that should be electric in CPerl.
6c72d195
IZ
1276Closing ones are electric only if the region is highlighted."
1277 :type 'string
1278 :group 'cperl-affected-by-hairy)
9ea28adb 1279
6c72d195 1280(defcustom cperl-electric-parens nil
9ea28adb 1281 "*Non-nil (and non-null) means parentheses should be electric in CPerl.
6c72d195
IZ
1282Can be overwritten by `cperl-hairy' if nil."
1283 :type '(choice (const null) boolean)
1284 :group 'cperl-affected-by-hairy)
1285
1286(defvar zmacs-regions) ; Avoid warning
1287
1288(defcustom cperl-electric-parens-mark
9ea28adb 1289 (and window-system
1290 (or (and (boundp 'transient-mark-mode) ; For Emacs
1291 transient-mark-mode)
1292 (and (boundp 'zmacs-regions) ; For XEmacs
1293 zmacs-regions)))
1294 "*Not-nil means that electric parens look for active mark.
6c72d195
IZ
1295Default is yes if there is visual feedback on mark."
1296 :type 'boolean
1297 :group 'cperl-autoinsert-details)
9ea28adb 1298
6c72d195 1299(defcustom cperl-electric-linefeed nil
4633a7c4
LW
1300 "*If true, LFD should be hairy in CPerl, otherwise C-c LFD is hairy.
1301In any case these two mean plain and hairy linefeeds together.
6c72d195
IZ
1302Can be overwritten by `cperl-hairy' if nil."
1303 :type '(choice (const null) boolean)
1304 :group 'cperl-affected-by-hairy)
4633a7c4 1305
6c72d195 1306(defcustom cperl-electric-keywords nil
4633a7c4 1307 "*Not-nil (and non-null) means keywords are electric in CPerl.
6c72d195
IZ
1308Can be overwritten by `cperl-hairy' if nil."
1309 :type '(choice (const null) boolean)
1310 :group 'cperl-affected-by-hairy)
1311
1312(defcustom cperl-hairy nil
1313 "*Not-nil means most of the bells and whistles are enabled in CPerl.
1314Affects: `cperl-font-lock', `cperl-electric-lbrace-space',
1315`cperl-electric-parens', `cperl-electric-linefeed', `cperl-electric-keywords',
1316`cperl-info-on-command-no-prompt', `cperl-clobber-lisp-bindings',
1317`cperl-lazy-help-time'."
1318 :type 'boolean
1319 :group 'cperl-affected-by-hairy)
1320
1321(defcustom cperl-comment-column 32
1322 "*Column to put comments in CPerl (use \\[cperl-indent] to lineup with code)."
1323 :type 'integer
1324 :group 'cperl-indentation-details)
1325
1326(defcustom cperl-vc-header-alist '((SCCS "$sccs = '%W\%' ;")
1327 (RCS "$rcs = ' $Id\$ ' ;"))
1328 "*What to use as `vc-header-alist' in CPerl."
1329 :type '(repeat (list symbol string))
1330 :group 'cperl)
1331
20675f5d
IZ
1332(defcustom cperl-clobber-mode-lists
1333 (not
1334 (and
1335 (boundp 'interpreter-mode-alist)
1336 (assoc "miniperl" interpreter-mode-alist)
1337 (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist)))
1338 "*Whether to install us into `interpreter-' and `extension' mode lists."
1339 :type 'boolean
1340 :group 'cperl)
1341
6c72d195 1342(defcustom cperl-info-on-command-no-prompt nil
4633a7c4
LW
1343 "*Not-nil (and non-null) means not to prompt on C-h f.
1344The opposite behaviour is always available if prefixed with C-c.
6c72d195
IZ
1345Can be overwritten by `cperl-hairy' if nil."
1346 :type '(choice (const null) boolean)
1347 :group 'cperl-affected-by-hairy)
1348
1349(defcustom cperl-clobber-lisp-bindings nil
1350 "*Not-nil (and non-null) means not overwrite C-h f.
1351The function is available on \\[cperl-info-on-command], \\[cperl-get-help].
1352Can be overwritten by `cperl-hairy' if nil."
1353 :type '(choice (const null) boolean)
1354 :group 'cperl-affected-by-hairy)
1355
1356(defcustom cperl-lazy-help-time nil
1357 "*Not-nil (and non-null) means to show lazy help after given idle time.
1358Can be overwritten by `cperl-hairy' to be 5 sec if nil."
7bcea553 1359 :type '(choice (const null) (const nil) integer)
6c72d195
IZ
1360 :group 'cperl-affected-by-hairy)
1361
1362(defcustom cperl-pod-face 'font-lock-comment-face
1363 "*The result of evaluation of this expression is used for pod highlighting."
1364 :type 'face
1365 :group 'cperl-faces)
1366
1367(defcustom cperl-pod-head-face 'font-lock-variable-name-face
c07a80fd 1368 "*The result of evaluation of this expression is used for pod highlighting.
6c72d195
IZ
1369Font for POD headers."
1370 :type 'face
1371 :group 'cperl-faces)
c07a80fd 1372
6c72d195
IZ
1373(defcustom cperl-here-face 'font-lock-string-face
1374 "*The result of evaluation of this expression is used for here-docs highlighting."
1375 :type 'face
1376 :group 'cperl-faces)
c07a80fd 1377
4584684c
GS
1378(defcustom cperl-invalid-face ''underline ; later evaluated by `font-lock'
1379 "*The result of evaluation of this expression highlights trailing whitespace."
1380 :type 'face
1381 :group 'cperl-faces)
1382
6c72d195
IZ
1383(defcustom cperl-pod-here-fontify '(featurep 'font-lock)
1384 "*Not-nil after evaluation means to highlight pod and here-docs sections."
1385 :type 'boolean
1386 :group 'cperl-faces)
c07a80fd 1387
20675f5d
IZ
1388(defcustom cperl-fontify-m-as-s t
1389 "*Not-nil means highlight 1arg regular expressions operators same as 2arg."
1390 :type 'boolean
1391 :group 'cperl-faces)
1392
7bcea553
IZ
1393(defcustom cperl-highlight-variables-indiscriminately nil
1394 "*Not-nil means perform additional hightlighting on variables.
1395Currently only changes how scalar variables are hightlighted.
1396Note that that variable is only read at initialization time for
1397the variable perl-font-lock-keywords-2, so changing it after you've
1398entered cperl-mode the first time will have no effect."
1399 :type 'boolean
1400 :group 'cperl)
1401
6c72d195 1402(defcustom cperl-pod-here-scan t
c07a80fd 1403 "*Not-nil means look for pod and here-docs sections during startup.
6c72d195
IZ
1404You can always make lookup from menu or using \\[cperl-find-pods-heres]."
1405 :type 'boolean
1406 :group 'cperl-speed)
c07a80fd 1407
7bcea553
IZ
1408(defcustom cperl-regexp-scan t
1409 "*Not-nil means make marking of regular expression more thorough.
1410Effective only with `cperl-pod-here-scan'. Not implemented yet."
1411 :type 'boolean
1412 :group 'cperl-speed)
1413
6c72d195 1414(defcustom cperl-imenu-addback nil
9ea28adb 1415 "*Not-nil means add backreferences to generated `imenu's.
6c72d195
IZ
1416May require patched `imenu' and `imenu-go'. Obsolete."
1417 :type 'boolean
1418 :group 'cperl-help-system)
9ea28adb 1419
6c72d195
IZ
1420(defcustom cperl-max-help-size 66
1421 "*Non-nil means shrink-wrapping of info-buffer allowed up to these percents."
1422 :type '(choice integer (const nil))
1423 :group 'cperl-help-system)
5f05dabc 1424
6c72d195
IZ
1425(defcustom cperl-shrink-wrap-info-frame t
1426 "*Non-nil means shrink-wrapping of info-buffer-frame allowed."
1427 :type 'boolean
1428 :group 'cperl-help-system)
5f05dabc 1429
6c72d195 1430(defcustom cperl-info-page "perl"
ebcd4dbc 1431 "*Name of the info page containing perl docs.
6c72d195
IZ
1432Older version of this page was called `perl5', newer `perl'."
1433 :type 'string
1434 :group 'cperl-help-system)
499d5216 1435
6c72d195 1436(defcustom cperl-use-syntax-table-text-property
05bbd9c3 1437 (boundp 'parse-sexp-lookup-properties)
6c72d195
IZ
1438 "*Non-nil means CPerl sets up and uses `syntax-table' text property."
1439 :type 'boolean
1440 :group 'cperl-speed)
ebcd4dbc 1441
6c72d195 1442(defcustom cperl-use-syntax-table-text-property-for-tags
05bbd9c3 1443 cperl-use-syntax-table-text-property
6c72d195
IZ
1444 "*Non-nil means: set up and use `syntax-table' text property generating TAGS."
1445 :type 'boolean
1446 :group 'cperl-speed)
1447
1448(defcustom cperl-scan-files-regexp "\\.\\([pP][Llm]\\|xs\\)$"
1449 "*Regexp to match files to scan when generating TAGS."
1450 :type 'regexp
1451 :group 'cperl)
1452
1453(defcustom cperl-noscan-files-regexp "/\\(\\.\\.?\\|SCCS\\|RCS\\|blib\\)$"
1454 "*Regexp to match files/dirs to skip when generating TAGS."
1455 :type 'regexp
1456 :group 'cperl)
1457
1458(defcustom cperl-regexp-indent-step nil
1459 "*Indentation used when beautifying regexps.
1460If `nil', the value of `cperl-indent-level' will be used."
1461 :type '(choice integer (const nil))
1462 :group 'cperl-indentation-details)
1463
1464(defcustom cperl-indent-left-aligned-comments t
1465 "*Non-nil means that the comment starting in leftmost column should indent."
1466 :type 'boolean
1467 :group 'cperl-indentation-details)
1468
1469(defcustom cperl-under-as-char t
1470 "*Non-nil means that the _ (underline) should be treated as word char."
1471 :type 'boolean
1472 :group 'cperl)
1473
1474(defcustom cperl-extra-perl-args ""
1475 "*Extra arguments to use when starting Perl.
1476Currently used with `cperl-check-syntax' only."
1477 :type 'string
1478 :group 'cperl)
1479
1480(defcustom cperl-message-electric-keyword t
1481 "*Non-nil means that the `cperl-electric-keyword' prints a help message."
1482 :type 'boolean
1483 :group 'cperl-help-system)
1484
1485(defcustom cperl-indent-region-fix-constructs 1
1486 "*Amount of space to insert between `}' and `else' or `elsif'
1487in `cperl-indent-region'. Set to nil to leave as is. Values other
1488than 1 and nil will probably not work."
1489 :type '(choice (const nil) (const 1))
1490 :group 'cperl-indentation-details)
1491
1492(defcustom cperl-break-one-line-blocks-when-indent t
1493 "*Non-nil means that one-line if/unless/while/until/for/foreach BLOCKs
1494need to be reformated into multiline ones when indenting a region."
1495 :type 'boolean
1496 :group 'cperl-indentation-details)
1497
1498(defcustom cperl-fix-hanging-brace-when-indent t
1499 "*Non-nil means that BLOCK-end `}' may be put on a separate line
1500when indenting a region.
1501Braces followed by else/elsif/while/until are excepted."
1502 :type 'boolean
1503 :group 'cperl-indentation-details)
1504
1505(defcustom cperl-merge-trailing-else t
1506 "*Non-nil means that BLOCK-end `}' followed by else/elsif/continue
1507may be merged to be on the same line when indenting a region."
1508 :type 'boolean
1509 :group 'cperl-indentation-details)
1510
7bcea553
IZ
1511(defcustom cperl-indent-parens-as-block nil
1512 "*Non-nil means that non-block ()-, {}- and []-groups are indented as blocks,
1513but for trailing \",\" inside the group, which won't increase indentation.
1514One should tune up `cperl-close-paren-offset' as well."
1515 :type 'boolean
1516 :group 'cperl-indentation-details)
1517
6c72d195 1518(defcustom cperl-syntaxify-by-font-lock
4584684c
GS
1519 (and window-system
1520 (boundp 'parse-sexp-lookup-properties))
7bcea553 1521 "*Non-nil means that CPerl uses `font-lock's routines for syntaxification."
6c72d195
IZ
1522 :type '(choice (const message) boolean)
1523 :group 'cperl-speed)
05bbd9c3 1524
20675f5d
IZ
1525(defcustom cperl-syntaxify-unwind
1526 t
1527 "*Non-nil means that CPerl unwinds to a start of along construction
1528when syntaxifying a chunk of buffer."
1529 :type 'boolean
1530 :group 'cperl-speed)
1531
4584684c
GS
1532(defcustom cperl-ps-print-face-properties
1533 '((font-lock-keyword-face nil nil bold shadow)
1534 (font-lock-variable-name-face nil nil bold)
1535 (font-lock-function-name-face nil nil bold italic box)
1536 (font-lock-constant-face nil "LightGray" bold)
1537 (cperl-array-face nil "LightGray" bold underline)
1538 (cperl-hash-face nil "LightGray" bold italic underline)
1539 (font-lock-comment-face nil "LightGray" italic)
1540 (font-lock-string-face nil nil italic underline)
1541 (cperl-nonoverridable-face nil nil italic underline)
1542 (font-lock-type-face nil nil underline)
1543 (underline nil "LightGray" strikeout))
1544 "List given as an argument to `ps-extend-face-list' in `cperl-ps-print'."
1545 :type '(repeat (cons symbol
1546 (cons (choice (const nil) string)
1547 (cons (choice (const nil) string)
1548 (repeat symbol)))))
1549 :group 'cperl-faces)
1550
6c72d195
IZ
1551(if window-system
1552 (progn
1553 (defvar cperl-dark-background
1554 (cperl-choose-color "navy" "os2blue" "darkgreen"))
20675f5d
IZ
1555 (defvar cperl-dark-foreground
1556 (cperl-choose-color "orchid1" "orange"))
1557
4584684c 1558 (defface cperl-nonoverridable-face
20675f5d
IZ
1559 (` ((((class grayscale) (background light))
1560 (:background "Gray90" :italic t :underline t))
1561 (((class grayscale) (background dark))
1562 (:foreground "Gray80" :italic t :underline t :bold t))
1563 (((class color) (background light))
1564 (:foreground "chartreuse3"))
1565 (((class color) (background dark))
1566 (:foreground (, cperl-dark-foreground)))
1567 (t (:bold t :underline t))))
1568 "Font Lock mode face used to highlight array names."
1569 :group 'cperl-faces)
6c72d195
IZ
1570
1571 (defface cperl-array-face
1572 (` ((((class grayscale) (background light))
1573 (:background "Gray90" :bold t))
1574 (((class grayscale) (background dark))
1575 (:foreground "Gray80" :bold t))
1576 (((class color) (background light))
1577 (:foreground "Blue" :background "lightyellow2" :bold t))
1578 (((class color) (background dark))
1579 (:foreground "yellow" :background (, cperl-dark-background) :bold t))
1580 (t (:bold t))))
1581 "Font Lock mode face used to highlight array names."
1582 :group 'cperl-faces)
1583
1584 (defface cperl-hash-face
1585 (` ((((class grayscale) (background light))
1586 (:background "Gray90" :bold t :italic t))
1587 (((class grayscale) (background dark))
1588 (:foreground "Gray80" :bold t :italic t))
1589 (((class color) (background light))
1590 (:foreground "Red" :background "lightyellow2" :bold t :italic t))
1591 (((class color) (background dark))
1592 (:foreground "Red" :background (, cperl-dark-background) :bold t :italic t))
1593 (t (:bold t :italic t))))
1594 "Font Lock mode face used to highlight hash names."
1595 :group 'cperl-faces)))
05bbd9c3 1596
c07a80fd 1597\f
1598
1599;;; Short extra-docs.
1600
1601(defvar cperl-tips 'please-ignore-this-line
1602 "Get newest version of this package from
29043b61 1603 ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs
c07a80fd 1604and/or
1605 ftp://ftp.math.ohio-state.edu/pub/users/ilya/perl
6c72d195
IZ
1606Subdirectory `cperl-mode' may contain yet newer development releases and/or
1607patches to related files.
c07a80fd 1608
4584684c
GS
1609For best results apply to an older Emacs the patches from
1610 ftp://ftp.math.ohio-state.edu/pub/users/ilya/cperl-mode/patches
1611\(this upgrades syntax-parsing abilities of RMS Emaxen v19.34 and
1612v20.2 up to the level of RMS Emacs v20.3 - a must for a good Perl
022735b4 1613mode.) You will not get much from XEmacs; its syntax abilities are
4584684c
GS
1614too primitive.
1615
9ea28adb 1616Get support packages choose-color.el (or font-lock-extra.el before
161719.30), imenu-go.el from the same place. \(Look for other files there
6c72d195 1618too... ;-). Get a patch for imenu.el in 19.29. Note that for 19.30 and
9ea28adb 1619later you should use choose-color.el *instead* of font-lock-extra.el
1620\(and you will not get smart highlighting in C :-().
c07a80fd 1621
1622Note that to enable Compile choices in the menu you need to install
29043b61 1623mode-compile.el.
c07a80fd 1624
7bcea553
IZ
1625If your Emacs does not default to `cperl-mode' on Perl files, and you
1626want it to: put the following into your .emacs file:
1627
1628(autoload 'perl-mode \"cperl-mode\" \"alternate mode for editing Perl programs\" t)
1629
c07a80fd 1630Get perl5-info from
499d5216
IZ
1631 $CPAN/doc/manual/info/perl-info.tar.gz
1632older version was on
c07a80fd 1633 http://www.metronet.com:70/9/perlinfo/perl5/manual/perl5-info.tar.gz
c07a80fd 1634
9ea28adb 1635If you use imenu-go, run imenu on perl5-info buffer (you can do it
4584684c
GS
1636from Perl menu). If many files are related, generate TAGS files from
1637Tools/Tags submenu in Perl menu.
9ea28adb 1638
1639If some class structure is too complicated, use Tools/Hierarchy-view
4584684c 1640from Perl menu, or hierarchic view of imenu. The second one uses the
499d5216 1641current buffer only, the first one requires generation of TAGS from
4584684c
GS
1642Perl/Tools/Tags menu beforehand.
1643
1644Run Perl/Tools/Insert-spaces-if-needed to fix your lazy typing.
1645
1646Switch auto-help on/off with Perl/Tools/Auto-help.
c07a80fd 1647
4584684c
GS
1648Though with contemporary Emaxen CPerl mode should maintain the correct
1649parsing of Perl even when editing, sometimes it may be lost. Fix this by
499d5216 1650
4584684c 1651 M-x norm RET
55497cff 1652
7bcea553
IZ
1653In cases of more severe confusion sometimes it is helpful to do
1654
1655 M-x load-l RET cperl-mode RET
1656 M-x norm RET
1657
4584684c
GS
1658Before reporting (non-)problems look in the problem section of online
1659micro-docs on what I know about CPerl problems.")
c07a80fd 1660
1661(defvar cperl-problems 'please-ignore-this-line
6c72d195
IZ
1662"Some faces will not be shown on some versions of Emacs unless you
1663install choose-color.el, available from
1664 ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs/
1665
7bcea553
IZ
1666`fill-paragraph' on a comment may leave the point behind the
1667paragraph. Parsing of lines with several <<EOF is not implemented
1668yet.
1669
6c72d195
IZ
1670Emacs had a _very_ restricted syntax parsing engine until RMS's Emacs
167120.1. Most problems below are corrected starting from this version of
7bcea553
IZ
1672Emacs, and all of them should go with RMS's version 20.3. (Or apply
1673patches to Emacs 19.33/34 - see tips.) XEmacs is very backward in
1674this respect.
6c72d195 1675
7bcea553
IZ
1676Note that even with newer Emacsen in some very rare cases the details
1677of interaction of `font-lock' and syntaxification may be not cleaned
1678up yet. You may get slightly different colors basing on the order of
1679fontification and syntaxification. Say, the initial faces is correct,
1680but editing the buffer breaks this.
6c72d195
IZ
1681
1682Even with older Emacsen CPerl mode tries to corrects some Emacs
1683misunderstandings, however, for efficiency reasons the degree of
1684correction is different for different operations. The partially
1685corrected problems are: POD sections, here-documents, regexps. The
1686operations are: highlighting, indentation, electric keywords, electric
1687braces.
c07a80fd 1688
1689This may be confusing, since the regexp s#//#/#\; may be highlighted
55497cff 1690as a comment, but it will be recognized as a regexp by the indentation
6c72d195 1691code. Or the opposite case, when a pod section is highlighted, but
ebcd4dbc
IZ
1692may break the indentation of the following code (though indentation
1693should work if the balance of delimiters is not broken by POD).
c07a80fd 1694
1695The main trick (to make $ a \"backslash\") makes constructions like
6c72d195 1696${aaa} look like unbalanced braces. The only trick I can think of is
c07a80fd 1697to insert it as $ {aaa} (legal in perl5, not in perl4).
1698
1699Similar problems arise in regexps, when /(\\s|$)/ should be rewritten
6c72d195
IZ
1700as /($|\\s)/. Note that such a transposition is not always possible.
1701
4584684c
GS
1702The solution is to upgrade your Emacs or patch an older one. Note
1703that RMS's 20.2 has some bugs related to `syntax-table' text
1704properties. Patches are available on the main CPerl download site,
1705and on CPAN.
6c72d195
IZ
1706
1707If these bugs cannot be fixed on your machine (say, you have an inferior
1708environment and cannot recompile), you may still disable all the fancy stuff
1709via `cperl-use-syntax-table-text-property'." )
c07a80fd 1710
1711(defvar cperl-non-problems 'please-ignore-this-line
6c72d195 1712"As you know from `problems' section, Perl syntax is too hard for CPerl on
4584684c
GS
1713older Emacsen. Here is what you can do if you cannot upgrade, or if
1714you want to switch off these capabilities on RMS Emacs 20.2 (+patches) or 20.3
1715or better. Please skip this docs if you run a capable Emacs already.
c07a80fd 1716
6c72d195
IZ
1717Most of the time, if you write your own code, you may find an equivalent
1718\(and almost as readable) expression (what is discussed below is usually
1719not relevant on newer Emacsen, since they can do it automatically).
c07a80fd 1720
ebcd4dbc 1721Try to help CPerl: add comments with embedded quotes to fix CPerl
c07a80fd 1722misunderstandings about the end of quotation:
1723
1724$a='500$'; # ';
1725
6c72d195 1726You won't need it too often. The reason: $ \"quotes\" the following
c07a80fd 1727character (this saves a life a lot of times in CPerl), thus due to
ebcd4dbc 1728Emacs parsing rules it does not consider tick (i.e., ' ) after a
6c72d195
IZ
1729dollar as a closing one, but as a usual character. This is usually
1730correct, but not in the above context.
c07a80fd 1731
6c72d195
IZ
1732Even with older Emacsen the indentation code is pretty wise. The only
1733drawback is that it relied on Emacs parsing to find matching
1734parentheses. And Emacs *could not* match parentheses in Perl 100%
1735correctly. So
c07a80fd 1736 1 if s#//#/#;
6c72d195 1737would not break indentation, but
c07a80fd 1738 1 if ( s#//#/# );
6c72d195 1739would. Upgrade.
c07a80fd 1740
5f05dabc 1741By similar reasons
1742 s\"abc\"def\";
7bcea553 1743could confuse CPerl a lot.
5f05dabc 1744
c07a80fd 1745If you still get wrong indentation in situation that you think the
1746code should be able to parse, try:
1747
1748a) Check what Emacs thinks about balance of your parentheses.
1749b) Supply the code to me (IZ).
1750
6c72d195
IZ
1751Pods were treated _very_ rudimentally. Here-documents were not
1752treated at all (except highlighting and inhibiting indentation). Upgrade.
c07a80fd 1753
1754To speed up coloring the following compromises exist:
1755 a) sub in $mypackage::sub may be highlighted.
1756 b) -z in [a-z] may be highlighted.
1757 c) if your regexp contains a keyword (like \"s\"), it may be highlighted.
9ea28adb 1758
1759
6c72d195 1760Imenu in 19.31 is broken. Set `imenu-use-keymap-menu' to t, and remove
9ea28adb 1761`car' before `imenu-choose-buffer-index' in `imenu'.
6c72d195
IZ
1762`imenu-add-to-menubar' in 20.2 is broken.
1763A lot of things on XEmacs may be broken too, judging by bug reports I
7bcea553 1764receive. Note that some releases of XEmacs are better than the others
6c72d195 1765as far as bugs reports I see are concerned.")
c07a80fd 1766
ebcd4dbc 1767(defvar cperl-praise 'please-ignore-this-line
6c72d195 1768 "RMS asked me to list good things about CPerl. Here they go:
ebcd4dbc
IZ
1769
17700) It uses the newest `syntax-table' property ;-);
1771
17721) It does 99% of Perl syntax correct (as opposed to 80-90% in Perl
1773mode - but the latter number may have improved too in last years) even
4584684c
GS
1774with old Emaxen which do not support `syntax-table' property.
1775
1776When using `syntax-table' property for syntax assist hints, it should
1777handle 99.995% of lines correct - or somesuch. It automatically
1778updates syntax assist hints when you edit your script.
ebcd4dbc 1779
6c72d195 17802) It is generally believed to be \"the most user-friendly Emacs
ebcd4dbc
IZ
1781package\" whatever it may mean (I doubt that the people who say similar
1782things tried _all_ the rest of Emacs ;-), but this was not a lonely
1783voice);
1784
17853) Everything is customizable, one-by-one or in a big sweep;
1786
17874) It has many easily-accessable \"tools\":
1788 a) Can run program, check syntax, start debugger;
1789 b) Can lineup vertically \"middles\" of rows, like `=' in
1790 a = b;
1791 cc = d;
1792 c) Can insert spaces where this impoves readability (in one
1793 interactive sweep over the buffer);
1794 d) Has support for imenu, including:
1795 1) Separate unordered list of \"interesting places\";
1796 2) Separate TOC of POD sections;
1797 3) Separate list of packages;
1798 4) Hierarchical view of methods in (sub)packages;
1799 5) and functions (by the full name - with package);
1800 e) Has an interface to INFO docs for Perl; The interface is
1801 very flexible, including shrink-wrapping of
1802 documentation buffer/frame;
1803 f) Has a builtin list of one-line explanations for perl constructs.
1804 g) Can show these explanations if you stay long enough at the
1805 corresponding place (or on demand);
1806 h) Has an enhanced fontification (using 3 or 4 additional faces
1807 comparing to font-lock - basically, different
1808 namespaces in Perl have different colors);
1809 i) Can construct TAGS basing on its knowledge of Perl syntax,
1810 the standard menu has 6 different way to generate
6c72d195 1811 TAGS (if \"by directory\", .xs files - with C-language
ebcd4dbc
IZ
1812 bindings - are included in the scan);
1813 j) Can build a hierarchical view of classes (via imenu) basing
1814 on generated TAGS file;
1815 k) Has electric parentheses, electric newlines, uses Abbrev
1816 for electric logical constructs
1817 while () {}
1818 with different styles of expansion (context sensitive
6c72d195 1819 to be not so bothering). Electric parentheses behave
ebcd4dbc
IZ
1820 \"as they should\" in a presence of a visible region.
1821 l) Changes msb.el \"on the fly\" to insert a group \"Perl files\";
6c72d195
IZ
1822 m) Can convert from
1823 if (A) { B }
1824 to
1825 B if A;
ebcd4dbc 1826
20675f5d 1827 n) Highlights (by user-choice) either 3-delimiters constructs
7bcea553
IZ
1828 (such as tr/a/b/), or regular expressions and `y/tr';
1829 o) Highlights trailing whitespace;
1830 p) Is able to manipulate Perl Regular Expressions to ease
1831 conversion to a more readable form.
20675f5d 1832
ebcd4dbc 18335) The indentation engine was very smart, but most of tricks may be
6c72d195 1834not needed anymore with the support for `syntax-table' property. Has
ebcd4dbc
IZ
1835progress indicator for indentation (with `imenu' loaded).
1836
6c72d195
IZ
18376) Indent-region improves inline-comments as well; also corrects
1838whitespace *inside* the conditional/loop constructs.
ebcd4dbc
IZ
1839
18407) Fill-paragraph correctly handles multi-line comments;
6c72d195
IZ
1841
18428) Can switch to different indentation styles by one command, and restore
1843the settings present before the switch.
1844
18459) When doing indentation of control constructs, may correct
1846line-breaks/spacing between elements of the construct.
7bcea553
IZ
1847
184810) Uses a linear-time algorith for indentation of regions (on Emaxen with
1849capable syntax engines).
6c72d195
IZ
1850")
1851
1852(defvar cperl-speed 'please-ignore-this-line
1853 "This is an incomplete compendium of what is available in other parts
1854of CPerl documentation. (Please inform me if I skept anything.)
1855
1856There is a perception that CPerl is slower than alternatives. This part
1857of documentation is designed to overcome this misconception.
1858
1859*By default* CPerl tries to enable the most comfortable settings.
1860From most points of view, correctly working package is infinitely more
1861comfortable than a non-correctly working one, thus by default CPerl
1862prefers correctness over speed. Below is the guide how to change
1863settings if your preferences are different.
1864
1865A) Speed of loading the file. When loading file, CPerl may perform a
1866scan which indicates places which cannot be parsed by primitive Emacs
1867syntax-parsing routines, and marks them up so that either
1868
1869 A1) CPerl may work around these deficiencies (for big chunks, mostly
1870 PODs and HERE-documents), or
1871 A2) On capable Emaxen CPerl will use improved syntax-handlings
1872 which reads mark-up hints directly.
1873
1874 The scan in case A2 is much more comprehensive, thus may be slower.
1875
1876 User can disable syntax-engine-helping scan of A2 by setting
1877 `cperl-use-syntax-table-text-property'
1878 variable to nil (if it is set to t).
1879
1880 One can disable the scan altogether (both A1 and A2) by setting
1881 `cperl-pod-here-scan'
1882 to nil.
1883
1884B) Speed of editing operations.
1885
1886 One can add a (minor) speedup to editing operations by setting
1887 `cperl-use-syntax-table-text-property'
1888 variable to nil (if it is set to t). This will disable
1889 syntax-engine-helping scan, thus will make many more Perl
1890 constructs be wrongly recognized by CPerl, thus may lead to
1891 wrongly matched parentheses, wrong indentation, etc.
20675f5d
IZ
1892
1893 One can unset `cperl-syntaxify-unwind'. This might speed up editing
1894 of, say, long POD sections.
ebcd4dbc
IZ
1895")
1896
4584684c
GS
1897(defvar cperl-tips-faces 'please-ignore-this-line
1898 "CPerl mode uses following faces for highlighting:
1899
1900 cperl-array-face Array names
1901 cperl-hash-face Hash names
1902 font-lock-comment-face Comments, PODs and whatever is considered
1903 syntaxically to be not code
1904 font-lock-constant-face HERE-doc delimiters, labels, delimiters of
1905 2-arg operators s/y/tr/ or of RExen,
1906 font-lock-function-name-face Special-cased m// and s//foo/, _ as
1907 a target of a file tests, file tests,
1908 subroutine names at the moment of definition
1909 (except those conflicting with Perl operators),
1910 package names (when recognized), format names
1911 font-lock-keyword-face Control flow switch constructs, declarators
1912 cperl-nonoverridable-face Non-overridable keywords, modifiers of RExen
1913 font-lock-string-face Strings, qw() constructs, RExen, POD sections,
1914 literal parts and the terminator of formats
1915 and whatever is syntaxically considered
1916 as string literals
1917 font-lock-type-face Overridable keywords
1918 font-lock-variable-name-face Variable declarations, indirect array and
1919 hash names, POD headers/item names
1920 cperl-invalid-face Trailing whitespace
1921
1922Note that in several situations the highlighting tries to inform about
1923possible confusion, such as different colors for function names in
1924declarations depending on what they (do not) override, or special cases
1925m// and s/// which do not do what one would expect them to do.
1926
1927Help with best setup of these faces for printout requested (for each of
1928the faces: please specify bold, italic, underline, shadow and box.)
1929
1930\(Not finished.)")
1931
4633a7c4
LW
1932\f
1933
1934;;; Portability stuff:
1935
6c72d195
IZ
1936(defconst cperl-xemacs-p (string-match "XEmacs\\|Lucid" emacs-version))
1937
1938(defmacro cperl-define-key (emacs-key definition &optional xemacs-key)
ebcd4dbc
IZ
1939 (` (define-key cperl-mode-map
1940 (, (if xemacs-key
6c72d195
IZ
1941 (` (if cperl-xemacs-p (, xemacs-key) (, emacs-key)))
1942 emacs-key))
ebcd4dbc 1943 (, definition))))
4633a7c4 1944
6c72d195
IZ
1945(defvar cperl-del-back-ch
1946 (car (append (where-is-internal 'delete-backward-char)
1947 (where-is-internal 'backward-delete-char-untabify)))
4633a7c4
LW
1948 "Character generated by key bound to delete-backward-char.")
1949
6c72d195
IZ
1950(and (vectorp cperl-del-back-ch) (= (length cperl-del-back-ch) 1)
1951 (setq cperl-del-back-ch (aref cperl-del-back-ch 0)))
4633a7c4 1952
6c72d195 1953(defun cperl-mark-active () (mark)) ; Avoid undefined warning
55497cff 1954(if cperl-xemacs-p
9ea28adb 1955 (progn
1956 ;; "Active regions" are on: use region only if active
1957 ;; "Active regions" are off: use region unconditionally
1958 (defun cperl-use-region-p ()
6c72d195 1959 (if zmacs-regions (mark) t)))
4633a7c4 1960 (defun cperl-use-region-p ()
9ea28adb 1961 (if transient-mark-mode mark-active t))
1962 (defun cperl-mark-active () mark-active))
4633a7c4
LW
1963
1964(defsubst cperl-enable-font-lock ()
55497cff 1965 (or cperl-xemacs-p window-system))
4633a7c4 1966
6c72d195
IZ
1967(defun cperl-putback-char (c) ; Emacs 19
1968 (set 'unread-command-events (list c))) ; Avoid undefined warning
1969
4633a7c4 1970(if (boundp 'unread-command-events)
55497cff 1971 (if cperl-xemacs-p
4633a7c4 1972 (defun cperl-putback-char (c) ; XEmacs >= 19.12
6c72d195 1973 (setq unread-command-events (list (eval '(character-to-event c))))))
4633a7c4 1974 (defun cperl-putback-char (c) ; XEmacs <= 19.11
6c72d195 1975 (set 'unread-command-event (eval '(character-to-event c))))) ; Avoid warnings
4633a7c4
LW
1976
1977(or (fboundp 'uncomment-region)
1978 (defun uncomment-region (beg end)
1979 (interactive "r")
1980 (comment-region beg end -1)))
1981
29043b61 1982(defvar cperl-do-not-fontify
1983 (if (string< emacs-version "19.30")
1984 'fontified
1985 'lazy-lock)
1986 "Text property which inhibits refontification.")
1987
20675f5d
IZ
1988(defsubst cperl-put-do-not-fontify (from to &optional post)
1989 ;; If POST, do not do it with postponed fontification
1990 (if (and post cperl-syntaxify-by-font-lock)
1991 nil
1992 (put-text-property (max (point-min) (1- from))
1993 to cperl-do-not-fontify t)))
9ea28adb 1994
6c72d195
IZ
1995(defcustom cperl-mode-hook nil
1996 "Hook run by `cperl-mode'."
1997 :type 'hook
1998 :group 'cperl)
05bbd9c3 1999
6c72d195
IZ
2000(defvar cperl-syntax-state nil)
2001(defvar cperl-syntax-done-to nil)
2002(defvar cperl-emacs-can-parse (> (length (save-excursion
2003 (parse-partial-sexp 1 1))) 9))
2004\f
2005;; Make customization possible "in reverse"
2006(defsubst cperl-val (symbol &optional default hairy)
2007 (cond
2008 ((eq (symbol-value symbol) 'null) default)
2009 (cperl-hairy (or hairy t))
2010 (t (symbol-value symbol))))
29043b61 2011\f
4633a7c4
LW
2012;;; Probably it is too late to set these guys already, but it can help later:
2013
20675f5d
IZ
2014(and cperl-clobber-mode-lists
2015 (setq auto-mode-alist
05bbd9c3 2016 (append '(("\\.\\([pP][Llm]\\|al\\)$" . perl-mode)) auto-mode-alist ))
20675f5d
IZ
2017 (and (boundp 'interpreter-mode-alist)
2018 (setq interpreter-mode-alist (append interpreter-mode-alist
2019 '(("miniperl" . perl-mode))))))
4633a7c4
LW
2020(if (fboundp 'eval-when-compile)
2021 (eval-when-compile
2022 (condition-case nil
2023 (require 'imenu)
2024 (error nil))
2025 (condition-case nil
2026 (require 'easymenu)
2027 (error nil))
6c72d195
IZ
2028 (condition-case nil
2029 (require 'etags)
2030 (error nil))
2031 (condition-case nil
2032 (require 'timer)
2033 (error nil))
2034 (condition-case nil
2035 (require 'man)
2036 (error nil))
2037 (condition-case nil
2038 (require 'info)
2039 (error nil))
7bcea553
IZ
2040 (if (fboundp 'ps-extend-face-list)
2041 (defmacro cperl-ps-extend-face-list (arg)
2042 (` (ps-extend-face-list (, arg))))
2043 (defmacro cperl-ps-extend-face-list (arg)
2044 (` (error "This version of Emacs has no `ps-extend-face-list'."))))
4633a7c4
LW
2045 ;; Calling `cperl-enable-font-lock' below doesn't compile on XEmacs,
2046 ;; macros instead of defsubsts don't work on Emacs, so we do the
6c72d195 2047 ;; expansion manually. Any other suggestions?
4633a7c4
LW
2048 (if (or (string-match "XEmacs\\|Lucid" emacs-version)
2049 window-system)
2050 (require 'font-lock))
6c72d195 2051 (require 'cl)))
4633a7c4
LW
2052
2053(defvar cperl-mode-abbrev-table nil
2054 "Abbrev table in use in Cperl-mode buffers.")
2055
2056(add-hook 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-")))
2057
2058(defvar cperl-mode-map () "Keymap used in CPerl mode.")
2059
2060(if cperl-mode-map nil
2061 (setq cperl-mode-map (make-sparse-keymap))
55497cff 2062 (cperl-define-key "{" 'cperl-electric-lbrace)
2063 (cperl-define-key "[" 'cperl-electric-paren)
2064 (cperl-define-key "(" 'cperl-electric-paren)
2065 (cperl-define-key "<" 'cperl-electric-paren)
2066 (cperl-define-key "}" 'cperl-electric-brace)
2067 (cperl-define-key "]" 'cperl-electric-rparen)
2068 (cperl-define-key ")" 'cperl-electric-rparen)
2069 (cperl-define-key ";" 'cperl-electric-semi)
2070 (cperl-define-key ":" 'cperl-electric-terminator)
2071 (cperl-define-key "\C-j" 'newline-and-indent)
2072 (cperl-define-key "\C-c\C-j" 'cperl-linefeed)
6c72d195 2073 (cperl-define-key "\C-c\C-t" 'cperl-invert-if-unless)
55497cff 2074 (cperl-define-key "\C-c\C-a" 'cperl-toggle-auto-newline)
2075 (cperl-define-key "\C-c\C-k" 'cperl-toggle-abbrev)
6c72d195
IZ
2076 (cperl-define-key "\C-c\C-w" 'cperl-toggle-construct-fix)
2077 (cperl-define-key "\C-c\C-f" 'auto-fill-mode)
55497cff 2078 (cperl-define-key "\C-c\C-e" 'cperl-toggle-electric)
6c72d195 2079 (cperl-define-key "\C-c\C-ha" 'cperl-toggle-autohelp)
55497cff 2080 (cperl-define-key "\e\C-q" 'cperl-indent-exp) ; Usually not bound
05bbd9c3
IZ
2081 (cperl-define-key [?\C-\M-\|] 'cperl-lineup
2082 [(control meta |)])
55497cff 2083 ;;(cperl-define-key "\M-q" 'cperl-fill-paragraph)
2084 ;;(cperl-define-key "\e;" 'cperl-indent-for-comment)
2085 (cperl-define-key "\177" 'cperl-electric-backspace)
2086 (cperl-define-key "\t" 'cperl-indent-command)
2087 ;; don't clobber the backspace binding:
6c72d195
IZ
2088 (cperl-define-key "\C-c\C-hF" 'cperl-info-on-command
2089 [(control c) (control h) F])
6c72d195
IZ
2090 (if (cperl-val 'cperl-clobber-lisp-bindings)
2091 (progn
2092 (cperl-define-key "\C-hf"
2093 ;;(concat (char-to-string help-char) "f") ; does not work
2094 'cperl-info-on-command
2095 [(control h) f])
2096 (cperl-define-key "\C-hv"
2097 ;;(concat (char-to-string help-char) "v") ; does not work
2098 'cperl-get-help
20675f5d
IZ
2099 [(control h) v])
2100 (cperl-define-key "\C-c\C-hf"
2101 ;;(concat (char-to-string help-char) "f") ; does not work
2102 (key-binding "\C-hf")
2103 [(control c) (control h) f])
2104 (cperl-define-key "\C-c\C-hv"
2105 ;;(concat (char-to-string help-char) "v") ; does not work
2106 (key-binding "\C-hv")
2107 [(control c) (control h) v]))
2108 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-current-command
2109 [(control c) (control h) f])
2110 (cperl-define-key "\C-c\C-hv"
2111 ;;(concat (char-to-string help-char) "v") ; does not work
2112 'cperl-get-help
2113 [(control c) (control h) v]))
55497cff 2114 (if (and cperl-xemacs-p
4633a7c4
LW
2115 (<= emacs-minor-version 11) (<= emacs-major-version 19))
2116 (progn
2117 ;; substitute-key-definition is usefulness-deenhanced...
55497cff 2118 (cperl-define-key "\M-q" 'cperl-fill-paragraph)
2119 (cperl-define-key "\e;" 'cperl-indent-for-comment)
2120 (cperl-define-key "\e\C-\\" 'cperl-indent-region))
4633a7c4
LW
2121 (substitute-key-definition
2122 'indent-sexp 'cperl-indent-exp
2123 cperl-mode-map global-map)
2124 (substitute-key-definition
2125 'fill-paragraph 'cperl-fill-paragraph
2126 cperl-mode-map global-map)
2127 (substitute-key-definition
2128 'indent-region 'cperl-indent-region
2129 cperl-mode-map global-map)
2130 (substitute-key-definition
2131 'indent-for-comment 'cperl-indent-for-comment
2132 cperl-mode-map global-map)))
2133
05bbd9c3 2134(defvar cperl-menu)
6c72d195
IZ
2135(defvar cperl-lazy-installed)
2136(defvar cperl-old-style nil)
4633a7c4
LW
2137(condition-case nil
2138 (progn
2139 (require 'easymenu)
2140 (easy-menu-define cperl-menu cperl-mode-map "Menu for CPerl mode"
2141 '("Perl"
2142 ["Beginning of function" beginning-of-defun t]
2143 ["End of function" end-of-defun t]
2144 ["Mark function" mark-defun t]
2145 ["Indent expression" cperl-indent-exp t]
2146 ["Fill paragraph/comment" cperl-fill-paragraph t]
ebcd4dbc 2147 "----"
4633a7c4 2148 ["Line up a construction" cperl-lineup (cperl-use-region-p)]
7bcea553 2149 ["Invert if/unless/while etc" cperl-invert-if-unless t]
6c72d195
IZ
2150 ("Regexp"
2151 ["Beautify" cperl-beautify-regexp
2152 cperl-use-syntax-table-text-property]
7bcea553
IZ
2153 ["Beautify one level deep" (cperl-beautify-regexp 1)
2154 cperl-use-syntax-table-text-property]
6c72d195
IZ
2155 ["Beautify a group" cperl-beautify-level
2156 cperl-use-syntax-table-text-property]
7bcea553
IZ
2157 ["Beautify a group one level deep" (cperl-beautify-level 1)
2158 cperl-use-syntax-table-text-property]
6c72d195
IZ
2159 ["Contract a group" cperl-contract-level
2160 cperl-use-syntax-table-text-property]
2161 ["Contract groups" cperl-contract-levels
2162 cperl-use-syntax-table-text-property])
3ee700d1 2163 ["Refresh \"hard\" constructions" cperl-find-pods-heres t]
4633a7c4
LW
2164 "----"
2165 ["Indent region" cperl-indent-region (cperl-use-region-p)]
499d5216
IZ
2166 ["Comment region" cperl-comment-region (cperl-use-region-p)]
2167 ["Uncomment region" cperl-uncomment-region (cperl-use-region-p)]
4633a7c4
LW
2168 "----"
2169 ["Run" mode-compile (fboundp 'mode-compile)]
2170 ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
2171 (get-buffer "*compilation*"))]
2172 ["Next error" next-error (get-buffer "*compilation*")]
2173 ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
2174 "----"
499d5216 2175 ["Debugger" cperl-db t]
4633a7c4
LW
2176 "----"
2177 ("Tools"
2178 ["Imenu" imenu (fboundp 'imenu)]
499d5216 2179 ["Insert spaces if needed" cperl-find-bad-style t]
9ea28adb 2180 ["Class Hierarchy from TAGS" cperl-tags-hier-init t]
2181 ;;["Update classes" (cperl-tags-hier-init t) tags-table-list]
4584684c
GS
2182 ["CPerl pretty print (exprmntl)" cperl-ps-print
2183 (fboundp 'ps-extend-face-list)]
4633a7c4
LW
2184 ["Imenu on info" cperl-imenu-on-info (featurep 'imenu)]
2185 ("Tags"
9ea28adb 2186;;; ["Create tags for current file" cperl-etags t]
2187;;; ["Add tags for current file" (cperl-etags t) t]
2188;;; ["Create tags for Perl files in directory" (cperl-etags nil t) t]
2189;;; ["Add tags for Perl files in directory" (cperl-etags t t) t]
2190;;; ["Create tags for Perl files in (sub)directories"
2191;;; (cperl-etags nil 'recursive) t]
2192;;; ["Add tags for Perl files in (sub)directories"
2193;;; (cperl-etags t 'recursive) t])
2194;;;; cperl-write-tags (&optional file erase recurse dir inbuffer)
2195 ["Create tags for current file" (cperl-write-tags nil t) t]
2196 ["Add tags for current file" (cperl-write-tags) t]
2197 ["Create tags for Perl files in directory"
2198 (cperl-write-tags nil t nil t) t]
2199 ["Add tags for Perl files in directory"
2200 (cperl-write-tags nil nil nil t) t]
4633a7c4 2201 ["Create tags for Perl files in (sub)directories"
9ea28adb 2202 (cperl-write-tags nil t t t) t]
4633a7c4 2203 ["Add tags for Perl files in (sub)directories"
6c72d195
IZ
2204 (cperl-write-tags nil nil t t) t]))
2205 ("Perl docs"
4633a7c4
LW
2206 ["Define word at point" imenu-go-find-at-position
2207 (fboundp 'imenu-go-find-at-position)]
2208 ["Help on function" cperl-info-on-command t]
55497cff 2209 ["Help on function at point" cperl-info-on-current-command t]
2210 ["Help on symbol at point" cperl-get-help t]
6c72d195
IZ
2211 ["Perldoc" cperl-perldoc t]
2212 ["Perldoc on word at point" cperl-perldoc-at-point t]
2213 ["View manpage of POD in this file" cperl-pod-to-manpage t]
2214 ["Auto-help on" cperl-lazy-install
2215 (and (fboundp 'run-with-idle-timer)
2216 (not cperl-lazy-installed))]
2217 ["Auto-help off" (eval '(cperl-lazy-unstall))
2218 (and (fboundp 'run-with-idle-timer)
2219 cperl-lazy-installed)])
9ea28adb 2220 ("Toggle..."
2221 ["Auto newline" cperl-toggle-auto-newline t]
2222 ["Electric parens" cperl-toggle-electric t]
2223 ["Electric keywords" cperl-toggle-abbrev t]
6c72d195
IZ
2224 ["Fix whitespace on indent" cperl-toggle-construct-fix t]
2225 ["Auto fill" auto-fill-mode t])
4633a7c4 2226 ("Indent styles..."
6c72d195
IZ
2227 ["CPerl" (cperl-set-style "CPerl") t]
2228 ["PerlStyle" (cperl-set-style "PerlStyle") t]
4633a7c4
LW
2229 ["GNU" (cperl-set-style "GNU") t]
2230 ["C++" (cperl-set-style "C++") t]
2231 ["FSF" (cperl-set-style "FSF") t]
2232 ["BSD" (cperl-set-style "BSD") t]
6c72d195
IZ
2233 ["Whitesmith" (cperl-set-style "Whitesmith") t]
2234 ["Current" (cperl-set-style "Current") t]
2235 ["Memorized" (cperl-set-style-back) cperl-old-style])
c07a80fd 2236 ("Micro-docs"
2237 ["Tips" (describe-variable 'cperl-tips) t]
2238 ["Problems" (describe-variable 'cperl-problems) t]
ebcd4dbc 2239 ["Non-problems" (describe-variable 'cperl-non-problems) t]
6c72d195
IZ
2240 ["Speed" (describe-variable 'cperl-speed) t]
2241 ["Praise" (describe-variable 'cperl-praise) t]
4584684c
GS
2242 ["Faces" (describe-variable 'cperl-tips-faces) t]
2243 ["CPerl mode" (describe-function 'cperl-mode) t]
2244 ["CPerl version"
2245 (message "The version of master-file for this CPerl is %s"
2246 cperl-version) t]))))
4633a7c4
LW
2247 (error nil))
2248
2249(autoload 'c-macro-expand "cmacexp"
2250 "Display the result of expanding all C macros occurring in the region.
2251The expansion is entirely correct because it uses the C preprocessor."
2252 t)
2253
2254(defvar cperl-mode-syntax-table nil
2255 "Syntax table in use in Cperl-mode buffers.")
2256
ebcd4dbc
IZ
2257(defvar cperl-string-syntax-table nil
2258 "Syntax table in use in Cperl-mode string-like chunks.")
2259
4633a7c4
LW
2260(if cperl-mode-syntax-table
2261 ()
2262 (setq cperl-mode-syntax-table (make-syntax-table))
2263 (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table)
2264 (modify-syntax-entry ?/ "." cperl-mode-syntax-table)
2265 (modify-syntax-entry ?* "." cperl-mode-syntax-table)
2266 (modify-syntax-entry ?+ "." cperl-mode-syntax-table)
2267 (modify-syntax-entry ?- "." cperl-mode-syntax-table)
2268 (modify-syntax-entry ?= "." cperl-mode-syntax-table)
2269 (modify-syntax-entry ?% "." cperl-mode-syntax-table)
2270 (modify-syntax-entry ?< "." cperl-mode-syntax-table)
2271 (modify-syntax-entry ?> "." cperl-mode-syntax-table)
2272 (modify-syntax-entry ?& "." cperl-mode-syntax-table)
2273 (modify-syntax-entry ?$ "\\" cperl-mode-syntax-table)
2274 (modify-syntax-entry ?\n ">" cperl-mode-syntax-table)
2275 (modify-syntax-entry ?# "<" cperl-mode-syntax-table)
2276 (modify-syntax-entry ?' "\"" cperl-mode-syntax-table)
2277 (modify-syntax-entry ?` "\"" cperl-mode-syntax-table)
05bbd9c3
IZ
2278 (if cperl-under-as-char
2279 (modify-syntax-entry ?_ "w" cperl-mode-syntax-table))
499d5216 2280 (modify-syntax-entry ?: "_" cperl-mode-syntax-table)
ebcd4dbc
IZ
2281 (modify-syntax-entry ?| "." cperl-mode-syntax-table)
2282 (setq cperl-string-syntax-table (copy-syntax-table cperl-mode-syntax-table))
2283 (modify-syntax-entry ?$ "." cperl-string-syntax-table)
2284 (modify-syntax-entry ?# "." cperl-string-syntax-table) ; (?# comment )
2285)
4633a7c4
LW
2286
2287
2288\f
4633a7c4
LW
2289;; provide an alias for working with emacs 19. the perl-mode that comes
2290;; with it is really bad, and this lets us seamlessly replace it.
6c72d195 2291;;;###autoload
4633a7c4 2292(fset 'perl-mode 'cperl-mode)
6c72d195 2293(defvar cperl-faces-init nil)
05bbd9c3
IZ
2294;; Fix for msb.el
2295(defvar cperl-msb-fixed nil)
6c72d195
IZ
2296(defvar font-lock-syntactic-keywords)
2297(defvar perl-font-lock-keywords)
2298(defvar perl-font-lock-keywords-1)
2299(defvar perl-font-lock-keywords-2)
7bcea553
IZ
2300(defvar outline-level)
2301(defvar cperl-outline-regexp)
2302
6c72d195 2303;;;###autoload
4633a7c4
LW
2304(defun cperl-mode ()
2305 "Major mode for editing Perl code.
2306Expression and list commands understand all C brackets.
2307Tab indents for Perl code.
2308Paragraphs are separated by blank lines only.
2309Delete converts tabs to spaces as it moves back.
2310
2311Various characters in Perl almost always come in pairs: {}, (), [],
6c72d195 2312sometimes <>. When the user types the first, she gets the second as
4633a7c4
LW
2313well, with optional special formatting done on {}. (Disabled by
2314default.) You can always quote (with \\[quoted-insert]) the left
6c72d195
IZ
2315\"paren\" to avoid the expansion. The processing of < is special,
2316since most the time you mean \"less\". Cperl mode tries to guess
4633a7c4 2317whether you want to type pair <>, and inserts is if it
6c72d195 2318appropriate. You can set `cperl-electric-parens-string' to the string that
4633a7c4 2319contains the parenths from the above list you want to be electrical.
9ea28adb 2320Electricity of parenths is controlled by `cperl-electric-parens'.
2321You may also set `cperl-electric-parens-mark' to have electric parens
2322look for active mark and \"embrace\" a region if possible.'
4633a7c4
LW
2323
2324CPerl mode provides expansion of the Perl control constructs:
6c72d195
IZ
2325
2326 if, else, elsif, unless, while, until, continue, do,
2327 for, foreach, formy and foreachmy.
2328
2329and POD directives (Disabled by default, see `cperl-electric-keywords'.)
2330
2331The user types the keyword immediately followed by a space, which
2332causes the construct to be expanded, and the point is positioned where
2333she is most likely to want to be. eg. when the user types a space
2334following \"if\" the following appears in the buffer: if () { or if ()
2335} { } and the cursor is between the parentheses. The user can then
2336type some boolean expression within the parens. Having done that,
2337typing \\[cperl-linefeed] places you - appropriately indented - on a
2338new line between the braces (if you typed \\[cperl-linefeed] in a POD
2339directive line, then appropriate number of new lines is inserted).
2340
2341If CPerl decides that you want to insert \"English\" style construct like
2342
4633a7c4 2343 bite if angry;
6c72d195
IZ
2344
2345it will not do any expansion. See also help on variable
2346`cperl-extra-newline-before-brace'. (Note that one can switch the
2347help message on expansion by setting `cperl-message-electric-keyword'
2348to nil.)
4633a7c4 2349
55497cff 2350\\[cperl-linefeed] is a convenience replacement for typing carriage
6c72d195 2351return. It places you in the next line with proper indentation, or if
4633a7c4 2352you type it inside the inline block of control construct, like
6c72d195 2353
4633a7c4 2354 foreach (@lines) {print; print}
6c72d195 2355
4633a7c4
LW
2356and you are on a boundary of a statement inside braces, it will
2357transform the construct into a multiline and will place you into an
6c72d195 2358appropriately indented blank line. If you need a usual
4633a7c4
LW
2359`newline-and-indent' behaviour, it is on \\[newline-and-indent],
2360see documentation on `cperl-electric-linefeed'.
2361
6c72d195
IZ
2362Use \\[cperl-invert-if-unless] to change a construction of the form
2363
2364 if (A) { B }
2365
2366into
2367
2368 B if A;
2369
4633a7c4
LW
2370\\{cperl-mode-map}
2371
6c72d195
IZ
2372Setting the variable `cperl-font-lock' to t switches on font-lock-mode
2373\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
2374on electric space between $ and {, `cperl-electric-parens-string' is
2375the string that contains parentheses that should be electric in CPerl
2376\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
9ea28adb 2377setting `cperl-electric-keywords' enables electric expansion of
6c72d195
IZ
2378control structures in CPerl. `cperl-electric-linefeed' governs which
2379one of two linefeed behavior is preferable. You can enable all these
9ea28adb 2380options simultaneously (recommended mode of use) by setting
6c72d195
IZ
2381`cperl-hairy' to t. In this case you can switch separate options off
2382by setting them to `null'. Note that one may undo the extra
2383whitespace inserted by semis and braces in `auto-newline'-mode by
2384consequent \\[cperl-electric-backspace].
4633a7c4
LW
2385
2386If your site has perl5 documentation in info format, you can use commands
2387\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
2388These keys run commands `cperl-info-on-current-command' and
2389`cperl-info-on-command', which one is which is controlled by variable
6c72d195
IZ
2390`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
2391\(in turn affected by `cperl-hairy').
4633a7c4 2392
55497cff 2393Even if you have no info-format documentation, short one-liner-style
6c72d195
IZ
2394help is available on \\[cperl-get-help], and one can run perldoc or
2395man via menu.
55497cff 2396
6c72d195
IZ
2397It is possible to show this help automatically after some idle time.
2398This is regulated by variable `cperl-lazy-help-time'. Default with
2399`cperl-hairy' (if the value of `cperl-lazy-help-time' is nil) is 5
2400secs idle time . It is also possible to switch this on/off from the
2401menu, or via \\[cperl-toggle-autohelp]. Requires `run-with-idle-timer'.
55497cff 2402
ebcd4dbc
IZ
2403Use \\[cperl-lineup] to vertically lineup some construction - put the
2404beginning of the region at the start of construction, and make region
2405span the needed amount of lines.
2406
c07a80fd 2407Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
2408`cperl-pod-face', `cperl-pod-head-face' control processing of pod and
6c72d195
IZ
2409here-docs sections. With capable Emaxen results of scan are used
2410for indentation too, otherwise they are used for highlighting only.
c07a80fd 2411
4633a7c4
LW
2412Variables controlling indentation style:
2413 `cperl-tab-always-indent'
2414 Non-nil means TAB in CPerl mode should always reindent the current line,
2415 regardless of where in the line point is when the TAB command is used.
6c72d195
IZ
2416 `cperl-indent-left-aligned-comments'
2417 Non-nil means that the comment starting in leftmost column should indent.
4633a7c4
LW
2418 `cperl-auto-newline'
2419 Non-nil means automatically newline before and after braces,
6c72d195 2420 and after colons and semicolons, inserted in Perl code. The following
9ea28adb 2421 \\[cperl-electric-backspace] will remove the inserted whitespace.
2422 Insertion after colons requires both this variable and
2423 `cperl-auto-newline-after-colon' set.
2424 `cperl-auto-newline-after-colon'
2425 Non-nil means automatically newline even after colons.
2426 Subject to `cperl-auto-newline' setting.
4633a7c4
LW
2427 `cperl-indent-level'
2428 Indentation of Perl statements within surrounding block.
2429 The surrounding block's indentation is the indentation
2430 of the line on which the open-brace appears.
2431 `cperl-continued-statement-offset'
2432 Extra indentation given to a substatement, such as the
2433 then-clause of an if, or body of a while, or just a statement continuation.
2434 `cperl-continued-brace-offset'
2435 Extra indentation given to a brace that starts a substatement.
2436 This is in addition to `cperl-continued-statement-offset'.
2437 `cperl-brace-offset'
2438 Extra indentation for line if it starts with an open brace.
2439 `cperl-brace-imaginary-offset'
2440 An open brace following other text is treated as if it the line started
2441 this far to the right of the actual line indentation.
2442 `cperl-label-offset'
2443 Extra indentation for line that is a label.
2444 `cperl-min-label-indent'
2445 Minimal indentation for line that is a label.
2446
2447Settings for K&R and BSD indentation styles are
2448 `cperl-indent-level' 5 8
2449 `cperl-continued-statement-offset' 5 8
2450 `cperl-brace-offset' -5 -8
2451 `cperl-label-offset' -5 -8
2452
6c72d195
IZ
2453CPerl knows several indentation styles, and may bulk set the
2454corresponding variables. Use \\[cperl-set-style] to do this. Use
2455\\[cperl-set-style-back] to restore the memorized preexisting values
2456\(both available from menu).
2457
2458If `cperl-indent-level' is 0, the statement after opening brace in
2459column 0 is indented on
2460`cperl-brace-offset'+`cperl-continued-statement-offset'.
4633a7c4
LW
2461
2462Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook'
6c72d195
IZ
2463with no args.
2464
2465DO NOT FORGET to read micro-docs (available from `Perl' menu)
2466or as help on variables `cperl-tips', `cperl-problems',
2467`cperl-non-problems', `cperl-praise', `cperl-speed'."
4633a7c4
LW
2468 (interactive)
2469 (kill-all-local-variables)
4633a7c4
LW
2470 (use-local-map cperl-mode-map)
2471 (if (cperl-val 'cperl-electric-linefeed)
2472 (progn
2473 (local-set-key "\C-J" 'cperl-linefeed)
2474 (local-set-key "\C-C\C-J" 'newline-and-indent)))
6c72d195
IZ
2475 (if (and
2476 (cperl-val 'cperl-clobber-lisp-bindings)
2477 (cperl-val 'cperl-info-on-command-no-prompt))
4633a7c4 2478 (progn
55497cff 2479 ;; don't clobber the backspace binding:
2480 (cperl-define-key "\C-hf" 'cperl-info-on-current-command [(control h) f])
2481 (cperl-define-key "\C-c\C-hf" 'cperl-info-on-command
2482 [(control c) (control h) f])))
4633a7c4
LW
2483 (setq major-mode 'perl-mode)
2484 (setq mode-name "CPerl")
2485 (if (not cperl-mode-abbrev-table)
2486 (let ((prev-a-c abbrevs-changed))
2487 (define-abbrev-table 'cperl-mode-abbrev-table '(
2488 ("if" "if" cperl-electric-keyword 0)
2489 ("elsif" "elsif" cperl-electric-keyword 0)
2490 ("while" "while" cperl-electric-keyword 0)
2491 ("until" "until" cperl-electric-keyword 0)
2492 ("unless" "unless" cperl-electric-keyword 0)
2493 ("else" "else" cperl-electric-else 0)
6c72d195 2494 ("continue" "continue" cperl-electric-else 0)
4633a7c4
LW
2495 ("for" "for" cperl-electric-keyword 0)
2496 ("foreach" "foreach" cperl-electric-keyword 0)
6c72d195
IZ
2497 ("formy" "formy" cperl-electric-keyword 0)
2498 ("foreachmy" "foreachmy" cperl-electric-keyword 0)
2499 ("do" "do" cperl-electric-keyword 0)
7bcea553
IZ
2500 ("=pod" "=pod" cperl-electric-pod 0)
2501 ("=over" "=over" cperl-electric-pod 0)
2502 ("=head1" "=head1" cperl-electric-pod 0)
2503 ("=head2" "=head2" cperl-electric-pod 0)
6c72d195
IZ
2504 ("pod" "pod" cperl-electric-pod 0)
2505 ("over" "over" cperl-electric-pod 0)
2506 ("head1" "head1" cperl-electric-pod 0)
2507 ("head2" "head2" cperl-electric-pod 0)))
4633a7c4
LW
2508 (setq abbrevs-changed prev-a-c)))
2509 (setq local-abbrev-table cperl-mode-abbrev-table)
2510 (abbrev-mode (if (cperl-val 'cperl-electric-keywords) 1 0))
2511 (set-syntax-table cperl-mode-syntax-table)
7bcea553
IZ
2512 (make-local-variable 'outline-regexp)
2513 ;; (setq outline-regexp imenu-example--function-name-regexp-perl)
2514 (setq outline-regexp cperl-outline-regexp)
2515 (make-local-variable 'outline-level)
2516 (setq outline-level 'cperl-outline-level)
4633a7c4
LW
2517 (make-local-variable 'paragraph-start)
2518 (setq paragraph-start (concat "^$\\|" page-delimiter))
2519 (make-local-variable 'paragraph-separate)
2520 (setq paragraph-separate paragraph-start)
2521 (make-local-variable 'paragraph-ignore-fill-prefix)
2522 (setq paragraph-ignore-fill-prefix t)
2523 (make-local-variable 'indent-line-function)
2524 (setq indent-line-function 'cperl-indent-line)
2525 (make-local-variable 'require-final-newline)
2526 (setq require-final-newline t)
2527 (make-local-variable 'comment-start)
2528 (setq comment-start "# ")
2529 (make-local-variable 'comment-end)
2530 (setq comment-end "")
2531 (make-local-variable 'comment-column)
2532 (setq comment-column cperl-comment-column)
2533 (make-local-variable 'comment-start-skip)
2534 (setq comment-start-skip "#+ *")
2535 (make-local-variable 'defun-prompt-regexp)
ebcd4dbc 2536 (setq defun-prompt-regexp "^[ \t]*sub[ \t]+\\([^ \t\n{(;]+\\)[ \t]*")
4633a7c4
LW
2537 (make-local-variable 'comment-indent-function)
2538 (setq comment-indent-function 'cperl-comment-indent)
2539 (make-local-variable 'parse-sexp-ignore-comments)
2540 (setq parse-sexp-ignore-comments t)
2541 (make-local-variable 'indent-region-function)
2542 (setq indent-region-function 'cperl-indent-region)
2543 ;;(setq auto-fill-function 'cperl-do-auto-fill) ; Need to switch on and off!
2544 (make-local-variable 'imenu-create-index-function)
2545 (setq imenu-create-index-function
2546 (function imenu-example--create-perl-index))
c07a80fd 2547 (make-local-variable 'imenu-sort-function)
2548 (setq imenu-sort-function nil)
4633a7c4 2549 (make-local-variable 'vc-header-alist)
6c72d195 2550 (set 'vc-header-alist cperl-vc-header-alist) ; Avoid warning
c07a80fd 2551 (make-local-variable 'font-lock-defaults)
2552 (setq font-lock-defaults
6c72d195
IZ
2553 (cond
2554 ((string< emacs-version "19.30")
2555 '(perl-font-lock-keywords-2))
2556 ((string< emacs-version "19.33") ; Which one to use?
c07a80fd 2557 '((perl-font-lock-keywords
2558 perl-font-lock-keywords-1
6c72d195
IZ
2559 perl-font-lock-keywords-2)))
2560 (t
2561 '((cperl-load-font-lock-keywords
2562 cperl-load-font-lock-keywords-1
2563 cperl-load-font-lock-keywords-2)))))
2564 (make-local-variable 'cperl-syntax-state)
ebcd4dbc
IZ
2565 (if cperl-use-syntax-table-text-property
2566 (progn
2567 (make-variable-buffer-local 'parse-sexp-lookup-properties)
05bbd9c3 2568 ;; Do not introduce variable if not needed, we check it!
6c72d195
IZ
2569 (set 'parse-sexp-lookup-properties t)
2570 ;; Fix broken font-lock:
2571 (or (boundp 'font-lock-unfontify-region-function)
2572 (set 'font-lock-unfontify-region-function
4584684c 2573 'font-lock-default-unfontify-region))
6c72d195
IZ
2574 (make-variable-buffer-local 'font-lock-unfontify-region-function)
2575 (set 'font-lock-unfontify-region-function
2576 'cperl-font-lock-unfontify-region-function)
2577 (make-variable-buffer-local 'cperl-syntax-done-to)
2578 ;; Another bug: unless font-lock-syntactic-keywords, font-lock
2579 ;; ignores syntax-table text-property. (t) is a hack
2580 ;; to make font-lock think that font-lock-syntactic-keywords
2581 ;; are defined
2582 (make-variable-buffer-local 'font-lock-syntactic-keywords)
2583 (setq font-lock-syntactic-keywords
2584 (if cperl-syntaxify-by-font-lock
2585 '(t (cperl-fontify-syntaxically))
2586 '(t)))))
2587 (make-local-variable 'cperl-old-style)
4633a7c4
LW
2588 (or (fboundp 'cperl-old-auto-fill-mode)
2589 (progn
2590 (fset 'cperl-old-auto-fill-mode (symbol-function 'auto-fill-mode))
2591 (defun auto-fill-mode (&optional arg)
2592 (interactive "P")
6c72d195 2593 (eval '(cperl-old-auto-fill-mode arg)) ; Avoid a warning
4633a7c4
LW
2594 (and auto-fill-function (eq major-mode 'perl-mode)
2595 (setq auto-fill-function 'cperl-do-auto-fill)))))
2596 (if (cperl-enable-font-lock)
c07a80fd 2597 (if (cperl-val 'cperl-font-lock)
2598 (progn (or cperl-faces-init (cperl-init-faces))
2599 (font-lock-mode 1))))
4633a7c4
LW
2600 (and (boundp 'msb-menu-cond)
2601 (not cperl-msb-fixed)
2602 (cperl-msb-fix))
55497cff 2603 (if (featurep 'easymenu)
6c72d195 2604 (easy-menu-add cperl-menu)) ; A NOP in RMS Emacs.
c07a80fd 2605 (run-hooks 'cperl-mode-hook)
2606 ;; After hooks since fontification will break this
6c72d195
IZ
2607 (if cperl-pod-here-scan
2608 (or ;;(and (boundp 'font-lock-mode)
2609 ;; (eval 'font-lock-mode) ; Avoid warning
2610 ;; (boundp 'font-lock-hot-pass) ; Newer font-lock
2611 cperl-syntaxify-by-font-lock ;;)
2612 (progn (or cperl-faces-init (cperl-init-faces-weak))
2613 (cperl-find-pods-heres)))))
4633a7c4 2614\f
499d5216 2615;; Fix for perldb - make default reasonable
6c72d195 2616(defvar gud-perldb-history)
499d5216
IZ
2617(defun cperl-db ()
2618 (interactive)
2619 (require 'gud)
2620 (perldb (read-from-minibuffer "Run perldb (like this): "
2621 (if (consp gud-perldb-history)
2622 (car gud-perldb-history)
2623 (concat "perl " ;;(file-name-nondirectory
2624 ;; I have problems
2625 ;; in OS/2
2626 ;; otherwise
2627 (buffer-file-name)))
2628 nil nil
2629 '(gud-perldb-history . 1))))
2630\f
6c72d195 2631(defvar msb-menu-cond)
4633a7c4
LW
2632(defun cperl-msb-fix ()
2633 ;; Adds perl files to msb menu, supposes that msb is already loaded
2634 (setq cperl-msb-fixed t)
2635 (let* ((l (length msb-menu-cond))
2636 (last (nth (1- l) msb-menu-cond))
2637 (precdr (nthcdr (- l 2) msb-menu-cond)) ; cdr of this is last
2638 (handle (1- (nth 1 last))))
2639 (setcdr precdr (list
2640 (list
2641 '(eq major-mode 'perl-mode)
2642 handle
2643 "Perl Files (%d)")
2644 last))))
2645\f
2646;; This is used by indent-for-comment
2647;; to decide how much to indent a comment in CPerl code
6c72d195 2648;; based on its context. Do fallback if comment is found wrong.
4633a7c4
LW
2649
2650(defvar cperl-wrong-comment)
4584684c
GS
2651(defvar cperl-st-cfence '(14)) ; Comment-fence
2652(defvar cperl-st-sfence '(15)) ; String-fence
2653(defvar cperl-st-punct '(1))
2654(defvar cperl-st-word '(2))
2655(defvar cperl-st-bra '(4 . ?\>))
2656(defvar cperl-st-ket '(5 . ?\<))
2657
4633a7c4
LW
2658
2659(defun cperl-comment-indent ()
4584684c 2660 (let ((p (point)) (c (current-column)) was phony)
4633a7c4
LW
2661 (if (looking-at "^#") 0 ; Existing comment at bol stays there.
2662 ;; Wrong comment found
2663 (save-excursion
4584684c
GS
2664 (setq was (cperl-to-comment-or-eol)
2665 phony (eq (get-text-property (point) 'syntax-table)
2666 cperl-st-cfence))
2667 (if phony
2668 (progn
2669 (re-search-forward "#\\|$") ; Hmm, what about embedded #?
2670 (if (eq (preceding-char) ?\#)
2671 (forward-char -1))
2672 (setq was nil)))
4633a7c4
LW
2673 (if (= (point) p)
2674 (progn
2675 (skip-chars-backward " \t")
2676 (max (1+ (current-column)) ; Else indent at comment column
2677 comment-column))
2678 (if was nil
2679 (insert comment-start)
2680 (backward-char (length comment-start)))
2681 (setq cperl-wrong-comment t)
2682 (indent-to comment-column 1) ; Indent minimum 1
2683 c))))) ; except leave at least one space.
2684
2685;;;(defun cperl-comment-indent-fallback ()
2686;;; "Is called if the standard comment-search procedure fails.
2687;;;Point is at start of real comment."
2688;;; (let ((c (current-column)) target cnt prevc)
2689;;; (if (= c comment-column) nil
2690;;; (setq cnt (skip-chars-backward "[ \t]"))
2691;;; (setq target (max (1+ (setq prevc
2692;;; (current-column))) ; Else indent at comment column
2693;;; comment-column))
2694;;; (if (= c comment-column) nil
2695;;; (delete-backward-char cnt)
2696;;; (while (< prevc target)
2697;;; (insert "\t")
2698;;; (setq prevc (current-column)))
2699;;; (if (> prevc target) (progn (delete-char -1) (setq prevc (current-column))))
2700;;; (while (< prevc target)
2701;;; (insert " ")
2702;;; (setq prevc (current-column)))))))
2703
2704(defun cperl-indent-for-comment ()
55497cff 2705 "Substitute for `indent-for-comment' in CPerl."
4633a7c4
LW
2706 (interactive)
2707 (let (cperl-wrong-comment)
2708 (indent-for-comment)
2709 (if cperl-wrong-comment
2710 (progn (cperl-to-comment-or-eol)
2711 (forward-char (length comment-start))))))
2712
499d5216
IZ
2713(defun cperl-comment-region (b e arg)
2714 "Comment or uncomment each line in the region in CPerl mode.
2715See `comment-region'."
2716 (interactive "r\np")
2717 (let ((comment-start "#"))
2718 (comment-region b e arg)))
2719
2720(defun cperl-uncomment-region (b e arg)
2721 "Uncomment or comment each line in the region in CPerl mode.
2722See `comment-region'."
2723 (interactive "r\np")
2724 (let ((comment-start "#"))
2725 (comment-region b e (- arg))))
2726
55497cff 2727(defvar cperl-brace-recursing nil)
2728
4633a7c4
LW
2729(defun cperl-electric-brace (arg &optional only-before)
2730 "Insert character and correct line's indentation.
2731If ONLY-BEFORE and `cperl-auto-newline', will insert newline before the
6c72d195 2732place (even in empty line), but not after. If after \")\" and the inserted
9ea28adb 2733char is \"{\", insert extra newline before only if
2734`cperl-extra-newline-before-brace'."
4633a7c4 2735 (interactive "P")
55497cff 2736 (let (insertpos
2737 (other-end (if (and cperl-electric-parens-mark
2738 (cperl-mark-active)
2739 (< (mark) (point)))
2740 (mark)
2741 nil)))
2742 (if (and other-end
2743 (not cperl-brace-recursing)
2744 (cperl-val 'cperl-electric-parens)
2745 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point)))
2746 ;; Need to insert a matching pair
4633a7c4 2747 (progn
4633a7c4 2748 (save-excursion
55497cff 2749 (setq insertpos (point-marker))
2750 (goto-char other-end)
2751 (setq last-command-char ?\{)
2752 (cperl-electric-lbrace arg insertpos))
2753 (forward-char 1))
6c72d195
IZ
2754 ;: Check whether we close something "usual" with `}'
2755 (if (and (eq last-command-char ?\})
2756 (not
2757 (condition-case nil
2758 (save-excursion
2759 (up-list (- (prefix-numeric-value arg)))
2760 ;;(cperl-after-block-p (point-min))
2761 (cperl-after-expr-p nil "{;)"))
2762 (error nil))))
2763 ;; Just insert the guy
2764 (self-insert-command (prefix-numeric-value arg))
2765 (if (and (not arg) ; No args, end (of empty line or auto)
2766 (eolp)
2767 (or (and (null only-before)
2768 (save-excursion
2769 (skip-chars-backward " \t")
2770 (bolp)))
2771 (and (eq last-command-char ?\{) ; Do not insert newline
2772 ;; if after ")" and `cperl-extra-newline-before-brace'
2773 ;; is nil, do not insert extra newline.
2774 (not cperl-extra-newline-before-brace)
2775 (save-excursion
2776 (skip-chars-backward " \t")
2777 (eq (preceding-char) ?\))))
2778 (if cperl-auto-newline
2779 (progn (cperl-indent-line) (newline) t) nil)))
2780 (progn
2781 (self-insert-command (prefix-numeric-value arg))
2782 (cperl-indent-line)
2783 (if cperl-auto-newline
2784 (setq insertpos (1- (point))))
2785 (if (and cperl-auto-newline (null only-before))
2786 (progn
2787 (newline)
2788 (cperl-indent-line)))
2789 (save-excursion
2790 (if insertpos (progn (goto-char insertpos)
2791 (search-forward (make-string
2792 1 last-command-char))
2793 (setq insertpos (1- (point)))))
2794 (delete-char -1))))
2795 (if insertpos
55497cff 2796 (save-excursion
6c72d195
IZ
2797 (goto-char insertpos)
2798 (self-insert-command (prefix-numeric-value arg)))
2799 (self-insert-command (prefix-numeric-value arg)))))))
4633a7c4 2800
55497cff 2801(defun cperl-electric-lbrace (arg &optional end)
4633a7c4
LW
2802 "Insert character, correct line's indentation, correct quoting by space."
2803 (interactive "P")
9ea28adb 2804 (let (pos after
55497cff 2805 (cperl-brace-recursing t)
9ea28adb 2806 (cperl-auto-newline cperl-auto-newline)
55497cff 2807 (other-end (or end
2808 (if (and cperl-electric-parens-mark
2809 (cperl-mark-active)
2810 (> (mark) (point)))
2811 (save-excursion
2812 (goto-char (mark))
2813 (point-marker))
2814 nil))))
4633a7c4
LW
2815 (and (cperl-val 'cperl-electric-lbrace-space)
2816 (eq (preceding-char) ?$)
2817 (save-excursion
2818 (skip-chars-backward "$")
2819 (looking-at "\\(\\$\\$\\)*\\$\\([^\\$]\\|$\\)"))
3ee700d1 2820 (insert ?\ ))
6c72d195
IZ
2821 ;; Check whether we are in comment
2822 (if (and
2823 (save-excursion
2824 (beginning-of-line)
2825 (not (looking-at "[ \t]*#")))
2826 (cperl-after-expr-p nil "{;)"))
2827 nil
2828 (setq cperl-auto-newline nil))
4633a7c4 2829 (cperl-electric-brace arg)
9ea28adb 2830 (and (cperl-val 'cperl-electric-parens)
2831 (eq last-command-char ?{)
4633a7c4 2832 (memq last-command-char
9ea28adb 2833 (append cperl-electric-parens-string nil))
2834 (or (if other-end (goto-char (marker-position other-end)))
2835 t)
4633a7c4
LW
2836 (setq last-command-char ?} pos (point))
2837 (progn (cperl-electric-brace arg t)
2838 (goto-char pos)))))
2839
2840(defun cperl-electric-paren (arg)
2841 "Insert a matching pair of parentheses."
2842 (interactive "P")
9ea28adb 2843 (let ((beg (save-excursion (beginning-of-line) (point)))
2844 (other-end (if (and cperl-electric-parens-mark
2845 (cperl-mark-active)
2846 (> (mark) (point)))
2847 (save-excursion
2848 (goto-char (mark))
2849 (point-marker))
2850 nil)))
2851 (if (and (cperl-val 'cperl-electric-parens)
2852 (memq last-command-char
2853 (append cperl-electric-parens-string nil))
4633a7c4
LW
2854 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
2855 ;;(not (save-excursion (search-backward "#" beg t)))
2856 (if (eq last-command-char ?<)
3ee700d1
IZ
2857 (progn
2858 (and abbrev-mode ; later it is too late, may be after `for'
2859 (expand-abbrev))
2860 (cperl-after-expr-p nil "{;(,:="))
4633a7c4
LW
2861 1))
2862 (progn
3ee700d1 2863 (self-insert-command (prefix-numeric-value arg))
9ea28adb 2864 (if other-end (goto-char (marker-position other-end)))
3ee700d1
IZ
2865 (insert (make-string
2866 (prefix-numeric-value arg)
2867 (cdr (assoc last-command-char '((?{ .?})
2868 (?[ . ?])
2869 (?( . ?))
2870 (?< . ?>))))))
2871 (forward-char (- (prefix-numeric-value arg))))
2872 (self-insert-command (prefix-numeric-value arg)))))
4633a7c4 2873
55497cff 2874(defun cperl-electric-rparen (arg)
2875 "Insert a matching pair of parentheses if marking is active.
2876If not, or if we are not at the end of marking range, would self-insert."
2877 (interactive "P")
2878 (let ((beg (save-excursion (beginning-of-line) (point)))
2879 (other-end (if (and cperl-electric-parens-mark
5f05dabc 2880 (cperl-val 'cperl-electric-parens)
2881 (memq last-command-char
2882 (append cperl-electric-parens-string nil))
55497cff 2883 (cperl-mark-active)
2884 (< (mark) (point)))
2885 (mark)
2886 nil))
2887 p)
2888 (if (and other-end
2889 (cperl-val 'cperl-electric-parens)
2890 (memq last-command-char '( ?\) ?\] ?\} ?\> ))
2891 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
2892 ;;(not (save-excursion (search-backward "#" beg t)))
2893 )
2894 (progn
3ee700d1 2895 (self-insert-command (prefix-numeric-value arg))
55497cff 2896 (setq p (point))
2897 (if other-end (goto-char other-end))
3ee700d1
IZ
2898 (insert (make-string
2899 (prefix-numeric-value arg)
2900 (cdr (assoc last-command-char '((?\} . ?\{)
55497cff 2901 (?\] . ?\[)
2902 (?\) . ?\()
3ee700d1 2903 (?\> . ?\<))))))
55497cff 2904 (goto-char (1+ p)))
3ee700d1 2905 (self-insert-command (prefix-numeric-value arg)))))
55497cff 2906
4633a7c4 2907(defun cperl-electric-keyword ()
6c72d195
IZ
2908 "Insert a construction appropriate after a keyword.
2909Help message may be switched off by setting `cperl-message-electric-keyword'
2910to nil."
9ea28adb 2911 (let ((beg (save-excursion (beginning-of-line) (point)))
3ee700d1
IZ
2912 (dollar (and (eq last-command-char ?$)
2913 (eq this-command 'self-insert-command)))
2914 (delete (and (memq last-command-char '(?\ ?\n ?\t ?\f))
6c72d195
IZ
2915 (memq this-command '(self-insert-command newline))))
2916 my do)
4633a7c4 2917 (and (save-excursion
6c72d195
IZ
2918 (condition-case nil
2919 (progn
2920 (backward-sexp 1)
2921 (setq do (looking-at "do\\>")))
2922 (error nil))
ebcd4dbc 2923 (cperl-after-expr-p nil "{;:"))
4633a7c4
LW
2924 (save-excursion
2925 (not
2926 (re-search-backward
20675f5d 2927 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
4633a7c4
LW
2928 beg t)))
2929 (save-excursion (or (not (re-search-backward "^=" nil t))
6c72d195
IZ
2930 (or
2931 (looking-at "=cut")
2932 (and cperl-use-syntax-table-text-property
2933 (not (eq (get-text-property (point)
2934 'syntax-type)
2935 'pod))))))
4633a7c4 2936 (progn
6c72d195
IZ
2937 (and (eq (preceding-char) ?y)
2938 (progn ; "foreachmy"
2939 (forward-char -2)
2940 (insert " ")
2941 (forward-char 2)
2942 (setq my t dollar t
2943 delete
2944 (memq this-command '(self-insert-command newline)))))
9ea28adb 2945 (and dollar (insert " $"))
4633a7c4
LW
2946 (cperl-indent-line)
2947 ;;(insert " () {\n}")
2948 (cond
2949 (cperl-extra-newline-before-brace
6c72d195 2950 (insert (if do "\n" " ()\n"))
4633a7c4
LW
2951 (insert "{")
2952 (cperl-indent-line)
2953 (insert "\n")
2954 (cperl-indent-line)
6c72d195
IZ
2955 (insert "\n}")
2956 (and do (insert " while ();")))
4633a7c4 2957 (t
6c72d195 2958 (insert (if do " {\n} while ();" " () {\n}")))
4633a7c4
LW
2959 )
2960 (or (looking-at "[ \t]\\|$") (insert " "))
2961 (cperl-indent-line)
9ea28adb 2962 (if dollar (progn (search-backward "$")
6c72d195
IZ
2963 (if my
2964 (forward-char 1)
2965 (delete-char 1)))
9ea28adb 2966 (search-backward ")"))
3ee700d1 2967 (if delete
6c72d195
IZ
2968 (cperl-putback-char cperl-del-back-ch))
2969 (if cperl-message-electric-keyword
2970 (message "Precede char by C-q to avoid expansion"))))))
2971
2972(defun cperl-ensure-newlines (n &optional pos)
2973 "Make sure there are N newlines after the point."
2974 (or pos (setq pos (point)))
2975 (if (looking-at "\n")
2976 (forward-char 1)
2977 (insert "\n"))
2978 (if (> n 1)
2979 (cperl-ensure-newlines (1- n) pos)
2980 (goto-char pos)))
2981
2982(defun cperl-electric-pod ()
2983 "Insert a POD chunk appropriate after a =POD directive."
2984 (let ((delete (and (memq last-command-char '(?\ ?\n ?\t ?\f))
2985 (memq this-command '(self-insert-command newline))))
2986 head1 notlast name p really-delete over)
2987 (and (save-excursion
7bcea553 2988 (forward-word -1)
6c72d195
IZ
2989 (and
2990 (eq (preceding-char) ?=)
2991 (progn
7bcea553
IZ
2992 (setq head1 (looking-at "head1\\>[ \t]*$"))
2993 (setq over (and (looking-at "over\\>[ \t]*$")
2994 (not (looking-at "over[ \t]*\n\n\n*=item\\>"))))
6c72d195
IZ
2995 (forward-char -1)
2996 (bolp))
2997 (or
20675f5d 2998 (get-text-property (point) 'in-pod)
6c72d195
IZ
2999 (cperl-after-expr-p nil "{;:")
3000 (and (re-search-backward
7bcea553
IZ
3001 ;; "\\(\\`\n?\\|\n\n\\)=\\sw+"
3002 "\\(\\`\n?\\|^\n\\)=\\sw+"
3003 (point-min) t)
6c72d195
IZ
3004 (not (or
3005 (looking-at "=cut")
3006 (and cperl-use-syntax-table-text-property
3007 (not (eq (get-text-property (point) 'syntax-type)
3008 'pod)))))))))
3009 (progn
3010 (save-excursion
7bcea553 3011 (setq notlast (re-search-forward "^\n=" nil t)))
6c72d195
IZ
3012 (or notlast
3013 (progn
3014 (insert "\n\n=cut")
3015 (cperl-ensure-newlines 2)
7bcea553 3016 (forward-word -2)
6c72d195
IZ
3017 (if (and head1
3018 (not
3019 (save-excursion
3020 (forward-char -1)
3021 (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\>"
3022 nil t)))) ; Only one
3023 (progn
7bcea553 3024 (forward-word 1)
6c72d195
IZ
3025 (setq name (file-name-sans-extension
3026 (file-name-nondirectory (buffer-file-name)))
3027 p (point))
3028 (insert " NAME\n\n" name
7bcea553 3029 " - \n\n=head1 SYNOPSIS\n\n\n\n"
6c72d195
IZ
3030 "=head1 DESCRIPTION")
3031 (cperl-ensure-newlines 4)
3032 (goto-char p)
7bcea553 3033 (forward-word 2)
6c72d195
IZ
3034 (end-of-line)
3035 (setq really-delete t))
7bcea553 3036 (forward-word 1))))
6c72d195
IZ
3037 (if over
3038 (progn
3039 (setq p (point))
3040 (insert "\n\n=item \n\n\n\n"
3041 "=back")
3042 (cperl-ensure-newlines 2)
3043 (goto-char p)
7bcea553 3044 (forward-word 1)
6c72d195
IZ
3045 (end-of-line)
3046 (setq really-delete t)))
3047 (if (and delete really-delete)
3048 (cperl-putback-char cperl-del-back-ch))))))
4633a7c4
LW
3049
3050(defun cperl-electric-else ()
6c72d195
IZ
3051 "Insert a construction appropriate after a keyword.
3052Help message may be switched off by setting `cperl-message-electric-keyword'
3053to nil."
4633a7c4
LW
3054 (let ((beg (save-excursion (beginning-of-line) (point))))
3055 (and (save-excursion
3056 (backward-sexp 1)
ebcd4dbc 3057 (cperl-after-expr-p nil "{;:"))
4633a7c4
LW
3058 (save-excursion
3059 (not
3060 (re-search-backward
20675f5d 3061 "[#\"'`]\\|\\<q\\(\\|[wqxr]\\)\\>"
4633a7c4
LW
3062 beg t)))
3063 (save-excursion (or (not (re-search-backward "^=" nil t))
6c72d195
IZ
3064 (looking-at "=cut")
3065 (and cperl-use-syntax-table-text-property
3066 (not (eq (get-text-property (point)
3067 'syntax-type)
3068 'pod)))))
4633a7c4
LW
3069 (progn
3070 (cperl-indent-line)
3071 ;;(insert " {\n\n}")
3072 (cond
3073 (cperl-extra-newline-before-brace
3074 (insert "\n")
3075 (insert "{")
3076 (cperl-indent-line)
3077 (insert "\n\n}"))
3078 (t
3079 (insert " {\n\n}"))
3080 )
3081 (or (looking-at "[ \t]\\|$") (insert " "))
3082 (cperl-indent-line)
3083 (forward-line -1)
3084 (cperl-indent-line)
6c72d195
IZ
3085 (cperl-putback-char cperl-del-back-ch)
3086 (setq this-command 'cperl-electric-else)
3087 (if cperl-message-electric-keyword
3088 (message "Precede char by C-q to avoid expansion"))))))
4633a7c4
LW
3089
3090(defun cperl-linefeed ()
6c72d195
IZ
3091 "Go to end of line, open a new line and indent appropriately.
3092If in POD, insert appropriate lines."
4633a7c4
LW
3093 (interactive)
3094 (let ((beg (save-excursion (beginning-of-line) (point)))
3095 (end (save-excursion (end-of-line) (point)))
6c72d195 3096 (pos (point)) start over cut res)
4633a7c4
LW
3097 (if (and ; Check if we need to split:
3098 ; i.e., on a boundary and inside "{...}"
4633a7c4 3099 (save-excursion (cperl-to-comment-or-eol)
499d5216 3100 (>= (point) pos)) ; Not in a comment
4633a7c4
LW
3101 (or (save-excursion
3102 (skip-chars-backward " \t" beg)
3103 (forward-char -1)
499d5216
IZ
3104 (looking-at "[;{]")) ; After { or ; + spaces
3105 (looking-at "[ \t]*}") ; Before }
3106 (re-search-forward "\\=[ \t]*;" end t)) ; Before spaces + ;
4633a7c4
LW
3107 (save-excursion
3108 (and
499d5216
IZ
3109 (eq (car (parse-partial-sexp pos end -1)) -1)
3110 ; Leave the level of parens
9ea28adb 3111 (looking-at "[,; \t]*\\($\\|#\\)") ; Comma to allow anon subr
499d5216 3112 ; Are at end
7bcea553 3113 (cperl-after-block-p (point-min))
4633a7c4
LW
3114 (progn
3115 (backward-sexp 1)
3116 (setq start (point-marker))
6c72d195 3117 (<= start pos))))) ; Redundant? Are after the
499d5216 3118 ; start of parens group.
4633a7c4
LW
3119 (progn
3120 (skip-chars-backward " \t")
3121 (or (memq (preceding-char) (append ";{" nil))
3122 (insert ";"))
3123 (insert "\n")
3124 (forward-line -1)
3125 (cperl-indent-line)
4633a7c4
LW
3126 (goto-char start)
3127 (or (looking-at "{[ \t]*$") ; If there is a statement
3128 ; before, move it to separate line
3129 (progn
3130 (forward-char 1)
3131 (insert "\n")
3132 (cperl-indent-line)))
3133 (forward-line 1) ; We are on the target line
3134 (cperl-indent-line)
3135 (beginning-of-line)
9ea28adb 3136 (or (looking-at "[ \t]*}[,; \t]*$") ; If there is a statement
4633a7c4
LW
3137 ; after, move it to separate line
3138 (progn
3139 (end-of-line)
3140 (search-backward "}" beg)
3141 (skip-chars-backward " \t")
3142 (or (memq (preceding-char) (append ";{" nil))
3143 (insert ";"))
3144 (insert "\n")
3145 (cperl-indent-line)
3146 (forward-line -1)))
3147 (forward-line -1) ; We are on the line before target
3148 (end-of-line)
3149 (newline-and-indent))
6c72d195 3150 (end-of-line) ; else - no splitting
499d5216
IZ
3151 (cond
3152 ((and (looking-at "\n[ \t]*{$")
3153 (save-excursion
3154 (skip-chars-backward " \t")
3155 (eq (preceding-char) ?\)))) ; Probably if () {} group
3156 ; with an extra newline.
3157 (forward-line 2)
3158 (cperl-indent-line))
6c72d195
IZ
3159 ((save-excursion ; In POD header
3160 (forward-paragraph -1)
3161 ;; (re-search-backward "\\(\\`\n?\\|\n\n\\)=head1\\b")
3162 ;; We are after \n now, so look for the rest
3163 (if (looking-at "\\(\\`\n?\\|\n\\)=\\sw+")
3164 (progn
3165 (setq cut (looking-at "\\(\\`\n?\\|\n\\)=cut\\>"))
3166 (setq over (looking-at "\\(\\`\n?\\|\n\\)=over\\>"))
3167 t)))
3168 (if (and over
3169 (progn
3170 (forward-paragraph -1)
3171 (forward-word 1)
3172 (setq pos (point))
3173 (setq cut (buffer-substring (point)
3174 (save-excursion
3175 (end-of-line)
3176 (point))))
3177 (delete-char (- (save-excursion (end-of-line) (point))
3178 (point)))
3179 (setq res (expand-abbrev))
3180 (save-excursion
3181 (goto-char pos)
3182 (insert cut))
3183 res))
3184 nil
3185 (cperl-ensure-newlines (if cut 2 4))
3186 (forward-line 2)))
3187 ((get-text-property (point) 'in-pod) ; In POD section
3188 (cperl-ensure-newlines 4)
3189 (forward-line 2))
499d5216
IZ
3190 ((looking-at "\n[ \t]*$") ; Next line is empty - use it.
3191 (forward-line 1)
3192 (cperl-indent-line))
3193 (t
3194 (newline-and-indent))))))
4633a7c4
LW
3195
3196(defun cperl-electric-semi (arg)
3197 "Insert character and correct line's indentation."
3198 (interactive "P")
3199 (if cperl-auto-newline
3200 (cperl-electric-terminator arg)
7bcea553
IZ
3201 (self-insert-command (prefix-numeric-value arg))
3202 (if cperl-autoindent-on-semi
3203 (cperl-indent-line))))
4633a7c4
LW
3204
3205(defun cperl-electric-terminator (arg)
3206 "Insert character and correct line's indentation."
3207 (interactive "P")
9ea28adb 3208 (let (insertpos (end (point))
3209 (auto (and cperl-auto-newline
3210 (or (not (eq last-command-char ?:))
3211 cperl-auto-newline-after-colon))))
499d5216
IZ
3212 (if (and ;;(not arg)
3213 (eolp)
4633a7c4
LW
3214 (not (save-excursion
3215 (beginning-of-line)
3216 (skip-chars-forward " \t")
c07a80fd 3217 (or
3218 ;; Ignore in comment lines
3219 (= (following-char) ?#)
3220 ;; Colon is special only after a label
3221 ;; So quickly rule out most other uses of colon
3222 ;; and do no indentation for them.
3223 (and (eq last-command-char ?:)
3224 (save-excursion
3225 (forward-word 1)
3226 (skip-chars-forward " \t")
3227 (and (< (point) end)
3228 (progn (goto-char (- end 1))
3229 (not (looking-at ":"))))))
3230 (progn
3231 (beginning-of-defun)
3232 (let ((pps (parse-partial-sexp (point) end)))
3233 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
4633a7c4 3234 (progn
3ee700d1 3235 (self-insert-command (prefix-numeric-value arg))
499d5216 3236 ;;(forward-char -1)
9ea28adb 3237 (if auto (setq insertpos (point-marker)))
499d5216 3238 ;;(forward-char 1)
4633a7c4 3239 (cperl-indent-line)
9ea28adb 3240 (if auto
4633a7c4
LW
3241 (progn
3242 (newline)
3243 (cperl-indent-line)))
3244 (save-excursion
499d5216 3245 (if insertpos (goto-char (1- (marker-position insertpos)))
9ea28adb 3246 (forward-char -1))
3247 (delete-char 1))))
4633a7c4
LW
3248 (if insertpos
3249 (save-excursion
3250 (goto-char insertpos)
3251 (self-insert-command (prefix-numeric-value arg)))
3252 (self-insert-command (prefix-numeric-value arg)))))
3253
9ea28adb 3254(defun cperl-electric-backspace (arg)
6c72d195
IZ
3255 "Backspace-untabify, or remove the whitespace around the point inserted
3256by an electric key."
9ea28adb 3257 (interactive "p")
3258 (if (and cperl-auto-newline
3259 (memq last-command '(cperl-electric-semi
3260 cperl-electric-terminator
3261 cperl-electric-lbrace))
6c72d195 3262 (memq (preceding-char) '(?\ ?\t ?\n)))
9ea28adb 3263 (let (p)
3264 (if (eq last-command 'cperl-electric-lbrace)
3265 (skip-chars-forward " \t\n"))
3266 (setq p (point))
3267 (skip-chars-backward " \t\n")
3268 (delete-region (point) p))
6c72d195
IZ
3269 (and (eq last-command 'cperl-electric-else)
3270 ;; We are removing the whitespace *inside* cperl-electric-else
3271 (setq this-command 'cperl-electric-else-really))
3272 (if (and cperl-auto-newline
3273 (eq last-command 'cperl-electric-else-really)
3274 (memq (preceding-char) '(?\ ?\t ?\n)))
3275 (let (p)
3276 (skip-chars-forward " \t\n")
3277 (setq p (point))
3278 (skip-chars-backward " \t\n")
3279 (delete-region (point) p))
3280 (backward-delete-char-untabify arg))))
9ea28adb 3281
4633a7c4
LW
3282(defun cperl-inside-parens-p ()
3283 (condition-case ()
3284 (save-excursion
3285 (save-restriction
3286 (narrow-to-region (point)
3287 (progn (beginning-of-defun) (point)))
3288 (goto-char (point-max))
3289 (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
3290 (error nil)))
3291\f
3292(defun cperl-indent-command (&optional whole-exp)
4633a7c4 3293 "Indent current line as Perl code, or in some cases insert a tab character.
6c72d195
IZ
3294If `cperl-tab-always-indent' is non-nil (the default), always indent current
3295line. Otherwise, indent the current line only if point is at the left margin
4633a7c4
LW
3296or in the line's indentation; otherwise insert a tab.
3297
3298A numeric argument, regardless of its value,
3299means indent rigidly all the lines of the expression starting after point
3300so that this line becomes properly indented.
3301The relative indentation among the lines of the expression are preserved."
9ea28adb 3302 (interactive "P")
6c72d195 3303 (cperl-update-syntaxification (point) (point))
4633a7c4
LW
3304 (if whole-exp
3305 ;; If arg, always indent this line as Perl
3306 ;; and shift remaining lines of expression the same amount.
3307 (let ((shift-amt (cperl-indent-line))
3308 beg end)
3309 (save-excursion
3310 (if cperl-tab-always-indent
3311 (beginning-of-line))
3312 (setq beg (point))
3313 (forward-sexp 1)
3314 (setq end (point))
3315 (goto-char beg)
3316 (forward-line 1)
3317 (setq beg (point)))
6c72d195 3318 (if (and shift-amt (> end beg))
4633a7c4
LW
3319 (indent-code-rigidly beg end shift-amt "#")))
3320 (if (and (not cperl-tab-always-indent)
3321 (save-excursion
3322 (skip-chars-backward " \t")
3323 (not (bolp))))
3324 (insert-tab)
3325 (cperl-indent-line))))
3326
6c72d195 3327(defun cperl-indent-line (&optional parse-data)
4633a7c4
LW
3328 "Indent current line as Perl code.
3329Return the amount the indentation changed by."
6c72d195 3330 (let (indent i beg shift-amt
4633a7c4
LW
3331 (case-fold-search nil)
3332 (pos (- (point-max) (point))))
6c72d195
IZ
3333 (setq indent (cperl-calculate-indent parse-data)
3334 i indent)
4633a7c4
LW
3335 (beginning-of-line)
3336 (setq beg (point))
ebcd4dbc 3337 (cond ((or (eq indent nil) (eq indent t))
6c72d195 3338 (setq indent (current-indentation) i nil))
4633a7c4
LW
3339 ;;((eq indent t) ; Never?
3340 ;; (setq indent (cperl-calculate-indent-within-comment)))
3341 ;;((looking-at "[ \t]*#")
3342 ;; (setq indent 0))
3343 (t
3344 (skip-chars-forward " \t")
3345 (if (listp indent) (setq indent (car indent)))
ebcd4dbc 3346 (cond ((looking-at "[A-Za-z_][A-Za-z_0-9]*:[^:]")
4633a7c4
LW
3347 (and (> indent 0)
3348 (setq indent (max cperl-min-label-indent
3349 (+ indent cperl-label-offset)))))
4633a7c4
LW
3350 ((= (following-char) ?})
3351 (setq indent (- indent cperl-indent-level)))
3352 ((memq (following-char) '(?\) ?\])) ; To line up with opening paren.
3353 (setq indent (+ indent cperl-close-paren-offset)))
3354 ((= (following-char) ?{)
3355 (setq indent (+ indent cperl-brace-offset))))))
3356 (skip-chars-forward " \t")
6c72d195
IZ
3357 (setq shift-amt (and i (- indent (current-column))))
3358 (if (or (not shift-amt)
3359 (zerop shift-amt))
4633a7c4
LW
3360 (if (> (- (point-max) pos) (point))
3361 (goto-char (- (point-max) pos)))
3362 (delete-region beg (point))
3363 (indent-to indent)
3364 ;; If initial point was within line's indentation,
3365 ;; position after the indentation. Else stay at same point in text.
3366 (if (> (- (point-max) pos) (point))
3367 (goto-char (- (point-max) pos))))
3368 shift-amt))
3369
c07a80fd 3370(defun cperl-after-label ()
6c72d195 3371 ;; Returns true if the point is after label. Does not do save-excursion.
4633a7c4
LW
3372 (and (eq (preceding-char) ?:)
3373 (memq (char-syntax (char-after (- (point) 2)))
3374 '(?w ?_))
3375 (progn
3376 (backward-sexp)
499d5216 3377 (looking-at "[a-zA-Z_][a-zA-Z0-9_]*:[^:]"))))
4633a7c4 3378
c07a80fd 3379(defun cperl-get-state (&optional parse-start start-state)
4584684c
GS
3380 ;; returns list (START STATE DEPTH PRESTART),
3381 ;; START is a good place to start parsing, or equal to
3382 ;; PARSE-START if preset,
3383 ;; STATE is what is returned by `parse-partial-sexp'.
3384 ;; DEPTH is true is we are immediately after end of block
3385 ;; which contains START.
3386 ;; PRESTART is the position basing on which START was found.
4633a7c4 3387 (save-excursion
c07a80fd 3388 (let ((start-point (point)) depth state start prestart)
6c72d195
IZ
3389 (if (and parse-start
3390 (<= parse-start start-point))
4633a7c4 3391 (goto-char parse-start)
6c72d195
IZ
3392 (beginning-of-defun)
3393 (setq start-state nil))
c07a80fd 3394 (setq prestart (point))
4633a7c4 3395 (if start-state nil
c07a80fd 3396 ;; Try to go out, if sub is not on the outermost level
3397 (while (< (point) start-point)
3398 (setq start (point) parse-start start depth nil
3399 state (parse-partial-sexp start start-point -1))
4633a7c4
LW
3400 (if (> (car state) -1) nil
3401 ;; The current line could start like }}}, so the indentation
3402 ;; corresponds to a different level than what we reached
c07a80fd 3403 (setq depth t)
4633a7c4 3404 (beginning-of-line 2))) ; Go to the next line.
c07a80fd 3405 (if start (goto-char start))) ; Not at the start of file
3406 (setq start (point))
c07a80fd 3407 (or state (setq state (parse-partial-sexp start start-point -1 nil start-state)))
3408 (list start state depth prestart))))
3409
6c72d195
IZ
3410(defun cperl-block-p () ; Do not C-M-q ! One string contains ";" !
3411 ;; Positions is before ?\{. Checks whether it starts a block.
c07a80fd 3412 ;; No save-excursion!
3413 (cperl-backward-to-noncomment (point-min))
6c72d195 3414 (or (memq (preceding-char) (append ";){}$@&%\C-@" nil)) ; Or label! \C-@ at bobp
4633a7c4 3415 ; Label may be mixed up with `$blah :'
c07a80fd 3416 (save-excursion (cperl-after-label))
499d5216 3417 (and (memq (char-syntax (preceding-char)) '(?w ?_))
c07a80fd 3418 (progn
3419 (backward-sexp)
9ea28adb 3420 ;; Need take into account `bless', `return', `tr',...
499d5216 3421 (or (and (looking-at "[a-zA-Z0-9_:]+[ \t\n\f]*[{#]") ; Method call syntax
20675f5d 3422 (not (looking-at "\\(bless\\|return\\|q[wqrx]?\\|tr\\|[smy]\\)\\>")))
4633a7c4 3423 (progn
c07a80fd 3424 (skip-chars-backward " \t\n\f")
499d5216 3425 (and (memq (char-syntax (preceding-char)) '(?w ?_))
c07a80fd 3426 (progn
3427 (backward-sexp)
3428 (looking-at
ebcd4dbc
IZ
3429 "sub[ \t]+[a-zA-Z0-9_:]+[ \t\n\f]*\\(([^()]*)[ \t\n\f]*\\)?[#{]")))))))))
3430
3431(defvar cperl-look-for-prop '((pod in-pod) (here-doc-delim here-doc-group)))
4633a7c4 3432
6c72d195 3433(defun cperl-calculate-indent (&optional parse-data) ; was parse-start
c07a80fd 3434 "Return appropriate indentation for current line as Perl code.
3435In usual case returns an integer: the column to indent to.
4584684c
GS
3436Returns nil if line starts inside a string, t if in a comment.
3437
3438Will not correct the indentation for labels, but will correct it for braces
3439and closing parentheses and brackets.."
c07a80fd 3440 (save-excursion
ebcd4dbc 3441 (if (or
7bcea553
IZ
3442 (and (memq (get-text-property (point) 'syntax-type)
3443 '(pod here-doc here-doc-delim format))
3444 (not (get-text-property (point) 'indentable)))
ebcd4dbc
IZ
3445 ;; before start of POD - whitespace found since do not have 'pod!
3446 (and (looking-at "[ \t]*\n=")
05bbd9c3
IZ
3447 (error "Spaces before pod section!"))
3448 (and (not cperl-indent-left-aligned-comments)
3449 (looking-at "^#")))
ebcd4dbc
IZ
3450 nil
3451 (beginning-of-line)
3452 (let ((indent-point (point))
3453 (char-after (save-excursion
3454 (skip-chars-forward " \t")
3455 (following-char)))
3456 (in-pod (get-text-property (point) 'in-pod))
3457 (pre-indent-point (point))
7bcea553 3458 p prop look-prop is-block delim)
ebcd4dbc
IZ
3459 (cond
3460 (in-pod
6c72d195 3461 ;; In the verbatim part, probably code example. What to do???
ebcd4dbc
IZ
3462 )
3463 (t
3464 (save-excursion
3465 ;; Not in pod
3466 (cperl-backward-to-noncomment nil)
3467 (setq p (max (point-min) (1- (point)))
3468 prop (get-text-property p 'syntax-type)
3469 look-prop (or (nth 1 (assoc prop cperl-look-for-prop))
3470 'syntax-type))
3471 (if (memq prop '(pod here-doc format here-doc-delim))
3472 (progn
3473 (goto-char (or (previous-single-property-change p look-prop)
3474 (point-min)))
3475 (beginning-of-line)
3476 (setq pre-indent-point (point)))))))
3477 (goto-char pre-indent-point)
3478 (let* ((case-fold-search nil)
6c72d195 3479 (s-s (cperl-get-state (car parse-data) (nth 1 parse-data)))
4584684c
GS
3480 (start (or (nth 2 parse-data)
3481 (nth 0 s-s)))
c07a80fd 3482 (state (nth 1 s-s))
3483 (containing-sexp (car (cdr state)))
c07a80fd 3484 old-indent)
4584684c
GS
3485 (if (and
3486 ;;containing-sexp ;; We are buggy at toplevel :-(
3487 parse-data)
6c72d195
IZ
3488 (progn
3489 (setcar parse-data pre-indent-point)
20675f5d 3490 (setcar (cdr parse-data) state)
4584684c
GS
3491 (or (nth 2 parse-data)
3492 (setcar (cddr parse-data) start))
3493 ;; Before this point: end of statement
3494 (setq old-indent (nth 3 parse-data))))
7bcea553
IZ
3495 (cond ((get-text-property (point) 'indentable)
3496 ;; indent to just after the surrounding open,
3497 ;; skip blanks if we do not close the expression.
3498 (goto-char (1+ (previous-single-property-change (point) 'indentable)))
3499 (or (memq char-after (append ")]}" nil))
3500 (looking-at "[ \t]*\\(#\\|$\\)")
3501 (skip-chars-forward " \t"))
3502 (current-column))
3503 ((or (nth 3 state) (nth 4 state))
c07a80fd 3504 ;; return nil or t if should not change this line
3505 (nth 4 state))
7bcea553 3506 ;; XXXX Do we need to special-case this?
c07a80fd 3507 ((null containing-sexp)
3508 ;; Line is at top level. May be data or function definition,
3509 ;; or may be function argument declaration.
3510 ;; Indent like the previous top level line
3511 ;; unless that ends in a closeparen without semicolon,
3512 ;; in which case this line is the first argument decl.
3513 (skip-chars-forward " \t")
4584684c
GS
3514 (+ (save-excursion
3515 (goto-char start)
3516 (- (current-indentation)
3517 (if (nth 2 s-s) cperl-indent-level 0)))
20675f5d 3518 (if (= char-after ?{) cperl-continued-brace-offset 0)
c07a80fd 3519 (progn
20675f5d 3520 (cperl-backward-to-noncomment (or old-indent (point-min)))
c07a80fd 3521 ;; Look at previous line that's at column 0
3522 ;; to determine whether we are in top-level decls
3523 ;; or function's arg decls. Set basic-indent accordingly.
3524 ;; Now add a little if this is a continuation line.
3525 (if (or (bobp)
4584684c 3526 (eq (point) old-indent) ; old-indent was at comment
6c72d195
IZ
3527 (eq (preceding-char) ?\;)
3528 ;; Had ?\) too
3529 (and (eq (preceding-char) ?\})
4584684c
GS
3530 (cperl-after-block-and-statement-beg
3531 (point-min))) ; Was start - too close
55497cff 3532 (memq char-after (append ")]}" nil))
3533 (and (eq (preceding-char) ?\:) ; label
3534 (progn
3535 (forward-sexp -1)
3536 (skip-chars-backward " \t")
3537 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*[ \t]*:"))))
20675f5d
IZ
3538 (progn
3539 (if (and parse-data
3540 (not (eq char-after ?\C-j)))
4584684c 3541 (setcdr (cddr parse-data)
20675f5d
IZ
3542 (list pre-indent-point)))
3543 0)
c07a80fd 3544 cperl-continued-statement-offset))))
7bcea553
IZ
3545 ((not
3546 (or (setq is-block
3547 (and (setq delim (= (char-after containing-sexp) ?{))
3548 (save-excursion ; Is it a hash?
3549 (goto-char containing-sexp)
3550 (cperl-block-p))))
3551 cperl-indent-parens-as-block))
3552 ;; group is an expression, not a block:
3553 ;; indent to just after the surrounding open parens,
c07a80fd 3554 ;; skip blanks if we do not close the expression.
3555 (goto-char (1+ containing-sexp))
7bcea553
IZ
3556 (or (memq char-after
3557 (append (if delim "}" ")]}") nil))
c07a80fd 3558 (looking-at "[ \t]*\\(#\\|$\\)")
3559 (skip-chars-forward " \t"))
7bcea553
IZ
3560 (+ (current-column)
3561 (if (and delim
3562 (eq char-after ?\}))
3563 ;; Correct indentation of trailing ?\}
3564 (+ cperl-indent-level cperl-close-paren-offset)
c07a80fd 3565 0)))
7bcea553
IZ
3566;;; ((and (/= (char-after containing-sexp) ?{)
3567;;; (not cperl-indent-parens-as-block))
3568;;; ;; line is expression, not statement:
3569;;; ;; indent to just after the surrounding open,
3570;;; ;; skip blanks if we do not close the expression.
3571;;; (goto-char (1+ containing-sexp))
3572;;; (or (memq char-after (append ")]}" nil))
3573;;; (looking-at "[ \t]*\\(#\\|$\\)")
3574;;; (skip-chars-forward " \t"))
3575;;; (current-column))
3576;;; ((progn
3577;;; ;; Containing-expr starts with \{. Check whether it is a hash.
3578;;; (goto-char containing-sexp)
3579;;; (and (not (cperl-block-p))
3580;;; (not cperl-indent-parens-as-block)))
3581;;; (goto-char (1+ containing-sexp))
3582;;; (or (eq char-after ?\})
3583;;; (looking-at "[ \t]*\\(#\\|$\\)")
3584;;; (skip-chars-forward " \t"))
3585;;; (+ (current-column) ; Correct indentation of trailing ?\}
3586;;; (if (eq char-after ?\}) (+ cperl-indent-level
3587;;; cperl-close-paren-offset)
3588;;; 0)))
c07a80fd 3589 (t
3590 ;; Statement level. Is it a continuation or a new statement?
3591 ;; Find previous non-comment character.
ebcd4dbc 3592 (goto-char pre-indent-point)
c07a80fd 3593 (cperl-backward-to-noncomment containing-sexp)
3594 ;; Back up over label lines, since they don't
3595 ;; affect whether our line is a continuation.
4584684c
GS
3596 ;; (Had \, too)
3597 (while ;;(or (eq (preceding-char) ?\,)
c07a80fd 3598 (and (eq (preceding-char) ?:)
3599 (or;;(eq (char-after (- (point) 2)) ?\') ; ????
3600 (memq (char-syntax (char-after (- (point) 2)))
4584684c
GS
3601 '(?w ?_))))
3602 ;;)
c07a80fd 3603 (if (eq (preceding-char) ?\,)
3604 ;; Will go to beginning of line, essentially.
3605 ;; Will ignore embedded sexpr XXXX.
3606 (cperl-backward-to-start-of-continued-exp containing-sexp))
3607 (beginning-of-line)
3608 (cperl-backward-to-noncomment containing-sexp))
3609 ;; Now we get the answer.
7bcea553
IZ
3610 (if (not (or (eq (1- (point)) containing-sexp)
3611 (memq (preceding-char)
3612 (append (if is-block " ;{" " ,;{") '(nil)))
6c72d195
IZ
3613 (and (eq (preceding-char) ?\})
3614 (cperl-after-block-and-statement-beg
7bcea553 3615 containing-sexp))))
c07a80fd 3616 ;; This line is continuation of preceding line's statement;
3617 ;; indent `cperl-continued-statement-offset' more than the
3618 ;; previous line of the statement.
4584684c
GS
3619 ;;
3620 ;; There might be a label on this line, just
3621 ;; consider it bad style and ignore it.
4633a7c4 3622 (progn
c07a80fd 3623 (cperl-backward-to-start-of-continued-exp containing-sexp)
3624 (+ (if (memq char-after (append "}])" nil))
3625 0 ; Closing parenth
3626 cperl-continued-statement-offset)
7bcea553
IZ
3627 (if (or is-block
3628 (not delim)
3629 (not (eq char-after ?\})))
3630 0
3631 ;; Now it is a hash reference
3632 (+ cperl-indent-level cperl-close-paren-offset))
4584684c
GS
3633 (if (looking-at "\\w+[ \t]*:")
3634 (if (> (current-indentation) cperl-min-label-indent)
3635 (- (current-indentation) cperl-label-offset)
3636 ;; Do not move `parse-data', this should
3637 ;; be quick anyway (this comment comes
3638 ;;from different location):
3639 (cperl-calculate-indent))
3640 (current-column))
c07a80fd 3641 (if (eq char-after ?\{)
3642 cperl-continued-brace-offset 0)))
3643 ;; This line starts a new statement.
3644 ;; Position following last unclosed open.
3645 (goto-char containing-sexp)
3646 ;; Is line first statement after an open-brace?
3647 (or
3648 ;; If no, find that first statement and indent like
3649 ;; it. If the first statement begins with label, do
55497cff 3650 ;; not believe when the indentation of the label is too
c07a80fd 3651 ;; small.
3652 (save-excursion
3653 (forward-char 1)
3654 (setq old-indent (current-indentation))
3655 (let ((colon-line-end 0))
3656 (while (progn (skip-chars-forward " \t\n")
3657 (looking-at "#\\|[a-zA-Z0-9_$]*:[^:]"))
3658 ;; Skip over comments and labels following openbrace.
3659 (cond ((= (following-char) ?\#)
3660 (forward-line 1))
3661 ;; label:
3662 (t
3663 (save-excursion (end-of-line)
3664 (setq colon-line-end (point)))
3665 (search-forward ":"))))
3666 ;; The first following code counts
3667 ;; if it is before the line we want to indent.
3668 (and (< (point) indent-point)
3669 (if (> colon-line-end (point)) ; After label
3670 (if (> (current-indentation)
3671 cperl-min-label-indent)
3672 (- (current-indentation) cperl-label-offset)
55497cff 3673 ;; Do not believe: `max' is involved
c07a80fd 3674 (+ old-indent cperl-indent-level))
3675 (current-column)))))
3676 ;; If no previous statement,
3677 ;; indent it relative to line brace is on.
3678 ;; For open brace in column zero, don't let statement
3679 ;; start there too. If cperl-indent-level is zero,
3680 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
3681 ;; For open-braces not the first thing in a line,
3682 ;; add in cperl-brace-imaginary-offset.
3683
3684 ;; If first thing on a line: ?????
3685 (+ (if (and (bolp) (zerop cperl-indent-level))
3686 (+ cperl-brace-offset cperl-continued-statement-offset)
3687 cperl-indent-level)
7bcea553
IZ
3688 (if (or is-block
3689 (not delim)
3690 (not (eq char-after ?\})))
3691 0
3692 ;; Now it is a hash reference
3693 (+ cperl-indent-level cperl-close-paren-offset))
c07a80fd 3694 ;; Move back over whitespace before the openbrace.
3695 ;; If openbrace is not first nonwhite thing on the line,
3696 ;; add the cperl-brace-imaginary-offset.
3697 (progn (skip-chars-backward " \t")
3698 (if (bolp) 0 cperl-brace-imaginary-offset))
3699 ;; If the openbrace is preceded by a parenthesized exp,
3700 ;; move to the beginning of that;
3701 ;; possibly a different line
3702 (progn
3703 (if (eq (preceding-char) ?\))
3704 (forward-sexp -1))
9ea28adb 3705 ;; In the case it starts a subroutine, indent with
3706 ;; respect to `sub', not with respect to the the
3707 ;; first thing on the line, say in the case of
3708 ;; anonymous sub in a hash.
3709 ;;
3710 (skip-chars-backward " \t")
3711 (if (and (eq (preceding-char) ?b)
3712 (progn
ebcd4dbc 3713 (forward-sexp -1)
9ea28adb 3714 (looking-at "sub\\>"))
3715 (setq old-indent
3716 (nth 1
3717 (parse-partial-sexp
3718 (save-excursion (beginning-of-line) (point))
3719 (point)))))
3720 (progn (goto-char (1+ old-indent))
3721 (skip-chars-forward " \t")
3722 (current-column))
3723 ;; Get initial indentation of the line we are on.
3724 ;; If line starts with label, calculate label indentation
3725 (if (save-excursion
3726 (beginning-of-line)
ebcd4dbc 3727 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
9ea28adb 3728 (if (> (current-indentation) cperl-min-label-indent)
3729 (- (current-indentation) cperl-label-offset)
6c72d195
IZ
3730 ;; Do not move `parse-data', this should
3731 ;; be quick anyway:
3732 (cperl-calculate-indent))
ebcd4dbc 3733 (current-indentation))))))))))))))
4633a7c4
LW
3734
3735(defvar cperl-indent-alist
3736 '((string nil)
3737 (comment nil)
3738 (toplevel 0)
3739 (toplevel-after-parenth 2)
3740 (toplevel-continued 2)
3741 (expression 1))
3742 "Alist of indentation rules for CPerl mode.
3743The values mean:
3744 nil: do not indent;
6c72d195
IZ
3745 number: add this amount of indentation.
3746
3747Not finished, not used.")
4633a7c4
LW
3748
3749(defun cperl-where-am-i (&optional parse-start start-state)
3750 ;; Unfinished
c07a80fd 3751 "Return a list of lists ((TYPE POS)...) of good points before the point.
6c72d195
IZ
3752POS may be nil if it is hard to find, say, when TYPE is `string' or `comment'.
3753
3754Not finished, not used."
4633a7c4 3755 (save-excursion
c07a80fd 3756 (let* ((start-point (point))
3757 (s-s (cperl-get-state))
3758 (start (nth 0 s-s))
3759 (state (nth 1 s-s))
3760 (prestart (nth 3 s-s))
3761 (containing-sexp (car (cdr state)))
3762 (case-fold-search nil)
3763 (res (list (list 'parse-start start) (list 'parse-prestart prestart))))
4633a7c4 3764 (cond ((nth 3 state) ; In string
c07a80fd 3765 (setq res (cons (list 'string nil (nth 3 state)) res))) ; What started string
4633a7c4 3766 ((nth 4 state) ; In comment
c07a80fd 3767 (setq res (cons '(comment) res)))
4633a7c4
LW
3768 ((null containing-sexp)
3769 ;; Line is at top level.
3770 ;; Indent like the previous top level line
3771 ;; unless that ends in a closeparen without semicolon,
3772 ;; in which case this line is the first argument decl.
3773 (cperl-backward-to-noncomment (or parse-start (point-min)))
c07a80fd 3774 ;;(skip-chars-backward " \t\f\n")
4633a7c4
LW
3775 (cond
3776 ((or (bobp)
3777 (memq (preceding-char) (append ";}" nil)))
c07a80fd 3778 (setq res (cons (list 'toplevel start) res)))
4633a7c4 3779 ((eq (preceding-char) ?\) )
c07a80fd 3780 (setq res (cons (list 'toplevel-after-parenth start) res)))
3781 (t
3782 (setq res (cons (list 'toplevel-continued start) res)))))
4633a7c4
LW
3783 ((/= (char-after containing-sexp) ?{)
3784 ;; line is expression, not statement:
3785 ;; indent to just after the surrounding open.
c07a80fd 3786 ;; skip blanks if we do not close the expression.
3787 (setq res (cons (list 'expression-blanks
3788 (progn
3789 (goto-char (1+ containing-sexp))
3790 (or (looking-at "[ \t]*\\(#\\|$\\)")
3791 (skip-chars-forward " \t"))
3792 (point)))
3793 (cons (list 'expression containing-sexp) res))))
4633a7c4 3794 ((progn
6c72d195 3795 ;; Containing-expr starts with \{. Check whether it is a hash.
4633a7c4 3796 (goto-char containing-sexp)
c07a80fd 3797 (not (cperl-block-p)))
3798 (setq res (cons (list 'expression-blanks
3799 (progn
3800 (goto-char (1+ containing-sexp))
3801 (or (looking-at "[ \t]*\\(#\\|$\\)")
3802 (skip-chars-forward " \t"))
3803 (point)))
3804 (cons (list 'expression containing-sexp) res))))
4633a7c4 3805 (t
c07a80fd 3806 ;; Statement level.
3807 (setq res (cons (list 'in-block containing-sexp) res))
3808 ;; Is it a continuation or a new statement?
4633a7c4
LW
3809 ;; Find previous non-comment character.
3810 (cperl-backward-to-noncomment containing-sexp)
3811 ;; Back up over label lines, since they don't
3812 ;; affect whether our line is a continuation.
c07a80fd 3813 ;; Back up comma-delimited lines too ?????
4633a7c4 3814 (while (or (eq (preceding-char) ?\,)
c07a80fd 3815 (save-excursion (cperl-after-label)))
4633a7c4 3816 (if (eq (preceding-char) ?\,)
c07a80fd 3817 ;; Will go to beginning of line, essentially
3818 ;; Will ignore embedded sexpr XXXX.
4633a7c4
LW
3819 (cperl-backward-to-start-of-continued-exp containing-sexp))
3820 (beginning-of-line)
3821 (cperl-backward-to-noncomment containing-sexp))
3822 ;; Now we get the answer.
3823 (if (not (memq (preceding-char) (append ";}{" '(nil)))) ; Was ?\,
3824 ;; This line is continuation of preceding line's statement.
c07a80fd 3825 (list (list 'statement-continued containing-sexp))
4633a7c4
LW
3826 ;; This line starts a new statement.
3827 ;; Position following last unclosed open.
3828 (goto-char containing-sexp)
3829 ;; Is line first statement after an open-brace?
3830 (or
3831 ;; If no, find that first statement and indent like
3832 ;; it. If the first statement begins with label, do
55497cff 3833 ;; not believe when the indentation of the label is too
4633a7c4
LW
3834 ;; small.
3835 (save-excursion
3836 (forward-char 1)
4633a7c4 3837 (let ((colon-line-end 0))
c07a80fd 3838 (while (progn (skip-chars-forward " \t\n" start-point)
3839 (and (< (point) start-point)
3840 (looking-at
3841 "#\\|[a-zA-Z_][a-zA-Z0-9_]*:[^:]")))
4633a7c4
LW
3842 ;; Skip over comments and labels following openbrace.
3843 (cond ((= (following-char) ?\#)
c07a80fd 3844 ;;(forward-line 1)
3845 (end-of-line))
4633a7c4
LW
3846 ;; label:
3847 (t
3848 (save-excursion (end-of-line)
3849 (setq colon-line-end (point)))
3850 (search-forward ":"))))
c07a80fd 3851 ;; Now at the point, after label, or at start
3852 ;; of first statement in the block.
4633a7c4 3853 (and (< (point) start-point)
c07a80fd 3854 (if (> colon-line-end (point))
3855 ;; Before statement after label
4633a7c4
LW
3856 (if (> (current-indentation)
3857 cperl-min-label-indent)
c07a80fd 3858 (list (list 'label-in-block (point)))
55497cff 3859 ;; Do not believe: `max' is involved
c07a80fd 3860 (list
3861 (list 'label-in-block-min-indent (point))))
3862 ;; Before statement
3863 (list 'statement-in-block (point))))))
4633a7c4
LW
3864 ;; If no previous statement,
3865 ;; indent it relative to line brace is on.
3866 ;; For open brace in column zero, don't let statement
3867 ;; start there too. If cperl-indent-level is zero,
3868 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
3869 ;; For open-braces not the first thing in a line,
3870 ;; add in cperl-brace-imaginary-offset.
3871
3872 ;; If first thing on a line: ?????
3873 (+ (if (and (bolp) (zerop cperl-indent-level))
3874 (+ cperl-brace-offset cperl-continued-statement-offset)
3875 cperl-indent-level)
3876 ;; Move back over whitespace before the openbrace.
3877 ;; If openbrace is not first nonwhite thing on the line,
3878 ;; add the cperl-brace-imaginary-offset.
3879 (progn (skip-chars-backward " \t")
3880 (if (bolp) 0 cperl-brace-imaginary-offset))
3881 ;; If the openbrace is preceded by a parenthesized exp,
3882 ;; move to the beginning of that;
3883 ;; possibly a different line
3884 (progn
3885 (if (eq (preceding-char) ?\))
3886 (forward-sexp -1))
3887 ;; Get initial indentation of the line we are on.
3888 ;; If line starts with label, calculate label indentation
3889 (if (save-excursion
3890 (beginning-of-line)
ebcd4dbc 3891 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
4633a7c4
LW
3892 (if (> (current-indentation) cperl-min-label-indent)
3893 (- (current-indentation) cperl-label-offset)
6c72d195 3894 (cperl-calculate-indent))
c07a80fd 3895 (current-indentation))))))))
3896 res)))
4633a7c4
LW
3897
3898(defun cperl-calculate-indent-within-comment ()
3899 "Return the indentation amount for line, assuming that
3900the current line is to be regarded as part of a block comment."
3901 (let (end star-start)
3902 (save-excursion
3903 (beginning-of-line)
3904 (skip-chars-forward " \t")
3905 (setq end (point))
3906 (and (= (following-char) ?#)
3907 (forward-line -1)
3908 (cperl-to-comment-or-eol)
3909 (setq end (point)))
3910 (goto-char end)
3911 (current-column))))
3912
3913
3914(defun cperl-to-comment-or-eol ()
3915 "Goes to position before comment on the current line, or to end of line.
3916Returns true if comment is found."
3917 (let (state stop-in cpoint (lim (progn (end-of-line) (point))))
3918 (beginning-of-line)
ebcd4dbc
IZ
3919 (if (or
3920 (eq (get-text-property (point) 'syntax-type) 'pod)
3921 (re-search-forward "\\=[ \t]*\\(#\\|$\\)" lim t))
4633a7c4
LW
3922 (if (eq (preceding-char) ?\#) (progn (backward-char 1) t))
3923 ;; Else
3924 (while (not stop-in)
3925 (setq state (parse-partial-sexp (point) lim nil nil nil t))
3926 ; stop at comment
3927 ;; If fails (beginning-of-line inside sexp), then contains not-comment
4633a7c4
LW
3928 (if (nth 4 state) ; After `#';
3929 ; (nth 2 state) can be
3930 ; beginning of m,s,qq and so
3931 ; on
3932 (if (nth 2 state)
3933 (progn
3934 (setq cpoint (point))
3935 (goto-char (nth 2 state))
3936 (cond
3937 ((looking-at "\\(s\\|tr\\)\\>")
3938 (or (re-search-forward
3939 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*"
3940 lim 'move)
3941 (setq stop-in t)))
20675f5d 3942 ((looking-at "\\(m\\|q\\([qxwr]\\)?\\)\\>")
4633a7c4
LW
3943 (or (re-search-forward
3944 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#"
3945 lim 'move)
3946 (setq stop-in t)))
3947 (t ; It was fair comment
3948 (setq stop-in t) ; Finish
3949 (goto-char (1- cpoint)))))
3950 (setq stop-in t) ; Finish
3951 (forward-char -1))
3952 (setq stop-in t)) ; Finish
3953 )
3954 (nth 4 state))))
3955
ebcd4dbc
IZ
3956(defsubst cperl-1- (p)
3957 (max (point-min) (1- p)))
3958
3959(defsubst cperl-1+ (p)
3960 (min (point-max) (1+ p)))
3961
3ee700d1
IZ
3962(defsubst cperl-modify-syntax-type (at how)
3963 (if (< at (point-max))
3964 (progn
3965 (put-text-property at (1+ at) 'syntax-table how)
3966 (put-text-property at (1+ at) 'rear-nonsticky t))))
ebcd4dbc
IZ
3967
3968(defun cperl-protect-defun-start (s e)
3969 ;; C code looks for "^\\s(" to skip comment backward in "hard" situations
3970 (save-excursion
3971 (goto-char s)
3972 (while (re-search-forward "^\\s(" e 'to-end)
3973 (put-text-property (1- (point)) (point) 'syntax-table cperl-st-punct))))
3974
20675f5d 3975(defun cperl-commentify (bb e string &optional noface)
ebcd4dbc 3976 (if cperl-use-syntax-table-text-property
20675f5d
IZ
3977 (if (eq noface 'n) ; Only immediate
3978 nil
ebcd4dbc
IZ
3979 ;; We suppose that e is _after_ the end of construction, as after eol.
3980 (setq string (if string cperl-st-sfence cperl-st-cfence))
7bcea553
IZ
3981 (if (> bb (- e 2))
3982 ;; one-char string/comment?!
3983 (cperl-modify-syntax-type bb cperl-st-punct)
3984 (cperl-modify-syntax-type bb string)
3985 (cperl-modify-syntax-type (1- e) string))
ebcd4dbc
IZ
3986 (if (and (eq string cperl-st-sfence) (> (- e 2) bb))
3987 (put-text-property (1+ bb) (1- e)
3988 'syntax-table cperl-string-syntax-table))
20675f5d
IZ
3989 (cperl-protect-defun-start bb e))
3990 ;; Fontify
3991 (or noface
3992 (not cperl-pod-here-fontify)
3993 (put-text-property bb e 'face (if string 'font-lock-string-face
3994 'font-lock-comment-face)))))
7bcea553 3995
20675f5d
IZ
3996(defvar cperl-starters '(( ?\( . ?\) )
3997 ( ?\[ . ?\] )
3998 ( ?\{ . ?\} )
3999 ( ?\< . ?\> )))
ebcd4dbc 4000
3ee700d1
IZ
4001(defun cperl-forward-re (lim end is-2arg set-st st-l err-l argument
4002 &optional ostart oend)
05bbd9c3
IZ
4003 ;; Works *before* syntax recognition is done
4004 ;; May modify syntax-type text property if the situation is too hard
7bcea553 4005 (let (b starter ender st i i2 go-forward reset-st)
05bbd9c3
IZ
4006 (skip-chars-forward " \t")
4007 ;; ender means matching-char matcher.
4008 (setq b (point)
4584684c 4009 starter (if (eobp) 0 (char-after b))
20675f5d 4010 ender (cdr (assoc starter cperl-starters)))
05bbd9c3
IZ
4011 ;; What if starter == ?\\ ????
4012 (if set-st
4013 (if (car st-l)
4014 (setq st (car st-l))
4015 (setcar st-l (make-syntax-table))
4016 (setq i 0 st (car st-l))
4017 (while (< i 256)
4018 (modify-syntax-entry i "." st)
4019 (setq i (1+ i)))
4020 (modify-syntax-entry ?\\ "\\" st)))
4021 (setq set-st t)
4022 ;; Whether we have an intermediate point
4023 (setq i nil)
4024 ;; Prepare the syntax table:
4025 (and set-st
4026 (if (not ender) ; m/blah/, s/x//, s/x/y/
4027 (modify-syntax-entry starter "$" st)
4028 (modify-syntax-entry starter (concat "(" (list ender)) st)
4029 (modify-syntax-entry ender (concat ")" (list starter)) st)))
4030 (condition-case bb
4031 (progn
20675f5d
IZ
4032 ;; We use `$' syntax class to find matching stuff, but $$
4033 ;; is recognized the same as $, so we need to check this manually.
05bbd9c3
IZ
4034 (if (and (eq starter (char-after (cperl-1+ b)))
4035 (not ender))
4036 ;; $ has TeXish matching rules, so $$ equiv $...
4037 (forward-char 2)
7bcea553 4038 (setq reset-st (syntax-table))
05bbd9c3
IZ
4039 (set-syntax-table st)
4040 (forward-sexp 1)
7bcea553
IZ
4041 (if (<= (point) (1+ b))
4042 (error "Unfinished regular expression"))
4043 (set-syntax-table reset-st)
4044 (setq reset-st nil)
05bbd9c3
IZ
4045 ;; Now the problem is with m;blah;;
4046 (and (not ender)
4047 (eq (preceding-char)
4048 (char-after (- (point) 2)))
4049 (save-excursion
4050 (forward-char -2)
4051 (= 0 (% (skip-chars-backward "\\\\") 2)))
4052 (forward-char -1)))
20675f5d 4053 ;; Now we are after the first part.
05bbd9c3
IZ
4054 (and is-2arg ; Have trailing part
4055 (not ender)
4056 (eq (following-char) starter) ; Empty trailing part
3ee700d1
IZ
4057 (progn
4058 (or (eq (char-syntax (following-char)) ?.)
4059 ;; Make trailing letter into punctuation
4060 (cperl-modify-syntax-type (point) cperl-st-punct))
4061 (setq is-2arg nil go-forward t))) ; Ignore the tail
05bbd9c3
IZ
4062 (if is-2arg ; Not number => have second part
4063 (progn
4064 (setq i (point) i2 i)
4065 (if ender
3ee700d1 4066 (if (memq (following-char) '(?\ ?\t ?\n ?\f))
05bbd9c3 4067 (progn
3ee700d1
IZ
4068 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
4069 (goto-char (match-end 0))
4070 (skip-chars-forward " \t\n\f"))
05bbd9c3
IZ
4071 (setq i2 (point))))
4072 (forward-char -1))
4073 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
4074 (if ender (modify-syntax-entry ender "." st))
4075 (setq set-st nil)
20675f5d
IZ
4076 (setq ender (cperl-forward-re lim end nil t st-l err-l
4077 argument starter ender)
4078 ender (nth 2 ender)))))
3ee700d1
IZ
4079 (error (goto-char lim)
4080 (setq set-st nil)
7bcea553
IZ
4081 (if reset-st
4082 (set-syntax-table reset-st))
3ee700d1
IZ
4083 (or end
4084 (message
20675f5d 4085 "End of `%s%s%c ... %c' string/RE not found: %s"
3ee700d1
IZ
4086 argument
4087 (if ostart (format "%c ... %c" ostart (or oend ostart)) "")
4088 starter (or ender starter) bb)
4089 (or (car err-l) (setcar err-l b)))))
05bbd9c3
IZ
4090 (if set-st
4091 (progn
4092 (modify-syntax-entry starter (if (eq starter ?\\) "\\" ".") st)
4093 (if ender (modify-syntax-entry ender "." st))))
20675f5d
IZ
4094 ;; i: have 2 args, after end of the first arg
4095 ;; i2: start of the second arg, if any (before delim iff `ender').
4096 ;; ender: the last arg bounded by parens-like chars, the second one of them
4097 ;; starter: the starting delimiter of the first arg
7bcea553 4098 ;; go-forward: has 2 args, and the second part is empty
3ee700d1 4099 (list i i2 ender starter go-forward)))
05bbd9c3 4100
6c72d195 4101(defvar font-lock-string-face)
20675f5d 4102;;(defvar font-lock-reference-face)
6c72d195 4103(defvar font-lock-constant-face)
20675f5d
IZ
4104(defsubst cperl-postpone-fontification (b e type val &optional now)
4105 ;; Do after syntactic fontification?
4106 (if cperl-syntaxify-by-font-lock
4107 (or now (put-text-property b e 'cperl-postpone (cons type val)))
4108 (put-text-property b e type val)))
4109
4110;;; Here is how the global structures (those which cannot be
4111;;; recognized locally) are marked:
4112;; a) PODs:
4113;; Start-to-end is marked `in-pod' ==> t
4114;; Each non-literal part is marked `syntax-type' ==> `pod'
4115;; Each literal part is marked `syntax-type' ==> `in-pod'
4116;; b) HEREs:
4117;; Start-to-end is marked `here-doc-group' ==> t
4118;; The body is marked `syntax-type' ==> `here-doc'
4119;; The delimiter is marked `syntax-type' ==> `here-doc-delim'
4584684c 4120;; c) FORMATs:
20675f5d 4121;; After-initial-line--to-end is marked `syntax-type' ==> `format'
4584684c
GS
4122;; d) 'Q'uoted string:
4123;; part between markers inclusive is marked `syntax-type' ==> `string'
7bcea553 4124;; part between `q' and the first marker is marked `syntax-type' ==> `prestring'
20675f5d 4125
4584684c
GS
4126(defun cperl-unwind-to-safe (before &optional end)
4127 ;; if BEFORE, go to the previous start-of-line on each step of unwinding
4128 (let ((pos (point)) opos)
4129 (setq opos pos)
20675f5d
IZ
4130 (while (and pos (get-text-property pos 'syntax-type))
4131 (setq pos (previous-single-property-change pos 'syntax-type))
4132 (if pos
4133 (if before
4134 (progn
4135 (goto-char (cperl-1- pos))
4136 (beginning-of-line)
4137 (setq pos (point)))
4138 (goto-char (setq pos (cperl-1- pos))))
4139 ;; Up to the start
4584684c 4140 (goto-char (point-min))))
7bcea553
IZ
4141 ;; Skip empty lines
4142 (and (looking-at "\n*=")
4143 (/= 0 (skip-chars-backward "\n"))
4144 (forward-char))
4145 (setq pos (point))
4584684c
GS
4146 (if end
4147 ;; Do the same for end, going small steps
4148 (progn
4149 (while (and end (get-text-property end 'syntax-type))
4150 (setq pos end
4151 end (next-single-property-change end 'syntax-type)))
4152 (or end pos)))))
20675f5d 4153
7bcea553
IZ
4154(defvar cperl-nonoverridable-face)
4155(defvar font-lock-function-name-face)
4156(defvar font-lock-comment-face)
4157
6c72d195 4158(defun cperl-find-pods-heres (&optional min max non-inter end ignore-max)
05bbd9c3 4159 "Scans the buffer for hard-to-parse Perl constructions.
c07a80fd 4160If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify
4161the sections using `cperl-pod-head-face', `cperl-pod-face',
4162`cperl-here-face'."
4163 (interactive)
6c72d195
IZ
4164 (or min (setq min (point-min)
4165 cperl-syntax-state nil
4166 cperl-syntax-done-to min))
c07a80fd 4167 (or max (setq max (point-max)))
6c72d195 4168 (let* (face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb
7bcea553 4169 is-REx is-x-REx REx-comment-start REx-comment-end was-comment i2
6c72d195
IZ
4170 (cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend
4171 (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
4172 (modified (buffer-modified-p))
4173 (after-change-functions nil)
4174 (use-syntax-state (and cperl-syntax-state
4175 (>= min (car cperl-syntax-state))))
4176 (state-point (if use-syntax-state
4177 (car cperl-syntax-state)
4178 (point-min)))
4179 (state (if use-syntax-state
4180 (cdr cperl-syntax-state)))
7bcea553
IZ
4181 ;; (st-l '(nil)) (err-l '(nil)) ; Would overwrite - propagates from a function call to a function call!
4182 (st-l (list nil)) (err-l (list nil))
6c72d195
IZ
4183 ;; Somehow font-lock may be not loaded yet...
4184 (font-lock-string-face (if (boundp 'font-lock-string-face)
4185 font-lock-string-face
4186 'font-lock-string-face))
20675f5d
IZ
4187 (font-lock-constant-face (if (boundp 'font-lock-constant-face)
4188 font-lock-constant-face
4189 'font-lock-constant-face))
4190 (font-lock-function-name-face
4191 (if (boundp 'font-lock-function-name-face)
4192 font-lock-function-name-face
4193 'font-lock-function-name-face))
7bcea553
IZ
4194 (font-lock-comment-face
4195 (if (boundp 'font-lock-comment-face)
4196 font-lock-comment-face
4197 'font-lock-comment-face))
4584684c
GS
4198 (cperl-nonoverridable-face
4199 (if (boundp 'cperl-nonoverridable-face)
4200 cperl-nonoverridable-face
4201 'cperl-nonoverridable-face))
6c72d195
IZ
4202 (stop-point (if ignore-max
4203 (point-max)
4204 max))
4205 (search
4206 (concat
7bcea553 4207 "\\(\\`\n?\\|^\n\\)="
6c72d195
IZ
4208 "\\|"
4209 ;; One extra () before this:
4210 "<<"
4211 "\\(" ; 1 + 1
4212 ;; First variant "BLAH" or just ``.
7bcea553
IZ
4213 "[ \t]*" ; Yes, whitespace is allowed!
4214 "\\([\"'`]\\)" ; 2 + 1 = 3
6c72d195
IZ
4215 "\\([^\"'`\n]*\\)" ; 3 + 1
4216 "\\3"
4217 "\\|"
4218 ;; Second variant: Identifier or \ID or empty
4219 "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
4220 ;; Do not have <<= or << 30 or <<30 or << $blah.
4221 ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
4222 "\\(\\)" ; To preserve count of pars :-( 6 + 1
4223 "\\)"
4224 "\\|"
4225 ;; 1+6 extra () before this:
4226 "^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
4227 (if cperl-use-syntax-table-text-property
4228 (concat
4229 "\\|"
4230 ;; 1+6+2=9 extra () before this:
20675f5d 4231 "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
6c72d195
IZ
4232 "\\|"
4233 ;; 1+6+2+1=10 extra () before this:
4234 "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
4235 "\\|"
4236 ;; 1+6+2+1+1=11 extra () before this:
4237 "\\<sub\\>[ \t]*\\([a-zA-Z_:'0-9]+[ \t]*\\)?\\(([^()]*)\\)"
4238 "\\|"
4239 ;; 1+6+2+1+1+2=13 extra () before this:
4240 "\\$\\(['{]\\)"
4241 "\\|"
4242 ;; 1+6+2+1+1+2+1=14 extra () before this:
4243 "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'"
4244 ;; 1+6+2+1+1+2+1+1=15 extra () before this:
4245 "\\|"
7bcea553
IZ
4246 "__\\(END\\|DATA\\)__"
4247 ;; 1+6+2+1+1+2+1+1+1=16 extra () before this:
4248 "\\|"
4249 "\\\\\\(['`\"]\\)"
6c72d195
IZ
4250 )
4251 ""))))
c07a80fd 4252 (unwind-protect
4253 (progn
4254 (save-excursion
3ee700d1
IZ
4255 (or non-inter
4256 (message "Scanning for \"hard\" Perl constructions..."))
6c72d195 4257 (and cperl-pod-here-fontify
499d5216
IZ
4258 ;; We had evals here, do not know why...
4259 (setq face cperl-pod-face
4260 head-face cperl-pod-head-face
4261 here-face cperl-here-face))
ebcd4dbc 4262 (remove-text-properties min max
20675f5d 4263 '(syntax-type t in-pod t syntax-table t
7bcea553
IZ
4264 cperl-postpone t
4265 syntax-subtype t
4266 rear-nonsticky t
4267 indentable t))
c07a80fd 4268 ;; Need to remove face as well...
4269 (goto-char min)
6c72d195
IZ
4270 (and (eq system-type 'emx)
4271 (looking-at "extproc[ \t]") ; Analogue of #!
4272 (cperl-commentify min
4273 (save-excursion (end-of-line) (point))
4274 nil))
4275 (while (and
4276 (< (point) max)
4277 (re-search-forward search max t))
4278 (setq tmpend nil) ; Valid for most cases
499d5216
IZ
4279 (cond
4280 ((match-beginning 1) ; POD section
7bcea553
IZ
4281 ;; "\\(\\`\n?\\|^\n\\)="
4282 (if (looking-at "cut\\>")
6c72d195
IZ
4283 (if ignore-max
4284 nil ; Doing a chunk only
3ee700d1 4285 (message "=cut is not preceded by a POD section")
05bbd9c3 4286 (or (car err-l) (setcar err-l (point))))
c07a80fd 4287 (beginning-of-line)
499d5216 4288
6c72d195
IZ
4289 (setq b (point)
4290 bb b
20675f5d
IZ
4291 tb (match-beginning 0)
4292 b1 nil) ; error condition
6c72d195
IZ
4293 ;; We do not search to max, since we may be called from
4294 ;; some hook of fontification, and max is random
7bcea553 4295 (or (re-search-forward "^\n=cut\\>" stop-point 'toend)
ebcd4dbc 4296 (progn
7bcea553
IZ
4297 (goto-char b)
4298 (if (re-search-forward "\n=cut\\>" stop-point 'toend)
4299 (progn
4300 (message "=cut is not preceded by an empty line")
4301 (setq b1 t)
4302 (or (car err-l) (setcar err-l b))))))
ebcd4dbc 4303 (beginning-of-line 2) ; An empty line after =cut is not POD!
499d5216 4304 (setq e (point))
7bcea553
IZ
4305 (and (> e max)
4306 (progn
4307 (remove-text-properties
4308 max e '(syntax-type t in-pod t syntax-table t
4309 cperl-postpone t
4310 syntax-subtype t
4311 rear-nonsticky t
4312 indentable t))
4313 (setq tmpend tb)))
4314 (put-text-property b e 'in-pod t)
4315 (put-text-property b e 'syntax-type 'in-pod)
4316 (goto-char b)
4317 (while (re-search-forward "\n\n[ \t]" e t)
4318 ;; We start 'pod 1 char earlier to include the preceding line
4319 (beginning-of-line)
4320 (put-text-property (cperl-1- b) (point) 'syntax-type 'pod)
4321 (cperl-put-do-not-fontify b (point) t)
4322 ;; mark the non-literal parts as PODs
20675f5d 4323 (if cperl-pod-here-fontify
7bcea553
IZ
4324 (cperl-postpone-fontification b (point) 'face face t))
4325 (re-search-forward "\n\n[^ \t\f\n]" e 'toend)
4326 (beginning-of-line)
4327 (setq b (point)))
4328 (put-text-property (cperl-1- (point)) e 'syntax-type 'pod)
4329 (cperl-put-do-not-fontify (point) e t)
4330 (if cperl-pod-here-fontify
4331 (progn
4332 ;; mark the non-literal parts as PODs
4333 (cperl-postpone-fontification (point) e 'face face t)
4334 (goto-char bb)
4335 (if (looking-at
4336 "=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$")
20675f5d
IZ
4337 ;; mark the headers
4338 (cperl-postpone-fontification
4339 (match-beginning 1) (match-end 1)
7bcea553
IZ
4340 'face head-face))
4341 (while (re-search-forward
4342 ;; One paragraph
4343 "^\n=[a-zA-Z0-9_]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$"
4344 e 'toend)
4345 ;; mark the headers
4346 (cperl-postpone-fontification
4347 (match-beginning 1) (match-end 1)
4348 'face head-face))))
4349 (cperl-commentify bb e nil)
4350 (goto-char e)
4351 (or (eq e (point-max))
4352 (forward-char -1)))) ; Prepare for immediate pod start.
55497cff 4353 ;; Here document
ebcd4dbc 4354 ;; We do only one here-per-line
6c72d195
IZ
4355 ;; ;; One extra () before this:
4356 ;;"<<"
4357 ;; "\\(" ; 1 + 1
4358 ;; ;; First variant "BLAH" or just ``.
4359 ;; "\\([\"'`]\\)" ; 2 + 1
4360 ;; "\\([^\"'`\n]*\\)" ; 3 + 1
4361 ;; "\\3"
4362 ;; "\\|"
4363 ;; ;; Second variant: Identifier or \ID or empty
4364 ;; "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
4365 ;; ;; Do not have <<= or << 30 or <<30 or << $blah.
4366 ;; ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
4367 ;; "\\(\\)" ; To preserve count of pars :-( 6 + 1
4368 ;; "\\)"
55497cff 4369 ((match-beginning 2) ; 1 + 1
ebcd4dbc 4370 ;; Abort in comment:
55497cff 4371 (setq b (point))
ebcd4dbc 4372 (setq state (parse-partial-sexp state-point b nil nil state)
6c72d195
IZ
4373 state-point b
4374 tb (match-beginning 0)
4375 i (or (nth 3 state) (nth 4 state)))
4376 (if i
4377 (setq c t)
4378 (setq c (and
4379 (match-beginning 5)
4380 (not (match-beginning 6)) ; Empty
4381 (looking-at
20675f5d 4382 "[ \t]*[=0-9$@%&(]"))))
6c72d195
IZ
4383 (if c ; Not here-doc
4384 nil ; Skip it.
55497cff 4385 (if (match-beginning 5) ;4 + 1
4386 (setq b1 (match-beginning 5) ; 4 + 1
4387 e1 (match-end 5)) ; 4 + 1
4388 (setq b1 (match-beginning 4) ; 3 + 1
4389 e1 (match-end 4))) ; 3 + 1
4390 (setq tag (buffer-substring b1 e1)
4391 qtag (regexp-quote tag))
4392 (cond (cperl-pod-here-fontify
20675f5d
IZ
4393 ;; Highlight the starting delimiter
4394 (cperl-postpone-fontification b1 e1 'face font-lock-constant-face)
4395 (cperl-put-do-not-fontify b1 e1 t)))
55497cff 4396 (forward-line)
4397 (setq b (point))
6c72d195
IZ
4398 ;; We do not search to max, since we may be called from
4399 ;; some hook of fontification, and max is random
4400 (cond ((re-search-forward (concat "^" qtag "$")
4401 stop-point 'toend)
55497cff 4402 (if cperl-pod-here-fontify
4403 (progn
20675f5d
IZ
4404 ;; Highlight the ending delimiter
4405 (cperl-postpone-fontification (match-beginning 0) (match-end 0)
6c72d195 4406 'face font-lock-constant-face)
20675f5d
IZ
4407 (cperl-put-do-not-fontify b (match-end 0) t)
4408 ;; Highlight the HERE-DOC
4409 (cperl-postpone-fontification b (match-beginning 0)
55497cff 4410 'face here-face)))
ebcd4dbc 4411 (setq e1 (cperl-1+ (match-end 0)))
55497cff 4412 (put-text-property b (match-beginning 0)
4413 'syntax-type 'here-doc)
ebcd4dbc
IZ
4414 (put-text-property (match-beginning 0) e1
4415 'syntax-type 'here-doc-delim)
4416 (put-text-property b e1
4417 'here-doc-group t)
4418 (cperl-commentify b e1 nil)
20675f5d 4419 (cperl-put-do-not-fontify b (match-end 0) t)
6c72d195
IZ
4420 (if (> e1 max)
4421 (setq tmpend tb)))
ebcd4dbc 4422 (t (message "End of here-document `%s' not found." tag)
05bbd9c3 4423 (or (car err-l) (setcar err-l b))))))
55497cff 4424 ;; format
ebcd4dbc 4425 ((match-beginning 8)
5f05dabc 4426 ;; 1+6=7 extra () before this:
ebcd4dbc 4427 ;;"^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
55497cff 4428 (setq b (point)
5f05dabc 4429 name (if (match-beginning 8) ; 7 + 1
4430 (buffer-substring (match-beginning 8) ; 7 + 1
4431 (match-end 8)) ; 7 + 1
6c72d195
IZ
4432 "")
4433 tb (match-beginning 0))
55497cff 4434 (setq argument nil)
4435 (if cperl-pod-here-fontify
4436 (while (and (eq (forward-line) 0)
4437 (not (looking-at "^[.;]$")))
4438 (cond
4439 ((looking-at "^#")) ; Skip comments
4440 ((and argument ; Skip argument multi-lines
4441 (looking-at "^[ \t]*{"))
4442 (forward-sexp 1)
4443 (setq argument nil))
4444 (argument ; Skip argument lines
4445 (setq argument nil))
4446 (t ; Format line
4447 (setq b1 (point))
4448 (setq argument (looking-at "^[^\n]*[@^]"))
4449 (end-of-line)
20675f5d
IZ
4450 ;; Highlight the format line
4451 (cperl-postpone-fontification b1 (point)
55497cff 4452 'face font-lock-string-face)
ebcd4dbc 4453 (cperl-commentify b1 (point) nil)
20675f5d 4454 (cperl-put-do-not-fontify b1 (point) t))))
6c72d195
IZ
4455 ;; We do not search to max, since we may be called from
4456 ;; some hook of fontification, and max is random
4457 (re-search-forward "^[.;]$" stop-point 'toend))
55497cff 4458 (beginning-of-line)
20675f5d 4459 (if (looking-at "^\\.$") ; ";" is not supported yet
55497cff 4460 (progn
20675f5d
IZ
4461 ;; Highlight the ending delimiter
4462 (cperl-postpone-fontification (point) (+ (point) 2)
55497cff 4463 'face font-lock-string-face)
ebcd4dbc 4464 (cperl-commentify (point) (+ (point) 2) nil)
20675f5d 4465 (cperl-put-do-not-fontify (point) (+ (point) 2) t))
ebcd4dbc 4466 (message "End of format `%s' not found." name)
05bbd9c3 4467 (or (car err-l) (setcar err-l b)))
55497cff 4468 (forward-line)
6c72d195
IZ
4469 (if (> (point) max)
4470 (setq tmpend tb))
4471 (put-text-property b (point) 'syntax-type 'format))
ebcd4dbc
IZ
4472 ;; Regexp:
4473 ((or (match-beginning 10) (match-beginning 11))
4474 ;; 1+6+2=9 extra () before this:
20675f5d 4475 ;; "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
05bbd9c3 4476 ;; "\\|"
6c72d195 4477 ;; "\\([?/<]\\)" ; /blah/ or ?blah? or <file*glob>
ebcd4dbc
IZ
4478 (setq b1 (if (match-beginning 10) 10 11)
4479 argument (buffer-substring
4480 (match-beginning b1) (match-end b1))
4481 b (point)
4482 i b
4483 c (char-after (match-beginning b1))
05bbd9c3 4484 bb (char-after (1- (match-beginning b1))) ; tmp holder
4584684c 4485 ;; bb == "Not a stringy"
20675f5d
IZ
4486 bb (if (eq b1 10) ; user variables/whatever
4487 (or
4488 (memq bb '(?\$ ?\@ ?\% ?\* ?\#)) ; $#y
4489 (and (eq bb ?-) (eq c ?s)) ; -s file test
7bcea553
IZ
4490 (and (eq bb ?\&)
4491 (not (eq (char-after ; &&m/blah/
20675f5d
IZ
4492 (- (match-beginning b1) 2))
4493 ?\&))))
4494 ;; <file> or <$file>
4495 (and (eq c ?\<)
7bcea553 4496 ;; Do not stringify <FH>, <$fh> :
20675f5d
IZ
4497 (save-match-data
4498 (looking-at
7bcea553 4499 "\\$?\\([_a-zA-Z:][_a-zA-Z0-9:]*\\)?>"))))
6c72d195
IZ
4500 tb (match-beginning 0))
4501 (goto-char (match-beginning b1))
4502 (cperl-backward-to-noncomment (point-min))
ebcd4dbc 4503 (or bb
6c72d195 4504 (if (eq b1 11) ; bare /blah/ or ?blah? or <foo>
ebcd4dbc 4505 (setq argument ""
6c72d195
IZ
4506 bb ; Not a regexp?
4507 (progn
4508 (not
4509 ;; What is below: regexp-p?
4510 (and
4511 (or (memq (preceding-char)
4584684c 4512 (append (if (memq c '(?\? ?\<))
6c72d195 4513 ;; $a++ ? 1 : 2
4584684c
GS
4514 "~{(=|&*!,;:"
4515 "~{(=|&+-*!,;:") nil))
6c72d195
IZ
4516 (and (eq (preceding-char) ?\})
4517 (cperl-after-block-p (point-min)))
4518 (and (eq (char-syntax (preceding-char)) ?w)
4519 (progn
4520 (forward-sexp -1)
4521;;; After these keywords `/' starts a RE. One should add all the
4522;;; functions/builtins which expect an argument, but ...
4523 (if (eq (preceding-char) ?-)
4524 ;; -d ?foo? is a RE
20675f5d 4525 (looking-at "[a-zA-Z]\\>")
7bcea553
IZ
4526 (and
4527 (not (memq (preceding-char)
4528 '(?$ ?@ ?& ?%)))
4529 (looking-at
4530 "\\(while\\|if\\|unless\\|until\\|and\\|or\\|not\\|xor\\|split\\|grep\\|map\\|print\\)\\>")))))
6c72d195
IZ
4531 (and (eq (preceding-char) ?.)
4532 (eq (char-after (- (point) 2)) ?.))
4533 (bobp))
4534 ;; m|blah| ? foo : bar;
4535 (not
4536 (and (eq c ?\?)
4537 cperl-use-syntax-table-text-property
4538 (not (bobp))
4539 (progn
4540 (forward-char -1)
20675f5d 4541 (looking-at "\\s|")))))))
6c72d195
IZ
4542 b (1- b))
4543 ;; s y tr m
4544 ;; Check for $a->y
4545 (if (and (eq (preceding-char) ?>)
4546 (eq (char-after (- (point) 2)) ?-))
4547 ;; Not a regexp
4548 (setq bb t))))
ebcd4dbc
IZ
4549 (or bb (setq state (parse-partial-sexp
4550 state-point b nil nil state)
4551 state-point b))
4552 (goto-char b)
4553 (if (or bb (nth 3 state) (nth 4 state))
4554 (goto-char i)
7bcea553 4555 ;; Skip whitespace and comments...
3ee700d1
IZ
4556 (if (looking-at "[ \t\n\f]+\\(#[^\n]*\n[ \t\n\f]*\\)+")
4557 (goto-char (match-end 0))
4558 (skip-chars-forward " \t\n\f"))
7bcea553
IZ
4559 (if (> (point) b)
4560 (put-text-property b (point) 'syntax-type 'prestring))
05bbd9c3
IZ
4561 ;; qtag means two-arg matcher, may be reset to
4562 ;; 2 or 3 later if some special quoting is needed.
4563 ;; e1 means matching-char matcher.
4564 (setq b (point)
20675f5d
IZ
4565 ;; has 2 args
4566 i2 (string-match "^\\([sy]\\|tr\\)$" argument)
6c72d195
IZ
4567 ;; We do not search to max, since we may be called from
4568 ;; some hook of fontification, and max is random
4569 i (cperl-forward-re stop-point end
20675f5d 4570 i2
6c72d195 4571 t st-l err-l argument)
20675f5d
IZ
4572 ;; Note that if `go', then it is considered as 1-arg
4573 b1 (nth 1 i) ; start of the second part
4574 tag (nth 2 i) ; ender-char, true if second part
4575 ; is with matching chars []
3ee700d1 4576 go (nth 4 i) ; There is a 1-char part after the end
05bbd9c3 4577 i (car i) ; intermediate point
20675f5d
IZ
4578 e1 (point) ; end
4579 ;; Before end of the second part if non-matching: ///
4580 tail (if (and i (not tag))
4581 (1- e1))
4582 e (if i i e1) ; end of the first part
7bcea553
IZ
4583 qtag nil ; need to preserve backslashitis
4584 is-x-REx nil) ; REx has //x modifier
05bbd9c3
IZ
4585 ;; Commenting \\ is dangerous, what about ( ?
4586 (and i tail
4587 (eq (char-after i) ?\\)
20675f5d 4588 (setq qtag t))
7bcea553
IZ
4589 (if (looking-at "\\sw*x") ; qr//x
4590 (setq is-x-REx t))
ebcd4dbc 4591 (if (null i)
20675f5d 4592 ;; Considered as 1arg form
3ee700d1
IZ
4593 (progn
4594 (cperl-commentify b (point) t)
4584684c 4595 (put-text-property b (point) 'syntax-type 'string)
7bcea553
IZ
4596 (if (or is-x-REx
4597 ;; ignore other text properties:
4598 (string-match "^qw$" argument))
4599 (put-text-property b (point) 'indentable t))
20675f5d 4600 (and go
4584684c
GS
4601 (setq e1 (cperl-1+ e1))
4602 (or (eobp)
4603 (forward-char 1))))
ebcd4dbc 4604 (cperl-commentify b i t)
05bbd9c3 4605 (if (looking-at "\\sw*e") ; s///e
3ee700d1
IZ
4606 (progn
4607 (and
4608 ;; silent:
20675f5d 4609 (cperl-find-pods-heres b1 (1- (point)) t end)
3ee700d1
IZ
4610 ;; Error
4611 (goto-char (1+ max)))
20675f5d 4612 (if (and tag (eq (preceding-char) ?\>))
3ee700d1
IZ
4613 (progn
4614 (cperl-modify-syntax-type (1- (point)) cperl-st-ket)
4584684c 4615 (cperl-modify-syntax-type i cperl-st-bra)))
7bcea553
IZ
4616 (put-text-property b i 'syntax-type 'string)
4617 (if is-x-REx
4618 (put-text-property b i 'indentable t)))
20675f5d 4619 (cperl-commentify b1 (point) t)
4584684c 4620 (put-text-property b (point) 'syntax-type 'string)
7bcea553
IZ
4621 (if is-x-REx
4622 (put-text-property b i 'indentable t))
20675f5d 4623 (if qtag
6c72d195 4624 (cperl-modify-syntax-type (1+ i) cperl-st-punct))
05bbd9c3 4625 (setq tail nil)))
20675f5d 4626 ;; Now: tail: if the second part is non-matching without ///e
ebcd4dbc 4627 (if (eq (char-syntax (following-char)) ?w)
05bbd9c3
IZ
4628 (progn
4629 (forward-word 1) ; skip modifiers s///s
20675f5d
IZ
4630 (if tail (cperl-commentify tail (point) t))
4631 (cperl-postpone-fontification
7bcea553 4632 e1 (point) 'face 'cperl-nonoverridable-face)))
20675f5d
IZ
4633 ;; Check whether it is m// which means "previous match"
4634 ;; and highlight differently
7bcea553
IZ
4635 (setq is-REx
4636 (and (string-match "^\\([sm]?\\|qr\\)$" argument)
4637 (or (not (= (length argument) 0))
4638 (not (eq c ?\<)))))
4639 (if (and is-REx
4640 (eq e (+ 2 b))
20675f5d
IZ
4641 ;; split // *is* using zero-pattern
4642 (save-excursion
4643 (condition-case nil
4644 (progn
4645 (goto-char tb)
4646 (forward-sexp -1)
4647 (not (looking-at "split\\>")))
4648 (error t))))
4649 (cperl-postpone-fontification
4650 b e 'face font-lock-function-name-face)
4651 (if (or i2 ; Has 2 args
4652 (and cperl-fontify-m-as-s
4653 (or
4654 (string-match "^\\(m\\|qr\\)$" argument)
4655 (and (eq 0 (length argument))
4656 (not (eq ?\< (char-after b)))))))
4657 (progn
4658 (cperl-postpone-fontification
4584684c 4659 b (cperl-1+ b) 'face font-lock-constant-face)
20675f5d 4660 (cperl-postpone-fontification
7bcea553
IZ
4661 (1- e) e 'face font-lock-constant-face)))
4662 (if (and is-REx cperl-regexp-scan)
4663 ;; Process RExen better
4664 (save-excursion
4665 (goto-char (1+ b))
4666 (while
4667 (and (< (point) e)
4668 (re-search-forward
4669 (if is-x-REx
4670 (if (eq (char-after b) ?\#)
4671 "\\((\\?\\\\#\\)\\|\\(\\\\#\\)"
4672 "\\((\\?#\\)\\|\\(#\\)")
4673 (if (eq (char-after b) ?\#)
4674 "\\((\\?\\\\#\\)"
4675 "\\((\\?#\\)"))
4676 (1- e) 'to-end))
4677 (goto-char (match-beginning 0))
4678 (setq REx-comment-start (point)
4679 was-comment t)
4680 (if (save-excursion
4681 (and
4682 ;; XXX not working if outside delimiter is #
4683 (eq (preceding-char) ?\\)
4684 (= (% (skip-chars-backward "$\\\\") 2) -1)))
4685 ;; Not a comment, avoid loop:
4686 (progn (setq was-comment nil)
4687 (forward-char 1))
4688 (if (match-beginning 2)
4689 (progn
4690 (beginning-of-line 2)
4691 (if (> (point) e)
4692 (goto-char (1- e))))
4693 ;; Works also if the outside delimiters are ().
4694 (or (search-forward ")" (1- e) 'toend)
4695 (message
4696 "Couldn't find end of (?#...)-comment in a REx, pos=%s"
4697 REx-comment-start))))
4698 (if (>= (point) e)
4699 (goto-char (1- e)))
4700 (if was-comment
4701 (progn
4702 (setq REx-comment-end (point))
4703 (cperl-commentify
4704 REx-comment-start REx-comment-end nil)
4705 (cperl-postpone-fontification
4706 REx-comment-start REx-comment-end
4707 'face font-lock-comment-face))))))
4708 (if (and is-REx is-x-REx)
4709 (put-text-property (1+ b) (1- e)
4710 'syntax-subtype 'x-REx)))
20675f5d
IZ
4711 (if i2
4712 (progn
4713 (cperl-postpone-fontification
4714 (1- e1) e1 'face font-lock-constant-face)
4715 (if (assoc (char-after b) cperl-starters)
4716 (cperl-postpone-fontification
4717 b1 (1+ b1) 'face font-lock-constant-face))))
6c72d195
IZ
4718 (if (> (point) max)
4719 (setq tmpend tb))))
ebcd4dbc
IZ
4720 ((match-beginning 13) ; sub with prototypes
4721 (setq b (match-beginning 0))
4722 (if (memq (char-after (1- b))
4723 '(?\$ ?\@ ?\% ?\& ?\*))
4724 nil
4725 (setq state (parse-partial-sexp
4584684c
GS
4726 state-point b nil nil state)
4727 state-point b)
ebcd4dbc
IZ
4728 (if (or (nth 3 state) (nth 4 state))
4729 nil
4730 ;; Mark as string
4731 (cperl-commentify (match-beginning 13) (match-end 13) t))
4732 (goto-char (match-end 0))))
05bbd9c3
IZ
4733 ;; 1+6+2+1+1+2=13 extra () before this:
4734 ;; "\\$\\(['{]\\)"
ebcd4dbc 4735 ((and (match-beginning 14)
6c72d195 4736 (eq (preceding-char) ?\')) ; $'
ebcd4dbc
IZ
4737 (setq b (1- (point))
4738 state (parse-partial-sexp
4739 state-point (1- b) nil nil state)
4740 state-point (1- b))
4741 (if (nth 3 state) ; in string
3ee700d1 4742 (cperl-modify-syntax-type (1- b) cperl-st-punct))
ebcd4dbc 4743 (goto-char (1+ b)))
05bbd9c3
IZ
4744 ;; 1+6+2+1+1+2=13 extra () before this:
4745 ;; "\\$\\(['{]\\)"
ebcd4dbc
IZ
4746 ((match-beginning 14) ; ${
4747 (setq bb (match-beginning 0))
3ee700d1 4748 (cperl-modify-syntax-type bb cperl-st-punct))
05bbd9c3
IZ
4749 ;; 1+6+2+1+1+2+1=14 extra () before this:
4750 ;; "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'")
4751 ((match-beginning 15) ; old $abc'efg syntax
4752 (setq bb (match-end 0)
4753 b (match-beginning 0)
4754 state (parse-partial-sexp
4755 state-point b nil nil state)
4756 state-point b)
4757 (if (nth 3 state) ; in string
4758 nil
4759 (put-text-property (1- bb) bb 'syntax-table cperl-st-word))
4760 (goto-char bb))
4761 ;; 1+6+2+1+1+2+1+1=15 extra () before this:
4762 ;; "__\\(END\\|DATA\\)__"
7bcea553 4763 ((match-beginning 16) ; __END__, __DATA__
05bbd9c3
IZ
4764 (setq bb (match-end 0)
4765 b (match-beginning 0)
4766 state (parse-partial-sexp
4767 state-point b nil nil state)
4768 state-point b)
4769 (if (or (nth 3 state) (nth 4 state))
4770 nil
4771 ;; (put-text-property b (1+ bb) 'syntax-type 'pod) ; Cheat
4772 (cperl-commentify b bb nil)
3ee700d1 4773 (setq end t))
7bcea553
IZ
4774 (goto-char bb))
4775 ((match-beginning 17) ; "\\\\\\(['`\"]\\)"
4776 (setq bb (match-end 0)
4777 b (match-beginning 0))
4778 (goto-char b)
4779 (skip-chars-backward "\\\\")
4780 ;;;(setq i2 (= (% (skip-chars-backward "\\\\") 2) -1))
4781 (setq state (parse-partial-sexp
4782 state-point b nil nil state)
4783 state-point b)
4784 (if (or (nth 3 state) (nth 4 state) )
4785 nil
4786 (cperl-modify-syntax-type b cperl-st-punct))
4787 (goto-char bb))
4788 (t (error "Error in regexp of the sniffer")))
6c72d195 4789 (if (> (point) stop-point)
3ee700d1
IZ
4790 (progn
4791 (if end
4792 (message "Garbage after __END__/__DATA__ ignored")
4793 (message "Unbalanced syntax found while scanning")
4794 (or (car err-l) (setcar err-l b)))
6c72d195
IZ
4795 (goto-char stop-point))))
4796 (setq cperl-syntax-state (cons state-point state)
4797 cperl-syntax-done-to (or tmpend (max (point) max))))
05bbd9c3 4798 (if (car err-l) (goto-char (car err-l))
6c72d195
IZ
4799 (or non-inter
4800 (message "Scanning for \"hard\" Perl constructions... done"))))
c07a80fd 4801 (and (buffer-modified-p)
4802 (not modified)
ebcd4dbc 4803 (set-buffer-modified-p nil))
3ee700d1
IZ
4804 (set-syntax-table cperl-mode-syntax-table))
4805 (car err-l)))
c07a80fd 4806
4807(defun cperl-backward-to-noncomment (lim)
4808 ;; Stops at lim or after non-whitespace that is not in comment
20675f5d 4809 (let (stop p pr)
4633a7c4
LW
4810 (while (and (not stop) (> (point) (or lim 1)))
4811 (skip-chars-backward " \t\n\f" lim)
4812 (setq p (point))
4813 (beginning-of-line)
20675f5d
IZ
4814 (if (memq (setq pr (get-text-property (point) 'syntax-type))
4815 '(pod here-doc here-doc-delim))
4816 (cperl-unwind-to-safe nil)
4817 (if (or (looking-at "^[ \t]*\\(#\\|$\\)")
4818 (progn (cperl-to-comment-or-eol) (bolp)))
4819 nil ; Only comment, skip
4820 ;; Else
4821 (skip-chars-backward " \t")
4822 (if (< p (point)) (goto-char p))
4823 (setq stop t))))))
4633a7c4 4824
ebcd4dbc
IZ
4825(defun cperl-after-block-p (lim)
4826 ;; We suppose that the preceding char is }.
4827 (save-excursion
4828 (condition-case nil
4829 (progn
4830 (forward-sexp -1)
4831 (cperl-backward-to-noncomment lim)
6c72d195
IZ
4832 (or (eq (point) lim)
4833 (eq (preceding-char) ?\) ) ; if () {} sub f () {}
4834 (if (eq (char-syntax (preceding-char)) ?w) ; else {}
4835 (save-excursion
4836 (forward-sexp -1)
296d8a58 4837 (or (looking-at "\\(else\\|grep\\|map\\|BEGIN\\|END\\|CHECK\\|INIT\\)\\>")
6c72d195
IZ
4838 ;; sub f {}
4839 (progn
4840 (cperl-backward-to-noncomment lim)
4841 (and (eq (char-syntax (preceding-char)) ?w)
4842 (progn
4843 (forward-sexp -1)
4844 (looking-at "sub\\>"))))))
4845 (cperl-after-expr-p lim))))
ebcd4dbc
IZ
4846 (error nil))))
4847
c07a80fd 4848(defun cperl-after-expr-p (&optional lim chars test)
4633a7c4 4849 "Returns true if the position is good for start of expression.
6c72d195 4850TEST is the expression to evaluate at the found position. If absent,
ebcd4dbc
IZ
4851CHARS is a string that contains good characters to have before us (however,
4852`}' is treated \"smartly\" if it is not in the list)."
4853 (let (stop p
4854 (lim (or lim (point-min))))
4633a7c4 4855 (save-excursion
ebcd4dbc 4856 (while (and (not stop) (> (point) lim))
4633a7c4
LW
4857 (skip-chars-backward " \t\n\f" lim)
4858 (setq p (point))
4859 (beginning-of-line)
4860 (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip
4584684c 4861 ;; Else: last iteration, or a label
4633a7c4
LW
4862 (cperl-to-comment-or-eol)
4863 (skip-chars-backward " \t")
4864 (if (< p (point)) (goto-char p))
4584684c
GS
4865 (setq p (point))
4866 (if (and (eq (preceding-char) ?:)
4867 (progn
4868 (forward-char -1)
4869 (skip-chars-backward " \t\n\f" lim)
4870 (eq (char-syntax (preceding-char)) ?w)))
4871 (forward-sexp -1) ; Possibly label. Skip it
4872 (goto-char p)
4873 (setq stop t))))
6c72d195
IZ
4874 (or (bobp) ; ???? Needed
4875 (eq (point) lim)
7bcea553 4876 (looking-at "[ \t]*__\\(END\\|DATA\\)__") ; After this anything goes
4633a7c4 4877 (progn
4633a7c4 4878 (if test (eval test)
ebcd4dbc
IZ
4879 (or (memq (preceding-char) (append (or chars "{;") nil))
4880 (and (eq (preceding-char) ?\})
4881 (cperl-after-block-p lim)))))))))
4633a7c4
LW
4882
4883(defun cperl-backward-to-start-of-continued-exp (lim)
c07a80fd 4884 (if (memq (preceding-char) (append ")]}\"'`" nil))
4633a7c4
LW
4885 (forward-sexp -1))
4886 (beginning-of-line)
4887 (if (<= (point) lim)
4888 (goto-char (1+ lim)))
4889 (skip-chars-forward " \t"))
4890
6c72d195
IZ
4891(defun cperl-after-block-and-statement-beg (lim)
4892 ;; We assume that we are after ?\}
4893 (and
4894 (cperl-after-block-p lim)
4895 (save-excursion
4896 (forward-sexp -1)
4897 (cperl-backward-to-noncomment (point-min))
4898 (or (bobp)
4899 (eq (point) lim)
4900 (not (= (char-syntax (preceding-char)) ?w))
4901 (progn
4902 (forward-sexp -1)
4903 (not
4904 (looking-at
4905 "\\(map\\|grep\\|printf?\\|system\\|exec\\|tr\\|s\\)\\>")))))))
4906
4633a7c4
LW
4907\f
4908(defvar innerloop-done nil)
4909(defvar last-depth nil)
4910
4911(defun cperl-indent-exp ()
4912 "Simple variant of indentation of continued-sexp.
4584684c
GS
4913
4914Will not indent comment if it starts at `comment-indent' or looks like
4915continuation of the comment on the previous line.
6c72d195
IZ
4916
4917If `cperl-indent-region-fix-constructs', will improve spacing on
4918conditional/loop constructs."
4633a7c4
LW
4919 (interactive)
4920 (save-excursion
4921 (let ((tmp-end (progn (end-of-line) (point))) top done)
4922 (save-excursion
05bbd9c3 4923 (beginning-of-line)
4633a7c4 4924 (while (null done)
4633a7c4
LW
4925 (setq top (point))
4926 (while (= (nth 0 (parse-partial-sexp (point) tmp-end
4927 -1)) -1)
4928 (setq top (point))) ; Get the outermost parenths in line
4929 (goto-char top)
4930 (while (< (point) tmp-end)
4931 (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol
4932 (or (eolp) (forward-sexp 1)))
4584684c
GS
4933 (if (> (point) tmp-end)
4934 (save-excursion
4935 (end-of-line)
4936 (setq tmp-end (point)))
4633a7c4
LW
4937 (setq done t)))
4938 (goto-char tmp-end)
4939 (setq tmp-end (point-marker)))
6c72d195
IZ
4940 (if cperl-indent-region-fix-constructs
4941 (cperl-fix-line-spacing tmp-end))
4633a7c4
LW
4942 (cperl-indent-region (point) tmp-end))))
4943
6c72d195 4944(defun cperl-fix-line-spacing (&optional end parse-data)
4584684c
GS
4945 "Improve whitespace in a conditional/loop construct.
4946Returns some position at the last line."
6c72d195
IZ
4947 (interactive)
4948 (or end
4949 (setq end (point-max)))
4584684c 4950 (let (p pp ml have-brace ret
6c72d195
IZ
4951 (ee (save-excursion (end-of-line) (point)))
4952 (cperl-indent-region-fix-constructs
4953 (or cperl-indent-region-fix-constructs 1)))
4954 (save-excursion
4955 (beginning-of-line)
4584684c 4956 (setq ret (point))
6c72d195
IZ
4957 ;; }? continue
4958 ;; blah; }
4959 (if (not
4960 (or (looking-at "[ \t]*\\(els\\(e\\|if\\)\\|continue\\|if\\|while\\|for\\(each\\)?\\|until\\)")
4961 (setq have-brace (save-excursion (search-forward "}" ee t)))))
4962 nil ; Do not need to do anything
4963 ;; Looking at:
4964 ;; }
4965 ;; else
4966 (if (and cperl-merge-trailing-else
4967 (looking-at
4968 "[ \t]*}[ \t]*\n[ \t\n]*\\(els\\(e\\|if\\)\\|continue\\)\\>"))
4969 (progn
4970 (search-forward "}")
4971 (setq p (point))
4972 (skip-chars-forward " \t\n")
4973 (delete-region p (point))
4974 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
4975 (beginning-of-line)))
4976 ;; Looking at:
4977 ;; } else
4978 (if (looking-at "[ \t]*}\\(\t*\\|[ \t][ \t]+\\)\\<\\(els\\(e\\|if\\)\\|continue\\)\\>")
4979 (progn
4980 (search-forward "}")
4981 (delete-horizontal-space)
4982 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
4983 (beginning-of-line)))
4984 ;; Looking at:
4985 ;; else {
4986 (if (looking-at
4987 "[ \t]*}?[ \t]*\\<\\(\\els\\(e\\|if\\)\\|continue\\|unless\\|if\\|while\\|for\\(each\\)?\\|until\\)\\>\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
4988 (progn
4989 (forward-word 1)
4990 (delete-horizontal-space)
4991 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
4992 (beginning-of-line)))
4993 ;; Looking at:
4994 ;; foreach my $var
4995 (if (looking-at
7bcea553 4996 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)\\(\t*\\|[ \t][ \t]+\\)[^ \t\n]")
6c72d195
IZ
4997 (progn
4998 (forward-word 2)
4999 (delete-horizontal-space)
5000 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
5001 (beginning-of-line)))
5002 ;; Looking at:
5003 ;; foreach my $var (
5004 (if (looking-at
7bcea553 5005 "[ \t]*\\<for\\(each\\)?[ \t]+\\(my\\|local\\|our\\)[ \t]*\\$[_a-zA-Z0-9]+\\(\t*\\|[ \t][ \t]+\\)[^ \t\n#]")
6c72d195
IZ
5006 (progn
5007 (forward-word 3)
5008 (delete-horizontal-space)
5009 (insert
5010 (make-string cperl-indent-region-fix-constructs ?\ ))
5011 (beginning-of-line)))
5012 ;; Looking at:
5013 ;; } foreach my $var () {
5014 (if (looking-at
7bcea553 5015 "[ \t]*\\(}[ \t]*\\)?\\<\\(\\els\\(e\\|if\\)\\|continue\\|if\\|unless\\|while\\|for\\(each\\)?\\(\\([ t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\$[_a-zA-Z0-9]+\\)?\\|until\\)\\>\\([ \t]*(\\|[ \t\n]*{\\)\\|[ \t]*{")
6c72d195
IZ
5016 (progn
5017 (setq ml (match-beginning 8))
5018 (re-search-forward "[({]")
5019 (forward-char -1)
5020 (setq p (point))
5021 (if (eq (following-char) ?\( )
5022 (progn
5023 (forward-sexp 1)
5024 (setq pp (point)))
5025 ;; after `else' or nothing
5026 (if ml ; after `else'
5027 (skip-chars-backward " \t\n")
5028 (beginning-of-line))
5029 (setq pp nil))
5030 ;; Now after the sexp before the brace
5031 ;; Multiline expr should be special
5032 (setq ml (and pp (save-excursion (goto-char p)
5033 (search-forward "\n" pp t))))
5034 (if (and (or (not pp) (< pp end))
5035 (looking-at "[ \t\n]*{"))
5036 (progn
5037 (cond
5038 ((bolp) ; Were before `{', no if/else/etc
5039 nil)
5040 ((looking-at "\\(\t*\\| [ \t]+\\){")
5041 (delete-horizontal-space)
5042 (if (if ml
5043 cperl-extra-newline-before-brace-multiline
5044 cperl-extra-newline-before-brace)
5045 (progn
5046 (delete-horizontal-space)
5047 (insert "\n")
4584684c 5048 (setq ret (point))
6c72d195 5049 (if (cperl-indent-line parse-data)
4584684c
GS
5050 (progn
5051 (cperl-fix-line-spacing end parse-data)
5052 (setq ret (point)))))
6c72d195
IZ
5053 (insert
5054 (make-string cperl-indent-region-fix-constructs ?\ ))))
5055 ((and (looking-at "[ \t]*\n")
5056 (not (if ml
5057 cperl-extra-newline-before-brace-multiline
5058 cperl-extra-newline-before-brace)))
5059 (setq pp (point))
5060 (skip-chars-forward " \t\n")
5061 (delete-region pp (point))
5062 (insert
5063 (make-string cperl-indent-region-fix-constructs ?\ ))))
5064 ;; Now we are before `{'
5065 (if (looking-at "[ \t\n]*{[ \t]*[^ \t\n#]")
5066 (progn
5067 (skip-chars-forward " \t\n")
5068 (setq pp (point))
5069 (forward-sexp 1)
5070 (setq p (point))
5071 (goto-char pp)
5072 (setq ml (search-forward "\n" p t))
5073 (if (or cperl-break-one-line-blocks-when-indent ml)
5074 ;; not good: multi-line BLOCK
5075 (progn
5076 (goto-char (1+ pp))
5077 (delete-horizontal-space)
5078 (insert "\n")
4584684c 5079 (setq ret (point))
6c72d195 5080 (if (cperl-indent-line parse-data)
4584684c 5081 (setq ret (cperl-fix-line-spacing end parse-data)))))))))))
6c72d195
IZ
5082 (beginning-of-line)
5083 (setq p (point) pp (save-excursion (end-of-line) (point))) ; May be different from ee.
5084 ;; Now check whether there is a hanging `}'
5085 ;; Looking at:
5086 ;; } blah
5087 (if (and
5088 cperl-fix-hanging-brace-when-indent
5089 have-brace
5090 (not (looking-at "[ \t]*}[ \t]*\\(\\<\\(els\\(if\\|e\\)\\|continue\\|while\\|until\\)\\>\\|$\\|#\\)"))
5091 (condition-case nil
5092 (progn
5093 (up-list 1)
5094 (if (and (<= (point) pp)
5095 (eq (preceding-char) ?\} )
5096 (cperl-after-block-and-statement-beg (point-min)))
5097 t
5098 (goto-char p)
5099 nil))
5100 (error nil)))
5101 (progn
5102 (forward-char -1)
5103 (skip-chars-backward " \t")
5104 (if (bolp)
5105 ;; `}' was the first thing on the line, insert NL *after* it.
5106 (progn
5107 (cperl-indent-line parse-data)
5108 (search-forward "}")
5109 (delete-horizontal-space)
5110 (insert "\n"))
5111 (delete-horizontal-space)
5112 (or (eq (preceding-char) ?\;)
5113 (bolp)
5114 (and (eq (preceding-char) ?\} )
5115 (cperl-after-block-p (point-min)))
5116 (insert ";"))
4584684c
GS
5117 (insert "\n")
5118 (setq ret (point)))
6c72d195 5119 (if (cperl-indent-line parse-data)
4584684c
GS
5120 (setq ret (cperl-fix-line-spacing end parse-data)))
5121 (beginning-of-line)))))
5122 ret))
6c72d195
IZ
5123
5124(defvar cperl-update-start) ; Do not need to make them local
5125(defvar cperl-update-end)
5126(defun cperl-delay-update-hook (beg end old-len)
5127 (setq cperl-update-start (min beg (or cperl-update-start (point-max))))
5128 (setq cperl-update-end (max end (or cperl-update-end (point-min)))))
5129
4633a7c4
LW
5130(defun cperl-indent-region (start end)
5131 "Simple variant of indentation of region in CPerl mode.
6c72d195 5132Should be slow. Will not indent comment if it starts at `comment-indent'
4633a7c4
LW
5133or looks like continuation of the comment on the previous line.
5134Indents all the lines whose first character is between START and END
6c72d195
IZ
5135inclusive.
5136
5137If `cperl-indent-region-fix-constructs', will improve spacing on
5138conditional/loop constructs."
4633a7c4 5139 (interactive "r")
6c72d195 5140 (cperl-update-syntaxification end end)
4633a7c4 5141 (save-excursion
6c72d195 5142 (let (cperl-update-start cperl-update-end (h-a-c after-change-functions))
4584684c 5143 (let (st comm old-comm-indent new-comm-indent p pp i empty
6c72d195 5144 (indent-info (if cperl-emacs-can-parse
4584684c 5145 (list nil nil nil) ; Cannot use '(), since will modify
6c72d195
IZ
5146 nil))
5147 after-change-functions ; Speed it up!
5148 (pm 0) (imenu-scanning-message "Indenting... (%3d%%)"))
5149 (if h-a-c (add-hook 'after-change-functions 'cperl-delay-update-hook))
5150 (goto-char start)
5151 (setq old-comm-indent (and (cperl-to-comment-or-eol)
5152 (current-column))
5153 new-comm-indent old-comm-indent)
5154 (goto-char start)
5155 (setq end (set-marker (make-marker) end)) ; indentation changes pos
5156 (or (bolp) (beginning-of-line 2))
5157 (or (fboundp 'imenu-progress-message)
5158 (message "Indenting... For feedback load `imenu'..."))
5159 (while (and (<= (point) end) (not (eobp))) ; bol to check start
5160 (and (fboundp 'imenu-progress-message)
5161 (imenu-progress-message
5162 pm (/ (* 100 (- (point) start)) (- end start -1))))
5163 (setq st (point))
4584684c
GS
5164 (if (or
5165 (setq empty (looking-at "[ \t]*\n"))
5166 (and (setq comm (looking-at "[ \t]*#"))
5167 (or (eq (current-indentation) (or old-comm-indent
5168 comment-column))
5169 (setq old-comm-indent nil))))
6c72d195 5170 (if (and old-comm-indent
4584684c 5171 (not empty)
6c72d195 5172 (= (current-indentation) old-comm-indent)
4584684c
GS
5173 (not (eq (get-text-property (point) 'syntax-type) 'pod))
5174 (not (eq (get-text-property (point) 'syntax-table)
5175 cperl-st-cfence)))
6c72d195
IZ
5176 (let ((comment-column new-comm-indent))
5177 (indent-for-comment)))
5178 (progn
5179 (setq i (cperl-indent-line indent-info))
5180 (or comm
5181 (not i)
5182 (progn
5183 (if cperl-indent-region-fix-constructs
4584684c 5184 (goto-char (cperl-fix-line-spacing end indent-info)))
6c72d195
IZ
5185 (if (setq old-comm-indent
5186 (and (cperl-to-comment-or-eol)
5187 (not (memq (get-text-property (point)
5188 'syntax-type)
5189 '(pod here-doc)))
4584684c
GS
5190 (not (eq (get-text-property (point)
5191 'syntax-table)
5192 cperl-st-cfence))
6c72d195
IZ
5193 (current-column)))
5194 (progn (indent-for-comment)
5195 (skip-chars-backward " \t")
5196 (skip-chars-backward "#")
5197 (setq new-comm-indent (current-column))))))))
5198 (beginning-of-line 2))
4633a7c4 5199 (if (fboundp 'imenu-progress-message)
6c72d195
IZ
5200 (imenu-progress-message pm 100)
5201 (message nil)))
5202 ;; Now run the update hooks
5203 (if after-change-functions
5204 (save-excursion
5205 (if cperl-update-end
5206 (progn
5207 (goto-char cperl-update-end)
5208 (insert " ")
5209 (delete-char -1)
5210 (goto-char cperl-update-start)
5211 (insert " ")
5212 (delete-char -1))))))))
4633a7c4
LW
5213
5214;; Stolen from lisp-mode with a lot of improvements
5215
5216(defun cperl-fill-paragraph (&optional justify iteration)
5217 "Like \\[fill-paragraph], but handle CPerl comments.
5218If any of the current line is a comment, fill the comment or the
5219block of it that point is in, preserving the comment's initial
6c72d195 5220indentation and initial hashes. Behaves usually outside of comment."
4633a7c4
LW
5221 (interactive "P")
5222 (let (
5223 ;; Non-nil if the current line contains a comment.
5224 has-comment
5225
5226 ;; If has-comment, the appropriate fill-prefix for the comment.
5227 comment-fill-prefix
5228 ;; Line that contains code and comment (or nil)
5229 start
5230 c spaces len dc (comment-column comment-column))
5231 ;; Figure out what kind of comment we are looking at.
5232 (save-excursion
5233 (beginning-of-line)
5234 (cond
5235
5236 ;; A line with nothing but a comment on it?
5237 ((looking-at "[ \t]*#[# \t]*")
5238 (setq has-comment t
5239 comment-fill-prefix (buffer-substring (match-beginning 0)
5240 (match-end 0))))
5241
5242 ;; A line with some code, followed by a comment? Remember that the
5243 ;; semi which starts the comment shouldn't be part of a string or
5244 ;; character.
5245 ((cperl-to-comment-or-eol)
5246 (setq has-comment t)
5247 (looking-at "#+[ \t]*")
5248 (setq start (point) c (current-column)
5249 comment-fill-prefix
5250 (concat (make-string (current-column) ?\ )
5251 (buffer-substring (match-beginning 0) (match-end 0)))
5252 spaces (progn (skip-chars-backward " \t")
5253 (buffer-substring (point) start))
5254 dc (- c (current-column)) len (- start (point))
5255 start (point-marker))
5256 (delete-char len)
5257 (insert (make-string dc ?-)))))
5258 (if (not has-comment)
5259 (fill-paragraph justify) ; Do the usual thing outside of comment
5260 ;; Narrow to include only the comment, and then fill the region.
5261 (save-restriction
5262 (narrow-to-region
5263 ;; Find the first line we should include in the region to fill.
5264 (if start (progn (beginning-of-line) (point))
5265 (save-excursion
5266 (while (and (zerop (forward-line -1))
c07a80fd 5267 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
4633a7c4 5268 ;; We may have gone to far. Go forward again.
c07a80fd 5269 (or (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")
4633a7c4
LW
5270 (forward-line 1))
5271 (point)))
5272 ;; Find the beginning of the first line past the region to fill.
5273 (save-excursion
5274 (while (progn (forward-line 1)
c07a80fd 5275 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
4633a7c4
LW
5276 (point)))
5277 ;; Remove existing hashes
5278 (goto-char (point-min))
5279 (while (progn (forward-line 1) (< (point) (point-max)))
5280 (skip-chars-forward " \t")
5281 (and (looking-at "#+")
5282 (delete-char (- (match-end 0) (match-beginning 0)))))
5283
5284 ;; Lines with only hashes on them can be paragraph boundaries.
5285 (let ((paragraph-start (concat paragraph-start "\\|^[ \t#]*$"))
5286 (paragraph-separate (concat paragraph-start "\\|^[ \t#]*$"))
5287 (fill-prefix comment-fill-prefix))
5288 (fill-paragraph justify)))
5289 (if (and start)
5290 (progn
5291 (goto-char start)
5292 (if (> dc 0)
5293 (progn (delete-char dc) (insert spaces)))
5294 (if (or (= (current-column) c) iteration) nil
5295 (setq comment-column c)
5296 (indent-for-comment)
5297 ;; Repeat once more, flagging as iteration
5298 (cperl-fill-paragraph justify t)))))))
5299
5300(defun cperl-do-auto-fill ()
5301 ;; Break out if the line is short enough
5302 (if (> (save-excursion
5303 (end-of-line)
5304 (current-column))
5305 fill-column)
5306 (let ((c (save-excursion (beginning-of-line)
5307 (cperl-to-comment-or-eol) (point)))
5308 (s (memq (following-char) '(?\ ?\t))) marker)
5309 (if (>= c (point)) nil
5310 (setq marker (point-marker))
5311 (cperl-fill-paragraph)
5312 (goto-char marker)
5313 ;; Is not enough, sometimes marker is a start of line
5314 (if (bolp) (progn (re-search-forward "#+[ \t]*")
5315 (goto-char (match-end 0))))
5316 ;; Following space could have gone:
5317 (if (or (not s) (memq (following-char) '(?\ ?\t))) nil
5318 (insert " ")
5319 (backward-char 1))
5320 ;; Previous space could have gone:
5321 (or (memq (preceding-char) '(?\ ?\t)) (insert " "))))))
5322
5323(defvar imenu-example--function-name-regexp-perl
ebcd4dbc
IZ
5324 (concat
5325 "^\\("
5326 "[ \t]*\\(sub\\|package\\)[ \t\n]+\\([a-zA-Z_0-9:']+\\)[ \t]*\\(([^()]*)[ \t]*\\)?"
5327 "\\|"
5328 "=head\\([12]\\)[ \t]+\\([^\n]+\\)$"
5329 "\\)"))
4633a7c4 5330
9ea28adb 5331(defun cperl-imenu-addback (lst &optional isback name)
5332 ;; We suppose that the lst is a DAG, unless the first element only
6c72d195 5333 ;; loops back, and ISBACK is set. Thus this function cannot be
9ea28adb 5334 ;; applied twice without ISBACK set.
5335 (cond ((not cperl-imenu-addback) lst)
5336 (t
5337 (or name
5338 (setq name "+++BACK+++"))
5339 (mapcar (function (lambda (elt)
5340 (if (and (listp elt) (listp (cdr elt)))
5341 (progn
5342 ;; In the other order it goes up
5343 ;; one level only ;-(
5344 (setcdr elt (cons (cons name lst)
5345 (cdr elt)))
5346 (cperl-imenu-addback (cdr elt) t name)
5347 ))))
5348 (if isback (cdr lst) lst))
5349 lst)))
5350
4633a7c4
LW
5351(defun imenu-example--create-perl-index (&optional regexp)
5352 (require 'cl)
05bbd9c3 5353 (require 'imenu) ; May be called from TAGS creator
c07a80fd 5354 (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '())
5355 (index-unsorted-alist '()) (i-s-f (default-value 'imenu-sort-function))
9ea28adb 5356 (index-meth-alist '()) meth
7bcea553 5357 packages ends-ranges p marker
c07a80fd 5358 (prev-pos 0) char fchar index index1 name (end-range 0) package)
4633a7c4 5359 (goto-char (point-min))
3ee700d1
IZ
5360 (if noninteractive
5361 (message "Scanning Perl for index")
5362 (imenu-progress-message prev-pos 0))
7bcea553 5363 (cperl-update-syntaxification (point-max) (point-max))
4633a7c4 5364 ;; Search for the function
9ea28adb 5365 (progn ;;save-match-data
4633a7c4
LW
5366 (while (re-search-forward
5367 (or regexp imenu-example--function-name-regexp-perl)
5368 nil t)
3ee700d1
IZ
5369 (or noninteractive
5370 (imenu-progress-message prev-pos))
c07a80fd 5371 (cond
05bbd9c3
IZ
5372 ((and ; Skip some noise if building tags
5373 (match-beginning 2) ; package or sub
5374 (eq (char-after (match-beginning 2)) ?p) ; package
5375 (not (save-match-data
5376 (looking-at "[ \t\n]*;")))) ; Plain text word 'package'
5377 nil)
ebcd4dbc
IZ
5378 ((and
5379 (match-beginning 2) ; package or sub
7bcea553 5380 ;; Skip if quoted (will not skip multi-line ''-strings :-():
ebcd4dbc
IZ
5381 (null (get-text-property (match-beginning 1) 'syntax-table))
5382 (null (get-text-property (match-beginning 1) 'syntax-type))
5383 (null (get-text-property (match-beginning 1) 'in-pod)))
c07a80fd 5384 (save-excursion
5385 (goto-char (match-beginning 2))
5386 (setq fchar (following-char))
5387 )
ebcd4dbc
IZ
5388 ;; (if (looking-at "([^()]*)[ \t\n\f]*")
5389 ;; (goto-char (match-end 0))) ; Messes what follows
7bcea553 5390 (setq char (following-char) ; ?\; for "sub foo () ;"
ebcd4dbc
IZ
5391 meth nil
5392 p (point))
c07a80fd 5393 (while (and ends-ranges (>= p (car ends-ranges)))
5394 ;; delete obsolete entries
5395 (setq ends-ranges (cdr ends-ranges) packages (cdr packages)))
5396 (setq package (or (car packages) "")
5397 end-range (or (car ends-ranges) 0))
5398 (if (eq fchar ?p)
9ea28adb 5399 (setq name (buffer-substring (match-beginning 3) (match-end 3))
499d5216
IZ
5400 name (progn
5401 (set-text-properties 0 (length name) nil name)
5402 name)
9ea28adb 5403 package (concat name "::")
5404 name (concat "package " name)
5405 end-range
5406 (save-excursion
5407 (parse-partial-sexp (point) (point-max) -1) (point))
5408 ends-ranges (cons end-range ends-ranges)
5409 packages (cons package packages)))
c07a80fd 5410 ;; )
5411 ;; Skip this function name if it is a prototype declaration.
5412 (if (and (eq fchar ?s) (eq char ?\;)) nil
7bcea553
IZ
5413 (setq name (buffer-substring (match-beginning 3) (match-end 3))
5414 marker (make-marker))
5415 (set-text-properties 0 (length name) nil name)
5416 (set-marker marker (match-end 3))
5417 (if (eq fchar ?p)
5418 (setq name (concat "package " name))
9ea28adb 5419 (cond ((string-match "[:']" name)
5420 (setq meth t))
5421 ((> p end-range) nil)
5422 (t
5423 (setq name (concat package name) meth t))))
7bcea553 5424 (setq index (cons name marker))
c07a80fd 5425 (if (eq fchar ?p)
5426 (push index index-pack-alist)
5427 (push index index-alist))
9ea28adb 5428 (if meth (push index index-meth-alist))
c07a80fd 5429 (push index index-unsorted-alist)))
ebcd4dbc 5430 ((match-beginning 5) ; Pod section
c07a80fd 5431 ;; (beginning-of-line)
5432 (setq index (imenu-example--name-and-position)
ebcd4dbc 5433 name (buffer-substring (match-beginning 6) (match-end 6)))
499d5216 5434 (set-text-properties 0 (length name) nil name)
ebcd4dbc 5435 (if (eq (char-after (match-beginning 5)) ?2)
c07a80fd 5436 (setq name (concat " " name)))
4633a7c4 5437 (setcar index name)
c07a80fd 5438 (setq index1 (cons (concat "=" name) (cdr index)))
5439 (push index index-pod-alist)
5440 (push index1 index-unsorted-alist)))))
3ee700d1
IZ
5441 (or noninteractive
5442 (imenu-progress-message prev-pos 100))
c07a80fd 5443 (setq index-alist
5444 (if (default-value 'imenu-sort-function)
5445 (sort index-alist (default-value 'imenu-sort-function))
5446 (nreverse index-alist)))
5447 (and index-pod-alist
9ea28adb 5448 (push (cons "+POD headers+..."
c07a80fd 5449 (nreverse index-pod-alist))
5450 index-alist))
9ea28adb 5451 (and (or index-pack-alist index-meth-alist)
5452 (let ((lst index-pack-alist) hier-list pack elt group name)
5453 ;; Remove "package ", reverse and uniquify.
5454 (while lst
5455 (setq elt (car lst) lst (cdr lst) name (substring (car elt) 8))
5456 (if (assoc name hier-list) nil
5457 (setq hier-list (cons (cons name (cdr elt)) hier-list))))
5458 (setq lst index-meth-alist)
5459 (while lst
5460 (setq elt (car lst) lst (cdr lst))
499d5216
IZ
5461 (cond ((string-match "\\(::\\|'\\)[_a-zA-Z0-9]+$" (car elt))
5462 (setq pack (substring (car elt) 0 (match-beginning 0)))
5463 (if (setq group (assoc pack hier-list))
5464 (if (listp (cdr group))
5465 ;; Have some functions already
5466 (setcdr group
5467 (cons (cons (substring
5468 (car elt)
5469 (+ 2 (match-beginning 0)))
5470 (cdr elt))
5471 (cdr group)))
5472 (setcdr group (list (cons (substring
5473 (car elt)
5474 (+ 2 (match-beginning 0)))
5475 (cdr elt)))))
5476 (setq hier-list
5477 (cons (cons pack
5478 (list (cons (substring
5479 (car elt)
5480 (+ 2 (match-beginning 0)))
5481 (cdr elt))))
5482 hier-list))))))
9ea28adb 5483 (push (cons "+Hierarchy+..."
5484 hier-list)
5485 index-alist)))
4633a7c4 5486 (and index-pack-alist
9ea28adb 5487 (push (cons "+Packages+..."
c07a80fd 5488 (nreverse index-pack-alist))
5489 index-alist))
5490 (and (or index-pack-alist index-pod-alist
5491 (default-value 'imenu-sort-function))
5492 index-unsorted-alist
9ea28adb 5493 (push (cons "+Unsorted List+..."
c07a80fd 5494 (nreverse index-unsorted-alist))
4633a7c4 5495 index-alist))
9ea28adb 5496 (cperl-imenu-addback index-alist)))
4633a7c4 5497
7bcea553
IZ
5498\f
5499(defvar cperl-outline-regexp
5500 (concat imenu-example--function-name-regexp-perl "\\|" "\\`"))
5501
5502;; Suggested by Mark A. Hershberger
5503(defun cperl-outline-level ()
5504 (looking-at outline-regexp)
5505 (cond ((not (match-beginning 1)) 0) ; beginning-of-file
5506 ((match-beginning 2)
5507 (if (eq (char-after (match-beginning 2)) ?p)
5508 0 ; package
5509 1)) ; sub
5510 ((match-beginning 5)
5511 (if (eq (char-after (match-beginning 5)) ?1)
5512 1 ; head1
5513 2)) ; head2
5514 (t 3))) ; should not happen
5515
5516\f
4633a7c4
LW
5517(defvar cperl-compilation-error-regexp-alist
5518 ;; This look like a paranoiac regexp: could anybody find a better one? (which WORK).
5519 '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
5520 2 3))
5521 "Alist that specifies how to match errors in perl output.")
5522
5523(if (fboundp 'eval-after-load)
5524 (eval-after-load
5525 "mode-compile"
5526 '(setq perl-compilation-error-regexp-alist
5527 cperl-compilation-error-regexp-alist)))
5528
5529
4633a7c4
LW
5530(defun cperl-windowed-init ()
5531 "Initialization under windowed version."
6c72d195
IZ
5532 (if (or (featurep 'ps-print) cperl-faces-init)
5533 ;; Need to init anyway:
5534 (or cperl-faces-init (cperl-init-faces))
5535 (add-hook 'font-lock-mode-hook
5536 (function
5537 (lambda ()
5538 (if (or
5539 (eq major-mode 'perl-mode)
5540 (eq major-mode 'cperl-mode))
5541 (progn
5542 (or cperl-faces-init (cperl-init-faces)))))))
5543 (if (fboundp 'eval-after-load)
5544 (eval-after-load
5545 "ps-print"
5546 '(or cperl-faces-init (cperl-init-faces))))))
5547
5548(defun cperl-load-font-lock-keywords ()
5549 (or cperl-faces-init (cperl-init-faces))
5550 perl-font-lock-keywords)
5551
5552(defun cperl-load-font-lock-keywords-1 ()
5553 (or cperl-faces-init (cperl-init-faces))
5554 perl-font-lock-keywords-1)
5555
5556(defun cperl-load-font-lock-keywords-2 ()
5557 (or cperl-faces-init (cperl-init-faces))
5558 perl-font-lock-keywords-2)
c07a80fd 5559
5560(defvar perl-font-lock-keywords-1 nil
6c72d195 5561 "Additional expressions to highlight in Perl mode. Minimal set.")
c07a80fd 5562(defvar perl-font-lock-keywords nil
6c72d195 5563 "Additional expressions to highlight in Perl mode. Default set.")
c07a80fd 5564(defvar perl-font-lock-keywords-2 nil
6c72d195
IZ
5565 "Additional expressions to highlight in Perl mode. Maximal set")
5566
5567(defvar font-lock-background-mode)
5568(defvar font-lock-display-type)
5569(defun cperl-init-faces-weak ()
5570 ;; Allow `cperl-find-pods-heres' to run.
5571 (or (boundp 'font-lock-constant-face)
4584684c
GS
5572 (cperl-force-face font-lock-constant-face
5573 "Face for constant and label names")
5574 ;;(setq font-lock-constant-face 'font-lock-constant-face)
5575 ))
4633a7c4
LW
5576
5577(defun cperl-init-faces ()
20675f5d 5578 (condition-case errs
4633a7c4
LW
5579 (progn
5580 (require 'font-lock)
c07a80fd 5581 (and (fboundp 'font-lock-fontify-anchored-keywords)
5582 (featurep 'font-lock-extra)
6c72d195 5583 (message "You have an obsolete package `font-lock-extra'. Install `choose-color'."))
c07a80fd 5584 (let (t-font-lock-keywords t-font-lock-keywords-1 font-lock-anchored)
c07a80fd 5585 (if (fboundp 'font-lock-fontify-anchored-keywords)
5586 (setq font-lock-anchored t))
4633a7c4
LW
5587 (setq
5588 t-font-lock-keywords
5589 (list
4584684c 5590 (list "[ \t]+$" 0 cperl-invalid-face t)
4633a7c4
LW
5591 (cons
5592 (concat
5593 "\\(^\\|[^$@%&\\]\\)\\<\\("
5594 (mapconcat
5595 'identity
5596 '("if" "until" "while" "elsif" "else" "unless" "for"
5597 "foreach" "continue" "exit" "die" "last" "goto" "next"
5598 "redo" "return" "local" "exec" "sub" "do" "dump" "use"
7bcea553 5599 "require" "package" "eval" "my" "BEGIN" "END" "CHECK" "INIT")
4633a7c4
LW
5600 "\\|") ; Flow control
5601 "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]"
5602 ; In what follows we use `type' style
55497cff 5603 ; for overwritable builtins
4633a7c4
LW
5604 (list
5605 (concat
5606 "\\(^\\|[^$@%&\\]\\)\\<\\("
55497cff 5607 ;; "CORE" "__FILE__" "__LINE__" "abs" "accept" "alarm"
5608 ;; "and" "atan2" "bind" "binmode" "bless" "caller"
5609 ;; "chdir" "chmod" "chown" "chr" "chroot" "close"
5610 ;; "closedir" "cmp" "connect" "continue" "cos" "crypt"
5611 ;; "dbmclose" "dbmopen" "die" "dump" "endgrent"
5612 ;; "endhostent" "endnetent" "endprotoent" "endpwent"
5613 ;; "endservent" "eof" "eq" "exec" "exit" "exp" "fcntl"
5614 ;; "fileno" "flock" "fork" "formline" "ge" "getc"
5615 ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr"
5616 ;; "gethostbyname" "gethostent" "getlogin"
5617 ;; "getnetbyaddr" "getnetbyname" "getnetent"
5618 ;; "getpeername" "getpgrp" "getppid" "getpriority"
5619 ;; "getprotobyname" "getprotobynumber" "getprotoent"
5620 ;; "getpwent" "getpwnam" "getpwuid" "getservbyname"
5621 ;; "getservbyport" "getservent" "getsockname"
5622 ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int"
5623 ;; "ioctl" "join" "kill" "lc" "lcfirst" "le" "length"
20675f5d 5624 ;; "link" "listen" "localtime" "lock" "log" "lstat" "lt"
55497cff 5625 ;; "mkdir" "msgctl" "msgget" "msgrcv" "msgsnd" "ne"
5626 ;; "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
5627 ;; "quotemeta" "rand" "read" "readdir" "readline"
5628 ;; "readlink" "readpipe" "recv" "ref" "rename" "require"
5629 ;; "reset" "reverse" "rewinddir" "rindex" "rmdir" "seek"
5630 ;; "seekdir" "select" "semctl" "semget" "semop" "send"
5631 ;; "setgrent" "sethostent" "setnetent" "setpgrp"
5632 ;; "setpriority" "setprotoent" "setpwent" "setservent"
5633 ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite"
5634 ;; "shutdown" "sin" "sleep" "socket" "socketpair"
5635 ;; "sprintf" "sqrt" "srand" "stat" "substr" "symlink"
7bcea553 5636 ;; "syscall" "sysopen" "sysread" "system" "syswrite" "tell"
55497cff 5637 ;; "telldir" "time" "times" "truncate" "uc" "ucfirst"
5638 ;; "umask" "unlink" "unpack" "utime" "values" "vec"
5639 ;; "wait" "waitpid" "wantarray" "warn" "write" "x" "xor"
4633a7c4
LW
5640 "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|"
5641 "b\\(in\\(d\\|mode\\)\\|less\\)\\|"
5642 "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|"
5643 "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|"
5644 "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|"
5645 "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|"
5646 "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|"
5647 "f\\(ileno\\|cntl\\|lock\\|or\\(k\\|mline\\)\\)\\|"
5648 "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|"
5649 "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w"
5650 "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|"
5651 "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|"
5652 "ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|"
5653 "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|"
5654 "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|"
5655 "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e"
20675f5d 5656 "\\(\\|ngth\\)\\|o\\(c\\(altime\\|k\\)\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|"
4633a7c4
LW
5657 "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|"
5658 "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|"
5659 "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin"
5660 "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name"
5661 "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r"
5662 "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|"
5663 "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|"
5664 "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|"
7bcea553 5665 "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|open\\|tem\\|write\\)\\|"
4633a7c4
LW
5666 "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|"
5667 "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|"
5668 "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|"
5669 "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|"
ebcd4dbc 5670 "x\\(\\|or\\)\\|__\\(FILE__\\|LINE__\\|PACKAGE__\\)"
4633a7c4
LW
5671 "\\)\\>") 2 'font-lock-type-face)
5672 ;; In what follows we use `other' style
55497cff 5673 ;; for nonoverwritable builtins
5674 ;; Somehow 's', 'm' are not auto-generated???
4633a7c4
LW
5675 (list
5676 (concat
5677 "\\(^\\|[^$@%&\\]\\)\\<\\("
7bcea553 5678 ;; "AUTOLOAD" "BEGIN" "CHECK" "DESTROY" "END" "INIT" "__END__" "chomp"
55497cff 5679 ;; "chop" "defined" "delete" "do" "each" "else" "elsif"
5680 ;; "eval" "exists" "for" "foreach" "format" "goto"
5681 ;; "grep" "if" "keys" "last" "local" "map" "my" "next"
7bcea553 5682 ;; "no" "package" "pop" "pos" "print" "printf" "push"
55497cff 5683 ;; "q" "qq" "qw" "qx" "redo" "return" "scalar" "shift"
5684 ;; "sort" "splice" "split" "study" "sub" "tie" "tr"
5685 ;; "undef" "unless" "unshift" "untie" "until" "use"
5686 ;; "while" "y"
296d8a58 5687 "AUTOLOAD\\|BEGIN\\|CHECK\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|"
4633a7c4 5688 "o\\)\\|DESTROY\\|e\\(ach\\|val\\|xists\\|ls\\(e\\|if\\)\\)\\|"
7bcea553
IZ
5689 "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|INIT\\|if\\|keys\\|"
5690 "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|our\\|"
4633a7c4 5691 "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|"
20675f5d 5692 "q\\(\\|q\\|w\\|x\\|r\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|"
4633a7c4
LW
5693 "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|"
5694 "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|"
5695 "while\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added manually
5696 "\\|[sm]" ; Added manually
4584684c 5697 "\\)\\>") 2 'cperl-nonoverridable-face)
4633a7c4
LW
5698 ;; (mapconcat 'identity
5699 ;; '("#endif" "#else" "#ifdef" "#ifndef" "#if"
5700 ;; "#include" "#define" "#undef")
5701 ;; "\\|")
5702 '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0
55497cff 5703 font-lock-function-name-face keep) ; Not very good, triggers at "[a-z]"
4584684c 5704 '("\\<sub[ \t]+\\([^ \t{;()]+\\)[ \t]*\\(([^()]*)[ \t]*\\)?[#{\n]" 1
4633a7c4 5705 font-lock-function-name-face)
c07a80fd 5706 '("\\<\\(package\\|require\\|use\\|import\\|no\\|bootstrap\\)[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t;]" ; require A if B;
4633a7c4 5707 2 font-lock-function-name-face)
499d5216
IZ
5708 '("^[ \t]*format[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t]*=[ \t]*$"
5709 1 font-lock-function-name-face)
c07a80fd 5710 (cond ((featurep 'font-lock-extra)
29043b61 5711 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 5712 (2 font-lock-string-face t)
5713 (0 '(restart 2 t)))) ; To highlight $a{bc}{ef}
5714 (font-lock-anchored
29043b61 5715 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 5716 (2 font-lock-string-face t)
29043b61 5717 ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 5718 nil nil
5719 (1 font-lock-string-face t))))
29043b61 5720 (t '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 5721 2 font-lock-string-face t)))
6c72d195 5722 '("[\[ \t{,(]\\(-?[a-zA-Z0-9_:]+\\)[ \t]*=>" 1
4633a7c4
LW
5723 font-lock-string-face t)
5724 '("^[ \t]*\\([a-zA-Z0-9_]+[ \t]*:\\)[ \t]*\\($\\|{\\|\\<\\(until\\|while\\|for\\(each\\)?\\|do\\)\\>\\)" 1
6c72d195 5725 font-lock-constant-face) ; labels
4633a7c4 5726 '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets
6c72d195 5727 2 font-lock-constant-face)
7bcea553
IZ
5728 ;; Uncomment to get perl-mode-like vars
5729 ;;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
5730 ;;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
5731 ;;; (2 (cons font-lock-variable-name-face '(underline))))
c07a80fd 5732 (cond ((featurep 'font-lock-extra)
296d8a58 5733 '("^[ \t]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
c07a80fd 5734 (3 font-lock-variable-name-face)
5735 (4 '(another 4 nil
5736 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
5737 (1 font-lock-variable-name-face)
5738 (2 '(restart 2 nil) nil t)))
5739 nil t))) ; local variables, multiple
5740 (font-lock-anchored
296d8a58 5741 '("^[ \t{}]*\\(my\\|local\\|our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
c07a80fd 5742 (3 font-lock-variable-name-face)
5743 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)"
5744 nil nil
5745 (1 font-lock-variable-name-face))))
7bcea553 5746 (t '("^[ \t{}]*\\(my\\|local\\our\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
c07a80fd 5747 3 font-lock-variable-name-face)))
7bcea553
IZ
5748 '("\\<for\\(each\\)?\\([ \t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*("
5749 4 font-lock-variable-name-face)))
c07a80fd 5750 (setq
5751 t-font-lock-keywords-1
5752 (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock
55497cff 5753 (not cperl-xemacs-p) ; not yet as of XEmacs 19.12
5754 '(
5755 ("\\(\\([@%]\\|\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
5756 (if (eq (char-after (match-beginning 2)) ?%)
6c72d195
IZ
5757 cperl-hash-face
5758 cperl-array-face)
55497cff 5759 t) ; arrays and hashes
5760 ("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
c07a80fd 5761 1
5762 (if (= (- (match-end 2) (match-beginning 2)) 1)
5763 (if (eq (char-after (match-beginning 3)) ?{)
6c72d195
IZ
5764 cperl-hash-face
5765 cperl-array-face) ; arrays and hashes
c07a80fd 5766 font-lock-variable-name-face) ; Just to put something
5767 t)
c07a80fd 5768 ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
4633a7c4 5769 ;;; Too much noise from \s* @s[ and friends
c07a80fd 5770 ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
5771 ;;(3 font-lock-function-name-face t t)
5772 ;;(4
5773 ;; (if (cperl-slash-is-regexp)
5774 ;; font-lock-function-name-face 'default) nil t))
5775 )))
7bcea553
IZ
5776 (if cperl-highlight-variables-indiscriminately
5777 (setq t-font-lock-keywords-1
5778 (append t-font-lock-keywords-1
5779 (list '("[$*]{?\\(\\sw+\\)" 1
5780 font-lock-variable-name-face)))))
20675f5d
IZ
5781 (setq perl-font-lock-keywords-1
5782 (if cperl-syntaxify-by-font-lock
5783 (cons 'cperl-fontify-update
5784 t-font-lock-keywords)
5785 t-font-lock-keywords)
c07a80fd 5786 perl-font-lock-keywords perl-font-lock-keywords-1
5787 perl-font-lock-keywords-2 (append
20675f5d 5788 perl-font-lock-keywords-1
c07a80fd 5789 t-font-lock-keywords-1)))
4633a7c4 5790 (if (fboundp 'ps-print-buffer) (cperl-ps-print-init))
c07a80fd 5791 (if (or (featurep 'choose-color) (featurep 'font-lock-extra))
6c72d195
IZ
5792 (eval ; Avoid a warning
5793 '(font-lock-require-faces
4633a7c4
LW
5794 (list
5795 ;; Color-light Color-dark Gray-light Gray-dark Mono
5796 (list 'font-lock-comment-face
5797 ["Firebrick" "OrangeRed" "DimGray" "Gray80"]
5798 nil
5799 [nil nil t t t]
5800 [nil nil t t t]
5801 nil)
5802 (list 'font-lock-string-face
5803 ["RosyBrown" "LightSalmon" "Gray50" "LightGray"]
5804 nil
5805 nil
5806 [nil nil t t t]
5807 nil)
4633a7c4
LW
5808 (list 'font-lock-function-name-face
5809 (vector
5810 "Blue" "LightSkyBlue" "Gray50" "LightGray"
5811 (cdr (assq 'background-color ; if mono
5812 (frame-parameters))))
5813 (vector
5814 nil nil nil nil
5815 (cdr (assq 'foreground-color ; if mono
5816 (frame-parameters))))
5817 [nil nil t t t]
5818 nil
5819 nil)
5820 (list 'font-lock-variable-name-face
5821 ["DarkGoldenrod" "LightGoldenrod" "DimGray" "Gray90"]
5822 nil
5823 [nil nil t t t]
5824 [nil nil t t t]
5825 nil)
5826 (list 'font-lock-type-face
5827 ["DarkOliveGreen" "PaleGreen" "DimGray" "Gray80"]
5828 nil
5829 [nil nil t t t]
5830 nil
5831 [nil nil t t t]
5832 )
6c72d195 5833 (list 'font-lock-constant-face
4633a7c4
LW
5834 ["CadetBlue" "Aquamarine" "Gray50" "LightGray"]
5835 nil
5836 [nil nil t t t]
5837 nil
5838 [nil nil t t t]
5839 )
4584684c 5840 (list 'cperl-nonoverridable-face
4633a7c4
LW
5841 ["chartreuse3" ("orchid1" "orange")
5842 nil "Gray80"]
5843 [nil nil "gray90"]
5844 [nil nil nil t t]
5845 [nil nil t t]
5846 [nil nil t t t]
5847 )
6c72d195 5848 (list 'cperl-array-face
4633a7c4
LW
5849 ["blue" "yellow" nil "Gray80"]
5850 ["lightyellow2" ("navy" "os2blue" "darkgreen")
5851 "gray90"]
5852 t
5853 nil
5854 nil)
6c72d195 5855 (list 'cperl-hash-face
4633a7c4
LW
5856 ["red" "red" nil "Gray80"]
5857 ["lightyellow2" ("navy" "os2blue" "darkgreen")
5858 "gray90"]
5859 t
5860 t
6c72d195 5861 nil))))
20675f5d 5862 ;; Do it the dull way, without choose-color
4633a7c4
LW
5863 (defvar cperl-guessed-background nil
5864 "Display characteristics as guessed by cperl.")
20675f5d
IZ
5865;; (or (fboundp 'x-color-defined-p)
5866;; (defalias 'x-color-defined-p
5867;; (cond ((fboundp 'color-defined-p) 'color-defined-p)
5868;; ;; XEmacs >= 19.12
5869;; ((fboundp 'valid-color-name-p) 'valid-color-name-p)
5870;; ;; XEmacs 19.11
5871;; (t 'x-valid-color-name-p))))
5872 (cperl-force-face font-lock-constant-face
5873 "Face for constant and label names")
5874 (cperl-force-face font-lock-variable-name-face
5875 "Face for variable names")
5876 (cperl-force-face font-lock-type-face
5877 "Face for data types")
4584684c 5878 (cperl-force-face cperl-nonoverridable-face
20675f5d
IZ
5879 "Face for data types from another group")
5880 (cperl-force-face font-lock-comment-face
5881 "Face for comments")
20675f5d
IZ
5882 (cperl-force-face font-lock-function-name-face
5883 "Face for function names")
5884 (cperl-force-face cperl-hash-face
5885 "Face for hashes")
5886 (cperl-force-face cperl-array-face
5887 "Face for arrays")
5888 ;;(defvar font-lock-constant-face 'font-lock-constant-face)
5889 ;;(defvar font-lock-variable-name-face 'font-lock-variable-name-face)
5890 ;;(or (boundp 'font-lock-type-face)
5891 ;; (defconst font-lock-type-face
5892 ;; 'font-lock-type-face
5893 ;; "Face to use for data types."))
4584684c
GS
5894 ;;(or (boundp 'cperl-nonoverridable-face)
5895 ;; (defconst cperl-nonoverridable-face
5896 ;; 'cperl-nonoverridable-face
20675f5d
IZ
5897 ;; "Face to use for data types from another group."))
5898 ;;(if (not cperl-xemacs-p) nil
5899 ;; (or (boundp 'font-lock-comment-face)
5900 ;; (defconst font-lock-comment-face
5901 ;; 'font-lock-comment-face
5902 ;; "Face to use for comments."))
5903 ;; (or (boundp 'font-lock-keyword-face)
5904 ;; (defconst font-lock-keyword-face
5905 ;; 'font-lock-keyword-face
5906 ;; "Face to use for keywords."))
5907 ;; (or (boundp 'font-lock-function-name-face)
5908 ;; (defconst font-lock-function-name-face
5909 ;; 'font-lock-function-name-face
5910 ;; "Face to use for function names.")))
6c72d195
IZ
5911 (if (and
5912 (not (cperl-is-face 'cperl-array-face))
5913 (cperl-is-face 'font-lock-emphasized-face))
20675f5d 5914 (copy-face 'font-lock-emphasized-face 'cperl-array-face))
6c72d195
IZ
5915 (if (and
5916 (not (cperl-is-face 'cperl-hash-face))
5917 (cperl-is-face 'font-lock-other-emphasized-face))
5918 (copy-face 'font-lock-other-emphasized-face
5919 'cperl-hash-face))
4584684c
GS
5920 (if (and
5921 (not (cperl-is-face 'cperl-nonoverridable-face))
5922 (cperl-is-face 'font-lock-other-type-face))
5923 (copy-face 'font-lock-other-type-face
5924 'cperl-nonoverridable-face))
20675f5d
IZ
5925 ;;(or (boundp 'cperl-hash-face)
5926 ;; (defconst cperl-hash-face
5927 ;; 'cperl-hash-face
5928 ;; "Face to use for hashes."))
5929 ;;(or (boundp 'cperl-array-face)
5930 ;; (defconst cperl-array-face
5931 ;; 'cperl-array-face
5932 ;; "Face to use for arrays."))
4633a7c4
LW
5933 ;; Here we try to guess background
5934 (let ((background
5935 (if (boundp 'font-lock-background-mode)
5936 font-lock-background-mode
5937 'light))
5938 (face-list (and (fboundp 'face-list) (face-list)))
20675f5d
IZ
5939 ;; cperl-is-face
5940 )
5941;;;; (fset 'cperl-is-face
5942;;;; (cond ((fboundp 'find-face)
5943;;;; (symbol-function 'find-face))
5944;;;; (face-list
5945;;;; (function (lambda (face) (member face face-list))))
5946;;;; (t
5947;;;; (function (lambda (face) (boundp face))))))
4633a7c4
LW
5948 (defvar cperl-guessed-background
5949 (if (and (boundp 'font-lock-display-type)
5950 (eq font-lock-display-type 'grayscale))
5951 'gray
5952 background)
5953 "Background as guessed by CPerl mode")
6c72d195
IZ
5954 (if (and
5955 (not (cperl-is-face 'font-lock-constant-face))
5956 (cperl-is-face 'font-lock-reference-face))
6c72d195
IZ
5957 (copy-face 'font-lock-reference-face 'font-lock-constant-face))
5958 (if (cperl-is-face 'font-lock-type-face) nil
4633a7c4
LW
5959 (copy-face 'default 'font-lock-type-face)
5960 (cond
5961 ((eq background 'light)
5962 (set-face-foreground 'font-lock-type-face
5963 (if (x-color-defined-p "seagreen")
5964 "seagreen"
5965 "sea green")))
5966 ((eq background 'dark)
5967 (set-face-foreground 'font-lock-type-face
5968 (if (x-color-defined-p "os2pink")
5969 "os2pink"
5970 "pink")))
5971 (t
5972 (set-face-background 'font-lock-type-face "gray90"))))
4584684c 5973 (if (cperl-is-face 'cperl-nonoverridable-face)
4633a7c4 5974 nil
4584684c 5975 (copy-face 'font-lock-type-face 'cperl-nonoverridable-face)
4633a7c4
LW
5976 (cond
5977 ((eq background 'light)
4584684c 5978 (set-face-foreground 'cperl-nonoverridable-face
4633a7c4
LW
5979 (if (x-color-defined-p "chartreuse3")
5980 "chartreuse3"
5981 "chartreuse")))
5982 ((eq background 'dark)
4584684c 5983 (set-face-foreground 'cperl-nonoverridable-face
4633a7c4
LW
5984 (if (x-color-defined-p "orchid1")
5985 "orchid1"
5986 "orange")))))
4584684c
GS
5987;;; (if (cperl-is-face 'font-lock-other-emphasized-face) nil
5988;;; (copy-face 'bold-italic 'font-lock-other-emphasized-face)
5989;;; (cond
5990;;; ((eq background 'light)
5991;;; (set-face-background 'font-lock-other-emphasized-face
5992;;; (if (x-color-defined-p "lightyellow2")
5993;;; "lightyellow2"
5994;;; (if (x-color-defined-p "lightyellow")
5995;;; "lightyellow"
5996;;; "light yellow"))))
5997;;; ((eq background 'dark)
5998;;; (set-face-background 'font-lock-other-emphasized-face
5999;;; (if (x-color-defined-p "navy")
6000;;; "navy"
6001;;; (if (x-color-defined-p "darkgreen")
6002;;; "darkgreen"
6003;;; "dark green"))))
6004;;; (t (set-face-background 'font-lock-other-emphasized-face "gray90"))))
6005;;; (if (cperl-is-face 'font-lock-emphasized-face) nil
6006;;; (copy-face 'bold 'font-lock-emphasized-face)
6007;;; (cond
6008;;; ((eq background 'light)
6009;;; (set-face-background 'font-lock-emphasized-face
6010;;; (if (x-color-defined-p "lightyellow2")
6011;;; "lightyellow2"
6012;;; "lightyellow")))
6013;;; ((eq background 'dark)
6014;;; (set-face-background 'font-lock-emphasized-face
6015;;; (if (x-color-defined-p "navy")
6016;;; "navy"
6017;;; (if (x-color-defined-p "darkgreen")
6018;;; "darkgreen"
6019;;; "dark green"))))
6020;;; (t (set-face-background 'font-lock-emphasized-face "gray90"))))
6c72d195 6021 (if (cperl-is-face 'font-lock-variable-name-face) nil
4633a7c4 6022 (copy-face 'italic 'font-lock-variable-name-face))
6c72d195
IZ
6023 (if (cperl-is-face 'font-lock-constant-face) nil
6024 (copy-face 'italic 'font-lock-constant-face))))
c07a80fd 6025 (setq cperl-faces-init t))
20675f5d 6026 (error (message "cperl-init-faces (ignored): %s" errs))))
4633a7c4
LW
6027
6028
6029(defun cperl-ps-print-init ()
6030 "Initialization of `ps-print' components for faces used in CPerl."
4584684c
GS
6031 (eval-after-load "ps-print"
6032 '(setq ps-bold-faces
6033 ;; font-lock-variable-name-face
6034 ;; font-lock-constant-face
6035 (append '(cperl-array-face
6036 cperl-hash-face)
6037 ps-bold-faces)
6038 ps-italic-faces
6039 ;; font-lock-constant-face
6040 (append '(cperl-nonoverridable-face
6041 cperl-hash-face)
6042 ps-italic-faces)
6043 ps-underlined-faces
6044 ;; font-lock-type-face
6045 (append '(cperl-array-face
6046 cperl-hash-face
6047 underline
6048 cperl-nonoverridable-face)
6049 ps-underlined-faces))))
6050
6051(defvar ps-print-face-extension-alist)
6052
6053(defun cperl-ps-print (&optional file)
6054 "Pretty-print in CPerl style.
6055If optional argument FILE is an empty string, prints to printer, otherwise
6056to the file FILE. If FILE is nil, prompts for a file name.
6057
6058Style of printout regulated by the variable `cperl-ps-print-face-properties'."
6059 (interactive)
6060 (or file
6061 (setq file (read-from-minibuffer
6062 "Print to file (if empty - to printer): "
6063 (concat (buffer-file-name) ".ps")
6064 nil nil 'file-name-history)))
6065 (or (> (length file) 0)
6066 (setq file nil))
6067 (require 'ps-print) ; To get ps-print-face-extension-alist
6068 (let ((ps-print-color-p t)
6069 (ps-print-face-extension-alist ps-print-face-extension-alist))
6070 (cperl-ps-extend-face-list cperl-ps-print-face-properties)
6071 (ps-print-buffer-with-faces file)))
6072
6073;;; (defun cperl-ps-print-init ()
6074;;; "Initialization of `ps-print' components for faces used in CPerl."
6075;;; ;; Guard against old versions
6076;;; (defvar ps-underlined-faces nil)
6077;;; (defvar ps-bold-faces nil)
6078;;; (defvar ps-italic-faces nil)
6079;;; (setq ps-bold-faces
6080;;; (append '(font-lock-emphasized-face
6081;;; cperl-array-face
6082;;; font-lock-keyword-face
6083;;; font-lock-variable-name-face
6084;;; font-lock-constant-face
6085;;; font-lock-reference-face
6086;;; font-lock-other-emphasized-face
6087;;; cperl-hash-face)
6088;;; ps-bold-faces))
6089;;; (setq ps-italic-faces
6090;;; (append '(cperl-nonoverridable-face
6091;;; font-lock-constant-face
6092;;; font-lock-reference-face
6093;;; font-lock-other-emphasized-face
6094;;; cperl-hash-face)
6095;;; ps-italic-faces))
6096;;; (setq ps-underlined-faces
6097;;; (append '(font-lock-emphasized-face
6098;;; cperl-array-face
6099;;; font-lock-other-emphasized-face
6100;;; cperl-hash-face
6101;;; cperl-nonoverridable-face font-lock-type-face)
6102;;; ps-underlined-faces))
6103;;; (cons 'font-lock-type-face ps-underlined-faces))
4633a7c4
LW
6104
6105
6106(if (cperl-enable-font-lock) (cperl-windowed-init))
6107
6c72d195
IZ
6108(defconst cperl-styles-entries
6109 '(cperl-indent-level cperl-brace-offset cperl-continued-brace-offset
6110 cperl-label-offset cperl-extra-newline-before-brace
6111 cperl-merge-trailing-else
6112 cperl-continued-statement-offset))
6113
6114(defconst cperl-style-alist
6115 '(("CPerl" ; =GNU without extra-newline-before-brace
6116 (cperl-indent-level . 2)
6117 (cperl-brace-offset . 0)
6118 (cperl-continued-brace-offset . 0)
6119 (cperl-label-offset . -2)
6120 (cperl-extra-newline-before-brace . nil)
6121 (cperl-merge-trailing-else . t)
6122 (cperl-continued-statement-offset . 2))
6123 ("PerlStyle" ; CPerl with 4 as indent
6124 (cperl-indent-level . 4)
6125 (cperl-brace-offset . 0)
6126 (cperl-continued-brace-offset . 0)
6127 (cperl-label-offset . -4)
6128 (cperl-extra-newline-before-brace . nil)
6129 (cperl-merge-trailing-else . t)
6130 (cperl-continued-statement-offset . 4))
6131 ("GNU"
6132 (cperl-indent-level . 2)
6133 (cperl-brace-offset . 0)
6134 (cperl-continued-brace-offset . 0)
6135 (cperl-label-offset . -2)
6136 (cperl-extra-newline-before-brace . t)
6137 (cperl-merge-trailing-else . nil)
6138 (cperl-continued-statement-offset . 2))
6139 ("K&R"
6140 (cperl-indent-level . 5)
6141 (cperl-brace-offset . 0)
6142 (cperl-continued-brace-offset . -5)
6143 (cperl-label-offset . -5)
6144 ;;(cperl-extra-newline-before-brace . nil) ; ???
6145 (cperl-merge-trailing-else . nil)
6146 (cperl-continued-statement-offset . 5))
6147 ("BSD"
6148 (cperl-indent-level . 4)
6149 (cperl-brace-offset . 0)
6150 (cperl-continued-brace-offset . -4)
6151 (cperl-label-offset . -4)
6152 ;;(cperl-extra-newline-before-brace . nil) ; ???
6153 (cperl-continued-statement-offset . 4))
6154 ("C++"
6155 (cperl-indent-level . 4)
6156 (cperl-brace-offset . 0)
6157 (cperl-continued-brace-offset . -4)
6158 (cperl-label-offset . -4)
6159 (cperl-continued-statement-offset . 4)
6160 (cperl-merge-trailing-else . nil)
6161 (cperl-extra-newline-before-brace . t))
6162 ("Current")
6163 ("Whitesmith"
6164 (cperl-indent-level . 4)
6165 (cperl-brace-offset . 0)
6166 (cperl-continued-brace-offset . 0)
6167 (cperl-label-offset . -4)
6168 ;;(cperl-extra-newline-before-brace . nil) ; ???
6169 (cperl-continued-statement-offset . 4)))
6170 "(Experimental) list of variables to set to get a particular indentation style.
4584684c 6171Should be used via `cperl-set-style' or via Perl menu.")
6c72d195 6172
4633a7c4
LW
6173(defun cperl-set-style (style)
6174 "Set CPerl-mode variables to use one of several different indentation styles.
6175The arguments are a string representing the desired style.
6c72d195
IZ
6176The list of styles is in `cperl-style-alist', available styles
6177are GNU, K&R, BSD, C++ and Whitesmith.
6178
6179The current value of style is memorized (unless there is a memorized
6180data already), may be restored by `cperl-set-style-back'.
6181
6182Chosing \"Current\" style will not change style, so this may be used for
6183side-effect of memorizing only."
4633a7c4
LW
6184 (interactive
6185 (let ((list (mapcar (function (lambda (elt) (list (car elt))))
6c72d195 6186 cperl-style-alist)))
4633a7c4 6187 (list (completing-read "Enter style: " list nil 'insist))))
6c72d195
IZ
6188 (or cperl-old-style
6189 (setq cperl-old-style
6190 (mapcar (function
6191 (lambda (name)
6192 (cons name (eval name))))
6193 cperl-styles-entries)))
6194 (let ((style (cdr (assoc style cperl-style-alist))) setting str sym)
4633a7c4
LW
6195 (while style
6196 (setq setting (car style) style (cdr style))
6c72d195
IZ
6197 (set (car setting) (cdr setting)))))
6198
6199(defun cperl-set-style-back ()
6200 "Restore a style memorised by `cperl-set-style'."
6201 (interactive)
6202 (or cperl-old-style (error "The style was not changed"))
6203 (let (setting)
6204 (while cperl-old-style
6205 (setq setting (car cperl-old-style)
6206 cperl-old-style (cdr cperl-old-style))
6207 (set (car setting) (cdr setting)))))
4633a7c4
LW
6208
6209(defun cperl-check-syntax ()
6210 (interactive)
6211 (require 'mode-compile)
6c72d195
IZ
6212 (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc")))
6213 (eval '(mode-compile)))) ; Avoid a warning
4633a7c4 6214
5f05dabc 6215(defun cperl-info-buffer (type)
6c72d195 6216 ;; Returns buffer with documentation. Creates if missing.
5f05dabc 6217 ;; If TYPE, this vars buffer.
6218 ;; Special care is taken to not stomp over an existing info buffer
6219 (let* ((bname (if type "*info-perl-var*" "*info-perl*"))
6220 (info (get-buffer bname))
6221 (oldbuf (get-buffer "*info*")))
4633a7c4
LW
6222 (if info info
6223 (save-window-excursion
6224 ;; Get Info running
6225 (require 'info)
5f05dabc 6226 (cond (oldbuf
6227 (set-buffer oldbuf)
6228 (rename-buffer "*info-perl-tmp*")))
4633a7c4
LW
6229 (save-window-excursion
6230 (info))
5f05dabc 6231 (Info-find-node cperl-info-page (if type "perlvar" "perlfunc"))
4633a7c4 6232 (set-buffer "*info*")
5f05dabc 6233 (rename-buffer bname)
6234 (cond (oldbuf
6235 (set-buffer "*info-perl-tmp*")
6236 (rename-buffer "*info*")
6237 (set-buffer bname)))
6238 (make-variable-buffer-local 'window-min-height)
6239 (setq window-min-height 2)
4633a7c4
LW
6240 (current-buffer)))))
6241
6242(defun cperl-word-at-point (&optional p)
6243 ;; Returns the word at point or at P.
6244 (save-excursion
6245 (if p (goto-char p))
5f05dabc 6246 (or (cperl-word-at-point-hard)
6247 (progn
6248 (require 'etags)
6249 (funcall (or (and (boundp 'find-tag-default-function)
6250 find-tag-default-function)
6251 (get major-mode 'find-tag-default-function)
6252 ;; XEmacs 19.12 has `find-tag-default-hook'; it is
6253 ;; automatically used within `find-tag-default':
6254 'find-tag-default))))))
4633a7c4
LW
6255
6256(defun cperl-info-on-command (command)
5f05dabc 6257 "Shows documentation for Perl command in other window.
6258If perl-info buffer is shown in some frame, uses this frame.
6259Customized by setting variables `cperl-shrink-wrap-info-frame',
6260`cperl-max-help-size'."
4633a7c4
LW
6261 (interactive
6262 (let* ((default (cperl-word-at-point))
6263 (read (read-string
6264 (format "Find doc for Perl function (default %s): "
6265 default))))
6266 (list (if (equal read "")
6267 default
6268 read))))
6269
6270 (let ((buffer (current-buffer))
c07a80fd 6271 (cmd-desc (concat "^" (regexp-quote command) "[^a-zA-Z_0-9]")) ; "tr///"
5f05dabc 6272 pos isvar height iniheight frheight buf win fr1 fr2 iniwin not-loner
6273 max-height char-height buf-list)
4633a7c4
LW
6274 (if (string-match "^-[a-zA-Z]$" command)
6275 (setq cmd-desc "^-X[ \t\n]"))
5f05dabc 6276 (setq isvar (string-match "^[$@%]" command)
6277 buf (cperl-info-buffer isvar)
6278 iniwin (selected-window)
6279 fr1 (window-frame iniwin))
6280 (set-buffer buf)
4633a7c4 6281 (beginning-of-buffer)
5f05dabc 6282 (or isvar
6283 (progn (re-search-forward "^-X[ \t\n]")
6284 (forward-line -1)))
4633a7c4
LW
6285 (if (re-search-forward cmd-desc nil t)
6286 (progn
5f05dabc 6287 ;; Go back to beginning of the group (ex, for qq)
6288 (if (re-search-backward "^[ \t\n\f]")
6289 (forward-line 1))
6290 (beginning-of-line)
6291 ;; Get some of
6292 (setq pos (point)
6293 buf-list (list buf "*info-perl-var*" "*info-perl*"))
6294 (while (and (not win) buf-list)
6295 (setq win (get-buffer-window (car buf-list) t))
6296 (setq buf-list (cdr buf-list)))
6297 (or (not win)
6298 (eq (window-buffer win) buf)
6299 (set-window-buffer win buf))
6300 (and win (setq fr2 (window-frame win)))
6301 (if (or (not fr2) (eq fr1 fr2))
6302 (pop-to-buffer buf)
6303 (special-display-popup-frame buf) ; Make it visible
6304 (select-window win))
6305 (goto-char pos) ; Needed (?!).
6306 ;; Resize
6307 (setq iniheight (window-height)
6308 frheight (frame-height)
6309 not-loner (< iniheight (1- frheight))) ; Are not alone
6310 (cond ((if not-loner cperl-max-help-size
6311 cperl-shrink-wrap-info-frame)
6312 (setq height
6313 (+ 2
6314 (count-lines
6315 pos
6316 (save-excursion
6317 (if (re-search-forward
6318 "^[ \t][^\n]*\n+\\([^ \t\n\f]\\|\\'\\)" nil t)
6319 (match-beginning 0) (point-max)))))
6320 max-height
6321 (if not-loner
6322 (/ (* (- frheight 3) cperl-max-help-size) 100)
6323 (setq char-height (frame-char-height))
6324 ;; Non-functioning under OS/2:
6325 (if (eq char-height 1) (setq char-height 18))
6326 ;; Title, menubar, + 2 for slack
6327 (- (/ (x-display-pixel-height) char-height) 4)
6328 ))
6329 (if (> height max-height) (setq height max-height))
6330 ;;(message "was %s doing %s" iniheight height)
6331 (if not-loner
6332 (enlarge-window (- height iniheight))
6333 (set-frame-height (window-frame win) (1+ height)))))
4633a7c4
LW
6334 (set-window-start (selected-window) pos))
6335 (message "No entry for %s found." command))
5f05dabc 6336 ;;(pop-to-buffer buffer)
6337 (select-window iniwin)))
4633a7c4
LW
6338
6339(defun cperl-info-on-current-command ()
6340 "Shows documentation for Perl command at point in other window."
6341 (interactive)
6342 (cperl-info-on-command (cperl-word-at-point)))
6343
6344(defun cperl-imenu-info-imenu-search ()
6345 (if (looking-at "^-X[ \t\n]") nil
6346 (re-search-backward
ebcd4dbc 6347 "^\n\\([-a-zA-Z_]+\\)[ \t\n]")
4633a7c4
LW
6348 (forward-line 1)))
6349
6350(defun cperl-imenu-info-imenu-name ()
6351 (buffer-substring
6352 (match-beginning 1) (match-end 1)))
6353
6354(defun cperl-imenu-on-info ()
6355 (interactive)
6356 (let* ((buffer (current-buffer))
6357 imenu-create-index-function
6358 imenu-prev-index-position-function
6359 imenu-extract-index-name-function
6360 (index-item (save-restriction
6361 (save-window-excursion
5f05dabc 6362 (set-buffer (cperl-info-buffer nil))
4633a7c4
LW
6363 (setq imenu-create-index-function
6364 'imenu-default-create-index-function
6365 imenu-prev-index-position-function
6366 'cperl-imenu-info-imenu-search
6367 imenu-extract-index-name-function
6368 'cperl-imenu-info-imenu-name)
6369 (imenu-choose-buffer-index)))))
6370 (and index-item
6371 (progn
6372 (push-mark)
6373 (pop-to-buffer "*info-perl*")
6374 (cond
6375 ((markerp (cdr index-item))
6376 (goto-char (marker-position (cdr index-item))))
6377 (t
6378 (goto-char (cdr index-item))))
6379 (set-window-start (selected-window) (point))
6380 (pop-to-buffer buffer)))))
6381
6382(defun cperl-lineup (beg end &optional step minshift)
6383 "Lineup construction in a region.
6384Beginning of region should be at the start of a construction.
55497cff 6385All first occurrences of this construction in the lines that are
4633a7c4
LW
6386partially contained in the region are lined up at the same column.
6387
6388MINSHIFT is the minimal amount of space to insert before the construction.
6389STEP is the tabwidth to position constructions.
6390If STEP is `nil', `cperl-lineup-step' will be used
6391\(or `cperl-indent-level', if `cperl-lineup-step' is `nil').
6392Will not move the position at the start to the left."
6393 (interactive "r")
6394 (let (search col tcol seen b e)
6395 (save-excursion
6396 (goto-char end)
6397 (end-of-line)
6398 (setq end (point-marker))
6399 (goto-char beg)
6400 (skip-chars-forward " \t\f")
6401 (setq beg (point-marker))
6402 (indent-region beg end nil)
6403 (goto-char beg)
6404 (setq col (current-column))
499d5216
IZ
6405 (if (looking-at "[a-zA-Z0-9_]")
6406 (if (looking-at "\\<[a-zA-Z0-9_]+\\>")
4633a7c4
LW
6407 (setq search
6408 (concat "\\<"
6409 (regexp-quote
6410 (buffer-substring (match-beginning 0)
6411 (match-end 0))) "\\>"))
6412 (error "Cannot line up in a middle of the word"))
6413 (if (looking-at "$")
6414 (error "Cannot line up end of line"))
6415 (setq search (regexp-quote (char-to-string (following-char)))))
6416 (setq step (or step cperl-lineup-step cperl-indent-level))
6417 (or minshift (setq minshift 1))
6418 (while (progn
6419 (beginning-of-line 2)
6420 (and (< (point) end)
6421 (re-search-forward search end t)
6422 (goto-char (match-beginning 0))))
6423 (setq tcol (current-column) seen t)
6424 (if (> tcol col) (setq col tcol)))
6425 (or seen
55497cff 6426 (error "The construction to line up occurred only once"))
4633a7c4
LW
6427 (goto-char beg)
6428 (setq col (+ col minshift))
6429 (if (/= (% col step) 0) (setq step (* step (1+ (/ col step)))))
6430 (while
6431 (progn
6432 (setq e (point))
6433 (skip-chars-backward " \t")
6434 (delete-region (point) e)
6435 (indent-to-column col); (make-string (- col (current-column)) ?\ ))
6436 (beginning-of-line 2)
6437 (and (< (point) end)
6438 (re-search-forward search end t)
6439 (goto-char (match-beginning 0)))))))) ; No body
6440
6441(defun cperl-etags (&optional add all files)
6442 "Run etags with appropriate options for Perl files.
6443If optional argument ALL is `recursive', will process Perl files
6444in subdirectories too."
6445 (interactive)
6446 (let ((cmd "etags")
ebcd4dbc 6447 (args '("-l" "none" "-r" "/\\<\\(package\\|sub\\)[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)[ \\t]*\\(([^()]*)[ \t]*\\)?\\([{#]\\|$\\)\\)/\\4/"))
4633a7c4
LW
6448 res)
6449 (if add (setq args (cons "-a" args)))
6450 (or files (setq files (list buffer-file-name)))
6451 (cond
6452 ((eq all 'recursive)
6453 ;;(error "Not implemented: recursive")
6454 (setq args (append (list "-e"
05bbd9c3 6455 "sub wanted {push @ARGV, $File::Find::name if /\\.[pP][Llm]$/}
4633a7c4
LW
6456 use File::Find;
6457 find(\\&wanted, '.');
6458 exec @ARGV;"
6459 cmd) args)
6460 cmd "perl"))
6461 (all
6462 ;;(error "Not implemented: all")
6463 (setq args (append (list "-e"
6464 "push @ARGV, <*.PL *.pl *.pm>;
6465 exec @ARGV;"
6466 cmd) args)
6467 cmd "perl"))
6468 (t
6469 (setq args (append args files))))
6470 (setq res (apply 'call-process cmd nil nil nil args))
6471 (or (eq res 0)
6472 (message "etags returned \"%s\"" res))))
9ea28adb 6473
6474(defun cperl-toggle-auto-newline ()
6475 "Toggle the state of `cperl-auto-newline'."
6476 (interactive)
6477 (setq cperl-auto-newline (not cperl-auto-newline))
6478 (message "Newlines will %sbe auto-inserted now."
6479 (if cperl-auto-newline "" "not ")))
6480
6481(defun cperl-toggle-abbrev ()
6482 "Toggle the state of automatic keyword expansion in CPerl mode."
6483 (interactive)
6484 (abbrev-mode (if abbrev-mode 0 1))
6485 (message "Perl control structure will %sbe auto-inserted now."
6486 (if abbrev-mode "" "not ")))
6487
6488
6489(defun cperl-toggle-electric ()
6490 "Toggle the state of parentheses doubling in CPerl mode."
6491 (interactive)
6492 (setq cperl-electric-parens (if (cperl-val 'cperl-electric-parens) 'null t))
6493 (message "Parentheses will %sbe auto-doubled now."
6494 (if (cperl-val 'cperl-electric-parens) "" "not ")))
6495
6c72d195
IZ
6496(defun cperl-toggle-autohelp ()
6497 "Toggle the state of automatic help message in CPerl mode.
6498See `cperl-lazy-help-time' too."
6499 (interactive)
6500 (if (fboundp 'run-with-idle-timer)
6501 (progn
6502 (if cperl-lazy-installed
6503 (eval '(cperl-lazy-unstall))
6504 (cperl-lazy-install))
6505 (message "Perl help messages will %sbe automatically shown now."
6506 (if cperl-lazy-installed "" "not ")))
6507 (message "Cannot automatically show Perl help messages - run-with-idle-timer missing.")))
6508
6509(defun cperl-toggle-construct-fix ()
6510 "Toggle whether `indent-region'/`indent-sexp' fix whitespace too."
6511 (interactive)
6512 (setq cperl-indent-region-fix-constructs
4584684c
GS
6513 (if cperl-indent-region-fix-constructs
6514 nil
6515 1))
6c72d195
IZ
6516 (message "indent-region/indent-sexp will %sbe automatically fix whitespace."
6517 (if cperl-indent-region-fix-constructs "" "not ")))
6518
9ea28adb 6519;;;; Tags file creation.
6520
6521(defvar cperl-tmp-buffer " *cperl-tmp*")
6522
6523(defun cperl-setup-tmp-buf ()
6524 (set-buffer (get-buffer-create cperl-tmp-buffer))
6525 (set-syntax-table cperl-mode-syntax-table)
6526 (buffer-disable-undo)
05bbd9c3
IZ
6527 (auto-fill-mode 0)
6528 (if cperl-use-syntax-table-text-property-for-tags
6529 (progn
6530 (make-variable-buffer-local 'parse-sexp-lookup-properties)
6531 ;; Do not introduce variable if not needed, we check it!
6532 (set 'parse-sexp-lookup-properties t))))
9ea28adb 6533
6534(defun cperl-xsub-scan ()
6535 (require 'cl)
499d5216 6536 (require 'imenu)
9ea28adb 6537 (let ((index-alist '())
6538 (prev-pos 0) index index1 name package prefix)
6539 (goto-char (point-min))
3ee700d1
IZ
6540 (if noninteractive
6541 (message "Scanning XSUB for index")
6542 (imenu-progress-message prev-pos 0))
9ea28adb 6543 ;; Search for the function
6544 (progn ;;save-match-data
6545 (while (re-search-forward
6546 "^\\([ \t]*MODULE\\>[^\n]*\\<PACKAGE[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9:]*\\)\\>\\|\\([a-zA-Z_][a-zA-Z_0-9]*\\)(\\|[ \t]*BOOT:\\)"
6547 nil t)
3ee700d1
IZ
6548 (or noninteractive
6549 (imenu-progress-message prev-pos))
9ea28adb 6550 (cond
6551 ((match-beginning 2) ; SECTION
6552 (setq package (buffer-substring (match-beginning 2) (match-end 2)))
6553 (goto-char (match-beginning 0))
6554 (skip-chars-forward " \t")
6555 (forward-char 1)
6556 (if (looking-at "[^\n]*\\<PREFIX[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9]*\\)\\>")
6557 (setq prefix (buffer-substring (match-beginning 1) (match-end 1)))
6558 (setq prefix nil)))
6559 ((not package) nil) ; C language section
6560 ((match-beginning 3) ; XSUB
6561 (goto-char (1+ (match-beginning 3)))
6562 (setq index (imenu-example--name-and-position))
6563 (setq name (buffer-substring (match-beginning 3) (match-end 3)))
6564 (if (and prefix (string-match (concat "^" prefix) name))
6565 (setq name (substring name (length prefix))))
9ea28adb 6566 (cond ((string-match "::" name) nil)
6567 (t
6568 (setq index1 (cons (concat package "::" name) (cdr index)))
6569 (push index1 index-alist)))
6570 (setcar index name)
6571 (push index index-alist))
6572 (t ; BOOT: section
6573 ;; (beginning-of-line)
6574 (setq index (imenu-example--name-and-position))
6575 (setcar index (concat package "::BOOT:"))
6576 (push index index-alist)))))
3ee700d1
IZ
6577 (or noninteractive
6578 (imenu-progress-message prev-pos 100))
9ea28adb 6579 index-alist))
6580
7bcea553
IZ
6581(defvar cperl-unreadable-ok nil)
6582
6583(defun cperl-find-tags (ifile xs topdir)
3ee700d1 6584 (let (ind (b (get-buffer cperl-tmp-buffer)) lst elt pos ret rel
7bcea553 6585 (cperl-pod-here-fontify nil) f file)
9ea28adb 6586 (save-excursion
6587 (if b (set-buffer b)
6588 (cperl-setup-tmp-buf))
6589 (erase-buffer)
7bcea553
IZ
6590 (condition-case err
6591 (setq file (car (insert-file-contents ifile)))
6592 (error (if cperl-unreadable-ok nil
6593 (if (y-or-n-p
6594 (format "File %s unreadable. Continue? " ifile))
6595 (setq cperl-unreadable-ok t)
6596 (error "Aborting: unreadable file %s" ifile)))))
6597 (if (not file)
6598 (message "Unreadable file %s" ifile)
3ee700d1
IZ
6599 (message "Scanning file %s ..." file)
6600 (if (and cperl-use-syntax-table-text-property-for-tags
6601 (not xs))
6602 (condition-case err ; after __END__ may have garbage
7bcea553 6603 (cperl-find-pods-heres nil nil noninteractive)
3ee700d1 6604 (error (message "While scanning for syntax: %s" err))))
9ea28adb 6605 (if xs
6606 (setq lst (cperl-xsub-scan))
6607 (setq ind (imenu-example--create-perl-index))
6608 (setq lst (cdr (assoc "+Unsorted List+..." ind))))
6609 (setq lst
6610 (mapcar
6611 (function
6612 (lambda (elt)
6613 (cond ((string-match "^[_a-zA-Z]" (car elt))
6614 (goto-char (cdr elt))
4584684c 6615 (beginning-of-line) ; pos should be of the start of the line
9ea28adb 6616 (list (car elt)
4584684c
GS
6617 (point)
6618 (1+ (count-lines 1 (point))) ; 1+ since at beg-o-l
9ea28adb 6619 (buffer-substring (progn
7bcea553
IZ
6620 (goto-char (cdr elt))
6621 ;; After name now...
9ea28adb 6622 (or (eolp) (forward-char 1))
6623 (point))
6624 (progn
6625 (beginning-of-line)
6626 (point))))))))
6627 lst))
6628 (erase-buffer)
6629 (while lst
6630 (setq elt (car lst) lst (cdr lst))
6631 (if elt
6632 (progn
6633 (insert (elt elt 3)
6634 127
6635 (if (string-match "^package " (car elt))
6636 (substring (car elt) 8)
6637 (car elt) )
6638 1
4584684c 6639 (number-to-string (elt elt 2)) ; Line
9ea28adb 6640 ","
4584684c 6641 (number-to-string (1- (elt elt 1))) ; Char pos 0-based
9ea28adb 6642 "\n")
6643 (if (and (string-match "^[_a-zA-Z]+::" (car elt))
6644 (string-match "^sub[ \t]+\\([_a-zA-Z]+\\)[^:_a-zA-Z]"
6645 (elt elt 3)))
6646 ;; Need to insert the name without package as well
6647 (setq lst (cons (cons (substring (elt elt 3)
6648 (match-beginning 1)
6649 (match-end 1))
6650 (cdr elt))
6651 lst))))))
6652 (setq pos (point))
6653 (goto-char 1)
3ee700d1
IZ
6654 (setq rel file)
6655 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
6656 (set-text-properties 0 (length rel) nil rel)
6657 (and (equal topdir (substring rel 0 (length topdir)))
6658 (setq rel (substring file (length topdir))))
6659 (insert "\f\n" rel "," (number-to-string (1- pos)) "\n")
9ea28adb 6660 (setq ret (buffer-substring 1 (point-max)))
6661 (erase-buffer)
3ee700d1
IZ
6662 (or noninteractive
6663 (message "Scanning file %s finished" file))
7bcea553 6664 ret))))
9ea28adb 6665
3ee700d1
IZ
6666(defun cperl-add-tags-recurse-noxs ()
6667 "Add to TAGS data for Perl and XSUB files in the current directory and kids.
6668Use as
6669 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
6670 -f cperl-add-tags-recurse
6671"
6672 (cperl-write-tags nil nil t t nil t))
6673
6674(defun cperl-add-tags-recurse ()
6675 "Add to TAGS file data for Perl files in the current directory and kids.
6676Use as
6677 emacs -batch -q -no-site-file -l emacs/cperl-mode.el \
6678 -f cperl-add-tags-recurse
6679"
6680 (cperl-write-tags nil nil t t))
6681
6682(defun cperl-write-tags (&optional file erase recurse dir inbuffer noxs topdir)
9ea28adb 6683 ;; If INBUFFER, do not select buffer, and do not save
6684 ;; If ERASE is `ignore', do not erase, and do not try to delete old info.
499d5216 6685 (require 'etags)
9ea28adb 6686 (if file nil
6687 (setq file (if dir default-directory (buffer-file-name)))
6688 (if (and (not dir) (buffer-modified-p)) (error "Save buffer first!")))
3ee700d1
IZ
6689 (or topdir
6690 (setq topdir default-directory))
9ea28adb 6691 (let ((tags-file-name "TAGS")
6692 (case-fold-search (eq system-type 'emx))
7bcea553 6693 xs rel tm)
9ea28adb 6694 (save-excursion
6695 (cond (inbuffer nil) ; Already there
6696 ((file-exists-p tags-file-name)
4584684c
GS
6697 (if cperl-xemacs-p
6698 (visit-tags-table-buffer)
6699 (visit-tags-table-buffer tags-file-name)))
9ea28adb 6700 (t (set-buffer (find-file-noselect tags-file-name))))
6701 (cond
6702 (dir
6703 (cond ((eq erase 'ignore))
6704 (erase
6705 (erase-buffer)
6706 (setq erase 'ignore)))
6707 (let ((files
7bcea553
IZ
6708 (condition-case err
6709 (directory-files file t
6710 (if recurse nil cperl-scan-files-regexp)
6711 t)
6712 (error
6713 (if cperl-unreadable-ok nil
6714 (if (y-or-n-p
6715 (format "Directory %s unreadable. Continue? " file))
6716 (setq cperl-unreadable-ok t
6717 tm nil) ; Return empty list
6718 (error "Aborting: unreadable directory %s" file)))))))
9ea28adb 6719 (mapcar (function (lambda (file)
6720 (cond
ebcd4dbc
IZ
6721 ((string-match cperl-noscan-files-regexp file)
6722 nil)
9ea28adb 6723 ((not (file-directory-p file))
ebcd4dbc 6724 (if (string-match cperl-scan-files-regexp file)
3ee700d1 6725 (cperl-write-tags file erase recurse nil t noxs topdir)))
9ea28adb 6726 ((not recurse) nil)
3ee700d1 6727 (t (cperl-write-tags file erase recurse t t noxs topdir)))))
9ea28adb 6728 files))
6729 )
6730 (t
6731 (setq xs (string-match "\\.xs$" file))
3ee700d1
IZ
6732 (if (not (and xs noxs))
6733 (progn
6734 (cond ((eq erase 'ignore) (goto-char (point-max)))
6735 (erase (erase-buffer))
6736 (t
6737 (goto-char 1)
4584684c
GS
6738 (setq rel file)
6739 ;; On case-preserving filesystems (EMX on OS/2) case might be encoded in properties
6740 (set-text-properties 0 (length rel) nil rel)
6741 (and (equal topdir (substring rel 0 (length topdir)))
6742 (setq rel (substring file (length topdir))))
6743 (if (search-forward (concat "\f\n" rel ",") nil t)
3ee700d1
IZ
6744 (progn
6745 (search-backward "\f\n")
6746 (delete-region (point)
6747 (save-excursion
6748 (forward-char 1)
6749 (if (search-forward "\f\n"
6750 nil 'toend)
6751 (- (point) 2)
6752 (point-max)))))
6753 (goto-char (point-max)))))
6754 (insert (cperl-find-tags file xs topdir))))))
9ea28adb 6755 (if inbuffer nil ; Delegate to the caller
6756 (save-buffer 0) ; No backup
5f05dabc 6757 (if (fboundp 'initialize-new-tags-table) ; Do we need something special in XEmacs?
6758 (initialize-new-tags-table))))))
9ea28adb 6759
6760(defvar cperl-tags-hier-regexp-list
ebcd4dbc
IZ
6761 (concat
6762 "^\\("
6763 "\\(package\\)\\>"
6764 "\\|"
6765 "sub\\>[^\n]+::"
6766 "\\|"
6767 "[a-zA-Z_][a-zA-Z_0-9:]*(\C-?[^\n]+::" ; XSUB?
6768 "\\|"
6769 "[ \t]*BOOT:\C-?[^\n]+::" ; BOOT section
6770 "\\)"))
9ea28adb 6771
6772(defvar cperl-hierarchy '(() ())
6773 "Global hierarchy of classes")
6774
6775(defun cperl-tags-hier-fill ()
6776 ;; Suppose we are in a tag table cooked by cperl.
6777 (goto-char 1)
6778 (let (type pack name pos line chunk ord cons1 file str info fileind)
6779 (while (re-search-forward cperl-tags-hier-regexp-list nil t)
6780 (setq pos (match-beginning 0)
6781 pack (match-beginning 2))
6782 (beginning-of-line)
ebcd4dbc
IZ
6783 (if (looking-at (concat
6784 "\\([^\n]+\\)"
6785 "\C-?"
6786 "\\([^\n]+\\)"
6787 "\C-a"
6788 "\\([0-9]+\\)"
6789 ","
6790 "\\([0-9]+\\)"))
9ea28adb 6791 (progn
6792 (setq ;;str (buffer-substring (match-beginning 1) (match-end 1))
6793 name (buffer-substring (match-beginning 2) (match-end 2))
6794 ;;pos (buffer-substring (match-beginning 3) (match-end 3))
4584684c 6795 line (buffer-substring (match-beginning 3) (match-end 3))
9ea28adb 6796 ord (if pack 1 0)
9ea28adb 6797 file (file-of-tag)
4584684c
GS
6798 fileind (format "%s:%s" file line)
6799 ;; Moves to beginning of the next line:
6800 info (cperl-etags-snarf-tag file line))
9ea28adb 6801 ;; Move back
6802 (forward-char -1)
6803 ;; Make new member of hierarchy name ==> file ==> pos if needed
6804 (if (setq cons1 (assoc name (nth ord cperl-hierarchy)))
6805 ;; Name known
6806 (setcdr cons1 (cons (cons fileind (vector file info))
6807 (cdr cons1)))
55497cff 6808 ;; First occurrence of the name, start alist
9ea28adb 6809 (setq cons1 (cons name (list (cons fileind (vector file info)))))
6810 (if pack
6811 (setcar (cdr cperl-hierarchy)
6812 (cons cons1 (nth 1 cperl-hierarchy)))
6813 (setcar cperl-hierarchy
6814 (cons cons1 (car cperl-hierarchy)))))))
6815 (end-of-line))))
6816
6817(defun cperl-tags-hier-init (&optional update)
6818 "Show hierarchical menu of classes and methods.
6819Finds info about classes by a scan of loaded TAGS files.
6820Supposes that the TAGS files contain fully qualified function names.
6821One may build such TAGS files from CPerl mode menu."
6822 (interactive)
6823 (require 'etags)
6824 (require 'imenu)
6825 (if (or update (null (nth 2 cperl-hierarchy)))
4584684c 6826 (let (pack name cons1 to l1 l2 l3 l4 b
9ea28adb 6827 (remover (function (lambda (elt) ; (name (file1...) (file2..))
6828 (or (nthcdr 2 elt)
6829 ;; Only in one file
6830 (setcdr elt (cdr (nth 1 elt))))))))
6831 ;; (setq cperl-hierarchy '(() () ())) ; Would write into '() later!
6832 (setq cperl-hierarchy (list l1 l2 l3))
4584684c
GS
6833 (if cperl-xemacs-p ; Not checked
6834 (progn
6835 (or tags-file-name
6836 ;; Does this work in XEmacs?
6837 (call-interactively 'visit-tags-table))
6838 (message "Updating list of classes...")
6839 (set-buffer (get-file-buffer tags-file-name))
6840 (cperl-tags-hier-fill))
6841 (or tags-table-list
6842 (call-interactively 'visit-tags-table))
6843 (mapcar
6844 (function
6845 (lambda (tagsfile)
6846 (message "Updating list of classes... %s" tagsfile)
6847 (set-buffer (get-file-buffer tagsfile))
6848 (cperl-tags-hier-fill)))
6849 tags-table-list)
6850 (message "Updating list of classes... postprocessing..."))
9ea28adb 6851 (mapcar remover (car cperl-hierarchy))
6852 (mapcar remover (nth 1 cperl-hierarchy))
6853 (setq to (list nil (cons "Packages: " (nth 1 cperl-hierarchy))
6854 (cons "Methods: " (car cperl-hierarchy))))
6855 (cperl-tags-treeify to 1)
6856 (setcar (nthcdr 2 cperl-hierarchy)
6857 (cperl-menu-to-keymap (cons '("+++UPDATE+++" . -999) (cdr to))))
6858 (message "Updating list of classes: done, requesting display...")
6859 ;;(cperl-imenu-addback (nth 2 cperl-hierarchy))
6860 ))
6861 (or (nth 2 cperl-hierarchy)
6862 (error "No items found"))
6863 (setq update
6864;;; (imenu-choose-buffer-index "Packages: " (nth 2 cperl-hierarchy))
6865 (if window-system
6866 (x-popup-menu t (nth 2 cperl-hierarchy))
6867 (require 'tmm)
ebcd4dbc 6868 (tmm-prompt (nth 2 cperl-hierarchy))))
9ea28adb 6869 (if (and update (listp update))
6870 (progn (while (cdr update) (setq update (cdr update)))
6871 (setq update (car update)))) ; Get the last from the list
6872 (if (vectorp update)
6873 (progn
6874 (find-file (elt update 0))
4584684c 6875 (cperl-etags-goto-tag-location (elt update 1))))
9ea28adb 6876 (if (eq update -999) (cperl-tags-hier-init t)))
6877
6878(defun cperl-tags-treeify (to level)
6c72d195 6879 ;; cadr of `to' is read-write. On start it is a cons
9ea28adb 6880 (let* ((regexp (concat "^\\(" (mapconcat
6881 'identity
6882 (make-list level "[_a-zA-Z0-9]+")
6883 "::")
6884 "\\)\\(::\\)?"))
6885 (packages (cdr (nth 1 to)))
6886 (methods (cdr (nth 2 to)))
6887 l1 head tail cons1 cons2 ord writeto packs recurse
6888 root-packages root-functions ms many_ms same_name ps
6889 (move-deeper
6890 (function
6891 (lambda (elt)
6892 (cond ((and (string-match regexp (car elt))
6893 (or (eq ord 1) (match-end 2)))
6894 (setq head (substring (car elt) 0 (match-end 1))
6895 tail (if (match-end 2) (substring (car elt)
6896 (match-end 2)))
6897 recurse t)
6898 (if (setq cons1 (assoc head writeto)) nil
6899 ;; Need to init new head
6900 (setcdr writeto (cons (list head (list "Packages: ")
6901 (list "Methods: "))
6902 (cdr writeto)))
6903 (setq cons1 (nth 1 writeto)))
6904 (setq cons2 (nth ord cons1)) ; Either packs or meths
6905 (setcdr cons2 (cons elt (cdr cons2))))
6906 ((eq ord 2)
6907 (setq root-functions (cons elt root-functions)))
6908 (t
6909 (setq root-packages (cons elt root-packages))))))))
6910 (setcdr to l1) ; Init to dynamic space
6911 (setq writeto to)
6912 (setq ord 1)
6913 (mapcar move-deeper packages)
6914 (setq ord 2)
6915 (mapcar move-deeper methods)
6916 (if recurse
6917 (mapcar (function (lambda (elt)
6918 (cperl-tags-treeify elt (1+ level))))
6919 (cdr to)))
05bbd9c3
IZ
6920 ;;Now clean up leaders with one child only
6921 (mapcar (function (lambda (elt)
6922 (if (not (and (listp (cdr elt))
6923 (eq (length elt) 2))) nil
6924 (setcar elt (car (nth 1 elt)))
6925 (setcdr elt (cdr (nth 1 elt))))))
6926 (cdr to))
6927 ;; Sort the roots of subtrees
6928 (if (default-value 'imenu-sort-function)
6929 (setcdr to
6930 (sort (cdr to) (default-value 'imenu-sort-function))))
9ea28adb 6931 ;; Now add back functions removed from display
6932 (mapcar (function (lambda (elt)
6933 (setcdr to (cons elt (cdr to)))))
05bbd9c3
IZ
6934 (if (default-value 'imenu-sort-function)
6935 (nreverse
6936 (sort root-functions (default-value 'imenu-sort-function)))
6937 root-functions))
9ea28adb 6938 ;; Now add back packages removed from display
6939 (mapcar (function (lambda (elt)
6940 (setcdr to (cons (cons (concat "package " (car elt))
6941 (cdr elt))
6942 (cdr to)))))
05bbd9c3
IZ
6943 (if (default-value 'imenu-sort-function)
6944 (nreverse
6945 (sort root-packages (default-value 'imenu-sort-function)))
6946 root-packages))
9ea28adb 6947 ))
6948
6949;;;(x-popup-menu t
6950;;; '(keymap "Name1"
6951;;; ("Ret1" "aa")
6952;;; ("Head1" "ab"
6953;;; keymap "Name2"
6954;;; ("Tail1" "x") ("Tail2" "y"))))
6955
6956(defun cperl-list-fold (list name limit)
6957 (let (list1 list2 elt1 (num 0))
6958 (if (<= (length list) limit) list
6959 (setq list1 nil list2 nil)
6960 (while list
6961 (setq num (1+ num)
6962 elt1 (car list)
6963 list (cdr list))
6964 (if (<= num imenu-max-items)
6965 (setq list2 (cons elt1 list2))
6966 (setq list1 (cons (cons name
6967 (nreverse list2))
6968 list1)
6969 list2 (list elt1)
6970 num 1)))
6971 (nreverse (cons (cons name
6972 (nreverse list2))
6973 list1)))))
6974
6975(defun cperl-menu-to-keymap (menu &optional name)
6976 (let (list)
6977 (cons 'keymap
6978 (mapcar
6979 (function
6980 (lambda (elt)
6981 (cond ((listp (cdr elt))
6982 (setq list (cperl-list-fold
6983 (cdr elt) (car elt) imenu-max-items))
6984 (cons nil
6985 (cons (car elt)
6986 (cperl-menu-to-keymap list))))
6987 (t
ebcd4dbc 6988 (list (cdr elt) (car elt) t))))) ; t is needed in 19.34
9ea28adb 6989 (cperl-list-fold menu "Root" imenu-max-items)))))
499d5216
IZ
6990
6991\f
6992(defvar cperl-bad-style-regexp
6993 (mapconcat 'identity
6994 '("[^-\n\t <>=+!.&|(*/'`\"#^][-=+<>!|&^]" ; char sign
6995 "[-<>=+^&|]+[^- \t\n=+<>~]" ; sign+ char
6996 )
6997 "\\|")
6998 "Finds places such that insertion of a whitespace may help a lot.")
6999
7000(defvar cperl-not-bad-style-regexp
7001 (mapconcat 'identity
7002 '("[^-\t <>=+]\\(--\\|\\+\\+\\)" ; var-- var++
ebcd4dbc
IZ
7003 "[a-zA-Z0-9_][|&][a-zA-Z0-9_$]" ; abc|def abc&def are often used.
7004 "&[(a-zA-Z0-9_$]" ; &subroutine &(var->field)
499d5216 7005 "<\\$?\\sw+\\(\\.\\sw+\\)?>" ; <IN> <stdin.h>
20675f5d 7006 "-[a-zA-Z][ \t]+[_$\"'`a-zA-Z]" ; -f file, -t STDIN
499d5216
IZ
7007 "-[0-9]" ; -5
7008 "\\+\\+" ; ++var
7009 "--" ; --var
7010 ".->" ; a->b
7011 "->" ; a SPACE ->b
7012 "\\[-" ; a[-1]
20675f5d 7013 "\\\\[&$@*\\\\]" ; \&func
499d5216 7014 "^=" ; =head
20675f5d
IZ
7015 "\\$." ; $|
7016 "<<[a-zA-Z_'\"`]" ; <<FOO, <<'FOO'
499d5216
IZ
7017 "||"
7018 "&&"
7019 "[CBIXSLFZ]<\\(\\sw\\|\\s \\|\\s_\\|[\n]\\)*>" ; C<code like text>
ebcd4dbc 7020 "-[a-zA-Z_0-9]+[ \t]*=>" ; -option => value
499d5216
IZ
7021 ;; Unaddressed trouble spots: = -abc, f(56, -abc) --- specialcased below
7022 ;;"[*/+-|&<.]+="
7023 )
7024 "\\|")
7025 "If matches at the start of match found by `my-bad-c-style-regexp',
7026insertion of a whitespace will not help.")
7027
7028(defvar found-bad)
7029
7030(defun cperl-find-bad-style ()
7031 "Find places in the buffer where insertion of a whitespace may help.
7032Prompts user for insertion of spaces.
7033Currently it is tuned to C and Perl syntax."
7034 (interactive)
7035 (let (found-bad (p (point)))
7036 (setq last-nonmenu-event 13) ; To disable popup
7037 (beginning-of-buffer)
7038 (map-y-or-n-p "Insert space here? "
7039 (function (lambda (arg) (insert " ")))
7040 'cperl-next-bad-style
7041 '("location" "locations" "insert a space into")
7042 '((?\C-r (lambda (arg)
7043 (let ((buffer-quit-function
7044 'exit-recursive-edit))
7045 (message "Exit with Esc Esc")
7046 (recursive-edit)
7047 t)) ; Consider acted upon
7048 "edit, exit with Esc Esc")
7049 (?e (lambda (arg)
7050 (let ((buffer-quit-function
7051 'exit-recursive-edit))
7052 (message "Exit with Esc Esc")
7053 (recursive-edit)
7054 t)) ; Consider acted upon
7055 "edit, exit with Esc Esc"))
7056 t)
7057 (if found-bad (goto-char found-bad)
7058 (goto-char p)
7059 (message "No appropriate place found"))))
7060
7061(defun cperl-next-bad-style ()
7062 (let (p (not-found t) (point (point)) found)
7063 (while (and not-found
7064 (re-search-forward cperl-bad-style-regexp nil 'to-end))
7065 (setq p (point))
7066 (goto-char (match-beginning 0))
7067 (if (or
7068 (looking-at cperl-not-bad-style-regexp)
7069 ;; Check for a < -b and friends
7070 (and (eq (following-char) ?\-)
7071 (save-excursion
7072 (skip-chars-backward " \t\n")
7073 (memq (preceding-char) '(?\= ?\> ?\< ?\, ?\(, ?\[, ?\{))))
7074 ;; Now check for syntax type
7075 (save-match-data
7076 (setq found (point))
7077 (beginning-of-defun)
7078 (let ((pps (parse-partial-sexp (point) found)))
7079 (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))
7080 (goto-char (match-end 0))
7081 (goto-char (1- p))
7082 (setq not-found nil
7083 found-bad found)))
7084 (not not-found)))
7085
55497cff 7086;;; Getting help
7087(defvar cperl-have-help-regexp
7088 ;;(concat "\\("
7089 (mapconcat
7090 'identity
5f05dabc 7091 '("[$@%*&][0-9a-zA-Z_:]+\\([ \t]*[[{]\\)?" ; Usual variable
55497cff 7092 "[$@]\\^[a-zA-Z]" ; Special variable
7093 "[$@][^ \n\t]" ; Special variable
7094 "-[a-zA-Z]" ; File test
7095 "\\\\[a-zA-Z0]" ; Special chars
5f05dabc 7096 "^=[a-z][a-zA-Z0-9_]*" ; Pod sections
55497cff 7097 "[-!&*+,-./<=>?\\\\^|~]+" ; Operator
7098 "[a-zA-Z_0-9:]+" ; symbol or number
7099 "x="
7100 "#!"
7101 )
7102 ;;"\\)\\|\\("
7103 "\\|"
7104 )
7105 ;;"\\)"
7106 ;;)
7107 "Matches places in the buffer we can find help for.")
7108
7109(defvar cperl-message-on-help-error t)
5f05dabc 7110(defvar cperl-help-from-timer nil)
7111
7112(defun cperl-word-at-point-hard ()
7113 ;; Does not save-excursion
7114 ;; Get to the something meaningful
7115 (or (eobp) (eolp) (forward-char 1))
7116 (re-search-backward "[-a-zA-Z0-9_:!&*+,-./<=>?\\\\^|~$%@]"
7117 (save-excursion (beginning-of-line) (point))
7118 'to-beg)
7119 ;; (cond
7120 ;; ((or (eobp) (looking-at "[][ \t\n{}();,]")) ; Not at a symbol
7121 ;; (skip-chars-backward " \n\t\r({[]});,")
7122 ;; (or (bobp) (backward-char 1))))
7123 ;; Try to backtrace
7124 (cond
7125 ((looking-at "[a-zA-Z0-9_:]") ; symbol
ebcd4dbc 7126 (skip-chars-backward "a-zA-Z0-9_:")
5f05dabc 7127 (cond
7128 ((and (eq (preceding-char) ?^) ; $^I
7129 (eq (char-after (- (point) 2)) ?\$))
7130 (forward-char -2))
7131 ((memq (preceding-char) (append "*$@%&\\" nil)) ; *glob
7132 (forward-char -1))
7133 ((and (eq (preceding-char) ?\=)
7134 (eq (current-column) 1))
7135 (forward-char -1))) ; =head1
7136 (if (and (eq (preceding-char) ?\<)
7137 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <FH>
7138 (forward-char -1)))
7139 ((and (looking-at "=") (eq (preceding-char) ?x)) ; x=
7140 (forward-char -1))
7141 ((and (looking-at "\\^") (eq (preceding-char) ?\$)) ; $^I
7142 (forward-char -1))
7143 ((looking-at "[-!&*+,-./<=>?\\\\^|~]")
ebcd4dbc 7144 (skip-chars-backward "-!&*+,-./<=>?\\\\^|~")
5f05dabc 7145 (cond
7146 ((and (eq (preceding-char) ?\$)
7147 (not (eq (char-after (- (point) 2)) ?\$))) ; $-
7148 (forward-char -1))
7149 ((and (eq (following-char) ?\>)
7150 (string-match "[a-zA-Z0-9_]" (char-to-string (preceding-char)))
7151 (save-excursion
7152 (forward-sexp -1)
7153 (and (eq (preceding-char) ?\<)
7154 (looking-at "\\$?[a-zA-Z0-9_:]+>")))) ; <FH>
7155 (search-backward "<"))))
7156 ((and (eq (following-char) ?\$)
7157 (eq (preceding-char) ?\<)
7158 (looking-at "\\$?[a-zA-Z0-9_:]+>")) ; <$fh>
7159 (forward-char -1)))
7160 (if (looking-at cperl-have-help-regexp)
7161 (buffer-substring (match-beginning 0) (match-end 0))))
55497cff 7162
7163(defun cperl-get-help ()
7164 "Get one-line docs on the symbol at the point.
7165The data for these docs is a little bit obsolete and may be in fact longer
6c72d195 7166than a line. Your contribution to update/shorten it is appreciated."
55497cff 7167 (interactive)
ebcd4dbc
IZ
7168 (save-match-data ; May be called "inside" query-replace
7169 (save-excursion
7170 (let ((word (cperl-word-at-point-hard)))
7171 (if word
7172 (if (and cperl-help-from-timer ; Bail out if not in mainland
7173 (not (string-match "^#!\\|\\\\\\|^=" word)) ; Show help even in comments/strings.
7174 (or (memq (get-text-property (point) 'face)
7175 '(font-lock-comment-face font-lock-string-face))
7176 (memq (get-text-property (point) 'syntax-type)
7177 '(pod here-doc format))))
7178 nil
7179 (cperl-describe-perl-symbol word))
7180 (if cperl-message-on-help-error
7181 (message "Nothing found for %s..."
7182 (buffer-substring (point) (min (+ 5 (point)) (point-max))))))))))
55497cff 7183
7184;;; Stolen from perl-descr.el by Johan Vromans:
7185
7186(defvar cperl-doc-buffer " *perl-doc*"
7187 "Where the documentation can be found.")
7188
7189(defun cperl-describe-perl-symbol (val)
7190 "Display the documentation of symbol at point, a Perl operator."
5f05dabc 7191 (let ((enable-recursive-minibuffers t)
55497cff 7192 args-file regexp)
55497cff 7193 (cond
7194 ((string-match "^[&*][a-zA-Z_]" val)
7195 (setq val (concat (substring val 0 1) "NAME")))
5f05dabc 7196 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*\\[" val)
7197 (setq val (concat "@" (substring val 1 (match-end 1)))))
7198 ((string-match "^[$@]\\([a-zA-Z_:0-9]+\\)[ \t]*{" val)
7199 (setq val (concat "%" (substring val 1 (match-end 1)))))
7200 ((and (string= val "x") (string-match "^x=" val))
55497cff 7201 (setq val "x="))
7202 ((string-match "^\\$[\C-a-\C-z]" val)
7203 (setq val (concat "$^" (char-to-string (+ ?A -1 (aref val 1))))))
5f05dabc 7204 ((string-match "^CORE::" val)
7205 (setq val "CORE::"))
7206 ((string-match "^SUPER::" val)
7207 (setq val "SUPER::"))
7208 ((and (string= "<" val) (string-match "^<\\$?[a-zA-Z0-9_:]+>" val))
55497cff 7209 (setq val "<NAME>")))
5f05dabc 7210 (setq regexp (concat "^"
7211 "\\([^a-zA-Z0-9_:]+[ \t]+\\)?"
55497cff 7212 (regexp-quote val)
7213 "\\([ \t([/]\\|$\\)"))
7214
7215 ;; get the buffer with the documentation text
7216 (cperl-switch-to-doc-buffer)
7217
7218 ;; lookup in the doc
7219 (goto-char (point-min))
7220 (let ((case-fold-search nil))
7221 (list
7222 (if (re-search-forward regexp (point-max) t)
7223 (save-excursion
7224 (beginning-of-line 1)
7225 (let ((lnstart (point)))
7226 (end-of-line)
7227 (message "%s" (buffer-substring lnstart (point)))))
7228 (if cperl-message-on-help-error
7229 (message "No definition for %s" val)))))))
7230
7231(defvar cperl-short-docs "Ignore my value"
5f05dabc 7232 ;; Perl4 version was written by Johan Vromans (jvromans@squirrel.nl)
55497cff 7233 "# based on '@(#)@ perl-descr.el 1.9 - describe-perl-symbol' [Perl 5]
5f05dabc 7234! ... Logical negation.
7235... != ... Numeric inequality.
7236... !~ ... Search pattern, substitution, or translation (negated).
6c72d195 7237$! In numeric context: errno. In a string context: error string.
55497cff 7238$\" The separator which joins elements of arrays interpolated in strings.
6c72d195
IZ
7239$# The output format for printed numbers. Initial value is %.15g or close.
7240$$ Process number of this script. Changes in the fork()ed child process.
55497cff 7241$% The current page number of the currently selected output channel.
7242
7243 The following variables are always local to the current block:
7244
7245$1 Match of the 1st set of parentheses in the last match (auto-local).
7246$2 Match of the 2nd set of parentheses in the last match (auto-local).
7247$3 Match of the 3rd set of parentheses in the last match (auto-local).
7248$4 Match of the 4th set of parentheses in the last match (auto-local).
7249$5 Match of the 5th set of parentheses in the last match (auto-local).
7250$6 Match of the 6th set of parentheses in the last match (auto-local).
7251$7 Match of the 7th set of parentheses in the last match (auto-local).
7252$8 Match of the 8th set of parentheses in the last match (auto-local).
7253$9 Match of the 9th set of parentheses in the last match (auto-local).
7254$& The string matched by the last pattern match (auto-local).
7255$' The string after what was matched by the last match (auto-local).
7256$` The string before what was matched by the last match (auto-local).
7257
7258$( The real gid of this process.
7259$) The effective gid of this process.
7260$* Deprecated: Set to 1 to do multiline matching within a string.
7261$+ The last bracket matched by the last search pattern.
7262$, The output field separator for the print operator.
7263$- The number of lines left on the page.
7264$. The current input line number of the last filehandle that was read.
7265$/ The input record separator, newline by default.
6c72d195 7266$0 Name of the file containing the perl script being executed. May be set.
5f05dabc 7267$: String may be broken after these characters to fill ^-lines in a format.
6c72d195 7268$; Subscript separator for multi-dim array emulation. Default \"\\034\".
55497cff 7269$< The real uid of this process.
6c72d195 7270$= The page length of the current output channel. Default is 60 lines.
55497cff 7271$> The effective uid of this process.
7272$? The status returned by the last ``, pipe close or `system'.
7273$@ The perl error message from the last eval or do @var{EXPR} command.
7274$ARGV The name of the current file used with <> .
7275$[ Deprecated: The index of the first element/char in an array/string.
7276$\\ The output record separator for the print operator.
7277$] The perl version string as displayed with perl -v.
7278$^ The name of the current top-of-page format.
7279$^A The current value of the write() accumulator for format() lines.
7280$^D The value of the perl debug (-D) flags.
7281$^E Information about the last system error other than that provided by $!.
7282$^F The highest system file descriptor, ordinarily 2.
7283$^H The current set of syntax checks enabled by `use strict'.
7284$^I The value of the in-place edit extension (perl -i option).
6c72d195 7285$^L What formats output to perform a formfeed. Default is \f.
20675f5d 7286$^M A buffer for emergency memory allocation when running out of memory.
55497cff 7287$^O The operating system name under which this copy of Perl was built.
7288$^P Internal debugging flag.
6c72d195 7289$^T The time the script was started. Used by -A/-M/-C file tests.
55497cff 7290$^W True if warnings are requested (perl -w flag).
7291$^X The name under which perl was invoked (argv[0] in C-speech).
7292$_ The default input and pattern-searching space.
6c72d195 7293$| Auto-flush after write/print on current output channel? Default 0.
55497cff 7294$~ The name of the current report format.
5f05dabc 7295... % ... Modulo division.
7296... %= ... Modulo division assignment.
55497cff 7297%ENV Contains the current environment.
7298%INC List of files that have been require-d or do-ne.
7299%SIG Used to set signal handlers for various signals.
5f05dabc 7300... & ... Bitwise and.
7301... && ... Logical and.
7302... &&= ... Logical and assignment.
7303... &= ... Bitwise and assignment.
7304... * ... Multiplication.
7305... ** ... Exponentiation.
6c72d195
IZ
7306*NAME Glob: all objects refered by NAME. *NAM1 = *NAM2 aliases NAM1 to NAM2.
7307&NAME(arg0, ...) Subroutine call. Arguments go to @_.
5f05dabc 7308... + ... Addition. +EXPR Makes EXPR into scalar context.
7309++ Auto-increment (magical on strings). ++EXPR EXPR++
7310... += ... Addition assignment.
55497cff 7311, Comma operator.
5f05dabc 7312... - ... Subtraction.
7313-- Auto-decrement (NOT magical on strings). --EXPR EXPR--
7314... -= ... Subtraction assignment.
55497cff 7315-A Access time in days since script started.
7316-B File is a non-text (binary) file.
7317-C Inode change time in days since script started.
7318-M Age in days since script started.
7319-O File is owned by real uid.
7320-R File is readable by real uid.
7321-S File is a socket .
7322-T File is a text file.
7323-W File is writable by real uid.
7324-X File is executable by real uid.
7325-b File is a block special file.
7326-c File is a character special file.
7327-d File is a directory.
7328-e File exists .
7329-f File is a plain file.
7330-g File has setgid bit set.
7331-k File has sticky bit set.
7332-l File is a symbolic link.
7333-o File is owned by effective uid.
7334-p File is a named pipe (FIFO).
7335-r File is readable by effective uid.
7336-s File has non-zero size.
7337-t Tests if filehandle (STDIN by default) is opened to a tty.
7338-u File has setuid bit set.
7339-w File is writable by effective uid.
7340-x File is executable by effective uid.
7341-z File has zero size.
7342. Concatenate strings.
7343.. Alternation, also range operator.
7344.= Concatenate assignment strings
5f05dabc 7345... / ... Division. /PATTERN/ioxsmg Pattern match
7346... /= ... Division assignment.
55497cff 7347/PATTERN/ioxsmg Pattern match.
5f05dabc 7348... < ... Numeric less than. <pattern> Glob. See <NAME>, <> as well.
6c72d195
IZ
7349<NAME> Reads line from filehandle NAME (a bareword or dollar-bareword).
7350<pattern> Glob (Unless pattern is bareword/dollar-bareword - see <NAME>).
55497cff 7351<> Reads line from union of files in @ARGV (= command line) and STDIN.
5f05dabc 7352... << ... Bitwise shift left. << start of HERE-DOCUMENT.
7353... <= ... Numeric less than or equal to.
7354... <=> ... Numeric compare.
7355... = ... Assignment.
7356... == ... Numeric equality.
7357... =~ ... Search pattern, substitution, or translation
7358... > ... Numeric greater than.
7359... >= ... Numeric greater than or equal to.
7360... >> ... Bitwise shift right.
7361... >>= ... Bitwise shift right assignment.
7362... ? ... : ... Condition=if-then-else operator. ?PAT? One-time pattern match.
7363?PATTERN? One-time pattern match.
55497cff 7364@ARGV Command line arguments (not including the command name - see $0).
7365@INC List of places to look for perl scripts during do/include/use.
91e74348 7366@_ Parameter array for subroutines. Also used by split unless in list context.
ebcd4dbc 7367\\ Creates reference to what follows, like \$var, or quotes non-\w in strings.
55497cff 7368\\0 Octal char, e.g. \\033.
6c72d195
IZ
7369\\E Case modification terminator. See \\Q, \\L, and \\U.
7370\\L Lowercase until \\E . See also \l, lc.
7371\\U Upcase until \\E . See also \u, uc.
7372\\Q Quote metacharacters until \\E . See also quotemeta.
55497cff 7373\\a Alarm character (octal 007).
7374\\b Backspace character (octal 010).
7375\\c Control character, e.g. \\c[ .
7376\\e Escape character (octal 033).
7377\\f Formfeed character (octal 014).
6c72d195 7378\\l Lowercase the next character. See also \\L and \\u, lcfirst.
ebcd4dbc
IZ
7379\\n Newline character (octal 012 on most systems).
7380\\r Return character (octal 015 on most systems).
55497cff 7381\\t Tab character (octal 011).
6c72d195 7382\\u Upcase the next character. See also \\U and \\l, ucfirst.
55497cff 7383\\x Hex character, e.g. \\x1b.
ebcd4dbc 7384... ^ ... Bitwise exclusive or.
5f05dabc 7385__END__ Ends program source.
7386__DATA__ Ends program source.
55497cff 7387__FILE__ Current (source) filename.
7388__LINE__ Current line in current source.
ebcd4dbc 7389__PACKAGE__ Current package.
6c72d195 7390ARGV Default multi-file input filehandle. <ARGV> is a synonym for <>.
55497cff 7391ARGVOUT Output filehandle with -i flag.
5f05dabc 7392BEGIN { ... } Immediately executed (during compilation) piece of code.
7393END { ... } Pseudo-subroutine executed after the script finishes.
7bcea553
IZ
7394CHECK { ... } Pseudo-subroutine executed after the script is compiled.
7395INIT { ... } Pseudo-subroutine executed before the script starts running.
55497cff 7396DATA Input filehandle for what follows after __END__ or __DATA__.
7397accept(NEWSOCKET,GENERICSOCKET)
7398alarm(SECONDS)
7399atan2(X,Y)
7400bind(SOCKET,NAME)
7401binmode(FILEHANDLE)
7402caller[(LEVEL)]
7403chdir(EXPR)
7404chmod(LIST)
7405chop[(LIST|VAR)]
7406chown(LIST)
7407chroot(FILENAME)
7408close(FILEHANDLE)
7409closedir(DIRHANDLE)
5f05dabc 7410... cmp ... String compare.
55497cff 7411connect(SOCKET,NAME)
6c72d195 7412continue of { block } continue { block }. Is executed after `next' or at end.
55497cff 7413cos(EXPR)
7414crypt(PLAINTEXT,SALT)
5f05dabc 7415dbmclose(%HASH)
7416dbmopen(%HASH,DBNAME,MODE)
55497cff 7417defined(EXPR)
5f05dabc 7418delete($HASH{KEY})
55497cff 7419die(LIST)
7420do { ... }|SUBR while|until EXPR executes at least once
ebcd4dbc 7421do(EXPR|SUBR([LIST])) (with while|until executes at least once)
55497cff 7422dump LABEL
5f05dabc 7423each(%HASH)
55497cff 7424endgrent
7425endhostent
7426endnetent
7427endprotoent
7428endpwent
7429endservent
7430eof[([FILEHANDLE])]
5f05dabc 7431... eq ... String equality.
55497cff 7432eval(EXPR) or eval { BLOCK }
7433exec(LIST)
7434exit(EXPR)
7435exp(EXPR)
7436fcntl(FILEHANDLE,FUNCTION,SCALAR)
7437fileno(FILEHANDLE)
7438flock(FILEHANDLE,OPERATION)
7439for (EXPR;EXPR;EXPR) { ... }
7440foreach [VAR] (@ARRAY) { ... }
7441fork
5f05dabc 7442... ge ... String greater than or equal.
55497cff 7443getc[(FILEHANDLE)]
7444getgrent
7445getgrgid(GID)
7446getgrnam(NAME)
7447gethostbyaddr(ADDR,ADDRTYPE)
7448gethostbyname(NAME)
7449gethostent
7450getlogin
7451getnetbyaddr(ADDR,ADDRTYPE)
7452getnetbyname(NAME)
7453getnetent
7454getpeername(SOCKET)
7455getpgrp(PID)
7456getppid
7457getpriority(WHICH,WHO)
7458getprotobyname(NAME)
7459getprotobynumber(NUMBER)
7460getprotoent
7461getpwent
7462getpwnam(NAME)
7463getpwuid(UID)
7464getservbyname(NAME,PROTO)
7465getservbyport(PORT,PROTO)
7466getservent
7467getsockname(SOCKET)
7468getsockopt(SOCKET,LEVEL,OPTNAME)
7469gmtime(EXPR)
7470goto LABEL
5f05dabc 7471... gt ... String greater than.
55497cff 7472hex(EXPR)
7473if (EXPR) { ... } [ elsif (EXPR) { ... } ... ] [ else { ... } ] or EXPR if EXPR
7474index(STR,SUBSTR[,OFFSET])
7475int(EXPR)
7476ioctl(FILEHANDLE,FUNCTION,SCALAR)
7477join(EXPR,LIST)
5f05dabc 7478keys(%HASH)
55497cff 7479kill(LIST)
7480last [LABEL]
5f05dabc 7481... le ... String less than or equal.
55497cff 7482length(EXPR)
7483link(OLDFILE,NEWFILE)
7484listen(SOCKET,QUEUESIZE)
7485local(LIST)
7486localtime(EXPR)
7487log(EXPR)
7488lstat(EXPR|FILEHANDLE|VAR)
5f05dabc 7489... lt ... String less than.
55497cff 7490m/PATTERN/iogsmx
7491mkdir(FILENAME,MODE)
7492msgctl(ID,CMD,ARG)
7493msgget(KEY,FLAGS)
7494msgrcv(ID,VAR,SIZE,TYPE.FLAGS)
7495msgsnd(ID,MSG,FLAGS)
7496my VAR or my (VAR1,...) Introduces a lexical variable ($VAR, @ARR, or %HASH).
7bcea553 7497our VAR or our (VAR1,...) Lexically enable a global variable ($V, @A, or %H).
5f05dabc 7498... ne ... String inequality.
55497cff 7499next [LABEL]
7500oct(EXPR)
7501open(FILEHANDLE[,EXPR])
7502opendir(DIRHANDLE,EXPR)
ebcd4dbc 7503ord(EXPR) ASCII value of the first char of the string.
55497cff 7504pack(TEMPLATE,LIST)
5f05dabc 7505package NAME Introduces package context.
ebcd4dbc 7506pipe(READHANDLE,WRITEHANDLE) Create a pair of filehandles on ends of a pipe.
55497cff 7507pop(ARRAY)
7508print [FILEHANDLE] [(LIST)]
7509printf [FILEHANDLE] (FORMAT,LIST)
7510push(ARRAY,LIST)
7511q/STRING/ Synonym for 'STRING'
7512qq/STRING/ Synonym for \"STRING\"
7513qx/STRING/ Synonym for `STRING`
7514rand[(EXPR)]
7515read(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7516readdir(DIRHANDLE)
7517readlink(EXPR)
7518recv(SOCKET,SCALAR,LEN,FLAGS)
7519redo [LABEL]
7520rename(OLDNAME,NEWNAME)
7521require [FILENAME | PERL_VERSION]
7522reset[(EXPR)]
7523return(LIST)
7524reverse(LIST)
7525rewinddir(DIRHANDLE)
7526rindex(STR,SUBSTR[,OFFSET])
7527rmdir(FILENAME)
7528s/PATTERN/REPLACEMENT/gieoxsm
7529scalar(EXPR)
7530seek(FILEHANDLE,POSITION,WHENCE)
7531seekdir(DIRHANDLE,POS)
7532select(FILEHANDLE | RBITS,WBITS,EBITS,TIMEOUT)
7533semctl(ID,SEMNUM,CMD,ARG)
7534semget(KEY,NSEMS,SIZE,FLAGS)
7535semop(KEY,...)
7536send(SOCKET,MSG,FLAGS[,TO])
7537setgrent
7538sethostent(STAYOPEN)
7539setnetent(STAYOPEN)
7540setpgrp(PID,PGRP)
7541setpriority(WHICH,WHO,PRIORITY)
7542setprotoent(STAYOPEN)
7543setpwent
7544setservent(STAYOPEN)
7545setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)
7546shift[(ARRAY)]
7547shmctl(ID,CMD,ARG)
7548shmget(KEY,SIZE,FLAGS)
7549shmread(ID,VAR,POS,SIZE)
7550shmwrite(ID,STRING,POS,SIZE)
7551shutdown(SOCKET,HOW)
7552sin(EXPR)
7553sleep[(EXPR)]
7554socket(SOCKET,DOMAIN,TYPE,PROTOCOL)
7555socketpair(SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL)
7556sort [SUBROUTINE] (LIST)
7557splice(ARRAY,OFFSET[,LENGTH[,LIST]])
7558split[(/PATTERN/[,EXPR[,LIMIT]])]
7559sprintf(FORMAT,LIST)
7560sqrt(EXPR)
7561srand(EXPR)
7562stat(EXPR|FILEHANDLE|VAR)
7563study[(SCALAR)]
5f05dabc 7564sub [NAME [(format)]] { BODY } sub NAME [(format)]; sub [(format)] {...}
55497cff 7565substr(EXPR,OFFSET[,LEN])
7566symlink(OLDFILE,NEWFILE)
7567syscall(LIST)
7568sysread(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7569system(LIST)
7570syswrite(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
7571tell[(FILEHANDLE)]
7572telldir(DIRHANDLE)
7573time
7574times
7575tr/SEARCHLIST/REPLACEMENTLIST/cds
7576truncate(FILE|EXPR,LENGTH)
7577umask[(EXPR)]
7578undef[(EXPR)]
7579unless (EXPR) { ... } [ else { ... } ] or EXPR unless EXPR
7580unlink(LIST)
7581unpack(TEMPLATE,EXPR)
7582unshift(ARRAY,LIST)
5f05dabc 7583until (EXPR) { ... } EXPR until EXPR
55497cff 7584utime(LIST)
5f05dabc 7585values(%HASH)
55497cff 7586vec(EXPR,OFFSET,BITS)
7587wait
7588waitpid(PID,FLAGS)
ebcd4dbc 7589wantarray Returns true if the sub/eval is called in list context.
55497cff 7590warn(LIST)
5f05dabc 7591while (EXPR) { ... } EXPR while EXPR
55497cff 7592write[(EXPR|FILEHANDLE)]
5f05dabc 7593... x ... Repeat string or array.
7594x= ... Repetition assignment.
55497cff 7595y/SEARCHLIST/REPLACEMENTLIST/
5f05dabc 7596... | ... Bitwise or.
7597... || ... Logical or.
7598~ ... Unary bitwise complement.
6c72d195 7599#! OS interpreter indicator. If contains `perl', used for options, and -x.
5f05dabc 7600AUTOLOAD {...} Shorthand for `sub AUTOLOAD {...}'.
7601CORE:: Prefix to access builtin function if imported sub obscures it.
7602SUPER:: Prefix to lookup for a method in @ISA classes.
7603DESTROY Shorthand for `sub DESTROY {...}'.
7604... EQ ... Obsolete synonym of `eq'.
7605... GE ... Obsolete synonym of `ge'.
7606... GT ... Obsolete synonym of `gt'.
7607... LE ... Obsolete synonym of `le'.
7608... LT ... Obsolete synonym of `lt'.
7609... NE ... Obsolete synonym of `ne'.
7610abs [ EXPR ] absolute value
7611... and ... Low-precedence synonym for &&.
7612bless REFERENCE [, PACKAGE] Makes reference into an object of a package.
6c72d195 7613chomp [LIST] Strips $/ off LIST/$_. Returns count. Special if $/ eq ''!
ebcd4dbc 7614chr Converts a number to char with the same ordinal.
5f05dabc 7615else Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
7616elsif Part of if/unless {BLOCK} elsif {BLOCK} else {BLOCK}.
7617exists $HASH{KEY} True if the key exists.
6c72d195 7618format [NAME] = Start of output format. Ended by a single dot (.) on a line.
ebcd4dbc 7619formline PICTURE, LIST Backdoor into \"format\" processing.
5f05dabc 7620glob EXPR Synonym of <EXPR>.
7621lc [ EXPR ] Returns lowercased EXPR.
7622lcfirst [ EXPR ] Returns EXPR with lower-cased first letter.
6c72d195 7623grep EXPR,LIST or grep {BLOCK} LIST Filters LIST via EXPR/BLOCK.
ebcd4dbc 7624map EXPR, LIST or map {BLOCK} LIST Applies EXPR/BLOCK to elts of LIST.
6c72d195 7625no PACKAGE [SYMBOL1, ...] Partial reverse for `use'. Runs `unimport' method.
ebcd4dbc 7626not ... Low-precedence synonym for ! - negation.
5f05dabc 7627... or ... Low-precedence synonym for ||.
7628pos STRING Set/Get end-position of the last match over this string, see \\G.
ebcd4dbc
IZ
7629quotemeta [ EXPR ] Quote regexp metacharacters.
7630qw/WORD1 .../ Synonym of split('', 'WORD1 ...')
5f05dabc 7631readline FH Synonym of <FH>.
7632readpipe CMD Synonym of `CMD`.
7633ref [ EXPR ] Type of EXPR when dereferenced.
ebcd4dbc
IZ
7634sysopen FH, FILENAME, MODE [, PERM] (MODE is numeric, see Fcntl.)
7635tie VAR, PACKAGE, LIST Hide an object behind a simple Perl variable.
7636tied Returns internal object for a tied data.
5f05dabc 7637uc [ EXPR ] Returns upcased EXPR.
7638ucfirst [ EXPR ] Returns EXPR with upcased first letter.
ebcd4dbc 7639untie VAR Unlink an object from a simple Perl variable.
5f05dabc 7640use PACKAGE [SYMBOL1, ...] Compile-time `require' with consequent `import'.
7641... xor ... Low-precedence synonym for exclusive or.
7642prototype \&SUB Returns prototype of the function given a reference.
7643=head1 Top-level heading.
7644=head2 Second-level heading.
7645=head3 Third-level heading (is there such?).
7646=over [ NUMBER ] Start list.
7647=item [ TITLE ] Start new item in the list.
7648=back End list.
7649=cut Switch from POD to Perl.
7650=pod Switch from Perl to POD.
55497cff 7651")
7652
7653(defun cperl-switch-to-doc-buffer ()
7654 "Go to the perl documentation buffer and insert the documentation."
7655 (interactive)
7656 (let ((buf (get-buffer-create cperl-doc-buffer)))
7657 (if (interactive-p)
7658 (switch-to-buffer-other-window buf)
7659 (set-buffer buf))
7660 (if (= (buffer-size) 0)
7661 (progn
7662 (insert (documentation-property 'cperl-short-docs
7663 'variable-documentation))
7664 (setq buffer-read-only t)))))
7665
7bcea553 7666(defun cperl-beautify-regexp-piece (b e embed level)
ebcd4dbc
IZ
7667 ;; b is before the starting delimiter, e before the ending
7668 ;; e should be a marker, may be changed, but remains "correct".
7bcea553
IZ
7669 ;; EMBED is nil iff we process the whole REx.
7670 ;; The REx is guarantied to have //x
7671 ;; LEVEL shows how many levels deep to go
7672 ;; position at enter and at leave is not defined
7673 (let (s c tmp (m (make-marker)) (m1 (make-marker)) c1 spaces inline code pos)
ebcd4dbc
IZ
7674 (if (not embed)
7675 (goto-char (1+ b))
7676 (goto-char b)
7bcea553 7677 (cond ((looking-at "(\\?\\\\#") ; (?#) wrongly commented when //x-ing
ebcd4dbc
IZ
7678 (forward-char 2)
7679 (delete-char 1)
7680 (forward-char 1))
7681 ((looking-at "(\\?[^a-zA-Z]")
7682 (forward-char 3))
7683 ((looking-at "(\\?") ; (?i)
7684 (forward-char 2))
7685 (t
7686 (forward-char 1))))
05bbd9c3 7687 (setq c (if embed (current-indentation) (1- (current-column)))
ebcd4dbc
IZ
7688 c1 (+ c (or cperl-regexp-indent-step cperl-indent-level)))
7689 (or (looking-at "[ \t]*[\n#]")
7690 (progn
7691 (insert "\n")))
7692 (goto-char e)
7693 (beginning-of-line)
7694 (if (re-search-forward "[^ \t]" e t)
7bcea553 7695 (progn ; Something before the ending delimiter
ebcd4dbc 7696 (goto-char e)
7bcea553 7697 (delete-horizontal-space)
ebcd4dbc
IZ
7698 (insert "\n")
7699 (indent-to-column c)
7700 (set-marker e (point))))
7701 (goto-char b)
7702 (end-of-line 2)
7703 (while (< (point) (marker-position e))
7704 (beginning-of-line)
7705 (setq s (point)
7706 inline t)
7707 (skip-chars-forward " \t")
7708 (delete-region s (point))
7709 (indent-to-column c1)
7710 (while (and
7711 inline
7712 (looking-at
05bbd9c3
IZ
7713 (concat "\\([a-zA-Z0-9]+[^*+{?]\\)" ; 1 word
7714 "\\|" ; Embedded variable
ebcd4dbc 7715 "\\$\\([a-zA-Z0-9_]+\\([[{]\\)?\\|[^\n \t)|]\\)" ; 2 3
05bbd9c3 7716 "\\|" ; $ ^
ebcd4dbc 7717 "[$^]"
05bbd9c3 7718 "\\|" ; simple-code simple-code*?
ebcd4dbc 7719 "\\(\\\\.\\|[^][()#|*+?\n]\\)\\([*+{?]\\??\\)?" ; 4 5
05bbd9c3 7720 "\\|" ; Class
ebcd4dbc 7721 "\\(\\[\\)" ; 6
05bbd9c3 7722 "\\|" ; Grouping
ebcd4dbc 7723 "\\((\\(\\?\\)?\\)" ; 7 8
05bbd9c3 7724 "\\|" ; |
ebcd4dbc
IZ
7725 "\\(|\\)" ; 9
7726 )))
7727 (goto-char (match-end 0))
7728 (setq spaces t)
7729 (cond ((match-beginning 1) ; Alphanum word + junk
7730 (forward-char -1))
7731 ((or (match-beginning 3) ; $ab[12]
7732 (and (match-beginning 5) ; X* X+ X{2,3}
7733 (eq (preceding-char) ?\{)))
7734 (forward-char -1)
7735 (forward-sexp 1))
7736 ((match-beginning 6) ; []
7737 (setq tmp (point))
7738 (if (looking-at "\\^?\\]")
7739 (goto-char (match-end 0)))
7bcea553
IZ
7740 ;; XXXX POSIX classes?!
7741 (while (and (not pos)
7742 (re-search-forward "\\[:\\|\\]" e t))
7743 (if (eq (preceding-char) ?:)
7744 (or (re-search-forward ":\\]" e t)
7745 (error "[:POSIX:]-group in []-group not terminated"))
7746 (setq pos t)))
7747 (or (eq (preceding-char) ?\])
7748 (error "[]-group not terminated"))
7749 (if (eq (following-char) ?\{)
ebcd4dbc 7750 (progn
7bcea553
IZ
7751 (forward-sexp 1)
7752 (and (eq (following-char) ??)
7753 (forward-char 1)))
7754 (re-search-forward "\\=\\([*+?]\\??\\)" e t)))
ebcd4dbc
IZ
7755 ((match-beginning 7) ; ()
7756 (goto-char (match-beginning 0))
7bcea553
IZ
7757 (setq pos (current-column))
7758 (or (eq pos c1)
ebcd4dbc 7759 (progn
7bcea553 7760 (delete-horizontal-space)
ebcd4dbc
IZ
7761 (insert "\n")
7762 (indent-to-column c1)))
7763 (setq tmp (point))
7764 (forward-sexp 1)
7765 ;; (or (forward-sexp 1)
7766 ;; (progn
7767 ;; (goto-char tmp)
7768 ;; (error "()-group not terminated")))
7769 (set-marker m (1- (point)))
7770 (set-marker m1 (point))
7bcea553
IZ
7771 (if (= level 1)
7772 (if (progn ; indent rigidly if multiline
7773 ;; In fact does not make a lot of sense, since
7774 ;; the starting position can be already lost due
7775 ;; to insertion of "\n" and " "
7776 (goto-char tmp)
7777 (search-forward "\n" m1 t))
7778 (indent-rigidly (point) m1 (- c1 pos)))
7779 (setq level (1- level))
7780 (cond
7781 ((not (match-beginning 8))
7782 (cperl-beautify-regexp-piece tmp m t level))
7783 ((eq (char-after (+ 2 tmp)) ?\{) ; Code
7784 t)
7785 ((eq (char-after (+ 2 tmp)) ?\() ; Conditional
7786 (goto-char (+ 2 tmp))
7787 (forward-sexp 1)
7788 (cperl-beautify-regexp-piece (point) m t level))
7789 ((eq (char-after (+ 2 tmp)) ?<) ; Lookbehind
7790 (goto-char (+ 3 tmp))
7791 (cperl-beautify-regexp-piece (point) m t level))
7792 (t
7793 (cperl-beautify-regexp-piece tmp m t level))))
ebcd4dbc
IZ
7794 (goto-char m1)
7795 (cond ((looking-at "[*+?]\\??")
7796 (goto-char (match-end 0)))
7797 ((eq (following-char) ?\{)
7798 (forward-sexp 1)
7799 (if (eq (following-char) ?\?)
7800 (forward-char))))
7801 (skip-chars-forward " \t")
7802 (setq spaces nil)
7803 (if (looking-at "[#\n]")
05bbd9c3
IZ
7804 (progn
7805 (or (eolp) (indent-for-comment))
7806 (beginning-of-line 2))
7bcea553 7807 (delete-horizontal-space)
ebcd4dbc
IZ
7808 (insert "\n"))
7809 (end-of-line)
7810 (setq inline nil))
7811 ((match-beginning 9) ; |
7812 (forward-char -1)
7813 (setq tmp (point))
7814 (beginning-of-line)
7815 (if (re-search-forward "[^ \t]" tmp t)
7816 (progn
7817 (goto-char tmp)
7bcea553 7818 (delete-horizontal-space)
ebcd4dbc
IZ
7819 (insert "\n"))
7820 ;; first at line
7821 (delete-region (point) tmp))
7822 (indent-to-column c)
7823 (forward-char 1)
7824 (skip-chars-forward " \t")
7825 (setq spaces nil)
7826 (if (looking-at "[#\n]")
7827 (beginning-of-line 2)
7bcea553 7828 (delete-horizontal-space)
ebcd4dbc
IZ
7829 (insert "\n"))
7830 (end-of-line)
7831 (setq inline nil)))
7832 (or (looking-at "[ \t\n]")
7833 (not spaces)
7834 (insert " "))
7835 (skip-chars-forward " \t"))
7836 (or (looking-at "[#\n]")
7bcea553
IZ
7837 (error "unknown code \"%s\" in a regexp"
7838 (buffer-substring (point) (1+ (point)))))
ebcd4dbc 7839 (and inline (end-of-line 2)))
05bbd9c3
IZ
7840 ;; Special-case the last line of group
7841 (if (and (>= (point) (marker-position e))
7842 (/= (current-indentation) c))
7843 (progn
7844 (beginning-of-line)
7845 (setq s (point))
7846 (skip-chars-forward " \t")
7847 (delete-region s (point))
7848 (indent-to-column c)))
ebcd4dbc
IZ
7849 ))
7850
05bbd9c3 7851(defun cperl-make-regexp-x ()
6c72d195 7852 ;; Returns position of the start
7bcea553 7853 ;; XXX this is called too often! Need to cache the result!
05bbd9c3
IZ
7854 (save-excursion
7855 (or cperl-use-syntax-table-text-property
20675f5d 7856 (error "I need to have a regexp marked!"))
05bbd9c3 7857 ;; Find the start
6c72d195
IZ
7858 (if (looking-at "\\s|")
7859 nil ; good already
20675f5d 7860 (if (looking-at "\\([smy]\\|qr\\)\\s|")
6c72d195
IZ
7861 (forward-char 1)
7862 (re-search-backward "\\s|"))) ; Assume it is scanned already.
05bbd9c3
IZ
7863 ;;(forward-char 1)
7864 (let ((b (point)) (e (make-marker)) have-x delim (c (current-column))
7865 (sub-p (eq (preceding-char) ?s)) s)
7866 (forward-sexp 1)
7867 (set-marker e (1- (point)))
7868 (setq delim (preceding-char))
7869 (if (and sub-p (eq delim (char-after (- (point) 2))))
7870 (error "Possible s/blah// - do not know how to deal with"))
7871 (if sub-p (forward-sexp 1))
7872 (if (looking-at "\\sw*x")
7873 (setq have-x t)
7874 (insert "x"))
7875 ;; Protect fragile " ", "#"
7876 (if have-x nil
7877 (goto-char (1+ b))
7878 (while (re-search-forward "\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*[ \t\n#]" e t) ; Need to include (?#) too?
7879 (forward-char -1)
7880 (insert "\\")
7881 (forward-char 1)))
7882 b)))
7883
7bcea553 7884(defun cperl-beautify-regexp (&optional deep)
6c72d195 7885 "do it. (Experimental, may change semantics, recheck the result.)
ebcd4dbc 7886We suppose that the regexp is scanned already."
7bcea553
IZ
7887 (interactive "P")
7888 (if deep
7889 (prefix-numeric-value deep)
7890 (setq deep -1))
7891 (save-excursion
7892 (goto-char (cperl-make-regexp-x))
7893 (let ((b (point)) (e (make-marker)))
7894 (forward-sexp 1)
7895 (set-marker e (1- (point)))
7896 (cperl-beautify-regexp-piece b e nil deep))))
ebcd4dbc 7897
6c72d195
IZ
7898(defun cperl-regext-to-level-start ()
7899 "Goto start of an enclosing group in regexp.
05bbd9c3
IZ
7900We suppose that the regexp is scanned already."
7901 (interactive)
6c72d195 7902 (let ((limit (cperl-make-regexp-x)) done)
05bbd9c3
IZ
7903 (while (not done)
7904 (or (eq (following-char) ?\()
6c72d195 7905 (search-backward "(" (1+ limit) t)
05bbd9c3
IZ
7906 (error "Cannot find `(' which starts a group"))
7907 (setq done
7908 (save-excursion
7909 (skip-chars-backward "\\")
7910 (looking-at "\\(\\\\\\\\\\)*(")))
6c72d195
IZ
7911 (or done (forward-char -1)))))
7912
7913(defun cperl-contract-level ()
4584684c 7914 "Find an enclosing group in regexp and contract it.
6c72d195
IZ
7915\(Experimental, may change semantics, recheck the result.)
7916We suppose that the regexp is scanned already."
7917 (interactive)
7bcea553
IZ
7918 ;; (save-excursion ; Can't, breaks `cperl-contract-levels'
7919 (cperl-regext-to-level-start)
7920 (let ((b (point)) (e (make-marker)) s c)
7921 (forward-sexp 1)
7922 (set-marker e (1- (point)))
7923 (goto-char b)
7924 (while (re-search-forward "\\(#\\)\\|\n" e 'to-end)
7925 (cond
7926 ((match-beginning 1) ; #-comment
7927 (or c (setq c (current-indentation)))
7928 (beginning-of-line 2) ; Skip
7929 (setq s (point))
7930 (skip-chars-forward " \t")
7931 (delete-region s (point))
7932 (indent-to-column c))
7933 (t
7934 (delete-char -1)
7935 (just-one-space))))))
6c72d195
IZ
7936
7937(defun cperl-contract-levels ()
4584684c 7938 "Find an enclosing group in regexp and contract all the kids.
6c72d195
IZ
7939\(Experimental, may change semantics, recheck the result.)
7940We suppose that the regexp is scanned already."
7941 (interactive)
7bcea553
IZ
7942 (save-excursion
7943 (condition-case nil
7944 (cperl-regext-to-level-start)
7945 (error ; We are outside outermost group
7946 (goto-char (cperl-make-regexp-x))))
7947 (let ((b (point)) (e (make-marker)) s c)
7948 (forward-sexp 1)
7949 (set-marker e (1- (point)))
7950 (goto-char (1+ b))
7951 (while (re-search-forward "\\(\\\\\\\\\\)\\|(" e t)
7952 (cond
7953 ((match-beginning 1) ; Skip
7954 nil)
7955 (t ; Group
7956 (cperl-contract-level)))))))
7957
7958(defun cperl-beautify-level (&optional deep)
6c72d195
IZ
7959 "Find an enclosing group in regexp and beautify it.
7960\(Experimental, may change semantics, recheck the result.)
05bbd9c3 7961We suppose that the regexp is scanned already."
7bcea553
IZ
7962 (interactive "P")
7963 (if deep
7964 (prefix-numeric-value deep)
7965 (setq deep -1))
7966 (save-excursion
7967 (cperl-regext-to-level-start)
7968 (let ((b (point)) (e (make-marker)))
7969 (forward-sexp 1)
7970 (set-marker e (1- (point)))
7971 (cperl-beautify-regexp-piece b e nil deep))))
6c72d195
IZ
7972
7973(defun cperl-invert-if-unless ()
7bcea553 7974 "Change `if (A) {B}' into `B if A;' etc if possible."
6c72d195
IZ
7975 (interactive)
7976 (or (looking-at "\\<")
7977 (forward-sexp -1))
7bcea553 7978 (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>")
6c72d195
IZ
7979 (let ((pos1 (point))
7980 pos2 pos3 pos4 pos5 s1 s2 state p pos45
7981 (s0 (buffer-substring (match-beginning 0) (match-end 0))))
7982 (forward-sexp 2)
7983 (setq pos3 (point))
7984 (forward-sexp -1)
7985 (setq pos2 (point))
7986 (if (eq (following-char) ?\( )
7987 (progn
7988 (goto-char pos3)
7989 (forward-sexp 1)
7990 (setq pos5 (point))
7991 (forward-sexp -1)
7992 (setq pos4 (point))
7993 ;; XXXX In fact may be `A if (B); {C}' ...
7994 (if (and (eq (following-char) ?\{ )
7995 (progn
7996 (cperl-backward-to-noncomment pos3)
7997 (eq (preceding-char) ?\) )))
7998 (if (condition-case nil
7999 (progn
8000 (goto-char pos5)
8001 (forward-sexp 1)
8002 (forward-sexp -1)
8003 (looking-at "\\<els\\(e\\|if\\)\\>"))
8004 (error nil))
8005 (error
8006 "`%s' (EXPR) {BLOCK} with `else'/`elsif'" s0)
8007 (goto-char (1- pos5))
8008 (cperl-backward-to-noncomment pos4)
8009 (if (eq (preceding-char) ?\;)
8010 (forward-char -1))
8011 (setq pos45 (point))
8012 (goto-char pos4)
8013 (while (re-search-forward "\\<\\(for\\|foreach\\|if\\|unless\\|while\\|until\\)\\>\\|;" pos45 t)
8014 (setq p (match-beginning 0)
8015 s1 (buffer-substring p (match-end 0))
8016 state (parse-partial-sexp pos4 p))
8017 (or (nth 3 state)
8018 (nth 4 state)
8019 (nth 5 state)
8020 (error "`%s' inside `%s' BLOCK" s1 s0))
8021 (goto-char (match-end 0)))
8022 ;; Finally got it
8023 (goto-char (1+ pos4))
8024 (skip-chars-forward " \t\n")
8025 (setq s2 (buffer-substring (point) pos45))
8026 (goto-char pos45)
8027 (or (looking-at ";?[ \t\n]*}")
8028 (progn
8029 (skip-chars-forward "; \t\n")
8030 (setq s2 (concat s2 "\n" (buffer-substring (point) (1- pos5))))))
8031 (and (equal s2 "")
8032 (setq s2 "1"))
8033 (goto-char (1- pos3))
8034 (cperl-backward-to-noncomment pos2)
8035 (or (looking-at "[ \t\n]*)")
8036 (goto-char (1- pos3)))
8037 (setq p (point))
8038 (goto-char (1+ pos2))
8039 (skip-chars-forward " \t\n")
8040 (setq s1 (buffer-substring (point) p))
8041 (delete-region pos4 pos5)
8042 (delete-region pos2 pos3)
8043 (goto-char pos1)
8044 (insert s2 " ")
8045 (just-one-space)
8046 (forward-word 1)
8047 (setq pos1 (point))
8048 (insert " " s1 ";")
7bcea553 8049 (delete-horizontal-space)
6c72d195
IZ
8050 (forward-char -1)
8051 (delete-horizontal-space)
8052 (goto-char pos1)
8053 (just-one-space)
8054 (cperl-indent-line))
8055 (error "`%s' (EXPR) not with an {BLOCK}" s0)))
8056 (error "`%s' not with an (EXPR)" s0)))
7bcea553 8057 (error "Not at `if', `unless', `while', `unless', `for' or `foreach'")))
6c72d195
IZ
8058
8059;;; By Anthony Foiani <afoiani@uswest.com>
8060;;; Getting help on modules in C-h f ?
7bcea553 8061;;; This is a modified version of `man'.
6c72d195 8062;;; Need to teach it how to lookup functions
6c72d195 8063(defun cperl-perldoc (word)
7bcea553 8064 "Run `perldoc' on WORD."
6c72d195
IZ
8065 (interactive
8066 (list (let* ((default-entry (cperl-word-at-point))
8067 (input (read-string
8068 (format "perldoc entry%s: "
8069 (if (string= default-entry "")
8070 ""
8071 (format " (default %s)" default-entry))))))
8072 (if (string= input "")
8073 (if (string= default-entry "")
8074 (error "No perldoc args given")
8075 default-entry)
8076 input))))
8077 (let* ((is-func (and
8078 (string-match "^[a-z]+$" word)
8079 (string-match (concat "^" word "\\>")
8080 (documentation-property
8081 'cperl-short-docs
8082 'variable-documentation))))
8083 (manual-program (if is-func "perldoc -f" "perldoc")))
8084 (require 'man)
8085 (Man-getpage-in-background word)))
8086
8087(defun cperl-perldoc-at-point ()
7bcea553 8088 "Run a `perldoc' on the word around point."
6c72d195
IZ
8089 (interactive)
8090 (cperl-perldoc (cperl-word-at-point)))
8091
7bcea553
IZ
8092(defcustom pod2man-program "pod2man"
8093 "*File name for `pod2man'."
8094 :type 'file
8095 :group 'cperl)
6c72d195 8096
7bcea553 8097;;; By Nick Roberts <Nick.Roberts@src.bae.co.uk> (with changes)
6c72d195 8098(defun cperl-pod-to-manpage ()
7bcea553 8099 "Create a virtual manpage in Emacs from the Perl Online Documentation."
6c72d195
IZ
8100 (interactive)
8101 (require 'man)
8102 (let* ((pod2man-args (concat buffer-file-name " | nroff -man "))
8103 (bufname (concat "Man " buffer-file-name))
8104 (buffer (generate-new-buffer bufname)))
8105 (save-excursion
8106 (set-buffer buffer)
8107 (let ((process-environment (copy-sequence process-environment)))
8108 ;; Prevent any attempt to use display terminal fanciness.
8109 (setenv "TERM" "dumb")
8110 (set-process-sentinel
8111 (start-process pod2man-program buffer "sh" "-c"
8112 (format (cperl-pod2man-build-command) pod2man-args))
8113 'Man-bgproc-sentinel)))))
8114
8115(defun cperl-pod2man-build-command ()
8116 "Builds the entire background manpage and cleaning command."
8117 (let ((command (concat pod2man-program " %s 2>/dev/null"))
8118 (flist Man-filter-list))
8119 (while (and flist (car flist))
8120 (let ((pcom (car (car flist)))
8121 (pargs (cdr (car flist))))
8122 (setq command
8123 (concat command " | " pcom " "
8124 (mapconcat '(lambda (phrase)
8125 (if (not (stringp phrase))
8126 (error "Malformed Man-filter-list"))
8127 phrase)
8128 pargs " ")))
8129 (setq flist (cdr flist))))
8130 command))
8131
8132(defun cperl-lazy-install ()) ; Avoid a warning
05bbd9c3 8133
55497cff 8134(if (fboundp 'run-with-idle-timer)
8135 (progn
8136 (defvar cperl-help-shown nil
8137 "Non-nil means that the help was already shown now.")
8138
ebcd4dbc
IZ
8139 (defvar cperl-lazy-installed nil
8140 "Non-nil means that the lazy-help handlers are installed now.")
55497cff 8141
8142 (defun cperl-lazy-install ()
8143 (interactive)
8144 (make-variable-buffer-local 'cperl-help-shown)
ebcd4dbc
IZ
8145 (if (and (cperl-val 'cperl-lazy-help-time)
8146 (not cperl-lazy-installed))
55497cff 8147 (progn
8148 (add-hook 'post-command-hook 'cperl-lazy-hook)
ebcd4dbc
IZ
8149 (run-with-idle-timer
8150 (cperl-val 'cperl-lazy-help-time 1000000 5)
8151 t
8152 'cperl-get-help-defer)
8153 (setq cperl-lazy-installed t))))
55497cff 8154
8155 (defun cperl-lazy-unstall ()
8156 (interactive)
8157 (remove-hook 'post-command-hook 'cperl-lazy-hook)
ebcd4dbc
IZ
8158 (cancel-function-timers 'cperl-get-help-defer)
8159 (setq cperl-lazy-installed nil))
55497cff 8160
8161 (defun cperl-lazy-hook ()
8162 (setq cperl-help-shown nil))
8163
8164 (defun cperl-get-help-defer ()
8165 (if (not (eq major-mode 'perl-mode)) nil
5f05dabc 8166 (let ((cperl-message-on-help-error nil) (cperl-help-from-timer t))
55497cff 8167 (cperl-get-help)
8168 (setq cperl-help-shown t))))
8169 (cperl-lazy-install)))
ebcd4dbc 8170
6c72d195
IZ
8171
8172;;; Plug for wrong font-lock:
8173
8174(defun cperl-font-lock-unfontify-region-function (beg end)
8175 (let* ((modified (buffer-modified-p)) (buffer-undo-list t)
8176 (inhibit-read-only t) (inhibit-point-motion-hooks t)
8177 before-change-functions after-change-functions
8178 deactivate-mark buffer-file-name buffer-file-truename)
8179 (remove-text-properties beg end '(face nil))
8180 (when (and (not modified) (buffer-modified-p))
8181 (set-buffer-modified-p nil))))
8182
8183(defvar cperl-d-l nil)
8184(defun cperl-fontify-syntaxically (end)
4584684c 8185 ;; Some vars for debugging only
7bcea553 8186 ;; (message "Syntaxifying...")
4584684c
GS
8187 (let (start (dbg (point)) (iend end)
8188 (istate (car cperl-syntax-state)))
8189 (and cperl-syntaxify-unwind
8190 (setq end (cperl-unwind-to-safe t end)))
8191 (setq start (point))
6c72d195
IZ
8192 (or cperl-syntax-done-to
8193 (setq cperl-syntax-done-to (point-min)))
8194 (if (or (not (boundp 'font-lock-hot-pass))
8195 (eval 'font-lock-hot-pass)
8196 t) ; Not debugged otherwise
8197 ;; Need to forget what is after `start'
8198 (setq start (min cperl-syntax-done-to start))
8199 ;; Fontification without a change
8200 (setq start (max cperl-syntax-done-to start)))
8201 (and (> end start)
8202 (setq cperl-syntax-done-to start) ; In case what follows fails
8203 (cperl-find-pods-heres start end t nil t))
6c72d195 8204 (if (eq cperl-syntaxify-by-font-lock 'message)
4584684c
GS
8205 (message "Syntaxified %s..%s from %s to %s(%s), state %s-->%s"
8206 dbg iend
8207 start end cperl-syntax-done-to
8208 istate (car cperl-syntax-state))) ; For debugging
6c72d195
IZ
8209 nil)) ; Do not iterate
8210
20675f5d
IZ
8211(defun cperl-fontify-update (end)
8212 (let ((pos (point)) prop posend)
8213 (while (< pos end)
8214 (setq prop (get-text-property pos 'cperl-postpone))
8215 (setq posend (next-single-property-change pos 'cperl-postpone nil end))
8216 (and prop (put-text-property pos posend (car prop) (cdr prop)))
8217 (setq pos posend)))
8218 nil) ; Do not iterate
8219
6c72d195
IZ
8220(defun cperl-update-syntaxification (from to)
8221 (if (and cperl-use-syntax-table-text-property
8222 cperl-syntaxify-by-font-lock
8223 (or (null cperl-syntax-done-to)
8224 (< cperl-syntax-done-to to)))
8225 (progn
8226 (save-excursion
8227 (goto-char from)
8228 (cperl-fontify-syntaxically to)))))
8229
4584684c 8230(defvar cperl-version
7bcea553 8231 (let ((v "$Revision: 4.32 $"))
4584684c
GS
8232 (string-match ":\\s *\\([0-9.]+\\)" v)
8233 (substring v (match-beginning 1) (match-end 1)))
8234 "Version of IZ-supported CPerl package this file is based on.")
8235
ebcd4dbc 8236(provide 'cperl-mode)
6c72d195
IZ
8237
8238;;; cperl-mode.el ends here