From 95968c5dff4c8128a377d241436b6454c31c2e69 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Fri, 5 Nov 2010 01:58:28 +0100 Subject: Racket: fix for help function --- elisp/geiser-racket.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'elisp/geiser-racket.el') diff --git a/elisp/geiser-racket.el b/elisp/geiser-racket.el index c32bcc9..0508d6c 100644 --- a/elisp/geiser-racket.el +++ b/elisp/geiser-racket.el @@ -168,7 +168,7 @@ This function uses `geiser-racket-init-file' if it exists." (defsubst geiser-racket--get-help (symbol module) (geiser-eval--send/wait - `(:eval (get-help ',symbol (:module ,module)) geiser/autodoc))) + `(:eval (get-help ',symbol '(:module ,module)) geiser/autodoc))) (defun geiser-racket--external-help (id module) (message "Requesting help for '%s'..." id) -- cgit v1.2.3 From 2aad392f96e8fdf6040c3761171045e25fb0a8c9 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sat, 6 Nov 2010 21:42:09 +0100 Subject: Racket: little evaluation nits --- elisp/geiser-eval.el | 1 + elisp/geiser-racket.el | 7 ++++--- scheme/racket/geiser.rkt | 1 + scheme/racket/geiser/eval.rkt | 9 +++++---- scheme/racket/geiser/modules.rkt | 2 +- scheme/racket/geiser/user.rkt | 22 ++++++++++++++++------ 6 files changed, 28 insertions(+), 14 deletions(-) (limited to 'elisp/geiser-racket.el') diff --git a/elisp/geiser-eval.el b/elisp/geiser-eval.el index df31594..ffe3306 100644 --- a/elisp/geiser-eval.el +++ b/elisp/geiser-eval.el @@ -113,6 +113,7 @@ module-exports, autodoc, callers, callees and generic-methods.") (mapconcat 'geiser-eval--scheme-str code " ") ")")))) ((symbolp code) (format "%s" code)) + ((stringp code) (format "%S" (substring-no-properties code))) (t (format "%S" code)))) diff --git a/elisp/geiser-racket.el b/elisp/geiser-racket.el index 0508d6c..cd4cc8a 100644 --- a/elisp/geiser-racket.el +++ b/elisp/geiser-racket.el @@ -98,12 +98,12 @@ This function uses `geiser-racket-init-file' if it exists." (defun geiser-racket--geiser-procedure (proc &rest args) (case proc ((eval compile) - (format ",geiser-eval %s %s %s" + (format ",geiser-eval %s %s %s\n" (or (car args) "#f") (geiser-racket--language) (mapconcat 'identity (cdr args) " "))) ((load-file compile-file) - (format ",geiser-eval geiser/main racket (geiser:%s %s)" + (format ",geiser-eval geiser/main racket (geiser:%s %s)\n" proc (car args))) ((no-values) ",geiser-no-values") (t (format ",apply geiser:%s (%s)" proc (mapconcat 'identity args " "))))) @@ -150,7 +150,8 @@ This function uses `geiser-racket-init-file' if it exists." (format "(require %s)" module))) (defun geiser-racket--exit-command () - (not (geiser-eval--send/result '(:eval (exit) geiser/emacs)))) + (comint-send-eof) + (get-buffer-process (current-buffer))) (defconst geiser-racket--binding-forms '(for for/list for/hash for/hasheq for/and for/or diff --git a/scheme/racket/geiser.rkt b/scheme/racket/geiser.rkt index 1ab7983..44a2ed8 100644 --- a/scheme/racket/geiser.rkt +++ b/scheme/racket/geiser.rkt @@ -20,5 +20,6 @@ (require errortrace) (require geiser/user) +(init-geiser-repl) ;;; geiser.rkt ends here diff --git a/scheme/racket/geiser/eval.rkt b/scheme/racket/geiser/eval.rkt index 4e7f3db..66eccc6 100644 --- a/scheme/racket/geiser/eval.rkt +++ b/scheme/racket/geiser/eval.rkt @@ -55,10 +55,11 @@ (append last-result `((output . ,output))))) (define (eval-in form spec lang) - (call-with-result - (lambda () - (update-signature-cache spec form) - (eval form (module-spec->namespace spec lang))))) + (write (call-with-result + (lambda () + (update-signature-cache spec form) + (eval form (module-spec->namespace spec lang))))) + (newline)) (define compile-in eval-in) diff --git a/scheme/racket/geiser/modules.rkt b/scheme/racket/geiser/modules.rkt index 9b640ec..5c6ba1f 100644 --- a/scheme/racket/geiser/modules.rkt +++ b/scheme/racket/geiser/modules.rkt @@ -74,7 +74,7 @@ (call-with-values (lambda () (split-path path)) (lambda (_ basename __) (path->string basename))) (regexp-replace "\\.[^./]*$" real-path "")))] - [(eq? path '#%kernel) "(kernel)"] + ;; [(eq? path '#%kernel) "(kernel)"] [(string? path) path] [(symbol? path) (symbol->string path)] [else ""])) diff --git a/scheme/racket/geiser/user.rkt b/scheme/racket/geiser/user.rkt index 20f8a00..88cc24c 100644 --- a/scheme/racket/geiser/user.rkt +++ b/scheme/racket/geiser/user.rkt @@ -11,7 +11,7 @@ #lang racket/base -(provide enter!) +(provide init-geiser-repl run-geiser-repl enter!) (require geiser/main geiser/enter geiser/eval (for-syntax racket/base)) @@ -29,6 +29,7 @@ mod)))) (define orig-loader (current-load/use-compiled)) +(define geiser-loader (module-loader orig-loader)) (define orig-reader (current-prompt-read)) @@ -56,10 +57,19 @@ (else form))) (_ form)))) -(define (init) +(define geiser-prompt-read + (compose (make-repl-reader geiser-read) current-namespace)) + +(define (init-geiser-repl) (compile-enforce-module-constants #f) - (current-load/use-compiled (module-loader orig-loader)) - (current-prompt-read - (compose (make-repl-reader geiser-read) current-namespace))) + (current-load/use-compiled geiser-loader) + (current-prompt-read geiser-prompt-read)) -(init) +(define (run-geiser-repl in out (enforce-module-constants #f)) + (parameterize [(compile-enforce-module-constants enforce-module-constants) + (current-input-port in) + (current-output-port out) + (current-error-port out) + (current-load/use-compiled geiser-loader) + (current-prompt-read geiser-prompt-read)] + (read-eval-print-loop))) -- cgit v1.2.3 From 3ba17b64dfd84a313fdb631c0127de7f54218465 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sun, 7 Nov 2010 17:31:09 +0100 Subject: Pumbling cleanups --- elisp/geiser-connection.el | 118 +++++++++++++++++++++++---------------------- elisp/geiser-racket.el | 4 +- elisp/geiser-repl.el | 3 +- 3 files changed, 64 insertions(+), 61 deletions(-) (limited to 'elisp/geiser-racket.el') diff --git a/elisp/geiser-connection.el b/elisp/geiser-connection.el index 2702f0f..e24511b 100644 --- a/elisp/geiser-connection.el +++ b/elisp/geiser-connection.el @@ -35,12 +35,13 @@ ;;; Request datatype: -(defun geiser-con--make-request (str cont &optional sender-buffer) +(defun geiser-con--make-request (con str cont &optional sender-buffer) (list :geiser-connection-request - (cons :id (random)) + (cons :id (geiser-con--connection-inc-count con)) (cons :string str) (cons :continuation cont) - (cons :buffer (or sender-buffer (current-buffer))))) + (cons :buffer (or sender-buffer (current-buffer))) + (cons :connection con))) (defsubst geiser-con--request-p (req) (and (listp req) (eq (car req) :geiser-connection-request))) @@ -57,6 +58,9 @@ (defsubst geiser-con--request-buffer (req) (cdr (assoc :buffer req))) +(defsubst geiser-con--request-connection (req) + (cdr (assoc :connection req))) + (defsubst geiser-con--request-deactivate (req) (setcdr (assoc :continuation req) nil)) @@ -70,9 +74,16 @@ (list :geiser-connection (cons :requests (list)) (cons :current nil) + (cons :count 0) (cons :completed (make-hash-table :weakness 'value)) (cons :buffer buffer) - (cons :timer nil))) + (cons :timer nil) + (cons :reply (geiser-con--make-reply-buffer (buffer-name buffer))))) + +(defun geiser-con--make-reply-buffer (n) + (let ((rb (generate-new-buffer (concat " geiser-con-reply: " n)))) + (buffer-disable-undo rb) + rb)) (defsubst geiser-con--connection-p (c) (and (listp c) (eq (car c) :geiser-connection))) @@ -89,6 +100,9 @@ (defsubst geiser-con--connection-current-request (c) (cdr (assoc :current c))) +(defsubst geiser-con--connection-reply-buffer (c) + (cdr (assoc :reply c))) + (defun geiser-con--connection-clean-current-request (c) (let* ((cell (assoc :current c)) (req (cdr cell))) @@ -112,14 +126,11 @@ (geiser-con--connection-pop-request c) (cdr current)))) -(defun geiser-con--connection-start-timer (c) - (let ((cell (assoc :timer c))) - (when (cdr cell) (cancel-timer (cdr cell))) - (setcdr cell (run-at-time t 0.5 'geiser-con--process-next c)))) - -(defun geiser-con--connection-cancel-timer (c) - (let ((cell (assoc :timer c))) - (when (cdr cell) (cancel-timer (cdr cell))))) +(defun geiser-con--connection-inc-count (c) + (let* ((cnt (assoc :count c)) + (new (1+ (cdr cnt)))) + (setcdr cnt new) + new)) ;;; Connection setup: @@ -142,50 +153,45 @@ (overlay-end comint-last-prompt-overlay))))) -(defsubst geiser-con--has-entered-debugger () - (and geiser-con--debugging-prompt-regexp - (re-search-backward geiser-con--debugging-prompt-regexp nil t) - (or (null geiser-con--debugging-preamble-regexp) - (save-excursion - (re-search-backward geiser-con--debugging-preamble-regexp nil t))))) +(defsubst geiser-con--has-entered-debugger (con) + (with-current-buffer (geiser-con--connection-buffer con) + (and geiser-con--debugging-prompt-regexp + (re-search-backward geiser-con--debugging-prompt-regexp nil t) + (or (null geiser-con--debugging-preamble-regexp) + (save-excursion + (re-search-backward geiser-con--debugging-preamble-regexp + nil t)))))) -(defun geiser-con--cleanup-connection (c) - (geiser-con--connection-cancel-timer c)) +(defun geiser-con--connection-teardown () + (when geiser-con--connection + (kill-buffer + (geiser-con--connection-reply-buffer geiser-con--connection)))) (defun geiser-con--setup-connection (buffer prompt-regexp &optional debug-prompt-regexp debug-preamble-regexp) (with-current-buffer buffer - (when geiser-con--connection - (geiser-con--cleanup-connection geiser-con--connection)) + (geiser-con--connection-teardown) (setq geiser-con--debugging-prompt-regexp debug-prompt-regexp) (setq geiser-con--debugging-preamble-regexp debug-preamble-regexp) (setq geiser-con--connection (geiser-con--make-connection buffer)) - (geiser-con--setup-comint prompt-regexp debug-prompt-regexp) - (geiser-con--connection-start-timer geiser-con--connection) - (message "Geiser REPL up and running!"))) - -(defun geiser-con--setup-comint (prompt-regexp debug-prompt-regexp) - (set (make-local-variable 'comint-redirect-insert-matching-regexp) - (not (null debug-prompt-regexp))) - (set (make-local-variable 'comint-redirect-finished-regexp) - (if debug-prompt-regexp - (format "\\(%s\\)\\|\\(%s\\)" prompt-regexp debug-prompt-regexp) - prompt-regexp)) - (setq comint-prompt-regexp comint-redirect-finished-regexp) - (add-hook 'comint-redirect-hook 'geiser-con--comint-redirect-hook nil t)) + (set (make-local-variable 'comint-redirect-insert-matching-regexp) + (not (null debug-prompt-regexp))) + (set (make-local-variable 'comint-redirect-finished-regexp) + (if debug-prompt-regexp + (format "\\(%s\\)\\|\\(%s\\)" prompt-regexp debug-prompt-regexp) + prompt-regexp)) + (setq comint-prompt-regexp comint-redirect-finished-regexp) + (add-hook 'comint-redirect-hook 'geiser-con--comint-redirect-hook nil t))) ;;; Requests handling: -(defsubst geiser-con--comint-buffer () - (get-buffer-create " *geiser connection retort*")) - -(defun geiser-con--comint-buffer-form () - (with-current-buffer (geiser-con--comint-buffer) +(defun geiser-con--comint-buffer-form (con) + (with-current-buffer (geiser-con--connection-reply-buffer con) (goto-char (point-max)) - (if (geiser-con--has-entered-debugger) + (if (geiser-con--has-entered-debugger con) `((error (key . geiser-debugger)) (output . ,(buffer-substring (point-min) (point)))) (condition-case nil @@ -207,32 +213,28 @@ geiser-con--debugging-preamble-regexp)) (req (geiser-con--connection-pop-request con)) (str (and req (geiser-con--request-string req))) - (cbuf (geiser-con--comint-buffer))) - (if (not (buffer-live-p buffer)) - (geiser-con--connection-cancel-timer con) - (when (and buffer req str) - (with-current-buffer cbuf - (setq comint-redirect-echo-input nil) - (setq geiser-con--debugging-prompt-regexp debug-prompt) - (setq geiser-con--debugging-preamble-regexp debug-preamble) - (delete-region (point-min) (point-max))) - (set-buffer buffer) - (if (geiser-con--is-debugging) - (geiser-con--request-deactivate req) - (geiser-log--info "<%s>: %s" (geiser-con--request-id req) str) - (comint-redirect-send-command (format "%s" str) cbuf nil t))))))) + (rbuffer (geiser-con--connection-reply-buffer con))) + (when (and buffer (buffer-live-p buffer) req str) + (with-current-buffer rbuffer + (delete-region (point-min) (point-max))) + (set-buffer buffer) + (if (geiser-con--is-debugging) + (geiser-con--request-deactivate req) + (geiser-log--info "<%s>: %s" (geiser-con--request-id req) str) + (comint-redirect-send-command (format "%s" str) rbuffer nil t)))))) (defun geiser-con--process-completed-request (req) (let ((cont (geiser-con--request-continuation req)) (id (geiser-con--request-id req)) (rstr (geiser-con--request-string req)) - (buffer (geiser-con--request-buffer req))) + (buffer (geiser-con--request-buffer req)) + (con (geiser-con--request-connection req))) (if (not cont) (geiser-log--warn "<%s> Droping result for request %S (%s)" id rstr req) (condition-case cerr (with-current-buffer (or buffer (current-buffer)) - (funcall cont (geiser-con--comint-buffer-form)) + (funcall cont (geiser-con--comint-buffer-form con)) (geiser-log--info "<%s>: processed" id)) (error (geiser-log--error "<%s>: continuation failed %S \n\t%s" id rstr cerr)))))) @@ -263,7 +265,7 @@ (save-current-buffer (let ((con (geiser-con--get-connection buffer/proc))) (unless con (error geiser-con--error-message)) - (let ((req (geiser-con--make-request str cont sender-buffer))) + (let ((req (geiser-con--make-request con str cont sender-buffer))) (geiser-con--connection-add-request con req) (geiser-con--process-next con) req)))) diff --git a/elisp/geiser-racket.el b/elisp/geiser-racket.el index cd4cc8a..34dd497 100644 --- a/elisp/geiser-racket.el +++ b/elisp/geiser-racket.el @@ -98,12 +98,12 @@ This function uses `geiser-racket-init-file' if it exists." (defun geiser-racket--geiser-procedure (proc &rest args) (case proc ((eval compile) - (format ",geiser-eval %s %s %s\n" + (format ",geiser-eval %s %s %s" (or (car args) "#f") (geiser-racket--language) (mapconcat 'identity (cdr args) " "))) ((load-file compile-file) - (format ",geiser-eval geiser/main racket (geiser:%s %s)\n" + (format ",geiser-eval geiser/main racket (geiser:%s %s)" proc (car args))) ((no-values) ",geiser-no-values") (t (format ",apply geiser:%s (%s)" proc (mapconcat 'identity args " "))))) diff --git a/elisp/geiser-repl.el b/elisp/geiser-repl.el index 13b655e..f6fc12b 100644 --- a/elisp/geiser-repl.el +++ b/elisp/geiser-repl.el @@ -247,7 +247,8 @@ module command as a string") deb-preamble-rx) (add-to-list 'geiser-repl--repls (current-buffer)) (geiser-repl--set-this-buffer-repl (current-buffer)) - (geiser-repl--startup impl))) + (geiser-repl--startup impl) + (message "Geiser REPL up and running!"))) (defun geiser-repl--process () (let ((buffer (geiser-repl--set-up-repl geiser-impl--implementation))) -- cgit v1.2.3 From 6a197dae0735eb92f66ee98a8ca4137eac7649ee Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Mon, 8 Nov 2010 03:39:36 +0100 Subject: Racket: use EOT token for internal communications --- elisp/geiser-racket.el | 1 + scheme/racket/geiser/eval.rkt | 16 ++++++---------- scheme/racket/geiser/modules.rkt | 4 ++++ scheme/racket/geiser/user.rkt | 32 ++++++++++++++++++++------------ 4 files changed, 31 insertions(+), 22 deletions(-) (limited to 'elisp/geiser-racket.el') diff --git a/elisp/geiser-racket.el b/elisp/geiser-racket.el index 34dd497..18ed2eb 100644 --- a/elisp/geiser-racket.el +++ b/elisp/geiser-racket.el @@ -230,6 +230,7 @@ This function uses `geiser-racket-init-file' if it exists." (binary geiser-racket--binary) (arglist geiser-racket--parameters) (startup) + (eot-regexp "\0") (prompt-regexp geiser-racket--prompt-regexp) (marshall-procedure geiser-racket--geiser-procedure) (find-module geiser-racket--get-module) diff --git a/scheme/racket/geiser/eval.rkt b/scheme/racket/geiser/eval.rkt index f66f149..78db857 100644 --- a/scheme/racket/geiser/eval.rkt +++ b/scheme/racket/geiser/eval.rkt @@ -17,15 +17,13 @@ compile-file macroexpand make-repl-reader) + (require geiser/enter geiser/modules geiser/autodoc) (require errortrace/errortrace-lib) (define last-result (void)) -(define namespace->module-name - (compose module-path-name->name namespace->module-path-name)) - (define last-namespace (make-parameter (current-namespace))) (define (exn-key e) @@ -59,8 +57,7 @@ (lambda () (update-signature-cache spec form) (eval form (module-spec->namespace spec lang))))) - (newline) - (flush-output)) + (newline)) (define compile-in eval-in) @@ -76,10 +73,9 @@ (lambda () (pretty-print (syntax->datum ((if all expand expand-once) form))))))) -(define (make-repl-reader builtin-reader) - (lambda (ns) - (last-namespace ns) - (printf "racket@~a" (namespace->module-name ns)) - (builtin-reader))) +(define (make-repl-reader reader) + (lambda () + (last-namespace (current-namespace)) + (reader))) ;;; eval.rkt ends here diff --git a/scheme/racket/geiser/modules.rkt b/scheme/racket/geiser/modules.rkt index 5c6ba1f..0591a92 100644 --- a/scheme/racket/geiser/modules.rkt +++ b/scheme/racket/geiser/modules.rkt @@ -14,6 +14,7 @@ (provide load-module ensure-module-spec module-spec->namespace + namespace->module-name namespace->module-path-name module-path-name->name module-spec->path-name @@ -79,6 +80,9 @@ [(symbol? path) (symbol->string path)] [else ""])) +(define namespace->module-name + (compose module-path-name->name namespace->module-path-name)) + (define (skippable-dir? path) (call-with-values (lambda () (split-path path)) (lambda (_ basename __) diff --git a/scheme/racket/geiser/user.rkt b/scheme/racket/geiser/user.rkt index e00e306..e615400 100644 --- a/scheme/racket/geiser/user.rkt +++ b/scheme/racket/geiser/user.rkt @@ -13,7 +13,8 @@ (provide init-geiser-repl run-geiser-repl enter!) -(require geiser/main geiser/enter geiser/eval (for-syntax racket/base)) +(require (for-syntax racket/base) + geiser/main geiser/enter geiser/eval geiser/modules) (define top-namespace (current-namespace)) @@ -31,7 +32,7 @@ (define orig-loader (current-load/use-compiled)) (define geiser-loader (module-loader orig-loader)) -(define orig-reader (current-prompt-read)) +(define geiser-send-null (make-parameter #f)) (define (geiser-eval) (define geiser-main (module->namespace 'geiser/main)) @@ -47,18 +48,25 @@ (else ((geiser:eval lang) form mod))))))) (define (geiser-read) - (let ((form (orig-reader))) + (if (geiser-send-null) + (begin (geiser-send-null #f) + (write-char #\nul)) + (printf "racket@~a> " (namespace->module-name (current-namespace)))) + (flush-output) + (let* ([in (current-input-port)] + [form ((current-read-interaction) (object-name in) in)]) (syntax-case form () - ((uq cmd) (eq? 'unquote (syntax-e #'uq)) - (case (syntax-e #'cmd) - ((enter) (enter! (read) #'cmd)) - ((geiser-eval) (geiser-eval)) - ((geiser-no-values) (datum->syntax #f (void))) - (else form))) - (_ form)))) + [(uq cmd) (eq? 'unquote (syntax-e #'uq)) + (begin + (geiser-send-null #t) + (case (syntax-e #'cmd) + ((enter) (enter! (read) #'cmd)) + ((geiser-eval) (geiser-eval)) + ((geiser-no-values) (datum->syntax #f (void))) + (else form)))] + [_ form]))) -(define geiser-prompt-read - (compose (make-repl-reader geiser-read) current-namespace)) +(define geiser-prompt-read (make-repl-reader geiser-read)) (define (init-geiser-repl) (compile-enforce-module-constants #f) -- cgit v1.2.3 From f2bf4b2cda05fe8c32ee74ce3b5cce743d81de61 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Tue, 9 Nov 2010 21:35:50 +0100 Subject: Racket: remote REPLs --- .gitignore | 1 + Makefile.am | 2 +- bin/Makefile.am | 15 +++++++++++ bin/geiser-racket.sh | 19 +++++++++++++ configure.ac | 1 + doc/repl.texi | 60 ++++++++++++++++++++++++++++------------- elisp/geiser-connection.el | 57 +++++++++++++++++---------------------- elisp/geiser-racket.el | 12 +++++++++ scheme/racket/geiser/server.rkt | 24 +++++++++++++++++ 9 files changed, 138 insertions(+), 53 deletions(-) create mode 100644 bin/Makefile.am create mode 100755 bin/geiser-racket.sh create mode 100644 scheme/racket/geiser/server.rkt (limited to 'elisp/geiser-racket.el') diff --git a/.gitignore b/.gitignore index 15ac980..444b523 100644 --- a/.gitignore +++ b/.gitignore @@ -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{/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) diff --git a/elisp/geiser-racket.el b/elisp/geiser-racket.el index 18ed2eb..8c66e67 100644 --- a/elisp/geiser-racket.el +++ b/elisp/geiser-racket.el @@ -222,6 +222,18 @@ This function uses `geiser-racket-init-file' if it exists." (re-search-forward "#lang " nil t)) (geiser-racket--explicit-module))) + +;;; Remote REPLs + +(defun connect-to-racket () + "Start a Racket REPL connected to a remote process. + +The remote process needs to be running a REPL server started +using start-geiser, a procedure in the geiser/server module." + (interactive) + (geiser-connect 'racket)) + + ;;; Implementation definition: diff --git a/scheme/racket/geiser/server.rkt b/scheme/racket/geiser/server.rkt new file mode 100644 index 0000000..cf86b2c --- /dev/null +++ b/scheme/racket/geiser/server.rkt @@ -0,0 +1,24 @@ +;;; server.rkt -- REPL server + +;; Copyright (c) 2010 Jose Antonio Ortega Ruiz + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the Modified BSD License. You should +;; have received a copy of the license along with this program. If +;; not, see . + +;; Start date: Sat Nov 06, 2010 15:15 + +#lang racket/base + +(require geiser/user mzlib/thread) +(provide run-geiser-server start-geiser) + +(define (run-geiser-server port enforce-module-constants) + (run-server port + (lambda (in out) + (run-geiser-repl in out enforce-module-constants)) + #f)) + +(define (start-geiser (port 1969) (enforce-module-constants #f)) + (thread (lambda () (run-geiser-server port enforce-module-constants)))) -- cgit v1.2.3