To enable the use of GDS in your own Emacs sessions, simply add
somewhere in your .emacs file. This will cause Emacs to load the GDS Emacs Lisp code when starting up, and to start the inferior GDS server process so that it is ready and waiting for any Guile programs that want to use GDS.
The Scheme side of GDS is installed automatically by Guile. The Emacs Lisp side, however, is not. You will have to grab gds-server.el, gds-scheme.el, and gds.el from Guile's source distribution, and make sure they end up in Emacs' load path.
(If GDS's Scheme code is not installed in one of the locations in Guile's load path, you may find that the server process fails to start. When this happens you will see an error message from Emacs:
error in process filter: Wrong type argument: listp, Backtrace:
gds-debug buffer will contain a Scheme backtrace ending
with the message:
no code for module (ice-9 gds-server)
The solution for this is to customize the Emacs variable
gds-scheme-directory so that it specifies where the GDS Scheme
code is installed. Then either restart Emacs or type M-x
gds-run-debug-server to try starting the GDS server process again.)
For evaluations, help and completion from Scheme code buffers that you
are working on, this is all you need. The first time you do any of
these things, GDS will automatically start a new Guile client program as
an Emacs subprocess. This Guile program does nothing but wait for and
act on instructions from GDS, and we refer to it as a utility
Guile client. Over time this utility client will accumulate the code
that you ask it to evaluate, and you can also tell it to load complete
files or modules by sending it
When you want to use GDS to work on an independent Guile application, you need to add something to that application's Scheme code to cause it to connect to and interact with GDS at the right times. The following subsections describe the ways of doing this.
One option is to use GDS to catch and display any exceptions that
are thrown by the application's code. If you already have a
with-throw-handler around the area of code
that you want to monitor, you just need to add the following to the
(gds-debug-trap (throw->trap-context key args))
args are the first and rest arguments that
Guile passes to the handler. (In other words, they assume the handler
(lambda (key . args) ...).) With Guile 1.8 or
later, you can also do this with a
catch, by adding this same
code to the catch's pre-unwind handler.
If you don't already have any of these, insert a whole
with-throw-handler expression (or
lazy-catch if your Guile
is pre-1.8) around the code of interest like this:
(with-throw-handler #t (lambda () ;; Protected code here. ) (lambda (key . args) (gds-debug-trap (throw->trap-context key args))))
Either way, you will need to use the
(ice-9 gds-client) and
(ice-9 debugging traps) modules.
Two special cases of this are the lazy-catch that the Guile REPL code
uses to catch exceptions in user code, and the lazy-catch inside the
stack-catch utility procedure that is provided by the
(ice-9 stack-catch) module. Both of these use a handler called
lazy-handler-dispatch (defined in boot-9.scm), which you
can hook into such that it calls GDS to display the stack when an
exception occurs. To do this, use the
procedure as follows.
(use-modules (ice-9 gds-client) (ice-9 debugging traps)) (on-lazy-handler-dispatch gds-debug-trap)
After this the program will use GDS to display the stack whenever it
hits an exception that is protected by a
In addition to setting an exception handler as described above, a Guile program can in principle set itself up to accept new instructions from GDS at any time, not just when it has stopped at an exception. This would allow the GDS user to evaluate code in the context of the running program, without having to wait for the program to stop first.
(use-modules (ice-9 gds-client)) (gds-accept-input #t)
gds-accept-input causes the calling program to loop processing
instructions from GDS, until GDS sends the
This blocks the thread that calls it, however, so it will normally be
more practical for the program to set up a dedicated GDS thread and call
gds-accept-input from that thread.
select-driven applications, an alternative approach would be
for the GDS client code to provide an API which allowed the application
selectindicated data available for reading on those descriptors/ports.
This approach is not yet implemented, though.
The “utility” Guile client mentioned above is a simple combination of the mechanisms that we have just described. In fact the code for the utility Guile client is essentially just this:
(use-modules (ice-9 gds-client)) (named-module-use! '(guile-user) '(ice-9 session)) (gds-accept-input #f))
named-module-use! line ensures that the client can process
apropos expressions, to implement lookups in
Guile's online help. The
#f parameter to
gds-accept-input means that the
will not cause the instruction loop to exit, which makes sense here
because the utility client has nothing to do except to process GDS
The utility client does not use
on-lazy-handler-dispatch at its
top level, because it has its own mechanism for catching and reporting
exceptions in the code that it is asked to evaluate. This mechanism
summarizes the exception and gives the user a button they can click to
see the full stack, so the end result is very similar to what
on-lazy-handler-dispatch provides. Deep inside
gds-accept-input, in the part that handles evaluating
expressions from Emacs, the GDS client code uses
gds-debug-trap to implement