|
|
1.1 root 1: ;; Lisp mode, and its idiosyncratic commands.
2: ;; Copyright (C) 1985 Richard M. Stallman.
3:
4: ;; This file is part of GNU Emacs.
5:
6: ;; GNU Emacs is distributed in the hope that it will be useful,
7: ;; but WITHOUT ANY WARRANTY. No author or distributor
8: ;; accepts responsibility to anyone for the consequences of using it
9: ;; or for whether it serves any particular purpose or works at all,
10: ;; unless he says so in writing. Refer to the GNU Emacs General Public
11: ;; License for full details.
12:
13: ;; Everyone is granted permission to copy, modify and redistribute
14: ;; GNU Emacs, but only under the conditions described in the
15: ;; GNU Emacs General Public License. A copy of this license is
16: ;; supposed to have been given to you along with GNU Emacs so you
17: ;; can know your rights and responsibilities. It should be in a
18: ;; file named COPYING. Among other things, the copyright notice
19: ;; and this notice must be preserved on all copies.
20:
21:
22: (defvar lisp-mode-syntax-table nil "")
23: (defvar lisp-mode-abbrev-table nil "")
24:
25: (if (not lisp-mode-syntax-table)
26: (let ((i 0))
27: (setq lisp-mode-syntax-table (make-syntax-table))
28: (set-syntax-table lisp-mode-syntax-table)
29: (while (< i ?0)
30: (modify-syntax-entry i "_ ")
31: (setq i (1+ i)))
32: (setq i (1+ ?9))
33: (while (< i ?A)
34: (modify-syntax-entry i "_ ")
35: (setq i (1+ i)))
36: (setq i (1+ ?Z))
37: (while (< i ?a)
38: (modify-syntax-entry i "_ ")
39: (setq i (1+ i)))
40: (setq i (1+ ?z))
41: (while (< i 128)
42: (modify-syntax-entry i "_ ")
43: (setq i (1+ i)))
44: (modify-syntax-entry ? " ")
45: (modify-syntax-entry ?\t " ")
46: (modify-syntax-entry ?\n "> ")
47: (modify-syntax-entry ?\f "> ")
48: (modify-syntax-entry ?\; "< ")
49: (modify-syntax-entry ?` "' ")
50: (modify-syntax-entry ?' "' ")
51: (modify-syntax-entry ?, "' ")
52: (modify-syntax-entry ?. "' ")
53: (modify-syntax-entry ?# "' ")
54: (modify-syntax-entry ?\" "\" ")
55: (modify-syntax-entry ?\\ "\\ ")
56: (modify-syntax-entry ?\( "() ")
57: (modify-syntax-entry ?\) ")( ")))
58:
59: (define-abbrev-table 'lisp-mode-abbrev-table ())
60:
61: (defun lisp-mode-variables ()
62: (set-syntax-table lisp-mode-syntax-table)
63: (setq local-abbrev-table lisp-mode-abbrev-table)
64: (make-local-variable 'paragraph-start)
65: (setq paragraph-start (concat "^$\\|" page-delimiter))
66: (make-local-variable 'paragraph-separate)
67: (setq paragraph-separate paragraph-start)
68: (make-local-variable 'indent-line-function)
69: (setq indent-line-function 'lisp-indent-line)
70: (make-local-variable 'comment-start)
71: (setq comment-start ";")
72: (make-local-variable 'comment-start-skip)
73: (setq comment-start-skip ";+ *")
74: (make-local-variable 'comment-column)
75: (setq comment-column 40)
76: (make-local-variable 'comment-indent-hook)
77: (setq comment-indent-hook 'lisp-comment-indent))
78:
79: (defun lisp-mode-commands (map)
80: (define-key map "\e\C-q" 'indent-sexp)
81: (define-key map "\177" 'backward-delete-char-untabify)
82: (define-key map "\t" 'lisp-indent-line))
83:
84: (defvar emacs-lisp-mode-map (make-sparse-keymap) "")
85: (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun)
86: (lisp-mode-commands emacs-lisp-mode-map)
87:
88: (defun emacs-lisp-mode ()
89: "Major mode for editing Lisp code to run in Emacs.
90: Commands:
91: Delete converts tabs to spaces as it moves back.
92: Blank lines separate paragraphs. Semicolons start comments.
93: \\{emacs-lisp-mode-map}
94: Entry to this mode calls the value of emacs-lisp-mode-hook
95: if that value is non-nil."
96: (interactive)
97: (kill-all-local-variables)
98: (use-local-map emacs-lisp-mode-map)
99: (setq major-mode 'emacs-lisp-mode)
100: (setq mode-name "Emacs-Lisp")
101: (lisp-mode-variables)
102: (run-hooks 'emacs-lisp-mode-hook))
103:
104: (defvar lisp-mode-map (make-sparse-keymap))
105: (define-key lisp-mode-map "\e\C-x" 'lisp-send-defun)
106: (lisp-mode-commands lisp-mode-map)
107:
108: (defun lisp-mode ()
109: "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
110: Commands:
111: Delete converts tabs to spaces as it moves back.
112: Blank lines separate paragraphs. Semicolons start comments.
113: \\{lisp-mode-map}
114: Entry to this mode calls the value of lisp-mode-hook
115: if that value is non-nil."
116: (interactive)
117: (kill-all-local-variables)
118: (use-local-map lisp-mode-map)
119: (setq major-mode 'lisp-mode)
120: (setq mode-name "Lisp")
121: (lisp-mode-variables)
122: (run-hooks 'lisp-mode-hook))
123:
124: ;; This will do unless shell.el is loaded.
125: (defun lisp-send-defun nil
126: "Send the current defun to the Lisp process made by M-x run-lisp."
127: (interactive)
128: (error "Process lisp does not exist"))
129:
130: (defvar lisp-interaction-mode-map (make-sparse-keymap))
131: (lisp-mode-commands lisp-interaction-mode-map)
132: (define-key lisp-interaction-mode-map "\e\C-x" 'eval-defun)
133: (define-key lisp-interaction-mode-map "\n" 'eval-print-last-sexp)
134:
135: (defun lisp-interaction-mode ()
136: "Major mode for typing and evaluating Lisp forms.
137: Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
138: before point, and prints its value into the buffer, advancing point.
139:
140: Commands:
141: Delete converts tabs to spaces as it moves back.
142: Paragraphs are separated only by blank lines. Semicolons start comments.
143: \\{lisp-interaction-mode-map}
144: Entry to this mode calls the value of lisp-interaction-mode-hook
145: if that value is non-nil."
146: (interactive)
147: (kill-all-local-variables)
148: (use-local-map lisp-interaction-mode-map)
149: (setq major-mode 'lisp-interaction-mode)
150: (setq mode-name "Lisp Interaction")
151: (lisp-mode-variables)
152: (run-hooks 'lisp-interaction-mode-hook))
153:
154: (defun eval-print-last-sexp (arg)
155: "Evaluate sexp before point; print value into current buffer."
156: (interactive "P")
157: (eval-region
158: (let ((stab (syntax-table)))
159: (unwind-protect
160: (save-excursion
161: (set-syntax-table lisp-mode-syntax-table)
162: (forward-sexp -1)
163: (point))
164: (set-syntax-table stab)))
165: (point)
166: (current-buffer)))
167:
168: (defun eval-last-sexp (arg)
169: "Evaluate sexp before point; print value in minibuffer.
170: With argument, print output into current buffer."
171: (interactive "P")
172: (eval-region
173: (let ((stab (syntax-table)))
174: (unwind-protect
175: (save-excursion
176: (set-syntax-table lisp-mode-syntax-table)
177: (forward-sexp -1)
178: (point))
179: (set-syntax-table stab)))
180: (point)
181: (if arg (current-buffer) t)))
182:
183: (defun eval-defun (arg)
184: "Evaluate defun that point is in or before.
185: Print value in minibuffer.
186: With argument, insert value in current buffer after the defun."
187: (interactive "P")
188: (save-excursion
189: (end-of-defun)
190: (let ((end (point)))
191: (beginning-of-defun)
192: (eval-region (point) end
193: (if arg (current-buffer) t)))))
194:
195: (defun lisp-comment-indent ()
196: (if (looking-at ";;;")
197: (current-column)
198: (if (looking-at ";;")
199: (let ((tem (calculate-lisp-indent)))
200: (if (listp tem) (car tem) tem))
201: (skip-chars-backward " \t")
202: (max (if (bolp) 0 (1+ (current-column)))
203: comment-column))))
204:
205: (defconst lisp-indent-offset nil "")
206: (defconst lisp-indent-hook 'lisp-indent-hook "")
207:
208: (defun lisp-indent-line (&optional whole-exp)
209: "Indent current line as Lisp code.
210: With argument, indent any additional lines of the same expression
211: rigidly along with this one."
212: (interactive "P")
213: (let ((indent (calculate-lisp-indent)) shift-amt beg end
214: (pos (- (point-max) (point))))
215: (beginning-of-line)
216: (setq beg (point))
217: (skip-chars-forward " \t")
218: (if (looking-at "[ \t]*;;;")
219: ;; Don't alter indentation of a ;;; comment line.
220: nil
221: (if (listp indent) (setq indent (car indent)))
222: (setq shift-amt (- indent (current-column)))
223: (if (zerop shift-amt)
224: nil
225: (delete-region beg (point))
226: (indent-to indent))
227: ;; If initial point was within line's indentation,
228: ;; position after the indentation. Else stay at same point in text.
229: (if (> (- (point-max) pos) (point))
230: (goto-char (- (point-max) pos)))
231: ;; If desired, shift remaining lines of expression the same amount.
232: (and whole-exp (not (zerop shift-amt))
233: (save-excursion
234: (goto-char beg)
235: (forward-sexp 1)
236: (setq end (point))
237: (goto-char beg)
238: (forward-line 1)
239: (setq beg (point))
240: (> end beg))
241: (indent-code-rigidly beg end shift-amt)))))
242:
243: (defun calculate-lisp-indent (&optional parse-start)
244: "Return appropriate indentation for current line as Lisp code.
245: In usual case returns an integer: the column to indent to.
246: Can instead return a list, whose car is the column to indent to.
247: This means that following lines at the same level of indentation
248: should not necessarily be indented the same way.
249: The second element of the list is the buffer position
250: of the start of the containing expression."
251: (save-excursion
252: (beginning-of-line)
253: (let ((indent-point (point)) state paren-depth desired-indent (retry t)
254: last-sexp containing-sexp)
255: (if parse-start
256: (goto-char parse-start)
257: (beginning-of-defun))
258: ;; Find outermost containing sexp
259: (while (< (point) indent-point)
260: (setq state (parse-partial-sexp (point) indent-point 0)))
261: ;; Find innermost containing sexp
262: (while (and retry (setq paren-depth (car state)) (> paren-depth 0))
263: (setq retry nil)
264: (setq last-sexp (nth 2 state))
265: (setq containing-sexp (car (cdr state)))
266: ;; Position following last unclosed open.
267: (goto-char (1+ containing-sexp))
268: ;; Is there a complete sexp since then?
269: (if (and last-sexp (> last-sexp (point)))
270: ;; Yes, but is there a containing sexp after that?
271: (let ((peek (parse-partial-sexp last-sexp indent-point 0)))
272: (if (setq retry (car (cdr peek))) (setq state peek))))
273: (if (not retry)
274: ;; Innermost containing sexp found
275: (progn
276: (goto-char (1+ containing-sexp))
277: (if (not last-sexp)
278: ;; indent-point immediately follows open paren.
279: ;; Don't call hook.
280: (setq desired-indent (current-column))
281: ;; Move to first sexp after containing open paren
282: (parse-partial-sexp (point) last-sexp 0 t)
283: (cond
284: ((looking-at "\\s(")
285: ;; Looking at a list. Don't call hook.
286: (if (not (> (save-excursion (forward-line 1) (point))
287: last-sexp))
288: (progn (goto-char last-sexp)
289: (beginning-of-line)
290: (parse-partial-sexp (point) last-sexp 0 t)))
291: ;; Indent under the list or under the first sexp on the
292: ;; same line as last-sexp. Note that first thing on that
293: ;; line has to be complete sexp since we are inside the
294: ;; innermost containing sexp.
295: (backward-prefix-chars)
296: (setq desired-indent (current-column)))
297: ((> (save-excursion (forward-line 1) (point))
298: last-sexp)
299: ;; Last sexp is on same line as containing sexp.
300: ;; It's almost certainly a function call.
301: (parse-partial-sexp (point) last-sexp 0 t)
302: (if (/= (point) last-sexp)
303: ;; Indent beneath first argument or, if only one sexp
304: ;; on line, indent beneath that.
305: (progn (forward-sexp 1)
306: (parse-partial-sexp (point) last-sexp 0 t)))
307: (backward-prefix-chars))
308: (t
309: ;; Indent beneath first sexp on same line as last-sexp.
310: ;; Again, it's almost certainly a function call.
311: (goto-char last-sexp)
312: (beginning-of-line)
313: (parse-partial-sexp (point) last-sexp 0 t)
314: (backward-prefix-chars)))))))
315: ;; Point is at the point to indent under unless we are inside a string.
316: ;; Call indentation hook except when overriden by lisp-indent-offset
317: ;; or if the desired indentation has already been computed.
318: (cond ((car (nthcdr 3 state))
319: ;; Inside a string, don't change indentation.
320: (goto-char indent-point)
321: (skip-chars-forward " \t")
322: (setq desired-indent (current-column)))
323: ((and (integerp lisp-indent-offset) containing-sexp)
324: ;; Indent by constant offset
325: (goto-char containing-sexp)
326: (setq desired-indent (+ lisp-indent-offset (current-column))))
327: ((not (or desired-indent
328: (and (boundp 'lisp-indent-hook)
329: lisp-indent-hook
330: (not retry)
331: (setq desired-indent
332: (funcall lisp-indent-hook indent-point state)))))
333: ;; Use default indentation if not computed yet
334: (setq desired-indent (current-column))))
335: desired-indent)))
336:
337: (defun lisp-indent-hook (indent-point state)
338: (let ((normal-indent (current-column)))
339: (save-excursion
340: (goto-char (1+ (car (cdr state))))
341: (re-search-forward "\\sw\\|\\s_")
342: (if (/= (point) (car (cdr state)))
343: (let ((function (buffer-substring (progn (forward-char -1) (point))
344: (progn (forward-sexp 1) (point))))
345: method)
346: (setq method (get (intern-soft function) 'lisp-indent-hook))
347: (if (or (eq method 'defun)
348: (and (null method)
349: (> (length function) 3)
350: (string-equal (substring function 0 3) "def")))
351: (lisp-indent-defform state indent-point)
352: (if (integerp method)
353: (lisp-indent-specform method state indent-point)
354: (if method
355: (funcall method state indent-point)))))))))
356:
357: (defconst lisp-body-indent 2 "")
358:
359: (defun lisp-indent-specform (count state indent-point)
360: (let ((containing-form-start (car (cdr state))) (i count)
361: body-indent containing-form-column)
362: ;; Move to the start of containing form, calculate indentation
363: ;; to use for non-distinguished forms (> count), and move past the
364: ;; function symbol. lisp-indent-hook guarantees that there is at
365: ;; least one word or symbol character following open paren of containing
366: ;; form.
367: (goto-char containing-form-start)
368: (setq containing-form-column (current-column))
369: (setq body-indent (+ lisp-body-indent containing-form-column))
370: (forward-char 1)
371: (forward-sexp 1)
372: ;; Now find the start of the last form.
373: (parse-partial-sexp (point) indent-point 1 t)
374: (while (and (< (point) indent-point)
375: (condition-case nil
376: (progn
377: (setq count (1- count))
378: (forward-sexp 1)
379: (parse-partial-sexp (point) indent-point 1 t))
380: (error nil))))
381: ;; Point is sitting on first character of last (or count) sexp.
382: (if (> count 0)
383: ;; A distinguished form. If it is the first or second form use double
384: ;; lisp-body-indent, else normal indent. With lisp-body-indent bound
385: ;; to 2 (the default), this just happens to work the same with if as
386: ;; the older code, but it makes unwind-protect, condition-case,
387: ;; with-output-to-temp-buffer, et. al. much more tasteful. The older,
388: ;; less hacked, behavior can be obtained by replacing below with
389: ;; (list normal-indent containing-form-start).
390: (if (<= (- i count) 1)
391: (list (+ containing-form-column (* 2 lisp-body-indent))
392: containing-form-start)
393: (list normal-indent containing-form-start))
394: ;; A non-distinguished form. Use body-indent if there are no distinguished
395: ;; forms and this is the first undistinguished form, or if this is the
396: ;; first undistinguished form and the preceding distinguished form has
397: ;; indentation at least as great as body-indent.
398: (if (or (and (= i 0) (= count 0))
399: (and (= count 0) (<= body-indent normal-indent)))
400: body-indent
401: normal-indent))))
402:
403: (defun lisp-indent-defform (state indent-point)
404: (goto-char (car (cdr state)))
405: (forward-line 1)
406: (if (> (point) (car (cdr (cdr state))))
407: (progn
408: (goto-char (car (cdr state)))
409: (+ lisp-body-indent (current-column)))))
410:
411: ;; (put 'progn 'lisp-indent-hook 0), say, causes progn to be indented
412: ;; like defun if the first form is placed on the next line, otherwise
413: ;; it is indented like any other form (i.e. forms line up under first).
414:
415: (put 'lambda 'lisp-indent-hook 'defun)
416: (put 'progn 'lisp-indent-hook 0)
417: (put 'prog1 'lisp-indent-hook 1)
418: (put 'save-excursion 'lisp-indent-hook 0)
419: (put 'save-window-excursion 'lisp-indent-hook 0)
420: (put 'save-restriction 'lisp-indent-hook 0)
421: (put 'let 'lisp-indent-hook 1)
422: (put 'let* 'lisp-indent-hook 1)
423: (put 'while 'lisp-indent-hook 1)
424: (put 'if 'lisp-indent-hook 2)
425: (put 'catch 'lisp-indent-hook 1)
426: (put 'condition-case 'lisp-indent-hook 2)
427: (put 'unwind-protect 'lisp-indent-hook 1)
428: (put 'with-output-to-temp-buffer 'lisp-indent-hook 1)
429:
430: (defun indent-sexp ()
431: "Indent each line of the list starting just after point."
432: (interactive)
433: (let ((indent-stack (list nil)) (next-depth 0) bol
434: outer-loop-done inner-loop-done state this-indent)
435: (save-excursion (forward-sexp 1))
436: (save-excursion
437: (setq outer-loop-done nil)
438: (while (not outer-loop-done)
439: (setq last-depth next-depth
440: innerloop-done nil)
441: (while (and (not innerloop-done)
442: (not (setq outer-loop-done (eobp))))
443: (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
444: nil nil state))
445: (setq next-depth (car state))
446: (if (car (nthcdr 4 state))
447: (progn (indent-for-comment)
448: (end-of-line)
449: (setcar (nthcdr 4 state) nil)))
450: (if (car (nthcdr 3 state))
451: (progn
452: (forward-line 1)
453: (setcar (nthcdr 5 state) nil))
454: (setq innerloop-done t)))
455: (if (setq outer-loop-done (<= next-depth 0))
456: nil
457: (while (> last-depth next-depth)
458: (setq indent-stack (cdr indent-stack)
459: last-depth (1- last-depth)))
460: (while (< last-depth next-depth)
461: (setq indent-stack (cons nil indent-stack)
462: last-depth (1+ last-depth)))
463: (forward-line 1)
464: (setq bol (point))
465: (skip-chars-forward " \t")
466: (if (or (eobp) (looking-at "[;\n]"))
467: nil
468: (if (and (car indent-stack)
469: (>= (car indent-stack) 0))
470: (setq this-indent (car indent-stack))
471: (let ((val (calculate-lisp-indent
472: (if (car indent-stack) (- (car indent-stack))))))
473: (if (integerp val)
474: (setcar indent-stack
475: (setq this-indent val))
476: (setcar indent-stack (- (car (cdr val))))
477: (setq this-indent (car val)))))
478: (if (/= (current-column) this-indent)
479: (progn (delete-region bol (point))
480: (indent-to this-indent)))))))))
481:
482: (defun indent-code-rigidly (start end arg &optional nochange-regexp)
483: "Indent all lines of code, starting in the region, sideways by ARG columns.
484: Does not affect lines starting inside comments or strings,
485: assuming that the start of the region is not inside them.
486: Called from a program, takes args START, END, COLUMNS and NOCHANGE-REGEXP.
487: The last is a regexp which, if matched at the beginning of a line,
488: means don't indent that line."
489: (interactive "r\np")
490: (let (state)
491: (save-excursion
492: (goto-char end)
493: (setq end (point-marker))
494: (goto-char start)
495: (or (bolp)
496: (setq state (parse-partial-sexp (point)
497: (progn
498: (forward-line 1) (point))
499: nil nil state)))
500: (while (< (point) end)
501: (or (car (nthcdr 3 state))
502: (and nochange-regexp
503: (looking-at nochange-regexp))
504: ;; If line does not start in string, indent it
505: (let ((indent (current-indentation)))
506: (delete-region (point) (progn (skip-chars-forward " \t") (point)))
507: (or (eolp)
508: (indent-to (max 0 (+ indent arg)) 0))))
509: (setq state (parse-partial-sexp (point)
510: (progn
511: (forward-line 1) (point))
512: nil nil state))))))
513:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.