compatibility/compatibility-lib/mzlib/transcr.rkt
2014-12-02 09:43:08 -05:00

50 lines
1.4 KiB
Racket

(module transcr mzscheme
(require mzlib/port)
(provide (rename -transcript-on transcript-on)
(rename -transcript-off transcript-off))
;; Bug: the implementation strategy used for the tees does not
;; guarantee that flushes to stdout and stderr are kept in order.
;; It depends instead on the whims of scheduling the tee threads.
;; This problem could be fixed using `make-output-port' instead
;; of pipes and `copy-port'.
(define-values (-transcript-on -transcript-off)
(let ([in #f]
[out #f]
[err #f]
[tee-out (lambda (p p2)
(let-values ([(r w) (make-pipe)])
(thread
(lambda ()
(copy-port r p p2)))
w))]
[tee-in (lambda (in out)
(let-values ([(r w) (make-pipe)])
(thread
(lambda ()
(copy-port in w out)))
r))])
(values
(lambda (file)
(when in
(error 'transcript-on "transcript is already on"))
(let ([p (open-output-file file)])
(set! in (current-input-port))
(set! out (current-output-port))
(set! err (current-error-port))
(current-output-port (tee-out out p))
(current-error-port (tee-out err p))
(current-input-port (tee-in in p))))
(lambda ()
(unless in
(error 'transcript-on "transcript is not on"))
(current-input-port in)
(current-output-port out)
(current-error-port err)
(set! in #f)
(set! out #f)
(set! err #f))))))