,cd for Racket REPL
[geiser.git] / scheme / racket / geiser / user.rkt
blobc8cca24e0978a11f100edca30c9421843bfad4be
1 ;;; user.rkt -- global bindings visible to geiser users
3 ;; Copyright (C) 2010, 2011, 2012 Jose Antonio Ortega Ruiz
5 ;; This program is free software; you can redistribute it and/or
6 ;; modify it under the terms of the Modified BSD License. You should
7 ;; have received a copy of the license along with this program. If
8 ;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>.
10 ;; Start date: Wed Mar 31, 2010 22:24
12 #lang racket/base
14 (provide init-geiser-repl run-geiser-server start-geiser)
16 (require (for-syntax racket/base)
17          mzlib/thread
18          racket/tcp
19          geiser
20          geiser/enter
21          geiser/eval
22          geiser/modules)
24 (define top-namespace (current-namespace))
25 (define last-entered (make-parameter ""))
27 (define (do-enter mod name)
28   (enter-module mod)
29   (current-namespace (module->namespace mod))
30   (last-entered name))
32 (define (enter! mod stx)
33   (cond [(not mod)
34          (current-namespace top-namespace)
35          (last-entered "")]
36         [(symbol? mod) (do-enter mod (symbol->string mod))]
37         [(and (list? mod)
38               (= 2 (length mod))
39               (eq? 'file (car mod))
40               (path-string? (cadr mod))) (do-enter mod (cadr mod))]
41         [(path-string? mod) (do-enter `(file ,mod) mod)]
42         [else (raise-syntax-error
43                #f
44                "not a valid module path, and not #f"
45                stx
46                mod)]))
48 (define orig-loader (current-load/use-compiled))
49 (define geiser-loader (module-loader orig-loader))
51 (define (geiser-eval)
52   (define geiser-main (module->namespace 'geiser))
53   (define (eval-here form) (eval form geiser-main))
54   (let* ([mod (read)]
55          [lang (read)]
56          [form (read)])
57     (datum->syntax #f
58                    (list 'quote
59                          (cond [(equal? form '(unquote apply))
60                                 (let* ([proc (eval-here (read))]
61                                        [args (map eval-here (read))]
62                                        [ev (lambda () (apply proc args))])
63                                   (eval-in `(,ev) mod lang))]
64                                [else ((geiser:eval lang) form mod)])))))
66 (define ((geiser-read prompt))
67   (prompt)
68   (flush-output)
69   (let* ([in ((current-get-interaction-input-port))]
70          [form ((current-read-interaction) (object-name in) in)])
71     (syntax-case form ()
72       [(uq cmd) (eq? 'unquote (syntax-e #'uq))
73        (case (syntax-e #'cmd)
74          [(start-geiser) (datum->syntax #f `(list 'port ,(start-geiser)))]
75          [(enter) (enter! (read) #'cmd)]
76          [(geiser-eval) (geiser-eval)]
77          [(geiser-no-values) (datum->syntax #f (void))]
78          [(add-to-load-path) (add-to-load-path (read))]
79          [(cd) (current-directory (read))]
80          [else form])]
81       [_ form])))
83 (define geiser-prompt
84   (lambda ()
85     (printf "racket@~a> "
86             (namespace->module-name (current-namespace) (last-entered)))))
88 (define (geiser-prompt-read prompt)
89   (make-repl-reader (geiser-read prompt)))
91 (define (init-geiser-repl)
92   (compile-enforce-module-constants #f)
93   (current-load/use-compiled geiser-loader)
94   (current-prompt-read (geiser-prompt-read geiser-prompt)))
96 (define (run-geiser-repl in out enforce-module-constants)
97   (parameterize [(compile-enforce-module-constants enforce-module-constants)
98                  (current-input-port in)
99                  (current-output-port out)
100                  (current-error-port out)
101                  (current-load/use-compiled geiser-loader)
102                  (current-prompt-read (geiser-prompt-read geiser-prompt))]
103     (read-eval-print-loop)))
105 (define server-channel (make-channel))
107 (define (run-geiser-server port enforce-module-constants)
108   (run-server port
109               (lambda (in out)
110                 (run-geiser-repl in out enforce-module-constants))
111               #f
112               void
113               (lambda (p _ __)
114                 (let ([lsner (tcp-listen p)])
115                   (let-values ([(_ p __ ___) (tcp-addresses lsner #t)])
116                     (channel-put server-channel p)
117                     lsner)))))
119 (define (start-geiser (port 0) (enforce-module-constants #f))
120   (thread (lambda () (run-geiser-server port enforce-module-constants)))
121   (channel-get server-channel))