[plt-scheme] Hacking Emacs

From: Eli Barzilay (eli at barzilay.org)
Date: Sat Jun 9 21:30:07 EDT 2007

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!


Posted on the users mailing list.