From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Andy Wingo Newsgroups: gmane.lisp.guile.user Subject: Guile + Emacs HOWTO Date: Fri, 15 Feb 2008 15:43:00 +0100 Message-ID: <874pca9t6z.fsf@pobox.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1203086800 32529 80.91.229.12 (15 Feb 2008 14:46:40 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Fri, 15 Feb 2008 14:46:40 +0000 (UTC) To: guile-user Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Fri Feb 15 15:47:03 2008 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1JQ1q2-00047U-7Y for guile-user@m.gmane.org; Fri, 15 Feb 2008 15:46:54 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JQ1pY-0001Yk-5G for guile-user@m.gmane.org; Fri, 15 Feb 2008 09:46:24 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JQ1nm-0000S2-5v for guile-user@gnu.org; Fri, 15 Feb 2008 09:44:34 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JQ1nl-0000Qo-6W for guile-user@gnu.org; Fri, 15 Feb 2008 09:44:33 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JQ1nk-0000QZ-UE for guile-user@gnu.org; Fri, 15 Feb 2008 09:44:32 -0500 Original-Received: from ambient.dashsystems.com ([216.27.85.7] helo=kettle.ambient-hosting.net) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JQ1nk-0007bp-Hg for guile-user@gnu.org; Fri, 15 Feb 2008 09:44:32 -0500 Original-Received: from localhost.localdomain (ambient-hosting.net [10.1.6.1]) by kettle.ambient-hosting.net (Postfix) with ESMTP id 6D7E5880CB for ; Fri, 15 Feb 2008 09:43:53 -0500 (EST) Original-Received: by localhost.localdomain (Postfix, from userid 1000) id 259341180C6; Fri, 15 Feb 2008 15:43:01 +0100 (CET) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.50 (gnu/linux) X-detected-kernel: by monty-python.gnu.org: Linux 2.4-2.6 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:6423 Archived-At: Greetings conniving guilers, Today I figured out some awesomeness: how to hook up Emacs to a running Guile application. Good times! Directions follow, after a bit of background. 1) Install guile-debugging. If you are running HEAD guile, you already have it installed, because it is part of Guile. Otherwise if you are running 1.6 or 1.8, it's a little bit hacky: # Check out Guile HEAD: cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/guile \ co -d guile-HEAD guile/guile-core # Copy (ice-9 debugging) to a suitable location: sudo mkdir -p /usr/share/guile/site/ice-9 sudo cp -r guile-HEAD/ice-9/debugging /usr/share/guile/site/ice-9 # Copy (ice-9 gds-client) and (ice-9 gds-server) there too: sudo cp -r guile-HEAD/ice-9/gds-* /usr/share/guile/site/ice-9 # Install the emacs foo: sudo mkdir -p ~/.emacs-el/ sudo cp -r guile-HEAD/emacs/gds*.el ~/.emacs-el. (Alternately you can download and install the guile-debugging 0.15 tarball, but its gds-scheme.el file is slightly out of date relative to the one in Guile CVS.) 2) In Emacs, load up GDS by adding: (require 'gds) to your ~/.emacs. If you had to follow the manual installation steps of (1), you'll want to add ~/.emacs-el to the load path via: (add-to-list 'load-path "~/.emacs-el/") Put the `add-to-list' before the `require'. 3) Verify that GDS is working. Open /tmp/foo.scm, type (+ 2 2), and press C-x C-e. It should start a guile process, evaluate the expression, and print out the answer. Yay! So now the obvious question is, how do I get Emacs to do this with a running process, like a web server? Well, it turns out this is easy enough. However you should know something about the architecture of GDS, Guile's Emacs integration library. +--------------------------+ | Emacs | | running gds-server.el | +-----------+--------------+ | +-----------+--------------+ | guile running | | (ice-9 gds-server) | +----/------\--------------+ /--- \- +---------------+ +-----\-----------+ |guile running | |another guile | more guiles... |(ice-9 gds-client) |running gds-client +---------------+ +-----------------+ All of the boxes in this diagram are processes, and all of them connect to the gds server, which conventionally runs on port 8333. Indeed, (ice-9 gds-client) has no way to specify another port -- something to fix, I guess. The GDS server serves as a kind of multiplexing point between emacsen and guiles, although I do not thing the multiple-emacs thing works yet. By default, and currenty the only way to do things, Emacs will start gds-server as needed, or explicitly via M-x gds-run-debug-server. When you pressed C-x C-e before in the foo.scm buffer, what happened was that Emacs saw that the buffer was not yet associated with any guile process, so Emacs started a guile process itself. The client process was spawned by emacs exactly like this: guile -c '(begin (use-modules (ice-9 gds-client)) (run-utility))' `run-utility' is named that way because it was made for emacs to run a "utility guile process", an anonymous process in which to evaluate guile things. However the code is generic, you can call this in your own application, and voici the point of this email. In your application, just run the following: (use-modules (ice-9 gds-client) (ice-9 threads)) (make-thread run-utility) and then go about your business. A separate thread will be spawned for interacting with emacs. Of course, your guile will have to support threads, and I don't think that Debian's 1.8 does. In that case you might want to add a --gds-debug option to your application so that instead of going into whatever other main loop it would go into, that it goes into the run-utility loop. Or just compile a threaded guile. Then, inside emacs, associate your buffers with that guile: M-x gds-associate-buffer [choose the PID of your guile process] At that point you can start evaluating code inside emacs and having it update in the live application, interactively deal with backtraces, inspect the stack, set breakpoints, etc. Fun stuff. Happy hacking! Andy -- http://wingolog.org/