Change install- and uninstall- to -install and -uninstall.
[bpt/emacs.git] / lisp / emacs-lisp / lisp-mode.el
1 ;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands.
2
3 ;; Copyright (C) 1985 Free Software Foundation, Inc.
4
5 ;; Maintainer: FSF
6 ;; Keywords: lisp, languages
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 ;;; Code:
25
26 ;;; Commentary:
27
28 ;; The base major mode for editing Lisp code (used also for Emacs Lisp).
29 ;; This mode is documented in the Emacs manual
30
31 ;;; Code:
32
33 (defvar lisp-mode-syntax-table nil "")
34 (defvar emacs-lisp-mode-syntax-table nil "")
35 (defvar lisp-mode-abbrev-table nil "")
36
37 (if (not emacs-lisp-mode-syntax-table)
38 (let ((i 0))
39 (setq emacs-lisp-mode-syntax-table (make-syntax-table))
40 (while (< i ?0)
41 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
42 (setq i (1+ i)))
43 (setq i (1+ ?9))
44 (while (< i ?A)
45 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
46 (setq i (1+ i)))
47 (setq i (1+ ?Z))
48 (while (< i ?a)
49 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
50 (setq i (1+ i)))
51 (setq i (1+ ?z))
52 (while (< i 128)
53 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
54 (setq i (1+ i)))
55 (modify-syntax-entry ? " " emacs-lisp-mode-syntax-table)
56 (modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table)
57 (modify-syntax-entry ?\n "> " emacs-lisp-mode-syntax-table)
58 (modify-syntax-entry ?\f "> " emacs-lisp-mode-syntax-table)
59 (modify-syntax-entry ?\; "< " emacs-lisp-mode-syntax-table)
60 (modify-syntax-entry ?` "' " emacs-lisp-mode-syntax-table)
61 (modify-syntax-entry ?' "' " emacs-lisp-mode-syntax-table)
62 (modify-syntax-entry ?, "' " emacs-lisp-mode-syntax-table)
63 ;; Used to be singlequote; changed for flonums.
64 (modify-syntax-entry ?. "_ " emacs-lisp-mode-syntax-table)
65 (modify-syntax-entry ?# "' " emacs-lisp-mode-syntax-table)
66 (modify-syntax-entry ?\" "\" " emacs-lisp-mode-syntax-table)
67 (modify-syntax-entry ?\\ "\\ " emacs-lisp-mode-syntax-table)
68 (modify-syntax-entry ?\( "() " emacs-lisp-mode-syntax-table)
69 (modify-syntax-entry ?\) ")( " emacs-lisp-mode-syntax-table)
70 (modify-syntax-entry ?\[ "(] " emacs-lisp-mode-syntax-table)
71 (modify-syntax-entry ?\] ")[ " emacs-lisp-mode-syntax-table)))
72
73 (if (not lisp-mode-syntax-table)
74 (progn (setq lisp-mode-syntax-table
75 (copy-syntax-table emacs-lisp-mode-syntax-table))
76 (modify-syntax-entry ?\| "\" " lisp-mode-syntax-table)
77 (modify-syntax-entry ?\[ "_ " lisp-mode-syntax-table)
78 (modify-syntax-entry ?\] "_ " lisp-mode-syntax-table)))
79
80 (define-abbrev-table 'lisp-mode-abbrev-table ())
81
82 (defun lisp-mode-variables (lisp-syntax)
83 (cond (lisp-syntax
84 (set-syntax-table lisp-mode-syntax-table)))
85 (setq local-abbrev-table lisp-mode-abbrev-table)
86 (make-local-variable 'paragraph-start)
87 (setq paragraph-start (concat "^$\\|" page-delimiter))
88 (make-local-variable 'paragraph-separate)
89 (setq paragraph-separate paragraph-start)
90 (make-local-variable 'paragraph-ignore-fill-prefix)
91 (setq paragraph-ignore-fill-prefix t)
92 (make-local-variable 'indent-line-function)
93 (setq indent-line-function 'lisp-indent-line)
94 (make-local-variable 'indent-region-function)
95 (setq indent-region-function 'lisp-indent-region)
96 (make-local-variable 'parse-sexp-ignore-comments)
97 (setq parse-sexp-ignore-comments t)
98 (make-local-variable 'outline-regexp)
99 (setq outline-regexp ";;; \|(....")
100 (make-local-variable 'comment-start)
101 (setq comment-start ";")
102 (make-local-variable 'comment-start-skip)
103 (setq comment-start-skip ";+ *")
104 (make-local-variable 'comment-column)
105 (setq comment-column 40)
106 (make-local-variable 'comment-indent-function)
107 (setq comment-indent-function 'lisp-comment-indent))
108 \f
109 (defvar shared-lisp-mode-map ()
110 "Keymap for commands shared by all sorts of Lisp modes.")
111
112 (if shared-lisp-mode-map
113 ()
114 (setq shared-lisp-mode-map (make-sparse-keymap))
115 (define-key shared-lisp-mode-map "\e\C-q" 'indent-sexp)
116 (define-key shared-lisp-mode-map "\M-q" 'lisp-fill-paragraph)
117 (define-key shared-lisp-mode-map "\177" 'backward-delete-char-untabify)
118 (define-key shared-lisp-mode-map "\t" 'lisp-indent-line))
119
120 (defvar emacs-lisp-mode-map ()
121 "Keymap for Emacs Lisp mode.
122 All commands in shared-lisp-mode-map are inherited by this map.")
123
124 (if emacs-lisp-mode-map
125 ()
126 (setq emacs-lisp-mode-map
127 (nconc (make-sparse-keymap) shared-lisp-mode-map))
128 (define-key emacs-lisp-mode-map "\e\t" 'lisp-complete-symbol)
129 (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun))
130
131 (defun emacs-lisp-mode ()
132 "Major mode for editing Lisp code to run in Emacs.
133 Commands:
134 Delete converts tabs to spaces as it moves back.
135 Blank lines separate paragraphs. Semicolons start comments.
136 \\{emacs-lisp-mode-map}
137 Entry to this mode calls the value of `emacs-lisp-mode-hook'
138 if that value is non-nil."
139 (interactive)
140 (kill-all-local-variables)
141 (use-local-map emacs-lisp-mode-map)
142 (set-syntax-table emacs-lisp-mode-syntax-table)
143 (setq major-mode 'emacs-lisp-mode)
144 (setq mode-name "Emacs-Lisp")
145 (lisp-mode-variables nil)
146 (run-hooks 'emacs-lisp-mode-hook))
147
148 (defvar lisp-mode-map ()
149 "Keymap for ordinary Lisp mode.
150 All commands in `shared-lisp-mode-map' are inherited by this map.")
151
152 (if lisp-mode-map
153 ()
154 (setq lisp-mode-map
155 (nconc (make-sparse-keymap) shared-lisp-mode-map))
156 (define-key lisp-mode-map "\e\C-x" 'lisp-eval-defun)
157 (define-key lisp-mode-map "\C-c\C-z" 'run-lisp))
158
159 (defun lisp-mode ()
160 "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
161 Commands:
162 Delete converts tabs to spaces as it moves back.
163 Blank lines separate paragraphs. Semicolons start comments.
164 \\{lisp-mode-map}
165 Note that `run-lisp' may be used either to start an inferior Lisp job
166 or to switch back to an existing one.
167
168 Entry to this mode calls the value of `lisp-mode-hook'
169 if that value is non-nil."
170 (interactive)
171 (kill-all-local-variables)
172 (use-local-map lisp-mode-map)
173 (setq major-mode 'lisp-mode)
174 (setq mode-name "Lisp")
175 (lisp-mode-variables t)
176 (set-syntax-table lisp-mode-syntax-table)
177 (run-hooks 'lisp-mode-hook))
178
179 ;; This will do unless shell.el is loaded.
180 (defun lisp-eval-defun nil
181 "Send the current defun to the Lisp process made by \\[run-lisp]."
182 (interactive)
183 (error "Process lisp does not exist"))
184
185 (defvar lisp-interaction-mode-map ()
186 "Keymap for Lisp Interaction moe.
187 All commands in `shared-lisp-mode-map' are inherited by this map.")
188
189 (if lisp-interaction-mode-map
190 ()
191 (setq lisp-interaction-mode-map
192 (nconc (make-sparse-keymap) shared-lisp-mode-map))
193 (define-key lisp-interaction-mode-map "\e\C-x" 'eval-defun)
194 (define-key lisp-interaction-mode-map "\e\t" 'lisp-complete-symbol)
195 (define-key lisp-interaction-mode-map "\n" 'eval-print-last-sexp))
196
197 (defun lisp-interaction-mode ()
198 "Major mode for typing and evaluating Lisp forms.
199 Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
200 before point, and prints its value into the buffer, advancing point.
201
202 Commands:
203 Delete converts tabs to spaces as it moves back.
204 Paragraphs are separated only by blank lines.
205 Semicolons start comments.
206 \\{lisp-interaction-mode-map}
207 Entry to this mode calls the value of `lisp-interaction-mode-hook'
208 if that value is non-nil."
209 (interactive)
210 (kill-all-local-variables)
211 (use-local-map lisp-interaction-mode-map)
212 (setq major-mode 'lisp-interaction-mode)
213 (setq mode-name "Lisp Interaction")
214 (set-syntax-table emacs-lisp-mode-syntax-table)
215 (lisp-mode-variables nil)
216 (run-hooks 'lisp-interaction-mode-hook))
217
218 (defun eval-print-last-sexp ()
219 "Evaluate sexp before point; print value into current buffer."
220 (interactive)
221 (let ((standard-output (current-buffer)))
222 (terpri)
223 (eval-last-sexp t)
224 (terpri)))
225 \f
226 (defun eval-last-sexp (eval-last-sexp-arg-internal)
227 "Evaluate sexp before point; print value in minibuffer.
228 With argument, print output into current buffer."
229 (interactive "P")
230 (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))
231 (opoint (point)))
232 (prin1 (let ((stab (syntax-table)))
233 (eval (unwind-protect
234 (save-excursion
235 (set-syntax-table emacs-lisp-mode-syntax-table)
236 (forward-sexp -1)
237 (save-restriction
238 (narrow-to-region (point-min) opoint)
239 (read (current-buffer))))
240 (set-syntax-table stab)))))))
241
242 (defun eval-defun (eval-defun-arg-internal)
243 "Evaluate defun that point is in or before.
244 Print value in minibuffer.
245 With argument, insert value in current buffer after the defun."
246 (interactive "P")
247 (let ((standard-output (if eval-defun-arg-internal (current-buffer) t)))
248 (prin1 (eval (save-excursion
249 (end-of-defun)
250 (beginning-of-defun)
251 (read (current-buffer)))))))
252 \f
253 (defun lisp-comment-indent ()
254 (if (looking-at "\\s<\\s<\\s<")
255 (current-column)
256 (if (looking-at "\\s<\\s<")
257 (let ((tem (calculate-lisp-indent)))
258 (if (listp tem) (car tem) tem))
259 (skip-chars-backward " \t")
260 (max (if (bolp) 0 (1+ (current-column)))
261 comment-column))))
262
263 (defconst lisp-indent-offset nil "")
264 (defconst lisp-indent-function 'lisp-indent-function "")
265
266 (defun lisp-indent-line (&optional whole-exp)
267 "Indent current line as Lisp code.
268 With argument, indent any additional lines of the same expression
269 rigidly along with this one."
270 (interactive "P")
271 (let ((indent (calculate-lisp-indent)) shift-amt beg end
272 (pos (- (point-max) (point))))
273 (beginning-of-line)
274 (setq beg (point))
275 (skip-chars-forward " \t")
276 (if (looking-at "\\s<\\s<\\s<")
277 ;; Don't alter indentation of a ;;; comment line.
278 (goto-char (- (point-max) pos))
279 (if (and (looking-at "\\s<") (not (looking-at "\\s<\\s<")))
280 ;; Single-semicolon comment lines should be indented
281 ;; as comment lines, not as code.
282 (progn (indent-for-comment) (forward-char -1))
283 (if (listp indent) (setq indent (car indent)))
284 (setq shift-amt (- indent (current-column)))
285 (if (zerop shift-amt)
286 nil
287 (delete-region beg (point))
288 (indent-to indent)))
289 ;; If initial point was within line's indentation,
290 ;; position after the indentation. Else stay at same point in text.
291 (if (> (- (point-max) pos) (point))
292 (goto-char (- (point-max) pos)))
293 ;; If desired, shift remaining lines of expression the same amount.
294 (and whole-exp (not (zerop shift-amt))
295 (save-excursion
296 (goto-char beg)
297 (forward-sexp 1)
298 (setq end (point))
299 (goto-char beg)
300 (forward-line 1)
301 (setq beg (point))
302 (> end beg))
303 (indent-code-rigidly beg end shift-amt)))))
304
305 (defun calculate-lisp-indent (&optional parse-start)
306 "Return appropriate indentation for current line as Lisp code.
307 In usual case returns an integer: the column to indent to.
308 Can instead return a list, whose car is the column to indent to.
309 This means that following lines at the same level of indentation
310 should not necessarily be indented the same way.
311 The second element of the list is the buffer position
312 of the start of the containing expression."
313 (save-excursion
314 (beginning-of-line)
315 (let ((indent-point (point))
316 state paren-depth
317 ;; setting this to a number inhibits calling hook
318 (desired-indent nil)
319 (retry t)
320 last-sexp containing-sexp)
321 (if parse-start
322 (goto-char parse-start)
323 (beginning-of-defun))
324 ;; Find outermost containing sexp
325 (while (< (point) indent-point)
326 (setq state (parse-partial-sexp (point) indent-point 0)))
327 ;; Find innermost containing sexp
328 (while (and retry
329 state
330 (> (setq paren-depth (elt state 0)) 0))
331 (setq retry nil)
332 (setq last-sexp (elt state 2))
333 (setq containing-sexp (elt state 1))
334 ;; Position following last unclosed open.
335 (goto-char (1+ containing-sexp))
336 ;; Is there a complete sexp since then?
337 (if (and last-sexp (> last-sexp (point)))
338 ;; Yes, but is there a containing sexp after that?
339 (let ((peek (parse-partial-sexp last-sexp indent-point 0)))
340 (if (setq retry (car (cdr peek))) (setq state peek)))))
341 (if retry
342 nil
343 ;; Innermost containing sexp found
344 (goto-char (1+ containing-sexp))
345 (if (not last-sexp)
346 ;; indent-point immediately follows open paren.
347 ;; Don't call hook.
348 (setq desired-indent (current-column))
349 ;; Find the start of first element of containing sexp.
350 (parse-partial-sexp (point) last-sexp 0 t)
351 (cond ((looking-at "\\s(")
352 ;; First element of containing sexp is a list.
353 ;; Indent under that list.
354 )
355 ((> (save-excursion (forward-line 1) (point))
356 last-sexp)
357 ;; This is the first line to start within the containing sexp.
358 ;; It's almost certainly a function call.
359 (if (= (point) last-sexp)
360 ;; Containing sexp has nothing before this line
361 ;; except the first element. Indent under that element.
362 nil
363 ;; Skip the first element, find start of second (the first
364 ;; argument of the function call) and indent under.
365 (progn (forward-sexp 1)
366 (parse-partial-sexp (point) last-sexp 0 t)))
367 (backward-prefix-chars))
368 (t
369 ;; Indent beneath first sexp on same line as last-sexp.
370 ;; Again, it's almost certainly a function call.
371 (goto-char last-sexp)
372 (beginning-of-line)
373 (parse-partial-sexp (point) last-sexp 0 t)
374 (backward-prefix-chars)))))
375 ;; Point is at the point to indent under unless we are inside a string.
376 ;; Call indentation hook except when overridden by lisp-indent-offset
377 ;; or if the desired indentation has already been computed.
378 (let ((normal-indent (current-column)))
379 (cond ((elt state 3)
380 ;; Inside a string, don't change indentation.
381 (goto-char indent-point)
382 (skip-chars-forward " \t")
383 (current-column))
384 ((and (integerp lisp-indent-offset) containing-sexp)
385 ;; Indent by constant offset
386 (goto-char containing-sexp)
387 (+ (current-column) lisp-indent-offset))
388 (desired-indent)
389 ((and (boundp 'lisp-indent-function)
390 lisp-indent-function
391 (not retry))
392 (or (funcall lisp-indent-function indent-point state)
393 normal-indent))
394 (t
395 normal-indent))))))
396
397 (defun lisp-indent-function (indent-point state)
398 (let ((normal-indent (current-column)))
399 (goto-char (1+ (elt state 1)))
400 (parse-partial-sexp (point) last-sexp 0 t)
401 (if (and (elt state 2)
402 (not (looking-at "\\sw\\|\\s_")))
403 ;; car of form doesn't seem to be a a symbol
404 (progn
405 (if (not (> (save-excursion (forward-line 1) (point))
406 last-sexp))
407 (progn (goto-char last-sexp)
408 (beginning-of-line)
409 (parse-partial-sexp (point) last-sexp 0 t)))
410 ;; Indent under the list or under the first sexp on the
411 ;; same line as last-sexp. Note that first thing on that
412 ;; line has to be complete sexp since we are inside the
413 ;; innermost containing sexp.
414 (backward-prefix-chars)
415 (current-column))
416 (let ((function (buffer-substring (point)
417 (progn (forward-sexp 1) (point))))
418 method)
419 (setq method (or (get (intern-soft function) 'lisp-indent-function)
420 (get (intern-soft function) 'lisp-indent-hook)))
421 (cond ((or (eq method 'defun)
422 (and (null method)
423 (> (length function) 3)
424 (string-match "\\`def" function)))
425 (lisp-indent-defform state indent-point))
426 ((integerp method)
427 (lisp-indent-specform method state
428 indent-point normal-indent))
429 (method
430 (funcall method state indent-point)))))))
431
432 (defconst lisp-body-indent 2
433 "Number of columns to indent the second line of a `(def...)' form.")
434
435 (defun lisp-indent-specform (count state indent-point normal-indent)
436 (let ((containing-form-start (elt state 1))
437 (i count)
438 body-indent containing-form-column)
439 ;; Move to the start of containing form, calculate indentation
440 ;; to use for non-distinguished forms (> count), and move past the
441 ;; function symbol. lisp-indent-function guarantees that there is at
442 ;; least one word or symbol character following open paren of containing
443 ;; form.
444 (goto-char containing-form-start)
445 (setq containing-form-column (current-column))
446 (setq body-indent (+ lisp-body-indent containing-form-column))
447 (forward-char 1)
448 (forward-sexp 1)
449 ;; Now find the start of the last form.
450 (parse-partial-sexp (point) indent-point 1 t)
451 (while (and (< (point) indent-point)
452 (condition-case ()
453 (progn
454 (setq count (1- count))
455 (forward-sexp 1)
456 (parse-partial-sexp (point) indent-point 1 t))
457 (error nil))))
458 ;; Point is sitting on first character of last (or count) sexp.
459 (if (> count 0)
460 ;; A distinguished form. If it is the first or second form use double
461 ;; lisp-body-indent, else normal indent. With lisp-body-indent bound
462 ;; to 2 (the default), this just happens to work the same with if as
463 ;; the older code, but it makes unwind-protect, condition-case,
464 ;; with-output-to-temp-buffer, et. al. much more tasteful. The older,
465 ;; less hacked, behavior can be obtained by replacing below with
466 ;; (list normal-indent containing-form-start).
467 (if (<= (- i count) 1)
468 (list (+ containing-form-column (* 2 lisp-body-indent))
469 containing-form-start)
470 (list normal-indent containing-form-start))
471 ;; A non-distinguished form. Use body-indent if there are no
472 ;; distinguished forms and this is the first undistinguished form,
473 ;; or if this is the first undistinguished form and the preceding
474 ;; distinguished form has indentation at least as great as body-indent.
475 (if (or (and (= i 0) (= count 0))
476 (and (= count 0) (<= body-indent normal-indent)))
477 body-indent
478 normal-indent))))
479
480 (defun lisp-indent-defform (state indent-point)
481 (goto-char (car (cdr state)))
482 (forward-line 1)
483 (if (> (point) (car (cdr (cdr state))))
484 (progn
485 (goto-char (car (cdr state)))
486 (+ lisp-body-indent (current-column)))))
487
488 \f
489 ;; (put 'progn 'lisp-indent-function 0), say, causes progn to be indented
490 ;; like defun if the first form is placed on the next line, otherwise
491 ;; it is indented like any other form (i.e. forms line up under first).
492
493 (put 'lambda 'lisp-indent-function 'defun)
494 (put 'autoload 'lisp-indent-function 'defun)
495 (put 'progn 'lisp-indent-function 0)
496 (put 'prog1 'lisp-indent-function 1)
497 (put 'prog2 'lisp-indent-function 2)
498 (put 'save-excursion 'lisp-indent-function 0)
499 (put 'save-window-excursion 'lisp-indent-function 0)
500 (put 'save-restriction 'lisp-indent-function 0)
501 (put 'save-match-data 'lisp-indent-function 0)
502 (put 'let 'lisp-indent-function 1)
503 (put 'let* 'lisp-indent-function 1)
504 (put 'while 'lisp-indent-function 1)
505 (put 'if 'lisp-indent-function 2)
506 (put 'catch 'lisp-indent-function 1)
507 (put 'condition-case 'lisp-indent-function 2)
508 (put 'unwind-protect 'lisp-indent-function 1)
509 (put 'with-output-to-temp-buffer 'lisp-indent-function 1)
510
511 (defun indent-sexp (&optional endpos)
512 "Indent each line of the list starting just after point.
513 If optional arg ENDPOS is given, indent each line, stopping when
514 ENDPOS is encountered."
515 (interactive)
516 (let ((indent-stack (list nil))
517 (next-depth 0)
518 (starting-point (point))
519 (last-point (point))
520 last-depth bol outer-loop-done inner-loop-done state this-indent)
521 ;; Get error now if we don't have a complete sexp after point.
522 (save-excursion (forward-sexp 1))
523 (save-excursion
524 (setq outer-loop-done nil)
525 (while (if endpos (< (point) endpos)
526 (not outer-loop-done))
527 (setq last-depth next-depth
528 inner-loop-done nil)
529 ;; Parse this line so we can learn the state
530 ;; to indent the next line.
531 ;; This inner loop goes through only once
532 ;; unless a line ends inside a string.
533 (while (and (not inner-loop-done)
534 (not (setq outer-loop-done (eobp))))
535 (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
536 nil nil state))
537 (setq next-depth (car state))
538 ;; If the line contains a comment other than the sort
539 ;; that is indented like code,
540 ;; indent it now with indent-for-comment.
541 ;; Comments indented like code are right already.
542 ;; In any case clear the in-comment flag in the state
543 ;; because parse-partial-sexp never sees the newlines.
544 (if (car (nthcdr 4 state))
545 (progn (indent-for-comment)
546 (end-of-line)
547 (setcar (nthcdr 4 state) nil)))
548 ;; If this line ends inside a string,
549 ;; go straight to next line, remaining within the inner loop,
550 ;; and turn off the \-flag.
551 (if (car (nthcdr 3 state))
552 (progn
553 (forward-line 1)
554 (setcar (nthcdr 5 state) nil))
555 (setq inner-loop-done t)))
556 (and endpos
557 (<= next-depth 0)
558 (progn
559 (setq indent-stack (append indent-stack
560 (make-list (- next-depth) nil))
561 last-depth (- last-depth next-depth)
562 next-depth 0)))
563 (or outer-loop-done
564 (setq outer-loop-done (<= next-depth 0)))
565 (if outer-loop-done
566 (forward-line 1)
567 (while (> last-depth next-depth)
568 (setq indent-stack (cdr indent-stack)
569 last-depth (1- last-depth)))
570 (while (< last-depth next-depth)
571 (setq indent-stack (cons nil indent-stack)
572 last-depth (1+ last-depth)))
573 ;; Now go to the next line and indent it according
574 ;; to what we learned from parsing the previous one.
575 (forward-line 1)
576 (setq bol (point))
577 (skip-chars-forward " \t")
578 ;; But not if the line is blank, or just a comment
579 ;; (except for double-semi comments; indent them as usual).
580 (if (or (eobp) (looking-at "\\s<\\|\n"))
581 nil
582 (if (and (car indent-stack)
583 (>= (car indent-stack) 0))
584 (setq this-indent (car indent-stack))
585 (let ((val (calculate-lisp-indent
586 (if (car indent-stack) (- (car indent-stack))
587 starting-point))))
588 (if (integerp val)
589 (setcar indent-stack
590 (setq this-indent val))
591 (setcar indent-stack (- (car (cdr val))))
592 (setq this-indent (car val)))))
593 (if (/= (current-column) this-indent)
594 (progn (delete-region bol (point))
595 (indent-to this-indent)))))
596 (or outer-loop-done
597 (setq outer-loop-done (= (point) last-point))
598 (setq last-point (point)))))))
599
600 ;; Indent every line whose first char is between START and END inclusive.
601 (defun lisp-indent-region (start end)
602 (save-excursion
603 (goto-char start)
604 (and (bolp) (not (eolp))
605 (lisp-indent-line))
606 (let ((endmark (copy-marker end)))
607 (indent-sexp endmark)
608 (set-marker endmark nil))))
609 \f
610 ;;;; Lisp paragraph filling commands.
611
612 (defun lisp-fill-paragraph (&optional justify)
613 "Like \\[fill-paragraph], but handle Emacs Lisp comments.
614 If any of the current line is a comment, fill the comment or the
615 paragraph of it that point is in, preserving the comment's indentation
616 and initial semicolons."
617 (interactive "P")
618 (let (
619 ;; Non-nil if the current line contains a comment.
620 has-comment
621
622 ;; If has-comment, the appropriate fill-prefix for the comment.
623 comment-fill-prefix
624 )
625
626 ;; Figure out what kind of comment we are looking at.
627 (save-excursion
628 (beginning-of-line)
629 (cond
630
631 ;; A line with nothing but a comment on it?
632 ((looking-at "[ \t]*;[; \t]*")
633 (setq has-comment t
634 comment-fill-prefix (buffer-substring (match-beginning 0)
635 (match-end 0))))
636
637 ;; A line with some code, followed by a comment? Remember that the
638 ;; semi which starts the comment shouldn't be part of a string or
639 ;; character.
640 ((progn
641 (while (not (looking-at ";\\|$"))
642 (skip-chars-forward "^;\n\"\\\\?")
643 (cond
644 ((eq (char-after (point)) ?\\) (forward-char 2))
645 ((memq (char-after (point)) '(?\" ??)) (forward-sexp 1))))
646 (looking-at ";+[\t ]*"))
647 (setq has-comment t)
648 (setq comment-fill-prefix
649 (concat (make-string (current-column) ? )
650 (buffer-substring (match-beginning 0) (match-end 0)))))))
651
652 (if (not has-comment)
653 (fill-paragraph justify)
654
655 ;; Narrow to include only the comment, and then fill the region.
656 (save-restriction
657 (narrow-to-region
658 ;; Find the first line we should include in the region to fill.
659 (save-excursion
660 (while (and (zerop (forward-line -1))
661 (looking-at "^[ \t]*;")))
662 ;; We may have gone to far. Go forward again.
663 (or (looking-at "^[ \t]*;")
664 (forward-line 1))
665 (point))
666 ;; Find the beginning of the first line past the region to fill.
667 (save-excursion
668 (while (progn (forward-line 1)
669 (looking-at "^[ \t]*;")))
670 (point)))
671
672 ;; Lines with only semicolons on them can be paragraph boundaries.
673 (let ((paragraph-start (concat paragraph-start "\\|^[ \t;]*$"))
674 (paragraph-separate (concat paragraph-start "\\|^[ \t;]*$"))
675 (fill-prefix comment-fill-prefix))
676 (fill-paragraph justify))))))
677
678 \f
679 (defun indent-code-rigidly (start end arg &optional nochange-regexp)
680 "Indent all lines of code, starting in the region, sideways by ARG columns.
681 Does not affect lines starting inside comments or strings, assuming that
682 the start of the region is not inside them.
683
684 Called from a program, takes args START, END, COLUMNS and NOCHANGE-REGEXP.
685 The last is a regexp which, if matched at the beginning of a line,
686 means don't indent that line."
687 (interactive "r\np")
688 (let (state)
689 (save-excursion
690 (goto-char end)
691 (setq end (point-marker))
692 (goto-char start)
693 (or (bolp)
694 (setq state (parse-partial-sexp (point)
695 (progn
696 (forward-line 1) (point))
697 nil nil state)))
698 (while (< (point) end)
699 (or (car (nthcdr 3 state))
700 (and nochange-regexp
701 (looking-at nochange-regexp))
702 ;; If line does not start in string, indent it
703 (let ((indent (current-indentation)))
704 (delete-region (point) (progn (skip-chars-forward " \t") (point)))
705 (or (eolp)
706 (indent-to (max 0 (+ indent arg)) 0))))
707 (setq state (parse-partial-sexp (point)
708 (progn
709 (forward-line 1) (point))
710 nil nil state))))))
711
712 (provide 'lisp-mode)
713
714 ;;; lisp-mode.el ends here