[lice @ simulate interrupt key when waiting for input]
[lice.git] / lisp-mode.lisp
blob7af5664d1feb09289a66cddf22958e1bd297bd73
1 ;;; This is a cheap, pigeon lisp mode. One Day, it'll be replaced with
2 ;;; something amazing.
4 (in-package "LICE")
6 (defcustom *defun-prompt-regexp* nil
7 "*If non-nil, a regexp to ignore before a defun.
8 This is only necessary if the opening paren or brace is not in column 0.
9 See function `beginning-of-defun'."
10 :type '(choice (const nil)
11 regexp)
12 :group 'lisp)
14 (defvar *emacs-lisp-mode-syntax-table*
15 (let ((table (make-syntax-table)))
16 (loop for i from (char-code #\0) to (char-code #\9) do
17 (modify-syntax-entry (code-char i) :symbol-constituent :table table))
18 (loop for i from (char-code #\A) to (char-code #\Z) do
19 (modify-syntax-entry (code-char i) :symbol-constituent :table table))
21 (loop for i from (char-code #\a) to (char-code #\z) do
22 (modify-syntax-entry (code-char i) :symbol-constituent :table table))
24 (loop for c in '(#\{ #\| #\} #\~ #| 127 |#) do
25 (modify-syntax-entry c :symbol-constituent :table table))
27 (modify-syntax-entry #\Space :whitespace :table table)
28 (modify-syntax-entry #\Tab :whitespace :table table)
29 ;; XXX what is \f ? (modify-syntax-entry ?\f :whitespace :table table)
30 (modify-syntax-entry #\Newline :end-comment :table table)
31 ;; This is probably obsolete since nowadays such features use overlays.
32 ;; ;; Give CR the same syntax as newline, for selective-display.
33 ;; (modify-syntax-entry ?\^m "> " :table table)
34 (modify-syntax-entry #\; :comment :table table)
35 (modify-syntax-entry #\` :quote :table table)
36 (modify-syntax-entry #\' :quote :table table)
37 (modify-syntax-entry #\, :quote :table table)
38 (modify-syntax-entry #\@ :quote :table table)
39 ;; Used to be singlequote; changed for flonums.
40 (modify-syntax-entry #\. :symbol-constituent :table table)
41 (modify-syntax-entry #\# :quote :table table)
42 (modify-syntax-entry #\" :string :table table)
43 (modify-syntax-entry #\\ :escape :table table)
44 (modify-syntax-entry #\( :open :extra #\) :table table)
45 (modify-syntax-entry #\) :close :extra #\( :table table)
46 (modify-syntax-entry #\[ :open :extra #\] :table table)
47 (modify-syntax-entry #\] :close :extra #\[ :table table)
48 table))
50 (defvar *lisp-mode-syntax-table*
51 (let ((table (copy-syntax-table *emacs-lisp-mode-syntax-table*)))
52 (modify-syntax-entry #\[ :symbol-constituent :table table)
53 (modify-syntax-entry #\] :symbol-constituent :table table)
54 (modify-syntax-entry #\# :quote :flags '(:comment-start-first :comment-end-second :comment-style) :table table)
55 (modify-syntax-entry #\| :string :flags '(:comment-start-second :comment-end-first :comment-style :comment-nested) :table table)
56 table))
58 (define-major-mode lisp-interaction-mode
59 (:name "Lisp Interaction"
60 :map (let ((m (make-sparse-keymap)))
61 (define-key m (make-instance 'key :char #\j :control t) 'eval-print-last-sexp)
62 (define-key m (make-instance 'key :char #\Tab) 'lisp-indent-line)
63 (define-key m (make-instance 'key :char #\i :control t) 'lisp-indent-line)
64 (define-key m (make-instance 'key :char #\q :control t :meta t) 'indent-sexp)
65 (define-key m (make-instance 'key :char #\x :control t :meta t) 'eval-defun)
66 m))
67 "Lisp mode"
68 (set-syntax-table *lisp-mode-syntax-table*))
70 (defun buffer-end (arg)
71 "Return the \"far end\" position of the buffer, in direction ARG.
72 If ARG is positive, that's the end of the buffer.
73 Otherwise, that's the beginning of the buffer."
74 (if (> arg 0) (point-max) (point-min)))
76 (defvar *end-of-defun-function* nil
77 "If non-nil, function for function `end-of-defun' to call.
78 This is used to find the end of the defun instead of using the normal
79 recipe (see `end-of-defun'). Major modes can define this if the
80 normal method is not appropriate.")
82 (defcommand end-of-defun ((&optional arg)
83 :prefix)
84 "Move forward to next end of defun.
85 With argument, do it that many times.
86 Negative argument -N means move back to Nth preceding end of defun.
88 An end of a defun occurs right after the close-parenthesis that
89 matches the open-parenthesis that starts a defun; see function
90 `beginning-of-defun'.
92 If variable `*end-of-defun-function*' is non-nil, its value
93 is called as a function to find the defun's end."
94 (or (not (eq *this-command* 'end-of-defun))
95 (eq *last-command* 'end-of-defun)
96 ;;XXX (and transient-mark-mode mark-active)
97 (push-mark))
98 (if (or (null arg) (= arg 0)) (setq arg 1))
99 (if *end-of-defun-function*
100 (if (> arg 0)
101 (dotimes (i arg)
102 (funcall *end-of-defun-function*))
103 ;; Better not call beginning-of-defun-function
104 ;; directly, in case it's not defined.
105 (beginning-of-defun (- arg)))
106 (let ((first t))
107 (while (and (> arg 0) (< (point) (point-max)))
108 (let ((pos (point)))
109 (while (progn
110 (if (and first
111 (progn
112 (end-of-line 1)
113 (beginning-of-defun-raw 1)))
115 (progn
116 (or (bobp) (forward-char -1))
117 (beginning-of-defun-raw -1)))
118 (setq first nil)
119 (forward-list 1)
120 (skip-whitespace-forward)
121 (if (looking-at ";|\\n") ; XXX: used to be comment starter \\s<
122 (forward-line 1))
123 (<= (point) pos))))
124 (setq arg (1- arg)))
125 (while (< arg 0)
126 (let ((pos (point)))
127 (beginning-of-defun-raw 1)
128 (forward-sexp 1)
129 (forward-line 1)
130 (if (>= (point) pos)
131 (if (beginning-of-defun-raw 2)
132 (progn
133 (forward-list 1)
134 (skip-whitespace-forward)
135 (if (looking-at ";|\\n") ; XXX: used to be comment starter \\s<
136 (forward-line 1)))
137 (goto-char (point-min)))))
138 (setq arg (1+ arg))))))
140 (defvar *forward-sexp-function* nil
141 "If non-nil, `forward-sexp' delegates to this function.
142 Should take the same arguments and behave similarly to `forward-sexp'.")
144 (defcommand forward-sexp ((&optional (arg 1))
145 :prefix)
146 "Move forward across one balanced expression (sexp).
147 With ARG, do it that many times. Negative arg -N means
148 move backward across N balanced expressions."
149 (if *forward-sexp-function*
150 (funcall *forward-sexp-function* arg)
151 (progn
152 (goto-char (or (scan-sexps (point) arg) (buffer-end arg)))
153 (if (< arg 0) (backward-prefix-chars)))))
155 (defcommand backward-sexp ((&optional (arg 1))
156 :prefix)
157 "Move backward across one balanced expression (sexp).
158 With ARG, do it that many times. Negative arg -N means
159 move forward across N balanced expressions."
160 (forward-sexp (- arg)))
162 (defcommand forward-list ((&optional arg)
163 :prefix)
164 "Move forward across one balanced group of parentheses.
165 With ARG, do it that many times.
166 Negative arg -N means move backward across N groups of parentheses."
167 (or arg (setq arg 1))
168 (goto-char (or (scan-lists (point) arg 0) (buffer-end arg))))
170 (defcommand backward-list ((&optional arg)
171 :prefix)
172 "Move backward across one balanced group of parentheses.
173 With ARG, do it that many times.
174 Negative arg -N means move forward across N groups of parentheses."
175 (or arg (setq arg 1))
176 (forward-list (- arg)))
178 (defcommand eval-last-sexp ()
179 (let ((start (point))
180 end)
181 ;; some nice'n'gross point handling
182 (backward-sexp)
183 (setf end (point))
184 (goto-char start)
185 (handler-case (eval-echo (buffer-substring-no-properties start end))
186 (error (c) (message "Eval error: ~a" c)))))
188 (defcommand eval-print-last-sexp ()
189 (let ((start (point))
190 end)
191 ;; some nice'n'gross point handling
192 (backward-sexp)
193 (setf end (point))
194 (goto-char start)
195 (handler-case (eval-print (buffer-substring-no-properties start end))
196 (error (c) (message "Eval error: ~a" c)))))
198 (defcommand lisp-interaction-mode ()
199 (set-major-mode lisp-interaction-mode))
201 (defvar *lisp-indent-offset* nil
202 "If non-nil, indent second line of expressions that many more columns.")
204 (defvar *lisp-indent-function* 'common-lisp-indent-function)
206 (defcommand lisp-indent-line ((&optional whole-exp)
207 :raw-prefix)
208 "Indent current line as Lisp code.
209 With argument, indent any additional lines of the same expression
210 rigidly along with this one."
211 (let ((indent (calculate-lisp-indent)) shift-amt end
212 (pos (- (point-max) (point)))
213 (beg (progn (beginning-of-line) (point))))
214 (skip-whitespace-forward)
215 (if (or (null indent) (looking-at ";;;")) ; XXX: used to be comment starter \\s<
216 ;; Don't alter indentation of a ;;; comment line
217 ;; or a line that starts in a string.
218 (goto-char (- (point-max) pos))
219 (progn
220 (if (and (looking-at ";") (not (looking-at ";;"))) ; XXX: used to be comment starter \\s<
221 ;; Single-semicolon comment lines should be indented
222 ;; as comment lines, not as code.
223 (progn (indent-for-comment) (forward-char -1))
224 (progn
225 (if (listp indent) (setq indent (car indent)))
226 (setq shift-amt (- indent (current-column)))
227 (if (zerop shift-amt)
229 (progn
230 (delete-region beg (point))
231 (indent-to indent)))))
232 ;; If initial point was within line's indentation,
233 ;; position after the indentation. Else stay at same point in text.
234 (if (> (- (point-max) pos) (point))
235 (goto-char (- (point-max) pos)))
236 ;; If desired, shift remaining lines of expression the same amount.
237 (and whole-exp (not (zerop shift-amt))
238 (save-excursion
239 (goto-char beg)
240 (message "this111")
241 (forward-sexp 1)
242 (message "done 11")
243 (setq end (point))
244 (goto-char beg)
245 (forward-line 1)
246 (setq beg (point))
247 (> end beg))
248 (indent-code-rigidly beg end shift-amt))))))
250 (defvar *calculate-lisp-indent-last-sexp*)
252 (defun calculate-lisp-indent (&optional parse-start)
253 "Return appropriate indentation for current line as Lisp code.
254 In usual case returns an integer: the column to indent to.
255 If the value is nil, that means don't change the indentation
256 because the line starts inside a string.
258 The value can also be a list of the form (COLUMN CONTAINING-SEXP-START).
259 This means that following lines at the same level of indentation
260 should not necessarily be indented the same as this line.
261 Then COLUMN is the column to indent to, and CONTAINING-SEXP-START
262 is the buffer position of the start of the containing expression."
263 (save-excursion
264 (beginning-of-line)
265 (let ((indent-point (point))
266 state paren-depth
267 ;; setting this to a number inhibits calling hook
268 (desired-indent nil)
269 (retry t)
270 *calculate-lisp-indent-last-sexp* containing-sexp)
271 (if parse-start
272 (goto-char parse-start)
273 (beginning-of-defun))
274 ;; Find outermost containing sexp
275 (while (< (point) indent-point)
276 (message "flitz ~d" indent-point (point))
277 (setq state (parse-partial-sexp (point) indent-point :target-depth 0)))
278 ;; Find innermost containing sexp
279 (while (and retry
280 state
281 (> (setq paren-depth (parse-state-depth state)) 0))
282 (setq retry nil)
283 (setq *calculate-lisp-indent-last-sexp* (parse-state-this-level-start state))
284 (message "gaah ~d" *calculate-lisp-indent-last-sexp*)
285 (setq containing-sexp (parse-state-prev-level-start state))
286 ;; Position following last unclosed open.
287 (goto-char (1+ containing-sexp))
288 ;; Is there a complete sexp since then?
289 (if (and *calculate-lisp-indent-last-sexp*
290 (> *calculate-lisp-indent-last-sexp* (point)))
291 ;; Yes, but is there a containing sexp after that?
292 (let ((peek (parse-partial-sexp *calculate-lisp-indent-last-sexp*
293 indent-point :target-depth 0)))
294 (if (setq retry (parse-state-prev-level-start peek)) (setq state peek)))))
295 (message "retry ~a" retry)
296 (if retry
298 ;; Innermost containing sexp found
299 (progn
300 (goto-char (1+ containing-sexp))
301 (if (not *calculate-lisp-indent-last-sexp*)
302 ;; indent-point immediately follows open paren.
303 ;; Don't call hook.
304 (setq desired-indent (current-column))
305 (progn
306 ;; Find the start of first element of containing sexp.
307 (parse-partial-sexp (point) *calculate-lisp-indent-last-sexp* :target-depth 0 :stop-before t)
308 (cond ((looking-at "\\(") ; XXX used to be open \\s(
309 ;; First element of containing sexp is a list.
310 ;; Indent under that list.
312 ((> (save-excursion (forward-line 1) (point))
313 *calculate-lisp-indent-last-sexp*)
315 ;; This is the first line to start within the containing sexp.
316 ;; It's almost certainly a function call.
317 (if (= (point) *calculate-lisp-indent-last-sexp*)
318 ;; Containing sexp has nothing before this line
319 ;; except the first element. Indent under that element.
321 ;; Skip the first element, find start of second (the first
322 ;; argument of the function call) and indent under.
323 (progn (forward-sexp 1)
324 (parse-partial-sexp (point)
325 *calculate-lisp-indent-last-sexp*
326 :target-depth 0 :stop-before t)))
327 (backward-prefix-chars))
329 ;; Indent beneath first sexp on same line as
330 ;; `*calculate-lisp-indent-last-sexp*'. Again, it's
331 ;; almost certainly a function call.
332 (goto-char *calculate-lisp-indent-last-sexp*)
333 (beginning-of-line)
334 (parse-partial-sexp (point) *calculate-lisp-indent-last-sexp*
335 :target-depth 0 :stop-before t)
336 (backward-prefix-chars)))))))
337 ;; Point is at the point to indent under unless we are inside a string.
338 ;; Call indentation hook except when overridden by *lisp-indent-offset*
339 ;; or if the desired indentation has already been computed.
340 (let ((normal-indent (current-column)))
341 (cond ((parse-state-in-string state)
342 ;; Inside a string, don't change indentation.
343 nil)
344 ((and (integerp *lisp-indent-offset*) containing-sexp)
345 ;; Indent by constant offset
346 (goto-char containing-sexp)
347 (+ (current-column) *lisp-indent-offset*))
348 (desired-indent)
349 ((and (boundp '*lisp-indent-function*)
350 *lisp-indent-function*
351 (not retry))
352 (or (funcall *lisp-indent-function* indent-point state)
353 normal-indent))
355 normal-indent))))))
357 (defvar *beginning-of-defun-function* nil
358 "If non-nil, function for `beginning-of-defun-raw' to call.
359 This is used to find the beginning of the defun instead of using the
360 normal recipe (see `beginning-of-defun'). Major modes can define this
361 if defining `*defun-prompt-regexp*' is not sufficient to handle the mode's
362 needs.
364 The function (of no args) should go to the line on which the current
365 defun starts, and return non-nil, or should return nil if it can't
366 find the beginning.")
368 (defcommand beginning-of-defun-raw ((&optional (arg 1))
369 :prefix)
370 "Move point to the character that starts a defun.
371 This is identical to function `beginning-of-defun', except that point
372 does not move to the beginning of the line when `*defun-prompt-regexp*'
373 is non-nil.
375 If variable `*beginning-of-defun-function*' is non-nil, its value
376 is called as a function to find the defun's beginning."
377 (if *beginning-of-defun-function*
378 (if (> arg 0)
379 (dotimes (i arg)
380 (funcall *beginning-of-defun-function*))
381 ;; Better not call *end-of-defun-function* directly, in case
382 ;; it's not defined.
383 (end-of-defun (- arg)))
384 (progn
385 (when (and (< arg 0)
386 (not (eobp)))
387 (forward-char 1))
388 (let ((mdata (re-search-backward (if *defun-prompt-regexp*
389 (concat (if *open-paren-in-column-0-is-defun-start*
390 "^\\(|" "")
391 "(?:" *defun-prompt-regexp* ")\\(")
392 "\\n\\(") ;; used to be ^\\(
393 :error 'move :count (or arg 1))))
394 (when mdata
395 (goto-char (1- (match-end mdata 0)))) t))))
397 (defcommand beginning-of-defun ((&optional (arg 1))
398 :prefix)
399 "Move backward to the beginning of a defun.
400 With ARG, do it that many times. Negative arg -N
401 means move forward to Nth following beginning of defun.
402 Returns t unless search stops due to beginning or end of buffer.
404 Normally a defun starts when there is a char with open-parenthesis
405 syntax at the beginning of a line. If `*defun-prompt-regexp*' is
406 non-nil, then a string which matches that regexp may precede the
407 open-parenthesis, and point ends up at the beginning of the line.
409 If variable `*beginning-of-defun-function*' is non-nil, its value
410 is called as a function to find the defun's beginning."
411 (or (not (eq *this-command* 'beginning-of-defun))
412 (eq *last-command* 'beginning-of-defun)
413 ;;XXX (and transient-mark-mode mark-active)
414 (push-mark))
415 (and (beginning-of-defun-raw arg)
416 (progn (beginning-of-line) t)))
418 (defcommand indent-code-rigidly ((start end arg &optional nochange-regexp)
419 :region-beginning :region-end :prefix)
420 "Indent all lines of code, starting in the region, sideways by ARG columns.
421 Does not affect lines starting inside comments or strings, assuming that
422 the start of the region is not inside them.
424 Called from a program, takes args START, END, COLUMNS and NOCHANGE-REGEXP.
425 The last is a regexp which, if matched at the beginning of a line,
426 means don't indent that line."
427 (let (state)
428 (save-excursion
429 (goto-char end)
430 (setq end (point-marker))
431 (goto-char start)
432 (or (bolp)
433 (setq state (parse-partial-sexp (point)
434 (progn
435 (forward-line 1) (point))
436 :old-state state)))
437 (while (< (point) end)
438 (or (car (nthcdr 3 state))
439 (and nochange-regexp
440 (looking-at nochange-regexp))
441 ;; If line does not start in string, indent it
442 (let ((indent (current-indentation)))
443 (delete-region (point) (progn (skip-whitespace-forward) (point)))
444 (or (eolp)
445 (indent-to (max 0 (+ indent arg)) 0))))
446 (setq state (parse-partial-sexp (point)
447 (progn
448 (forward-line 1) (point))
449 :old-state state))))))
452 (defcommand indent-sexp ((&optional endpos))
453 "Indent each line of the list starting just after point.
454 If optional arg ENDPOS is given, indent each line, stopping when
455 ENDPOS is encountered."
456 (let ((indent-stack (list nil))
457 (next-depth 0)
458 ;; If ENDPOS is non-nil, use nil as STARTING-POINT
459 ;; so that calculate-lisp-indent will find the beginning of
460 ;; the defun we are in.
461 ;; If ENDPOS is nil, it is safe not to scan before point
462 ;; since every line we indent is more deeply nested than point is.
463 (starting-point (if endpos nil (point)))
464 (last-point (point))
465 last-depth bol outer-loop-done inner-loop-done state this-indent)
466 (or endpos
467 ;; Get error now if we don't have a complete sexp after point.
468 (save-excursion (forward-sexp 1)))
469 (save-excursion
470 (setq outer-loop-done nil)
471 (while (if endpos (< (point) (ensure-number endpos))
472 (not outer-loop-done))
473 (setq last-depth next-depth
474 inner-loop-done nil)
475 ;; Parse this line so we can learn the state
476 ;; to indent the next line.
477 ;; This inner loop goes through only once
478 ;; unless a line ends inside a string.
479 (while (and (not inner-loop-done)
480 (not (setq outer-loop-done (eobp))))
481 (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
482 :old-state state))
483 (setq next-depth (parse-state-depth state))
484 ;; If the line contains a comment other than the sort
485 ;; that is indented like code,
486 ;; indent it now with indent-for-comment.
487 ;; Comments indented like code are right already.
488 ;; In any case clear the in-comment flag in the state
489 ;; because parse-partial-sexp never sees the newlines.
490 (if (parse-state-in-comment state) ;;(car (nthcdr 4 state))
491 (progn (indent-for-comment)
492 (end-of-line)
493 (setf (parse-state-in-comment state) nil))) ;;(setcar (nthcdr 4 state) nil)))
494 ;; If this line ends inside a string,
495 ;; go straight to next line, remaining within the inner loop,
496 ;; and turn off the \-flag.
497 (if (parse-state-in-string state) ;;(car (nthcdr 3 state))
498 (progn
499 (forward-line 1)
500 (setf (parse-state-in-string state) nil));;(setf (car (nthcdr 5 state)) nil))
501 (setq inner-loop-done t)))
502 (and endpos
503 (<= next-depth 0)
504 (progn
505 (setq indent-stack (nconc indent-stack
506 (make-list (- next-depth) :initial-element nil))
507 last-depth (- last-depth next-depth)
508 next-depth 0)))
509 (or outer-loop-done endpos
510 (setq outer-loop-done (<= next-depth 0)))
511 (if outer-loop-done
512 (forward-line 1)
513 (progn
514 (while (> last-depth next-depth)
515 (setq indent-stack (cdr indent-stack)
516 last-depth (1- last-depth)))
517 (while (< last-depth next-depth)
518 (setq indent-stack (cons nil indent-stack)
519 last-depth (1+ last-depth)))
520 ;; Now go to the next line and indent it according
521 ;; to what we learned from parsing the previous one.
522 (forward-line 1)
523 (setq bol (point))
524 (skip-whitespace-forward)
525 ;; But not if the line is blank, or just a comment
526 ;; (except for double-semi comments; indent them as usual).
527 (if (or (eobp) (looking-at "\\w|\\n")) ;; FIXME: used to be "\\s<|\\n"
529 (progn
530 (if (and (car indent-stack)
531 (>= (car indent-stack) 0))
532 (setq this-indent (car indent-stack))
533 (let ((val (calculate-lisp-indent
534 (if (car indent-stack) (- (car indent-stack))
535 starting-point))))
536 (if (null val)
537 (setq this-indent val)
538 (if (integerp val)
539 (setf (car indent-stack)
540 (setq this-indent val))
541 (progn
542 (setf (car indent-stack) (- (car (cdr val))))
543 (setq this-indent (car val)))))))
544 (if (and this-indent (/= (current-column) this-indent))
545 (progn (delete-region bol (point))
546 (indent-to this-indent)))))))
547 (or outer-loop-done
548 (setq outer-loop-done (= (point) last-point))
549 (setq last-point (point)))))))
551 (defun lisp-indent-region (start end)
552 "Indent every line whose first char is between START and END inclusive."
553 (save-excursion
554 (let ((endmark (copy-marker end)))
555 (goto-char start)
556 (and (bolp) (not (eolp))
557 (lisp-indent-line))
558 (indent-sexp endmark)
559 (set-marker endmark nil))))
561 (defun eval-defun-1 (form)
562 "Treat some expressions specially.
563 Reset the `defvar' and `defcustom' variables to the initial value.
564 Reinitialize the face according to the `defface' specification."
565 ;; The code in edebug-defun should be consistent with this, but not
566 ;; the same, since this gets a macroexpended form.
567 (cond ((not (listp form))
568 form)
569 ((and (eq (car form) 'defvar)
570 (cdr-safe (cdr-safe form))
571 (boundp (cadr form)))
572 ;; Force variable to be re-set.
573 `(progn (defvar ,(nth 1 form) nil ,@(nthcdr 3 form))
574 (setf ,(nth 1 form) ,(nth 2 form)))) ;; used to be setq-default
575 ;; `defcustom' is now macroexpanded to
576 ;; `custom-declare-variable' with a quoted value arg.
577 ((and (eq (car form) 'custom-declare-variable)
578 (boundp (eval (nth 1 form)))) ;; used to be default-boundp
579 ;; Force variable to be bound.
580 ;; XXX: we can't handle defcustom
581 ;;(set-default (eval (nth 1 form)) (eval (nth 1 (nth 2 form))))
582 form)
583 ;; `defface' is macroexpanded to `custom-declare-face'.
584 ((eq (car form) 'custom-declare-face)
585 ;; Reset the face.
586 ;; XXX: what do we do with this?
587 ;; (setq face-new-frame-defaults
588 ;; (assq-delete-all (eval (nth 1 form)) face-new-frame-defaults))
589 ;; (put (eval (nth 1 form)) 'face-defface-spec nil)
590 ;; ;; Setting `customized-face' to the new spec after calling
591 ;; ;; the form, but preserving the old saved spec in `saved-face',
592 ;; ;; imitates the situation when the new face spec is set
593 ;; ;; temporarily for the current session in the customize
594 ;; ;; buffer, thus allowing `face-user-default-spec' to use the
595 ;; ;; new customized spec instead of the saved spec.
596 ;; ;; Resetting `saved-face' temporarily to nil is needed to let
597 ;; ;; `defface' change the spec, regardless of a saved spec.
598 ;; (prog1 `(prog1 ,form
599 ;; (put ,(nth 1 form) 'saved-face
600 ;; ',(get (eval (nth 1 form)) 'saved-face))
601 ;; (put ,(nth 1 form) 'customized-face
602 ;; ,(nth 2 form)))
603 ;; (put (eval (nth 1 form)) 'saved-face nil))
605 ((eq (car form) 'progn)
606 (cons 'progn (mapcar 'eval-defun-1 (cdr form))))
607 (t form)))
609 (defcommand eval-defun-2 ()
610 "Evaluate defun that point is in or before.
611 The value is displayed in the minibuffer.
612 If the current defun is actually a call to `defvar',
613 then reset the variable using the initial value expression
614 even if the variable already has some other value.
615 \(Normally `defvar' does not change the variable's value
616 if it already has a value.\)
618 With argument, insert value in current buffer after the defun.
619 Return the result of evaluation."
620 (let* ((*debug-on-error* *eval-expression-debug-on-error*)
621 (*print-length* *eval-expression-print-length*)
622 (*print-level* *eval-expression-print-level*)
623 ;; FIXME: accum the eval/compiler output and i guess do
624 ;; something with it, cept in this case we don't.
625 (*debug-io* (make-string-output-stream))
626 (*standard-output* *debug-io*)
627 (*error-output* *debug-io*))
628 (save-excursion
629 ;; FIXME: In gnu emacs eval-region handles recording which file defines
630 ;; a function or variable. How do we do that in CL?
632 (let ( ;;XXX (standard-output t)
633 beg end form)
634 ;; Read the form from the buffer, and record where it ends.
635 (save-excursion
636 (end-of-defun)
637 (beginning-of-defun)
638 (setq beg (point))
639 (setq form (read-from-buffer))
640 (setq end (point)))
641 ;; Alter the form if necessary. FIXME: we don't macroexpand
642 ;; but really we want to macroexpand down to defvar (and
643 ;; friends) which could be several layers of expansion
644 ;; down. We don't want to go all the way since defvar is
645 ;; itself a macro.
646 (setq form (eval-defun-1 form ;; (macroexpand form)
648 (eval form)))))
650 (defcommand eval-defun ((edebug-it)
651 :prefix)
652 "Evaluate the top-level form containing point, or after point.
654 If the current defun is actually a call to `defvar' or `defcustom',
655 evaluating it this way resets the variable using its initial value
656 expression even if the variable already has some other value.
657 \(Normally `defvar' and `defcustom' do not alter the value if there
658 already is one.)
660 If `eval-expression-debug-on-error' is non-nil, which is the default,
661 this command arranges for all errors to enter the debugger.
663 With a prefix argument, instrument the code for Edebug.
665 If acting on a `defun' for FUNCTION, and the function was
666 instrumented, `Edebug: FUNCTION' is printed in the minibuffer. If not
667 instrumented, just FUNCTION is printed.
669 If not acting on a `defun', the result of evaluation is displayed in
670 the minibuffer. This display is controlled by the variables
671 `eval-expression-print-length' and `eval-expression-print-level',
672 which see."
673 ;; FIXME: edebug?
674 (declare (ignore edebug-it))
675 (cond ;; (edebug-it
676 ;; (require 'edebug)
677 ;; (eval-defun (not edebug-all-defs)))
679 (if (null *eval-expression-debug-on-error*)
680 (eval-defun-2)
681 (let ((old-value (gensym "t")) new-value value)
682 (let ((*debug-on-error* old-value))
683 (setq value (eval-defun-2))
684 (setq new-value *debug-on-error*))
685 (unless (eq old-value new-value)
686 (setq *debug-on-error* new-value))
687 value)))))
690 (provide :lice-0.1/lisp-mode)