Next: , Previous: Value History, Up: Top


45 REPL Under Emacs

You can run a Guile interpreter as a subprocess under Emacs in many ways. One way is to type M-x shell RET and invoke Guile from the resulting shell. Another is to type C-u M-x run-scheme RET and specify guile as the scheme program name. See Shell, for details.

This chapter documents yet another way, which makes use of an experimental, low-level, custom protocol between Emacs and the Guile subprocess.

45.1 Two Sides

On the Guile side of things, the protocol is activated by evaluating the form:

     (use-modules (ice-9 emacs))

Note that Guile does this for you if given the --emacs command-line option (see Invoking Guile).

On the Emacs side of things, M-x inferior-guile RET handles the lowest-level protocol details, including starting a Guile subprocess, passing the --emacs command-line option to it, and arranging to filter the subprocess output into state transitions (see below). To make this command available, place in your .emacs file the forms:

     (require 'add-guile-dirs)
     (require 'inf-guile)

45.2 Theory of Operation

The low-level details of the protocol are “internal”, and (despite years of neglect) are subject to change in the future. So this section concentrates on the abstract model presented to the Emacs side of the things:

45.3 Programming Interface

As you can surmise from the preceding section, any user-friendly (or even user-visible :-) behavior must be implemented by specifying state transition handler functions. You do this with define-inf-guile-transition:

— Emacs Lisp Function: define-inf-guile-transition from to handler

This arranges for handler to be called when the Guile subprocess goes from state from to state to. from or to may be t to indicate “any” state.

For any transition, the handler called is searched first with exact from and to, then with exact from and any to, then with any from and exact to and finally, with any from and any to. This latter transition is the default transition, which is pre-set to call inf-guile-null-transition.

— Emacs Lisp Function: inf-guile-null-transition proc old

This function does nothing, and is the handler for the default transition.

45.4 Example

An example of using the programming interface described above is distributed with Guile. To play, evaluate the forms in Emacs:

     (require 'add-guile-dirs)
     (require 'inf-guile-synch-voeb)

This will make inf-guile-synchronous-send/return available. Here is a sample session (snapshot from the *scratch* buffer) using it:

     (setq p (inferior-guile))
     ⇒ #<process inferior guile>
     
     (defun p! (s &rest args)
       (apply 'inf-guile-synchronous-send/return
              p s args))
     ⇒ p!
     
     (p! "42")
     ⇒ ["42
     " nil nil]
     
     (dolist (x (number-sequence 1 3))
       (p! "(define (add-%d n) (+ %d n))" x x))
     ⇒ nil
     
     (p! "add-3")
     ⇒ ["#<procedure add-3 (n)>
     " nil nil]
     
     (p! "(add-3 (* 3 13))")
     ⇒ ["42
     " nil nil]
     
     (p! "(add-2 #:nope!)")
     ⇒ ["ABORT: (wrong-type-arg)
     " "ERROR: In procedure + in expression (+ 2 n):
     ERROR: Wrong type argument: #:nope!
     " "
     Backtrace:
     0* [add-2 #:nope!]
     1  [+ 2 #:nope!]
     
     "]
     
     (p! "(quit)")
     ⇒ [nil nil nil]

Note that inf-guile-synchronous-send/return returns a “vector of output, error-message and backtrace-message”, which might help to explain the contraction “voeb”. Also, with the exception of the last call to p!, the output string (first element in the vector) always includes a newline.