perl 5.003_07: pod/perlvar.pod
[p5sagit/p5-mst-13.2.git] / emacs / cperl-mode.el
CommitLineData
4633a7c4 1;;; This code started from the following message of long time ago (IZ):
2
3;;; From: olson@mcs.anl.gov (Bob Olson)
4;;; Newsgroups: comp.lang.perl
5;;; Subject: cperl-mode: Another perl mode for Gnuemacs
6;;; Date: 14 Aug 91 15:20:01 GMT
7
8;; Perl code editing commands for Emacs
499d5216 9;; Copyright (C) 1985-1996 Bob Olson, Ilya Zakharevich
4633a7c4 10
499d5216 11;; This file is not (yet) part of GNU Emacs. It may be distributed
12;; either under the same terms as GNU Emacs, or under the same terms
13;; as Perl. You should have recieved a copy of Perl Artistic license
14;; along with the Perl distribution.
4633a7c4 15
16;; GNU Emacs is free software; you can redistribute it and/or modify
17;; it under the terms of the GNU General Public License as published by
18;; the Free Software Foundation; either version 2, or (at your option)
19;; any later version.
20
21;; GNU Emacs is distributed in the hope that it will be useful,
22;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24;; GNU General Public License for more details.
25
26;; You should have received a copy of the GNU General Public License
27;; along with GNU Emacs; see the file COPYING. If not, write to
28;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29
30;;; Corrections made by Ilya Zakharevich ilya@math.mps.ohio-state.edu
31;;; XEmacs changes by Peter Arius arius@informatik.uni-erlangen.de
32
499d5216 33;; $Id: cperl-mode.el,v 1.25 1996/09/06 09:51:41 ilya Exp ilya $
4633a7c4 34
35;;; To use this mode put the following into your .emacs file:
36
37;; (autoload 'perl-mode "cperl-mode" "alternate mode for editing Perl programs" t)
38
39;;; You can either fine-tune the bells and whistles of this mode or
40;;; bulk enable them by putting
41
42;; (setq cperl-hairy t)
43
44;;; in your .emacs file. (Emacs rulers do not consider it politically
45;;; correct to make whistles enabled by default.)
46
47;;; Additional useful commands to put into your .emacs file:
48
49;; (setq auto-mode-alist
50;; (append '(("\\.[pP][Llm]$" . perl-mode)) auto-mode-alist ))
51;; (setq interpreter-mode-alist (append interpreter-mode-alist
52;; '(("miniperl" . perl-mode))))
53
54;;; The mode information (on C-h m) provides customization help.
55;;; If you use font-lock feature of this mode, it is advisable to use
56;;; eather lazy-lock-mode or fast-lock-mode (available on ELisp
57;;; archive in files lazy-lock.el and fast-lock.el). I prefer lazy-lock.
58
59;;; Faces used now: three faces for first-class and second-class keywords
60;;; and control flow words, one for each: comments, string, labels,
61;;; functions definitions and packages, arrays, hashes, and variable
62;;; definitions. If you do not see all these faces, your font-lock does
63;;; not define them, so you need to define them manually. Maybe you have
64;;; an obsolete font-lock from 19.28 or earlier. Upgrade.
65
66;;; If you have grayscale monitor, and do not have the variable
67;;; font-lock-display-type bound to 'grayscale, insert
68
69;;; (setq font-lock-display-type 'grayscale)
70
71;;; to your .emacs file.
72
29043b61 73;;;; This mode supports font-lock, imenu and mode-compile. In the
4633a7c4 74;;;; hairy version font-lock is on, but you should activate imenu
29043b61 75;;;; yourself (note that mode-compile is not standard yet). Well, you
4633a7c4 76;;;; can use imenu from keyboard anyway (M-x imenu), but it is better
77;;;; to bind it like that:
78
79;; (define-key global-map [M-S-down-mouse-3] 'imenu)
80
81;;; In fact the version of font-lock that this version supports can be
82;;; much newer than the version you actually have. This means that a
83;;; lot of faces can be set up, but are not visible on your screen
84;;; since the coloring rules for this faces are not defined.
85
4633a7c4 86;;; Updates: ========================================
87
88;;; Made less hairy by default: parentheses not electric,
89;;; linefeed not magic. Bug with abbrev-mode corrected.
90
91;;;; After 1.4:
92;;; Better indentation:
93;;; subs inside braces should work now,
94;;; Toplevel braces obey customization.
95;;; indent-for-comment knows about bad cases, cperl-indent-for-comment
96;;; moves cursor to a correct place.
97;;; cperl-indent-exp written from the scratch! Slow... (quadratic!) :-(
98;;; (50 secs on DB::DB (sub of 430 lines), 486/66)
99;;; Minor documentation fixes.
100;;; Imenu understands packages as prefixes (including nested).
101;;; Hairy options can be switched off one-by-one by setting to null.
102;;; Names of functions and variables changed to conform to `cperl-' style.
103
104;;;; After 1.5:
105;;; Some bugs with indentation of labels (and embedded subs) corrected.
106;;; `cperl-indent-region' done (slow :-()).
107;;; `cperl-fill-paragraph' done.
108;;; Better package support for `imenu'.
109;;; Progress indicator for indentation (with `imenu' loaded).
110;;; `Cperl-set' was busted, now setting the individual hairy option
111;;; should be better.
112
113;;;; After 1.6:
114;;; `cperl-set-style' done.
115;;; `cperl-check-syntax' done.
116;;; Menu done.
117;;; New config variables `cperl-close-paren-offset' and `cperl-comment-column'.
118;;; Bugs with `cperl-auto-newline' corrected.
119;;; `cperl-electric-lbrace' can work with `cperl-auto-newline' in situation
120;;; like $hash{.
121
122;;;; 1.7 XEmacs (arius@informatik.uni-erlangen.de):
123;;; - use `next-command-event', if `next-command-events' does not exist
124;;; - use `find-face' as def. of `is-face'
125;;; - corrected def. of `x-color-defined-p'
126;;; - added const defs for font-lock-comment-face,
127;;; font-lock-keyword-face and font-lock-function-name-face
128;;; - added def. of font-lock-variable-name-face
129;;; - added (require 'easymenu) inside an `eval-when-compile'
130;;; - replaced 4-argument `substitute-key-definition' with ordinary
131;;; `define-key's
132;;; - replaced `mark-active' in menu definition by `cperl-use-region-p'.
133;;; Todo (at least):
134;;; - use emacs-vers.el (http://www.cs.utah.edu/~eeide/emacs/emacs-vers.el.gz)
135;;; for portable code?
136;;; - should `cperl-mode' do a
137;;; (if (featurep 'easymenu) (easy-menu-add cperl-menu))
138;;; or should this be left to the user's `cperl-mode-hook'?
139
140;;; Some bugs introduced by the above fix corrected (IZ ;-).
141;;; Some bugs under XEmacs introduced by the correction corrected.
142
143;;; Some more can remain since there are two many different variants.
144;;; Please feedback!
145
146;;; We do not support fontification of arrays and hashes under
147;;; obsolete font-lock any more. Upgrade.
148
149;;;; after 1.8 Minor bug with parentheses.
150;;;; after 1.9 Improvements from Joe Marzot.
151;;;; after 1.10
152;;; Does not need easymenu to compile under XEmacs.
153;;; `vc-insert-headers' should work better.
154;;; Should work with 19.29 and 19.12.
155;;; Small improvements to fontification.
156;;; Expansion of keywords does not depend on C-? being backspace.
157
158;;; after 1.10+
159;;; 19.29 and 19.12 supported.
160;;; `cperl-font-lock-enhanced' deprecated. Use font-lock-extra.el.
161;;; Support for font-lock-extra.el.
162
163;;;; After 1.11:
164;;; Tools submenu.
165;;; Support for perl5-info.
166;;; `imenu-go-find-at-position' in Tools requires imenu-go.el (see hints above)
167;;; Imenu entries do not work with stock imenu.el. Patch sent to maintainers.
168;;; Fontifies `require a if b;', __DATA__.
169;;; Arglist for auto-fill-mode was incorrect.
170
171;;;; After 1.12:
172;;; `cperl-lineup-step' and `cperl-lineup' added: lineup constructions
173;;; vertically.
174;;; `cperl-do-auto-fill' updated for 19.29 style.
175;;; `cperl-info-on-command' now has a default.
176;;; Workaround for broken C-h on XEmacs.
177;;; VC strings escaped.
178;;; C-h f now may prompt for function name instead of going on,
179;;; controlled by `cperl-info-on-command-no-prompt'.
180
181;;;; After 1.13:
182;;; Msb buffer list includes perl files
183;;; Indent-for-comment uses indent-to
184;;; Can write tag files using etags.
185
186;;;; After 1.14:
187;;; Recognizes (tries to ;-) {...} which are not blocks during indentation.
188;;; `cperl-close-paren-offset' affects ?\] too (and ?\} if not block)
c07a80fd 189;;; Bug with auto-filling comments started with "##" corrected.
190
191;;;; Very slow now: on DB::DB 0.91, 486/66:
192
193;;;Function Name Call Count Elapsed Time Average Time
194;;;======================================== ========== ============ ============
195;;;cperl-block-p 469 3.7799999999 0.0080597014
196;;;cperl-get-state 505 163.39000000 0.3235445544
197;;;cperl-comment-indent 12 0.0299999999 0.0024999999
198;;;cperl-backward-to-noncomment 939 4.4599999999 0.0047497337
199;;;cperl-calculate-indent 505 172.22000000 0.3410297029
200;;;cperl-indent-line 505 172.88000000 0.3423366336
201;;;cperl-use-region-p 40 0.0299999999 0.0007499999
202;;;cperl-indent-exp 1 177.97000000 177.97000000
203;;;cperl-to-comment-or-eol 1453 3.9800000000 0.0027391603
204;;;cperl-backward-to-start-of-continued-exp 9 0.0300000000 0.0033333333
205;;;cperl-indent-region 1 177.94000000 177.94000000
206
207;;;; After 1.15:
208;;; Takes into account white space after opening parentheses during indent.
209;;; May highlight pods and here-documents: see `cperl-pod-here-scan',
210;;; `cperl-pod-here-fontify', `cperl-pod-face'. Does not use this info
211;;; for indentation so far.
212;;; Fontification updated to 19.30 style.
213;;; The change 19.29->30 did not add all the required functionality,
214;;; but broke "font-lock-extra.el". Get "choose-color.el" from
215;;; ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs
216
217;;;; After 1.16:
218;;; else # comment
219;;; recognized as a start of a block.
220;;; Two different font-lock-levels provided.
221;;; `cperl-pod-head-face' introduced. Used for highlighting.
222;;; `imenu' marks pods, +Packages moved to the head.
223
224;;;; After 1.17:
225;;; Scan for pods highlights here-docs too.
226;;; Note that the tag of here-doc may be rehighlighted later by lazy-lock.
227;;; Only one here-doc-tag per line is supported, and one in comment
228;;; or a string may break fontification.
229;;; POD headers were supposed to fill one line only.
230
231;;;; After 1.18:
232;;; `font-lock-keywords' were set in 19.30 style _always_. Current scheme
233;;; may break under XEmacs.
234;;; `cperl-calculate-indent' dis suppose that `parse-start' was defined.
235;;; `fontified' tag is added to fontified text as well as `lazy-lock' (for
236;;; compatibility with older lazy-lock.el) (older one overfontifies
237;;; something nevertheless :-().
238;;; Will not indent something inside pod and here-documents.
239;;; Fontifies the package name after import/no/bootstrap.
240;;; Added new entry to menu with meta-info about the mode.
4633a7c4 241
29043b61 242;;;; After 1.19:
243;;; Prefontification works much better with 19.29. Should be checked
244;;; with 19.30 as well.
245;;; Some misprints in docs corrected.
246;;; Now $a{-text} and -text => "blah" are fontified as strings too.
247;;; Now the pod search is much stricter, so it can help you to find
248;;; pod sections which are broken because of whitespace before =blah
249;;; - just observe the fontification.
250
9ea28adb 251;;;; After 1.20
252;;; Anonymous subs are indented with respect to the level of
253;;; indentation of `sub' now.
254;;; {} is recognized as hash after `bless' and `return'.
255;;; Anonymous subs are split by `cperl-linefeed' as well.
256;;; Electric parens embrace a region if present.
257;;; To make `cperl-auto-newline' useful,
258;;; `cperl-auto-newline-after-colon' is introduced.
259;;; `cperl-electric-parens' is now t or nul. The old meaning is moved to
260;;; `cperl-electric-parens-string'.
261;;; `cperl-toggle-auto-newline' introduced, put on C-c C-a.
262;;; `cperl-toggle-abbrev' introduced, put on C-c C-k.
263;;; `cperl-toggle-electric' introduced, put on C-c C-e.
264;;; Beginning-of-defun-regexp was not anchored.
265
266;;;; After 1.21
267;;; Auto-newline grants `cperl-extra-newline-before-brace' if "{" is typed
268;;; after ")".
269;;; {} is recognized as expression after `tr' and friends.
270
271;;;; After 1.22
272;;; Entry Hierarchy added to imenu. Very primitive so far.
273;;; One needs newer `imenu-go'.el. A patch to `imenu' is needed as well.
274;;; Writes its own TAGS files.
275;;; Class viewer based on TAGS files. Does not trace @ISA so far.
276;;; 19.31: Problems with scan for PODs corrected.
277;;; First POD header correctly fontified.
278;;; I needed (setq imenu-use-keymap-menu t) to get good imenu in 19.31.
279;;; Apparently it makes a lot of hierarchy code obsolete...
280
281;;;; After 1.23
282;;; Tags filler now scans *.xs as well.
283;;; The info from *.xs scan is used by the hierarchy viewer.
284;;; Hierarchy viewer documented.
285;;; Bug in 19.31 imenu documented.
286
499d5216 287;;;; After 1.24
288;;; New location for info-files mentioned,
289;;; Electric-; should work better.
290;;; Minor bugs with POD marking.
291
292;;;; After 1.25
293;;; `cperl-info-page' introduced.
294;;; To make `uncomment-region' working, `comment-region' would
295;;; not insert extra space.
296;;; Here documents delimiters better recognized
297;;; (empty one, and non-alphanums in quotes handled). May be wrong with 1<<14?
298;;; `cperl-db' added, used in menu.
299;;; imenu scan removes text-properties, for better debugging
300;;; - but the bug is in 19.31 imenu.
301;;; formats highlighted by font-lock and prescan, embedded comments
302;;; are not treated.
303;;; POD/friends scan merged in one pass.
304;;; Syntax class is not used for analyzing the code, only char-syntax
305;;; may be cecked against _ or'ed with w.
306;;; Syntax class of `:' changed to be _.
307;;; `cperl-find-bad-style' added.
308
4633a7c4 309(defvar cperl-extra-newline-before-brace nil
310 "*Non-nil means that if, elsif, while, until, else, for, foreach
311and do constructs look like:
312
313 if ()
314 {
315 }
316
317instead of:
318
319 if () {
320 }
321")
c07a80fd 322
4633a7c4 323(defvar cperl-indent-level 2
324 "*Indentation of CPerl statements with respect to containing block.")
325(defvar cperl-lineup-step nil
326 "*`cperl-lineup' will always lineup at multiple of this number.
327If `nil', the value of `cperl-indent-level' will be used.")
328(defvar cperl-brace-imaginary-offset 0
329 "*Imagined indentation of a Perl open brace that actually follows a statement.
330An open brace following other text is treated as if it were this far
331to the right of the start of its line.")
332(defvar cperl-brace-offset 0
333 "*Extra indentation for braces, compared with other text in same context.")
334(defvar cperl-label-offset -2
335 "*Offset of CPerl label lines relative to usual indentation.")
336(defvar cperl-min-label-indent 1
337 "*Minimal offset of CPerl label lines.")
338(defvar cperl-continued-statement-offset 2
339 "*Extra indent for lines not starting new statements.")
340(defvar cperl-continued-brace-offset 0
341 "*Extra indent for substatements that start with open-braces.
342This is in addition to cperl-continued-statement-offset.")
343(defvar cperl-close-paren-offset -1
344 "*Extra indent for substatements that start with close-parenthesis.")
345
346(defvar cperl-auto-newline nil
347 "*Non-nil means automatically newline before and after braces,
9ea28adb 348and after colons and semicolons, inserted in CPerl code. The following
349\\[cperl-electric-backspace] will remove the inserted whitespace.
350Insertion after colons requires both this variable and
351`cperl-auto-newline-after-colon' set.")
352
353(defvar cperl-auto-newline-after-colon nil
354 "*Non-nil means automatically newline even after colons.
355Subject to `cperl-auto-newline' setting.")
4633a7c4 356
357(defvar cperl-tab-always-indent t
358 "*Non-nil means TAB in CPerl mode should always reindent the current line,
359regardless of where in the line point is when the TAB command is used.")
360
361(defvar cperl-font-lock nil
362 "*Non-nil (and non-null) means CPerl buffers will use font-lock-mode.
363Can be overwritten by `cperl-hairy' if nil.")
364
365(defvar cperl-electric-lbrace-space nil
366 "*Non-nil (and non-null) means { after $ in CPerl buffers should be preceeded by ` '.
367Can be overwritten by `cperl-hairy' if nil.")
368
9ea28adb 369(defvar cperl-electric-parens-string "({[<"
370 "*String of parentheses that should be electric in CPerl.")
371
372(defvar cperl-electric-parens nil
373 "*Non-nil (and non-null) means parentheses should be electric in CPerl.
374Can be overwritten by `cperl-hairy' if nil.")
375(defvar cperl-electric-parens-mark
376 (and window-system
377 (or (and (boundp 'transient-mark-mode) ; For Emacs
378 transient-mark-mode)
379 (and (boundp 'zmacs-regions) ; For XEmacs
380 zmacs-regions)))
381 "*Not-nil means that electric parens look for active mark.
382Default is yes if there is visual feedback on mark.")
383
384(defvar cperl-electric-parens-mark (and window-system transient-mark-mode)
385 "*Not-nil means that electric parens look for active mark.
386Default is yes if there is visual feedback on mark.")
4633a7c4 387
388(defvar cperl-electric-linefeed nil
389 "*If true, LFD should be hairy in CPerl, otherwise C-c LFD is hairy.
390In any case these two mean plain and hairy linefeeds together.
391Can be overwritten by `cperl-hairy' if nil.")
392
393(defvar cperl-electric-keywords nil
394 "*Not-nil (and non-null) means keywords are electric in CPerl.
395Can be overwritten by `cperl-hairy' if nil.")
396
397(defvar cperl-hairy nil
398 "*Not-nil means all the bells and whistles are enabled in CPerl.")
399
400(defvar cperl-comment-column 32
401 "*Column to put comments in CPerl (use \\[cperl-indent]' to lineup with code).")
402
403(defvar cperl-vc-header-alist '((SCCS "$sccs = '%W\%' ;")
404 (RCS "$rcs = ' $Id\$ ' ;"))
405 "*What to use as `vc-header-alist' in CPerl.")
406
407(defvar cperl-info-on-command-no-prompt nil
408 "*Not-nil (and non-null) means not to prompt on C-h f.
409The opposite behaviour is always available if prefixed with C-c.
410Can be overwritten by `cperl-hairy' if nil.")
c07a80fd 411
412(defvar cperl-pod-face 'font-lock-comment-face
413 "*The result of evaluation of this expression is used for pod highlighting.")
414
415(defvar cperl-pod-head-face 'font-lock-variable-name-face
416 "*The result of evaluation of this expression is used for pod highlighting.
417Font for POD headers.")
418
419(defvar cperl-here-face 'font-lock-string-face
420 "*The result of evaluation of this expression is used for here-docs highlighting.")
421
422(defvar cperl-pod-here-fontify '(featurep 'font-lock)
423 "*Not-nil after evaluation means to highlight pod and here-docs sections.")
424
425(defvar cperl-pod-here-scan t
426 "*Not-nil means look for pod and here-docs sections during startup.
427You can always make lookup from menu or using \\[cperl-find-pods-heres].")
428
9ea28adb 429(defvar cperl-imenu-addback nil
430 "*Not-nil means add backreferences to generated `imenu's.
431May require patched `imenu' and `imenu-go'.")
432
499d5216 433(defvar cperl-info-page "perl"
434 "Name of the info page containging perl docs.
435Older version of this page was called `perl5', newer `perl'.")
436
c07a80fd 437\f
438
439;;; Short extra-docs.
440
441(defvar cperl-tips 'please-ignore-this-line
442 "Get newest version of this package from
29043b61 443 ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs
c07a80fd 444and/or
445 ftp://ftp.math.ohio-state.edu/pub/users/ilya/perl
446
9ea28adb 447Get support packages choose-color.el (or font-lock-extra.el before
44819.30), imenu-go.el from the same place. \(Look for other files there
449too... ;-) Get a patch for imenu.el in 19.29. Note that for 19.30 and
450later you should use choose-color.el *instead* of font-lock-extra.el
451\(and you will not get smart highlighting in C :-().
c07a80fd 452
453Note that to enable Compile choices in the menu you need to install
29043b61 454mode-compile.el.
c07a80fd 455
456Get perl5-info from
499d5216 457 $CPAN/doc/manual/info/perl-info.tar.gz
458older version was on
c07a80fd 459 http://www.metronet.com:70/9/perlinfo/perl5/manual/perl5-info.tar.gz
c07a80fd 460
9ea28adb 461If you use imenu-go, run imenu on perl5-info buffer (you can do it
462from CPerl menu). If many files are related, generate TAGS files from
463Tools/Tags submenu in CPerl menu.
464
465If some class structure is too complicated, use Tools/Hierarchy-view
499d5216 466from CPerl menu, or hierarchic view of imenu. The second one uses the
467current buffer only, the first one requires generation of TAGS from
9ea28adb 468CPerl/Tools/Tags menu beforehand.
c07a80fd 469
499d5216 470Run CPerl/Tools/Insert-spaces-if-needed to fix your lazy typing.
471
c07a80fd 472Before reporting (non-)problems look in the problem section on what I
473know about them.")
474
475(defvar cperl-problems 'please-ignore-this-line
476"Emacs has a _very_ restricted syntax parsing engine.
477
9ea28adb 478It may be corrected on the level of C code, please look in the
479`non-problems' section if you want to volunteer.
c07a80fd 480
481CPerl mode tries to corrects some Emacs misunderstandings, however,
482for effeciency reasons the degree of correction is different for
483different operations. The partially corrected problems are: POD
484sections, here-documents, regexps. The operations are: highlighting,
485indentation, electric keywords, electric braces.
486
487This may be confusing, since the regexp s#//#/#\; may be highlighted
488as a comment, but it will recognized as a regexp by the indentation
489code. Or the opposite case, when a pod section is highlighted, but
490breaks the indentation of the following code.
491
492The main trick (to make $ a \"backslash\") makes constructions like
493${aaa} look like unbalanced braces. The only trick I can think out is
494to insert it as $ {aaa} (legal in perl5, not in perl4).
495
496Similar problems arise in regexps, when /(\\s|$)/ should be rewritten
497as /($|\\s)/. Note that such a transpositinon is not always possible
498:-(. " )
499
500(defvar cperl-non-problems 'please-ignore-this-line
501"As you know from `problems' section, Perl syntax too hard for CPerl.
502
503Most the time, if you write your own code, you may find an equivalent
504\(and almost as readable) expression.
505
506Try to help it: add comments with embedded quotes to fix CPerl
507misunderstandings about the end of quotation:
508
509$a='500$'; # ';
510
511You won't need it too often. The reason: $ \"quotes\" the following
512character (this saves a life a lot of times in CPerl), thus due to
513Emacs parsing rules it does not consider tick after the dollar as a
514closing one, but as a usual character.
515
516Now the indentation code is pretty wise. The only drawback is that it
517relies on Emacs parsing to find matching parentheses. And Emacs
518*cannot* match parentheses in Perl 100% correctly. So
519 1 if s#//#/#;
520will not break indentation, but
521 1 if ( s#//#/# );
522will.
523
524If you still get wrong indentation in situation that you think the
525code should be able to parse, try:
526
527a) Check what Emacs thinks about balance of your parentheses.
528b) Supply the code to me (IZ).
529
530Pods are treated _very_ rudimentally. Here-documents are not treated
531at all (except highlighting and inhibiting indentation). (This may
532change some time. RMS approved making syntax lookup recognize text
533attributes, but volonteers are needed to change Emacs C code.)
534
535To speed up coloring the following compromises exist:
536 a) sub in $mypackage::sub may be highlighted.
537 b) -z in [a-z] may be highlighted.
538 c) if your regexp contains a keyword (like \"s\"), it may be highlighted.
9ea28adb 539
540
541Imenu in 19.31 is broken. Set `imenu-use-keymap-menu' to t, and remove
542`car' before `imenu-choose-buffer-index' in `imenu'.
c07a80fd 543")
544
4633a7c4 545\f
546
547;;; Portability stuff:
548
549(defsubst cperl-xemacs-p ()
550 (string-match "XEmacs\\|Lucid" emacs-version))
551
552(defvar del-back-ch (car (append (where-is-internal 'delete-backward-char)
553 (where-is-internal 'backward-delete-char-untabify)))
554 "Character generated by key bound to delete-backward-char.")
555
556(and (vectorp del-back-ch) (= (length del-back-ch) 1)
557 (setq del-back-ch (aref del-back-ch 0)))
558
559(if (cperl-xemacs-p)
9ea28adb 560 (progn
561 ;; "Active regions" are on: use region only if active
562 ;; "Active regions" are off: use region unconditionally
563 (defun cperl-use-region-p ()
564 (if zmacs-regions (mark) t))
565 (defun cperl-mark-active () (mark)))
4633a7c4 566 (defun cperl-use-region-p ()
9ea28adb 567 (if transient-mark-mode mark-active t))
568 (defun cperl-mark-active () mark-active))
4633a7c4 569
570(defsubst cperl-enable-font-lock ()
571 (or (cperl-xemacs-p) window-system))
572
573(if (boundp 'unread-command-events)
574 (if (cperl-xemacs-p)
575 (defun cperl-putback-char (c) ; XEmacs >= 19.12
576 (setq unread-command-events (list (character-to-event c))))
577 (defun cperl-putback-char (c) ; Emacs 19
578 (setq unread-command-events (list c))))
579 (defun cperl-putback-char (c) ; XEmacs <= 19.11
580 (setq unread-command-event (character-to-event c))))
581
582(or (fboundp 'uncomment-region)
583 (defun uncomment-region (beg end)
584 (interactive "r")
585 (comment-region beg end -1)))
586
29043b61 587(defvar cperl-do-not-fontify
588 (if (string< emacs-version "19.30")
589 'fontified
590 'lazy-lock)
591 "Text property which inhibits refontification.")
592
9ea28adb 593(defsubst cperl-put-do-not-fontify (from to)
594 (put-text-property (max (point-min) (1- from))
595 to cperl-do-not-fontify t))
596
29043b61 597\f
4633a7c4 598;;; Probably it is too late to set these guys already, but it can help later:
599
600(setq auto-mode-alist
601 (append '(("\\.[pP][Llm]$" . perl-mode)) auto-mode-alist ))
602(and (boundp 'interpreter-mode-alist)
603 (setq interpreter-mode-alist (append interpreter-mode-alist
604 '(("miniperl" . perl-mode)))))
605(if (fboundp 'eval-when-compile)
606 (eval-when-compile
607 (condition-case nil
608 (require 'imenu)
609 (error nil))
610 (condition-case nil
611 (require 'easymenu)
612 (error nil))
613 ;; Calling `cperl-enable-font-lock' below doesn't compile on XEmacs,
614 ;; macros instead of defsubsts don't work on Emacs, so we do the
615 ;; expansion manually. Any other suggestions?
616 (if (or (string-match "XEmacs\\|Lucid" emacs-version)
617 window-system)
618 (require 'font-lock))
619 (require 'cl)
620 ))
621
622(defvar cperl-mode-abbrev-table nil
623 "Abbrev table in use in Cperl-mode buffers.")
624
625(add-hook 'edit-var-mode-alist '(perl-mode (regexp . "^cperl-")))
626
627(defvar cperl-mode-map () "Keymap used in CPerl mode.")
628
629(if cperl-mode-map nil
630 (setq cperl-mode-map (make-sparse-keymap))
631 (define-key cperl-mode-map "{" 'cperl-electric-lbrace)
632 (define-key cperl-mode-map "[" 'cperl-electric-paren)
633 (define-key cperl-mode-map "(" 'cperl-electric-paren)
634 (define-key cperl-mode-map "<" 'cperl-electric-paren)
635 (define-key cperl-mode-map "}" 'cperl-electric-brace)
636 (define-key cperl-mode-map ";" 'cperl-electric-semi)
637 (define-key cperl-mode-map ":" 'cperl-electric-terminator)
638 (define-key cperl-mode-map "\C-j" 'newline-and-indent)
639 (define-key cperl-mode-map "\C-c\C-j" 'cperl-linefeed)
9ea28adb 640 (define-key cperl-mode-map "\C-c\C-a" 'cperl-toggle-auto-newline)
641 (define-key cperl-mode-map "\C-c\C-k" 'cperl-toggle-abbrev)
642 (define-key cperl-mode-map "\C-c\C-e" 'cperl-toggle-electric)
4633a7c4 643 (define-key cperl-mode-map "\e\C-q" 'cperl-indent-exp) ; Usually not bound
644 ;;(define-key cperl-mode-map "\M-q" 'cperl-fill-paragraph)
645 ;;(define-key cperl-mode-map "\e;" 'cperl-indent-for-comment)
9ea28adb 646 (define-key cperl-mode-map "\177" 'cperl-electric-backspace)
4633a7c4 647 (define-key cperl-mode-map "\t" 'cperl-indent-command)
648 (if (cperl-xemacs-p)
649 ;; don't clobber the backspace binding:
650 (define-key cperl-mode-map [(control h) f] 'cperl-info-on-command)
651 (define-key cperl-mode-map "\C-hf" 'cperl-info-on-command))
652 (if (cperl-xemacs-p)
653 ;; don't clobber the backspace binding:
654 (define-key cperl-mode-map [(control c) (control h) f]
655 'cperl-info-on-current-command)
656 (define-key cperl-mode-map "\C-c\C-hf" 'cperl-info-on-current-command))
657 (if (and (cperl-xemacs-p)
658 (<= emacs-minor-version 11) (<= emacs-major-version 19))
659 (progn
660 ;; substitute-key-definition is usefulness-deenhanced...
661 (define-key cperl-mode-map "\M-q" 'cperl-fill-paragraph)
662 (define-key cperl-mode-map "\e;" 'cperl-indent-for-comment)
663 (define-key cperl-mode-map "\e\C-\\" 'cperl-indent-region))
664 (substitute-key-definition
665 'indent-sexp 'cperl-indent-exp
666 cperl-mode-map global-map)
667 (substitute-key-definition
668 'fill-paragraph 'cperl-fill-paragraph
669 cperl-mode-map global-map)
670 (substitute-key-definition
671 'indent-region 'cperl-indent-region
672 cperl-mode-map global-map)
673 (substitute-key-definition
674 'indent-for-comment 'cperl-indent-for-comment
675 cperl-mode-map global-map)))
676
677(condition-case nil
678 (progn
679 (require 'easymenu)
680 (easy-menu-define cperl-menu cperl-mode-map "Menu for CPerl mode"
681 '("Perl"
682 ["Beginning of function" beginning-of-defun t]
683 ["End of function" end-of-defun t]
684 ["Mark function" mark-defun t]
685 ["Indent expression" cperl-indent-exp t]
686 ["Fill paragraph/comment" cperl-fill-paragraph t]
687 ["Line up a construction" cperl-lineup (cperl-use-region-p)]
688 "----"
689 ["Indent region" cperl-indent-region (cperl-use-region-p)]
499d5216 690 ["Comment region" cperl-comment-region (cperl-use-region-p)]
691 ["Uncomment region" cperl-uncomment-region (cperl-use-region-p)]
4633a7c4 692 "----"
693 ["Run" mode-compile (fboundp 'mode-compile)]
694 ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
695 (get-buffer "*compilation*"))]
696 ["Next error" next-error (get-buffer "*compilation*")]
697 ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
698 "----"
499d5216 699 ["Debugger" cperl-db t]
4633a7c4 700 "----"
701 ("Tools"
702 ["Imenu" imenu (fboundp 'imenu)]
499d5216 703 ["Insert spaces if needed" cperl-find-bad-style t]
9ea28adb 704 ["Class Hierarchy from TAGS" cperl-tags-hier-init t]
705 ;;["Update classes" (cperl-tags-hier-init t) tags-table-list]
4633a7c4 706 ["Imenu on info" cperl-imenu-on-info (featurep 'imenu)]
707 ("Tags"
9ea28adb 708;;; ["Create tags for current file" cperl-etags t]
709;;; ["Add tags for current file" (cperl-etags t) t]
710;;; ["Create tags for Perl files in directory" (cperl-etags nil t) t]
711;;; ["Add tags for Perl files in directory" (cperl-etags t t) t]
712;;; ["Create tags for Perl files in (sub)directories"
713;;; (cperl-etags nil 'recursive) t]
714;;; ["Add tags for Perl files in (sub)directories"
715;;; (cperl-etags t 'recursive) t])
716;;;; cperl-write-tags (&optional file erase recurse dir inbuffer)
717 ["Create tags for current file" (cperl-write-tags nil t) t]
718 ["Add tags for current file" (cperl-write-tags) t]
719 ["Create tags for Perl files in directory"
720 (cperl-write-tags nil t nil t) t]
721 ["Add tags for Perl files in directory"
722 (cperl-write-tags nil nil nil t) t]
4633a7c4 723 ["Create tags for Perl files in (sub)directories"
9ea28adb 724 (cperl-write-tags nil t t t) t]
4633a7c4 725 ["Add tags for Perl files in (sub)directories"
9ea28adb 726 (cperl-write-tags nil nil t t) t])
727 ["Recalculate PODs and HEREs" cperl-find-pods-heres t]
4633a7c4 728 ["Define word at point" imenu-go-find-at-position
729 (fboundp 'imenu-go-find-at-position)]
730 ["Help on function" cperl-info-on-command t]
731 ["Help on function at point" cperl-info-on-current-command t])
9ea28adb 732 ("Toggle..."
733 ["Auto newline" cperl-toggle-auto-newline t]
734 ["Electric parens" cperl-toggle-electric t]
735 ["Electric keywords" cperl-toggle-abbrev t]
736 )
4633a7c4 737 ("Indent styles..."
738 ["GNU" (cperl-set-style "GNU") t]
739 ["C++" (cperl-set-style "C++") t]
740 ["FSF" (cperl-set-style "FSF") t]
741 ["BSD" (cperl-set-style "BSD") t]
c07a80fd 742 ["Whitesmith" (cperl-set-style "Whitesmith") t])
743 ("Micro-docs"
744 ["Tips" (describe-variable 'cperl-tips) t]
745 ["Problems" (describe-variable 'cperl-problems) t]
746 ["Non-problems" (describe-variable 'cperl-non-problems) t]))))
4633a7c4 747 (error nil))
748
749(autoload 'c-macro-expand "cmacexp"
750 "Display the result of expanding all C macros occurring in the region.
751The expansion is entirely correct because it uses the C preprocessor."
752 t)
753
754(defvar cperl-mode-syntax-table nil
755 "Syntax table in use in Cperl-mode buffers.")
756
757(if cperl-mode-syntax-table
758 ()
759 (setq cperl-mode-syntax-table (make-syntax-table))
760 (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table)
761 (modify-syntax-entry ?/ "." cperl-mode-syntax-table)
762 (modify-syntax-entry ?* "." cperl-mode-syntax-table)
763 (modify-syntax-entry ?+ "." cperl-mode-syntax-table)
764 (modify-syntax-entry ?- "." cperl-mode-syntax-table)
765 (modify-syntax-entry ?= "." cperl-mode-syntax-table)
766 (modify-syntax-entry ?% "." cperl-mode-syntax-table)
767 (modify-syntax-entry ?< "." cperl-mode-syntax-table)
768 (modify-syntax-entry ?> "." cperl-mode-syntax-table)
769 (modify-syntax-entry ?& "." cperl-mode-syntax-table)
770 (modify-syntax-entry ?$ "\\" cperl-mode-syntax-table)
771 (modify-syntax-entry ?\n ">" cperl-mode-syntax-table)
772 (modify-syntax-entry ?# "<" cperl-mode-syntax-table)
773 (modify-syntax-entry ?' "\"" cperl-mode-syntax-table)
774 (modify-syntax-entry ?` "\"" cperl-mode-syntax-table)
775 (modify-syntax-entry ?_ "w" cperl-mode-syntax-table)
499d5216 776 (modify-syntax-entry ?: "_" cperl-mode-syntax-table)
4633a7c4 777 (modify-syntax-entry ?| "." cperl-mode-syntax-table))
778
779
780\f
781;; Make customization possible "in reverse"
782;;(defun cperl-set (symbol to)
783;; (or (eq (symbol-value symbol) 'null) (set symbol to)))
784(defsubst cperl-val (symbol &optional default hairy)
785 (cond
786 ((eq (symbol-value symbol) 'null) default)
787 (cperl-hairy (or hairy t))
788 (t (symbol-value symbol))))
789\f
790;; provide an alias for working with emacs 19. the perl-mode that comes
791;; with it is really bad, and this lets us seamlessly replace it.
792(fset 'perl-mode 'cperl-mode)
793(defun cperl-mode ()
794 "Major mode for editing Perl code.
795Expression and list commands understand all C brackets.
796Tab indents for Perl code.
797Paragraphs are separated by blank lines only.
798Delete converts tabs to spaces as it moves back.
799
800Various characters in Perl almost always come in pairs: {}, (), [],
801sometimes <>. When the user types the first, she gets the second as
802well, with optional special formatting done on {}. (Disabled by
803default.) You can always quote (with \\[quoted-insert]) the left
804\"paren\" to avoid the expansion. The processing of < is special,
805since most the time you mean \"less\". Cperl mode tries to guess
806whether you want to type pair <>, and inserts is if it
9ea28adb 807appropriate. You can set `cperl-electric-parens-string' to the string that
4633a7c4 808contains the parenths from the above list you want to be electrical.
9ea28adb 809Electricity of parenths is controlled by `cperl-electric-parens'.
810You may also set `cperl-electric-parens-mark' to have electric parens
811look for active mark and \"embrace\" a region if possible.'
4633a7c4 812
813CPerl mode provides expansion of the Perl control constructs:
814 if, else, elsif, unless, while, until, for, and foreach.
815=========(Disabled by default, see `cperl-electric-keywords'.)
816The user types the keyword immediately followed by a space, which causes
817the construct to be expanded, and the user is positioned where she is most
818likely to want to be.
819eg. when the user types a space following \"if\" the following appears in
820the buffer:
821 if () { or if ()
822 } {
823 }
824and the cursor is between the parentheses. The user can then type some
825boolean expression within the parens. Having done that, typing
826\\[cperl-linefeed] places you, appropriately indented on a new line
827between the braces. If CPerl decides that you want to insert
828\"English\" style construct like
829 bite if angry;
830it will not do any expansion. See also help on variable
831`cperl-extra-newline-before-brace'.
832
833\\[cperl-linefeed] is a convinience replacement for typing carriage
834return. It places you in the next line with proper indentation, or if
835you type it inside the inline block of control construct, like
836 foreach (@lines) {print; print}
837and you are on a boundary of a statement inside braces, it will
838transform the construct into a multiline and will place you into an
839apporpriately indented blank line. If you need a usual
840`newline-and-indent' behaviour, it is on \\[newline-and-indent],
841see documentation on `cperl-electric-linefeed'.
842
843\\{cperl-mode-map}
844
845Setting the variable `cperl-font-lock' to t switches on
846font-lock-mode, `cperl-electric-lbrace-space' to t switches on
9ea28adb 847electric space between $ and {, `cperl-electric-parens-string' is the
848string that contains parentheses that should be electric in CPerl (see
849also `cperl-electric-parens-mark' and `cperl-electric-parens'),
850setting `cperl-electric-keywords' enables electric expansion of
851control structures in CPerl. `cperl-electric-linefeed' governs which
852one of two linefeed behavior is preferable. You can enable all these
853options simultaneously (recommended mode of use) by setting
854`cperl-hairy' to t. In this case you can switch separate options off
855by setting them to `null'. Note that one may undo the extra whitespace
856inserted by semis and braces in `auto-newline'-mode by consequent
857\\[cperl-electric-backspace].
4633a7c4 858
859If your site has perl5 documentation in info format, you can use commands
860\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
861These keys run commands `cperl-info-on-current-command' and
862`cperl-info-on-command', which one is which is controlled by variable
863`cperl-info-on-command-no-prompt' (in turn affected by `cperl-hairy').
864
c07a80fd 865Variables `cperl-pod-here-scan', `cperl-pod-here-fontify',
866`cperl-pod-face', `cperl-pod-head-face' control processing of pod and
867here-docs sections. In a future version results of scan may be used
868for indentation too, currently they are used for highlighting only.
869
4633a7c4 870Variables controlling indentation style:
871 `cperl-tab-always-indent'
872 Non-nil means TAB in CPerl mode should always reindent the current line,
873 regardless of where in the line point is when the TAB command is used.
874 `cperl-auto-newline'
875 Non-nil means automatically newline before and after braces,
9ea28adb 876 and after colons and semicolons, inserted in Perl code. The following
877 \\[cperl-electric-backspace] will remove the inserted whitespace.
878 Insertion after colons requires both this variable and
879 `cperl-auto-newline-after-colon' set.
880 `cperl-auto-newline-after-colon'
881 Non-nil means automatically newline even after colons.
882 Subject to `cperl-auto-newline' setting.
4633a7c4 883 `cperl-indent-level'
884 Indentation of Perl statements within surrounding block.
885 The surrounding block's indentation is the indentation
886 of the line on which the open-brace appears.
887 `cperl-continued-statement-offset'
888 Extra indentation given to a substatement, such as the
889 then-clause of an if, or body of a while, or just a statement continuation.
890 `cperl-continued-brace-offset'
891 Extra indentation given to a brace that starts a substatement.
892 This is in addition to `cperl-continued-statement-offset'.
893 `cperl-brace-offset'
894 Extra indentation for line if it starts with an open brace.
895 `cperl-brace-imaginary-offset'
896 An open brace following other text is treated as if it the line started
897 this far to the right of the actual line indentation.
898 `cperl-label-offset'
899 Extra indentation for line that is a label.
900 `cperl-min-label-indent'
901 Minimal indentation for line that is a label.
902
903Settings for K&R and BSD indentation styles are
904 `cperl-indent-level' 5 8
905 `cperl-continued-statement-offset' 5 8
906 `cperl-brace-offset' -5 -8
907 `cperl-label-offset' -5 -8
908
909If `cperl-indent-level' is 0, the statement after opening brace in column 0 is indented on `cperl-brace-offset'+`cperl-continued-statement-offset'.
910
911Turning on CPerl mode calls the hooks in the variable `cperl-mode-hook'
912with no args."
913 (interactive)
914 (kill-all-local-variables)
915 ;;(if cperl-hairy
916 ;; (progn
917 ;; (cperl-set 'cperl-font-lock cperl-hairy)
918 ;; (cperl-set 'cperl-electric-lbrace-space cperl-hairy)
919 ;; (cperl-set 'cperl-electric-parens "{[(<")
920 ;; (cperl-set 'cperl-electric-keywords cperl-hairy)
921 ;; (cperl-set 'cperl-electric-linefeed cperl-hairy)))
922 (use-local-map cperl-mode-map)
923 (if (cperl-val 'cperl-electric-linefeed)
924 (progn
925 (local-set-key "\C-J" 'cperl-linefeed)
926 (local-set-key "\C-C\C-J" 'newline-and-indent)))
927 (if (cperl-val 'cperl-info-on-command-no-prompt)
928 (progn
929 (if (cperl-xemacs-p)
930 ;; don't clobber the backspace binding:
931 (local-set-key [(control h) f] 'cperl-info-on-current-command)
932 (local-set-key "\C-hf" 'cperl-info-on-current-command))
933 (if (cperl-xemacs-p)
934 ;; don't clobber the backspace binding:
935 (local-set-key [(control c) (control h) f]
936 'cperl-info-on-command)
937 (local-set-key "\C-c\C-hf" 'cperl-info-on-command))))
938 (setq major-mode 'perl-mode)
939 (setq mode-name "CPerl")
940 (if (not cperl-mode-abbrev-table)
941 (let ((prev-a-c abbrevs-changed))
942 (define-abbrev-table 'cperl-mode-abbrev-table '(
943 ("if" "if" cperl-electric-keyword 0)
944 ("elsif" "elsif" cperl-electric-keyword 0)
945 ("while" "while" cperl-electric-keyword 0)
946 ("until" "until" cperl-electric-keyword 0)
947 ("unless" "unless" cperl-electric-keyword 0)
948 ("else" "else" cperl-electric-else 0)
949 ("for" "for" cperl-electric-keyword 0)
950 ("foreach" "foreach" cperl-electric-keyword 0)
951 ("do" "do" cperl-electric-keyword 0)))
952 (setq abbrevs-changed prev-a-c)))
953 (setq local-abbrev-table cperl-mode-abbrev-table)
954 (abbrev-mode (if (cperl-val 'cperl-electric-keywords) 1 0))
955 (set-syntax-table cperl-mode-syntax-table)
956 (make-local-variable 'paragraph-start)
957 (setq paragraph-start (concat "^$\\|" page-delimiter))
958 (make-local-variable 'paragraph-separate)
959 (setq paragraph-separate paragraph-start)
960 (make-local-variable 'paragraph-ignore-fill-prefix)
961 (setq paragraph-ignore-fill-prefix t)
962 (make-local-variable 'indent-line-function)
963 (setq indent-line-function 'cperl-indent-line)
964 (make-local-variable 'require-final-newline)
965 (setq require-final-newline t)
966 (make-local-variable 'comment-start)
967 (setq comment-start "# ")
968 (make-local-variable 'comment-end)
969 (setq comment-end "")
970 (make-local-variable 'comment-column)
971 (setq comment-column cperl-comment-column)
972 (make-local-variable 'comment-start-skip)
973 (setq comment-start-skip "#+ *")
974 (make-local-variable 'defun-prompt-regexp)
499d5216 975 (setq defun-prompt-regexp "^[ \t]*sub[ \t]+\\([^ \t\n{;]+\\)[ \t]*")
4633a7c4 976 (make-local-variable 'comment-indent-function)
977 (setq comment-indent-function 'cperl-comment-indent)
978 (make-local-variable 'parse-sexp-ignore-comments)
979 (setq parse-sexp-ignore-comments t)
980 (make-local-variable 'indent-region-function)
981 (setq indent-region-function 'cperl-indent-region)
982 ;;(setq auto-fill-function 'cperl-do-auto-fill) ; Need to switch on and off!
983 (make-local-variable 'imenu-create-index-function)
984 (setq imenu-create-index-function
985 (function imenu-example--create-perl-index))
c07a80fd 986 (make-local-variable 'imenu-sort-function)
987 (setq imenu-sort-function nil)
4633a7c4 988 (make-local-variable 'vc-header-alist)
989 (setq vc-header-alist cperl-vc-header-alist)
c07a80fd 990 (make-local-variable 'font-lock-defaults)
991 (setq font-lock-defaults
992 (if (string< emacs-version "19.30")
993 '(perl-font-lock-keywords-2)
994 '((perl-font-lock-keywords
995 perl-font-lock-keywords-1
996 perl-font-lock-keywords-2))))
4633a7c4 997 (or (fboundp 'cperl-old-auto-fill-mode)
998 (progn
999 (fset 'cperl-old-auto-fill-mode (symbol-function 'auto-fill-mode))
1000 (defun auto-fill-mode (&optional arg)
1001 (interactive "P")
1002 (cperl-old-auto-fill-mode arg)
1003 (and auto-fill-function (eq major-mode 'perl-mode)
1004 (setq auto-fill-function 'cperl-do-auto-fill)))))
1005 (if (cperl-enable-font-lock)
c07a80fd 1006 (if (cperl-val 'cperl-font-lock)
1007 (progn (or cperl-faces-init (cperl-init-faces))
1008 (font-lock-mode 1))))
4633a7c4 1009 (and (boundp 'msb-menu-cond)
1010 (not cperl-msb-fixed)
1011 (cperl-msb-fix))
c07a80fd 1012 (run-hooks 'cperl-mode-hook)
1013 ;; After hooks since fontification will break this
1014 (if cperl-pod-here-scan (cperl-find-pods-heres)))
4633a7c4 1015\f
499d5216 1016;; Fix for perldb - make default reasonable
1017(defun cperl-db ()
1018 (interactive)
1019 (require 'gud)
1020 (perldb (read-from-minibuffer "Run perldb (like this): "
1021 (if (consp gud-perldb-history)
1022 (car gud-perldb-history)
1023 (concat "perl " ;;(file-name-nondirectory
1024 ;; I have problems
1025 ;; in OS/2
1026 ;; otherwise
1027 (buffer-file-name)))
1028 nil nil
1029 '(gud-perldb-history . 1))))
1030\f
4633a7c4 1031;; Fix for msb.el
1032(defvar cperl-msb-fixed nil)
1033
1034(defun cperl-msb-fix ()
1035 ;; Adds perl files to msb menu, supposes that msb is already loaded
1036 (setq cperl-msb-fixed t)
1037 (let* ((l (length msb-menu-cond))
1038 (last (nth (1- l) msb-menu-cond))
1039 (precdr (nthcdr (- l 2) msb-menu-cond)) ; cdr of this is last
1040 (handle (1- (nth 1 last))))
1041 (setcdr precdr (list
1042 (list
1043 '(eq major-mode 'perl-mode)
1044 handle
1045 "Perl Files (%d)")
1046 last))))
1047\f
1048;; This is used by indent-for-comment
1049;; to decide how much to indent a comment in CPerl code
1050;; based on its context. Do fallback if comment is found wrong.
1051
1052(defvar cperl-wrong-comment)
1053
1054(defun cperl-comment-indent ()
1055 (let ((p (point)) (c (current-column)) was)
1056 (if (looking-at "^#") 0 ; Existing comment at bol stays there.
1057 ;; Wrong comment found
1058 (save-excursion
1059 (setq was (cperl-to-comment-or-eol))
1060 (if (= (point) p)
1061 (progn
1062 (skip-chars-backward " \t")
1063 (max (1+ (current-column)) ; Else indent at comment column
1064 comment-column))
1065 (if was nil
1066 (insert comment-start)
1067 (backward-char (length comment-start)))
1068 (setq cperl-wrong-comment t)
1069 (indent-to comment-column 1) ; Indent minimum 1
1070 c))))) ; except leave at least one space.
1071
1072;;;(defun cperl-comment-indent-fallback ()
1073;;; "Is called if the standard comment-search procedure fails.
1074;;;Point is at start of real comment."
1075;;; (let ((c (current-column)) target cnt prevc)
1076;;; (if (= c comment-column) nil
1077;;; (setq cnt (skip-chars-backward "[ \t]"))
1078;;; (setq target (max (1+ (setq prevc
1079;;; (current-column))) ; Else indent at comment column
1080;;; comment-column))
1081;;; (if (= c comment-column) nil
1082;;; (delete-backward-char cnt)
1083;;; (while (< prevc target)
1084;;; (insert "\t")
1085;;; (setq prevc (current-column)))
1086;;; (if (> prevc target) (progn (delete-char -1) (setq prevc (current-column))))
1087;;; (while (< prevc target)
1088;;; (insert " ")
1089;;; (setq prevc (current-column)))))))
1090
1091(defun cperl-indent-for-comment ()
1092 "Substite for `indent-for-comment' in CPerl."
1093 (interactive)
1094 (let (cperl-wrong-comment)
1095 (indent-for-comment)
1096 (if cperl-wrong-comment
1097 (progn (cperl-to-comment-or-eol)
1098 (forward-char (length comment-start))))))
1099
499d5216 1100(defun cperl-comment-region (b e arg)
1101 "Comment or uncomment each line in the region in CPerl mode.
1102See `comment-region'."
1103 (interactive "r\np")
1104 (let ((comment-start "#"))
1105 (comment-region b e arg)))
1106
1107(defun cperl-uncomment-region (b e arg)
1108 "Uncomment or comment each line in the region in CPerl mode.
1109See `comment-region'."
1110 (interactive "r\np")
1111 (let ((comment-start "#"))
1112 (comment-region b e (- arg))))
1113
4633a7c4 1114(defun cperl-electric-brace (arg &optional only-before)
1115 "Insert character and correct line's indentation.
1116If ONLY-BEFORE and `cperl-auto-newline', will insert newline before the
9ea28adb 1117place (even in empty line), but not after. If after \")\" and the inserted
1118char is \"{\", insert extra newline before only if
1119`cperl-extra-newline-before-brace'."
4633a7c4 1120 (interactive "P")
1121 (let (insertpos)
1122 (if (and (not arg) ; No args, end (of empty line or auto)
1123 (eolp)
1124 (or (and (null only-before)
1125 (save-excursion
1126 (skip-chars-backward " \t")
1127 (bolp)))
9ea28adb 1128 (and (eq last-command-char ?\{) ; Do not insert newline
1129 ;; if after ")" and `cperl-extra-newline-before-brace'
1130 ;; is nil, do not insert extra newline.
1131 (not cperl-extra-newline-before-brace)
1132 (save-excursion
1133 (skip-chars-backward " \t")
1134 (eq (preceding-char) ?\))))
4633a7c4 1135 (if cperl-auto-newline
1136 (progn (cperl-indent-line) (newline) t) nil)))
1137 (progn
1138 (if cperl-auto-newline
1139 (setq insertpos (point)))
1140 (insert last-command-char)
1141 (cperl-indent-line)
1142 (if (and cperl-auto-newline (null only-before))
1143 (progn
1144 (newline)
1145 (cperl-indent-line)))
1146 (save-excursion
1147 (if insertpos (progn (goto-char insertpos)
1148 (search-forward (make-string
1149 1 last-command-char))
1150 (setq insertpos (1- (point)))))
1151 (delete-char -1))))
1152 (if insertpos
1153 (save-excursion
1154 (goto-char insertpos)
1155 (self-insert-command (prefix-numeric-value arg)))
1156 (self-insert-command (prefix-numeric-value arg)))))
1157
1158(defun cperl-electric-lbrace (arg)
1159 "Insert character, correct line's indentation, correct quoting by space."
1160 (interactive "P")
9ea28adb 1161 (let (pos after
1162 (cperl-auto-newline cperl-auto-newline)
1163 (other-end (if (and cperl-electric-parens-mark
1164 (cperl-mark-active)
1165 (> (mark) (point)))
1166 (save-excursion
1167 (goto-char (mark))
1168 (point-marker))
1169 nil)))
4633a7c4 1170 (and (cperl-val 'cperl-electric-lbrace-space)
1171 (eq (preceding-char) ?$)
1172 (save-excursion
1173 (skip-chars-backward "$")
1174 (looking-at "\\(\\$\\$\\)*\\$\\([^\\$]\\|$\\)"))
1175 (insert ? ))
9ea28adb 1176 (if (cperl-after-expr-p nil "{};)") nil (setq cperl-auto-newline nil))
4633a7c4 1177 (cperl-electric-brace arg)
9ea28adb 1178 (and (cperl-val 'cperl-electric-parens)
1179 (eq last-command-char ?{)
4633a7c4 1180 (memq last-command-char
9ea28adb 1181 (append cperl-electric-parens-string nil))
1182 (or (if other-end (goto-char (marker-position other-end)))
1183 t)
4633a7c4 1184 (setq last-command-char ?} pos (point))
1185 (progn (cperl-electric-brace arg t)
1186 (goto-char pos)))))
1187
1188(defun cperl-electric-paren (arg)
1189 "Insert a matching pair of parentheses."
1190 (interactive "P")
9ea28adb 1191 (let ((beg (save-excursion (beginning-of-line) (point)))
1192 (other-end (if (and cperl-electric-parens-mark
1193 (cperl-mark-active)
1194 (> (mark) (point)))
1195 (save-excursion
1196 (goto-char (mark))
1197 (point-marker))
1198 nil)))
1199 (if (and (cperl-val 'cperl-electric-parens)
1200 (memq last-command-char
1201 (append cperl-electric-parens-string nil))
4633a7c4 1202 (>= (save-excursion (cperl-to-comment-or-eol) (point)) (point))
1203 ;;(not (save-excursion (search-backward "#" beg t)))
1204 (if (eq last-command-char ?<)
c07a80fd 1205 (cperl-after-expr-p nil "{};(,:=")
4633a7c4 1206 1))
1207 (progn
1208 (insert last-command-char)
9ea28adb 1209 (if other-end (goto-char (marker-position other-end)))
4633a7c4 1210 (insert (cdr (assoc last-command-char '((?{ .?})
1211 (?[ . ?])
1212 (?( . ?))
1213 (?< . ?>)))))
1214 (forward-char -1))
1215 (insert last-command-char)
1216 )))
1217
1218(defun cperl-electric-keyword ()
1219 "Insert a construction appropriate after a keyword."
9ea28adb 1220 (let ((beg (save-excursion (beginning-of-line) (point)))
1221 (dollar (eq (preceding-char) ?$)))
4633a7c4 1222 (and (save-excursion
1223 (backward-sexp 1)
c07a80fd 1224 (cperl-after-expr-p nil "{};:"))
4633a7c4 1225 (save-excursion
1226 (not
1227 (re-search-backward
1228 "[#\"'`]\\|\\<q\\(\\|[wqx]\\)\\>"
1229 beg t)))
1230 (save-excursion (or (not (re-search-backward "^=" nil t))
1231 (looking-at "=cut")))
1232 (progn
9ea28adb 1233 (and dollar (insert " $"))
4633a7c4 1234 (cperl-indent-line)
1235 ;;(insert " () {\n}")
1236 (cond
1237 (cperl-extra-newline-before-brace
1238 (insert " ()\n")
1239 (insert "{")
1240 (cperl-indent-line)
1241 (insert "\n")
1242 (cperl-indent-line)
1243 (insert "\n}"))
1244 (t
1245 (insert " () {\n}"))
1246 )
1247 (or (looking-at "[ \t]\\|$") (insert " "))
1248 (cperl-indent-line)
9ea28adb 1249 (if dollar (progn (search-backward "$")
1250 (forward-char 1))
1251 (search-backward ")"))
4633a7c4 1252 (cperl-putback-char del-back-ch)))))
1253
1254(defun cperl-electric-else ()
1255 "Insert a construction appropriate after a keyword."
1256 (let ((beg (save-excursion (beginning-of-line) (point))))
1257 (and (save-excursion
1258 (backward-sexp 1)
c07a80fd 1259 (cperl-after-expr-p nil "{};:"))
4633a7c4 1260 (save-excursion
1261 (not
1262 (re-search-backward
1263 "[#\"'`]\\|\\<q\\(\\|[wqx]\\)\\>"
1264 beg t)))
1265 (save-excursion (or (not (re-search-backward "^=" nil t))
1266 (looking-at "=cut")))
1267 (progn
1268 (cperl-indent-line)
1269 ;;(insert " {\n\n}")
1270 (cond
1271 (cperl-extra-newline-before-brace
1272 (insert "\n")
1273 (insert "{")
1274 (cperl-indent-line)
1275 (insert "\n\n}"))
1276 (t
1277 (insert " {\n\n}"))
1278 )
1279 (or (looking-at "[ \t]\\|$") (insert " "))
1280 (cperl-indent-line)
1281 (forward-line -1)
1282 (cperl-indent-line)
1283 (cperl-putback-char del-back-ch)))))
1284
1285(defun cperl-linefeed ()
1286 "Go to end of line, open a new line and indent appropriately."
1287 (interactive)
1288 (let ((beg (save-excursion (beginning-of-line) (point)))
1289 (end (save-excursion (end-of-line) (point)))
1290 (pos (point)) start)
1291 (if (and ; Check if we need to split:
1292 ; i.e., on a boundary and inside "{...}"
4633a7c4 1293 (save-excursion (cperl-to-comment-or-eol)
499d5216 1294 (>= (point) pos)) ; Not in a comment
4633a7c4 1295 (or (save-excursion
1296 (skip-chars-backward " \t" beg)
1297 (forward-char -1)
499d5216 1298 (looking-at "[;{]")) ; After { or ; + spaces
1299 (looking-at "[ \t]*}") ; Before }
1300 (re-search-forward "\\=[ \t]*;" end t)) ; Before spaces + ;
4633a7c4 1301 (save-excursion
1302 (and
499d5216 1303 (eq (car (parse-partial-sexp pos end -1)) -1)
1304 ; Leave the level of parens
9ea28adb 1305 (looking-at "[,; \t]*\\($\\|#\\)") ; Comma to allow anon subr
499d5216 1306 ; Are at end
4633a7c4 1307 (progn
1308 (backward-sexp 1)
1309 (setq start (point-marker))
499d5216 1310 (<= start pos))))) ; Redundant? Are after the
1311 ; start of parens group.
4633a7c4 1312 (progn
1313 (skip-chars-backward " \t")
1314 (or (memq (preceding-char) (append ";{" nil))
1315 (insert ";"))
1316 (insert "\n")
1317 (forward-line -1)
1318 (cperl-indent-line)
4633a7c4 1319 (goto-char start)
1320 (or (looking-at "{[ \t]*$") ; If there is a statement
1321 ; before, move it to separate line
1322 (progn
1323 (forward-char 1)
1324 (insert "\n")
1325 (cperl-indent-line)))
1326 (forward-line 1) ; We are on the target line
1327 (cperl-indent-line)
1328 (beginning-of-line)
9ea28adb 1329 (or (looking-at "[ \t]*}[,; \t]*$") ; If there is a statement
4633a7c4 1330 ; after, move it to separate line
1331 (progn
1332 (end-of-line)
1333 (search-backward "}" beg)
1334 (skip-chars-backward " \t")
1335 (or (memq (preceding-char) (append ";{" nil))
1336 (insert ";"))
1337 (insert "\n")
1338 (cperl-indent-line)
1339 (forward-line -1)))
1340 (forward-line -1) ; We are on the line before target
1341 (end-of-line)
1342 (newline-and-indent))
1343 (end-of-line) ; else
499d5216 1344 (cond
1345 ((and (looking-at "\n[ \t]*{$")
1346 (save-excursion
1347 (skip-chars-backward " \t")
1348 (eq (preceding-char) ?\)))) ; Probably if () {} group
1349 ; with an extra newline.
1350 (forward-line 2)
1351 (cperl-indent-line))
1352 ((looking-at "\n[ \t]*$") ; Next line is empty - use it.
1353 (forward-line 1)
1354 (cperl-indent-line))
1355 (t
1356 (newline-and-indent))))))
4633a7c4 1357
1358(defun cperl-electric-semi (arg)
1359 "Insert character and correct line's indentation."
1360 (interactive "P")
1361 (if cperl-auto-newline
1362 (cperl-electric-terminator arg)
1363 (self-insert-command (prefix-numeric-value arg))))
1364
1365(defun cperl-electric-terminator (arg)
1366 "Insert character and correct line's indentation."
1367 (interactive "P")
9ea28adb 1368 (let (insertpos (end (point))
1369 (auto (and cperl-auto-newline
1370 (or (not (eq last-command-char ?:))
1371 cperl-auto-newline-after-colon))))
499d5216 1372 (if (and ;;(not arg)
1373 (eolp)
4633a7c4 1374 (not (save-excursion
1375 (beginning-of-line)
1376 (skip-chars-forward " \t")
c07a80fd 1377 (or
1378 ;; Ignore in comment lines
1379 (= (following-char) ?#)
1380 ;; Colon is special only after a label
1381 ;; So quickly rule out most other uses of colon
1382 ;; and do no indentation for them.
1383 (and (eq last-command-char ?:)
1384 (save-excursion
1385 (forward-word 1)
1386 (skip-chars-forward " \t")
1387 (and (< (point) end)
1388 (progn (goto-char (- end 1))
1389 (not (looking-at ":"))))))
1390 (progn
1391 (beginning-of-defun)
1392 (let ((pps (parse-partial-sexp (point) end)))
1393 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
4633a7c4 1394 (progn
4633a7c4 1395 (insert last-command-char)
499d5216 1396 ;;(forward-char -1)
9ea28adb 1397 (if auto (setq insertpos (point-marker)))
499d5216 1398 ;;(forward-char 1)
4633a7c4 1399 (cperl-indent-line)
9ea28adb 1400 (if auto
4633a7c4 1401 (progn
1402 (newline)
1403 (cperl-indent-line)))
9ea28adb 1404;; (save-excursion
1405;; (if insertpos (progn (goto-char (marker-position insertpos))
1406;; (search-forward (make-string
1407;; 1 last-command-char))
1408;; (setq insertpos (1- (point)))))
1409;; (delete-char -1))))
4633a7c4 1410 (save-excursion
499d5216 1411 (if insertpos (goto-char (1- (marker-position insertpos)))
9ea28adb 1412 (forward-char -1))
1413 (delete-char 1))))
4633a7c4 1414 (if insertpos
1415 (save-excursion
1416 (goto-char insertpos)
1417 (self-insert-command (prefix-numeric-value arg)))
1418 (self-insert-command (prefix-numeric-value arg)))))
1419
9ea28adb 1420(defun cperl-electric-backspace (arg)
1421 "Backspace-untabify, or remove the whitespace inserted by an electric key."
1422 (interactive "p")
1423 (if (and cperl-auto-newline
1424 (memq last-command '(cperl-electric-semi
1425 cperl-electric-terminator
1426 cperl-electric-lbrace))
1427 (memq (preceding-char) '(? ?\t ?\n)))
1428 (let (p)
1429 (if (eq last-command 'cperl-electric-lbrace)
1430 (skip-chars-forward " \t\n"))
1431 (setq p (point))
1432 (skip-chars-backward " \t\n")
1433 (delete-region (point) p))
1434 (backward-delete-char-untabify arg)))
1435
4633a7c4 1436(defun cperl-inside-parens-p ()
1437 (condition-case ()
1438 (save-excursion
1439 (save-restriction
1440 (narrow-to-region (point)
1441 (progn (beginning-of-defun) (point)))
1442 (goto-char (point-max))
1443 (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
1444 (error nil)))
1445\f
1446(defun cperl-indent-command (&optional whole-exp)
4633a7c4 1447 "Indent current line as Perl code, or in some cases insert a tab character.
1448If `cperl-tab-always-indent' is non-nil (the default), always indent current line.
1449Otherwise, indent the current line only if point is at the left margin
1450or in the line's indentation; otherwise insert a tab.
1451
1452A numeric argument, regardless of its value,
1453means indent rigidly all the lines of the expression starting after point
1454so that this line becomes properly indented.
1455The relative indentation among the lines of the expression are preserved."
9ea28adb 1456 (interactive "P")
4633a7c4 1457 (if whole-exp
1458 ;; If arg, always indent this line as Perl
1459 ;; and shift remaining lines of expression the same amount.
1460 (let ((shift-amt (cperl-indent-line))
1461 beg end)
1462 (save-excursion
1463 (if cperl-tab-always-indent
1464 (beginning-of-line))
1465 (setq beg (point))
1466 (forward-sexp 1)
1467 (setq end (point))
1468 (goto-char beg)
1469 (forward-line 1)
1470 (setq beg (point)))
1471 (if (> end beg)
1472 (indent-code-rigidly beg end shift-amt "#")))
1473 (if (and (not cperl-tab-always-indent)
1474 (save-excursion
1475 (skip-chars-backward " \t")
1476 (not (bolp))))
1477 (insert-tab)
1478 (cperl-indent-line))))
1479
1480(defun cperl-indent-line (&optional symbol)
1481 "Indent current line as Perl code.
1482Return the amount the indentation changed by."
1483 (let (indent
1484 beg shift-amt
1485 (case-fold-search nil)
1486 (pos (- (point-max) (point))))
1487 (setq indent (cperl-calculate-indent nil symbol))
1488 (beginning-of-line)
1489 (setq beg (point))
1490 (cond ((eq indent nil)
1491 (setq indent (current-indentation)))
1492 ;;((eq indent t) ; Never?
1493 ;; (setq indent (cperl-calculate-indent-within-comment)))
1494 ;;((looking-at "[ \t]*#")
1495 ;; (setq indent 0))
1496 (t
1497 (skip-chars-forward " \t")
1498 (if (listp indent) (setq indent (car indent)))
1499 (cond ((looking-at "[A-Za-z]+:[^:]")
1500 (and (> indent 0)
1501 (setq indent (max cperl-min-label-indent
1502 (+ indent cperl-label-offset)))))
4633a7c4 1503 ((= (following-char) ?})
1504 (setq indent (- indent cperl-indent-level)))
1505 ((memq (following-char) '(?\) ?\])) ; To line up with opening paren.
1506 (setq indent (+ indent cperl-close-paren-offset)))
1507 ((= (following-char) ?{)
1508 (setq indent (+ indent cperl-brace-offset))))))
1509 (skip-chars-forward " \t")
1510 (setq shift-amt (- indent (current-column)))
1511 (if (zerop shift-amt)
1512 (if (> (- (point-max) pos) (point))
1513 (goto-char (- (point-max) pos)))
1514 (delete-region beg (point))
1515 (indent-to indent)
1516 ;; If initial point was within line's indentation,
1517 ;; position after the indentation. Else stay at same point in text.
1518 (if (> (- (point-max) pos) (point))
1519 (goto-char (- (point-max) pos))))
1520 shift-amt))
1521
c07a80fd 1522(defun cperl-after-label ()
4633a7c4 1523 ;; Returns true if the point is after label. Does not do save-excursion.
1524 (and (eq (preceding-char) ?:)
1525 (memq (char-syntax (char-after (- (point) 2)))
1526 '(?w ?_))
1527 (progn
1528 (backward-sexp)
499d5216 1529 (looking-at "[a-zA-Z_][a-zA-Z0-9_]*:[^:]"))))
4633a7c4 1530
c07a80fd 1531(defun cperl-get-state (&optional parse-start start-state)
1532 ;; returns list (START STATE DEPTH PRESTART), START is a good place
1533 ;; to start parsing, STATE is what is returned by
1534 ;; `parse-partial-sexp'. DEPTH is true is we are immediately after
1535 ;; end of block which contains START. PRESTART is the position
1536 ;; basing on which START was found.
4633a7c4 1537 (save-excursion
c07a80fd 1538 (let ((start-point (point)) depth state start prestart)
4633a7c4 1539 (if parse-start
1540 (goto-char parse-start)
1541 (beginning-of-defun))
c07a80fd 1542 (setq prestart (point))
4633a7c4 1543 (if start-state nil
c07a80fd 1544 ;; Try to go out, if sub is not on the outermost level
1545 (while (< (point) start-point)
1546 (setq start (point) parse-start start depth nil
1547 state (parse-partial-sexp start start-point -1))
4633a7c4 1548 (if (> (car state) -1) nil
1549 ;; The current line could start like }}}, so the indentation
1550 ;; corresponds to a different level than what we reached
c07a80fd 1551 (setq depth t)
4633a7c4 1552 (beginning-of-line 2))) ; Go to the next line.
c07a80fd 1553 (if start (goto-char start))) ; Not at the start of file
1554 (setq start (point))
1555 (if (< start start-point) (setq parse-start start))
1556 (or state (setq state (parse-partial-sexp start start-point -1 nil start-state)))
1557 (list start state depth prestart))))
1558
1559(defun cperl-block-p () ; Do not C-M-q ! One string contains ";" !
1560 ;; Positions is before ?\{. Checks whether it starts a block.
1561 ;; No save-excursion!
1562 (cperl-backward-to-noncomment (point-min))
1563 ;;(skip-chars-backward " \t\n\f")
1564 (or (memq (preceding-char) (append ";){}$@&%\C-@" nil)) ; Or label! \C-@ at bobp
4633a7c4 1565 ; Label may be mixed up with `$blah :'
c07a80fd 1566 (save-excursion (cperl-after-label))
499d5216 1567 (and (memq (char-syntax (preceding-char)) '(?w ?_))
c07a80fd 1568 (progn
1569 (backward-sexp)
9ea28adb 1570 ;; Need take into account `bless', `return', `tr',...
499d5216 1571 (or (and (looking-at "[a-zA-Z0-9_:]+[ \t\n\f]*[{#]") ; Method call syntax
9ea28adb 1572 (not (looking-at "\\(bless\\|return\\|qw\\|tr\\|[smy]\\)\\>")))
4633a7c4 1573 (progn
c07a80fd 1574 (skip-chars-backward " \t\n\f")
499d5216 1575 (and (memq (char-syntax (preceding-char)) '(?w ?_))
c07a80fd 1576 (progn
1577 (backward-sexp)
1578 (looking-at
499d5216 1579 "sub[ \t]+[a-zA-Z0-9_:]+[ \t\n\f]*[#{]")))))))))
4633a7c4 1580
c07a80fd 1581(defun cperl-calculate-indent (&optional parse-start symbol)
1582 "Return appropriate indentation for current line as Perl code.
1583In usual case returns an integer: the column to indent to.
1584Returns nil if line starts inside a string, t if in a comment."
1585 (save-excursion
1586 (if (memq (get-text-property (point) 'syntax-type) '(pod here-doc)) nil
1587 (beginning-of-line)
1588 (let* ((indent-point (point))
1589 (case-fold-search nil)
1590 (s-s (cperl-get-state))
1591 (start (nth 0 s-s))
1592 (state (nth 1 s-s))
1593 (containing-sexp (car (cdr state)))
1594 (char-after (save-excursion
1595 (skip-chars-forward " \t")
1596 (following-char)))
1597 (start-indent (save-excursion
1598 (goto-char start)
1599 (- (current-indentation)
1600 (if (nth 2 s-s) cperl-indent-level 0))))
1601 old-indent)
1602 ;; (or parse-start (null symbol)
1603 ;; (setq parse-start (symbol-value symbol)
1604 ;; start-indent (nth 2 parse-start)
1605 ;; parse-start (car parse-start)))
1606 ;; (if parse-start
1607 ;; (goto-char parse-start)
1608 ;; (beginning-of-defun))
1609 ;; ;; Try to go out
1610 ;; (while (< (point) indent-point)
1611 ;; (setq start (point) parse-start start moved nil
1612 ;; state (parse-partial-sexp start indent-point -1))
1613 ;; (if (> (car state) -1) nil
1614 ;; ;; The current line could start like }}}, so the indentation
1615 ;; ;; corresponds to a different level than what we reached
1616 ;; (setq moved t)
1617 ;; (beginning-of-line 2))) ; Go to the next line.
1618 ;; (if start ; Not at the start of file
1619 ;; (progn
1620 ;; (goto-char start)
1621 ;; (setq start-indent (current-indentation))
1622 ;; (if moved ; Should correct...
1623 ;; (setq start-indent (- start-indent cperl-indent-level))))
1624 ;; (setq start-indent 0))
1625 ;; (if (< (point) indent-point) (setq parse-start (point)))
1626 ;; (or state (setq state (parse-partial-sexp
1627 ;; (point) indent-point -1 nil start-state)))
1628 ;; (setq containing-sexp
1629 ;; (or (car (cdr state))
1630 ;; (and (>= (nth 6 state) 0) old-containing-sexp))
1631 ;; old-containing-sexp nil start-state nil)
1632;;;; (while (< (point) indent-point)
1633;;;; (setq parse-start (point))
1634;;;; (setq state (parse-partial-sexp (point) indent-point -1 nil start-state))
1635;;;; (setq containing-sexp
1636;;;; (or (car (cdr state))
1637;;;; (and (>= (nth 6 state) 0) old-containing-sexp))
1638;;;; old-containing-sexp nil start-state nil))
1639 ;; (if symbol (set symbol (list indent-point state start-indent)))
1640 ;; (goto-char indent-point)
1641 (cond ((or (nth 3 state) (nth 4 state))
1642 ;; return nil or t if should not change this line
1643 (nth 4 state))
1644 ((null containing-sexp)
1645 ;; Line is at top level. May be data or function definition,
1646 ;; or may be function argument declaration.
1647 ;; Indent like the previous top level line
1648 ;; unless that ends in a closeparen without semicolon,
1649 ;; in which case this line is the first argument decl.
1650 (skip-chars-forward " \t")
1651 (+ start-indent
1652 (if (= (following-char) ?{) cperl-continued-brace-offset 0)
1653 (progn
1654 (cperl-backward-to-noncomment (or parse-start (point-min)))
1655 ;;(skip-chars-backward " \t\f\n")
1656 ;; Look at previous line that's at column 0
1657 ;; to determine whether we are in top-level decls
1658 ;; or function's arg decls. Set basic-indent accordingly.
1659 ;; Now add a little if this is a continuation line.
1660 (if (or (bobp)
1661 (memq (preceding-char) (append " ;}" nil)) ; Was ?\)
1662 (memq char-after (append ")]}" nil)))
1663 0
1664 cperl-continued-statement-offset))))
1665 ((/= (char-after containing-sexp) ?{)
1666 ;; line is expression, not statement:
1667 ;; indent to just after the surrounding open,
1668 ;; skip blanks if we do not close the expression.
1669 (goto-char (1+ containing-sexp))
1670 (or (memq char-after (append ")]}" nil))
1671 (looking-at "[ \t]*\\(#\\|$\\)")
1672 (skip-chars-forward " \t"))
1673 (current-column))
1674 ((progn
1675 ;; Containing-expr starts with \{. Check whether it is a hash.
1676 (goto-char containing-sexp)
1677 (not (cperl-block-p)))
1678 (goto-char (1+ containing-sexp))
1679 (or (eq char-after ?\})
1680 (looking-at "[ \t]*\\(#\\|$\\)")
1681 (skip-chars-forward " \t"))
1682 (+ (current-column) ; Correct indentation of trailing ?\}
1683 (if (eq char-after ?\}) (+ cperl-indent-level
1684 cperl-close-paren-offset)
1685 0)))
1686 (t
1687 ;; Statement level. Is it a continuation or a new statement?
1688 ;; Find previous non-comment character.
1689 (goto-char indent-point)
1690 (cperl-backward-to-noncomment containing-sexp)
1691 ;; Back up over label lines, since they don't
1692 ;; affect whether our line is a continuation.
1693 (while (or (eq (preceding-char) ?\,)
1694 (and (eq (preceding-char) ?:)
1695 (or;;(eq (char-after (- (point) 2)) ?\') ; ????
1696 (memq (char-syntax (char-after (- (point) 2)))
1697 '(?w ?_)))))
1698 (if (eq (preceding-char) ?\,)
1699 ;; Will go to beginning of line, essentially.
1700 ;; Will ignore embedded sexpr XXXX.
1701 (cperl-backward-to-start-of-continued-exp containing-sexp))
1702 (beginning-of-line)
1703 (cperl-backward-to-noncomment containing-sexp))
1704 ;; Now we get the answer.
1705 (if (not (memq (preceding-char) (append ", ;}{" '(nil)))) ; Was ?\,
1706 ;; This line is continuation of preceding line's statement;
1707 ;; indent `cperl-continued-statement-offset' more than the
1708 ;; previous line of the statement.
4633a7c4 1709 (progn
c07a80fd 1710 (cperl-backward-to-start-of-continued-exp containing-sexp)
1711 (+ (if (memq char-after (append "}])" nil))
1712 0 ; Closing parenth
1713 cperl-continued-statement-offset)
1714 (current-column)
1715 (if (eq char-after ?\{)
1716 cperl-continued-brace-offset 0)))
1717 ;; This line starts a new statement.
1718 ;; Position following last unclosed open.
1719 (goto-char containing-sexp)
1720 ;; Is line first statement after an open-brace?
1721 (or
1722 ;; If no, find that first statement and indent like
1723 ;; it. If the first statement begins with label, do
1724 ;; not belive when the indentation of the label is too
1725 ;; small.
1726 (save-excursion
1727 (forward-char 1)
1728 (setq old-indent (current-indentation))
1729 (let ((colon-line-end 0))
1730 (while (progn (skip-chars-forward " \t\n")
1731 (looking-at "#\\|[a-zA-Z0-9_$]*:[^:]"))
1732 ;; Skip over comments and labels following openbrace.
1733 (cond ((= (following-char) ?\#)
1734 (forward-line 1))
1735 ;; label:
1736 (t
1737 (save-excursion (end-of-line)
1738 (setq colon-line-end (point)))
1739 (search-forward ":"))))
1740 ;; The first following code counts
1741 ;; if it is before the line we want to indent.
1742 (and (< (point) indent-point)
1743 (if (> colon-line-end (point)) ; After label
1744 (if (> (current-indentation)
1745 cperl-min-label-indent)
1746 (- (current-indentation) cperl-label-offset)
1747 ;; Do not belive: `max' is involved
1748 (+ old-indent cperl-indent-level))
1749 (current-column)))))
1750 ;; If no previous statement,
1751 ;; indent it relative to line brace is on.
1752 ;; For open brace in column zero, don't let statement
1753 ;; start there too. If cperl-indent-level is zero,
1754 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
1755 ;; For open-braces not the first thing in a line,
1756 ;; add in cperl-brace-imaginary-offset.
1757
1758 ;; If first thing on a line: ?????
1759 (+ (if (and (bolp) (zerop cperl-indent-level))
1760 (+ cperl-brace-offset cperl-continued-statement-offset)
1761 cperl-indent-level)
1762 ;; Move back over whitespace before the openbrace.
1763 ;; If openbrace is not first nonwhite thing on the line,
1764 ;; add the cperl-brace-imaginary-offset.
1765 (progn (skip-chars-backward " \t")
1766 (if (bolp) 0 cperl-brace-imaginary-offset))
1767 ;; If the openbrace is preceded by a parenthesized exp,
1768 ;; move to the beginning of that;
1769 ;; possibly a different line
1770 (progn
1771 (if (eq (preceding-char) ?\))
1772 (forward-sexp -1))
9ea28adb 1773 ;; In the case it starts a subroutine, indent with
1774 ;; respect to `sub', not with respect to the the
1775 ;; first thing on the line, say in the case of
1776 ;; anonymous sub in a hash.
1777 ;;
1778 (skip-chars-backward " \t")
1779 (if (and (eq (preceding-char) ?b)
1780 (progn
1781 (forward-word -1)
1782 (looking-at "sub\\>"))
1783 (setq old-indent
1784 (nth 1
1785 (parse-partial-sexp
1786 (save-excursion (beginning-of-line) (point))
1787 (point)))))
1788 (progn (goto-char (1+ old-indent))
1789 (skip-chars-forward " \t")
1790 (current-column))
1791 ;; Get initial indentation of the line we are on.
1792 ;; If line starts with label, calculate label indentation
1793 (if (save-excursion
1794 (beginning-of-line)
1795 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_]*:[^:]"))
1796 (if (> (current-indentation) cperl-min-label-indent)
1797 (- (current-indentation) cperl-label-offset)
1798 (cperl-calculate-indent
1799 (if (and parse-start (<= parse-start (point)))
1800 parse-start)))
1801 (current-indentation)))))))))))))
4633a7c4 1802
1803(defvar cperl-indent-alist
1804 '((string nil)
1805 (comment nil)
1806 (toplevel 0)
1807 (toplevel-after-parenth 2)
1808 (toplevel-continued 2)
1809 (expression 1))
1810 "Alist of indentation rules for CPerl mode.
1811The values mean:
1812 nil: do not indent;
1813 number: add this amount of indentation.")
1814
1815(defun cperl-where-am-i (&optional parse-start start-state)
1816 ;; Unfinished
c07a80fd 1817 "Return a list of lists ((TYPE POS)...) of good points before the point.
4633a7c4 1818POS may be nil if it is hard to find, say, when TYPE is `string' or `comment'."
1819 (save-excursion
c07a80fd 1820 (let* ((start-point (point))
1821 (s-s (cperl-get-state))
1822 (start (nth 0 s-s))
1823 (state (nth 1 s-s))
1824 (prestart (nth 3 s-s))
1825 (containing-sexp (car (cdr state)))
1826 (case-fold-search nil)
1827 (res (list (list 'parse-start start) (list 'parse-prestart prestart))))
4633a7c4 1828 (cond ((nth 3 state) ; In string
c07a80fd 1829 (setq res (cons (list 'string nil (nth 3 state)) res))) ; What started string
4633a7c4 1830 ((nth 4 state) ; In comment
c07a80fd 1831 (setq res (cons '(comment) res)))
4633a7c4 1832 ((null containing-sexp)
1833 ;; Line is at top level.
1834 ;; Indent like the previous top level line
1835 ;; unless that ends in a closeparen without semicolon,
1836 ;; in which case this line is the first argument decl.
1837 (cperl-backward-to-noncomment (or parse-start (point-min)))
c07a80fd 1838 ;;(skip-chars-backward " \t\f\n")
4633a7c4 1839 (cond
1840 ((or (bobp)
1841 (memq (preceding-char) (append ";}" nil)))
c07a80fd 1842 (setq res (cons (list 'toplevel start) res)))
4633a7c4 1843 ((eq (preceding-char) ?\) )
c07a80fd 1844 (setq res (cons (list 'toplevel-after-parenth start) res)))
1845 (t
1846 (setq res (cons (list 'toplevel-continued start) res)))))
4633a7c4 1847 ((/= (char-after containing-sexp) ?{)
1848 ;; line is expression, not statement:
1849 ;; indent to just after the surrounding open.
c07a80fd 1850 ;; skip blanks if we do not close the expression.
1851 (setq res (cons (list 'expression-blanks
1852 (progn
1853 (goto-char (1+ containing-sexp))
1854 (or (looking-at "[ \t]*\\(#\\|$\\)")
1855 (skip-chars-forward " \t"))
1856 (point)))
1857 (cons (list 'expression containing-sexp) res))))
4633a7c4 1858 ((progn
1859 ;; Containing-expr starts with \{. Check whether it is a hash.
1860 (goto-char containing-sexp)
c07a80fd 1861 (not (cperl-block-p)))
1862 (setq res (cons (list 'expression-blanks
1863 (progn
1864 (goto-char (1+ containing-sexp))
1865 (or (looking-at "[ \t]*\\(#\\|$\\)")
1866 (skip-chars-forward " \t"))
1867 (point)))
1868 (cons (list 'expression containing-sexp) res))))
4633a7c4 1869 (t
c07a80fd 1870 ;; Statement level.
1871 (setq res (cons (list 'in-block containing-sexp) res))
1872 ;; Is it a continuation or a new statement?
4633a7c4 1873 ;; Find previous non-comment character.
1874 (cperl-backward-to-noncomment containing-sexp)
1875 ;; Back up over label lines, since they don't
1876 ;; affect whether our line is a continuation.
c07a80fd 1877 ;; Back up comma-delimited lines too ?????
4633a7c4 1878 (while (or (eq (preceding-char) ?\,)
c07a80fd 1879 (save-excursion (cperl-after-label)))
4633a7c4 1880 (if (eq (preceding-char) ?\,)
c07a80fd 1881 ;; Will go to beginning of line, essentially
1882 ;; Will ignore embedded sexpr XXXX.
4633a7c4 1883 (cperl-backward-to-start-of-continued-exp containing-sexp))
1884 (beginning-of-line)
1885 (cperl-backward-to-noncomment containing-sexp))
1886 ;; Now we get the answer.
1887 (if (not (memq (preceding-char) (append ";}{" '(nil)))) ; Was ?\,
1888 ;; This line is continuation of preceding line's statement.
c07a80fd 1889 (list (list 'statement-continued containing-sexp))
4633a7c4 1890 ;; This line starts a new statement.
1891 ;; Position following last unclosed open.
1892 (goto-char containing-sexp)
1893 ;; Is line first statement after an open-brace?
1894 (or
1895 ;; If no, find that first statement and indent like
1896 ;; it. If the first statement begins with label, do
1897 ;; not belive when the indentation of the label is too
1898 ;; small.
1899 (save-excursion
1900 (forward-char 1)
4633a7c4 1901 (let ((colon-line-end 0))
c07a80fd 1902 (while (progn (skip-chars-forward " \t\n" start-point)
1903 (and (< (point) start-point)
1904 (looking-at
1905 "#\\|[a-zA-Z_][a-zA-Z0-9_]*:[^:]")))
4633a7c4 1906 ;; Skip over comments and labels following openbrace.
1907 (cond ((= (following-char) ?\#)
c07a80fd 1908 ;;(forward-line 1)
1909 (end-of-line))
4633a7c4 1910 ;; label:
1911 (t
1912 (save-excursion (end-of-line)
1913 (setq colon-line-end (point)))
1914 (search-forward ":"))))
c07a80fd 1915 ;; Now at the point, after label, or at start
1916 ;; of first statement in the block.
4633a7c4 1917 (and (< (point) start-point)
c07a80fd 1918 (if (> colon-line-end (point))
1919 ;; Before statement after label
4633a7c4 1920 (if (> (current-indentation)
1921 cperl-min-label-indent)
c07a80fd 1922 (list (list 'label-in-block (point)))
4633a7c4 1923 ;; Do not belive: `max' is involved
c07a80fd 1924 (list
1925 (list 'label-in-block-min-indent (point))))
1926 ;; Before statement
1927 (list 'statement-in-block (point))))))
4633a7c4 1928 ;; If no previous statement,
1929 ;; indent it relative to line brace is on.
1930 ;; For open brace in column zero, don't let statement
1931 ;; start there too. If cperl-indent-level is zero,
1932 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
1933 ;; For open-braces not the first thing in a line,
1934 ;; add in cperl-brace-imaginary-offset.
1935
1936 ;; If first thing on a line: ?????
1937 (+ (if (and (bolp) (zerop cperl-indent-level))
1938 (+ cperl-brace-offset cperl-continued-statement-offset)
1939 cperl-indent-level)
1940 ;; Move back over whitespace before the openbrace.
1941 ;; If openbrace is not first nonwhite thing on the line,
1942 ;; add the cperl-brace-imaginary-offset.
1943 (progn (skip-chars-backward " \t")
1944 (if (bolp) 0 cperl-brace-imaginary-offset))
1945 ;; If the openbrace is preceded by a parenthesized exp,
1946 ;; move to the beginning of that;
1947 ;; possibly a different line
1948 (progn
1949 (if (eq (preceding-char) ?\))
1950 (forward-sexp -1))
1951 ;; Get initial indentation of the line we are on.
1952 ;; If line starts with label, calculate label indentation
1953 (if (save-excursion
1954 (beginning-of-line)
1955 (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_]*:[^:]"))
1956 (if (> (current-indentation) cperl-min-label-indent)
1957 (- (current-indentation) cperl-label-offset)
1958 (cperl-calculate-indent
c07a80fd 1959 (if (and parse-start (<= parse-start (point)))
1960 parse-start)))
1961 (current-indentation))))))))
1962 res)))
4633a7c4 1963
1964(defun cperl-calculate-indent-within-comment ()
1965 "Return the indentation amount for line, assuming that
1966the current line is to be regarded as part of a block comment."
1967 (let (end star-start)
1968 (save-excursion
1969 (beginning-of-line)
1970 (skip-chars-forward " \t")
1971 (setq end (point))
1972 (and (= (following-char) ?#)
1973 (forward-line -1)
1974 (cperl-to-comment-or-eol)
1975 (setq end (point)))
1976 (goto-char end)
1977 (current-column))))
1978
1979
1980(defun cperl-to-comment-or-eol ()
1981 "Goes to position before comment on the current line, or to end of line.
1982Returns true if comment is found."
1983 (let (state stop-in cpoint (lim (progn (end-of-line) (point))))
1984 (beginning-of-line)
1985 (if (re-search-forward "\\=[ \t]*\\(#\\|$\\)" lim t)
1986 (if (eq (preceding-char) ?\#) (progn (backward-char 1) t))
1987 ;; Else
1988 (while (not stop-in)
1989 (setq state (parse-partial-sexp (point) lim nil nil nil t))
1990 ; stop at comment
1991 ;; If fails (beginning-of-line inside sexp), then contains not-comment
1992 ;; Do simplified processing
1993 ;;(if (re-search-forward "[^$]#" lim 1)
1994 ;; (progn
1995 ;; (forward-char -1)
1996 ;; (skip-chars-backward " \t\n\f" lim))
1997 ;; (goto-char lim)) ; No `#' at all
1998 ;;)
1999 (if (nth 4 state) ; After `#';
2000 ; (nth 2 state) can be
2001 ; beginning of m,s,qq and so
2002 ; on
2003 (if (nth 2 state)
2004 (progn
2005 (setq cpoint (point))
2006 (goto-char (nth 2 state))
2007 (cond
2008 ((looking-at "\\(s\\|tr\\)\\>")
2009 (or (re-search-forward
2010 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*"
2011 lim 'move)
2012 (setq stop-in t)))
2013 ((looking-at "\\(m\\|q\\([qxw]\\)?\\)\\>")
2014 (or (re-search-forward
2015 "\\=\\w+[ \t]*#\\([^\n\\\\#]\\|\\\\[\\\\#]\\)*#"
2016 lim 'move)
2017 (setq stop-in t)))
2018 (t ; It was fair comment
2019 (setq stop-in t) ; Finish
2020 (goto-char (1- cpoint)))))
2021 (setq stop-in t) ; Finish
2022 (forward-char -1))
2023 (setq stop-in t)) ; Finish
2024 )
2025 (nth 4 state))))
2026
c07a80fd 2027(defun cperl-find-pods-heres (&optional min max)
2028 "Scans the buffer for POD sections and here-documents.
2029If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify
2030the sections using `cperl-pod-head-face', `cperl-pod-face',
2031`cperl-here-face'."
2032 (interactive)
2033 (or min (setq min (point-min)))
2034 (or max (setq max (point-max)))
499d5216 2035 (let (face head-face here-face b e bb tag qtag err b1 e1 argument
c07a80fd 2036 (cperl-pod-here-fontify (eval cperl-pod-here-fontify))
2037 (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
9ea28adb 2038 (modified (buffer-modified-p))
499d5216 2039 (after-change-functions nil)
2040 (search
2041 (concat
2042 "\\(\\`\n?\\|\n\n\\)="
2043 "\\|"
2044 ;; One extra () before this:
2045 "<<\\(\\([\"'`]\\)\\([^\"'`\n]*\\)\\3\\|\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)\\)"
2046 "\\|"
2047 ;; 1+5 extra () before this:
2048 "^[ \t]*format[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$")))
c07a80fd 2049 (unwind-protect
2050 (progn
2051 (save-excursion
499d5216 2052 (message "Scanning for pods, formats and here-docs...")
c07a80fd 2053 (if cperl-pod-here-fontify
499d5216 2054 ;; We had evals here, do not know why...
2055 (setq face cperl-pod-face
2056 head-face cperl-pod-head-face
2057 here-face cperl-here-face))
c07a80fd 2058 (remove-text-properties min max '(syntax-type t))
2059 ;; Need to remove face as well...
2060 (goto-char min)
499d5216 2061 (while (re-search-forward search max t)
2062 (cond
2063 ((match-beginning 1) ; POD section
2064 ;; "\\(\\`\n?\\|\n\n\\)="
2065 (if (looking-at "\n*cut\\>")
2066 (progn
2067 (message "=cut is not preceeded by a pod section")
2068 (setq err (point)))
c07a80fd 2069 (beginning-of-line)
499d5216 2070
2071 (setq b (point) bb b)
2072 (or (re-search-forward "\n\n=cut\\>" max 'toend)
2073 (message "Cannot find the end of a pod section"))
2074 (beginning-of-line 3)
2075 (setq e (point))
2076 (put-text-property b e 'in-pod t)
2077 (goto-char b)
2078 (while (re-search-forward "\n\n[ \t]" e t)
2079 (beginning-of-line)
2080 (put-text-property b (point) 'syntax-type 'pod)
2081 (cperl-put-do-not-fontify b (point))
2082 ;;(put-text-property (max (point-min) (1- b))
2083 ;; (point) cperl-do-not-fontify t)
2084 (if cperl-pod-here-fontify (put-text-property b (point) 'face face))
2085 (re-search-forward "\n\n[^ \t\f\n]" e 'toend)
2086 (beginning-of-line)
2087 (setq b (point)))
2088 (put-text-property (point) e 'syntax-type 'pod)
2089 (cperl-put-do-not-fontify (point) e)
2090 ;;(put-text-property (max (point-min) (1- (point)))
2091 ;; e cperl-do-not-fontify t)
2092 (if cperl-pod-here-fontify
2093 (progn (put-text-property (point) e 'face face)
2094 (goto-char bb)
2095 (if (looking-at
2096 "=[a-zA-Z0-9]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$")
2097 (put-text-property
2098 (match-beginning 1) (match-end 1)
2099 'face head-face))
2100 (while (re-search-forward
2101 ;; One paragraph
2102 "\n\n=[a-zA-Z0-9]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$"
2103 e 'toend)
9ea28adb 2104 (put-text-property
2105 (match-beginning 1) (match-end 1)
499d5216 2106 'face head-face))))
2107 (goto-char e)))
2108 ;; 1 () ahead
2109 ;; "<<\\(\\([\"'`]\\)\\([^\"'`\n]*\\)\\3\\|\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)\\)"
2110 ((match-beginning 2) ; 1 + 1
2111 (if (match-beginning 5) ;4 + 1
2112 (setq b1 (match-beginning 5) ; 4 + 1
2113 e1 (match-end 5)) ; 4 + 1
2114 (setq b1 (match-beginning 4) ; 3 + 1
2115 e1 (match-end 4))) ; 3 + 1
2116 (setq tag (buffer-substring b1 e1)
2117 qtag (regexp-quote tag))
2118 (cond (cperl-pod-here-fontify
2119 (put-text-property b1 e1 'face font-lock-reference-face)
2120 (cperl-put-do-not-fontify b1 e1)))
c07a80fd 2121 (forward-line)
2122 (setq b (point))
499d5216 2123 (cond ((re-search-forward (concat "^" qtag "$") max 'toend)
c07a80fd 2124 (if cperl-pod-here-fontify
2125 (progn
2126 (put-text-property (match-beginning 0) (match-end 0)
2127 'face font-lock-reference-face)
9ea28adb 2128 (cperl-put-do-not-fontify b (match-end 0))
2129 ;;(put-text-property (max (point-min) (1- b))
2130 ;; (min (point-max)
2131 ;; (1+ (match-end 0)))
2132 ;; cperl-do-not-fontify t)
c07a80fd 2133 (put-text-property b (match-beginning 0)
29043b61 2134 'face here-face)))
c07a80fd 2135 (put-text-property b (match-beginning 0)
499d5216 2136 'syntax-type 'here-doc)
2137 (cperl-put-do-not-fontify b (match-beginning 0)))
2138 (t (message "End of here-document `%s' not found." tag))))
2139 (t
2140 ;; 1+5=6 extra () before this:
2141 ;; "^[ \t]*format[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$")))
2142 (setq b (point)
2143 name (if (match-beginning 7) ; 6 + 1
2144 (buffer-substring (match-beginning 7) ; 6 + 1
2145 (match-end 7)) ; 6 + 1
2146 ""))
2147 (setq argument nil)
2148 (if cperl-pod-here-fontify
2149 (while (and (eq (forward-line) 0)
2150 (not (looking-at "^[.;]$")))
2151 (cond
2152 ((looking-at "^#")) ; Skip comments
2153 ((and argument ; Skip argument multi-lines
2154 (looking-at "^[ \t]*{"))
2155 (forward-sexp 1)
2156 (setq argument nil))
2157 (argument ; Skip argument lines
2158 (setq argument nil))
2159 (t ; Format line
2160 (setq b1 (point))
2161 (setq argument (looking-at "^[^\n]*[@^]"))
2162 (end-of-line)
2163 (put-text-property b1 (point)
2164 'face font-lock-string-face)
2165 (cperl-put-do-not-fontify b1 (point)))))
2166 (re-search-forward (concat "^[.;]$") max 'toend))
2167 (beginning-of-line)
2168 (if (looking-at "^[.;]$")
2169 (progn
2170 (put-text-property (point) (+ (point) 2)
2171 'face font-lock-string-face)
2172 (cperl-put-do-not-fontify (point) (+ (point) 2)))
2173 (message "End of format `%s' not found." name))
2174 (forward-line)
2175 (put-text-property b (point) 'syntax-type 'format)
2176;;; (cond ((re-search-forward (concat "^[.;]$") max 'toend)
2177;;; (if cperl-pod-here-fontify
2178;;; (progn
2179;;; (put-text-property b (match-end 0)
2180;;; 'face font-lock-string-face)
2181;;; (cperl-put-do-not-fontify b (match-end 0))))
2182;;; (put-text-property b (match-end 0)
2183;;; 'syntax-type 'format)
2184;;; (cperl-put-do-not-fontify b (match-beginning 0)))
2185;;; (t (message "End of format `%s' not found." name)))
2186 )))
2187;;; (while (re-search-forward "\\(\\`\n?\\|\n\n\\)=" max t)
2188;;; (if (looking-at "\n*cut\\>")
2189;;; (progn
2190;;; (message "=cut is not preceeded by a pod section")
2191;;; (setq err (point)))
2192;;; (beginning-of-line)
2193
2194;;; (setq b (point) bb b)
2195;;; (or (re-search-forward "\n\n=cut\\>" max 'toend)
2196;;; (message "Cannot find the end of a pod section"))
2197;;; (beginning-of-line 3)
2198;;; (setq e (point))
2199;;; (put-text-property b e 'in-pod t)
2200;;; (goto-char b)
2201;;; (while (re-search-forward "\n\n[ \t]" e t)
2202;;; (beginning-of-line)
2203;;; (put-text-property b (point) 'syntax-type 'pod)
2204;;; (cperl-put-do-not-fontify b (point))
2205;;; ;;(put-text-property (max (point-min) (1- b))
2206;;; ;; (point) cperl-do-not-fontify t)
2207;;; (if cperl-pod-here-fontify (put-text-property b (point) 'face face))
2208;;; (re-search-forward "\n\n[^ \t\f\n]" e 'toend)
2209;;; (beginning-of-line)
2210;;; (setq b (point)))
2211;;; (put-text-property (point) e 'syntax-type 'pod)
2212;;; (cperl-put-do-not-fontify (point) e)
2213;;; ;;(put-text-property (max (point-min) (1- (point)))
2214;;; ;; e cperl-do-not-fontify t)
2215;;; (if cperl-pod-here-fontify
2216;;; (progn (put-text-property (point) e 'face face)
2217;;; (goto-char bb)
2218;;; (if (looking-at
2219;;; "=[a-zA-Z0-9]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$")
2220;;; (put-text-property
2221;;; (match-beginning 1) (match-end 1)
2222;;; 'face head-face))
2223;;; (while (re-search-forward
2224;;; ;; One paragraph
2225;;; "\n\n=[a-zA-Z0-9]+\\>[ \t]*\\(\\(\n?[^\n]\\)+\\)$"
2226;;; e 'toend)
2227;;; (put-text-property
2228;;; (match-beginning 1) (match-end 1)
2229;;; 'face head-face))))
2230;;; (goto-char e)))
2231;;; (goto-char min)
2232;;; (while (re-search-forward
2233;;; ;; We exclude \n to avoid misrecognition inside quotes.
2234;;; "<<\\(\\([\"'`]\\)\\([^\"'`\n]*\\)\\2\\|\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)\\)"
2235;;; max t)
2236;;; (if (match-beginning 4)
2237;;; (setq b1 (match-beginning 4)
2238;;; e1 (match-end 4))
2239;;; (setq b1 (match-beginning 3)
2240;;; e1 (match-end 3)))
2241;;; (setq tag (buffer-substring b1 e1)
2242;;; qtag (regexp-quote tag))
2243;;; (cond (cperl-pod-here-fontify
2244;;; (put-text-property b1 e1 'face font-lock-reference-face)
2245;;; (cperl-put-do-not-fontify b1 e1)))
2246;;; (forward-line)
2247;;; (setq b (point))
2248;;; (cond ((re-search-forward (concat "^" qtag "$") max 'toend)
2249;;; (if cperl-pod-here-fontify
2250;;; (progn
2251;;; (put-text-property (match-beginning 0) (match-end 0)
2252;;; 'face font-lock-reference-face)
2253;;; (cperl-put-do-not-fontify b (match-end 0))
2254;;; ;;(put-text-property (max (point-min) (1- b))
2255;;; ;; (min (point-max)
2256;;; ;; (1+ (match-end 0)))
2257;;; ;; cperl-do-not-fontify t)
2258;;; (put-text-property b (match-beginning 0)
2259;;; 'face here-face)))
2260;;; (put-text-property b (match-beginning 0)
2261;;; 'syntax-type 'here-doc)
2262;;; (cperl-put-do-not-fontify b (match-beginning 0)))
2263;;; (t (message "End of here-document `%s' not found." tag))))
2264;;; (goto-char min)
2265;;; (while (re-search-forward
2266;;; "^[ \t]*format[ \t]*\\(\\([a-zA-Z0-9_]+[ \t]*\\)?\\)=[ \t]*$"
2267;;; max t)
2268;;; (setq b (point)
2269;;; name (buffer-substring (match-beginning 1)
2270;;; (match-end 1)))
2271;;; (cond ((re-search-forward (concat "^[.;]$") max 'toend)
2272;;; (if cperl-pod-here-fontify
2273;;; (progn
2274;;; (put-text-property b (match-end 0)
2275;;; 'face font-lock-string-face)
2276;;; (cperl-put-do-not-fontify b (match-end 0))))
2277;;; (put-text-property b (match-end 0)
2278;;; 'syntax-type 'format)
2279;;; (cperl-put-do-not-fontify b (match-beginning 0)))
2280;;; (t (message "End of format `%s' not found." name))))
2281)
c07a80fd 2282 (if err (goto-char err)
499d5216 2283 (message "Scan for pods, formats and here-docs completed.")))
c07a80fd 2284 (and (buffer-modified-p)
2285 (not modified)
2286 (set-buffer-modified-p nil)))))
2287
2288(defun cperl-backward-to-noncomment (lim)
2289 ;; Stops at lim or after non-whitespace that is not in comment
4633a7c4 2290 (let (stop p)
2291 (while (and (not stop) (> (point) (or lim 1)))
2292 (skip-chars-backward " \t\n\f" lim)
2293 (setq p (point))
2294 (beginning-of-line)
2295 (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip
2296 ;; Else
2297 (cperl-to-comment-or-eol)
2298 (skip-chars-backward " \t")
2299 (if (< p (point)) (goto-char p))
2300 (setq stop t)))))
2301
c07a80fd 2302(defun cperl-after-expr-p (&optional lim chars test)
4633a7c4 2303 "Returns true if the position is good for start of expression.
2304TEST is the expression to evaluate at the found position. If absent,
2305CHARS is a string that contains good characters to have before us."
2306 (let (stop p)
2307 (save-excursion
2308 (while (and (not stop) (> (point) (or lim 1)))
2309 (skip-chars-backward " \t\n\f" lim)
2310 (setq p (point))
2311 (beginning-of-line)
2312 (if (looking-at "^[ \t]*\\(#\\|$\\)") nil ; Only comment, skip
2313 ;; Else: last iteration (What to do with labels?)
2314 (cperl-to-comment-or-eol)
2315 (skip-chars-backward " \t")
2316 (if (< p (point)) (goto-char p))
2317 (setq stop t)))
2318 (or (bobp)
2319 (progn
2320 (backward-char 1)
2321 (if test (eval test)
2322 (memq (following-char) (append (or chars "{};") nil))))))))
2323
2324(defun cperl-backward-to-start-of-continued-exp (lim)
c07a80fd 2325 (if (memq (preceding-char) (append ")]}\"'`" nil))
4633a7c4 2326 (forward-sexp -1))
2327 (beginning-of-line)
2328 (if (<= (point) lim)
2329 (goto-char (1+ lim)))
2330 (skip-chars-forward " \t"))
2331
4633a7c4 2332\f
2333(defvar innerloop-done nil)
2334(defvar last-depth nil)
2335
2336(defun cperl-indent-exp ()
2337 "Simple variant of indentation of continued-sexp.
2338Should be slow. Will not indent comment if it starts at `comment-indent'
2339or looks like continuation of the comment on the previous line."
2340 (interactive)
2341 (save-excursion
2342 (let ((tmp-end (progn (end-of-line) (point))) top done)
2343 (save-excursion
2344 (while (null done)
2345 (beginning-of-line)
2346 (setq top (point))
2347 (while (= (nth 0 (parse-partial-sexp (point) tmp-end
2348 -1)) -1)
2349 (setq top (point))) ; Get the outermost parenths in line
2350 (goto-char top)
2351 (while (< (point) tmp-end)
2352 (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol
2353 (or (eolp) (forward-sexp 1)))
2354 (if (> (point) tmp-end) (progn (end-of-line) (setq tmp-end (point)))
2355 (setq done t)))
2356 (goto-char tmp-end)
2357 (setq tmp-end (point-marker)))
2358 (cperl-indent-region (point) tmp-end))))
2359
2360(defun cperl-indent-region (start end)
2361 "Simple variant of indentation of region in CPerl mode.
2362Should be slow. Will not indent comment if it starts at `comment-indent'
2363or looks like continuation of the comment on the previous line.
2364Indents all the lines whose first character is between START and END
2365inclusive."
2366 (interactive "r")
2367 (save-excursion
2368 (let (st comm indent-info old-comm-indent new-comm-indent
2369 (pm 0) (imenu-scanning-message "Indenting... (%3d%%)"))
2370 (goto-char start)
2371 (setq old-comm-indent (and (cperl-to-comment-or-eol)
2372 (current-column))
2373 new-comm-indent old-comm-indent)
2374 (goto-char start)
2375 (or (bolp) (beginning-of-line 2))
2376 (or (fboundp 'imenu-progress-message)
2377 (message "Indenting... For feedback load `imenu'..."))
2378 (while (and (<= (point) end) (not (eobp))) ; bol to check start
2379 (and (fboundp 'imenu-progress-message)
2380 (imenu-progress-message
2381 pm (/ (* 100 (- (point) start)) (- end start -1))))
2382 (setq st (point)
2383 indent-info nil
2384 ) ; Believe indentation of the current
2385 (if (and (setq comm (looking-at "[ \t]*#"))
2386 (or (eq (current-indentation) (or old-comm-indent
2387 comment-column))
2388 (setq old-comm-indent nil)))
2389 (if (and old-comm-indent
2390 (= (current-indentation) old-comm-indent))
2391 (let ((comment-column new-comm-indent))
2392 (indent-for-comment)))
2393 (progn
2394 (cperl-indent-line 'indent-info)
2395 (or comm
2396 (progn
2397 (if (setq old-comm-indent (and (cperl-to-comment-or-eol)
2398 (current-column)))
2399 (progn (indent-for-comment)
2400 (skip-chars-backward " \t")
2401 (skip-chars-backward "#")
2402 (setq new-comm-indent (current-column))))))))
2403 (beginning-of-line 2))
2404 (if (fboundp 'imenu-progress-message)
2405 (imenu-progress-message pm 100)
2406 (message nil)))))
2407
2408(defun cperl-slash-is-regexp (&optional pos)
2409 (save-excursion
2410 (goto-char (if pos pos (1- (point))))
2411 (and
2412 (not (memq (get-text-property (point) 'face)
2413 '(font-lock-string-face font-lock-comment-face)))
c07a80fd 2414 (cperl-after-expr-p nil nil '
4633a7c4 2415 (or (looking-at "[^]a-zA-Z0-9_)}]")
2416 (eq (get-text-property (point) 'face)
2417 'font-lock-keyword-face))))))
2418
2419;; Stolen from lisp-mode with a lot of improvements
2420
2421(defun cperl-fill-paragraph (&optional justify iteration)
2422 "Like \\[fill-paragraph], but handle CPerl comments.
2423If any of the current line is a comment, fill the comment or the
2424block of it that point is in, preserving the comment's initial
2425indentation and initial hashes. Behaves usually outside of comment."
2426 (interactive "P")
2427 (let (
2428 ;; Non-nil if the current line contains a comment.
2429 has-comment
2430
2431 ;; If has-comment, the appropriate fill-prefix for the comment.
2432 comment-fill-prefix
2433 ;; Line that contains code and comment (or nil)
2434 start
2435 c spaces len dc (comment-column comment-column))
2436 ;; Figure out what kind of comment we are looking at.
2437 (save-excursion
2438 (beginning-of-line)
2439 (cond
2440
2441 ;; A line with nothing but a comment on it?
2442 ((looking-at "[ \t]*#[# \t]*")
2443 (setq has-comment t
2444 comment-fill-prefix (buffer-substring (match-beginning 0)
2445 (match-end 0))))
2446
2447 ;; A line with some code, followed by a comment? Remember that the
2448 ;; semi which starts the comment shouldn't be part of a string or
2449 ;; character.
2450 ((cperl-to-comment-or-eol)
2451 (setq has-comment t)
2452 (looking-at "#+[ \t]*")
2453 (setq start (point) c (current-column)
2454 comment-fill-prefix
2455 (concat (make-string (current-column) ?\ )
2456 (buffer-substring (match-beginning 0) (match-end 0)))
2457 spaces (progn (skip-chars-backward " \t")
2458 (buffer-substring (point) start))
2459 dc (- c (current-column)) len (- start (point))
2460 start (point-marker))
2461 (delete-char len)
2462 (insert (make-string dc ?-)))))
2463 (if (not has-comment)
2464 (fill-paragraph justify) ; Do the usual thing outside of comment
2465 ;; Narrow to include only the comment, and then fill the region.
2466 (save-restriction
2467 (narrow-to-region
2468 ;; Find the first line we should include in the region to fill.
2469 (if start (progn (beginning-of-line) (point))
2470 (save-excursion
2471 (while (and (zerop (forward-line -1))
c07a80fd 2472 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
4633a7c4 2473 ;; We may have gone to far. Go forward again.
c07a80fd 2474 (or (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")
4633a7c4 2475 (forward-line 1))
2476 (point)))
2477 ;; Find the beginning of the first line past the region to fill.
2478 (save-excursion
2479 (while (progn (forward-line 1)
c07a80fd 2480 (looking-at "^[ \t]*#+[ \t]*[^ \t\n#]")))
4633a7c4 2481 (point)))
2482 ;; Remove existing hashes
2483 (goto-char (point-min))
2484 (while (progn (forward-line 1) (< (point) (point-max)))
2485 (skip-chars-forward " \t")
2486 (and (looking-at "#+")
2487 (delete-char (- (match-end 0) (match-beginning 0)))))
2488
2489 ;; Lines with only hashes on them can be paragraph boundaries.
2490 (let ((paragraph-start (concat paragraph-start "\\|^[ \t#]*$"))
2491 (paragraph-separate (concat paragraph-start "\\|^[ \t#]*$"))
2492 (fill-prefix comment-fill-prefix))
2493 (fill-paragraph justify)))
2494 (if (and start)
2495 (progn
2496 (goto-char start)
2497 (if (> dc 0)
2498 (progn (delete-char dc) (insert spaces)))
2499 (if (or (= (current-column) c) iteration) nil
2500 (setq comment-column c)
2501 (indent-for-comment)
2502 ;; Repeat once more, flagging as iteration
2503 (cperl-fill-paragraph justify t)))))))
2504
2505(defun cperl-do-auto-fill ()
2506 ;; Break out if the line is short enough
2507 (if (> (save-excursion
2508 (end-of-line)
2509 (current-column))
2510 fill-column)
2511 (let ((c (save-excursion (beginning-of-line)
2512 (cperl-to-comment-or-eol) (point)))
2513 (s (memq (following-char) '(?\ ?\t))) marker)
2514 (if (>= c (point)) nil
2515 (setq marker (point-marker))
2516 (cperl-fill-paragraph)
2517 (goto-char marker)
2518 ;; Is not enough, sometimes marker is a start of line
2519 (if (bolp) (progn (re-search-forward "#+[ \t]*")
2520 (goto-char (match-end 0))))
2521 ;; Following space could have gone:
2522 (if (or (not s) (memq (following-char) '(?\ ?\t))) nil
2523 (insert " ")
2524 (backward-char 1))
2525 ;; Previous space could have gone:
2526 (or (memq (preceding-char) '(?\ ?\t)) (insert " "))))))
2527
2528(defvar imenu-example--function-name-regexp-perl
c07a80fd 2529 "^\\([ \t]*\\(sub\\|package\\)[ \t\n]+\\([a-zA-Z_0-9:']+\\)[ \t]*\\|=head\\([12]\\)[ \t]+\\([^\n]+\\)$\\)")
4633a7c4 2530
9ea28adb 2531(defun cperl-imenu-addback (lst &optional isback name)
2532 ;; We suppose that the lst is a DAG, unless the first element only
2533 ;; loops back, and ISBACK is set. Thus this function cannot be
2534 ;; applied twice without ISBACK set.
2535 (cond ((not cperl-imenu-addback) lst)
2536 (t
2537 (or name
2538 (setq name "+++BACK+++"))
2539 (mapcar (function (lambda (elt)
2540 (if (and (listp elt) (listp (cdr elt)))
2541 (progn
2542 ;; In the other order it goes up
2543 ;; one level only ;-(
2544 (setcdr elt (cons (cons name lst)
2545 (cdr elt)))
2546 (cperl-imenu-addback (cdr elt) t name)
2547 ))))
2548 (if isback (cdr lst) lst))
2549 lst)))
2550
4633a7c4 2551(defun imenu-example--create-perl-index (&optional regexp)
2552 (require 'cl)
c07a80fd 2553 (let ((index-alist '()) (index-pack-alist '()) (index-pod-alist '())
2554 (index-unsorted-alist '()) (i-s-f (default-value 'imenu-sort-function))
9ea28adb 2555 (index-meth-alist '()) meth
c07a80fd 2556 packages ends-ranges p
2557 (prev-pos 0) char fchar index index1 name (end-range 0) package)
4633a7c4 2558 (goto-char (point-min))
2559 (imenu-progress-message prev-pos 0)
2560 ;; Search for the function
9ea28adb 2561 (progn ;;save-match-data
4633a7c4 2562 (while (re-search-forward
2563 (or regexp imenu-example--function-name-regexp-perl)
2564 nil t)
2565 (imenu-progress-message prev-pos)
2566 ;;(backward-up-list 1)
c07a80fd 2567 (cond
2568 ((match-beginning 2) ; package or sub
2569 (save-excursion
2570 (goto-char (match-beginning 2))
2571 (setq fchar (following-char))
2572 )
9ea28adb 2573 (setq char (following-char) meth nil)
c07a80fd 2574 (setq p (point))
2575 (while (and ends-ranges (>= p (car ends-ranges)))
2576 ;; delete obsolete entries
2577 (setq ends-ranges (cdr ends-ranges) packages (cdr packages)))
2578 (setq package (or (car packages) "")
2579 end-range (or (car ends-ranges) 0))
2580 (if (eq fchar ?p)
9ea28adb 2581 (setq name (buffer-substring (match-beginning 3) (match-end 3))
499d5216 2582 name (progn
2583 (set-text-properties 0 (length name) nil name)
2584 name)
9ea28adb 2585 package (concat name "::")
2586 name (concat "package " name)
2587 end-range
2588 (save-excursion
2589 (parse-partial-sexp (point) (point-max) -1) (point))
2590 ends-ranges (cons end-range ends-ranges)
2591 packages (cons package packages)))
c07a80fd 2592 ;; )
2593 ;; Skip this function name if it is a prototype declaration.
2594 (if (and (eq fchar ?s) (eq char ?\;)) nil
9ea28adb 2595 (setq index (imenu-example--name-and-position))
c07a80fd 2596 (if (eq fchar ?p) nil
2597 (setq name (buffer-substring (match-beginning 3) (match-end 3)))
499d5216 2598 (set-text-properties 0 (length name) nil name)
9ea28adb 2599 (cond ((string-match "[:']" name)
2600 (setq meth t))
2601 ((> p end-range) nil)
2602 (t
2603 (setq name (concat package name) meth t))))
c07a80fd 2604 (setcar index name)
2605 (if (eq fchar ?p)
2606 (push index index-pack-alist)
2607 (push index index-alist))
9ea28adb 2608 (if meth (push index index-meth-alist))
c07a80fd 2609 (push index index-unsorted-alist)))
2610 (t ; Pod section
2611 ;; (beginning-of-line)
2612 (setq index (imenu-example--name-and-position)
2613 name (buffer-substring (match-beginning 5) (match-end 5)))
499d5216 2614 (set-text-properties 0 (length name) nil name)
c07a80fd 2615 (if (eq (char-after (match-beginning 4)) ?2)
2616 (setq name (concat " " name)))
4633a7c4 2617 (setcar index name)
c07a80fd 2618 (setq index1 (cons (concat "=" name) (cdr index)))
2619 (push index index-pod-alist)
2620 (push index1 index-unsorted-alist)))))
4633a7c4 2621 (imenu-progress-message prev-pos 100)
c07a80fd 2622 (setq index-alist
2623 (if (default-value 'imenu-sort-function)
2624 (sort index-alist (default-value 'imenu-sort-function))
2625 (nreverse index-alist)))
2626 (and index-pod-alist
9ea28adb 2627 (push (cons "+POD headers+..."
c07a80fd 2628 (nreverse index-pod-alist))
2629 index-alist))
9ea28adb 2630 (and (or index-pack-alist index-meth-alist)
2631 (let ((lst index-pack-alist) hier-list pack elt group name)
2632 ;; Remove "package ", reverse and uniquify.
2633 (while lst
2634 (setq elt (car lst) lst (cdr lst) name (substring (car elt) 8))
2635 (if (assoc name hier-list) nil
2636 (setq hier-list (cons (cons name (cdr elt)) hier-list))))
2637 (setq lst index-meth-alist)
2638 (while lst
2639 (setq elt (car lst) lst (cdr lst))
499d5216 2640 (cond ((string-match "\\(::\\|'\\)[_a-zA-Z0-9]+$" (car elt))
2641 (setq pack (substring (car elt) 0 (match-beginning 0)))
2642 (if (setq group (assoc pack hier-list))
2643 (if (listp (cdr group))
2644 ;; Have some functions already
2645 (setcdr group
2646 (cons (cons (substring
2647 (car elt)
2648 (+ 2 (match-beginning 0)))
2649 (cdr elt))
2650 (cdr group)))
2651 (setcdr group (list (cons (substring
2652 (car elt)
2653 (+ 2 (match-beginning 0)))
2654 (cdr elt)))))
2655 (setq hier-list
2656 (cons (cons pack
2657 (list (cons (substring
2658 (car elt)
2659 (+ 2 (match-beginning 0)))
2660 (cdr elt))))
2661 hier-list))))))
9ea28adb 2662 (push (cons "+Hierarchy+..."
2663 hier-list)
2664 index-alist)))
4633a7c4 2665 (and index-pack-alist
9ea28adb 2666 (push (cons "+Packages+..."
c07a80fd 2667 (nreverse index-pack-alist))
2668 index-alist))
2669 (and (or index-pack-alist index-pod-alist
2670 (default-value 'imenu-sort-function))
2671 index-unsorted-alist
9ea28adb 2672 (push (cons "+Unsorted List+..."
c07a80fd 2673 (nreverse index-unsorted-alist))
4633a7c4 2674 index-alist))
9ea28adb 2675 (cperl-imenu-addback index-alist)))
4633a7c4 2676
2677(defvar cperl-compilation-error-regexp-alist
2678 ;; This look like a paranoiac regexp: could anybody find a better one? (which WORK).
2679 '(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\., \n]"
2680 2 3))
2681 "Alist that specifies how to match errors in perl output.")
2682
2683(if (fboundp 'eval-after-load)
2684 (eval-after-load
2685 "mode-compile"
2686 '(setq perl-compilation-error-regexp-alist
2687 cperl-compilation-error-regexp-alist)))
2688
2689
2690(defvar cperl-faces-init nil)
2691
2692(defun cperl-windowed-init ()
2693 "Initialization under windowed version."
2694 (add-hook 'font-lock-mode-hook
2695 (function
2696 (lambda ()
2697 (if (or
2698 (eq major-mode 'perl-mode)
2699 (eq major-mode 'cperl-mode))
2700 (progn
c07a80fd 2701 (or cperl-faces-init (cperl-init-faces))))))))
2702
2703(defvar perl-font-lock-keywords-1 nil
2704 "Additional expressions to highlight in Perl mode. Minimal set.")
2705(defvar perl-font-lock-keywords nil
2706 "Additional expressions to highlight in Perl mode. Default set.")
2707(defvar perl-font-lock-keywords-2 nil
2708 "Additional expressions to highlight in Perl mode. Maximal set")
4633a7c4 2709
2710(defun cperl-init-faces ()
2711 (condition-case nil
2712 (progn
2713 (require 'font-lock)
c07a80fd 2714 (and (fboundp 'font-lock-fontify-anchored-keywords)
2715 (featurep 'font-lock-extra)
2716 (message "You have an obsolete package `font-lock-extra'. Install `choose-color'."))
2717 (let (t-font-lock-keywords t-font-lock-keywords-1 font-lock-anchored)
4633a7c4 2718 ;;(defvar cperl-font-lock-enhanced nil
2719 ;; "Set to be non-nil if font-lock allows active highlights.")
c07a80fd 2720 (if (fboundp 'font-lock-fontify-anchored-keywords)
2721 (setq font-lock-anchored t))
4633a7c4 2722 (setq
2723 t-font-lock-keywords
2724 (list
2725 (cons
2726 (concat
2727 "\\(^\\|[^$@%&\\]\\)\\<\\("
2728 (mapconcat
2729 'identity
2730 '("if" "until" "while" "elsif" "else" "unless" "for"
2731 "foreach" "continue" "exit" "die" "last" "goto" "next"
2732 "redo" "return" "local" "exec" "sub" "do" "dump" "use"
2733 "require" "package" "eval" "my" "BEGIN" "END")
2734 "\\|") ; Flow control
2735 "\\)\\>") 2) ; was "\\)[ \n\t;():,\|&]"
2736 ; In what follows we use `type' style
2737 ; for overwritable buildins
2738 (list
2739 (concat
2740 "\\(^\\|[^$@%&\\]\\)\\<\\("
2741 ;; "CORE" "__FILE__" "__LINE__" "abs" "accept" "alarm" "and" "atan2"
2742 ;; "bind" "binmode" "bless" "caller" "chdir" "chmod" "chown" "chr"
2743 ;; "chroot" "close" "closedir" "cmp" "connect" "continue" "cos"
2744 ;; "crypt" "dbmclose" "dbmopen" "die" "dump" "endgrent" "endhostent"
2745 ;; "endnetent" "endprotoent" "endpwent" "endservent" "eof" "eq" "exec"
2746 ;; "exit" "exp" "fcntl" "fileno" "flock" "fork" "formline" "ge" "getc"
2747 ;; "getgrent" "getgrgid" "getgrnam" "gethostbyaddr" "gethostbyname"
2748 ;; "gethostent" "getlogin" "getnetbyaddr" "getnetbyname" "getnetent"
2749 ;; "getpeername" "getpgrp" "getppid" "getpriority" "getprotobyname"
2750 ;; "getprotobynumber" "getprotoent" "getpwent" "getpwnam" "getpwuid"
2751 ;; "getservbyname" "getservbyport" "getservent" "getsockname"
2752 ;; "getsockopt" "glob" "gmtime" "gt" "hex" "index" "int" "ioctl"
2753 ;; "join" "kill" "lc" "lcfirst" "le" "length" "link" "listen"
2754 ;; "localtime" "log" "lstat" "lt" "mkdir" "msgctl" "msgget" "msgrcv"
2755 ;; "msgsnd" "ne" "not" "oct" "open" "opendir" "or" "ord" "pack" "pipe"
2756 ;; "quotemeta" "rand" "read" "readdir" "readline" "readlink"
2757 ;; "readpipe" "recv" "ref" "rename" "require" "reset" "reverse"
2758 ;; "rewinddir" "rindex" "rmdir" "seek" "seekdir" "select" "semctl"
2759 ;; "semget" "semop" "send" "setgrent" "sethostent" "setnetent"
2760 ;; "setpgrp" "setpriority" "setprotoent" "setpwent" "setservent"
2761 ;; "setsockopt" "shmctl" "shmget" "shmread" "shmwrite" "shutdown"
2762 ;; "sin" "sleep" "socket" "socketpair" "sprintf" "sqrt" "srand" "stat"
2763 ;; "substr" "symlink" "syscall" "sysread" "system" "syswrite" "tell"
2764 ;; "telldir" "time" "times" "truncate" "uc" "ucfirst" "umask" "unlink"
2765 ;; "unpack" "utime" "values" "vec" "wait" "waitpid" "wantarray" "warn"
2766 ;; "write" "x" "xor"
2767 "a\\(bs\\|ccept\\|tan2\\|larm\\|nd\\)\\|"
2768 "b\\(in\\(d\\|mode\\)\\|less\\)\\|"
2769 "c\\(h\\(r\\(\\|oot\\)\\|dir\\|mod\\|own\\)\\|aller\\|rypt\\|"
2770 "lose\\(\\|dir\\)\\|mp\\|o\\(s\\|n\\(tinue\\|nect\\)\\)\\)\\|"
2771 "CORE\\|d\\(ie\\|bm\\(close\\|open\\)\\|ump\\)\\|"
2772 "e\\(x\\(p\\|it\\|ec\\)\\|q\\|nd\\(p\\(rotoent\\|went\\)\\|"
2773 "hostent\\|servent\\|netent\\|grent\\)\\|of\\)\\|"
2774 "f\\(ileno\\|cntl\\|lock\\|or\\(k\\|mline\\)\\)\\|"
2775 "g\\(t\\|lob\\|mtime\\|e\\(\\|t\\(p\\(pid\\|r\\(iority\\|"
2776 "oto\\(byn\\(ame\\|umber\\)\\|ent\\)\\)\\|eername\\|w"
2777 "\\(uid\\|ent\\|nam\\)\\|grp\\)\\|host\\(by\\(addr\\|name\\)\\|"
2778 "ent\\)\\|s\\(erv\\(by\\(port\\|name\\)\\|ent\\)\\|"
2779 "ock\\(name\\|opt\\)\\)\\|c\\|login\\|net\\(by\\(addr\\|name\\)\\|"
2780 "ent\\)\\|gr\\(ent\\|nam\\|gid\\)\\)\\)\\)\\|"
2781 "hex\\|i\\(n\\(t\\|dex\\)\\|octl\\)\\|join\\|kill\\|"
2782 "l\\(i\\(sten\\|nk\\)\\|stat\\|c\\(\\|first\\)\\|t\\|e"
2783 "\\(\\|ngth\\)\\|o\\(caltime\\|g\\)\\)\\|m\\(sg\\(rcv\\|snd\\|"
2784 "ctl\\|get\\)\\|kdir\\)\\|n\\(e\\|ot\\)\\|o\\(pen\\(\\|dir\\)\\|"
2785 "r\\(\\|d\\)\\|ct\\)\\|p\\(ipe\\|ack\\)\\|quotemeta\\|"
2786 "r\\(index\\|and\\|mdir\\|e\\(quire\\|ad\\(pipe\\|\\|lin"
2787 "\\(k\\|e\\)\\|dir\\)\\|set\\|cv\\|verse\\|f\\|winddir\\|name"
2788 "\\)\\)\\|s\\(printf\\|qrt\\|rand\\|tat\\|ubstr\\|e\\(t\\(p\\(r"
2789 "\\(iority\\|otoent\\)\\|went\\|grp\\)\\|hostent\\|s\\(ervent\\|"
2790 "ockopt\\)\\|netent\\|grent\\)\\|ek\\(\\|dir\\)\\|lect\\|"
2791 "m\\(ctl\\|op\\|get\\)\\|nd\\)\\|h\\(utdown\\|m\\(read\\|ctl\\|"
2792 "write\\|get\\)\\)\\|y\\(s\\(read\\|call\\|tem\\|write\\)\\|"
2793 "mlink\\)\\|in\\|leep\\|ocket\\(pair\\|\\)\\)\\|t\\(runcate\\|"
2794 "ell\\(\\|dir\\)\\|ime\\(\\|s\\)\\)\\|u\\(c\\(\\|first\\)\\|"
2795 "time\\|mask\\|n\\(pack\\|link\\)\\)\\|v\\(alues\\|ec\\)\\|"
2796 "w\\(a\\(rn\\|it\\(pid\\|\\)\\|ntarray\\)\\|rite\\)\\|"
2797 "x\\(\\|or\\)\\|__\\(FILE__\\|LINE__\\)"
2798 "\\)\\>") 2 'font-lock-type-face)
2799 ;; In what follows we use `other' style
2800 ;; for nonoverwritable buildins
2801 ;; Somehow 's', 'm' are not autogenerated???
2802 (list
2803 (concat
2804 "\\(^\\|[^$@%&\\]\\)\\<\\("
2805 ;; "AUTOLOAD" "BEGIN" "DESTROY" "END" "__END__" "chomp" "chop"
2806 ;; "defined" "delete" "do" "each" "else" "elsif" "eval" "exists" "for"
2807 ;; "foreach" "format" "goto" "grep" "if" "keys" "last" "local" "map"
2808 ;; "my" "next" "no" "package" "pop" "pos" "print" "printf" "push" "q"
2809 ;; "qq" "qw" "qx" "redo" "return" "scalar" "shift" "sort" "splice"
2810 ;; "split" "study" "sub" "tie" "tr" "undef" "unless" "unshift" "untie"
2811 ;; "until" "use" "while" "y"
2812 "AUTOLOAD\\|BEGIN\\|cho\\(p\\|mp\\)\\|d\\(e\\(fined\\|lete\\)\\|"
2813 "o\\)\\|DESTROY\\|e\\(ach\\|val\\|xists\\|ls\\(e\\|if\\)\\)\\|"
2814 "END\\|for\\(\\|each\\|mat\\)\\|g\\(rep\\|oto\\)\\|if\\|keys\\|"
2815 "l\\(ast\\|ocal\\)\\|m\\(ap\\|y\\)\\|n\\(ext\\|o\\)\\|"
2816 "p\\(ackage\\|rint\\(\\|f\\)\\|ush\\|o\\(p\\|s\\)\\)\\|"
2817 "q\\(\\|q\\|w\\|x\\)\\|re\\(turn\\|do\\)\\|s\\(pli\\(ce\\|t\\)\\|"
2818 "calar\\|tudy\\|ub\\|hift\\|ort\\)\\|t\\(r\\|ie\\)\\|"
2819 "u\\(se\\|n\\(shift\\|ti\\(l\\|e\\)\\|def\\|less\\)\\)\\|"
2820 "while\\|y\\|__\\(END\\|DATA\\)__" ;__DATA__ added manually
2821 "\\|[sm]" ; Added manually
2822 "\\)\\>") 2 'font-lock-other-type-face)
2823 ;; (mapconcat 'identity
2824 ;; '("#endif" "#else" "#ifdef" "#ifndef" "#if"
2825 ;; "#include" "#define" "#undef")
2826 ;; "\\|")
2827 '("-[rwxoRWXOezsfdlpSbctugkTBMAC]\\>\\([ \t]+_\\>\\)?" 0
2828 font-lock-function-name-face) ; Not very good, triggers at "[a-z]"
c07a80fd 2829 '("\\<sub[ \t]+\\([^ \t{;]+\\)[ \t]*[{\n]" 1
4633a7c4 2830 font-lock-function-name-face)
c07a80fd 2831 '("\\<\\(package\\|require\\|use\\|import\\|no\\|bootstrap\\)[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t;]" ; require A if B;
4633a7c4 2832 2 font-lock-function-name-face)
499d5216 2833 '("^[ \t]*format[ \t]+\\([a-zA-z_][a-zA-z_0-9:]*\\)[ \t]*=[ \t]*$"
2834 1 font-lock-function-name-face)
c07a80fd 2835 (cond ((featurep 'font-lock-extra)
29043b61 2836 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 2837 (2 font-lock-string-face t)
2838 (0 '(restart 2 t)))) ; To highlight $a{bc}{ef}
2839 (font-lock-anchored
29043b61 2840 '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 2841 (2 font-lock-string-face t)
29043b61 2842 ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 2843 nil nil
2844 (1 font-lock-string-face t))))
29043b61 2845 (t '("\\([]}\\\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
c07a80fd 2846 2 font-lock-string-face t)))
29043b61 2847 '("[ \t{,(]\\(-?[a-zA-Z0-9_:]+\\)[ \t]*=>" 1
4633a7c4 2848 font-lock-string-face t)
2849 '("^[ \t]*\\([a-zA-Z0-9_]+[ \t]*:\\)[ \t]*\\($\\|{\\|\\<\\(until\\|while\\|for\\(each\\)?\\|do\\)\\>\\)" 1
2850 font-lock-reference-face) ; labels
2851 '("\\<\\(continue\\|next\\|last\\|redo\\|goto\\)\\>[ \t]+\\([a-zA-Z0-9_:]+\\)" ; labels as targets
2852 2 font-lock-reference-face)
c07a80fd 2853 (cond ((featurep 'font-lock-extra)
2854 '("^[ \t]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
2855 (3 font-lock-variable-name-face)
2856 (4 '(another 4 nil
2857 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)\\([ \t]*,\\)?"
2858 (1 font-lock-variable-name-face)
2859 (2 '(restart 2 nil) nil t)))
2860 nil t))) ; local variables, multiple
2861 (font-lock-anchored
2862 '("^[ \t]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
2863 (3 font-lock-variable-name-face)
2864 ("\\=[ \t]*,[ \t]*\\([$@%*][a-zA-Z0-9_:]+\\)"
2865 nil nil
2866 (1 font-lock-variable-name-face))))
2867 (t '("^[ \t]*\\(my\\|local\\)[ \t]*\\(([ \t]*\\)?\\([$@%*][a-zA-Z0-9_:]+\\)"
2868 3 font-lock-variable-name-face)))
4633a7c4 2869 '("\\<for\\(each\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*("
2870 2 font-lock-variable-name-face)))
c07a80fd 2871 (setq
2872 t-font-lock-keywords-1
2873 (and (fboundp 'turn-on-font-lock) ; Check for newer font-lock
2874 (not (cperl-xemacs-p)) ; not yet as of XEmacs 19.12
2875 '(("\\(\\([$@]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
2876 1
2877 (if (= (- (match-end 2) (match-beginning 2)) 1)
2878 (if (eq (char-after (match-beginning 3)) ?{)
2879 font-lock-other-emphasized-face
2880 font-lock-emphasized-face) ; arrays and hashes
2881 font-lock-variable-name-face) ; Just to put something
2882 t)
2883 ("\\(\\([@%]\\|\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
2884 (if (eq (char-after (match-beginning 2)) ?%)
2885 font-lock-other-emphasized-face
2886 font-lock-emphasized-face)
2887 t) ; arrays and hashes
2888 ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
4633a7c4 2889 ;;; Too much noise from \s* @s[ and friends
c07a80fd 2890 ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
2891 ;;(3 font-lock-function-name-face t t)
2892 ;;(4
2893 ;; (if (cperl-slash-is-regexp)
2894 ;; font-lock-function-name-face 'default) nil t))
2895 )))
2896 (setq perl-font-lock-keywords-1 t-font-lock-keywords
2897 perl-font-lock-keywords perl-font-lock-keywords-1
2898 perl-font-lock-keywords-2 (append
2899 t-font-lock-keywords
2900 t-font-lock-keywords-1)))
4633a7c4 2901 (if (fboundp 'ps-print-buffer) (cperl-ps-print-init))
c07a80fd 2902 (if (or (featurep 'choose-color) (featurep 'font-lock-extra))
4633a7c4 2903 (font-lock-require-faces
2904 (list
2905 ;; Color-light Color-dark Gray-light Gray-dark Mono
2906 (list 'font-lock-comment-face
2907 ["Firebrick" "OrangeRed" "DimGray" "Gray80"]
2908 nil
2909 [nil nil t t t]
2910 [nil nil t t t]
2911 nil)
2912 (list 'font-lock-string-face
2913 ["RosyBrown" "LightSalmon" "Gray50" "LightGray"]
2914 nil
2915 nil
2916 [nil nil t t t]
2917 nil)
2918 (list 'font-lock-keyword-face
2919 ["Purple" "LightSteelBlue" "DimGray" "Gray90"]
2920 nil
2921 [nil nil t t t]
2922 nil
2923 nil)
2924 (list 'font-lock-function-name-face
2925 (vector
2926 "Blue" "LightSkyBlue" "Gray50" "LightGray"
2927 (cdr (assq 'background-color ; if mono
2928 (frame-parameters))))
2929 (vector
2930 nil nil nil nil
2931 (cdr (assq 'foreground-color ; if mono
2932 (frame-parameters))))
2933 [nil nil t t t]
2934 nil
2935 nil)
2936 (list 'font-lock-variable-name-face
2937 ["DarkGoldenrod" "LightGoldenrod" "DimGray" "Gray90"]
2938 nil
2939 [nil nil t t t]
2940 [nil nil t t t]
2941 nil)
2942 (list 'font-lock-type-face
2943 ["DarkOliveGreen" "PaleGreen" "DimGray" "Gray80"]
2944 nil
2945 [nil nil t t t]
2946 nil
2947 [nil nil t t t]
2948 )
2949 (list 'font-lock-reference-face
2950 ["CadetBlue" "Aquamarine" "Gray50" "LightGray"]
2951 nil
2952 [nil nil t t t]
2953 nil
2954 [nil nil t t t]
2955 )
2956 (list 'font-lock-other-type-face
2957 ["chartreuse3" ("orchid1" "orange")
2958 nil "Gray80"]
2959 [nil nil "gray90"]
2960 [nil nil nil t t]
2961 [nil nil t t]
2962 [nil nil t t t]
2963 )
2964 (list 'font-lock-emphasized-face
2965 ["blue" "yellow" nil "Gray80"]
2966 ["lightyellow2" ("navy" "os2blue" "darkgreen")
2967 "gray90"]
2968 t
2969 nil
2970 nil)
2971 (list 'font-lock-other-emphasized-face
2972 ["red" "red" nil "Gray80"]
2973 ["lightyellow2" ("navy" "os2blue" "darkgreen")
2974 "gray90"]
2975 t
2976 t
2977 nil)))
2978 (defvar cperl-guessed-background nil
2979 "Display characteristics as guessed by cperl.")
2980 (or (fboundp 'x-color-defined-p)
2981 (defalias 'x-color-defined-p
2982 (cond ((fboundp 'color-defined-p) 'color-defined-p)
2983 ;; XEmacs >= 19.12
2984 ((fboundp 'valid-color-name-p) 'valid-color-name-p)
2985 ;; XEmacs 19.11
2986 (t 'x-valid-color-name-p))))
2987 (defvar font-lock-reference-face 'font-lock-reference-face)
2988 (defvar font-lock-variable-name-face 'font-lock-variable-name-face)
2989 (or (boundp 'font-lock-type-face)
2990 (defconst font-lock-type-face
2991 'font-lock-type-face
2992 "Face to use for data types.")
2993 )
2994 (or (boundp 'font-lock-other-type-face)
2995 (defconst font-lock-other-type-face
2996 'font-lock-other-type-face
2997 "Face to use for data types from another group.")
2998 )
2999 (if (not (cperl-xemacs-p)) nil
3000 (or (boundp 'font-lock-comment-face)
3001 (defconst font-lock-comment-face
3002 'font-lock-comment-face
3003 "Face to use for comments.")
3004 )
3005 (or (boundp 'font-lock-keyword-face)
3006 (defconst font-lock-keyword-face
3007 'font-lock-keyword-face
3008 "Face to use for keywords.")
3009 )
3010 (or (boundp 'font-lock-function-name-face)
3011 (defconst font-lock-function-name-face
3012 'font-lock-function-name-face
3013 "Face to use for function names.")
3014 )
3015 )
3016 ;;(if (featurep 'font-lock)
3017 (if (face-equal font-lock-type-face font-lock-comment-face)
3018 (defconst font-lock-type-face
3019 'font-lock-type-face
3020 "Face to use for basic data types.")
3021 )
3022;;; (if (fboundp 'eval-after-load)
3023;;; (eval-after-load "font-lock"
3024;;; '(if (face-equal font-lock-type-face
3025;;; font-lock-comment-face)
3026;;; (defconst font-lock-type-face
3027;;; 'font-lock-type-face
3028;;; "Face to use for basic data types.")
3029;;; ))) ; This does not work :-( Why?!
3030;;; ; Workaround: added to font-lock-m-h
3031;;; )
3032 (or (boundp 'font-lock-other-emphasized-face)
3033 (defconst font-lock-other-emphasized-face
3034 'font-lock-other-emphasized-face
3035 "Face to use for another type of emphasizing.")
3036 )
3037 (or (boundp 'font-lock-emphasized-face)
3038 (defconst font-lock-emphasized-face
3039 'font-lock-emphasized-face
3040 "Face to use for emphasizing.")
3041 )
3042 ;; Here we try to guess background
3043 (let ((background
3044 (if (boundp 'font-lock-background-mode)
3045 font-lock-background-mode
3046 'light))
3047 (face-list (and (fboundp 'face-list) (face-list)))
3048 is-face)
3049 (fset 'is-face
3050 (cond ((fboundp 'find-face)
3051 (symbol-function 'find-face))
3052 (face-list
3053 (function (lambda (face) (member face face-list))))
3054 (t
3055 (function (lambda (face) (boundp face))))))
3056 (defvar cperl-guessed-background
3057 (if (and (boundp 'font-lock-display-type)
3058 (eq font-lock-display-type 'grayscale))
3059 'gray
3060 background)
3061 "Background as guessed by CPerl mode")
3062 (if (is-face 'font-lock-type-face) nil
3063 (copy-face 'default 'font-lock-type-face)
3064 (cond
3065 ((eq background 'light)
3066 (set-face-foreground 'font-lock-type-face
3067 (if (x-color-defined-p "seagreen")
3068 "seagreen"
3069 "sea green")))
3070 ((eq background 'dark)
3071 (set-face-foreground 'font-lock-type-face
3072 (if (x-color-defined-p "os2pink")
3073 "os2pink"
3074 "pink")))
3075 (t
3076 (set-face-background 'font-lock-type-face "gray90"))))
3077 (if (is-face 'font-lock-other-type-face)
3078 nil
3079 (copy-face 'font-lock-type-face 'font-lock-other-type-face)
3080 (cond
3081 ((eq background 'light)
3082 (set-face-foreground 'font-lock-other-type-face
3083 (if (x-color-defined-p "chartreuse3")
3084 "chartreuse3"
3085 "chartreuse")))
3086 ((eq background 'dark)
3087 (set-face-foreground 'font-lock-other-type-face
3088 (if (x-color-defined-p "orchid1")
3089 "orchid1"
3090 "orange")))))
3091 (if (is-face 'font-lock-other-emphasized-face) nil
3092 (copy-face 'bold-italic 'font-lock-other-emphasized-face)
3093 (cond
3094 ((eq background 'light)
3095 (set-face-background 'font-lock-other-emphasized-face
3096 (if (x-color-defined-p "lightyellow2")
3097 "lightyellow2"
3098 (if (x-color-defined-p "lightyellow")
3099 "lightyellow"
3100 "light yellow"))))
3101 ((eq background 'dark)
3102 (set-face-background 'font-lock-other-emphasized-face
3103 (if (x-color-defined-p "navy")
3104 "navy"
3105 (if (x-color-defined-p "darkgreen")
3106 "darkgreen"
3107 "dark green"))))
3108 (t (set-face-background 'font-lock-other-emphasized-face "gray90"))))
3109 (if (is-face 'font-lock-emphasized-face) nil
3110 (copy-face 'bold 'font-lock-emphasized-face)
3111 (cond
3112 ((eq background 'light)
3113 (set-face-background 'font-lock-emphasized-face
3114 (if (x-color-defined-p "lightyellow2")
3115 "lightyellow2"
3116 "lightyellow")))
3117 ((eq background 'dark)
3118 (set-face-background 'font-lock-emphasized-face
3119 (if (x-color-defined-p "navy")
3120 "navy"
3121 (if (x-color-defined-p "darkgreen")
3122 "darkgreen"
3123 "dark green"))))
3124 (t (set-face-background 'font-lock-emphasized-face "gray90"))))
3125 (if (is-face 'font-lock-variable-name-face) nil
3126 (copy-face 'italic 'font-lock-variable-name-face))
3127 (if (is-face 'font-lock-reference-face) nil
c07a80fd 3128 (copy-face 'italic 'font-lock-reference-face))))
3129 (setq cperl-faces-init t))
4633a7c4 3130 (error nil)))
3131
3132
3133(defun cperl-ps-print-init ()
3134 "Initialization of `ps-print' components for faces used in CPerl."
3135 ;; Guard against old versions
3136 (defvar ps-underlined-faces nil)
3137 (defvar ps-bold-faces nil)
3138 (defvar ps-italic-faces nil)
3139 (setq ps-bold-faces
3140 (append '(font-lock-emphasized-face
3141 font-lock-keyword-face
3142 font-lock-variable-name-face
3143 font-lock-reference-face
3144 font-lock-other-emphasized-face)
3145 ps-bold-faces))
3146 (setq ps-italic-faces
3147 (append '(font-lock-other-type-face
3148 font-lock-reference-face
3149 font-lock-other-emphasized-face)
3150 ps-italic-faces))
3151 (setq ps-underlined-faces
3152 (append '(font-lock-emphasized-face
3153 font-lock-other-emphasized-face
3154 font-lock-other-type-face font-lock-type-face)
3155 ps-underlined-faces))
3156 (cons 'font-lock-type-face ps-underlined-faces))
3157
3158
3159(if (cperl-enable-font-lock) (cperl-windowed-init))
3160
3161(defun cperl-set-style (style)
3162 "Set CPerl-mode variables to use one of several different indentation styles.
3163The arguments are a string representing the desired style.
3164Available styles are GNU, K&R, BSD and Whitesmith."
3165 (interactive
3166 (let ((list (mapcar (function (lambda (elt) (list (car elt))))
3167 c-style-alist)))
3168 (list (completing-read "Enter style: " list nil 'insist))))
3169 (let ((style (cdr (assoc style c-style-alist))) setting str sym)
3170 (while style
3171 (setq setting (car style) style (cdr style))
3172 (setq str (symbol-name (car setting)))
3173 (and (string-match "^c-" str)
3174 (setq str (concat "cperl-" (substring str 2)))
3175 (setq sym (intern-soft str))
3176 (boundp sym)
3177 (set sym (cdr setting))))))
3178
3179(defun cperl-check-syntax ()
3180 (interactive)
3181 (require 'mode-compile)
3182 (let ((perl-dbg-flags "-wc"))
3183 (mode-compile)))
3184
3185(defun cperl-info-buffer ()
3186 ;; Returns buffer with documentation. Creats if missing
3187 (let ((info (get-buffer "*info-perl*")))
3188 (if info info
3189 (save-window-excursion
3190 ;; Get Info running
3191 (require 'info)
3192 (save-window-excursion
3193 (info))
499d5216 3194 (Info-find-node cperl-info-page "perlfunc")
4633a7c4 3195 (set-buffer "*info*")
3196 (rename-buffer "*info-perl*")
3197 (current-buffer)))))
3198
3199(defun cperl-word-at-point (&optional p)
3200 ;; Returns the word at point or at P.
3201 (save-excursion
3202 (if p (goto-char p))
3203 (require 'etags)
3204 (funcall (or (and (boundp 'find-tag-default-function)
3205 find-tag-default-function)
3206 (get major-mode 'find-tag-default-function)
3207 ;; XEmacs 19.12 has `find-tag-default-hook'; it is
3208 ;; automatically used within `find-tag-default':
3209 'find-tag-default))))
3210
3211(defun cperl-info-on-command (command)
3212 "Shows documentation for Perl command in other window."
3213 (interactive
3214 (let* ((default (cperl-word-at-point))
3215 (read (read-string
3216 (format "Find doc for Perl function (default %s): "
3217 default))))
3218 (list (if (equal read "")
3219 default
3220 read))))
3221
3222 (let ((buffer (current-buffer))
c07a80fd 3223 (cmd-desc (concat "^" (regexp-quote command) "[^a-zA-Z_0-9]")) ; "tr///"
4633a7c4 3224 pos)
3225 (if (string-match "^-[a-zA-Z]$" command)
3226 (setq cmd-desc "^-X[ \t\n]"))
3227 (set-buffer (cperl-info-buffer))
3228 (beginning-of-buffer)
3229 (re-search-forward "^-X[ \t\n]")
3230 (forward-line -1)
3231 (if (re-search-forward cmd-desc nil t)
3232 (progn
3233 (setq pos (progn (beginning-of-line)
3234 (point)))
3235 (pop-to-buffer (cperl-info-buffer))
3236 (set-window-start (selected-window) pos))
3237 (message "No entry for %s found." command))
c07a80fd 3238 (pop-to-buffer buffer)))
4633a7c4 3239
3240(defun cperl-info-on-current-command ()
3241 "Shows documentation for Perl command at point in other window."
3242 (interactive)
3243 (cperl-info-on-command (cperl-word-at-point)))
3244
3245(defun cperl-imenu-info-imenu-search ()
3246 (if (looking-at "^-X[ \t\n]") nil
3247 (re-search-backward
3248 "^\n\\([-a-zA-Z]+\\)[ \t\n]")
3249 (forward-line 1)))
3250
3251(defun cperl-imenu-info-imenu-name ()
3252 (buffer-substring
3253 (match-beginning 1) (match-end 1)))
3254
3255(defun cperl-imenu-on-info ()
3256 (interactive)
3257 (let* ((buffer (current-buffer))
3258 imenu-create-index-function
3259 imenu-prev-index-position-function
3260 imenu-extract-index-name-function
3261 (index-item (save-restriction
3262 (save-window-excursion
3263 (set-buffer (cperl-info-buffer))
3264 (setq imenu-create-index-function
3265 'imenu-default-create-index-function
3266 imenu-prev-index-position-function
3267 'cperl-imenu-info-imenu-search
3268 imenu-extract-index-name-function
3269 'cperl-imenu-info-imenu-name)
3270 (imenu-choose-buffer-index)))))
3271 (and index-item
3272 (progn
3273 (push-mark)
3274 (pop-to-buffer "*info-perl*")
3275 (cond
3276 ((markerp (cdr index-item))
3277 (goto-char (marker-position (cdr index-item))))
3278 (t
3279 (goto-char (cdr index-item))))
3280 (set-window-start (selected-window) (point))
3281 (pop-to-buffer buffer)))))
3282
3283(defun cperl-lineup (beg end &optional step minshift)
3284 "Lineup construction in a region.
3285Beginning of region should be at the start of a construction.
3286All first occurences of this construction in the lines that are
3287partially contained in the region are lined up at the same column.
3288
3289MINSHIFT is the minimal amount of space to insert before the construction.
3290STEP is the tabwidth to position constructions.
3291If STEP is `nil', `cperl-lineup-step' will be used
3292\(or `cperl-indent-level', if `cperl-lineup-step' is `nil').
3293Will not move the position at the start to the left."
3294 (interactive "r")
3295 (let (search col tcol seen b e)
3296 (save-excursion
3297 (goto-char end)
3298 (end-of-line)
3299 (setq end (point-marker))
3300 (goto-char beg)
3301 (skip-chars-forward " \t\f")
3302 (setq beg (point-marker))
3303 (indent-region beg end nil)
3304 (goto-char beg)
3305 (setq col (current-column))
499d5216 3306 (if (looking-at "[a-zA-Z0-9_]")
3307 (if (looking-at "\\<[a-zA-Z0-9_]+\\>")
4633a7c4 3308 (setq search
3309 (concat "\\<"
3310 (regexp-quote
3311 (buffer-substring (match-beginning 0)
3312 (match-end 0))) "\\>"))
3313 (error "Cannot line up in a middle of the word"))
3314 (if (looking-at "$")
3315 (error "Cannot line up end of line"))
3316 (setq search (regexp-quote (char-to-string (following-char)))))
3317 (setq step (or step cperl-lineup-step cperl-indent-level))
3318 (or minshift (setq minshift 1))
3319 (while (progn
3320 (beginning-of-line 2)
3321 (and (< (point) end)
3322 (re-search-forward search end t)
3323 (goto-char (match-beginning 0))))
3324 (setq tcol (current-column) seen t)
3325 (if (> tcol col) (setq col tcol)))
3326 (or seen
3327 (error "The construction to line up occured only once"))
3328 (goto-char beg)
3329 (setq col (+ col minshift))
3330 (if (/= (% col step) 0) (setq step (* step (1+ (/ col step)))))
3331 (while
3332 (progn
3333 (setq e (point))
3334 (skip-chars-backward " \t")
3335 (delete-region (point) e)
3336 (indent-to-column col); (make-string (- col (current-column)) ?\ ))
3337 (beginning-of-line 2)
3338 (and (< (point) end)
3339 (re-search-forward search end t)
3340 (goto-char (match-beginning 0)))))))) ; No body
3341
3342(defun cperl-etags (&optional add all files)
3343 "Run etags with appropriate options for Perl files.
3344If optional argument ALL is `recursive', will process Perl files
3345in subdirectories too."
3346 (interactive)
3347 (let ((cmd "etags")
3348 (args '("-l" "none" "-r" "/\\<\\(package\\|sub\\)[ \\t]+\\(\\([a-zA-Z0-9:_]*::\\)?\\([a-zA-Z0-9_]+\\)[ \\t]*\\([{#]\\|$\\)\\)/\\4/"))
3349 res)
3350 (if add (setq args (cons "-a" args)))
3351 (or files (setq files (list buffer-file-name)))
3352 (cond
3353 ((eq all 'recursive)
3354 ;;(error "Not implemented: recursive")
3355 (setq args (append (list "-e"
3356 "sub wanted {push @ARGV, $File::Find::name if /\\.[Pp][Llm]$/}
3357 use File::Find;
3358 find(\\&wanted, '.');
3359 exec @ARGV;"
3360 cmd) args)
3361 cmd "perl"))
3362 (all
3363 ;;(error "Not implemented: all")
3364 (setq args (append (list "-e"
3365 "push @ARGV, <*.PL *.pl *.pm>;
3366 exec @ARGV;"
3367 cmd) args)
3368 cmd "perl"))
3369 (t
3370 (setq args (append args files))))
3371 (setq res (apply 'call-process cmd nil nil nil args))
3372 (or (eq res 0)
3373 (message "etags returned \"%s\"" res))))
9ea28adb 3374
3375(defun cperl-toggle-auto-newline ()
3376 "Toggle the state of `cperl-auto-newline'."
3377 (interactive)
3378 (setq cperl-auto-newline (not cperl-auto-newline))
3379 (message "Newlines will %sbe auto-inserted now."
3380 (if cperl-auto-newline "" "not ")))
3381
3382(defun cperl-toggle-abbrev ()
3383 "Toggle the state of automatic keyword expansion in CPerl mode."
3384 (interactive)
3385 (abbrev-mode (if abbrev-mode 0 1))
3386 (message "Perl control structure will %sbe auto-inserted now."
3387 (if abbrev-mode "" "not ")))
3388
3389
3390(defun cperl-toggle-electric ()
3391 "Toggle the state of parentheses doubling in CPerl mode."
3392 (interactive)
3393 (setq cperl-electric-parens (if (cperl-val 'cperl-electric-parens) 'null t))
3394 (message "Parentheses will %sbe auto-doubled now."
3395 (if (cperl-val 'cperl-electric-parens) "" "not ")))
3396
3397;;;; Tags file creation.
3398
3399(defvar cperl-tmp-buffer " *cperl-tmp*")
3400
3401(defun cperl-setup-tmp-buf ()
3402 (set-buffer (get-buffer-create cperl-tmp-buffer))
3403 (set-syntax-table cperl-mode-syntax-table)
3404 (buffer-disable-undo)
3405 (auto-fill-mode 0))
3406
3407(defun cperl-xsub-scan ()
3408 (require 'cl)
499d5216 3409 (require 'imenu)
9ea28adb 3410 (let ((index-alist '())
3411 (prev-pos 0) index index1 name package prefix)
3412 (goto-char (point-min))
3413 (imenu-progress-message prev-pos 0)
3414 ;; Search for the function
3415 (progn ;;save-match-data
3416 (while (re-search-forward
3417 "^\\([ \t]*MODULE\\>[^\n]*\\<PACKAGE[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9:]*\\)\\>\\|\\([a-zA-Z_][a-zA-Z_0-9]*\\)(\\|[ \t]*BOOT:\\)"
3418 nil t)
3419 (imenu-progress-message prev-pos)
3420 (cond
3421 ((match-beginning 2) ; SECTION
3422 (setq package (buffer-substring (match-beginning 2) (match-end 2)))
3423 (goto-char (match-beginning 0))
3424 (skip-chars-forward " \t")
3425 (forward-char 1)
3426 (if (looking-at "[^\n]*\\<PREFIX[ \t]*=[ \t]*\\([a-zA-Z_][a-zA-Z_0-9]*\\)\\>")
3427 (setq prefix (buffer-substring (match-beginning 1) (match-end 1)))
3428 (setq prefix nil)))
3429 ((not package) nil) ; C language section
3430 ((match-beginning 3) ; XSUB
3431 (goto-char (1+ (match-beginning 3)))
3432 (setq index (imenu-example--name-and-position))
3433 (setq name (buffer-substring (match-beginning 3) (match-end 3)))
3434 (if (and prefix (string-match (concat "^" prefix) name))
3435 (setq name (substring name (length prefix))))
9ea28adb 3436 (cond ((string-match "::" name) nil)
3437 (t
3438 (setq index1 (cons (concat package "::" name) (cdr index)))
3439 (push index1 index-alist)))
3440 (setcar index name)
3441 (push index index-alist))
3442 (t ; BOOT: section
3443 ;; (beginning-of-line)
3444 (setq index (imenu-example--name-and-position))
3445 (setcar index (concat package "::BOOT:"))
3446 (push index index-alist)))))
3447 (imenu-progress-message prev-pos 100)
3448 ;;(setq index-alist
3449 ;; (if (default-value 'imenu-sort-function)
3450 ;; (sort index-alist (default-value 'imenu-sort-function))
3451 ;; (nreverse index-alist)))
3452 index-alist))
3453
3454(defun cperl-find-tags (file xs)
3455 (let (ind (b (get-buffer cperl-tmp-buffer)) lst elt pos ret)
3456 (save-excursion
3457 (if b (set-buffer b)
3458 (cperl-setup-tmp-buf))
3459 (erase-buffer)
3460 (setq file (car (insert-file-contents file)))
3461 (message "Scanning file %s..." file)
3462 (if xs
3463 (setq lst (cperl-xsub-scan))
3464 (setq ind (imenu-example--create-perl-index))
3465 (setq lst (cdr (assoc "+Unsorted List+..." ind))))
3466 (setq lst
3467 (mapcar
3468 (function
3469 (lambda (elt)
3470 (cond ((string-match "^[_a-zA-Z]" (car elt))
3471 (goto-char (cdr elt))
3472 (list (car elt)
3473 (point) (count-lines 1 (point))
3474 (buffer-substring (progn
3475 (skip-chars-forward
3476 ":_a-zA-Z0-9")
3477 (or (eolp) (forward-char 1))
3478 (point))
3479 (progn
3480 (beginning-of-line)
3481 (point))))))))
3482 lst))
3483 (erase-buffer)
3484 (while lst
3485 (setq elt (car lst) lst (cdr lst))
3486 (if elt
3487 (progn
3488 (insert (elt elt 3)
3489 127
3490 (if (string-match "^package " (car elt))
3491 (substring (car elt) 8)
3492 (car elt) )
3493 1
3494 (number-to-string (elt elt 1))
3495 ","
3496 (number-to-string (elt elt 2))
3497 "\n")
3498 (if (and (string-match "^[_a-zA-Z]+::" (car elt))
3499 (string-match "^sub[ \t]+\\([_a-zA-Z]+\\)[^:_a-zA-Z]"
3500 (elt elt 3)))
3501 ;; Need to insert the name without package as well
3502 (setq lst (cons (cons (substring (elt elt 3)
3503 (match-beginning 1)
3504 (match-end 1))
3505 (cdr elt))
3506 lst))))))
3507 (setq pos (point))
3508 (goto-char 1)
3509 (insert "\f\n" file "," (number-to-string (1- pos)) "\n")
3510 (setq ret (buffer-substring 1 (point-max)))
3511 (erase-buffer)
3512 (message "Scanning file %s finished" file)
3513 ret)))
3514
3515(defun cperl-write-tags (&optional file erase recurse dir inbuffer)
3516 ;; If INBUFFER, do not select buffer, and do not save
3517 ;; If ERASE is `ignore', do not erase, and do not try to delete old info.
499d5216 3518 (require 'etags)
9ea28adb 3519 (if file nil
3520 (setq file (if dir default-directory (buffer-file-name)))
3521 (if (and (not dir) (buffer-modified-p)) (error "Save buffer first!")))
3522 (let ((tags-file-name "TAGS")
3523 (case-fold-search (eq system-type 'emx))
3524 xs)
3525 (save-excursion
3526 (cond (inbuffer nil) ; Already there
3527 ((file-exists-p tags-file-name)
3528 (visit-tags-table-buffer tags-file-name))
3529 (t (set-buffer (find-file-noselect tags-file-name))))
3530 (cond
3531 (dir
3532 (cond ((eq erase 'ignore))
3533 (erase
3534 (erase-buffer)
3535 (setq erase 'ignore)))
3536 (let ((files
3537 (directory-files file t (if recurse nil "\\.[Pp][Llm]$") t)))
3538 (mapcar (function (lambda (file)
3539 (cond
3540 ((string-match "/\\.\\.?$" file) nil)
3541 ((not (file-directory-p file))
3542 (if (string-match "\\.\\([Pp][Llm]\\|xs\\)$" file)
3543 (cperl-write-tags file erase recurse nil t)))
3544 ((not recurse) nil)
3545 (t (cperl-write-tags file erase recurse t t)))))
3546 files))
3547 )
3548 (t
3549 (setq xs (string-match "\\.xs$" file))
3550 (cond ((eq erase 'ignore) nil)
3551 (erase (erase-buffer))
3552 (t
3553 (goto-char 1)
3554 (if (search-forward (concat "\f\n" file ",") nil t)
3555 (progn
3556 (search-backward "\f\n")
3557 (delete-region (point)
3558 (progn
3559 (forward-char 1)
3560 (search-forward "\f\n" nil 'toend)
3561 (point)))
3562 (goto-char 1)))))
3563 (insert (cperl-find-tags file xs))))
3564 (if inbuffer nil ; Delegate to the caller
3565 (save-buffer 0) ; No backup
3566 (initialize-new-tags-table)))))
3567
3568(defvar cperl-tags-hier-regexp-list
3569 "^\\(\\(package\\)\\>\\|sub\\>[^\n]+::\\|[a-zA-Z_][a-zA-Z_0-9:]*(\C-?[^\n]+::\\|[ \t]*BOOT:\C-?[^\n]+::\\)")
3570
3571(defvar cperl-hierarchy '(() ())
3572 "Global hierarchy of classes")
3573
3574(defun cperl-tags-hier-fill ()
3575 ;; Suppose we are in a tag table cooked by cperl.
3576 (goto-char 1)
3577 (let (type pack name pos line chunk ord cons1 file str info fileind)
3578 (while (re-search-forward cperl-tags-hier-regexp-list nil t)
3579 (setq pos (match-beginning 0)
3580 pack (match-beginning 2))
3581 (beginning-of-line)
3582 (if (looking-at "\\([^\n]+\\)\C-?\\([^\n]+\\)\C-a\\([0-9]+\\),\\([0-9]+\\)")
3583 (progn
3584 (setq ;;str (buffer-substring (match-beginning 1) (match-end 1))
3585 name (buffer-substring (match-beginning 2) (match-end 2))
3586 ;;pos (buffer-substring (match-beginning 3) (match-end 3))
3587 line (buffer-substring (match-beginning 4) (match-end 4))
3588 ord (if pack 1 0)
3589 info (etags-snarf-tag) ; Moves to beginning of the next line
3590 file (file-of-tag)
3591 fileind (format "%s:%s" file line))
3592 ;; Move back
3593 (forward-char -1)
3594 ;; Make new member of hierarchy name ==> file ==> pos if needed
3595 (if (setq cons1 (assoc name (nth ord cperl-hierarchy)))
3596 ;; Name known
3597 (setcdr cons1 (cons (cons fileind (vector file info))
3598 (cdr cons1)))
3599 ;; First occurence of the name, start alist
3600 (setq cons1 (cons name (list (cons fileind (vector file info)))))
3601 (if pack
3602 (setcar (cdr cperl-hierarchy)
3603 (cons cons1 (nth 1 cperl-hierarchy)))
3604 (setcar cperl-hierarchy
3605 (cons cons1 (car cperl-hierarchy)))))))
3606 (end-of-line))))
3607
3608(defun cperl-tags-hier-init (&optional update)
3609 "Show hierarchical menu of classes and methods.
3610Finds info about classes by a scan of loaded TAGS files.
3611Supposes that the TAGS files contain fully qualified function names.
3612One may build such TAGS files from CPerl mode menu."
3613 (interactive)
3614 (require 'etags)
3615 (require 'imenu)
3616 (if (or update (null (nth 2 cperl-hierarchy)))
3617 (let (pack name cons1 to l1 l2 l3 l4
3618 (remover (function (lambda (elt) ; (name (file1...) (file2..))
3619 (or (nthcdr 2 elt)
3620 ;; Only in one file
3621 (setcdr elt (cdr (nth 1 elt))))))))
3622 ;; (setq cperl-hierarchy '(() () ())) ; Would write into '() later!
3623 (setq cperl-hierarchy (list l1 l2 l3))
3624 (or tags-table-list
3625 (call-interactively 'visit-tags-table))
3626 (message "Updating list of classes...")
3627 (mapcar
3628 (function
3629 (lambda (tagsfile)
3630 (set-buffer (get-file-buffer tagsfile))
3631 (cperl-tags-hier-fill)))
3632 tags-table-list)
3633 (mapcar remover (car cperl-hierarchy))
3634 (mapcar remover (nth 1 cperl-hierarchy))
3635 (setq to (list nil (cons "Packages: " (nth 1 cperl-hierarchy))
3636 (cons "Methods: " (car cperl-hierarchy))))
3637 (cperl-tags-treeify to 1)
3638 (setcar (nthcdr 2 cperl-hierarchy)
3639 (cperl-menu-to-keymap (cons '("+++UPDATE+++" . -999) (cdr to))))
3640 (message "Updating list of classes: done, requesting display...")
3641 ;;(cperl-imenu-addback (nth 2 cperl-hierarchy))
3642 ))
3643 (or (nth 2 cperl-hierarchy)
3644 (error "No items found"))
3645 (setq update
3646;;; (imenu-choose-buffer-index "Packages: " (nth 2 cperl-hierarchy))
3647 (if window-system
3648 (x-popup-menu t (nth 2 cperl-hierarchy))
3649 (require 'tmm)
3650 (tmm-prompt t (nth 2 cperl-hierarchy))))
3651 (if (and update (listp update))
3652 (progn (while (cdr update) (setq update (cdr update)))
3653 (setq update (car update)))) ; Get the last from the list
3654 (if (vectorp update)
3655 (progn
3656 (find-file (elt update 0))
3657 (etags-goto-tag-location (elt update 1))))
3658 (if (eq update -999) (cperl-tags-hier-init t)))
3659
3660(defun cperl-tags-treeify (to level)
3661 ;; cadr of to is read-write. On start it is a cons
3662 (let* ((regexp (concat "^\\(" (mapconcat
3663 'identity
3664 (make-list level "[_a-zA-Z0-9]+")
3665 "::")
3666 "\\)\\(::\\)?"))
3667 (packages (cdr (nth 1 to)))
3668 (methods (cdr (nth 2 to)))
3669 l1 head tail cons1 cons2 ord writeto packs recurse
3670 root-packages root-functions ms many_ms same_name ps
3671 (move-deeper
3672 (function
3673 (lambda (elt)
3674 (cond ((and (string-match regexp (car elt))
3675 (or (eq ord 1) (match-end 2)))
3676 (setq head (substring (car elt) 0 (match-end 1))
3677 tail (if (match-end 2) (substring (car elt)
3678 (match-end 2)))
3679 recurse t)
3680 (if (setq cons1 (assoc head writeto)) nil
3681 ;; Need to init new head
3682 (setcdr writeto (cons (list head (list "Packages: ")
3683 (list "Methods: "))
3684 (cdr writeto)))
3685 (setq cons1 (nth 1 writeto)))
3686 (setq cons2 (nth ord cons1)) ; Either packs or meths
3687 (setcdr cons2 (cons elt (cdr cons2))))
3688 ((eq ord 2)
3689 (setq root-functions (cons elt root-functions)))
3690 (t
3691 (setq root-packages (cons elt root-packages))))))))
3692 (setcdr to l1) ; Init to dynamic space
3693 (setq writeto to)
3694 (setq ord 1)
3695 (mapcar move-deeper packages)
3696 (setq ord 2)
3697 (mapcar move-deeper methods)
3698 (if recurse
3699 (mapcar (function (lambda (elt)
3700 (cperl-tags-treeify elt (1+ level))))
3701 (cdr to)))
3702 ;; Now add back functions removed from display
3703 (mapcar (function (lambda (elt)
3704 (setcdr to (cons elt (cdr to)))))
3705 root-functions)
3706 ;; Now add back packages removed from display
3707 (mapcar (function (lambda (elt)
3708 (setcdr to (cons (cons (concat "package " (car elt))
3709 (cdr elt))
3710 (cdr to)))))
3711 root-packages)
3712 ;;Now clean up leaders with one child only
3713 (mapcar (function (lambda (elt)
3714 (if (not (and (listp (cdr elt))
3715 (eq (length elt) 2))) nil
3716 (setcar elt (car (nth 1 elt)))
3717 (setcdr elt (cdr (nth 1 elt))))))
3718 (cdr to))
3719 ))
3720
3721;;;(x-popup-menu t
3722;;; '(keymap "Name1"
3723;;; ("Ret1" "aa")
3724;;; ("Head1" "ab"
3725;;; keymap "Name2"
3726;;; ("Tail1" "x") ("Tail2" "y"))))
3727
3728(defun cperl-list-fold (list name limit)
3729 (let (list1 list2 elt1 (num 0))
3730 (if (<= (length list) limit) list
3731 (setq list1 nil list2 nil)
3732 (while list
3733 (setq num (1+ num)
3734 elt1 (car list)
3735 list (cdr list))
3736 (if (<= num imenu-max-items)
3737 (setq list2 (cons elt1 list2))
3738 (setq list1 (cons (cons name
3739 (nreverse list2))
3740 list1)
3741 list2 (list elt1)
3742 num 1)))
3743 (nreverse (cons (cons name
3744 (nreverse list2))
3745 list1)))))
3746
3747(defun cperl-menu-to-keymap (menu &optional name)
3748 (let (list)
3749 (cons 'keymap
3750 (mapcar
3751 (function
3752 (lambda (elt)
3753 (cond ((listp (cdr elt))
3754 (setq list (cperl-list-fold
3755 (cdr elt) (car elt) imenu-max-items))
3756 (cons nil
3757 (cons (car elt)
3758 (cperl-menu-to-keymap list))))
3759 (t
3760 (list (cdr elt) (car elt))))))
3761 (cperl-list-fold menu "Root" imenu-max-items)))))
499d5216 3762
3763\f
3764(defvar cperl-bad-style-regexp
3765 (mapconcat 'identity
3766 '("[^-\n\t <>=+!.&|(*/'`\"#^][-=+<>!|&^]" ; char sign
3767 "[-<>=+^&|]+[^- \t\n=+<>~]" ; sign+ char
3768 )
3769 "\\|")
3770 "Finds places such that insertion of a whitespace may help a lot.")
3771
3772(defvar cperl-not-bad-style-regexp
3773 (mapconcat 'identity
3774 '("[^-\t <>=+]\\(--\\|\\+\\+\\)" ; var-- var++
3775 "[a-zA-Z0-9][|&][a-zA-Z0-9$]" ; abc|def abc&def are often used.
3776 "&[(a-zA-Z0-9$]" ; &subroutine &(var->field)
3777 "<\\$?\\sw+\\(\\.\\sw+\\)?>" ; <IN> <stdin.h>
3778 "-[a-zA-Z][ \t]+[_$\"'`]" ; -f file
3779 "-[0-9]" ; -5
3780 "\\+\\+" ; ++var
3781 "--" ; --var
3782 ".->" ; a->b
3783 "->" ; a SPACE ->b
3784 "\\[-" ; a[-1]
3785 "^=" ; =head
3786 "||"
3787 "&&"
3788 "[CBIXSLFZ]<\\(\\sw\\|\\s \\|\\s_\\|[\n]\\)*>" ; C<code like text>
3789 "-[a-zA-Z0-9]+[ \t]*=>" ; -option => value
3790 ;; Unaddressed trouble spots: = -abc, f(56, -abc) --- specialcased below
3791 ;;"[*/+-|&<.]+="
3792 )
3793 "\\|")
3794 "If matches at the start of match found by `my-bad-c-style-regexp',
3795insertion of a whitespace will not help.")
3796
3797(defvar found-bad)
3798
3799(defun cperl-find-bad-style ()
3800 "Find places in the buffer where insertion of a whitespace may help.
3801Prompts user for insertion of spaces.
3802Currently it is tuned to C and Perl syntax."
3803 (interactive)
3804 (let (found-bad (p (point)))
3805 (setq last-nonmenu-event 13) ; To disable popup
3806 (beginning-of-buffer)
3807 (map-y-or-n-p "Insert space here? "
3808 (function (lambda (arg) (insert " ")))
3809 'cperl-next-bad-style
3810 '("location" "locations" "insert a space into")
3811 '((?\C-r (lambda (arg)
3812 (let ((buffer-quit-function
3813 'exit-recursive-edit))
3814 (message "Exit with Esc Esc")
3815 (recursive-edit)
3816 t)) ; Consider acted upon
3817 "edit, exit with Esc Esc")
3818 (?e (lambda (arg)
3819 (let ((buffer-quit-function
3820 'exit-recursive-edit))
3821 (message "Exit with Esc Esc")
3822 (recursive-edit)
3823 t)) ; Consider acted upon
3824 "edit, exit with Esc Esc"))
3825 t)
3826 (if found-bad (goto-char found-bad)
3827 (goto-char p)
3828 (message "No appropriate place found"))))
3829
3830(defun cperl-next-bad-style ()
3831 (let (p (not-found t) (point (point)) found)
3832 (while (and not-found
3833 (re-search-forward cperl-bad-style-regexp nil 'to-end))
3834 (setq p (point))
3835 (goto-char (match-beginning 0))
3836 (if (or
3837 (looking-at cperl-not-bad-style-regexp)
3838 ;; Check for a < -b and friends
3839 (and (eq (following-char) ?\-)
3840 (save-excursion
3841 (skip-chars-backward " \t\n")
3842 (memq (preceding-char) '(?\= ?\> ?\< ?\, ?\(, ?\[, ?\{))))
3843 ;; Now check for syntax type
3844 (save-match-data
3845 (setq found (point))
3846 (beginning-of-defun)
3847 (let ((pps (parse-partial-sexp (point) found)))
3848 (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))
3849 (goto-char (match-end 0))
3850 (goto-char (1- p))
3851 (setq not-found nil
3852 found-bad found)))
3853 (not not-found)))
3854