This is my patch patch.1n for perl5.001.
[p5sagit/p5-mst-13.2.git] / emacs / cperl-mode
CommitLineData
463ee0b2 1Article 15212 of comp.lang.perl:
2Path: netlabs!news.cerf.net!usc!howland.reston.ans.net!spool.mu.edu!umn.edu!news-feed-2.peachnet.edu!concert!duke!khera
3From: khera@cs.duke.edu (Vivek Khera)
4Newsgroups: comp.lang.perl
5Subject: cperl-mode.el
6Message-ID: <KHERA.93Oct21140851@thneed.cs.duke.edu>
7Date: 21 Oct 93 18:08:51 GMT
8Sender: news@duke.cs.duke.edu
9Organization: Duke University CS Dept., Durham, NC
10Lines: 694
11Nntp-Posting-Host: thneed.cs.duke.edu
12X-Md4-Signature: 40dd9bccfb99794a9da2ee891b5bf557
13X-Md5-Signature: e4baa8cf00c94092ebf9712514e4696b
14
15Since I've received requests to do so, I'm posting the cperl-mode.el
16file. This allows Emacs (both version 18 and 19) to do nice things
17when editing Perl code. Indentation works well, and it doesn't get
18confused like the perl-mode.el that comes with Emacs 19.
19
20Install this file as cperl-mode.el, and add the following to your
21.emacs file:
22
23(autoload 'perl-mode "cperl-mode" "alternate mode for editing Perl programs" t)
24
25This cperl-mode.el is not exactly the same as when it was originally
26posted here. I made the following changes: perl-mode is an alias for
27cperl-mode, and the major mode name is perl-mode, not cperl-mode.
28This is so it is easier to use with Emacs 19. I suppose one could
29install this as perl-mode.el and then not have to put the autoload
30line in (for Emacs 19).
31
32Anyway, I'm not maintaining this, so don't send me bugs.
33
34--cut here--
35;;; From: olson@mcs.anl.gov (Bob Olson)
36;;; Newsgroups: comp.lang.perl
37;;; Subject: cperl-mode: Another perl mode for Gnuemacs
38;;; Date: 14 Aug 91 15:20:01 GMT
39
40;; Perl code editing commands for Emacs
41;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
42
43;; This file is part of GNU Emacs.
44
45;; GNU Emacs is distributed in the hope that it will be useful,
46;; but WITHOUT ANY WARRANTY. No author or distributor
47;; accepts responsibility to anyone for the consequences of using it
48;; or for whether it serves any particular purpose or works at all,
49;; unless he says so in writing. Refer to the GNU Emacs General Public
50;; License for full details.
51
52;; Everyone is granted permission to copy, modify and redistribute
53;; GNU Emacs, but only under the conditions described in the
54;; GNU Emacs General Public License. A copy of this license is
55;; supposed to have been given to you along with GNU Emacs so you
56;; can know your rights and responsibilities. It should be in a
57;; file named COPYING. Among other things, the copyright notice
58;; and this notice must be preserved on all copies.
59
60
61(defvar cperl-mode-abbrev-table nil
62 "Abbrev table in use in Cperl-mode buffers.")
63(define-abbrev-table 'cperl-mode-abbrev-table ())
64
65(defvar cperl-mode-map ()
66 "Keymap used in C mode.")
67(if cperl-mode-map
68 ()
69 (setq cperl-mode-map (make-sparse-keymap))
70 (define-key cperl-mode-map "{" 'electric-cperl-brace)
71 (define-key cperl-mode-map "}" 'electric-cperl-brace)
72 (define-key cperl-mode-map ";" 'electric-cperl-semi)
73 (define-key cperl-mode-map ":" 'electric-cperl-terminator)
74 (define-key cperl-mode-map "\e\C-h" 'mark-cperl-function)
75 (define-key cperl-mode-map "\e\C-q" 'indent-cperl-exp)
76 (define-key cperl-mode-map "\177" 'backward-delete-char-untabify)
77 (define-key cperl-mode-map "\t" 'cperl-indent-command))
78
79(autoload 'cperl-macro-expand "cmacexp"
80 "Display the result of expanding all C macros occurring in the region.
81The expansion is entirely correct because it uses the C preprocessor."
82 t)
83
84(defvar cperl-mode-syntax-table nil
85 "Syntax table in use in Cperl-mode buffers.")
86
87(if cperl-mode-syntax-table
88 ()
89 (setq cperl-mode-syntax-table (make-syntax-table))
90 (modify-syntax-entry ?\\ "\\" cperl-mode-syntax-table)
91 (modify-syntax-entry ?/ ". 14" cperl-mode-syntax-table)
92 (modify-syntax-entry ?* ". 23" cperl-mode-syntax-table)
93 (modify-syntax-entry ?+ "." cperl-mode-syntax-table)
94 (modify-syntax-entry ?- "." cperl-mode-syntax-table)
95 (modify-syntax-entry ?= "." cperl-mode-syntax-table)
96 (modify-syntax-entry ?% "." cperl-mode-syntax-table)
97 (modify-syntax-entry ?< "." cperl-mode-syntax-table)
98 (modify-syntax-entry ?> "." cperl-mode-syntax-table)
99 (modify-syntax-entry ?& "." cperl-mode-syntax-table)
100 (modify-syntax-entry ?| "." cperl-mode-syntax-table))
101
102
103(defvar cperl-indent-level 2
104 "*Indentation of C statements with respect to containing block.")
105(defvar cperl-brace-imaginary-offset 0
106 "*Imagined indentation of a C open brace that actually follows a statement.")
107(defvar cperl-brace-offset 0
108 "*Extra indentation for braces, compared with other text in same context.")
109(defvar cperl-argdecl-indent 5
110 "*Indentation level of declarations of C function arguments.")
111(defvar cperl-label-offset -2
112 "*Offset of C label lines and case statements relative to usual indentation.")
113(defvar cperl-continued-statement-offset 2
114 "*Extra indent for lines not starting new statements.")
115(defvar cperl-continued-brace-offset 0
116 "*Extra indent for substatements that start with open-braces.
117This is in addition to cperl-continued-statement-offset.")
118
119(defvar cperl-auto-newline nil
120 "*Non-nil means automatically newline before and after braces,
121and after colons and semicolons, inserted in C code.")
122
123(defvar cperl-tab-always-indent t
124 "*Non-nil means TAB in C mode should always reindent the current line,
125regardless of where in the line point is when the TAB command is used.")
126\f
127;; provide an alias for working with emacs 19. the perl-mode that comes
128;; with it is really bad, and this lets us seamlessly replace it.
129(fset 'perl-mode 'cperl-mode)
130(defun cperl-mode ()
131 "Major mode for editing C code.
132Expression and list commands understand all C brackets.
133Tab indents for C code.
134Comments are delimited with /* ... */.
135Paragraphs are separated by blank lines only.
136Delete converts tabs to spaces as it moves back.
137\\{cperl-mode-map}
138Variables controlling indentation style:
139 cperl-tab-always-indent
140 Non-nil means TAB in C mode should always reindent the current line,
141 regardless of where in the line point is when the TAB command is used.
142 cperl-auto-newline
143 Non-nil means automatically newline before and after braces,
144 and after colons and semicolons, inserted in C code.
145 cperl-indent-level
146 Indentation of C statements within surrounding block.
147 The surrounding block's indentation is the indentation
148 of the line on which the open-brace appears.
149 cperl-continued-statement-offset
150 Extra indentation given to a substatement, such as the
151 then-clause of an if or body of a while.
152 cperl-continued-brace-offset
153 Extra indentation given to a brace that starts a substatement.
154 This is in addition to cperl-continued-statement-offset.
155 cperl-brace-offset
156 Extra indentation for line if it starts with an open brace.
157 cperl-brace-imaginary-offset
158 An open brace following other text is treated as if it were
159 this far to the right of the start of its line.
160 cperl-argdecl-indent
161 Indentation level of declarations of C function arguments.
162 cperl-label-offset
163 Extra indentation for line that is a label, or case or default.
164
165Settings for K&R and BSD indentation styles are
166 cperl-indent-level 5 8
167 cperl-continued-statement-offset 5 8
168 cperl-brace-offset -5 -8
169 cperl-argdecl-indent 0 8
170 cperl-label-offset -5 -8
171
172Turning on C mode calls the value of the variable cperl-mode-hook with no args,
173if that value is non-nil."
174 (interactive)
175 (kill-all-local-variables)
176 (use-local-map cperl-mode-map)
177 (setq major-mode 'perl-mode)
178 (setq mode-name "CPerl")
179 (setq local-abbrev-table cperl-mode-abbrev-table)
180 (set-syntax-table cperl-mode-syntax-table)
181 (make-local-variable 'paragraph-start)
182 (setq paragraph-start (concat "^$\\|" page-delimiter))
183 (make-local-variable 'paragraph-separate)
184 (setq paragraph-separate paragraph-start)
185 (make-local-variable 'paragraph-ignore-fill-prefix)
186 (setq paragraph-ignore-fill-prefix t)
187 (make-local-variable 'indent-line-function)
188 (setq indent-line-function 'cperl-indent-line)
189 (make-local-variable 'require-final-newline)
190 (setq require-final-newline t)
191 (make-local-variable 'comment-start)
192 (setq comment-start "# ")
193 (make-local-variable 'comment-end)
194 (setq comment-end "")
195 (make-local-variable 'comment-column)
196 (setq comment-column 32)
197 (make-local-variable 'comment-start-skip)
198 (setq comment-start-skip "# *")
199 (make-local-variable 'comment-indent-hook)
200 (setq comment-indent-hook 'cperl-comment-indent)
201 (make-local-variable 'parse-sexp-ignore-comments)
202 (setq parse-sexp-ignore-comments t)
203 (run-hooks 'cperl-mode-hook))
204\f
205;; This is used by indent-for-comment
206;; to decide how much to indent a comment in C code
207;; based on its context.
208(defun cperl-comment-indent ()
209 (if (looking-at "^#")
210 0 ;Existing comment at bol stays there.
211 (save-excursion
212 (skip-chars-backward " \t")
213 (max (1+ (current-column)) ;Else indent at comment column
214 comment-column)))) ; except leave at least one space.
215
216(defun electric-cperl-brace (arg)
217 "Insert character and correct line's indentation."
218 (interactive "P")
219 (let (insertpos)
220 (if (and (not arg)
221 (eolp)
222 (or (save-excursion
223 (skip-chars-backward " \t")
224 (bolp))
225 (if cperl-auto-newline (progn (cperl-indent-line) (newline) t) nil)))
226 (progn
227 (insert last-command-char)
228 (cperl-indent-line)
229 (if cperl-auto-newline
230 (progn
231 (newline)
232 ;; (newline) may have done auto-fill
233 (setq insertpos (- (point) 2))
234 (cperl-indent-line)))
235 (save-excursion
236 (if insertpos (goto-char (1+ insertpos)))
237 (delete-char -1))))
238 (if insertpos
239 (save-excursion
240 (goto-char insertpos)
241 (self-insert-command (prefix-numeric-value arg)))
242 (self-insert-command (prefix-numeric-value arg)))))
243
244(defun electric-cperl-semi (arg)
245 "Insert character and correct line's indentation."
246 (interactive "P")
247 (if cperl-auto-newline
248 (electric-cperl-terminator arg)
249 (self-insert-command (prefix-numeric-value arg))))
250
251(defun electric-cperl-terminator (arg)
252 "Insert character and correct line's indentation."
253 (interactive "P")
254 (let (insertpos (end (point)))
255 (if (and (not arg) (eolp)
256 (not (save-excursion
257 (beginning-of-line)
258 (skip-chars-forward " \t")
259 (or (= (following-char) ?#)
260 ;; Colon is special only after a label, or case ....
261 ;; So quickly rule out most other uses of colon
262 ;; and do no indentation for them.
263 (and (eq last-command-char ?:)
264 (not (looking-at "case[ \t]"))
265 (save-excursion
266 (forward-word 1)
267 (skip-chars-forward " \t")
268 (< (point) end)))
269 (progn
270 (beginning-of-defun)
271 (let ((pps (parse-partial-sexp (point) end)))
272 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
273 (progn
274 (insert last-command-char)
275 (cperl-indent-line)
276 (and cperl-auto-newline
277 (not (cperl-inside-parens-p))
278 (progn
279 (newline)
280 (setq insertpos (- (point) 2))
281 (cperl-indent-line)))
282 (save-excursion
283 (if insertpos (goto-char (1+ insertpos)))
284 (delete-char -1))))
285 (if insertpos
286 (save-excursion
287 (goto-char insertpos)
288 (self-insert-command (prefix-numeric-value arg)))
289 (self-insert-command (prefix-numeric-value arg)))))
290
291(defun cperl-inside-parens-p ()
292 (condition-case ()
293 (save-excursion
294 (save-restriction
295 (narrow-to-region (point)
296 (progn (beginning-of-defun) (point)))
297 (goto-char (point-max))
298 (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
299 (error nil)))
300\f
301(defun cperl-indent-command (&optional whole-exp)
302 (interactive "P")
303 "Indent current line as C code, or in some cases insert a tab character.
304If cperl-tab-always-indent is non-nil (the default), always indent current line.
305Otherwise, indent the current line only if point is at the left margin
306or in the line's indentation; otherwise insert a tab.
307
308A numeric argument, regardless of its value,
309means indent rigidly all the lines of the expression starting after point
310so that this line becomes properly indented.
311The relative indentation among the lines of the expression are preserved."
312 (if whole-exp
313 ;; If arg, always indent this line as C
314 ;; and shift remaining lines of expression the same amount.
315 (let ((shift-amt (cperl-indent-line))
316 beg end)
317 (save-excursion
318 (if cperl-tab-always-indent
319 (beginning-of-line))
320 (setq beg (point))
321 (forward-sexp 1)
322 (setq end (point))
323 (goto-char beg)
324 (forward-line 1)
325 (setq beg (point)))
326 (if (> end beg)
327 (indent-code-rigidly beg end shift-amt "#")))
328 (if (and (not cperl-tab-always-indent)
329 (save-excursion
330 (skip-chars-backward " \t")
331 (not (bolp))))
332 (insert-tab)
333 (cperl-indent-line))))
334
335(defun cperl-indent-line ()
336 "Indent current line as C code.
337Return the amount the indentation changed by."
338 (let ((indent (calculate-cperl-indent nil))
339 beg shift-amt
340 (case-fold-search nil)
341 (pos (- (point-max) (point))))
342 (beginning-of-line)
343 (setq beg (point))
344 (cond ((eq indent nil)
345 (setq indent (current-indentation)))
346 ((eq indent t)
347 (setq indent (calculate-cperl-indent-within-comment)))
348 ((looking-at "[ \t]*#")
349 (setq indent 0))
350 (t
351 (skip-chars-forward " \t")
352 (if (listp indent) (setq indent (car indent)))
353 (cond ((or (looking-at "case[ \t]")
354 (and (looking-at "[A-Za-z]")
355 (save-excursion
356 (forward-sexp 1)
357 (looking-at ":"))))
358 (setq indent (max 1 (+ indent cperl-label-offset))))
359 ((and (looking-at "else\\b")
360 (not (looking-at "else\\s_")))
361 (setq indent (save-excursion
362 (cperl-backward-to-start-of-if)
363 (current-indentation))))
364 ((= (following-char) ?})
365 (setq indent (- indent cperl-indent-level)))
366 ((= (following-char) ?{)
367 (setq indent (+ indent cperl-brace-offset))))))
368 (skip-chars-forward " \t")
369 (setq shift-amt (- indent (current-column)))
370 (if (zerop shift-amt)
371 (if (> (- (point-max) pos) (point))
372 (goto-char (- (point-max) pos)))
373 (delete-region beg (point))
374 (indent-to indent)
375 ;; If initial point was within line's indentation,
376 ;; position after the indentation. Else stay at same point in text.
377 (if (> (- (point-max) pos) (point))
378 (goto-char (- (point-max) pos))))
379 shift-amt))
380
381(defun calculate-cperl-indent (&optional parse-start)
382 "Return appropriate indentation for current line as C code.
383In usual case returns an integer: the column to indent to.
384Returns nil if line starts inside a string, t if in a comment."
385 (save-excursion
386 (beginning-of-line)
387 (let ((indent-point (point))
388 (case-fold-search nil)
389 state
390 containing-sexp)
391 (if parse-start
392 (goto-char parse-start)
393 (beginning-of-defun))
394 (while (< (point) indent-point)
395 (setq parse-start (point))
396 (setq state (parse-partial-sexp (point) indent-point 0))
397 (setq containing-sexp (car (cdr state))))
398 (cond ((or (nth 3 state) (nth 4 state))
399 ;; return nil or t if should not change this line
400 (nth 4 state))
401 ((null containing-sexp)
402 ;; Line is at top level. May be data or function definition,
403 ;; or may be function argument declaration.
404 ;; Indent like the previous top level line
405 ;; unless that ends in a closeparen without semicolon,
406 ;; in which case this line is the first argument decl.
407 (goto-char indent-point)
408 (skip-chars-forward " \t")
409 (if (= (following-char) ?{)
410 0 ; Unless it starts a function body
411 (cperl-backward-to-noncomment (or parse-start (point-min)))
412 ;; Look at previous line that's at column 0
413 ;; to determine whether we are in top-level decls
414 ;; or function's arg decls. Set basic-indent accordinglu.
415 (let ((basic-indent
416 (save-excursion
417 (re-search-backward "^[^ \^L\t\n#]" nil 'move)
418 (if (and (looking-at "\\sw\\|\\s_")
419 (looking-at ".*(")
420 (progn
421 (goto-char (1- (match-end 0)))
422 (forward-sexp 1)
423 (and (< (point) indent-point)
424 (not (memq (following-char)
425 '(?\, ?\;))))))
426 cperl-argdecl-indent 0))))
427 ;; Now add a little if this is a continuation line.
428 (+ basic-indent (if (or (bobp)
429 (memq (preceding-char) '(?\) ?\; ?\})))
430 0 cperl-continued-statement-offset)))))
431 ((/= (char-after containing-sexp) ?{)
432 ;; line is expression, not statement:
433 ;; indent to just after the surrounding open.
434 (goto-char (1+ containing-sexp))
435 (current-column))
436 (t
437 ;; Statement level. Is it a continuation or a new statement?
438 ;; Find previous non-comment character.
439 (goto-char indent-point)
440 (cperl-backward-to-noncomment containing-sexp)
441 ;; Back up over label lines, since they don't
442 ;; affect whether our line is a continuation.
443 (while (or (eq (preceding-char) ?\,)
444 (and (eq (preceding-char) ?:)
445 (or (eq (char-after (- (point) 2)) ?\')
446 (memq (char-syntax (char-after (- (point) 2)))
447 '(?w ?_)))))
448 (if (eq (preceding-char) ?\,)
449 (cperl-backward-to-start-of-continued-exp containing-sexp))
450 (beginning-of-line)
451 (cperl-backward-to-noncomment containing-sexp))
452 ;; Now we get the answer.
453 (if (not (memq (preceding-char) '(nil ?\, ?\; ?\} ?\{)))
454 ;; This line is continuation of preceding line's statement;
455 ;; indent cperl-continued-statement-offset more than the
456 ;; previous line of the statement.
457 (progn
458 (cperl-backward-to-start-of-continued-exp containing-sexp)
459 (+ cperl-continued-statement-offset (current-column)
460 (if (save-excursion (goto-char indent-point)
461 (skip-chars-forward " \t")
462 (eq (following-char) ?{))
463 cperl-continued-brace-offset 0)))
464 ;; This line starts a new statement.
465 ;; Position following last unclosed open.
466 (goto-char containing-sexp)
467 ;; Is line first statement after an open-brace?
468 (or
469 ;; If no, find that first statement and indent like it.
470 (save-excursion
471 (forward-char 1)
472 (let ((colon-line-end 0))
473 (while (progn (skip-chars-forward " \t\n")
474 (looking-at "#\\|/\\*\\|case[ \t\n].*:\\|[a-zA-Z0-9_$]*:"))
475 ;; Skip over comments and labels following openbrace.
476 (cond ((= (following-char) ?\#)
477 (forward-line 1))
478 ((= (following-char) ?\/)
479 (forward-char 2)
480 (search-forward "*/" nil 'move))
481 ;; case or label:
482 (t
483 (save-excursion (end-of-line)
484 (setq colon-line-end (point)))
485 (search-forward ":"))))
486 ;; The first following code counts
487 ;; if it is before the line we want to indent.
488 (and (< (point) indent-point)
489 (if (> colon-line-end (point))
490 (- (current-indentation) cperl-label-offset)
491 (current-column)))))
492 ;; If no previous statement,
493 ;; indent it relative to line brace is on.
494 ;; For open brace in column zero, don't let statement
495 ;; start there too. If cperl-indent-level is zero,
496 ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
497 ;; For open-braces not the first thing in a line,
498 ;; add in cperl-brace-imaginary-offset.
499 (+ (if (and (bolp) (zerop cperl-indent-level))
500 (+ cperl-brace-offset cperl-continued-statement-offset)
501 cperl-indent-level)
502 ;; Move back over whitespace before the openbrace.
503 ;; If openbrace is not first nonwhite thing on the line,
504 ;; add the cperl-brace-imaginary-offset.
505 (progn (skip-chars-backward " \t")
506 (if (bolp) 0 cperl-brace-imaginary-offset))
507 ;; If the openbrace is preceded by a parenthesized exp,
508 ;; move to the beginning of that;
509 ;; possibly a different line
510 (progn
511 (if (eq (preceding-char) ?\))
512 (forward-sexp -1))
513 ;; Get initial indentation of the line we are on.
514 (current-indentation))))))))))
515
516(defun calculate-cperl-indent-within-comment ()
517 "Return the indentation amount for line, assuming that
518the current line is to be regarded as part of a block comment."
519 (let (end star-start)
520 (save-excursion
521 (beginning-of-line)
522 (skip-chars-forward " \t")
523 (setq star-start (= (following-char) ?\*))
524 (skip-chars-backward " \t\n")
525 (setq end (point))
526 (beginning-of-line)
527 (skip-chars-forward " \t")
528 (and (re-search-forward "/\\*[ \t]*" end t)
529 star-start
530 (goto-char (1+ (match-beginning 0))))
531 (current-column))))
532
533
534(defun cperl-backward-to-noncomment (lim)
535 (let (opoint stop)
536 (while (not stop)
537 (skip-chars-backward " \t\n\f" lim)
538 (setq opoint (point))
539 (if (and (>= (point) (+ 2 lim))
540 (save-excursion
541 (forward-char -2)
542 (looking-at "\\*/")))
543 (search-backward "/*" lim 'move)
544 (beginning-of-line)
545 (skip-chars-forward " \t")
546 (setq stop (or (not (looking-at "#")) (<= (point) lim)))
547 (if stop (goto-char opoint)
548 (beginning-of-line))))))
549
550(defun cperl-backward-to-start-of-continued-exp (lim)
551 (if (= (preceding-char) ?\))
552 (forward-sexp -1))
553 (beginning-of-line)
554 (if (<= (point) lim)
555 (goto-char (1+ lim)))
556 (skip-chars-forward " \t"))
557
558(defun cperl-backward-to-start-of-if (&optional limit)
559 "Move to the start of the last ``unbalanced'' if."
560 (or limit (setq limit (save-excursion (beginning-of-defun) (point))))
561 (let ((if-level 1)
562 (case-fold-search nil))
563 (while (not (zerop if-level))
564 (backward-sexp 1)
565 (cond ((looking-at "else\\b")
566 (setq if-level (1+ if-level)))
567 ((looking-at "if\\b")
568 (setq if-level (1- if-level)))
569 ((< (point) limit)
570 (setq if-level 0)
571 (goto-char limit))))))
572
573\f
574(defun mark-cperl-function ()
575 "Put mark at end of C function, point at beginning."
576 (interactive)
577 (push-mark (point))
578 (end-of-defun)
579 (push-mark (point))
580 (beginning-of-defun)
581 (backward-paragraph))
582\f
583(defun indent-cperl-exp ()
584 "Indent each line of the C grouping following point."
585 (interactive)
586 (let ((indent-stack (list nil))
587 (contain-stack (list (point)))
588 (case-fold-search nil)
589 restart outer-loop-done inner-loop-done state ostate
590 this-indent last-sexp
591 at-else at-brace
592 (opoint (point))
593 (next-depth 0))
594 (save-excursion
595 (forward-sexp 1))
596 (save-excursion
597 (setq outer-loop-done nil)
598 (while (and (not (eobp)) (not outer-loop-done))
599 (setq last-depth next-depth)
600 ;; Compute how depth changes over this line
601 ;; plus enough other lines to get to one that
602 ;; does not end inside a comment or string.
603 ;; Meanwhile, do appropriate indentation on comment lines.
604 (setq innerloop-done nil)
605 (while (and (not innerloop-done)
606 (not (and (eobp) (setq outer-loop-done t))))
607 (setq ostate state)
608 (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
609 nil nil state))
610 (setq next-depth (car state))
611 (if (and (car (cdr (cdr state)))
612 (>= (car (cdr (cdr state))) 0))
613 (setq last-sexp (car (cdr (cdr state)))))
614 (if (or (nth 4 ostate))
615 (cperl-indent-line))
616 (if (or (nth 3 state))
617 (forward-line 1)
618 (setq innerloop-done t)))
619 (if (<= next-depth 0)
620 (setq outer-loop-done t))
621 (if outer-loop-done
622 nil
623 ;; If this line had ..))) (((.. in it, pop out of the levels
624 ;; that ended anywhere in this line, even if the final depth
625 ;; doesn't indicate that they ended.
626 (while (> last-depth (nth 6 state))
627 (setq indent-stack (cdr indent-stack)
628 contain-stack (cdr contain-stack)
629 last-depth (1- last-depth)))
630 (if (/= last-depth next-depth)
631 (setq last-sexp nil))
632 ;; Add levels for any parens that were started in this line.
633 (while (< last-depth next-depth)
634 (setq indent-stack (cons nil indent-stack)
635 contain-stack (cons nil contain-stack)
636 last-depth (1+ last-depth)))
637 (if (null (car contain-stack))
638 (setcar contain-stack (or (car (cdr state))
639 (save-excursion (forward-sexp -1)
640 (point)))))
641 (forward-line 1)
642 (skip-chars-forward " \t")
643 (if (eolp)
644 nil
645 (if (and (car indent-stack)
646 (>= (car indent-stack) 0))
647 ;; Line is on an existing nesting level.
648 ;; Lines inside parens are handled specially.
649 (if (/= (char-after (car contain-stack)) ?{)
650 (setq this-indent (car indent-stack))
651 ;; Line is at statement level.
652 ;; Is it a new statement? Is it an else?
653 ;; Find last non-comment character before this line
654 (save-excursion
655 (setq at-else (looking-at "else\\W"))
656 (setq at-brace (= (following-char) ?{))
657 (cperl-backward-to-noncomment opoint)
658 (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{)))
659 ;; Preceding line did not end in comma or semi;
660 ;; indent this line cperl-continued-statement-offset
661 ;; more than previous.
662 (progn
663 (cperl-backward-to-start-of-continued-exp (car contain-stack))
664 (setq this-indent
665 (+ cperl-continued-statement-offset (current-column)
666 (if at-brace cperl-continued-brace-offset 0))))
667 ;; Preceding line ended in comma or semi;
668 ;; use the standard indent for this level.
669 (if at-else
670 (progn (cperl-backward-to-start-of-if opoint)
671 (setq this-indent (current-indentation)))
672 (setq this-indent (car indent-stack))))))
673 ;; Just started a new nesting level.
674 ;; Compute the standard indent for this level.
675 (let ((val (calculate-cperl-indent
676 (if (car indent-stack)
677 (- (car indent-stack))))))
678 (setcar indent-stack
679 (setq this-indent val))))
680 ;; Adjust line indentation according to its contents
681 (if (or (looking-at "case[ \t]")
682 (and (looking-at "[A-Za-z]")
683 (save-excursion
684 (forward-sexp 1)
685 (looking-at ":"))))
686 (setq this-indent (max 1 (+ this-indent cperl-label-offset))))
687 (if (= (following-char) ?})
688 (setq this-indent (- this-indent cperl-indent-level)))
689 (if (= (following-char) ?{)
690 (setq this-indent (+ this-indent cperl-brace-offset)))
691 ;; Put chosen indentation into effect.
692 (or (= (current-column) this-indent)
693 (= (following-char) ?\#)
694 (progn
695 (delete-region (point) (progn (beginning-of-line) (point)))
696 (indent-to this-indent)))
697 ;; Indent any comment following the text.
698 (or (looking-at comment-start-skip)
699 (if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t)
700 (progn (indent-for-comment) (beginning-of-line)))))))))
701; (message "Indenting C expression...done")
702 )
703--cut here--
704--
705=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
706Vivek Khera, Gradual Student/Systems Guy Department of Computer Science
707Internet: khera@cs.duke.edu Box 90129
708 RIPEM/PGP/MIME spoken here Durham, NC 27708-0129 (919)660-6528
709
710