[plt-scheme] Hacking Emacs
Due to a request, here's how I see an Emacs hack to make it do the
DrScheme "run" thing. (With apologies to DrScheme-jr...)
* As soon as Scheme evaluation is necessary, a mzscheme process is
fired up, associated with some hidden buffer.
* In this process, the `sandbox' library is required, and some
parameters are set. (This is needed because the default sandbox
setup is geared towards safety -- for example, no IO is permitted,
and there are strict resource limits on evaluation. You wouldn't
want these things in a real developement environment.)
* Some parameters should be set according to preferences from Emacs.
* Once that's done, all you need is a way to get a `listener' from an
Emacs buffer. The sandbox library has several ways to get a
listener, one is by giving it a file which it will evaluate, and
another is by giving it a string. The latter is probably better,
since it means that you can play with code without saving it. (As
in DrScheme.)
* So to get a listener, you pass an Emacs buffer as a string to the
mzscheme process -- either
(make-evaluator "--buffer-text--")
for a buffer that has a module and getting an evaluator that works
in the context of that module's namespace, or
(make-evaluator 'mzscheme '() "--buffer-text--")
for a mzscheme REPL-based evaluator. (For example, mutating
bindings is forbidden in the former (by default) and allowed in the
latter.)
The string should be easy to create, since strings in Emacs are
quoted as in Scheme. Something like `(format "%S" (buffer-string))'
should work. If there are problems with that, then saving the
buffer to a temporary file and sending that to `make-evaluator'
should work too.
* Obviously, you'll want a way to get a hold of the evaluator that is
created. It will probably work best to send this to the mzscheme
process:
(define ev1234 (make-evaluator ...))
where the `1234' is some counter. Each evaluation in this evaluator
would be done using
(ev1234 ...expr...)
* Now that you have an evaluator object, you need to create an Emacs
buffer to talk to it (with a local variable that keeps the `ev1234'
name). Probably some comint-based thing will do. Something that
will read input, and hitting `enter' invokes some Emacs function to
deal with the input. To deal with the input, you'll send to the
mzscheme process something like:
(ev1234 ...input...)
and then use the sandbox's `get-output' function to get the output,
push that to the interaction buffer, then push the text of the
result. (This is already bogus, see below.)
* There should also be stuff like a kill buffer hook that will do
something like:
(kill-evaluator ev1234)
(set! ev1234 null)
* The bogus point above is that this requires sequential access from
Emacs. You don't want to wait for the output of each evaluation,
since you may have other buffers that you're working with. Another
thing is that you want this:
(begin (display "foo\n") (sleep 10) (display "bar\n"))
to show `foo' immediately, rather than seeing the whole thing when
it ends. The best way to do this would be use pipes for IO. I'm
not sure what is the state of Emacs for talking to such things.
Perhaps tcp ports would work? The above should be a good start
though, and I can make more code if anyone gets to that point.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!