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