diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | bin/Makefile.am | 15 | ||||
| -rwxr-xr-x | bin/geiser-racket.sh | 19 | ||||
| -rw-r--r-- | configure.ac | 1 | ||||
| -rw-r--r-- | doc/repl.texi | 60 | ||||
| -rw-r--r-- | elisp/geiser-connection.el | 57 | 
7 files changed, 102 insertions, 53 deletions
| @@ -30,3 +30,4 @@  /doc/geiser.info  /doc/texinfo.tex  /autom4te.cache/ +/bin/Makefile.in diff --git a/Makefile.am b/Makefile.am index 0ef180e..4f5a16b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = . elisp scheme doc +SUBDIRS = . elisp scheme bin doc  EXTRA_DIST = THANKS diff --git a/bin/Makefile.am b/bin/Makefile.am new file mode 100644 index 0000000..9f6ee2b --- /dev/null +++ b/bin/Makefile.am @@ -0,0 +1,15 @@ +EXTRA_DIST = geiser-racket.sh +dist_bin_SCRIPTS = geiser-racket +noinst_SCRIPTS = geiser-racket-noinst + +CLEANFILES = $(dist_bin_SCRIPTS) $(noinst_SCRIPTS) + +geiser-racket: $(srcdir)/geiser-racket.sh +	@sed -e "s|top=\".*\"|top=$(datarootdir)/geiser|" \ +             $(srcdir)/geiser-racket.sh >$@ +	@chmod +x $@ + +geiser-racket-noinst: $(srcdir)/geiser-racket.sh +	@sed -e "s|top=\".*\"|top=$(abs_top_srcdir)/scheme|" \ +             $(srcdir)/geiser-racket.sh >$@ +	@chmod +x $@ diff --git a/bin/geiser-racket.sh b/bin/geiser-racket.sh new file mode 100755 index 0000000..4f16383 --- /dev/null +++ b/bin/geiser-racket.sh @@ -0,0 +1,19 @@ +#!/bin/bash +#| +top="$(dirname $0)/../scheme" +exec racket -i -S "$top/racket" -l errortrace -cu "$0" ${1+"$@"} +|# + +#lang racket/base + +(require (lib "cmdline.rkt")) + +(define port (make-parameter 1969)) + +(command-line + "run-racket.sh" (current-command-line-arguments) + (once-each +  (("-p" "--port") p "Geiser server port" (port (string->number p))))) + +(and ((dynamic-require 'geiser/server 'start-geiser) (port)) +     (printf "Geiser server running at port ~a~%" (port))) diff --git a/configure.ac b/configure.ac index 1a70214..ddeec3f 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ elisp/Makefile  elisp/geiser-version.el  elisp/geiser-load.el  scheme/Makefile +bin/Makefile  doc/Makefile  ]) diff --git a/doc/repl.texi b/doc/repl.texi index e707e61..03fb42a 100644 --- a/doc/repl.texi +++ b/doc/repl.texi @@ -45,27 +45,49 @@ evaluation when they're complete, and will indent new lines properly  until then. It will also keep track of your input, maintaining a history  file that will be reloaded whenever you restart the REPL. +@subsubheading Connecting to an external Scheme  @cindex remote REPL  @cindex connect to server -If you use Guile, there's an alternative way of starting a Geiser REPL: -you can connect to a remote Guile process, provided the latter is -running a REPL server. For that to happen, you just need to start your -Guile process (outside Emacs) passing to it the flag @code{--listen}. -Then, come back to Emacs and execute @kbd{M-x connect-to-guile}. You'll -be asked for a host and a port, with suitable default values (Guile's -@code{--listen} flag accepts an optional port as argument (as in -@code{--listen=1969}), if you don't want to use the default). And voila, -you'll have a Geiser REPL that is served by the remote Guile process in -a dedicated thread, meaning that your Guile can go on doing whatever it -was doing while you tinker with it from Emacs. Note, however, -that all Guile threads share the heap, so that you'll be able to -interact with those other threads in the running scheme from Emacs in a -variety of ways. For starters, all you (re)defintions will be visible -everywhere. That's dangerous, but will come in handy when you need to -debug your running webserver. - -Nothing that fanciful this far, but there's more to Geiser's REPL. On -to the next section! +There's an alternative way of starting a Geiser REPL: you can connect to +an external Scheme process, provided it's running a REPL server at some +known port. How to make that happen depends on the Scheme implementation. + +@cindex Guile's REPL server +If you use Guile, you just need to start your Guile process (possibly +outside Emacs) passing to it the flag @code{--listen}. This flag accepts +an optional port as argument (as in @code{--listen=1969}), if you don't +want to use the default. + +@cindex Racket's REPL server +In Racket, you have to use the REPL server that comes with Geiser. To +that end, put Geiser's Racket scheme directory in the Racket's +collection search path and invoke @code{start-geiser} (a procedure in +the module @code{geiser/server}) somewhere in your program, passing it +the desired port. This procedure will start the REPL server in a +separate thread. For an example of how to do that, see the script +@file{bin/geiser-racket.sh} in the source distribution, or, if you've +compiled Geiser, @file{bin/geiser-racket-noinst} in the build directory, +or, if you've installed Geiser, @file{geiser-racket} in +@file{<installation-prefix>/bin}. These scripts start a new interactive +Racket that is also running a REPL server (they also load the errortrace +library to provide better diagnostics, but that's not strictly needed). + +With your external Scheme process running and serving, come back to +Emacs and execute @kbd{M-x geiser-connect}, @kbd{M-x connect-to-guile} +or @kbd{M-x connect-to-racket}. You'll be asked for a host and a port, +and, voila, you'll have a Geiser REPL that is served by the remote +Scheme process in a dedicated thread, meaning that your external program +can go on doing whatever it was doing while you tinker with it from +Emacs. Note, however, that all Scheme threads share the heap, so that +you'll be able to interact with those other threads in the running +scheme from Emacs in a variety of ways. For starters, all your +(re)defintions will be visible everywhere. That's dangerous, but will +come in handy when you need to debug your running webserver. + +@cindex remote connections +The connection between Emacs and the Scheme process goes over TCP, so it +can be as remote as you need, perhaps with the intervention of an SSH +tunnel.  @node First aids, Switching context, Starting the REPL, The REPL  @section First aids diff --git a/elisp/geiser-connection.el b/elisp/geiser-connection.el index f146563..dc669aa 100644 --- a/elisp/geiser-connection.el +++ b/elisp/geiser-connection.el @@ -159,15 +159,17 @@ By default, Geiser uses the prompt regexp.")  (make-variable-buffer-local   (defvar geiser-con--debugging-preamble-regexp nil)) -(defun geiser-con--is-debugging () -  (and geiser-con--debugging-prompt-regexp -       geiser-con--debugging-inhibits-eval -       comint-last-prompt-overlay -       (string-match-p geiser-con--debugging-prompt-regexp -                       (buffer-substring (overlay-start -                                          comint-last-prompt-overlay) -                                         (overlay-end -                                          comint-last-prompt-overlay))))) +(defun geiser-con--is-debugging (&optional con) +  (with-current-buffer (or (and con (geiser-con--connection-buffer con)) +                           (current-buffer)) +    (and geiser-con--debugging-prompt-regexp +         geiser-con--debugging-inhibits-eval +         comint-last-prompt-overlay +         (string-match-p geiser-con--debugging-prompt-regexp +                         (buffer-substring (overlay-start +                                            comint-last-prompt-overlay) +                                           (overlay-end +                                            comint-last-prompt-overlay))))))  (defsubst geiser-con--has-entered-debugger (con)    (with-current-buffer (geiser-con--connection-buffer con) @@ -278,35 +280,24 @@ By default, Geiser uses the prompt regexp.")  (defvar geiser-connection-timeout 30000    "Time limit, in msecs, blocking on synchronous evaluation requests") -(defun geiser-con--send-string/wait (buffer/proc str cont -						 &optional timeout sbuf) +(defun geiser-con--send-string/wait (b/p str cont &optional timeout sbuf)    (save-current-buffer -    (let* ((con (geiser-con--get-connection buffer/proc)) +    (let* ((con (geiser-con--get-connection b/p))             (proc (and con (geiser-con--connection-process con)))) -      (unless proc -        (error geiser-con--error-message)) -      (with-current-buffer (geiser-con--connection-buffer con) -        (when (geiser-con--is-debugging) -          (error "Geiser REPL is in debug mode"))) +      (unless proc (error geiser-con--error-message)) +      (when (geiser-con--is-debugging con) (error "REPL is in debug mode"))        (let* ((req (geiser-con--make-request con str cont sbuf)) -             (id (and req (geiser-con--request-id req))) -             (time (or timeout geiser-connection-timeout)) -             (step 100) -             (waitsecs (/ step 1000.0))) -        (when id -          (geiser-con--connection-add-request con req) -          (geiser-con--process-next con) +             (id (geiser-con--request-id req)) +             (timeout (/ (or timeout geiser-connection-timeout) 1000.0)) +             (waitsecs 0.1)) +        (geiser-con--connection-add-request con req) +        (with-timeout (timeout (geiser-con--request-deactivate req))            (condition-case nil -              (while (and (> time 0) -                          (geiser-con--connection-process con) +              (while (and (geiser-con--connection-process con)                            (not (geiser-con--connection-completed-p con id))) -                (unless (accept-process-output nil waitsecs nil nil) -		  (geiser-con--process-next con) -                  (setq time (- time step)))) -            (error (setq time 0))) -          (or (> time 0) -              (geiser-con--request-deactivate req) -              nil)))))) +                (geiser-con--process-next con) +                (accept-process-output proc waitsecs nil t)) +            (error (geiser-con--request-deactivate req))))))))  (provide 'geiser-connection) | 
