1 ;;; @(#) guile.el -- A GNU Emacs interface to Guile
2 ;;; @(#) $Keywords: guile, comint, scheme-mode $
4 ;; Copyright (C) 1995, 2002 Mikael Djurfeldt
7 ;; guile|djurfeldt@nada.kth.se|
8 ;; A GNU Emacs extension which |
9 ;; $Date: 2003-08-20 19:00:44 $|$Revision: 1.1 $|~/misc/guile.el.Z|
11 ;; Author: Mikael Djurfeldt <djurfeldt@nada.kth.se>
14 ;; This program is free software; you can redistribute it and/or modify it
15 ;; under the terms of the GNU General Public License as published by the Free
16 ;; Software Foundation; either version 2 of the License, or (at your option)
19 ;; This program is distributed in the hope that it will be useful, but
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 ;; You should have received a copy of the GNU General Public License along
25 ;; with GNU Emacs. If you did not, write to the Free Software Foundation,
26 ;; Inc., 675 Mass Ave., Cambridge, MA 02139, USA.
37 ;;; *************************************************************************
38 ;;; * This is code is currently under development *
39 ;;; * Mail any problems to djurfeldt@nada.kth.se *
40 ;;; *************************************************************************
45 (defvar guile-auto-attach nil
)
47 (defvar guile-load-hook nil
48 "*Hook run when file is loaded")
50 ;;(require 'cmuscheme)
51 (load "comint") ; `comint' and `cmuscheme' are already loaded.
52 (load "cmuscheme") ; We need to replace them.
54 ;; Faces are set in the cond expression below.
56 (defvar guile-error-face nil
57 "Face used to highlight erroneous scheme forms.")
59 (defvar guile-backtrace-mouse-face nil
60 "Face used when the mouse is over a backtrace frame.")
62 (defvar guile-modified-face nil
63 "Face for modified top-level forms in scheme-mode buffers.")
65 (defvar guile-broken-face nil
66 "Face for broken top-level forms in scheme-mode buffers.")
68 ;; These faces are used during debugging of the list parsing code.
70 (defvar guile-unmodified-face-1 nil
)
71 (defvar guile-unmodified-face-2 nil
)
72 (defvar guile-modified-face-1 nil
)
73 (defvar guile-modified-face-2 nil
)
74 (defvar guile-broken-face-1 nil
)
75 (defvar guile-broken-face-2 nil
)
80 (defvar guile-backtrace-in-source-window t
81 "*If non-nil, let backtrace windows appear in bottom of source window.
82 This only occurs if the erring expression can be located.")
84 (defvar guile-show-runlight-in-scheme-mode nil
85 "*If non-nil, show process status also in attached scheme-mode buffers.
86 Otherwise the mode-line shows if the buffer is attached or not.")
88 (defvar guile-default-enhanced-edit t
89 "If non-nil, automatically enter enhanced edit mode for scheme buffers.")
91 (defvar guile-popup-restart-on-death t
)
93 (defvar guile-popup-restart-on-stop t
)
95 (defvar guile-insert-reason t
)
97 (defvar guile-kill-buffer-on-death nil
)
99 (defvar guile-process-timeout
500
102 (defconst guile-backtrace-buffer-name
"*Scheme Backtrace*")
104 (defconst guile-error-buffer-name
"*Scheme Error*")
106 (defconst guile-backtrace-min-height
10)
107 (defconst guile-backtrace-max-height
30)
108 (defconst guile-backtrace-min-width
30)
109 (defconst guile-backtrace-max-width
90)
111 (cond ((not window-system
)
112 ;; Faces for text terminals
113 (setq guile-error-face
'modeline
)
114 (setq guile-backtrace-mouse-face
'highlight
)
115 (setq guile-modified-face nil
) ; no special face
116 (setq guile-broken-face nil
)
117 (setq guile-unmodified-face-1 nil
)
118 (setq guile-unmodified-face-2
'modeline
)
119 (setq guile-modified-face-1
'bold
)
120 (setq guile-modified-face-2 guile-error-face
)
121 (setq guile-broken-face-1 nil
)
122 (setq guile-broken-face-2 nil
))
124 ;; Faces for color screens
125 (setq guile-error-face
(lookup-face-create 'black
/red-bold
))
126 (setq guile-backtrace-mouse-face
'highlight
)
127 (setq guile-modified-face nil
) ; no special face
128 (setq guile-broken-face
'bold
)
129 (setq guile-unmodified-face-1
(lookup-face-create 'black
/lightblue
))
130 (setq guile-unmodified-face-2
'secondary-selection
)
131 (setq guile-modified-face-1
'highlight
)
132 (setq guile-modified-face-2
(lookup-face-create 'black
/pink
))
133 (setq guile-broken-face-1
134 (let ((face (make-face 'broken-form-1
)))
135 (copy-face guile-modified-face-1 face
)
136 (set-face-underline-p face t
)
138 (setq guile-broken-face-2
139 (let ((face (make-face 'broken-form-2
)))
140 (copy-face guile-modified-face-2 face
)
141 (set-face-underline-p face t
)
144 ;; Faces for monochrome screens
145 (setq guile-error-face
(lookup-face-create 'white
/black-bold
))
146 (setq guile-backtrace-mouse-face
'highlight
)
147 (setq guile-modified-face nil
) ; no special face
148 (setq guile-broken-face
'bold
)
149 (setq guile-unmodified-face-1 nil
)
150 (setq guile-unmodified-face-2
'modeline
)
151 (setq guile-modified-face-1
'bold
)
152 (setq guile-modified-face-2 guile-error-face
)
153 (setq guile-broken-face-1
154 (let ((face (make-face 'broken-form-1
)))
155 (copy-face guile-modified-face-1 face
)
156 (set-face-underline-p face t
)
158 (setq guile-broken-face-2
159 (let ((face (make-face 'broken-form-2
)))
160 (copy-face guile-modified-face-2 face
)
161 (set-face-underline-p face t
)
164 (if (not (fboundp 'lisp-mode-auto-fill
))
165 (defun lisp-mode-auto-fill ()
166 (if (> (current-column) (current-fill-column))
168 (nth 4 (parse-partial-sexp (save-excursion
173 (let ((comment-start nil
) (comment-start-skip nil
))
176 (defconst guile-symclash-obarray-size
521)
178 (defconst guile-big-integer
33333333)
180 ;;; Mode initializers
183 (defvar guile-inferior-scheme-frame nil
)
185 ;; Inferior Scheme Mode
187 (defun guile-inferior-initialize ()
188 ;; Buffer local variables
189 (make-local-variable 'guile-eval-result
)
190 (make-local-variable 'guile-eval-output
)
191 (make-local-variable 'guile-last-output-end
)
192 (make-local-variable 'guile-last-prompt-end
)
193 (make-local-variable 'guile-define-name-marker
)
194 (make-local-variable 'guile-unallowed-output
)
195 (make-local-variable 'guile-define-startcol
)
196 (make-local-variable 'guile-define-filler
)
197 (make-local-variable 'guile-define-fillcol
)
198 (set-process-sentinel (scheme-proc) (function guile-sentinel
))
199 (setq comint-dispatch-alist guile-dispatch-alist
)
200 (add-hook 'comint-input-filter-functions
201 (function guile-sync-on-input
) nil
'local
)
202 (add-hook 'comint-unallowed-output-filter-functions
203 (function guile-remember-unallowed-output
) nil
'local
)
204 (setq comint-dynamic-complete-functions
'(guile-complete-symbol))
205 (make-local-hook 'scheme-enter-input-wait-hook
)
206 ;; Some initializations
207 (setq scheme-ready-p nil
)
208 (setq scheme-load-p nil
)
209 (setq guile-no-stack-p nil
)
210 (setq guile-no-source-p nil
)
211 (setq guile-last-output-end
(make-marker))
212 (setq guile-last-prompt-end
(make-marker))
213 (setq guile-input-sent-p t
)
214 (setq guile-define-name-marker
(make-marker))
215 (setq guile-error-p nil
)
216 (setq guile-sexp-overlay nil
)
217 (setq guile-frame-overlay nil
)
218 (let ((enhanced (guile-get-enhanced-buffers)))
219 (and scheme-buffer
(guile-detach-all))
220 (for-each (function guile-normal-edit
) enhanced
)
221 (guile-kill-overlays)
222 (for-each (function (lambda (buffer)
227 (not scheme-buffer-modified-p
)))))
229 (setq guile-synchronizedp t
)
230 (setq comint-allow-output-p t
)
231 (setq guile-unallowed-output nil
)
234 (defvar default-handle-switch-frame-binding
235 (lookup-key global-map
[switch-frame
]))
236 (define-key global-map
[switch-frame
] 'guile-handle-switch-frame
)
238 (defun guile-handle-switch-frame (event)
240 (let ((frame (nth 1 event
)))
241 (if (eq frame guile-inferior-scheme-frame
)
242 (guile-sync-with-scheme))
243 (funcall default-handle-switch-frame-binding frame
)))
245 (defun guile-sync-on-input (string)
249 (setq guile-error-p nil
) ;; What is this??? *fixme*
250 (guile-sync-with-scheme)
253 ;; The read-only-overlay extends during transfer of error and
254 ;; backtrace information. Check why! *fixme*
255 (let ((inhibit-read-only t
))
257 ;; By generating an error we interrupt the execution
258 ;; of the comint-input-filter-functions hook.
259 (error "Bad expression! Please correct."))))
261 (defvar guile-unallowed-output nil
)
263 (defun guile-remember-unallowed-output (string)
264 (if guile-unallowed-output
265 (setq guile-unallowed-output
266 (concat guile-unallowed-output string
))))
268 (add-hook 'inferior-scheme-mode-hook
(function guile-inferior-initialize
))
272 (defvar scheme-buffer-overlays
()
273 "The overlays containing top-level sexps when in enhanced edit mode.
274 A nil value indicates that the buffer is not in enhanced edit mode.")
276 (defvar scheme-buffer-last-overlay nil
277 "When in enhanced edit mode, this variable contains the lowermost
280 (defvar scheme-buffer-modified-p nil
281 "Non-nil if any overlay has been modified since last synchronization.")
283 (defvar scheme-buffer-overlays-modified-p nil
)
285 (defvar scheme-associated-process-buffer nil
286 "The buffer of the scheme process to which this buffer is associated.
287 A value of nil means that this buffer is detached.")
289 (defvar scheme-overlay-repair-function nil
)
291 (make-variable-buffer-local 'scheme-overlay-repair-function
)
293 (defvar scheme-overlay-repair-idle-timer nil
)
295 (defun guile-scheme-mode-initialize ()
296 "Initialize a scheme mode buffer."
297 (make-local-variable 'scheme-buffer-overlays
)
298 (make-local-variable 'scheme-buffer-modified-p
)
299 (make-local-variable 'scheme-buffer-last-overlay
)
300 (make-local-variable 'scheme-buffer-overlays-modified-p
)
301 (make-local-variable 'scheme-associated-process-buffer
)
302 (make-local-variable 'guile-last-broken
)
303 (make-local-variable 'guile-repair-limit
)
304 (make-local-hook 'first-change-hook
)
305 (add-hook 'first-change-hook
(function guile-scheme-buffer-modified
) nil t
)
306 (make-local-hook 'kill-buffer-hook
)
307 (add-hook 'kill-buffer-hook
(function guile-scheme-mode-cleanup
) nil t
)
308 (if guile-default-enhanced-edit
309 (guile-enhanced-edit (current-buffer)
310 ;; If buffer not modified, take a chance...
311 (and (not scheme-buffer-modified-p
)
312 (not (buffer-modified-p (current-buffer))))
316 (add-hook 'scheme-mode-hook
(function guile-scheme-mode-initialize
))
318 (defun guile-scheme-buffer-modified ()
319 (setq scheme-buffer-modified-p t
))
321 (defun guile-scheme-mode-cleanup ()
322 (if (guile-attachedp (current-buffer))
324 (guile-sync-buffer (current-buffer))
325 (guile-detach-buffer (current-buffer))))
326 (if (guile-enhancedp (current-buffer))
327 (guile-normal-edit (current-buffer))))
329 ;;; User interface support
332 (defun guile-clear-transcript ()
333 "Delete all text before the last prompt in the scheme process buffer."
335 (if (or (not (buffer-name))
336 (not (string= (buffer-name) scheme-buffer
)))
337 (error "This command must be issued in the scheme process buffer!"))
339 (goto-char (or (marker-position guile-last-prompt-end
)
341 (if (re-search-backward comint-prompt-regexp nil t
)
342 (goto-char (match-beginning 0))
344 (let ((inhibit-read-only t
))
345 (delete-region (point-min) (point)))))
347 (defun guile-switch-to-scheme ()
348 "Switch to the scheme process buffer and places cursor at the end.
349 Also update the scheme process with all changes made in attached buffers."
351 (guile-sync-with-scheme)
352 ;(if (not guile-error-p)
353 ; (switch-to-scheme t))
354 (switch-to-scheme t
))
358 ;(defvar scheme-running-p nil
359 ; "This variable, if nil, indicates that the process is waiting for input.")
361 (defvar scheme-ready-p nil
362 "If non-nil, the process is waiting for input at the top-level repl.")
364 (defvar scheme-load-p nil
)
366 (defvar guile-no-stack-p nil
)
368 (defvar guile-no-source-p nil
)
370 (defun guile-inferior-dialog (contents)
371 (let ((window (display-buffer "*scheme*")))
372 (x-popup-dialog window contents
)))
374 (defun guile-sentinel (process reason
)
375 (let ((status (process-status process
)))
376 (if guile-insert-reason
377 (let ((old-buffer (current-buffer)))
380 (set-buffer (process-buffer process
))
381 (goto-char (point-max))
383 (goto-char (point-max))
385 (set-buffer old-buffer
))))
386 (cond ((eq status
'run
)
387 (scheme-set-runlight scheme-last-runlight
))
389 (scheme-set-runlight 'stopped
)
390 (if guile-popup-restart-on-stop
391 (if (guile-inferior-dialog '("The scheme process has been stopped.
392 Do you want to restart it?" ("Yes" . t
) nil
("No" . nil
)))
393 (continue-process process
))))
395 (guile-inferior-death-cleanup)
396 (if guile-popup-restart-on-death
397 (if (guile-inferior-dialog '("The scheme process has died.
398 Do you want to restart it?" ("Yes" . t
) nil
("No" . nil
)))
399 (run-scheme scheme-program-name
)
400 (or guile-kill-buffer-on-death
401 (kill-buffer "*scheme*")))
402 (or guile-kill-buffer-on-death
403 (kill-buffer "*scheme*")))))))
405 (defun guile-inferior-death-cleanup ()
406 (scheme-set-runlight nil
)
407 (setq scheme-ready-p nil
)
408 (setq scheme-virtual-file-list nil
)
411 ;; It would be too late to set this variable in the inferior-scheme-mode-hook:
412 ;;(setq comint-output-filter-function (function comint-dispatch-output-filter))
413 ;; *fixme* This should rather be done with advice.
415 (defun run-scheme (cmd)
416 "Run an inferior Scheme process, input and output via buffer *scheme*.
417 If there is a process already running in *scheme*, just switch to that buffer.
418 With argument, allows you to edit the command line (default is value
419 of scheme-program-name). Runs the hooks from inferior-scheme-mode-hook
420 \(after the comint-mode-hook is run).
421 \(Type \\[describe-mode] in the process buffer for a list of commands.)"
423 (interactive (list (if current-prefix-arg
424 (read-string "Run Scheme: " scheme-program-name
)
425 scheme-program-name
)))
426 (if (not (comint-check-proc "*scheme*"))
427 (let ((cmdlist (scheme-args-to-list cmd
))
428 (comint-output-filter-function
429 (function comint-dispatch-output-filter
)))
430 (set-buffer (apply 'make-comint
"scheme" (car cmdlist
)
432 (inferior-scheme-mode)))
433 (setq scheme-program-name cmd
)
434 (setq scheme-buffer
"*scheme*")
435 (pop-to-buffer "*scheme*")
436 ;; *fixme* Ugly to specialize `run-scheme' in this way...
437 (setq guile-inferior-scheme-frame
(selected-frame)))
439 (defun guile-restart-scheme ()
441 (let ((old-buffer (current-buffer)))
444 (set-buffer scheme-buffer
)
445 (let ((attached-buffers inferior-scheme-associated-buffers
))
447 (let ((inhibit-read-only t
))
449 (setq comint-allow-output-p t
)
450 (run-scheme scheme-program-name
)
452 (for-each (function (lambda (buffer)
453 (if (buffer-name buffer
)
454 (guile-attach-buffer buffer
))))
455 (reverse attached-buffers
))))
456 (set-buffer old-buffer
))))
458 (defun guile-shutdown ()
460 (let ((guile-popup-restart-on-death nil
)
461 (old-buffer (current-buffer)))
464 (set-buffer scheme-buffer
)
465 (setq comint-allow-output-p nil
) ; Hide output
466 (setq guile-unallowed-output nil
)
468 (let ((inhibit-read-only t
))
470 (comint-send-string (scheme-proc) "(quit)\n")
472 (while (and scheme-ready-p
(> countdown
0))
474 (setq countdown
(1- countdown
))))))
476 (if (comint-check-proc "*scheme*")
478 (kill-process (scheme-proc))
479 (while (comint-check-proc "*scheme*")
482 (set-buffer old-buffer
))))
484 (defun guile-exit-scheme ()
485 "Stop the running scheme process and kill the corresponding window"
488 (if (not (comint-check-proc "*scheme*"))
489 (kill-buffer "*scheme*")))
491 ;;; Basic process protocol
493 (setq guile-dispatch-alist
494 '((?f scheme-exit-input-wait scheme
:simple-action
)
495 (?l scheme-load-acknowledge scheme
:simple-action
)
496 (?r scheme-enter-read scheme
:simple-action
)
497 (?s scheme-enter-input-wait scheme
:simple-action
)
498 (?B guile-receive-backtrace scheme
:buffer-action
)
499 (?F guile-receive-error scheme
:buffer-action
)
500 (?x guile-receive-result scheme
:string-action
)
501 (?S guile-no-stack scheme
:simple-action
)
502 (?R guile-no-source scheme
:simple-action
)
505 (defun scheme:simple-action
(action)
506 (setq comint-dispatch-state
'idle
)
509 (defun scheme:string-action
(action)
510 (setq comint-string-receiver action
)
511 (setq comint-string-accumulator
"")
512 (setq comint-dispatch-state
'reading-string
))
514 (defun scheme:buffer-action
(action)
515 (setq comint-buffer-receiver action
)
516 (setq comint-receiving-buffer
(generate-new-buffer "*receiving-buffer*"))
517 (setq comint-dispatch-state
'reading-to-buffer
))
521 (defun guile-no-stack ()
522 (setq guile-no-stack-p t
))
524 (defun guile-no-source ()
525 (setq guile-no-source-p t
))
527 (defvar guile-eval-result nil
)
528 (defvar guile-eval-output nil
)
530 (defun guile-receive-result (string)
531 (setq comint-allow-output-p nil
)
532 (setq guile-eval-result string
)
533 (setq guile-eval-output guile-unallowed-output
)
534 (setq guile-unallowed-output nil
))
536 (defun guile-eval (sexp &optional stringp
)
537 (let ((process (scheme-proc)) ;*fixme*
538 (comint-input-filter-functions '())
539 (comint-output-filter-functions '()))
540 (if (not scheme-ready-p
)
541 (error "Scheme process not ready to receive commands."))
542 (setq guile-eval-result nil
)
543 (comint-send-string process
544 (format "(%%%%emacs-eval-request '%S)\n" sexp
))
545 (while (not guile-eval-result
)
546 (accept-process-output process
))
547 (while (not scheme-ready-p
)
548 (accept-process-output process
))
551 (car (read-from-string guile-eval-result
)))))
553 (defun scheme-set-runlight (runlight)
554 (setq inferior-scheme-mode-line-process
555 (or runlight
"no process"))
556 (setq scheme-last-runlight runlight
)
557 (if guile-show-runlight-in-scheme-mode
558 (let ((old-buffer (current-buffer))
559 (buffers inferior-scheme-associated-buffers
))
562 (set-buffer (car buffers
))
563 (setq scheme-mode-line-process runlight
)
564 (setq buffers
(cdr buffers
)))
565 (set-buffer old-buffer
))))
566 (force-mode-line-update t
))
568 (defconst scheme-runlight
:running
"eval"
569 "The character displayed when the Scheme process is running.")
571 (defconst scheme-runlight
:input
"ready"
572 "The character displayed when the Scheme process is waiting for input.")
574 (defconst scheme-runlight
:read
"input"
575 "The character displayed when the Scheme process is waiting for input.")
577 (defconst scheme-runlight
:load
"loading"
578 "The character displayed when the Scheme process is loading forms.")
580 (defvar guile-last-output-end
)
583 (defun scheme-enter-input-wait ()
584 (scheme-set-runlight scheme-runlight
:input
)
585 (setq scheme-running-p nil
)
586 (setq scheme-ready-p t
)
587 (setq count
(1+ count
))
588 ;(insert-before-markers (format "#%d\n" count))
590 ; l (append l (list (list n 'enter-input-wait))))
591 (if comint-allow-output-p
593 (set-marker guile-last-output-end
(point))
594 (if (and guile-input-sent-p
595 ;; This code can be invoked multiple times
596 (or (not (marker-position guile-last-prompt-end
))
597 (/= (marker-position guile-last-prompt-end
)
600 (setq guile-input-sent-p nil
)
601 (set-marker guile-last-prompt-end
(point))))))
602 (setq comint-allow-output-p t
)
603 (run-hooks 'scheme-enter-input-wait-hook
))
605 (defun guile-on-error ()
606 (setq guile-input-sent-p t
) ;*fixme*
607 (if comint-allow-output-p
609 (goto-char (point-max))
610 (if (not (zerop (current-column)))
612 (set-marker (process-mark (get-buffer-process scheme-buffer
))
615 (defun scheme-exit-input-wait ()
616 (scheme-set-runlight scheme-runlight
:running
)
617 (setq scheme-ready-p nil
)
618 (setq scheme-running-p t
))
620 (defun scheme-enter-read ()
621 (scheme-set-runlight scheme-runlight
:read
)
622 (setq scheme-ready-p nil
)
623 (setq scheme-running-p nil
))
625 (defun scheme-enter-load ()
626 (scheme-set-runlight scheme-runlight
:load
)
627 (setq scheme-ready-p nil
)
628 (setq scheme-load-p t
))
630 (defun scheme-load-acknowledge ()
631 (setq scheme-load-p nil
))
633 ;;; Error reporting and backtrace
635 (defvar guile-error-p nil
)
637 (defvar guile-last-displayed-position nil
)
639 (defvar guile-positional-reliability nil
)
641 (defvar guile-last-erring-overlay nil
)
643 (defvar guile-sexp-overlay nil
)
645 (defvar guile-frame-overlay nil
)
647 ;(defconst guile-position-regexp
648 ; " at line \\([0-9]+\\), column \\([0-9]+\\) in file \\(.+\\):$")
649 (defconst guile-position-regexp
650 "^\\(.+\\):\\([0-9]+\\):\\([0-9]+\\): ")
652 (defconst guile-position-regexp-line
2)
653 (defconst guile-position-regexp-column
3)
654 (defconst guile-position-regexp-filename
1)
656 (defvar guile-error-width
0)
657 (defvar guile-backtrace-length nil
)
658 (defvar guile-backtrace-width
0)
660 (defvar guile-error-map nil
)
663 (setq guile-error-map
;(copy-keymap global-map) copies menus too...
664 (cons 'keymap
(copy-sequence (nth 1 global-map
))))
665 (suppress-keymap guile-error-map
)
666 (define-key guile-error-map
"\e" 'guile-exit-debug
)
667 (define-key guile-error-map
"e" 'guile-frame-eval
)
668 (define-key guile-error-map
"q" 'guile-exit-debug
)
669 ;; The following line is included since `local-map' doesn't seem to work.
670 (define-key guile-error-map
[mouse-2
] 'guile-select-stackframe
)
671 (define-key guile-error-map
[S-mouse-2
] 'guile-frame-eval-at-click
)
674 (defvar guile-stack-frame-map nil
)
675 (if guile-stack-frame-map
677 (setq guile-stack-frame-map
(copy-list guile-error-map
))
678 (fset 'guile-stack-frame-map guile-stack-frame-map
) ;*fixme*
679 (define-key guile-stack-frame-map
[mouse-2
] 'guile-select-stackframe
)
682 (setplist 'guile-backtrace-button
683 (list 'mouse-face guile-backtrace-mouse-face
684 'local-map
'guile-stack-frame-map
))
686 (defun guile-exit-debug ()
688 (if (eq (selected-frame) guile-error-frame
)
690 (if guile-sexp-overlay
691 (delete-overlay guile-sexp-overlay
))
692 (delete-other-windows (frame-first-window)))
693 (guile-unselect-stackframe))
695 (setq guile-backtrace-received-p nil
) ;*fixme*
697 (defun guile-receive-backtrace (buffer)
698 (let ((backtrace (get-buffer-create guile-backtrace-buffer-name
)))
700 (set-buffer backtrace
)
703 (insert-buffer-substring buffer
)
705 (use-local-map guile-error-map
)
707 (setq truncate-lines t
)
708 (setq guile-backtrace-received-p t
)))) ;*fixme*
710 (defun guile-prep-backtrace ()
711 (guile-unselect-stackframe)
712 (let ((buffer (get-buffer-create guile-backtrace-buffer-name
)))
713 (and guile-got-backtrace-p
;*fixme*
716 (set-syntax-table scheme-mode-syntax-table
)
718 (goto-char (point-max))
719 (delete-backward-char 1)
720 (goto-char (point-min))
723 (if (not (looking-at "\\(.\\|\n\\)*Backtrace:\n"))
731 (let ((o (make-overlay beg
(point)))) ;(1- (point))
732 (overlay-put o
'category
'guile-backtrace-button
)
733 (overlay-put o
'frame-number-pos beg
))
734 (setq width
(- (point) beg
1))
735 (if (> width guile-backtrace-width
)
736 (setq guile-backtrace-width width
))
739 (setq guile-backtrace-length len
))))
740 (toggle-read-only 1)))
743 (defvar guile-selected-frame nil
)
745 (defun guile-select-stackframe (click)
747 (setq guile-no-stack-p nil
)
748 (setq guile-no-source-p nil
)
749 (let* ((frame (save-excursion
750 (mouse-set-point click
)
751 (goto-char (get-char-property (point) 'frame-number-pos
))
752 (guile-place-frame-overlay)
753 (let ((start (point)))
754 (skip-chars-forward " ")
755 (skip-chars-forward "0-9")
756 (if (= (char-after) ?
:)
757 ;; new backtrace format
760 (skip-chars-forward " ")
762 (skip-chars-forward "0-9")))
763 (string-to-number (buffer-substring-no-properties start
(point))))))
764 (oldpos (save-excursion
765 (set-buffer scheme-buffer
)
766 (guile-eval `(%%emacs-select-frame
,frame
))))
767 (pos (and oldpos
(list (nth 0 oldpos
)
768 (1+ (nth 1 oldpos
)) ;Increment line number
770 (setq guile-selected-frame frame
)
771 (cond (pos (if guile-source-window
;This is just insane *fixme*
772 (apply 'guile-display-scheme-sexp
773 (append pos
(list guile-source-window t
)))
774 (guile-display-error (get-buffer guile-error-buffer-name
)
775 (get-buffer guile-backtrace-buffer-name
)
777 (guile-no-stack-p (message "No stack."))
778 (guile-no-source-p (message "No source.")))))
780 (defun guile-unselect-stackframe ()
781 (guile-turn-off-frame-overlay)
782 (setq guile-selected-frame nil
))
784 (defun guile-frame-eval (string)
785 (interactive "sEval: ")
786 (if (not guile-selected-frame
)
787 (message "No frame selected.")
788 (setq guile-no-stack-p nil
)
789 (setq guile-no-source-p nil
)
790 (let ((res (save-excursion
791 (set-buffer scheme-buffer
)
792 (guile-eval `(%%emacs-frame-eval
,guile-selected-frame
794 (cond (guile-no-stack-p (message "No stack."))
795 (guile-no-source-p (message "No source."))
796 ((eq (car res
) 'result
) (message "%s = %s" string
(cadr res
)))
797 (t (message "%s" (cadr res
)))))))
799 (defun guile-frame-eval-at-click (click)
802 (mouse-set-point click
)
806 (guile-frame-eval (buffer-substring-no-properties (point) end
)))))
808 (defun guile-receive-error (buffer)
810 (setq guile-got-backtrace-p guile-backtrace-received-p
)
811 (setq guile-backtrace-received-p nil
) ;*fixme*
812 (setq guile-error-p t
)
813 (let ((errbuf (get-buffer-create guile-error-buffer-name
)))
818 (insert-buffer-substring buffer
)
820 (use-local-map guile-error-map
)
822 (setq guile-error-width
0)
823 (goto-char (point-min))
828 (setq width
(- (point) beg
1))
829 (if (> width guile-error-width
)
830 (setq guile-error-width width
))
832 (setq guile-backtrace-width guile-error-width
)
833 (guile-display-error errbuf
(guile-prep-backtrace)))))
835 (defvar guile-source-window nil
)
837 (defun guile-display-error (errbuf backbuf
&optional pos
)
839 (setq guile-source-window nil
)
840 (let* ((errbuf-len (progn
841 (goto-char (point-max))
842 (1- (guile-current-line))))
843 (selected-window (selected-window))
847 (apply 'guile-display-scheme-sexp pos
)
849 (goto-char (point-min))
850 (re-search-forward guile-position-regexp nil t
))
852 (guile-display-scheme-sexp
853 (car (read-from-string
855 (match-string guile-position-regexp-filename
)
857 (string-to-number (match-string guile-position-regexp-line
))
858 (1- (string-to-number (match-string guile-position-regexp-column
))))))))
861 (* 2 (/ guile-error-width
863 (window-width window
)
864 guile-backtrace-max-width
))))
865 ;;In case we get big error messages
866 (/ guile-backtrace-max-height
2)))
868 (if guile-got-backtrace-p
869 (min (max (+ guile-backtrace-length errbuf-lines
2)
870 guile-backtrace-min-height
)
871 guile-backtrace-max-height
)
872 (+ errbuf-lines
1))))
873 (if (and window guile-backtrace-in-source-window
)
875 (set-buffer errbuf
) ;*fixme* This is awkward...
877 (let ((inhibit-read-only t
))
879 (re-search-forward guile-position-regexp nil t
)
881 (setq guile-source-window window
) ;*fixme*
882 (and (frame-live-p guile-error-frame
)
883 (make-frame-invisible guile-error-frame
))
884 (let* ((window-min-height 2)
885 (size (max (- (window-height window
) total-height
)
886 (/ (window-height window
) 2)))
887 (new-window (split-window window size
)))
888 (set-buffer (window-buffer window
))
889 (goto-char guile-last-displayed-position
)
890 (guile-safe-forward-sexp)
891 (recenter (/ size
2))
892 (setq x errbuf-lines
)
893 (guile-display-buffers errbuf
(1+ errbuf-lines
) backbuf new-window
895 (setq guile-source-window nil
)
896 (guile-display-buffers
897 errbuf
(1+ errbuf-lines
) backbuf
899 (guile-get-create-error-window
901 (+ (min (max guile-backtrace-width
902 guile-backtrace-min-width
)
903 guile-backtrace-max-width
)
906 (cond ((window-live-p selected-window
)
907 (select-window selected-window
))
908 ((window-live-p window
)
909 (select-window window
))
910 ((window-live-p mini-window
)
911 (select-window mini-window
)))
912 ;; Warn if unreliable position
913 (if (and window
(not guile-positional-reliability
))
914 (message "Warning: Couldn't reliably locate erring expression."))
917 (defun guile-display-buffers (buffer1 split buffer2 window no-ding
)
918 "Display BUFFER1 and BUFFER2 in WINDOW and raise the containing frame.
919 Display BUFFER1 and BUFFER2 in two windows obtained by splitting WINDOW
920 and ring the bell. Make sure that the whole contents of BUFFER1 and the
921 lower part of BUFFER2 will be visible. Also delete all other windows
922 displaying the buffers."
923 ;; Delete other windows displaying the buffers
924 (or (not window-system
) (delete-windows-on buffer1
)) ; *fixme*
925 (delete-windows-on buffer2
)
928 (and guile-got-backtrace-p
929 (let ((window-min-height 2) ;; Parameter to split-window
931 (split-window window split
)))))
933 (set-window-buffer window buffer1
)
934 (and guile-got-backtrace-p
935 (set-window-buffer lower-window buffer2
))
937 (set-window-start window
1)
938 (if guile-got-backtrace-p
940 (let ((pos (save-excursion
942 (goto-char (point-max))
945 (set-window-point lower-window pos
))
946 (select-window lower-window
)
949 (make-frame-visible (window-frame window
))
950 (raise-frame (window-frame window
))
955 (defvar guile-error-frame nil
)
957 (defun guile-get-create-error-window (height width
)
960 (if (frame-live-p guile-error-frame
)
961 (set-frame-size guile-error-frame width height
)
962 (setq guile-error-frame
(make-frame (list (cons 'height height
)
965 '(menu-bar-lines .
0)))))
966 (let ((window (frame-first-window guile-error-frame
)))
967 (delete-other-windows window
)
969 (let ((window (get-buffer-window (pop-to-buffer guile-error-buffer-name
))))
970 (sit-for 0) ; necessary because of an Emacs bug
973 (defun guile-display-scheme-sexp (filename line column
&optional swindow no-error-p
)
974 (let ((finfo (scheme-virtual-file-list-find filename
)))
976 (guile-display-sexp finfo line column swindow no-error-p
)
977 (if (stringp filename
)
978 (let ((buffer (guile-get-file-buffer filename
)))
980 (if (and (guile-attachedp buffer
)
981 (not guile-known-by-scheme
))
983 ;(ding) ; We shouldn't generate errors inside a filter.
984 ;(message "Internal data structures corrupt: guile-display-scheme-sexp")
985 (error "Internal data structures corrupt: guile-display-scheme-sexp"))
986 (if (and (not scheme-buffer-modified-p
)
987 (not (buffer-modified-p buffer
)))
988 ;; Take a chance and let's hope the file looks
989 ;; like it did when scheme saw it...
991 (if guile-auto-attach
992 (guile-attach-buffer buffer t
)
994 (guile-dont-attach-buffer buffer t
))
995 (guile-display-scheme-sexp
996 (guile-buffer-file-name buffer
) line column swindow no-error-p
))
997 nil
; Can't trust this one...
999 (if (guile-file-readable-p filename
)
1000 (let ((guile-known-by-scheme t
))
1001 (let ((buffer (guile-find-file-noselect filename
)))
1002 (if guile-auto-attach
1003 (guile-attach-buffer buffer t
)
1005 (guile-dont-attach-buffer buffer t
))
1006 (guile-display-scheme-sexp
1007 (guile-buffer-file-name buffer
)
1008 line column swindow no-error-p
)))
1010 (message "Couldn't find the erring file.")
1013 (defun guile-file-readable-p (filename)
1015 (set-buffer scheme-buffer
)
1016 (file-readable-p filename
)))
1018 (defun guile-find-file-noselect (filename)
1020 (set-buffer scheme-buffer
)
1021 (find-file-noselect filename
)))
1023 (defun guile-display-sexp (finfo line column
&optional swindow no-error-p
)
1024 ;; Returns the window containing the displayed sexp
1025 (let ((overlay-list (cdr finfo
))
1027 ;; Select an overlay candidate
1029 (if (not (overlay-get (car overlay-list
) 'original-line
))
1030 (setq overlay-list
(cdr overlay-list
))
1031 (if (>= line
(overlay-get (car overlay-list
) 'original-line
))
1033 (setq overlay
(car overlay-list
))
1034 (setq overlay-list nil
))
1035 (setq overlay-list
(cdr overlay-list
)))))
1036 (let ((buffer (and overlay
(overlay-buffer overlay
))))
1040 (guile-goto-position line column overlay
)
1041 (if (< (point) (overlay-end overlay
))
1043 (setq guile-positional-reliability
1044 (not (overlay-get overlay
'modifiedp
)))
1045 (if (not (eq (char-syntax (following-char)) ?\
())
1047 (setq guile-positional-reliability nil
)
1048 (goto-char (overlay-start overlay
))))
1049 (setq guile-last-erring-overlay overlay
)
1050 (guile-display-sexp-at-point swindow no-error-p
))))))))
1052 (defun guile-display-sexp-at-point (&optional swindow no-error-p
)
1053 "Move sexp overlay to sexp at point and display window.
1054 Returns the displayed window."
1055 (let ((start (point))
1059 (if (guile-safe-forward-sexp)
1061 (goto-char (1+ start
))
1062 (if (re-search-forward "^\\((\\|$\\)" nil t
)
1063 (1- (match-beginning 0))
1065 (if (overlayp guile-sexp-overlay
)
1066 (move-overlay guile-sexp-overlay start end
(current-buffer))
1067 (setq guile-sexp-overlay
(make-overlay start end
))
1068 (overlay-put guile-sexp-overlay
'category
'guile-error-sexp
))
1069 (if (window-live-p swindow
)
1070 (set-window-buffer swindow
(current-buffer)))
1071 (guile-display-position start nil swindow no-error-p
)))
1073 (setplist 'guile-error-sexp
1074 (list 'face guile-error-face
1076 'modification-hooks
'(guile-turn-off-sexp-overlay)
1077 'insert-behind-hooks
'(guile-turn-off-sexp-overlay)))
1079 (setplist 'guile-stack-frame
1080 (list 'face guile-error-face
1081 'mouse-face guile-error-face
1083 'modification-hooks
'(guile-turn-off-frame-overlay)
1084 'insert-behind-hooks
'(guile-turn-off-frame-overlay)))
1086 (defun guile-place-frame-overlay ()
1087 (let ((end (save-excursion (forward-line) (point))))
1088 (if (and guile-frame-overlay
(overlayp guile-frame-overlay
))
1089 (move-overlay guile-frame-overlay
(point) end
)
1090 (setq guile-frame-overlay
(make-overlay (point) end
)))
1091 (overlay-put guile-frame-overlay
'category
'guile-stack-frame
)))
1093 (defun guile-turn-off-sexp-overlay (&rest args
)
1094 (cond (guile-sexp-overlay (delete-overlay guile-sexp-overlay
))
1096 ((overlayp (car args
)) (delete-overlay (car args
)))))
1098 (defun guile-turn-off-frame-overlay (&rest args
)
1099 (cond (guile-frame-overlay (delete-overlay guile-frame-overlay
))
1101 ((overlayp (car args
)) (delete-overlay (car args
)))))
1103 (defun guile-display-position (pos &optional buffer swindow no-delete-p
)
1104 "Display position POS in BUFFER.
1105 If BUFFER is omitted, the current buffer is used.
1106 Returns the displaying window."
1107 (let ((buffer (or buffer
(current-buffer))))
1109 (let ((window (or (and (window-live-p swindow
) swindow
)
1110 (get-buffer-window buffer t
)
1111 (if (frame-live-p guile-error-frame
)
1112 (delete-frame guile-error-frame
))
1113 (display-buffer buffer
))))
1115 (delete-other-windows window
))
1116 (select-window window
)
1118 (setq guile-last-displayed-position pos
)
1121 (defun guile-goto-position (line column overlay
)
1122 (goto-char (overlay-start overlay
))
1123 (forward-line (- line
(overlay-get overlay
'original-line
)))
1124 (move-to-column column
))
1127 ;;; Scheme process associated buffers
1130 ;; This function must be fixed to handle rel/absol filenames
1131 (defun guile-get-file-buffer (filename)
1132 (get-file-buffer filename
))
1134 (defun guile-attachedp (&optional buffer
)
1138 scheme-associated-process-buffer
)
1139 scheme-associated-process-buffer
))
1141 (defun guile-attach-buffer (buffer &optional known-by-scheme
)
1142 "Put the buffer in enhanced editing mode and attach it to the scheme
1143 process: load it into scheme, and make sure to send any changes to it
1144 hereafter to scheme at synchronization points."
1145 (interactive (list (current-buffer)))
1146 (if (memq buffer inferior-scheme-associated-buffers
)
1147 (error "Scheme buffer already attached!"))
1148 (if (not (guile-enhancedp buffer
))
1149 (guile-enhanced-edit buffer known-by-scheme
))
1151 (set-buffer scheme-buffer
)
1152 (setq inferior-scheme-associated-buffers
1154 inferior-scheme-associated-buffers
))
1156 (setq scheme-associated-process-buffer scheme-buffer
)
1157 (if (not guile-show-runlight-in-scheme-mode
)
1158 (setq scheme-mode-line-process
"attached"))
1159 ;; Now link it to the scheme process
1160 (if (and (guile-buffer-file-name)
1161 (not (guile-virtually-linked-p (guile-buffer-file-name))))
1162 (guile-virtual-link (guile-buffer-file-name) scheme-buffer-overlays
))
1164 (if (not known-by-scheme
)
1166 (for-each (function (lambda (overlay)
1167 (overlay-put overlay
'modifiedp t
)))
1168 scheme-buffer-overlays
)
1169 (setq scheme-buffer-modified-p t
)
1170 (setq guile-synchronizedp nil
)
1171 (guile-sync-with-scheme))))
1173 (force-mode-line-update))
1176 (defun guile-dont-attach-buffer (buffer &optional known-by-scheme
)
1177 "Put the buffer in enhanced editing mode and attach it to the scheme
1178 process: load it into scheme, and make sure to send any changes to it
1179 hereafter to scheme at synchronization points."
1180 (interactive (list (current-buffer)))
1181 (if (memq buffer inferior-scheme-associated-buffers
)
1182 (error "Scheme buffer already attached!"))
1183 (if (not (guile-enhancedp buffer
))
1184 (guile-enhanced-edit buffer known-by-scheme
))
1186 ; (set-buffer scheme-buffer)
1187 ; (setq inferior-scheme-associated-buffers
1189 ; inferior-scheme-associated-buffers))
1191 ; (setq scheme-associated-process-buffer scheme-buffer) == attach
1192 ; (if (not guile-show-runlight-in-scheme-mode)
1193 ; (setq scheme-mode-line-process "attached"))
1194 ;; Now link it to the scheme process
1195 (if (guile-buffer-file-name)
1196 (guile-virtual-link (guile-buffer-file-name) scheme-buffer-overlays
))
1198 (if (not known-by-scheme
)
1200 (for-each (function (lambda (overlay)
1201 (overlay-put overlay
'modifiedp t
)))
1202 scheme-buffer-overlays
)
1203 (setq scheme-buffer-modified-p t
)
1204 (setq guile-synchronizedp nil
)
1205 ;(guile-sync-with-scheme)
1208 (force-mode-line-update))
1210 (defun guile-detach-buffer (buffer)
1211 "Disconnect the buffer from the scheme process."
1212 (interactive (list (current-buffer)))
1215 ;; Unlink any virtual overlay files associated with the buffer...
1216 ;(let ((overlays scheme-buffer-overlays))
1218 ; (if (guile-virtual-p (car overlays))
1219 ; (scheme-virtual-unlink (overlay-get (car overlays) 'id)))
1220 ; (setq overlays (cdr overlays))))
1221 (setq scheme-associated-process-buffer nil
)
1222 (if (not guile-show-runlight-in-scheme-mode
)
1223 (setq scheme-mode-line-process nil
))
1224 (set-buffer scheme-buffer
)
1225 (setq inferior-scheme-associated-buffers
1227 inferior-scheme-associated-buffers
))
1228 ;(scheme-virtual-unlink (guile-buffer-file-name buffer))
1230 (force-mode-line-update))
1232 (defun guile-detach-all ()
1233 "Disconnect all buffers from the scheme process."
1236 (set-buffer scheme-buffer
)
1237 (while inferior-scheme-associated-buffers
1239 (if (buffer-name (car inferior-scheme-associated-buffers
))
1241 (set-buffer (car inferior-scheme-associated-buffers
))
1242 (setq scheme-associated-process-buffer nil
)
1243 (if (not guile-show-runlight-in-scheme-mode
)
1244 (setq scheme-mode-line-process nil
))))
1245 (setq inferior-scheme-associated-buffers
1246 (cdr inferior-scheme-associated-buffers
)))))
1248 ;;; Linkage of files to scheme space
1250 (defvar scheme-virtual-file-list
'())
1252 (defun scheme-virtual-file-list-find (name)
1253 (let ((name (file-truename name
)))
1254 (assoc name scheme-virtual-file-list
)))
1256 (defun guile-buffer-file-name (&optional buffer
)
1257 (let ((name (buffer-file-name buffer
)))
1259 (file-truename name
))))
1261 (defvar guile-synchronizedp t
)
1263 (defvar guile-last-virtual-id
0)
1265 (defun guile-synchronizedp ()
1266 guile-synchronizedp
)
1269 (defun guile-alloc-virtual-id (overlay)
1270 (let ((n (setq guile-last-virtual-id
(1+ guile-last-virtual-id
))))
1271 (let* ((buffer (overlay-buffer overlay
))
1272 (name (or (guile-buffer-file-name buffer
)
1273 (buffer-name buffer
))))
1274 (format "%s(%d)" name n
))))
1276 (defun guile-virtual-p (overlay)
1277 (overlay-get overlay
'virtualp
))
1279 (defun guile-virtually-linked-p (name)
1280 (scheme-virtual-file-list-find name
))
1282 (defun guile-virtual-link (name overlay-list
)
1283 (let ((finfo (scheme-virtual-file-list-find name
)))
1286 (guile-kill-overlays (cdr finfo
))
1287 (setcdr finfo
(copy-sequence overlay-list
)))
1288 (setq scheme-virtual-file-list
1290 (copy-sequence overlay-list
))
1291 scheme-virtual-file-list
)))))
1293 (defun scheme-virtual-unlink (name)
1294 (let ((finfo (scheme-virtual-file-list-find name
)))
1296 (setq scheme-virtual-file-list
1297 (delq finfo scheme-virtual-file-list
)))))
1299 (defun guile-load-file (filename)
1300 "Load a Scheme file into the inferior Scheme process."
1301 (interactive (comint-get-source "Load Scheme file: " scheme-prev-l
/c-dir
/file
1302 scheme-source-modes t
)) ; T because LOAD
1303 ; needs an exact name
1304 (if (not scheme-ready-p
)
1305 (error "Scheme not ready."))
1306 (comint-check-source filename
) ; Check to see if buffer needs to be saved.
1307 (setq scheme-prev-l
/c-dir
/file
(cons (file-name-directory filename
)
1308 (file-name-nondirectory filename
)))
1309 (let ((old-buffer (current-buffer)))
1310 (set-buffer scheme-buffer
)
1311 (setq comint-allow-output-p nil
)
1312 (setq guile-unallowed-output nil
)
1313 (set-buffer old-buffer
))
1314 (scheme-set-runlight scheme-runlight
:load
)
1315 (setq scheme-ready-p nil
)
1316 (comint-send-string (scheme-proc) (concat "(load \""
1320 (while (not scheme-ready-p
)
1321 (accept-process-output (scheme-proc) 0 guile-process-timeout
))
1324 (defun guile-reread-buffer (buffer)
1325 "Make the scheme interpreter read the buffer contents again."
1326 (interactive (list (current-buffer)))
1327 (if (not scheme-ready-p
)
1328 (error "Scheme not ready."))
1331 (for-each (function (lambda (overlay)
1332 (overlay-put overlay
'modifiedp t
)))
1333 scheme-buffer-overlays
)
1334 (setq scheme-buffer-modified-p t
))
1335 (setq guile-synchronizedp nil
)
1336 (guile-sync-with-scheme))
1338 (defun guile-get-associated-buffers ()
1340 (set-buffer scheme-buffer
)
1341 inferior-scheme-associated-buffers
))
1343 (defvar guile-symclash-obarray
(make-vector guile-symclash-obarray-size
0))
1345 (defun guile-reset-symclash-obarray ()
1346 (mapatoms (function makunbound
) guile-symclash-obarray
))
1348 (defvar guile-displayed-erring-buffers nil
)
1349 (defvar guile-quiet t
)
1351 (defun guile-check-all ()
1353 (setq guile-quiet t
)
1354 (guile-check-all-1))
1356 (defun guile-check-all-1 ()
1357 (guile-show-check-error
1358 (catch 'erroneous-overlay
1359 (guile-reset-symclash-obarray)
1360 (if (not (and guile-last-displayed-erring-overlay
1361 (eq (overlay-buffer guile-last-displayed-erring-overlay
)
1364 (setq guile-last-displayed-erring-overlay nil
)
1365 (setq guile-displayed-erring-buffers nil
)))
1366 (for-each (function (lambda (buffer)
1367 (guile-check-buffer-1 buffer
)
1368 (setq guile-displayed-erring-buffers
1370 guile-displayed-erring-buffers
))))
1371 (let ((ls (guile-get-enhanced-buffers))
1372 (rem guile-displayed-erring-buffers
))
1374 (setq ls
(delq (car rem
) ls
))
1375 (setq rem
(cdr rem
)))
1379 (defun guile-check-buffer (buffer)
1380 (interactive (list (current-buffer)))
1381 (guile-show-check-error
1382 (catch 'erroneous-overlay
1384 (guile-reset-symclash-obarray)
1385 (guile-check-buffer-1 buffer
)
1386 ;(set-buffer old-buffer)
1389 (defun guile-show-check-error (oinfo)
1392 (if guile-last-displayed-erring-overlay
1393 (message "No more errors found among buffers in enhanced editing mode!")
1394 (message "No errors found among buffers in enhanced editing mode!"))
1395 (setq guile-last-displayed-erring-overlay nil
)
1396 (setq guile-displayed-erring-buffers nil
)
1398 (setq guile-last-displayed-erring-overlay
(car oinfo
))
1399 (set-buffer (overlay-buffer (car oinfo
)))
1400 (goto-char (overlay-start (car oinfo
)))
1401 (if (not guile-quiet
)
1403 (guile-display-sexp-at-point)
1405 (message "%s" (cdr oinfo
))
1408 (defvar guile-last-displayed-erring-overlay nil
)
1410 (defun guile-check-buffer-1 (buffer)
1413 (for-each (function guile-check-overlay
)
1414 (let* ((ls (reverse scheme-buffer-overlays
))
1415 (tail (memq guile-last-displayed-erring-overlay ls
)))
1420 (defconst guile-defexpr
"(\\(define\\|defmacro\\)[^ \t\n()]*[ \t\n]+(*\\([^ \t\n()]+\\)")
1421 (defconst guile-defexpr-name
2)
1423 (defun guile-check-overlay (overlay)
1424 (if (overlay-get overlay
'brokenp
)
1425 (throw 'erroneous-overlay
1426 (cons overlay
"Bad expression."))
1427 (goto-char (overlay-start overlay
))
1428 (if (looking-at guile-defexpr
)
1429 (let ((sym (intern (match-string guile-defexpr-name
)
1430 guile-symclash-obarray
)))
1432 (let* ((overlay1 (symbol-value sym
))
1433 (buffer (overlay-buffer overlay1
))
1434 (line (save-excursion
1437 (goto-char (overlay-start overlay1
))
1438 (guile-current-line)))))
1439 (throw 'erroneous-overlay
1441 (format "Symbol \"%s\" already defined in %s, line %d."
1443 (file-name-nondirectory
1444 (or (guile-buffer-file-name buffer
)
1445 (buffer-name buffer
)))
1447 (set sym overlay
))))))
1449 (defun guile-sync-with-scheme ()
1451 (if (and (not guile-synchronizedp
)
1454 (setq guile-error-p nil
)
1455 (setq guile-last-erring-overlay nil
)
1457 (for-each (function guile-sync-buffer-1
)
1458 (guile-get-associated-buffers))
1459 (setq guile-synchronizedp t
))
1460 (if guile-last-erring-overlay
1462 (overlay-put guile-last-erring-overlay
'brokenp t
)
1463 (overlay-put guile-last-erring-overlay
1464 'face guile-broken-face
)
1465 (if guile-show-overlays-p
1467 (set-buffer (overlay-buffer guile-last-erring-overlay
))
1468 (guile-show-overlays))))))))
1470 (defun guile-sync-buffer (buffer)
1471 (interactive (list (current-buffer)))
1473 (guile-sync-buffer-1 buffer
)))
1475 (defun guile-sync-buffer-1 (buffer)
1478 (if scheme-buffer-modified-p
1480 ;; Can we do it by loading the file again?
1481 (if (and (not (buffer-modified-p buffer
))
1482 (file-readable-p (guile-buffer-file-name))
1483 (not (let ((overlays scheme-buffer-overlays
))
1484 (while (and overlays
1485 (not (overlay-get (car overlays
) 'brokenp
)))
1486 (goto-char (overlay-start (car overlays
)))
1487 (overlay-put (car overlays
) 'original-line
1488 (guile-current-line)) ; non-optimal *fixme*
1489 (setq overlays
(cdr overlays
)))
1492 (guile-load-file (guile-buffer-file-name))
1496 (let ((overlays scheme-buffer-overlays
))
1498 (overlay-put (car overlays
) 'modifiedp nil
)
1499 (setq overlays
(cdr overlays
)))))
1500 ;; No - we have to send the overlays separately from top to bottom
1501 (let ((overlays (reverse scheme-buffer-overlays
)))
1502 (if (or (= (point-min) (point-max))
1503 (not (eq (char-syntax (char-after (point-min))) ?\
()))
1504 (setq overlays
(cdr overlays
)))
1506 (if (and (overlay-get (car overlays
) 'modifiedp
)
1507 (not (overlay-get (car overlays
) 'brokenp
)))
1509 (guile-send-overlay (guile-alloc-finfo (car overlays
)))
1510 (if guile-error-p
(throw 'exit nil
))))
1511 (setq overlays
(cdr overlays
)))))
1512 (setq scheme-buffer-modified-p nil
)))
1513 (if guile-show-overlays-p
1514 (guile-show-overlays))))
1516 (defun guile-alloc-finfo (overlay)
1517 (if (not (overlay-get overlay
'id
))
1519 (let ((finfo (scheme-virtual-file-list-find (guile-buffer-file-name))))
1521 (setcdr finfo
(delq overlay
(cdr finfo
)))))
1522 (guile-new-finfo overlay
))
1523 (let ((finfo (assq (overlay-get overlay
'id
)
1524 scheme-virtual-file-list
)))
1526 (let ((id (guile-alloc-virtual-id overlay
)))
1528 (overlay-put overlay
'id id
)
1529 (overlay-put overlay
'virtualp t
)
1531 (guile-new-finfo overlay
)))))
1533 (defun guile-new-finfo (overlay)
1534 (let* ((id (guile-alloc-virtual-id overlay
))
1535 (finfo (cons id
(list overlay
))))
1536 (overlay-put overlay
'id id
)
1537 (overlay-put overlay
'virtualp t
)
1538 (goto-char (overlay-start overlay
))
1539 (overlay-put overlay
'original-line
(guile-current-line))
1540 (setq scheme-virtual-file-list
1541 (cons finfo scheme-virtual-file-list
))
1544 (defvar guile-last-prompt-end nil
)
1545 (defvar guile-input-sent-p t
)
1547 (defun guile-send-input ()
1549 (if (and (marker-position guile-last-prompt-end
)
1551 (let ((start (save-excursion
1552 (goto-char (point-max))
1553 (and (guile-real-safe-backward-sexp)
1556 (<= (marker-position guile-last-prompt-end
) start
)
1557 (guile-whitespace-between-p guile-last-prompt-end
1561 (put-text-property (1- (point)) (point) 'face
'bold
))
1562 (goto-char (point-max))
1564 (setq guile-input-sent-p t
)))
1565 (comint-send-input)))
1567 (defconst guile-whitespace-chars
" \t\n\r\f")
1569 (defun guile-whitespace-between-p (beg end
)
1570 (let ((beg (if (markerp beg
) (marker-position beg
) beg
))
1571 (end (if (markerp end
) (marker-position end
) end
)))
1574 (setq beg end end swap
)))
1577 (skip-chars-forward guile-whitespace-chars end
)
1580 ;;*fixme* This is redundant code. Compare sync.
1581 (defun guile-send-changes ()
1583 (setq guile-last-displayed-erring-overlay nil
)
1584 (setq guile-displayed-erring-buffers nil
)
1585 (setq guile-quiet nil
)
1586 (if (guile-check-all-1)
1588 (setq guile-error-p nil
)
1590 (let ((old-buffer (current-buffer)))
1595 (goto-char (point-max))
1596 (let ((end (point)))
1597 (beginning-of-buffer)
1598 (guile-send-region (point) end nil t
)))
1599 (if guile-show-overlays-p
1600 (guile-show-overlays))))
1601 (guile-get-enhanced-buffers))
1602 (set-buffer old-buffer
))))))
1604 (defun scheme-send-region (start end
)
1605 "Send the current region to the inferior Scheme process."
1607 (if (not (guile-enhancedp (current-buffer)))
1609 (comint-send-region (scheme-proc) start end
)
1610 (comint-send-string (scheme-proc) "\n"))
1611 (setq guile-error-p nil
)
1613 (guile-send-region start end t
)
1614 (cond (guile-define-header-emitted-p
1615 (message "Defined."))
1617 (guile-insert-before-prompt
1618 (concat "RESULT: " guile-last-result
"\n"))
1619 (message "%s" (concat "Result: " guile-last-result
)))))
1620 (if guile-show-overlays-p
1621 (guile-show-overlays))))
1623 (defvar guile-define-name-marker
)
1625 (defun guile-insert-before-prompt (string)
1627 (set-buffer scheme-buffer
)
1629 (goto-char guile-last-prompt-end
)
1630 (forward-line 0) ;; ignore field boundary
1631 (let ((inhibit-read-only t
)
1632 (before-prompt (point))
1633 (w (or (get-buffer-window scheme-buffer
'visible
)
1634 (get-buffer-window scheme-buffer t
))))
1635 (let ((w-start (and w
(window-start w
))))
1636 (insert-before-markers string
)
1637 (if (and w
(= before-prompt w-start
))
1638 (let ((selected (selected-window)))
1643 (select-window selected
)
1644 (set-buffer scheme-buffer
)))))))))
1646 (defvar guile-define-header-emitted-p nil
)
1647 (defvar guile-define-startcol
0)
1648 (defvar guile-define-filler
"")
1649 (defvar guile-define-fillcol
0)
1650 (defvar guile-last-result nil
)
1652 (defun guile-send-region (start end send-all-p
&optional multip
)
1653 (if (not scheme-ready-p
)
1654 (error "Scheme is not ready to receive expressions from Emacs."))
1655 (let ((overlays (reverse scheme-buffer-overlays
)))
1656 (if (or (= (point-min) (point-max))
1657 (not (eq (char-syntax (char-after (point-min))) ?\
()))
1658 (setq overlays
(cdr overlays
)))
1659 ;; First skip some overlays
1660 (while (and overlays
(<= (overlay-end (car overlays
)) start
))
1661 (setq overlays
(cdr overlays
)))
1662 (setq guile-define-header-emitted-p nil
)
1663 (setq guile-last-result nil
)
1664 (let ((start (max start
(overlay-start (car overlays
)))))
1665 (if (/= start
(overlay-start (car overlays
)))
1666 (guile-send-overlay (save-excursion
1667 (guile-alloc-finfo (car overlays
)))
1672 (while (and overlays
1673 (< (overlay-start (car overlays
)) end
))
1674 (if (and (not (overlay-get (car overlays
) 'brokenp
))
1676 (overlay-get (car overlays
) 'modifiedp
)))
1677 (guile-send-overlay (save-excursion
1678 (guile-alloc-finfo (car overlays
)))
1681 (setq overlays
(cdr overlays
)))))))
1683 (defconst guile-end-of-chunk
"\001\n")
1685 ;; *fixme* Improve code.
1686 (defun guile-send-overlay (finfo &optional interactivep multip start end
)
1687 (let* ((filename (car finfo
))
1688 (overlay (car (cdr finfo
)))
1689 (module-overlay (overlay-get overlay
'module-overlay
))
1690 (module (or (and module-overlay
1691 (overlay-get module-overlay
'define-module
))
1693 (old-buffer (current-buffer))
1696 ;; Define the module of the overlay if not done before
1697 (if (and module-overlay
1698 (overlay-get module-overlay
'modifiedp
))
1699 (guile-send-overlay (save-excursion
1700 (guile-alloc-finfo module-overlay
))))
1702 (set-buffer scheme-buffer
)
1703 ;; Inhibit process output and hamster it
1704 (setq comint-allow-output-p nil
)
1705 (setq guile-eval-output nil
)
1706 (setq guile-unallowed-output
"")
1708 (set-buffer old-buffer
)
1711 ;; Send load command
1715 (let ((column (save-excursion
1718 (format "(%%%%emacs-load %S %d %d '%s #%c)\n"
1720 (+ (overlay-get overlay
'original-line
)
1722 (count-lines (overlay-get overlay
'original-line
)
1724 (if (zerop column
) 0 -
1))
1727 (if interactivep ?t ?f
)))
1728 (format "(%%%%emacs-load %S %d %d '%s #%c)\n"
1730 (1- (overlay-get overlay
'original-line
))
1733 (if interactivep ?t ?f
))))
1734 ;; Send overlay contents
1737 (buffer-substring-no-properties (or start
(overlay-start overlay
))
1738 (or end
(overlay-end overlay
))))
1739 ;; If this is the last overlay we may have to send a final newline
1740 ;;(if (and (eq overlay scheme-buffer-last-overlay)
1741 ;; (/= (overlay-start overlay)
1742 ;; (overlay-end overlay))
1743 ;; (not (eq (char-after (1- (overlay-end overlay))) ?\n)))
1744 (comint-send-string (scheme-proc) "\n")
1745 ;; Remove modified mark so that Emacs will trust its idea about positions.
1746 (or start
(overlay-put overlay
'modifiedp nil
))
1748 (comint-send-string (scheme-proc) guile-end-of-chunk
)
1749 ;; Wait for acknowledge.
1750 (while (and scheme-load-p
(not guile-error-p
))
1751 (accept-process-output (scheme-proc) 0 guile-process-timeout
))
1753 ;; Have we received an error?
1758 (set-buffer scheme-buffer
)
1759 (let ((output guile-unallowed-output
))
1760 (if (string-match "\\(^ABORT:.*\n\\)+" output
)
1761 (guile-insert-before-prompt (match-string 1 output
))))))
1762 (overlay-put overlay
'modifiedp t
)
1763 (setq scheme-load-p nil
)
1764 (throw 'exit nil
))) ;Abort whatever we was doing.
1766 ;; The transfer has been successful. Display defined symbol.
1769 (goto-char (overlay-start overlay
))
1770 (if (and (not (and start
(/= start
(overlay-start overlay
))))
1771 (looking-at guile-defexpr
))
1773 (guile-display-name (match-string guile-defexpr-name
)
1775 (setq guile-last-result nil
))
1776 (set-buffer scheme-buffer
)
1777 (if guile-eval-output
1778 (guile-insert-before-prompt guile-eval-output
))
1779 (setq guile-last-result guile-eval-result
)
1780 (set-buffer old-buffer
))
1784 (goto-char old-pos
))))
1786 (defun guile-display-name (name multip
)
1788 (let ((buffer-file (guile-buffer-file-name))
1789 (buffer-name (buffer-name)))
1790 (set-buffer scheme-buffer
)
1792 (let ((inhibit-read-only t
))
1793 (if (not guile-define-header-emitted-p
)
1795 (format "DEFINED:%s ()\n"
1798 (or (and buffer-file
1799 (file-name-nondirectory
1803 (guile-insert-before-prompt header
)
1804 (set-marker guile-define-name-marker
1806 (goto-char guile-last-prompt-end
)
1809 (setq guile-define-startcol
(- (length header
) 2))
1810 (setq guile-define-filler
1812 (make-string guile-define-startcol ?
)))
1813 (setq guile-define-fillcol
1814 (let ((window (get-buffer-window scheme-buffer t
)))
1816 (- (window-width window
) 3)
1818 (setq guile-define-header-emitted-p t
)))
1819 (goto-char guile-define-name-marker
)
1820 (cond ((= (current-column) guile-define-startcol
))
1821 ((> (+ (current-column) (length name
)) guile-define-fillcol
)
1822 (insert-before-markers guile-define-filler
))
1823 (t (insert-before-markers " ")))
1824 (insert-before-markers name
))))))
1826 ;;; Enhanced editing
1829 (defvar guile-n-enhanced-buffers
0
1830 "Number of buffers in enhanced edit mode.")
1832 (defun guile-enhancedp (&optional buffer
)
1835 scheme-buffer-overlays
1838 scheme-buffer-overlays
)))
1840 (defun guile-get-enhanced-buffers ()
1841 (let ((ls (buffer-list))
1844 (if (guile-enhancedp (car ls
))
1845 (setq ans
(cons (car ls
) ans
)))
1849 (defun guile-enhanced-edit (buffer &optional known-by-scheme
)
1850 "Put the current scheme buffer into enhanced editing mode."
1851 (interactive (list (current-buffer)))
1852 (if (guile-enhancedp buffer
)
1853 (error "Already in enhanced editing mode!"))
1856 (guile-parse-buffer known-by-scheme
)
1857 (setq scheme-overlay-repair-function
'guile-repair-overlays
)
1858 (if (not (memq scheme-overlay-repair-idle-timer timer-idle-list
))
1859 (setq scheme-overlay-repair-idle-timer
1860 (run-with-idle-timer 0.1 t
'run-hook-with-args
1861 'scheme-overlay-repair-function
)))
1862 (setq guile-n-enhanced-buffers
(1+ guile-n-enhanced-buffers
)))
1863 (force-mode-line-update))
1865 (defun guile-normal-edit (buffer)
1866 "Exit enhanced editing mode."
1867 (interactive (list (current-buffer)))
1868 (if (guile-attachedp)
1869 (error "Can't exit enhanced editing mode while attached to scheme. Detach first."))
1872 (for-each (function (lambda (overlay)
1873 (if (overlayp overlay
) ; For stability's sake
1875 (if (guile-virtual-p overlay
)
1876 (scheme-virtual-unlink (overlay-get overlay
'id
)))
1877 (delete-overlay overlay
)))))
1878 scheme-buffer-overlays
)
1879 (setq scheme-buffer-overlays
())
1880 (setq scheme-buffer-last-overlay nil
)
1881 ;; Since we let go of the control, we have to mark the buffer...
1882 ;(setq scheme-buffer-modified-p t) Now using first-change-hook.
1883 (setq scheme-overlay-repair-function nil
)
1884 (scheme-virtual-unlink (guile-buffer-file-name buffer
))
1885 (setq guile-n-enhanced-buffers
(1- guile-n-enhanced-buffers
)))
1886 (force-mode-line-update))
1890 ;;; Every non-broken overlay containing a sexp starts with a character
1891 ;;; with syntax ?\(.
1892 ;;; The first overlay in the overlay list is never broken.
1894 (defun guile-current-line ()
1895 (+ (count-lines 1 (point))
1896 (if (= (current-column) 0) 1 0)))
1898 (defun guile-safe-forward-sexp ()
1899 "Move point one sexp forwards.
1900 Returns non-nil if no error was encountered."
1901 (not (condition-case err
1905 (defun guile-safe-backward-sexp ()
1906 "Move point one sexp forwards.
1907 Returns non-nil if no error was encountered."
1908 (not (condition-case err
1912 (defun guile-real-safe-backward-sexp ()
1913 (and (guile-safe-backward-sexp)
1916 (char-before (1- (point)))
1917 (eq (char-before (1- (point))) ?
#)
1918 (eq (char-syntax (char-before)) ?w
)
1922 (defun guile-parse-buffer (&optional initialp
)
1924 (if (= (point-min) (point-max))
1925 ;; Apparently, the buffer is empty
1927 (setq overlay
(make-overlay (point-min) (point-max) nil nil t
))
1928 (overlay-put overlay
'modification-hooks
1929 '(guile-handle-modification))
1930 (overlay-put overlay
'insert-behind-hooks
1931 '(rear-sticky-overlay-function guile-handle-modification
))
1932 (setq scheme-buffer-overlays
(list overlay
))
1933 (setq scheme-buffer-last-overlay overlay
))
1934 (setq scheme-buffer-last-overlay nil
)
1935 (guile-reparse-buffer nil
(point-min) initialp
)
1936 (guile-modularize scheme-buffer-overlays
)))
1938 (defvar guile-tail-cons
(cons nil nil
))
1940 (defun guile-cons-before-match (x ls
)
1941 "Match X against successive elements of LS.
1942 Return cons before the one with car matching X."
1946 (while (and (cdr ls
) (not (eq (car (cdr ls
)) x
)))
1951 ;; Here I've sacrificed readability for speed...
1952 ;; Geeh! What a monstrum!
1954 (defun guile-reparse-buffer (start-overlay limit
&optional initialp
)
1955 "Reparse buffer backwards to build/update `scheme-buffer-overlays'.
1956 Start with overlay START-OVERLAY. Stop when we have passed LIMIT.
1957 If START-OVERLAY is nil parsing starts from (point-max).
1958 The optional third argument INITIALP should be non-nil if parsing
1959 for the first time. This will cause initialization of the
1960 original-line property."
1961 (let* ((tailp (and start-overlay
1963 (goto-char (overlay-end start-overlay
))
1965 (guile-cons-before-match start-overlay
1966 scheme-buffer-overlays
)
1967 (let ((after (guile-cons-before-match
1969 scheme-buffer-overlays
)))
1972 (overlay-put (car after
) 'brokenp t
)
1973 (guile-cons-before-match
1975 scheme-buffer-overlays
))))))))
1976 (tail (or tailp guile-tail-cons
))
1977 (overlays (if tailp
(cdr tail
) scheme-buffer-overlays
))
1982 (overlay-end (car (cdr tail
)))
1984 (goto-char last-end
)
1985 ;; Parse buffer backwards...
1987 (while (> (point) limit
)
1988 ;; First try to move one sexp backwards...
1989 (if (and (guile-safe-backward-sexp)
1992 ;; Do we have it in the list?
1993 (while (and overlays
1994 (> (overlay-start (car overlays
)) (point)))
1995 ;; First throw away some trash overlays...
1996 (let ((id (overlay-get (car overlays
) 'id
)))
1997 (delete-overlay (car overlays
))
1999 ;; It's a stand-alone sexp, remove it from the list
2000 (scheme-virtual-unlink id
)))
2001 (setq overlays
(cdr overlays
)))
2003 (= (overlay-start (car overlays
)) (point)))
2005 (progn ; Is it intact?
2006 (if (or (overlay-get (car overlays
) 'brokenp
)
2007 (/= (overlay-end (car overlays
)) last-end
))
2011 (move-overlay (car overlays
) (point) last-end
)
2012 ;; Can we repair it?
2015 (eq (char-syntax (following-char)) ?\
()
2016 (eq (char-syntax (following-char)) ?
<)
2017 (eq (char-syntax (following-char)) ?
))
2018 (eq (char-syntax (following-char)) ?\
())
2021 (overlay-put (car overlays
) 'brokenp nil
)
2022 (overlay-put (car overlays
) 'face nil
)
2023 (overlay-put (car overlays
) 'modifiedp t
)
2024 (overlay-put (car overlays
)
2026 (and (looking-at "(define-module \\((.*)\\)")
2029 (goto-char (match-beginning 1))
2030 (read (current-buffer)))
2033 (overlay-put (car overlays
) 'face guile-broken-face
)
2034 (overlay-put (car overlays
) 'modifiedp t
))))
2036 (setcdr tail overlays
)
2037 (setq tail
(cdr tail
))
2038 (setq overlays
(cdr overlays
)))
2039 ;; We probably have to make a new overlay...
2040 ;; First check if it's OK.
2043 (eq (char-syntax (following-char)) ?\
()
2044 (eq (char-syntax (following-char)) ?
<)
2045 (eq (char-syntax (following-char)) ?
))
2046 (eq (char-syntax (following-char)) ?\
())
2047 ;; Everything seems OK with this one.
2049 (setq overlay
(make-overlay (point) last-end nil nil t
))
2051 (overlay-put overlay
'original-line
2052 (guile-current-line))
2053 (overlay-put overlay
'modifiedp t
))
2054 (overlay-put overlay
'modification-hooks
2055 '(guile-handle-modification))
2056 (overlay-put overlay
2058 (and (looking-at "(define-module \\((.*)\\)")
2061 (goto-char (match-beginning 1))
2062 (read (current-buffer)))
2064 ;; And link it in...
2065 (setcdr tail
(cons overlay overlays
))
2066 (setq tail
(cdr tail
)))
2067 ;; But this one is broken!
2068 ;; Try to find some structure...
2069 (guile-backward-broken-sexp)
2070 (while (and overlays
2071 (> (overlay-start (car overlays
)) (point)))
2072 (let ((id (overlay-get (car overlays
) 'id
)))
2073 (delete-overlay (car overlays
))
2075 (scheme-virtual-unlink id
)))
2076 (setq overlays
(cdr overlays
)))
2077 ;; Is it possibly the first one in the overlay list?
2079 (= (overlay-start (car overlays
)) (point)))
2082 (move-overlay (car overlays
) (point) last-end
)
2083 (overlay-put (car overlays
) 'face guile-broken-face
)
2084 (overlay-put (car overlays
) 'modifiedp t
)
2086 (setcdr tail overlays
)
2087 (setq tail
(cdr tail
))
2088 (setq overlays
(cdr overlays
)))
2089 ;; It wasn't - make a new overlay.
2090 (setq overlay
(make-overlay (point) last-end nil nil t
))
2091 (overlay-put overlay
'brokenp t
)
2092 (overlay-put overlay
'face guile-broken-face
)
2093 (overlay-put overlay
'modification-hooks
2094 '(guile-handle-modification))
2095 ;; And link it in...
2096 (setcdr tail
(cons overlay overlays
))
2097 (setq tail
(cdr tail
))))))
2098 ;; Broken overlay... Here we go again!
2099 (guile-backward-broken-sexp)
2100 (while (and overlays
2101 (> (overlay-start (car overlays
)) (point)))
2102 (let ((id (overlay-get (car overlays
) 'id
)))
2103 (delete-overlay (car overlays
))
2105 (scheme-virtual-unlink id
)))
2106 (setq overlays
(cdr overlays
)))
2108 (= (overlay-start (car overlays
)) (point)))
2110 (setq overlay
(car overlays
))
2111 (move-overlay overlay
(point) last-end
)
2112 (setcdr tail overlays
)
2113 (setq tail
(cdr tail
))
2114 (setq overlays
(cdr overlays
)))
2115 (setq overlay
(make-overlay (point) last-end nil nil t
))
2116 (overlay-put overlay
'modification-hooks
2117 '(guile-handle-modification))
2118 (setcdr tail
(cons overlay overlays
))
2119 (setq tail
(cdr tail
)))
2120 (overlay-put overlay
'brokenp t
)
2121 (overlay-put overlay
'face guile-broken-face
))
2122 (if (overlay-get (car tail
) 'brokenp
)
2124 (setq first-broken
(car tail
))
2125 (if (not last-broken
)
2126 (setq last-broken
(car tail
)))))
2127 (setq last-end
(point))))
2130 (setq scheme-buffer-overlays
2131 (cdr guile-tail-cons
))
2132 ;; Don't let the rear-stickiness propagate upwards...
2133 (if scheme-buffer-last-overlay
2134 (if (not (eq (car scheme-buffer-overlays
)
2135 scheme-buffer-last-overlay
))
2137 (overlay-put scheme-buffer-last-overlay
2138 'insert-behind-hooks
2140 (overlay-put (car scheme-buffer-overlays
)
2141 'insert-behind-hooks
2142 '(rear-sticky-overlay-function
2143 guile-handle-modification
))))
2144 (overlay-put (car scheme-buffer-overlays
)
2145 'insert-behind-hooks
2146 '(rear-sticky-overlay-function guile-handle-modification
)))
2147 (setq scheme-buffer-last-overlay
2148 (car scheme-buffer-overlays
))))
2149 (setq guile-last-broken last-broken
)
2150 (setq guile-repair-limit
2153 ; (let ((ovls (memq first-broken scheme-buffer-overlays)))
2154 ; (or (and ovls (cdr ovls) (car (cdr ovls)))
2156 (overlay-start first-broken
)
2157 guile-big-integer
)))
2158 (if guile-show-overlays-p
2159 (guile-show-overlays))
2162 (defvar guile-last-broken nil
)
2163 (defvar guile-repair-limit guile-big-integer
)
2165 (defun guile-handle-modification (overlay after from to
&optional length
)
2168 (overlay-put overlay
'brokenp t
)
2169 (setq scheme-buffer-overlays-modified-p t
)
2170 (if guile-last-broken
2171 (if (< (overlay-start overlay
) guile-repair-limit
)
2172 (setq guile-repair-limit
2174 ; (let ((ovls (memq overlay scheme-buffer-overlays)))
2175 ; (or (and ovls (cdr ovls) (car (cdr ovls)))
2177 (overlay-start overlay
))
2178 (if (> (overlay-start overlay
)
2179 (overlay-start guile-last-broken
))
2180 (setq guile-last-broken overlay
)))
2181 (setq guile-last-broken overlay
)
2182 (setq guile-repair-limit
2184 ; (let ((ovls (memq overlay scheme-buffer-overlays)))
2185 ; (or (and ovls (cdr ovls) (car (cdr ovls)))
2187 (overlay-start overlay
))))))
2189 (defun guile-repair-overlays ()
2190 (if (and (eq major-mode
'scheme-mode
)
2191 scheme-buffer-overlays-modified-p
)
2194 ;(message "Repair!")
2195 (setq scheme-buffer-modified-p t
)
2196 (if scheme-associated-process-buffer
2197 (setq guile-synchronizedp nil
))
2198 (guile-reparse-buffer guile-last-broken guile-repair-limit
)
2199 (guile-modularize scheme-buffer-overlays
)
2200 (setq scheme-buffer-overlays-modified-p nil
))))
2202 (defun guile-modularize (r-overlays)
2203 (let ((overlays (reverse r-overlays
))
2206 (if (overlay-get (car overlays
) 'define-module
)
2208 (overlay-put (car overlays
) 'module-overlay nil
)
2209 (setq module
(car overlays
)))
2210 (overlay-put (car overlays
) 'module-overlay module
))
2211 (setq overlays
(cdr overlays
)))))
2213 (defun guile-backward-broken-sexp ()
2216 (let ((last (point)))
2217 (while (not (or (bobp)
2218 (and (eq (following-char) ?\
()
2219 (guile-safe-backward-sexp)
2223 (setq last
(point)))
2224 (let ((end (point)))
2225 (goto-char (if (guile-safe-forward-sexp)
2229 ;; rear-sticky-overlay-function:
2230 ;; Put this function in the `insert-behind-hooks' of an overlay
2231 ;; in order to make the overlay rear-sticky.
2233 (defun rear-sticky-overlay-function (overlay after from to
&optional length
)
2235 (move-overlay overlay
(overlay-start overlay
) to
)))
2237 ;;; Some debugging utilities
2240 (defvar guile-show-overlays-p nil
)
2242 (defun guile-show-overlays ()
2244 (if (guile-enhancedp)
2248 (overlays scheme-buffer-overlays
))
2252 (message "Empty overlay list!"))
2253 (if (not (memq 'rear-sticky-overlay-function
2254 (overlay-get (car overlays
) 'insert-behind-hooks
)))
2257 (message "Last overlay not rear-sticky!")))
2259 (overlay-put (car overlays
)
2261 (if (setq color
(not color
))
2262 (if (overlay-get (car overlays
) 'brokenp
)
2264 (if (overlay-get (car overlays
) 'modifiedp
)
2265 guile-modified-face-1
2266 guile-unmodified-face-1
))
2267 (if (overlay-get (car overlays
) 'brokenp
)
2269 (if (overlay-get (car overlays
) 'modifiedp
)
2270 guile-modified-face-2
2271 guile-unmodified-face-2
))))
2274 (if (/= (overlay-end (car overlays
))
2275 (overlay-start previous
))
2277 (message "Bad end boundary at overlay no. %d" n
)))
2278 (if (overlay-get (car overlays
) 'insert-behind-hooks
)
2281 (message "Inner overlay no. %d rear-sticky!" n
)))))
2282 (setq previous
(car overlays
))
2284 (setq overlays
(cdr overlays
)))
2285 (if (/= (overlay-start previous
) (point-min))
2288 (message "First overlay doesn't start at %d" (point-min)))))))
2289 (setq guile-show-overlays-p t
))
2291 (defun guile-hide-overlays ()
2294 (overlays scheme-buffer-overlays
))
2296 (overlay-put (car overlays
)
2298 (if (overlay-get (car overlays
) 'brokenp
)
2301 (setq overlays
(cdr overlays
))))
2302 (setq guile-show-overlays-p nil
))
2304 ;; *fixme* Consider removing this function
2305 (defun guile-kill-overlays (&optional ls
)
2309 (setq ls
(apply (function append
)
2310 (mapcar (function cdr
)
2311 scheme-virtual-file-list
)))
2312 (setq scheme-virtual-file-list
())))
2314 (delete-overlay (car ls
))
2315 (setq ls
(cdr ls
))))
2317 ;; *fixme* Consider removing this function
2318 (defun overlay-kill ()
2320 (delete-overlay (car (overlays-at (point)))))
2322 (defun for-each (func ls
)
2324 (funcall func
(car ls
))
2325 (setq ls
(cdr ls
))))
2330 (defconst guile-symbol-chars
"---A-ZÅÄÖa-zåäö0-9!$%&/=?@+*<>|-_:.")
2332 (defun guile-match-symnames (word &optional exactp
)
2336 (set-buffer scheme-buffer
)
2337 (guile-eval `(map symbol-
>string
2341 (and exactp
"$"))))))))
2343 (defmacro guile-force-splittable
(&rest forms
)
2344 `(let ((f (selected-frame))
2345 (w (selected-window)))
2346 (let ((unsplittable (assq 'unsplittable
(frame-parameters f
)))
2347 (dedicatedp (window-dedicated-p w
))
2348 (same-window-buffer-names
2349 (append same-window-buffer-names
2350 (list (buffer-name (window-buffer w
))))))
2353 (modify-frame-parameters f
'((unsplittable . nil
)))
2354 (set-window-dedicated-p w nil
)
2356 (modify-frame-parameters f
(list unsplittable
))
2357 (set-window-dedicated-p w dedicatedp
)))))
2359 (defvar guile-complete-function
'comint-dynamic-complete
)
2361 (defun guile-indent-or-complete ()
2363 (let ((beg (save-excursion
2366 (if (guile-whitespace-between-p beg
(point))
2367 (funcall 'indent-for-tab-command
)
2368 (funcall guile-complete-function
))))
2370 (defun guile-complete-symbol ()
2372 (let ((word (comint-word guile-symbol-chars
)))
2375 (guile-force-splittable
2376 (comint-dynamic-simple-complete word
(guile-match-symnames word
)))
2377 (if (string= (buffer-name) scheme-buffer
)
2378 (put-text-property comint-last-output-start
2379 (point) 'face
'bold
))))))
2381 (defun guile-list-completions ()
2383 (let* ((word (comint-word guile-symbol-chars
))
2384 (candidates (mapcar (function (lambda (x) (list x
)))
2385 (guile-match-symnames word
)))
2386 (completions (all-completions word candidates
)))
2387 (if (null completions
)
2388 (message "No completions of %s" word
)
2389 (guile-force-splittable
2390 (comint-dynamic-list-completions completions
))
2391 (if (string= (buffer-name) scheme-buffer
)
2392 (put-text-property comint-last-output-start
(point) 'face
'bold
)))))
2396 (defun guile-documentation-symbols ()
2398 (set-buffer scheme-buffer
)
2399 (guile-eval '(map symbol-
>string
(%%apropos-internal
"")))))
2401 (defun guile-variable-at-point (symnames)
2403 (let ((stab (syntax-table)))
2406 (set-syntax-table scheme-mode-syntax-table
)
2407 (or (not (zerop (skip-syntax-backward "_w")))
2408 (eq (char-syntax (following-char)) ?w
)
2409 (eq (char-syntax (following-char)) ?_
)
2411 (skip-chars-forward "'")
2412 (let ((obj (read (current-buffer))))
2413 (and (symbolp obj
) (member (symbol-name obj
) symnames
) obj
)))
2414 (set-syntax-table stab
)))
2417 (defun guile-describe-variable (variable)
2418 "Display the full documentation of Guile variable VARIABLE."
2420 (let ((symnames (guile-documentation-symbols)))
2421 (let ((symbol (guile-variable-at-point symnames
))
2422 (enable-recursive-minibuffers t
)
2424 (setq val
(completing-read (if symbol
2425 (format "Describe Guile variable (default %s): " symbol
)
2426 "Describe Guile variable: ")
2431 (list (if (equal val
"")
2434 (guile-force-splittable
2435 (with-output-to-temp-buffer "*Help*"
2438 (princ (save-excursion
2439 (set-buffer scheme-buffer
)
2440 (guile-eval variable t
)))
2443 (let ((doc (save-excursion
2444 (set-buffer scheme-buffer
)
2445 (guile-eval `(%%emacs-symdoc
',variable
)))))
2448 (princ "not documented")))
2449 (print-help-return-message)
2451 (set-buffer standard-output
)
2453 ;; Return the text we displayed.
2457 (run-hooks 'guile-load-hook
)