|
|
1.1 root 1: ;; Run Scheme under Emacs
2: ;; Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
3:
4: ;; This file is part of GNU Emacs.
5:
6: ;; GNU Emacs is distributed in the hope that it will be useful,
7: ;; but WITHOUT ANY WARRANTY. No author or distributor
8: ;; accepts responsibility to anyone for the consequences of using it
9: ;; or for whether it serves any particular purpose or works at all,
10: ;; unless he says so in writing. Refer to the GNU Emacs General Public
11: ;; License for full details.
12:
13: ;; Everyone is granted permission to copy, modify and redistribute
14: ;; GNU Emacs, but only under the conditions described in the
15: ;; GNU Emacs General Public License. A copy of this license is
16: ;; supposed to have been given to you along with GNU Emacs so you
17: ;; can know your rights and responsibilities. It should be in a
18: ;; file named COPYING. Among other things, the copyright notice
19: ;; and this notice must be preserved on all copies.
20:
21: ;;; Requires C-Scheme release 5 or later
22: ;;; Changes to Control-G handler require runtime version 13.85 or later
23:
24: ;;; $Header: xscheme.el,v 1.23 89/04/28 22:59:40 GMT cph Rel $
25:
26: (require 'scheme)
27:
28: (defvar scheme-program-name "scheme"
29: "*Program invoked by the `run-scheme' command.")
30:
31: (defvar scheme-band-name nil
32: "*Band loaded by the `run-scheme' command.")
33:
34: (defvar scheme-program-arguments nil
35: "*Arguments passed to the Scheme program by the `run-scheme' command.")
36:
37: (defvar xscheme-allow-pipelined-evaluation t
38: "If non-nil, an expression may be transmitted while another is evaluating.
39: Otherwise, attempting to evaluate an expression before the previous expression
40: has finished evaluating will signal an error.")
41:
42: (defvar xscheme-startup-message
43: "This is the Scheme process buffer.
44: Type \\[advertised-xscheme-send-previous-expression] to evaluate the expression before point.
45: Type \\[xscheme-send-control-g-interrupt] to abort evaluation.
46: Type \\[describe-mode] for more information.
47:
48: "
49: "String to insert into Scheme process buffer first time it is started.
50: Is processed with `substitute-command-keys' first.")
51:
52: (defvar xscheme-signal-death-message nil
53: "If non-nil, causes a message to be generated when the Scheme process dies.")
54:
55: (defun xscheme-evaluation-commands (keymap)
56: (define-key keymap "\e\C-x" 'xscheme-send-definition)
57: (define-key keymap "\C-x\C-e" 'advertised-xscheme-send-previous-expression)
58: (define-key keymap "\eo" 'xscheme-send-buffer)
59: (define-key keymap "\ez" 'xscheme-send-definition)
60: (define-key keymap "\e\C-m" 'xscheme-send-previous-expression)
61: (define-key keymap "\e\C-z" 'xscheme-send-region))
62:
63: (defun xscheme-interrupt-commands (keymap)
64: (define-key keymap "\C-c\C-s" 'xscheme-select-process-buffer)
65: (define-key keymap "\C-c\C-b" 'xscheme-send-breakpoint-interrupt)
66: (define-key keymap "\C-c\C-c" 'xscheme-send-control-g-interrupt)
67: (define-key keymap "\C-c\C-u" 'xscheme-send-control-u-interrupt)
68: (define-key keymap "\C-c\C-x" 'xscheme-send-control-x-interrupt))
69:
70: (xscheme-evaluation-commands scheme-mode-map)
71: (xscheme-interrupt-commands scheme-mode-map)
72:
73: (defun run-scheme (command-line)
74: "Run an inferior Scheme process.
75: Output goes to the buffer `*scheme*'.
76: With argument, asks for a command line."
77: (interactive
78: (list (let ((default
79: (or xscheme-process-command-line
80: (xscheme-default-command-line))))
81: (if current-prefix-arg
82: (read-string "Run Scheme: " default)
83: default))))
84: (setq xscheme-process-command-line command-line)
85: (switch-to-buffer (xscheme-start-process command-line)))
86:
87: (defun reset-scheme ()
88: "Reset the Scheme process."
89: (interactive)
90: (let ((process (get-process "scheme")))
91: (cond ((or (not process)
92: (not (eq (process-status process) 'run))
93: (yes-or-no-p
94: "The Scheme process is running, are you SURE you want to reset it? "))
95: (message "Resetting Scheme process...")
96: (if process (kill-process process t))
97: (xscheme-start-process xscheme-process-command-line)
98: (message "Resetting Scheme process...done")))))
99:
100: (defun xscheme-default-command-line ()
101: (concat scheme-program-name " -emacs"
102: (if scheme-program-arguments
103: (concat " " scheme-program-arguments)
104: "")
105: (if scheme-band-name
106: (concat " -band " scheme-band-name)
107: "")))
108:
109: ;;;; Interaction Mode
110:
111: (defun scheme-interaction-mode ()
112: "Major mode for interacting with the inferior Scheme process.
113: Like scheme-mode except that:
114:
115: \\[advertised-xscheme-send-previous-expression] sends the expression before point to the Scheme process as input
116: \\[xscheme-yank-previous-send] yanks the expression most recently sent to Scheme
117:
118: All output from the Scheme process is written in the Scheme process
119: buffer, which is initially named \"*scheme*\". The result of
120: evaluating a Scheme expression is also printed in the process buffer,
121: preceded by the string \";Value: \" to highlight it. If the process
122: buffer is not visible at that time, the value will also be displayed
123: in the minibuffer. If an error occurs, the process buffer will
124: automatically pop up to show you the error message.
125:
126: While the Scheme process is running, the modelines of all buffers in
127: scheme-mode are modified to show the state of the process. The
128: possible states and their meanings are:
129:
130: input waiting for input
131: run evaluating
132: gc garbage collecting
133:
134: The process buffer's modeline contains additional information where
135: the buffer's name is normally displayed: the command interpreter level
136: and type.
137:
138: Scheme maintains a stack of command interpreters. Every time an error
139: or breakpoint occurs, the current command interpreter is pushed on the
140: command interpreter stack, and a new command interpreter is started.
141: One example of why this is done is so that an error that occurs while
142: you are debugging another error will not destroy the state of the
143: initial error, allowing you to return to it after the second error has
144: been fixed.
145:
146: The command interpreter level indicates how many interpreters are in
147: the command interpreter stack. It is initially set to one, and it is
148: incremented every time that stack is pushed, and decremented every
149: time it is popped. The following commands are useful for manipulating
150: the command interpreter stack:
151:
152: \\[xscheme-send-breakpoint-interrupt] pushes the stack once
153: \\[xscheme-send-control-u-interrupt] pops the stack once
154: \\[xscheme-send-control-g-interrupt] pops everything off
155: \\[xscheme-send-control-x-interrupt] aborts evaluation, doesn't affect stack
156:
157: Some possible command interpreter types and their meanings are:
158:
159: [Evaluator] read-eval-print loop for evaluating expressions
160: [Debugger] single character commands for debugging errors
161: [Where] single character commands for examining environments
162:
163: Starting with release 6.2 of Scheme, the latter two types of command
164: interpreters will change the major mode of the Scheme process buffer
165: to scheme-debugger-mode , in which the evaluation commands are
166: disabled, and the keys which normally self insert instead send
167: themselves to the Scheme process. The command character ? will list
168: the available commands.
169:
170: For older releases of Scheme, the major mode will be be
171: scheme-interaction-mode , and the command characters must be sent as
172: if they were expressions.
173:
174: Commands:
175: Delete converts tabs to spaces as it moves back.
176: Blank lines separate paragraphs. Semicolons start comments.
177: \\{scheme-interaction-mode-map}
178:
179: Entry to this mode calls the value of scheme-interaction-mode-hook
180: with no args, if that value is non-nil."
181: (interactive)
182: (kill-all-local-variables)
183: (scheme-interaction-mode-initialize)
184: (scheme-mode-variables)
185: (make-local-variable 'xscheme-previous-send)
186: (run-hooks 'scheme-interaction-mode-hook))
187:
188: (defun scheme-interaction-mode-initialize ()
189: (use-local-map scheme-interaction-mode-map)
190: (setq major-mode 'scheme-interaction-mode)
191: (setq mode-name "Scheme Interaction"))
192:
193: (defun scheme-interaction-mode-commands (keymap)
194: (define-key keymap "\C-c\C-m" 'xscheme-send-current-line)
195: (define-key keymap "\C-c\C-p" 'xscheme-send-proceed)
196: (define-key keymap "\C-c\C-y" 'xscheme-yank-previous-send))
197:
198: (defvar scheme-interaction-mode-map nil)
199: (if (not scheme-interaction-mode-map)
200: (progn
201: (setq scheme-interaction-mode-map (make-keymap))
202: (scheme-mode-commands scheme-interaction-mode-map)
203: (xscheme-interrupt-commands scheme-interaction-mode-map)
204: (xscheme-evaluation-commands scheme-interaction-mode-map)
205: (scheme-interaction-mode-commands scheme-interaction-mode-map)))
206:
207: (defun xscheme-enter-interaction-mode ()
208: (save-excursion
209: (set-buffer (xscheme-process-buffer))
210: (if (not (eq major-mode 'scheme-interaction-mode))
211: (if (eq major-mode 'scheme-debugger-mode)
212: (scheme-interaction-mode-initialize)
213: (scheme-interaction-mode)))))
214:
215: (fset 'advertised-xscheme-send-previous-expression
216: 'xscheme-send-previous-expression)
217:
218: ;;;; Debugger Mode
219:
220: (defun scheme-debugger-mode ()
221: "Major mode for executing the Scheme debugger.
222: Like scheme-mode except that the evaluation commands
223: are disabled, and characters that would normally be self inserting are
224: sent to the Scheme process instead. Typing ? will show you which
225: characters perform useful functions.
226:
227: Commands:
228: \\{scheme-debugger-mode-map}"
229: (error "Illegal entry to scheme-debugger-mode"))
230:
231: (defun scheme-debugger-mode-initialize ()
232: (use-local-map scheme-debugger-mode-map)
233: (setq major-mode 'scheme-debugger-mode)
234: (setq mode-name "Scheme Debugger"))
235:
236: (defun scheme-debugger-mode-commands (keymap)
237: (let ((char ? ))
238: (while (< char 127)
239: (define-key keymap (char-to-string char) 'scheme-debugger-self-insert)
240: (setq char (1+ char)))))
241:
242: (defvar scheme-debugger-mode-map nil)
243: (if (not scheme-debugger-mode-map)
244: (progn
245: (setq scheme-debugger-mode-map (make-keymap))
246: (scheme-mode-commands scheme-debugger-mode-map)
247: (xscheme-interrupt-commands scheme-debugger-mode-map)
248: (scheme-debugger-mode-commands scheme-debugger-mode-map)))
249:
250: (defun scheme-debugger-self-insert ()
251: "Transmit this character to the Scheme process."
252: (interactive)
253: (xscheme-send-char last-command-char))
254:
255: (defun xscheme-enter-debugger-mode (prompt-string)
256: (save-excursion
257: (set-buffer (xscheme-process-buffer))
258: (if (not (eq major-mode 'scheme-debugger-mode))
259: (progn
260: (if (not (eq major-mode 'scheme-interaction-mode))
261: (scheme-interaction-mode))
262: (scheme-debugger-mode-initialize)))))
263:
264: (defun xscheme-debugger-mode-p ()
265: (let ((buffer (xscheme-process-buffer)))
266: (and buffer
267: (save-excursion
268: (set-buffer buffer)
269: (eq major-mode 'scheme-debugger-mode)))))
270:
271: ;;;; Evaluation Commands
272:
273: (defun xscheme-send-string (&rest strings)
274: "Send the string arguments to the Scheme process.
275: The strings are concatenated and terminated by a newline."
276: (cond ((not (xscheme-process-running-p))
277: (if (yes-or-no-p "The Scheme process has died. Reset it? ")
278: (progn
279: (reset-scheme)
280: (xscheme-wait-for-process)
281: (goto-char (point-max))
282: (apply 'insert-before-markers strings)
283: (xscheme-send-string-1 strings))))
284: ((xscheme-debugger-mode-p) (error "No sends allowed in debugger mode"))
285: ((and (not xscheme-allow-pipelined-evaluation)
286: xscheme-running-p)
287: (error "No sends allowed while Scheme running"))
288: (t (xscheme-send-string-1 strings))))
289:
290: (defun xscheme-send-string-1 (strings)
291: (let ((string (apply 'concat strings)))
292: (xscheme-send-string-2 string)
293: (if (eq major-mode 'scheme-interaction-mode)
294: (setq xscheme-previous-send string))))
295:
296: (defun xscheme-send-string-2 (string)
297: (let ((process (get-process "scheme")))
298: (send-string process (concat string "\n"))
299: (if (xscheme-process-buffer-current-p)
300: (set-marker (process-mark process) (point)))))
301:
302: (defun xscheme-yank-previous-send ()
303: "Insert the most recent expression at point."
304: (interactive)
305: (push-mark)
306: (insert xscheme-previous-send))
307:
308: (defun xscheme-select-process-buffer ()
309: "Select the Scheme process buffer and move to its output point."
310: (interactive)
311: (let ((process (or (get-process "scheme") (error "No scheme process"))))
312: (let ((buffer (or (process-buffer process) (error "No process buffer"))))
313: (let ((window (get-buffer-window buffer)))
314: (if window
315: (select-window window)
316: (switch-to-buffer buffer))
317: (goto-char (process-mark process))))))
318:
319: (defun xscheme-send-region (start end)
320: "Send the current region to the Scheme process.
321: The region is sent terminated by a newline."
322: (interactive "r")
323: (if (xscheme-process-buffer-current-p)
324: (progn (goto-char end)
325: (set-marker (process-mark (get-process "scheme")) end)))
326: (xscheme-send-string (buffer-substring start end)))
327:
328: (defun xscheme-send-definition ()
329: "Send the current definition to the Scheme process.
330: If the current line begins with a non-whitespace character,
331: parse an expression from the beginning of the line and send that instead."
332: (interactive)
333: (let ((start nil) (end nil))
334: (save-excursion
335: (end-of-defun)
336: (setq end (point))
337: (if (re-search-backward "^\\s(" nil t)
338: (setq start (point))
339: (error "Can't find definition")))
340: (xscheme-send-region start end)))
341:
342: (defun xscheme-send-next-expression ()
343: "Send the expression to the right of `point' to the Scheme process."
344: (interactive)
345: (let ((start (point)))
346: (xscheme-send-region start (save-excursion (forward-sexp) (point)))))
347:
348: (defun xscheme-send-previous-expression ()
349: "Send the expression to the left of `point' to the Scheme process."
350: (interactive)
351: (let ((end (point)))
352: (xscheme-send-region (save-excursion (backward-sexp) (point)) end)))
353:
354: (defun xscheme-send-current-line ()
355: "Send the current line to the Scheme process.
356: Useful for working with debugging Scheme under adb."
357: (interactive)
358: (let ((line
359: (save-excursion
360: (beginning-of-line)
361: (let ((start (point)))
362: (end-of-line)
363: (buffer-substring start (point))))))
364: (end-of-line)
365: (insert ?\n)
366: (xscheme-send-string-2 line)))
367:
368: (defun xscheme-send-buffer ()
369: "Send the current buffer to the Scheme process."
370: (interactive)
371: (if (xscheme-process-buffer-current-p)
372: (error "Not allowed to send this buffer's contents to Scheme"))
373: (xscheme-send-region (point-min) (point-max)))
374:
375: (defun xscheme-send-char (char)
376: "Prompt for a character and send it to the Scheme process."
377: (interactive "cCharacter to send: ")
378: (send-string "scheme" (char-to-string char)))
379:
380: ;;;; Interrupts
381:
382: (defun xscheme-send-breakpoint-interrupt ()
383: "Cause the Scheme process to enter a breakpoint."
384: (interactive)
385: (xscheme-send-interrupt ?b nil))
386:
387: (defun xscheme-send-proceed ()
388: "Cause the Scheme process to proceed from a breakpoint."
389: (interactive)
390: (send-string "scheme" "(proceed)\n"))
391:
392: (defun xscheme-send-control-g-interrupt ()
393: "Cause the Scheme processor to halt and flush input.
394: Control returns to the top level rep loop."
395: (interactive)
396: (let ((inhibit-quit t))
397: (cond ((not xscheme-control-g-synchronization-p)
398: (interrupt-process "scheme"))
399: (xscheme-control-g-disabled-p
400: (message "Relax..."))
401: (t
402: (setq xscheme-control-g-disabled-p t)
403: (message "Sending C-G interrupt to Scheme...")
404: (interrupt-process "scheme")
405: (send-string "scheme" (char-to-string 0))))))
406:
407: (defun xscheme-send-control-u-interrupt ()
408: "Cause the Scheme process to halt, returning to previous rep loop."
409: (interactive)
410: (xscheme-send-interrupt ?u t))
411:
412: (defun xscheme-send-control-x-interrupt ()
413: "Cause the Scheme process to halt, returning to current rep loop."
414: (interactive)
415: (xscheme-send-interrupt ?x t))
416:
417: ;;; This doesn't really work right -- Scheme just gobbles the first
418: ;;; character in the input. There is no way for us to guarantee that
419: ;;; the argument to this procedure is the first char unless we put
420: ;;; some kind of marker in the input stream.
421:
422: (defun xscheme-send-interrupt (char mark-p)
423: "Send a ^A type interrupt to the Scheme process."
424: (interactive "cInterrupt character to send: ")
425: (quit-process "scheme")
426: (send-string "scheme" (char-to-string char))
427: (if (and mark-p xscheme-control-g-synchronization-p)
428: (send-string "scheme" (char-to-string 0))))
429:
430: ;;;; Internal Variables
431:
432: (defvar xscheme-process-command-line nil
433: "Command used to start the most recent Scheme process.")
434:
435: (defvar xscheme-previous-send ""
436: "Most recent expression transmitted to the Scheme process.")
437:
438: (defvar xscheme-process-filter-state 'idle
439: "State of scheme process escape reader state machine:
440: idle waiting for an escape sequence
441: reading-type received an altmode but nothing else
442: reading-string reading prompt string")
443:
444: (defvar xscheme-running-p nil
445: "This variable, if nil, indicates that the scheme process is
446: waiting for input. Otherwise, it is busy evaluating something.")
447:
448: (defconst xscheme-control-g-synchronization-p t
449: "If non-nil, insert markers in the scheme input stream to indicate when
450: control-g interrupts were signalled. Do not allow more control-g's to be
451: signalled until the scheme process acknowledges receipt.")
452:
453: (defvar xscheme-control-g-disabled-p nil
454: "This variable, if non-nil, indicates that a control-g is being processed
455: by the scheme process, so additional control-g's are to be ignored.")
456:
457: (defvar xscheme-allow-output-p t
458: "This variable, if nil, prevents output from the scheme process
459: from being inserted into the process-buffer.")
460:
461: (defvar xscheme-prompt ""
462: "The current scheme prompt string.")
463:
464: (defvar xscheme-string-accumulator ""
465: "Accumulator for the string being received from the scheme process.")
466:
467: (defvar xscheme-string-receiver nil
468: "Procedure to send the string argument from the scheme process.")
469:
470: (defvar xscheme-start-hook nil
471: "If non-nil, a procedure to call when the Scheme process is started.
472: When called, the current buffer will be the Scheme process-buffer.")
473:
474: (defvar xscheme-runlight-string nil)
475: (defvar xscheme-mode-string nil)
476: (defvar xscheme-filter-input nil)
477:
478: ;;;; Basic Process Control
479:
480: (defun xscheme-start-process (command-line)
481: (let ((buffer (get-buffer-create "*scheme*")))
482: (let ((process (get-buffer-process buffer)))
483: (save-excursion
484: (set-buffer buffer)
485: (if (and process (memq (process-status process) '(run stop)))
486: (set-marker (process-mark process) (point-max))
487: (progn (if process (delete-process process))
488: (goto-char (point-max))
489: (scheme-interaction-mode)
490: (if (bobp)
491: (insert-before-markers
492: (substitute-command-keys xscheme-startup-message)))
493: (setq process
494: (let ((process-connection-type nil))
495: (apply 'start-process
496: (cons "scheme"
497: (cons buffer
498: (xscheme-parse-command-line
499: command-line))))))
500: (set-marker (process-mark process) (point-max))
501: (xscheme-process-filter-initialize t)
502: (xscheme-modeline-initialize)
503: (set-process-sentinel process 'xscheme-process-sentinel)
504: (set-process-filter process 'xscheme-process-filter)
505: (run-hooks 'xscheme-start-hook)))))
506: buffer))
507:
508: (defun xscheme-parse-command-line (string)
509: (setq string (substitute-in-file-name string))
510: (let ((start 0)
511: (result '()))
512: (while start
513: (let ((index (string-match "[ \t]" string start)))
514: (setq start
515: (cond ((not index)
516: (setq result
517: (cons (substring string start)
518: result))
519: nil)
520: ((= index start)
521: (string-match "[^ \t]" string start))
522: (t
523: (setq result
524: (cons (substring string start index)
525: result))
526: (1+ index))))))
527: (nreverse result)))
528:
529: (defun xscheme-wait-for-process ()
530: (sleep-for 2)
531: (while xscheme-running-p
532: (sleep-for 1)))
533:
534: (defun xscheme-process-running-p ()
535: "True iff there is a Scheme process whose status is `run'."
536: (let ((process (get-process "scheme")))
537: (and process
538: (eq (process-status process) 'run))))
539:
540: (defun xscheme-process-buffer ()
541: (let ((process (get-process "scheme")))
542: (and process (process-buffer process))))
543:
544: (defun xscheme-process-buffer-window ()
545: (let ((buffer (xscheme-process-buffer)))
546: (and buffer (get-buffer-window buffer))))
547:
548: (defun xscheme-process-buffer-current-p ()
549: "True iff the current buffer is the Scheme process buffer."
550: (eq (xscheme-process-buffer) (current-buffer)))
551:
552: ;;;; Process Filter
553:
554: (defun xscheme-process-sentinel (proc reason)
555: (xscheme-process-filter-initialize (eq reason 'run))
556: (if (eq reason 'run)
557: (xscheme-modeline-initialize)
558: (progn
559: (setq scheme-mode-line-process "")
560: (setq xscheme-mode-string "no process")))
561: (if (and (not (memq reason '(run stop)))
562: xscheme-signal-death-message)
563: (progn (beep)
564: (message
565: "The Scheme process has died! Do M-x reset-scheme to restart it"))))
566:
567: (defun xscheme-process-filter-initialize (running-p)
568: (setq xscheme-process-filter-state 'idle)
569: (setq xscheme-running-p running-p)
570: (setq xscheme-control-g-disabled-p nil)
571: (setq xscheme-allow-output-p t)
572: (setq xscheme-prompt "")
573: (setq scheme-mode-line-process '(": " xscheme-runlight-string)))
574:
575: (defun xscheme-process-filter (proc string)
576: (let ((xscheme-filter-input string))
577: (while xscheme-filter-input
578: (cond ((eq xscheme-process-filter-state 'idle)
579: (let ((start (string-match "\e" xscheme-filter-input)))
580: (if start
581: (progn
582: (xscheme-process-filter-output
583: (substring xscheme-filter-input 0 start))
584: (setq xscheme-filter-input
585: (substring xscheme-filter-input (1+ start)))
586: (setq xscheme-process-filter-state 'reading-type))
587: (let ((string xscheme-filter-input))
588: (setq xscheme-filter-input nil)
589: (xscheme-process-filter-output string)))))
590: ((eq xscheme-process-filter-state 'reading-type)
591: (if (zerop (length xscheme-filter-input))
592: (setq xscheme-filter-input nil)
593: (let ((char (aref xscheme-filter-input 0)))
594: (setq xscheme-filter-input
595: (substring xscheme-filter-input 1))
596: (let ((entry (assoc char xscheme-process-filter-alist)))
597: (if entry
598: (funcall (nth 2 entry) (nth 1 entry))
599: (progn
600: (xscheme-process-filter-output ?\e char)
601: (setq xscheme-process-filter-state 'idle)))))))
602: ((eq xscheme-process-filter-state 'reading-string)
603: (let ((start (string-match "\e" xscheme-filter-input)))
604: (if start
605: (let ((string
606: (concat xscheme-string-accumulator
607: (substring xscheme-filter-input 0 start))))
608: (setq xscheme-filter-input
609: (substring xscheme-filter-input (1+ start)))
610: (setq xscheme-process-filter-state 'idle)
611: (funcall xscheme-string-receiver string))
612: (progn
613: (setq xscheme-string-accumulator
614: (concat xscheme-string-accumulator
615: xscheme-filter-input))
616: (setq xscheme-filter-input nil)))))
617: (t
618: (error "Scheme process filter -- bad state"))))))
619:
620: ;;;; Process Filter Output
621:
622: (defun xscheme-process-filter-output (&rest args)
623: (if xscheme-allow-output-p
624: (let ((string (apply 'concat args)))
625: (save-excursion
626: (xscheme-goto-output-point)
627: (while (string-match "\\(\007\\|\f\\)" string)
628: (let ((start (match-beginning 0))
629: (end (match-end 0)))
630: (insert-before-markers (substring string 0 start))
631: (if (= ?\f (aref string start))
632: (progn
633: (if (not (bolp))
634: (insert-before-markers ?\n))
635: (insert-before-markers ?\f))
636: (beep))
637: (setq string (substring string (1+ start)))))
638: (insert-before-markers string)))))
639:
640: (defun xscheme-guarantee-newlines (n)
641: (if xscheme-allow-output-p
642: (save-excursion
643: (xscheme-goto-output-point)
644: (let ((stop nil))
645: (while (and (not stop)
646: (bolp))
647: (setq n (1- n))
648: (if (bobp)
649: (setq stop t)
650: (backward-char))))
651: (xscheme-goto-output-point)
652: (while (> n 0)
653: (insert-before-markers ?\n)
654: (setq n (1- n))))))
655:
656: (defun xscheme-goto-output-point ()
657: (let ((process (get-process "scheme")))
658: (set-buffer (process-buffer process))
659: (goto-char (process-mark process))))
660:
661: (defun xscheme-modeline-initialize ()
662: (setq xscheme-runlight-string "")
663: (setq xscheme-mode-string "")
664: (setq mode-line-buffer-identification '("Scheme: " xscheme-mode-string)))
665:
666: (defun xscheme-set-runlight (runlight)
667: (setq xscheme-runlight-string runlight)
668: (xscheme-modeline-redisplay))
669:
670: (defun xscheme-modeline-redisplay ()
671: (save-excursion (set-buffer (other-buffer)))
672: (set-buffer-modified-p (buffer-modified-p))
673: (sit-for 0))
674:
675: ;;;; Process Filter Operations
676:
677: (defvar xscheme-process-filter-alist
678: '((?D xscheme-enter-debugger-mode
679: xscheme-process-filter:string-action)
680: (?P xscheme-set-prompt-variable
681: xscheme-process-filter:string-action)
682: (?R xscheme-enter-interaction-mode
683: xscheme-process-filter:simple-action)
684: (?b xscheme-start-gc
685: xscheme-process-filter:simple-action)
686: (?e xscheme-finish-gc
687: xscheme-process-filter:simple-action)
688: (?f xscheme-exit-input-wait
689: xscheme-process-filter:simple-action)
690: (?g xscheme-enable-control-g
691: xscheme-process-filter:simple-action)
692: (?i xscheme-prompt-for-expression
693: xscheme-process-filter:string-action)
694: (?m xscheme-message
695: xscheme-process-filter:string-action)
696: (?n xscheme-prompt-for-confirmation
697: xscheme-process-filter:string-action)
698: (?o xscheme-output-goto
699: xscheme-process-filter:simple-action)
700: (?p xscheme-set-prompt
701: xscheme-process-filter:string-action)
702: (?s xscheme-enter-input-wait
703: xscheme-process-filter:simple-action)
704: (?v xscheme-write-value
705: xscheme-process-filter:string-action)
706: (?w xscheme-cd
707: xscheme-process-filter:string-action)
708: (?z xscheme-display-process-buffer
709: xscheme-process-filter:simple-action)
710: (?c xscheme-unsolicited-read-char
711: xscheme-process-filter:simple-action))
712: "Table used to decide how to handle process filter commands.
713: Value is a list of entries, each entry is a list of three items.
714:
715: The first item is the character that the process filter dispatches on.
716: The second item is the action to be taken, a function.
717: The third item is the handler for the entry, a function.
718:
719: When the process filter sees a command whose character matches a
720: particular entry, it calls the handler with two arguments: the action
721: and the string containing the rest of the process filter's input
722: stream. It is the responsibility of the handler to invoke the action
723: with the appropriate arguments, and to reenter the process filter with
724: the remaining input.")
725:
726: (defun xscheme-process-filter:simple-action (action)
727: (setq xscheme-process-filter-state 'idle)
728: (funcall action))
729:
730: (defun xscheme-process-filter:string-action (action)
731: (setq xscheme-string-receiver action)
732: (setq xscheme-string-accumulator "")
733: (setq xscheme-process-filter-state 'reading-string))
734:
735: (defconst xscheme-runlight:running "run"
736: "The character displayed when the Scheme process is running.")
737:
738: (defconst xscheme-runlight:input "input"
739: "The character displayed when the Scheme process is waiting for input.")
740:
741: (defconst xscheme-runlight:gc "gc"
742: "The character displayed when the Scheme process is garbage collecting.")
743:
744: (defun xscheme-start-gc ()
745: (xscheme-set-runlight xscheme-runlight:gc))
746:
747: (defun xscheme-finish-gc ()
748: (xscheme-set-runlight
749: (if xscheme-running-p xscheme-runlight:running xscheme-runlight:input)))
750:
751: (defun xscheme-enter-input-wait ()
752: (xscheme-set-runlight xscheme-runlight:input)
753: (setq xscheme-running-p nil))
754:
755: (defun xscheme-exit-input-wait ()
756: (xscheme-set-runlight xscheme-runlight:running)
757: (setq xscheme-running-p t))
758:
759: (defun xscheme-enable-control-g ()
760: (setq xscheme-control-g-disabled-p nil))
761:
762: (defun xscheme-display-process-buffer ()
763: (let ((window (or (xscheme-process-buffer-window)
764: (display-buffer (xscheme-process-buffer)))))
765: (save-window-excursion
766: (select-window window)
767: (xscheme-goto-output-point)
768: (if (xscheme-debugger-mode-p)
769: (xscheme-enter-interaction-mode)))))
770:
771: (defun xscheme-unsolicited-read-char ()
772: nil)
773:
774: (defun xscheme-message (string)
775: (if (not (zerop (length string)))
776: (xscheme-write-message-1 string (format ";%s" string))))
777:
778: (defun xscheme-write-value (string)
779: (if (zerop (length string))
780: (xscheme-write-message-1 "(no value)" ";No value")
781: (xscheme-write-message-1 string (format ";Value: %s" string))))
782:
783: (defun xscheme-write-message-1 (message-string output-string)
784: (let* ((process (get-process "scheme"))
785: (window (get-buffer-window (process-buffer process))))
786: (if (or (not window)
787: (not (pos-visible-in-window-p (process-mark process)
788: window)))
789: (message "%s" message-string)))
790: (xscheme-guarantee-newlines 1)
791: (xscheme-process-filter-output output-string))
792:
793: (defun xscheme-set-prompt-variable (string)
794: (setq xscheme-prompt string))
795:
796: (defun xscheme-set-prompt (string)
797: (setq xscheme-prompt string)
798: (xscheme-guarantee-newlines 2)
799: (setq xscheme-mode-string (xscheme-coerce-prompt string))
800: (xscheme-modeline-redisplay))
801:
802: (defun xscheme-output-goto ()
803: (xscheme-goto-output-point)
804: (xscheme-guarantee-newlines 2))
805:
806: (defun xscheme-coerce-prompt (string)
807: (if (string-match "^[0-9]+ " string)
808: (let ((end (match-end 0)))
809: (concat (substring string 0 end)
810: (let ((prompt (substring string end)))
811: (let ((entry (assoc prompt xscheme-prompt-alist)))
812: (if entry
813: (cdr entry)
814: prompt)))))
815: string))
816:
817: (defvar xscheme-prompt-alist
818: '(("[Normal REPL]" . "[Evaluator]")
819: ("[Error REPL]" . "[Evaluator]")
820: ("[Breakpoint REPL]" . "[Evaluator]")
821: ("[Debugger REPL]" . "[Evaluator]")
822: ("[Visiting environment]" . "[Evaluator]")
823: ("[Environment Inspector]" . "[Where]"))
824: "An alist which maps the Scheme command interpreter type to a print string.")
825:
826: (defun xscheme-cd (directory-string)
827: (save-excursion
828: (set-buffer (xscheme-process-buffer))
829: (cd directory-string)))
830:
831: (defun xscheme-prompt-for-confirmation (prompt-string)
832: (xscheme-send-char (if (y-or-n-p prompt-string) ?y ?n)))
833:
834: (defun xscheme-prompt-for-expression (prompt-string)
835: (xscheme-send-string-2
836: (read-from-minibuffer prompt-string nil xscheme-prompt-for-expression-map)))
837:
838: (defvar xscheme-prompt-for-expression-map nil)
839: (if (not xscheme-prompt-for-expression-map)
840: (progn
841: (setq xscheme-prompt-for-expression-map
842: (copy-keymap minibuffer-local-map))
843: (substitute-key-definition 'exit-minibuffer
844: 'xscheme-prompt-for-expression-exit
845: xscheme-prompt-for-expression-map)))
846:
847: (defun xscheme-prompt-for-expression-exit ()
848: (interactive)
849: (if (eq (xscheme-region-expression-p (point-min) (point-max)) 'one)
850: (exit-minibuffer)
851: (error "input must be a single, complete expression")))
852:
853: (defun xscheme-region-expression-p (start end)
854: (save-excursion
855: (let ((old-syntax-table (syntax-table)))
856: (unwind-protect
857: (progn
858: (set-syntax-table scheme-mode-syntax-table)
859: (let ((state (parse-partial-sexp start end)))
860: (and (zerop (car state)) ;depth = 0
861: (nth 2 state) ;last-sexp exists, i.e. >= 1 sexps
862: (let ((state (parse-partial-sexp start (nth 2 state))))
863: (if (nth 2 state) 'many 'one)))))
864: (set-syntax-table old-syntax-table)))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.