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